MOES Zigbee Dimmer Switch

In case 4-gang switch there you need edit driver. I can help you with this but I need fingerprint of your switch.

Please i want your help to convert this drivers for Smartthings

i have create this thread
"moes 3 gang zigbee wall swithc need a handler that used for cluster ef00"
not aloud to use link search for this title on smartthings comunity i will donate for a solution

Hi @rs125cc,
I do not have a Smartthings device and therefore I cannot help you much.
I can only provide my input about the format of the commands of Tuya devices (which you can find at the first comments of this topic).
Maybe you can use that information at a Smartthings forum to help someone create the driver for you (or you can try doing it yourself if you have some programming knowledge).

Alternatively, you can buy a HE device :wink:

1 Like

thanks for your help... i think you are Greek i am Greek too
the smartthings code is very similar i think is not hard for you to convert it my knoledge is not good so propably i can't i willl try to convert your code as the martinkura code is more complex and i not have luck

is any way to send pm to you in this forum?

Yours code work as it is but not Martin Propably have some changes about childs

:+1:
@martinkura's code is for a multi-button switch, not a dimmer switch

Hi thank you for all the hard work
does it work with 2 gang modules. I got the first one working but no the second lightings
thanks

Hi @ugm2byww,
My code is for a single dimmer switch. If you own a 2-gang dimmer switch then you will need to do some adjustments to it. I think that @martinkura 's code will give you a hint on how to proceed.
Let me know in case you need any help with that

Hi,

I am trying to change the values โ€‹โ€‹to drive a 2gang moes type sonoff mini dimmer. When I configure with your driver, it is possible to handle one of the controls. I have added several commands as indicated above this same thread. Despite this, the second gang does not work even if i modify any value 1 by 2 in the text "00010101000101". I tried all combinations:
00020101000101
00010201000101
00010102000101
00010101000201
The last one too, but i supone it is the state.

I am new to this and I do not see where these values โ€‹โ€‹are taken from, in events I simply see clicks on-off but if I double click and wide it does not put these codes.

I hope you can help me.

see this formula:

0001XX010001YY

XX - gang nr. (01,02,03...)
YY - gang state (00-off, 01-on, 02-toggle)

1 Like

Hello there As I mentioned above I have tried this code 00010201000100 but it does not work for me. It only activates me with the code: 00010101000100 the first Gang. The second Gang is not remotely activated. I also modified the code but did not get a satisfactory result. I'll show you:


metadata {
definition (name: "MOES ZigBee Dimmer V.1.0", namespace: "CPS Smart Home", author: "Christos Psaroudis") {
capability "Actuator"
capability "PushableButton"

    capability "Configuration"
    capability "Refresh"
    capability "Sensor"
    capability "Switch"
    capability "Switch Level"

command "on"
command "off"

command "on1"
command "off1"

command "on2"
command "off2"

    fingerprint profileId: "0104", deviceId: "808F", inClusters: "0000,0004,0005,EF00", outClusters: "0019,000A", manufacturer: "_TZE200_9i9dt8is", model: "TS0601", deviceJoinName: "WorksWith Dimmer"
}

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:"#79b821", 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:"#79b821", 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"])
}

}

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

}

def off() {
log.debug "called off"
zigbee.command(0xEF00, 0x0, "000101010001000201000100") //TODO
}

def off1() {
log.debug "called off1"
zigbee.command(0xEF00, 0x0, "00010101000100")
}

def off2() {
log.debug "called off2"
zigbee.command(0xEF00, 0x0, "00010201000100") //TODO
}

def on() {
log.debug "called on"
zigbee.command(0xEF00, 0x0, "000101010001010201000101") //TODO
}

def on1() {
log.debug "called on1"
zigbee.command(0xEF00, 0x0, "00010101000101")
}

def on2() {
log.debug "called on2"
zigbee.command(0xEF00, 0x0, "00010201000101") //TODO
}

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

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

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)

        switch (attribute) {
            case "switch": 
                switch(value) {
                    case 0:
                        result = [
                            name: 'switch',
                            value: 'off',
                            data: [buttonNumber: 1],
                            descriptionText: "$device.displayName button was pressed",
                            isStateChange: true
                        ]
                    break;

                    case 1:
                        result = [
                            name: 'switch',
                            value: 'on',
                            data: [buttonNumber: 1],
                            descriptionText: "$device.displayName button was pressed",
                            isStateChange: true
                        ]
                    break;
                }
            
            break;
            
            case "level": 
                int levelValue = value / 10
                result = [
                    name: 'level',
                    value: levelValue + "%",
                    data: [buttonNumber: 1],
                    descriptionText: "$device.displayName level was modified",
                    isStateChange: true
                ]
            break;
        }
    
    break;
}

return result

}

private String getAttribute(ArrayList _data) {
String retValue = ""
if (_data.size() >= 5) {
if (_data[2] == 1 && _data[3] == 1 && _data[4] == 0) {
retValue = "switch"
}
else if (_data[2] == 2 && _data[3] == 2 && _data[4] == 0) {
retValue = "level"
}
}

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

}


I'm not sure what's wrong with it or how to correct it.
My device: https://cdn.alzashop.com/ImgW.ashx?fd=f16&cd=Szyslk005

In any case, thanks in advance.

thank you all for the great work and trying, I have no experience in coding. has anyone managed to get a driver working for this module??
thanks

Hello . I have carried out several tests but I only manage to handle 1 trigger. The device contains 2 triggers but despite changing the corresponding value, it does not execute the correct function.

This driver works great except that it doesnโ€™t allow for control of ep2-4.

@CPS Thank You Good Driver. I can control Moes Dimmer With Hubitat.

But there is one question, when I use The Home Remote why is there no feedback on Level. Do you know the problem?

Donny

I cannot know for sure because I never tried to use such a remote.
But my guess is that the remote expects the standard ZHA commands/responses and therefore it cannot understand the Tuya ones.
If this is the case, then you could try to modify the driver to relay the ZHA command as well every time you adjust the level.

EDIT 17th of April 2022:
I have deleted the content of my previous post here, as this thread is about Moes dimmers (not just on/off switch control). Sorry about the confusion.

Sorry sir, i am blind with zigbee code

Mr @kkossev always help me

You could probably receive help checking in Home Remote dashboard for Hubitat thread.

The supplier of my Tuya TS0601 based dimmer has a SmartThings driver here if it helps anyone, although it looks like a copy of another driver:
https://drive.google.com/file/d/1eqLByV3P_9wEDrZV9bQvIWGg2MIT5ySB/view

/*
 *  Oz Smart Dimmer 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: "Oz Smart ZigBee Switch", namespace: "Oz Smart Things", author: "OST", 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"]

        //Oz Smart Switch
        // 1 gang
		fingerprint profileId: "0104", model: "TS0601", manufacturer: "_TZE200_amp6tsvy", endpointId: "01", inClusters: "0000,0004,0005,EF00", outClusters: "0019,000A", application: "42", deviceJoinName: "Oz Smart 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: "Oz Smart 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: "Oz Smart 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: 'Oz Smart 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:'Oz Smart 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
}
2 Likes