DH for ATSmart Z6 3 Gang Switch

This is 3 gang Zigbee ZHA UK style 86mm x 86mm switch.

With the help from @Sticks18, I managed to put together a working custom DH for this switch.

http://www.atsmart.net/index.php?s=/Home/index/atsmart_switch

Highlights of this switch:

No neutral is required. Only live and switched live.

  • The switch trickles a small current thru switch 1 to keep the Zigbee radio alive. It might make low power LED fixtures blink if its wired to S1. A bypass capacitor is provided to solve this issue.

I wired a fluorescent PLC to the S1 and it works wonderfully.

Switch box is DEEP. You might have trouble fitting it if your box contains lots of wires.

Right now, it seems to be available on china Taobao only.

https://world.taobao.com/item/521229558487.htm?fromSite=main&spm=a312a.7700824.w4004-14123256707.8.MEQotN

Aliexpress/gearbest does not seem to stock this.

2 Likes

Device Handler

/*
 *  Custom Device type for ATSMART Z6 Triple Switch Controller http://www.atsmart.net/index.php?s=/Home/index/atsmart_switch
 *
 *  Copyright 2017 Andy Chan
 *
 *  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.
 *
 */
metadata {
	definition (name: "ATSMART Z6 Triple Switch Controller", namespace: "simic", author: "simics@gmail.com") {
        capability "Refresh"
        capability "Polling"
        capability "Sensor"
        capability "Configuration"
        capability "Switch"
		capability "Actuator"
		
        command "on2"
        command "off2"
        command "on3"
        command "off3"

        attribute "switch2","ENUM", ["on","off"]
        attribute "switch3","ENUM", ["on","off"]
 		attribute "switchstate","ENUM",["on","off"]        
 

    	//fingerprint profileId: "0104", inClusters: "0000", outClusters: "000D,0006"
        //fingerprint inClusters: "0000 0001 0003 0004 0005 0006", endpointId: "01", deviceId: "0100", profileId: "0104"

	}

	// simulator metadata
	simulator {
    }

	// UI tile definitions
	tiles {

		standardTile("switch1", "device.switch", width: 2, height: 2, canChangeIcon: true) {
			state "off", label: '${name}', action: "Switch.on", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
			state "on", label: '${name}', action: "Switch.off", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		}

		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"
		}

               standardTile("switch3", "device.switch3", width: 2, height: 2, canChangeIcon: true) {
			state "off", label: '${name}', action: "on3", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
			state "on", label: '${name}', action: "off3", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		}
        
        standardTile("switchstate", "device.switchstate", width: 2, height: 2, canChangeIcon: true) {
			state "off", label: '${name}' , icon: "st.switches.switch.off", backgroundColor: "#ffffff"
			state "on", label: '${name}', icon: "st.switches.switch.on", backgroundColor: "#79b821"
		}
        
                standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat") {
			state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
		}

		main (["switch1", "switch2", "switch3", "switchstate"])
		details (["switch1", "switch2", "switch3", "switchstate", "refresh"])
	}
}

// Parse incoming device messages to generate events
def parse(String description) {
    log.debug "Parse description $description"
    def name = null
    def value = null
    
    
    
    

    if (description?.startsWith("catchall: 0104 0006 01")) {
        log.debug "On/Off command received from EP 1"
        if (description?.endsWith(" 01 0140 00 6052 00 00 0000 01 01 0000001000")){
        	name = "switch"
            value = "off"}
        else if (description?.endsWith(" 01 0140 00 6052 00 00 0000 01 01 0000001001")){
        	name = "switch"
            value = "on"}                        
    }  
    else if (description?.startsWith("catchall: 0104 0006 02")) {
        log.debug "On/Off command received from EP 2"    
        if (description?.endsWith(" 01 0140 00 6052 00 00 0000 01 01 0000001000")){
        	name = "switch2"
            value = "off"}
        else if (description?.endsWith(" 01 0140 00 6052 00 00 0000 01 01 0000001001")){
        	name = "switch2"
            value = "on"}
    }
    else if (description?.startsWith("catchall: 0104 0006 03")) {
        log.debug "On/Off command received from EP 3"    
        if (description?.endsWith(" 01 0140 00 6052 00 00 0000 01 01 0000001000")){
        	name = "switch3"
            value = "off"}
        else if (description?.endsWith(" 01 0140 00 6052 00 00 0000 01 01 0000001001")){
        	name = "switch3"
            value = "on"}
    }
	else if (description?.startsWith("on/off")) {
    
    log.debug "Prepare to kick refresh thru companion smartapp"
    name = "switchstate"
    value = "off"
    
    
    }
	def result = createEvent(name: name, value: value)
    log.debug "Parse returned ${result?.descriptionText}"
    		
    return result
}

// Commands to device

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

def off() {
	log.debug "Relay 1 off()"
	sendEvent(name: "switch", value: "off")
	"st cmd 0x${device.deviceNetworkId} 0x01 0x0006 0x0 {}"
}

def on2() {
	log.debug "Relay 2 on()"
	sendEvent(name: "switch2", value: "on")
	"st cmd 0x${device.deviceNetworkId} 0x02 0x0006 0x1 {}"
}

def off2() {
	log.debug "Relay 2 off()"
	sendEvent(name: "switch2", value: "off")
	"st cmd 0x${device.deviceNetworkId} 0x02 0x0006 0x0 {}"
}

def on3() {
	log.debug "Relay 3 on()"
	sendEvent(name: "switch3", value: "on")
	"st cmd 0x${device.deviceNetworkId} 0x03 0x0006 0x1 {}"
}

def off3() {
	log.debug "Relay 3 off()"
	sendEvent(name: "switch3", value: "off")
	"st cmd 0x${device.deviceNetworkId} 0x03 0x0006 0x0 {}"
}

def poll(){
	log.debug "Poll is calling refresh"
	refresh()
}

def refresh() {
	log.debug "sending refresh command and reset switchstate"
    sendEvent(name: "switchstate", value: "on")
	
    def cmd = []

    cmd << "st rattr 0x${device.deviceNetworkId} 0x01 0x0006 0x0000"	// Read on / off value at End point 0x01 
    cmd << "delay 150"

    cmd << "st rattr 0x${device.deviceNetworkId} 0x02 0x0006 0x0000"	// Read on / off value at End point 0x02 
	cmd << "delay 250"
	cmd << "st rattr 0x${device.deviceNetworkId} 0x03 0x0006 0x0000"	// Read on / off value at End point 0x03
	cmd << "delay 350"
	
    cmd
}


def configure() { 
    log.debug "Binding SEP 0x01 DEP 0x01 Cluster 0x0006 On/Off cluster to hub"         
        def configCmds = [

        "zdo bind 0x${device.deviceNetworkId} 0x01 0x01 0x0006 {${device.zigbeeId}} {}", "delay 500",
        "zdo bind 0x${device.deviceNetworkId} 0x02 0x01 0x0006 {${device.zigbeeId}} {}", "delay 500",        
        "zdo bind 0x${device.deviceNetworkId} 0x03 0x01 0x0006 {${device.zigbeeId}} {}", "delay 1500",        
        ]
    log.info "Sending ZigBee Bind commands to 3 Button Switch"
    return configCmds
    }

SmartApp

/**
 *  ATSMART Switch Binder
 *  This app allows you to bind 2 Virtual On/Off Tiles to the 2 switchable outlets.
 *  I left out the first switch as it can be called from the actual DH
 *  I will also track the status of switchstate attribute and force a refresh switch state refresh when u physically
 *  press the buttons on the switch
 *  Author: Andy Chan
 *  Date: 22/02/2017
 */
// Automatically generated. Make future change here.
definition(
    name: "ATSMART Switch Binder 1.0",
    namespace: "",
    author: "simics@gmail.com",
    description: "This app allows you to bind 2 Virtual On/Off Tiles to the 2nd and 3rd switchable outlets on ATSMART.",
    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 ATSMART Switch is used?"){
		input "strip", "capability.switch"
        
	}
     section("Select a Virtual Switch to bind to Outlet 2"){
		input "switch2", "capability.Switch"
	}
    section("Select a Virtual Switch to bind to Outlet 3"){
		input "switch3", "capability.Switch"
	}

}
def installed() {
	log.debug "Installed with settings: ${settings}"
	
    // for force refresh of switch state when physical pressed
    subscribe(strip, "switchstate.off", switchRefreshHandler)
    
    //for update virtual switch when real DH endpoint state is changed
    subscribe(strip, "switch2.on", MainSwitchOnTwoHandler)
    subscribe(strip, "switch2.off", MainSwitchOffTwoHandler)
    subscribe(strip, "switch3.on", MainSwitchOnThreeHandler)
    subscribe(strip, "switch3.off", MainSwitchOffThreeHandler)
    
    //for update real DH endpoint when virtual switch is changed
    subscribe(switch2, "switch.on", switchOnTwoHandler)
    subscribe(switch2, "switch.off", switchOffTwoHandler)
    subscribe(switch3, "switch.off", switchOffThreeHandler)
    subscribe(switch3, "switch.on", switchOnThreeHandler)
 
}

def updated(settings) {
	log.debug "Updated with settings: ${settings}"
	unsubscribe()
    
    // for force refresh of switch state when physical pressed
    subscribe(strip, "switchstate.off", switchRefreshHandler)
    
    //for update virtual switch when real DH endpoint state is changed
    subscribe(strip, "switch2.on", MainSwitchOnTwoHandler)
    subscribe(strip, "switch2.off", MainSwitchOffTwoHandler)
    subscribe(strip, "switch3.on", MainSwitchOnThreeHandler)
    subscribe(strip, "switch3.off", MainSwitchOffThreeHandler)
    
    //for update real DH endpoint when virtual switch is changed
    subscribe(switch2, "switch.on", switchOnTwoHandler)
    subscribe(switch2, "switch.off", switchOffTwoHandler)
    subscribe(switch3, "switch.off", switchOffThreeHandler)
    subscribe(switch3, "switch.on", switchOnThreeHandler)
   }




def switchRefreshHandler(evt) {
	log.debug "switch refresh"
	strip.refresh()
}

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 switchOnTwoHandler(evt) {
	log.debug "switch on2"
	strip.on2()
}
def switchOnThreeHandler(evt) {
	log.debug "switch on3"
	strip.on3()
}

def switchOffTwoHandler(evt) {
	log.debug "switch off2"
	strip.off2()
}
def switchOffThreeHandler(evt) {
	log.debug "switch off3"
	strip.off3()
}
1 Like

@simic nice work. Your making a good job of these dh for switched :blush: