[Release] Tasmota Sonoff Hubitat Driver & Device Support

It has to be something with the driver your are using. This is the one that I am using for my basics and it works perfectly. Although, you have to set the Network ID yourself manually. It has to be the MAC address of your sonoff for local changes on the Sonoff to work correctly.

Just save the driver, create a virtual device and pick this driver, setting the correct Network ID. Then set the preferences and it should work and report local changes in the device. Should work for all single switch sonoff tasmota devices.

// Original driver developed by Brett Sheleski.
// Ported to Hubitat and updated to include switchNumber by ryan780.
metadata {
definition(name: "Sonoff-Tasmota RPC", namespace: "ryan780", author: "ryan780") {
capability "Actuator"
capability "Switch"
capability "Momentary"
capability "Polling"
capability "Refresh"
}

preferences {		
	section("Sonoff Host") {
    input(name: "ipAddress", type: "string", title: "IP Address", displayDuringSetup: true, required: true)
	input(name: "port", type: "number", title: "Port", displayDuringSetup: true, required: true, defaultValue: 80)
    input(name: "switchNumber", type: "number", title: "Switch Number", displayDuringSetup: true, required: false, defaultValue: null)
	}

	section("Authentication") {
		input(name: "username", type: "string", title: "Username", displayDuringSetup: false, required: false)
		input(name: "password", type: "password", title: "Password (sent cleartext)", displayDuringSetup: false, required: false)
	}
	section("Logging"){
		input(name: "logEnable", type: "bool", title: "Debug Logging", required: false, defaultValue: false)
    }
}
}
 

def parse(String description) {
def message = parseLanMessage(description)

// parse result from current and legacy formats
def resultJson = {}
if (message?.json) {
	// current json data format
	resultJson = message.json
if (logEnable) log.debug resultJson
}
else {
	// legacy Content-Type: text/plain
	// with json embedded in body text
	def STATUS_PREFIX = "STATUS = "
	def RESULT_PREFIX = "RESULT = "
	if (message?.body?.startsWith(STATUS_PREFIX)) {
		resultJson = new groovy.json.JsonSlurper().parseText(message.body.substring(STATUS_PREFIX.length()))
	}
	else if (message?.body?.startsWith(RESULT_PREFIX)) {
		resultJson = new groovy.json.JsonSlurper().parseText(message.body.substring(RESULT_PREFIX.length()))
	}
	/* else if (message?.header?.contains("HTTP/1.1 200 OK")) {
		if (logEnable) log.debug $message?.header
	}*/
}

// consume and set switch state
if ((resultJson?."POWER$switchNumber" in ["ON", 1, "1"])) {
	setSwitchState(true)
}
else if ((resultJson?."POWER$switchNumber" in ["OFF", 0, "0"])) {
	setSwitchState(false)
}
else if ((resultJson?."POWER" in ["ON", 1, "1"])) {
	setSwitchState(true)
}
else if ((resultJson?."POWER" in ["OFF", 0, "0"])) {
	setSwitchState(false)
}
else {
//	log.error "can not parse result with header: $message.header"
//	log.error "...and raw body: $message.body"
}
}

def setSwitchState(Boolean on) {
if (logEnable) log.info "switch is " + (on ? "ON" : "OFF")
sendEvent(name: "switch", value: on ? "on" : "off")
}

def push() {
sendCommand("Power$switchNumber", "Toggle")
}

def on() {
sendCommand("Power$switchNumber", "On")
}

def off() {
sendCommand("Power$switchNumber", "Off")
}

def poll() {
sendCommand("Power$switchNumber", null)
}

def refresh() {
sendCommand("Power$switchNumber", null)
}

private def sendCommand(String command, String payload) {
if (logEnable) log.debug "sendCommand(${command}:${payload}) to device at $ipAddress:$port"

if (!ipAddress || !port) {
	log.warn "aborting. ip address or port of device not set"
	return null;
}
def hosthex = convertIPtoHex(ipAddress)
def porthex = convertPortToHex(port)

def path = "/cm"
if (payload){
	path += "?cmnd=${command}%20${payload}"
}
else{
	path += "?cmnd=${command}"
}

if (username){
	path += "&user=${username}"
	if (password){
		path += "&password=${password}"
	}
}

def result = new hubitat.device.HubAction(
	method: "GET",
	path: path,
	headers: [
		HOST: "${ipAddress}:${port}"
	]
)
return result
}

private String convertIPtoHex(ipAddress) {
String hex = ipAddress.tokenize( '.' ).collect { String.format( '%02x', it.toInteger() ) }.join()
return hex
}

private String convertPortToHex(port) {
String hexport = port.toString().format('%04x', port.toInteger())
return hexport
}
3 Likes