Hi,
Ive attached my driver so far. It does the switch functionality but cant get it to repeatedly show temperature. Can you send me your driver too?
/**
- Custom Driver for Tuya Zigbee TS0001 with Temperature Input (_TZE21C_dohbhb5k)
- Author: James
- Updated: April 2025
*/
metadata {
definition(name: "TS0001 Relay + Temp (Tuya) - temp displaying 2", namespace: "custom", author: "James") {
capability "Actuator"
capability "Switch"
capability "Temperature Measurement"
capability "Configuration"
capability "Refresh"
fingerprint profileId:"0104", endpointId:"01", inClusters:"0000,EB00,0003,0004,0005,0006", outClusters:"000A,0019", model:"TS0001", manufacturer:"_TZE21C_dohbhb5k"
}
}
preferences {
input name: "debugLogging", type: "bool", title: "Enable debug logging", defaultValue: true
}
def installed() {
log.debug "Installed"
initialize()
}
def updated() {
log.debug "Updated"
initialize()
}
def initialize() {
if (debugLogging) runIn(1800, logsOff)
sendEvent(name: "switch", value: "off")
}
def logsOff() {
device.updateSetting("debugLogging", [value:"false", type:"bool"])
log.warn "Debug logging disabled"
}
def parse(String description) {
if (debugLogging) log.debug "Parsing: ${description}"
if (description?.startsWith("catchall:")) {
def descMap = zigbee.parseDescriptionAsMap(description)
def cluster = descMap.cluster instanceof String
? Integer.parseInt(descMap.cluster, 16)
: descMap.cluster
// 1) ZCL On/Off commands (physical button)
if (cluster == 0x0006) {
def cmd = descMap.command instanceof String
? Integer.parseInt(descMap.command, 16)
: descMap.command
def newState = (cmd == 0x01) ? "on" : "off"
if (debugLogging) log.debug "On/Off cluster cmd 0x${String.format('%02X', cmd)} → ${newState}"
sendEvent(name: "switch", value: newState)
return
}
// 2) Tuya manufacturer‐specific (both UI and physical, plus temp)
if (cluster == 0xEF00) {
def tuya = zigbee.parseTuyaDataMap(descMap)
if (!tuya) {
if (debugLogging) log.debug "Failed to parse Tuya map: ${descMap}"
return
}
def dp = tuya.dataPoint as Integer
def value = tuya.data as Integer
switch (dp) {
// Relay on/off (UI toggle and physical button)
case 0x01: // some firmwares use DP01 for manual toggles
case 0x02: // DP02 is also common for relay
def state = (value == 1) ? "on" : "off"
if (debugLogging) log.debug "Tuya DP${String.format('%02X', dp)} (relay) → ${state}"
sendEvent(name: "switch", value: state)
break
// Temperature reports:
// DP0B, DP1B or DP1C depending on firmware
case 0x0B:
case 0x1B:
case 0x1C:
def tempC = (value / 10.0).round(1)
if (debugLogging) log.debug "Tuya DP${String.format('%02X', dp)} (temp) → ${tempC} °C"
sendEvent(name: "temperature", value: tempC, unit: "°C")
break
default:
if (debugLogging) log.debug "Unhandled Tuya DP ${String.format('%02X', dp)} → ${value}"
}
return
}
}
// 3) readAttr fallback for refresh()
if (description?.startsWith("read attr -")) {
def descMap = zigbee.parseDescriptionAsMap(description)
if (descMap.cluster == "0006" && descMap.attrId == "0000") {
def relayState = (descMap.value == "01") ? "on" : "off"
if (debugLogging) log.debug "On/Off attribute read → ${relayState}"
sendEvent(name: "switch", value: relayState)
}
}
}
// Tuya on/off control:
def on() {
sendTuyaCommand(2, 0x04, [0x01]) // thermostatMode=heat (relay ON)
sendEvent(name: "switch", value: "on")
}
def off() {
sendTuyaCommand(2, 0x04, [0x02]) // thermostatMode=off (relay OFF)
sendEvent(name: "switch", value: "off")
}
def sendTuyaCommand(dp, dp_type, dp_value) {
def dpHex = zigbee.convertToHexString(dp, 2)
def dpTypeHex = zigbee.convertToHexString(dp_type, 2)
def dpLenHex = zigbee.convertToHexString(dp_value.size(), 4)
def dpValHex = dp_value.collect { zigbee.convertToHexString(it, 2) }.join()
// Add random transaction ID for Tuya commands
def transId = zigbee.convertToHexString(new Random().nextInt(256), 2) + zigbee.convertToHexString(new Random().nextInt(256), 2)
def commandPayload = transId + dpHex + dpTypeHex + dpLenHex + dpValHex
def cmd = "he cmd 0x${device.deviceNetworkId} 0x01 0xEF00 0x00 {${commandPayload}}"
if (debugLogging) log.debug "Sending Tuya Command: ${cmd}"
sendHubCommand(new hubitat.device.HubAction(cmd, hubitat.device.Protocol.ZIGBEE))
}
def refresh() {
if (debugLogging) log.debug "Refresh called"
return zigbee.readAttribute(0x0006, 0x0000)
}
def configure() {
if (debugLogging) log.debug "Configuring..."
return refresh()
}