[RELEASE] Tuya Zigbee Thermostats and TRVs driver

For anyone still trying to get this to work, this is the working driver code below that I have working to get the temp. Picture below of my unit below too

/**
 *  Tuya TS000F Temperature Relay (Multi-Endpoint EF00 Decoder)
 */

metadata {
    definition(name: "TS000F Temp Relay (Multi-EP)", namespace: "chatgpt.custom", author: "ChatGPT") {

        capability "Switch"
        capability "Temperature Measurement"
        capability "Refresh"
        capability "Configuration"

        // MAIN fingerprint
        fingerprint profileId:"0104",
            inClusters:"0000,0003,0004,0005,0006,E001,E000,EF00",
            outClusters:"000A,0019",
            manufacturer:"_TZ3218_7fiyo3kv",
            model:"TS000F"

        // Extra fingerprints to ensure Hubitat binds EF00 to this driver
        fingerprint endpointId:"02", profileId:"0104",
            inClusters:"0000,0003,0004,0005,0006,E001,E000,EF00",
            outClusters:"000A,0019",
            manufacturer:"_TZ3218_7fiyo3kv",
            model:"TS000F"

        fingerprint endpointId:"03", profileId:"0104",
            inClusters:"0000,0003,0004,0005,0006,E001,E000,EF00",
            outClusters:"000A,0019",
            manufacturer:"_TZ3218_7fiyo3kv",
            model:"TS000F"
    }
}

preferences {
    input "debugLogging", "bool", title:"Enable debug logging", defaultValue:true
    input "useF", "bool", title:"Use Fahrenheit?", defaultValue:false
}

def logDebug(msg){ if(debugLogging) log.debug msg }

def parse(String desc) {
    logDebug "RAW: ${desc}"

    // Do NOT filter EF00 by endpoint — accept everything
    if (!desc.contains("EF00")) return

    def map = zigbee.parseDescriptionAsMap(desc)
    if (!map?.data) return

    def raw = map.data
    if (raw.size() < 6) return

    //---------------------------------------------------------
    // Decode Temperature from last 2 bytes
    //---------------------------------------------------------
    try {
        def tail = raw[-4..-1].join()
        def tempRaw = Integer.parseInt(tail, 16)
        def tempC = tempRaw / 10.0

        def out = tempC
        def unit = "°C"
        if (useF) {
            out = (tempC * 1.8 + 32).toDouble().round(1)
            unit = "°F"
        }

        sendEvent(name:"temperature", value: out, unit: unit)
        logDebug "Temperature decoded → ${out}${unit}"
    } catch (e) {
        logDebug "Temp decode failed: ${e}"
    }

    //---------------------------------------------------------
    // Relay state based on last byte
    //---------------------------------------------------------
    def lastByte = raw[-1]
    if (lastByte == "01") {
        sendEvent(name:"switch", value:"on")
        logDebug "Relay → ON"
    }
    if (lastByte == "00") {
        sendEvent(name:"switch", value:"off")
        logDebug "Relay → OFF"
    }
}

def on()  { sendRelayCmd(1) }
def off() { sendRelayCmd(0) }

def sendRelayCmd(val) {
    def payload = "00001F010001" + zigbee.convertToHexString(val, 2)
    logDebug "Send Relay Cmd: ${payload}"
    sendHubCommand(new hubitat.device.HubAction(
        "he cmd 0x${device.deviceNetworkId} 0x01 0xEF00 0x00 {${payload}}",
        hubitat.device.Protocol.ZIGBEE))
}

def refresh() {
    logDebug "Refresh"
    zigbee.readAttribute(0x0006, 0x0000)
}

def configure() {
    logDebug "Configure"
}
1 Like