Generic Device handler for 2-Gang Zigbee dimmer?

I am completely new to ST, but I have still in a few days solved most of my issues, but I can’t find a working Device Handler for a dimmer puck (2 gang dimmer) with manufacturer ID _TYZB01_v8gtiaed model TS110F

One channel is working with the dimmer device handler and I manage to get on/off working with the “integrated ZigBee Switch” device handler:

I can’t find any device handler for 2-gang dimmers at all, are there any?

The raw description of the dimmer puck is:
01 0104 0101 01 05 0000 0004 0005 0006 0008 02 0019 000A

Does anyone know how I solve this?

1 Like

I think I have figured out a few things, the problem seems to be that there are no device handlers for dimmer child-devices in the standard device handlers. So I must create a child device for dimmers (which should be quite easy based on the code I have parsed), but then I also must take a copy of “zigbee-multi-switch” & “zigbee-dimmer” and merge these figuring out the zigbee clusters that I need to write to to set the dimmer level. That is not as easy for a newbie.

Is there a good template that I can use for child-devices in dimmers? I have found a few devices that may be possible to use, but I have no clue which one to use as a template for this. None of them has worked when I have tried them “out of the box”.

I guess I just have to print out the code for several of them (as well as the device handlers above), compare and use a highlight pen as I used to do back in the days when I was actively coding…

Any help in the right direction would be very helpful. Any help in acknowledging that I am on the right track would also be appreciated.

That dimmer is made by Tuya and sold under many different brand names, including Losonho, yagusmart, and Zemismart. (Zemismart also offers a Z wave version, so make sure the DTH you find is for Zigbee.)

Smartthings has never been very good at multi endpoint devices, and the child device construct was a way around that. However, the way that multi button devices, which is what a two gang looks like in many DTHs, are handled changed significantly a few months ago, so many DTHs older than October 2020 won’t work correctly with the new V3 app. Even if they worked just fine with the classic app.

The Number of Buttons Value

In particular, the old generation used “number of buttons” for multi button devices, and this was also commonly used for a device that had one button with multiple tap patterns like double tap, triple tap, etc. where the DTH would spoof individual buttons for the different tap patterns.

The newest architecture went too far the other way and now you’ll see DTHs for a triple gang switch with a DTH that says there is only one button, but is using 5 tap for the third gang, etc.

It’s all very confusing. so if you are going to use code from a different device, you might want to look up a picture of the device before you start so you understand what the code author was trying to work with.

Anyway… The new platform doesn’t use the “number of buttons“ value, but the official SmartLighting feature and Webcore still do, so you even see some brand new custom DTHs now which are using “number of buttons“ but then only work with smartlighting and Webcore, they don’t work with other automations. :scream:

The most common symptom is the only one button works and the others are ignored. But there could be other symptoms as well

So that’s the first thing to be aware of before you start researching, or you might be bringing in bits of code that no longer work. :disappointed_relieved:

None of this is clearly documented in any of the official documentation yet, at least not that I’ve seen. Individual community members have worked it out over time, so quite a few DTHs have been updated. But not all, and not even all of the official versions.

Doing research

And if it all sounds very confusing, it is. So I just wanted to make sure you knew a bit of the history before you get out that yellow highlighter.

I suggest you check the forum for threads on the Tuya or Zemismart Multi gang Zigbee devices and look for posts since October 2020. You should find something useful there. Just be sure to read carefully to determine if the code you were going to look at only works with smartlighting/Webcore or if it has been fully updated for the new automations. :sunglasses:

Tagging @johnconstantelo just because he uses a lot of zigbee devices and might have something to add.

2 Likes

And here’s one for a multi gang switch (not dimmer) from this line that just went up today. However, it looks like it’s using number of buttons, so I would expect it to work with Webcore but not with automations using the new rules API. But I might be wrong on that, I’ve asked the author to clarify.

1 Like

Actually you nailed it. It’s doable, but since there’s no child device for a dimmer, you’ll have to develop that one. I used “zigbee-multi-switch” when developing the DTH for Aqara’s double rocker to include power reporting.

EDIT:

Look at this example for a child dimmer:

1 Like

Also, you probably already know this, but just for clarity, smartthings adopted some of the Zigbee terminology and applied it for Z wave devices and some of the Z wave terminology and applied it for Zigbee devices, which can add more confusion. :thinking:

Anyway, in smartthings a “multilevel switch“ is a dimmer. The levels are the dim percentages like 10%, 50%, 75%, etc. up to 100%. But for many devices are expressed as 0 to 256 to allow for conversion to hex.

I went through the code of the standard zigbee-dimmers, switch child-devices and multi-switch devices yesterday and I think that the codes for these should be possible to merge. It will take me a day or two, but the dimmer child-device is actually already done, that part was simple.

The main thing that worries me is if the child-device commands are going to work as they are supposed to, but I will tell you after the weekend.

2 Likes

It is so difficult to code in a run-time typed programming language.

New errors popping up here and there.

It is not simpler when many of the examples are not working.

Documentation is not helping much either. I am currently stuck at sending a command or writeattribute to the secondary channel for setting the level, I can’t get that working. If it is not complaints about null pointers, it is complaining about the wrong datatype.

Is it possible to get a reference to something similar? I have looked around but I haven’t found any working code doing exactly that. Any pointers? Anyone?

Any good news ? Did you successfully activated the two channels dimmer module ?
Did you mange to finalize the device handler ?

I still have issues. It is now working as a dimmer on both channels, but I lost the possibility to turn it on and off without dimming to 0%. I will continue working on it…

Give me a few more days…

1 Like

I am now very close to have a working solution. It seems to work, I just need to test it a bit more.

Once I figured out what was wrong, it was so much easier… :wink:

1 Like

OK, so here is the code that seems to be working. I have some issues with Automations that can’t find the child device. I have no clue why, but I think it is a bug in the SmaretThings app rather than in my DH (as Automations shows a previous version of the child device than the one that is installed).

Note that there are two sets of code below, the “Zigbee Multi Dimmer” (the parent) and the “Child Switch Dimmer” (the child device). Both of them needs to be created.

I have based these on multiple other DH, but I guess most of it comes from the original Multi Switch, Dimmer, and Child Switch devices on the SmartThings GitHub.

So if anyone is interesting to try these, to find issues, and perhaps even solve issues, please do. Anyway, these DH are for the Lonsonho 2-Gang Tuya Dimmers (QS-Zigbee-D02-TRIAC-2C-LN) that looks like this:

/////////////////////////
// Zigbee Multi Dimmer
/////////////////////////
    
import physicalgraph.zigbee.zcl.DataType

metadata {
	definition (name: "ZigBee Multi Dimmer", namespace: "jhb", author: "jhb", ocfDeviceType: "oic.d.light", runLocally: false, minHubCoreVersion: '000.019.00012', executeCommandsLocally: true, genericHandler: "Zigbee") {
		capability "Actuator"
		capability "Configuration"
		capability "Refresh"
		capability "Switch"
		capability "Switch Level"
		capability "Health Check"
		capability "Light"
        
		command "childOn", ["string"]
		command "childOff", ["string"]
		command "childSetLevel", ["string", "string"]

		// Generic
		fingerprint profileId: "0104", deviceId: "0101", inClusters: "0006, 0008", deviceJoinName: "Light" //Generic Dimmable Light
	}

	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.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}
		standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
		}
		main "switch"
		details(["switch", "refresh"])
	}
}

def installed() {
	createChildDevices()
	updateDataValue("onOff", "catchall")
	refresh()
}

// Parse incoming device messages to generate events
def parse(String description) {

	Map eventMap = zigbee.getEvent(description)
	Map eventDescMap = zigbee.parseDescriptionAsMap(description)

	log.debug "description is $description"

	if (eventMap) {
		if (eventDescMap && eventDescMap?.attrId == "0000") {//0x0000 : OnOff attributeId
			if (eventDescMap?.sourceEndpoint == "01" || eventDescMap?.endpoint == "01") {
				sendEvent(eventMap)
			} else {
				def childDevice = childDevices.find {
					it.deviceNetworkId == "$device.deviceNetworkId:${eventDescMap.sourceEndpoint}" || it.deviceNetworkId == "$device.deviceNetworkId:${eventDescMap.endpoint}"
				}
				if (childDevice) {
					childDevice.sendEvent(eventMap)
				} else {
					log.debug "Child device: $device.deviceNetworkId:${eventDescMap.sourceEndpoint} was not found"
				}
			}
		}
	} else {
		def descMap = zigbee.parseDescriptionAsMap(description)
		if (descMap && descMap.clusterInt == 0x0006 && descMap.commandInt == 0x07) {
			if (descMap.data[0] == "00") {
				log.debug "ON/OFF REPORTING CONFIG RESPONSE: " + cluster
				sendEvent(name: "checkInterval", value: 60 * 12, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID])
			} else {
				log.warn "ON/OFF REPORTING CONFIG FAILED- error code:${cluster.data[0]}"
			}
		} else {
			log.warn "DID NOT PARSE MESSAGE for description : $description"
			log.debug "${descMap}"
		}
	}
}

private getChildEndpoint(String dni) {
	dni.split(":")[-1] as Integer
}

def off() {
	log.debug("off")
    zigbee.off()
}

def on() {
	log.debug("on")
    zigbee.on()
}

def childOn(String dni) {
	def childEndpoint = getChildEndpoint(dni)
    log.debug(" child on ${dni} ${childEndpoint} ")
	zigbee.command(zigbee.ONOFF_CLUSTER, 0x01, "", [destEndpoint: childEndpoint])
}

def childOff(String dni) {
	def childEndpoint = getChildEndpoint(dni)
    log.debug(" child off ${dni} ${ childEndpoint} ")
	zigbee.command(zigbee.ONOFF_CLUSTER, 0x00, "", [destEndpoint: childEndpoint])
}

def setOnLevel (endpoint, level) {
	log.debug "setOnLevel($endpoint, $level)"
	zigbee.writeAttribute(zigbee.LEVEL_CONTROL_CLUSTER, 0x0011, DataType.UINT8, level, [destEndpoint: endpoint])
}

def moveToLevel (endpoint, level, transitionTime) {
	log.debug "moveToLevel($endpoint, $level, $transitionTime)"
    def p1 = DataType.pack(level, DataType.UINT8, false)
    def p2 = DataType.pack(transitionTime, DataType.UINT16, false)
    def dataString = [p1, p2].join(" ")
    //"st cmd 0x${device.deviceNetworkId} ${endpointId} 8 4 {${scaledLevel} ${transitionTime}}"
    zigbee.command(zigbee.LEVEL_CONTROL_CLUSTER, 0x0000, dataString, [destEndpoint: endpoint]) +
    zigbee.command(zigbee.LEVEL_CONTROL_CLUSTER, 0x0004, dataString, [destEndpoint: endpoint])
}

def childSetLevel (String dni, Integer value) {
	def endpoint = getChildEndpoint(dni)
    def rate = 5;
	log.debug "setLevel($endpoint, $value, $rate)"
    def level = Math.round(Math.floor(value * 2.54))
    setOnLevel(endpoint, level) + moveToLevel(endpoint, level, rate)
}

def setLevel(value, rate = null) {
	def additionalCmds = []
	zigbee.setLevel(value) + additionalCmds
}
/**
 * PING is used by Device-Watch in attempt to reach the Device
 * */
def ping() {
	return zigbee.onOffRefresh()
}

def refresh() {
	zigbee.onOffRefresh() + zigbee.levelRefresh()
}

private void createChildDevices() {
	if (!childDevices) {
		def x = getChildCount()
       	log.debug(" childCount ${x}")

		for (i in 2..x) {
			addChildDevice("Child Switch Dimmer", "${device.deviceNetworkId}:0${i}", device.hubId,
				[completedSetup: true, label: "${device.displayName[0..-2]}${i}", isComponent: false])
           	log.debug(" Device ${i} created")

		}
	}
}

def updated() {
	log.debug "updated()"
	updateDataValue("onOff", "catchall")
	for (child in childDevices) {
		if (!child.deviceNetworkId.startsWith(device.deviceNetworkId) || //parent DNI has changed after rejoin
				!child.deviceNetworkId.split(':')[-1].startsWith('0')) {
			child.setDeviceNetworkId("${device.deviceNetworkId}:0${getChildEndpoint(child.deviceNetworkId)}")
		}
	}
	refresh()
}

def configureHealthCheck() {
	Integer hcIntervalMinutes = 12
	if (!state.hasConfiguredHealthCheck) {
		log.debug "Configuring Health Check, Reporting"
		unschedule("healthPoll")
		runEvery5Minutes("healthPoll")
		def healthEvent = [name: "checkInterval", value: hcIntervalMinutes * 60, displayed: false, data: [protocol: "zigbee", hubHardwareId: device.hub.hardwareID]]
		// Device-Watch allows 2 check-in misses from device
		sendEvent(healthEvent)
		childDevices.each {
			it.sendEvent(healthEvent)
		}
		state.hasConfiguredHealthCheck = true
	}
}

def configure() {
	log.debug "configure()"
	configureHealthCheck()
	   
    def cmds = zigbee.onOffConfig(0, 300) + zigbee.levelConfig()
	def x = getChildCount()
	for (i in 2..x) {
		cmds += zigbee.configureReporting(zigbee.ONOFF_CLUSTER, 0x0000, 0x10, 0, 120, null, [destEndpoint: i])
	}
	cmds += refresh()
	return cmds
}

private getChildCount() {
	return 2
}

/////////////////////////
// Child Switch Dimmer
/////////////////////////
    
metadata {
	definition(name: "Child Switch Dimmer", namespace: "jhb", author: "jhb", ocfDeviceType: "oic.d.light", runLocally: false, minHubCoreVersion: '000.019.00012', executeCommandsLocally: true, genericHandler: "Zigbee") {
		capability "Actuator"
		capability "Refresh"
		capability "Switch"
		capability "Switch Level"
		capability "Light"
	}

	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.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}
		standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
		}
		main "switch"
		details(["switch", "refresh"])
     
	}
}

def installed() {
    sendEvent(name: "checkInterval", value: 30 * 60, displayed: false, data: [protocol: "zigbee"])
    log.debug("installed")
}

// Parse incoming device messages to generate events
def parse(String description) {
    log.debug("parse")
}

def ping() {
    log.debug("ping")
}

def configure() {
    log.debug("configure")
}

def setLevel(value, rate = null) {
    log.debug("level ${value}  ")
	parent.childSetLevel(device.deviceNetworkId, value)
}


void on() {
    log.debug("Local child on ${device.deviceNetworkId}")
	parent.childOn(device.deviceNetworkId)
}

void off() {
    log.debug("Local child off ${device.deviceNetworkId}")
	parent.childOff(device.deviceNetworkId)
}

void refresh() {
    log.debug("Local child refresh ${device.deviceNetworkId}")
}
3 Likes

It tokk over 12h, but now the child device is correctly displayed also in automations.

2 Likes

Hi Jan, any chance you could share your DTH?

Hey, would you please share your updated codes? Highly appreciated

Finally found someone who has produced a DH for these - thanks, I have a WIFI version of this module that works great but am trying to move over to Zigbee for my controllers so had bought the Zigbee version but was really struggling to get the 2nd gang working - just installed this and looks very promising.

One question, the WIFI version via the Tuya app allows control of the minimum dimmable percentage so that when you are using the manual switch the dimming stops at a sensible level. Did you make an update that allows this param to be set or even know what the parameter is to hard-set on the Zigbee version?

1 Like

Hey,
I don’t want to open a new topic.
I have been trying Jan’s code, but seems not to work for mine device.
its tuya from Moes.

  • zigbeeNodeType: ROUTER
  • application: 44
  • endpointId: 01
  • manufacturer: _TZE200_e3oitdyu
  • model: TS0601
  • onOff: catchall
    Raw Description 01 0104 0051 01 04 0000 0004 0005 EF00 02 0019 000A

I have made a new device handler, its a bit messy but is looking promising. the first gang is working 100%. But the 2e gang does not get feedback to the smarttings app tiles. I use Jan’s child Switch Dimmer.

Can some one help me solve the last part?

https://github.com/Pumba1970/moes-2-gang-dimmer/tree/main

/*
 *  Moes ZigBee Switch
 *  https://gist.github.com/b16b/731e6f8f8154f5afbf9aafe10a7e3f1d/revisions
 *  Copyright 2020 SmartThings
 *
 *  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.
 *
 */
public static String version() { return "v0.0.1.20210727" }


private getMODEL_MAP() { 
    [
        'TS0601' : 3
    ]
}

metadata {
    definition(name: "Moes ZigBee Switch", namespace: "Moes", author: "Kotsos", ocfDeviceType: "oic.d.light", vid: "Light") {
        capability "Actuator"
        capability "Configuration"
        capability "Refresh"
        capability "Health Check"
        capability "Switch"
        capability "Switch Level"

        command "childOn", ["string"]
        command "childOff", ["string"]
		command "childSetLevel", ["string", "string"]

        //Moeshouse Switch
        // 1 gang
		fingerprint profileId: "0104", model: "TS0601", manufacturer: "_TZE200_amp6tsvy", endpointId: "01", inClusters: "0000,0004,0005,EF00", outClusters: "0019,000A", application: "42", deviceJoinName: "Moes Multi Switch 1"
		// 2 gang dimmer
        fingerprint profileId: "0104", model: "TS0601", manufacturer: "_TZE200_e3oitdyu", endpointId: "01", inClusters: "0000,0004,0005,EF00", outClusters: "0019,000A", application: "44", deviceJoinName: "Moes Multi Switch 1"
        // 3 gang
        fingerprint profileId: "0104", model: "TS0601", manufacturer: "_TZE200_tz32mtza", endpointId: "01", inClusters: "0000,0004,0005,EF00", outClusters: "0019,000A", application: "42", deviceJoinName: "Moes Multi Switch 1"
      }
 }
// Tile
    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.level", key: "SLIDER_CONTROL") {
				attributeState "level", action:"switch level.setLevel"
			}
		}
		standardTile("refresh", "device.refresh", inactiveLabel: false, decoration: "flat", width: 2, height: 2) {
			state "default", label:"", action:"refresh.refresh", icon:"st.secondary.refresh"
		}
		main "switch"
//		details(["switch", "refresh"])
        details(["switch", "refresh", "level"])
	}
    
def installed() {
	//createChildDevices()
	updateDataValue("onOff", "catchall")
	refresh()
}

// Parse incoming device messages to generate events
def parse(String description) {
    Map map = [:]
    //def event = zigbee.getEvent(description)

    if (description?.startsWith('catchall:')) {
        log.debug description
        // call parseCatchAllMessage to parse the catchall message received
        map = parseCatchAllMessage(description)
        if (map != [:]) {
            log.debug "ok send event: $map.name $map.value"
            sendEvent(name: map.name, value: map.value)
        }
    }
    else {
        log.warn "DID NOT PARSE MESSAGE for description : $description"
    }
}


private getChildEndpoint(String dni) {
	dni.split(":")[-1] as Integer
    }

def off() {
    log.debug "called off"
    zigbee.command(0xEF00, 0x0, "00010101000100")  //kanaal 1
}

def on() {
    log.debug "called on" 
    zigbee.command(0xEF00, 0x0, "00010101000101")  //kanaal 1
}

def setLevel(value) {
    log.debug "called setLevel with value $value"
    if (value >= 0 && value <= 100) {
        Map commandParams = [:]
        String commandPayload = "0001020200040000" + zigbee.convertToHexString((value * 10) as Integer, 4)  //kanaal 1
        zigbee.command(0xEF00, 0x0, commandPayload)
    }
}

def refresh() {
    log.debug "called refresh"
    zigbee.command(0xEF00, 0x0, "00020100")
    //pauseExecution(1000)
    //zigbee.command(0xEF00, 0x0, "0002020200")
   
}

def childOn(String dni) {
	log.debug(" child on ${dni} ${childEndpoint} ")
	zigbee.command(0xEF00, 0x0, "00000701000101") //kanaal 2
    }

def childOff(String dni) {
	log.debug " child off ${dni} ${childEndpoint} "
	zigbee.command(0xEF00, 0x0, "00000701000100") //kanaal 2
    }
    

def childSetLevel (String dni, Integer value) {
	log.debug "called setLevel with value $value"
    if (value >= 0 && value <= 100) {
        Map commandParams = [:]
        String commandPayload = "0000080200040000" + zigbee.convertToHexString((value * 10) as Integer, 4)  //kanaal 2 ?
        zigbee.command(0xEF00, 0x0, commandPayload)
  }
}

def configure() {
    log.debug "Configuring Reporting and Bindings."
    zigbee.onOffConfig() + zigbee.levelConfig() + zigbee.onOffRefresh() + zigbee.levelRefresh()
}

private Map parseCatchAllMessage(String description) {
    // Create a map from the raw zigbee message to make parsing more intuitive
    def msg = zigbee.parse(description)
    Map result = [:]
    switch(msg.clusterId) {
        case 0xEF00: 
            def attribute = getAttribute(msg.data)
            def value = getAttributeValue(msg.data)
            log.debug "173 Atribute ${attribute} AttributeValue ${value}"
                switch (attribute) {
                case "switch": 
                    switch(value) {
                        case 0:
                            result = [
                                name: 'switch',
                                value: 'off',
                                data: [buttonNumber: 1],
                                descriptionText: "${device.displayName} button was pressed",
                                isStateChange: true
                            ]
                            log.debug "185 ${device.displayName} button was pressed"
                        break;

                        case 1:
                            result = [
                                name: 'switch',
                                value: 'on',
                                data: [buttonNumber: 1],
                                descriptionText: "${device.displayName} button was pressed",
                                isStateChange: true
                            ]
                            log.debug "${device.displayName} button was pressed"
                            log.debug "297 ${result}"
                        break;
                        
                    }
                
                break;
                
                case "switch2": 
                    switch(value) {
                        case 0:
                            result = [
                                name: 'switch2',
                                //name: 'Moes Multi Switch 11'
                                value: 'off',
                                data: [buttonNumber: 1],
                                descriptionText: "${device.displayName+1} button was pressed",
                                isStateChange: true
                            ]
                            log.debug "214 ${device.displayName} button was pressed"
                            
                        break;

                        case 1:
                            result = [
                                //name:'Moes Multi Switch 11'
                                name: 'switch2',
                                value: 'on',
                                data: [buttonNumber: 1],
                                descriptionText: "${device.displayName+1} button was pressed",
                                isStateChange: true
                            ]
                            log.debug "${device.displayName} button was pressed"
                            log.debug "227 ${result}"
                        break;
                        
                    }
                break;
                
                case "level": 
                    int levelValue = value / 10
                    result = [
                        name: 'level',
                        value: levelValue,
                        data: [buttonNumber: 1],
                        descriptionText: "${device.displayName} level was modified",
                        isStateChange: true
                    ]
                    log.debug "241 result ${result}"
               
               break;
               
               case "level2": 
                    int levelValue = value / 10
                    result = [
                        name: 'level2',
                        value: levelValue,
                        data: [buttonNumber: 1],
                        descriptionText: "${device.displayName +1} level was modified",
                        isStateChange: true
                    ]
                    log.debug "254 result ${result}"
               
               break;
            }
        
       
    }
        
    return result
}


private String getAttribute(ArrayList _data) {
    log.debug "282 data:${_data}"
    String retValue = ""
      if (_data[1] >0) {  
     	if (_data[2] == 2 && _data[3] == 2 && _data[4] == 0) {
			retValue = "level" 
        }
       
      	if (_data[2] == 1 && _data[3] == 1 && _data[4] == 0) {
            retValue = "switch"
        }
        
   		if (_data[2] == 8 && _data[3] == 2 && _data[4] == 0) {
            retValue = "level2"
        }
        
        if (_data[2] == 7 && _data[3] == 1 && _data[4] == 0) {
            retValue = "switch2"
        }  
    }
    log.debug "276 return ${retValue}"
    
    return retValue
	
}


private int getAttributeValue(ArrayList _data) {
    int retValue = 0
    
    if (_data.size() >= 6) {
        int dataLength = _data[5] as Integer
        int power = 1;
        for (i in dataLength..1) {
            retValue = retValue + power * _data[i+5]
            power = power * 256
        }
    }
    
    return retValue
}


Hello
Anyone using this 2ch dimmer in CCT mode?
Looking at picture fro Aliexpress…