OK, here is the original SmartThings DTH that you linked earlier in this thread which I have made some very basic changes to in order for it to work with Hubitat. I have no way of testing this, but it does compile. This appears to be a Child Driver, which will require a Parent in order to work properly.
/**
* Tasmota - Virtual Air Conditioner
*
* Copyright 2020 AwfullySmart.com - HongTat Tan
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import groovy.json.JsonOutput
String driverVersion() { return "20200913" }
metadata {
definition (name: "Tasmota Virtual Air Conditioner", namespace: "hongtat", author: "HongTat Tan") {
capability "Actuator"
capability "Temperature Measurement"
capability "Thermostat Cooling Setpoint"
capability "Thermostat Mode"
//capability "voicehouse43588.airConditionerFanSpeed"
//capability "voicehouse43588.airConditionerVerticalSwing"
//capability "voicehouse43588.airConditionerHorizontalSwing"
capability "Switch"
//capability "Health Check"
capability "Configuration"
capability "Refresh"
capability "Sensor"
attribute "lastSeen", "string"
attribute "airConditionerFanSpeed", "string"
attribute "airConditionerVerticalSwing", "string"
attribute "airConditionerHorizontalSwing", "string"
}
preferences {
section {
input(title: "Device Settings",
description: "To view/update this settings, go to the Tasmota (Connect) SmartApp and select this device.",
displayDuringSetup: false,
type: "paragraph",
element: "paragraph")
input(title: "", description: "Tasmota Virtual Air Conditioner v${driverVersion()}", displayDuringSetup: false, type: "paragraph", element: "paragraph")
}
}
/*
tiles(scale: 2) {
multiAttributeTile(name:"thermostat", type:"general", width:6, height:4, canChangeIcon: false) {
tileAttribute("device.switch", key: "PRIMARY_CONTROL") {
attributeState("off", label: "Off", action: "switch.on", icon: "st.thermostat.heating-cooling-off", backgroundColor: "#ffffff")
attributeState("on", label: "On", action: "switch.off", backgroundColor: "#00a0dc")
}
tileAttribute("device.temperature", key: "SECONDARY_CONTROL") {
attributeState("temperature", label:'${currentValue}°', icon: "st.alarm.temperature.normal")
}
tileAttribute("device.coolingSetpoint", key: "COOLING_SETPOINT") {
attributeState("default", label: '${currentValue}', unit: "°", defaultState: true)
}
}
controlTile("coolingSetpoint", "device.coolingSetpoint", "slider",
sliderType: "COOLING",
debouncePeriod: 750,
range: "device.coolingSetpointRange",
width: 2, height: 2) {
state "default", action:"setCoolingSetpoint", label:'${currentValue}', backgroundColor: "#55D4ED"
}
controlTile("thermostatMode", "device.thermostatMode", "enum", width: 2 , height: 2, supportedStates: "device.supportedThermostatModes") {
state("off", action: "setThermostatMode", label: 'Off', icon: "st.thermostat.heating-cooling-off")
state("cool", action: "setThermostatMode", label: 'Cool', icon: "st.thermostat.cool")
state("heat", action: "setThermostatMode", label: 'Heat', icon: "st.thermostat.heat")
state("auto", action: "setThermostatMode", label: 'Auto', icon: "st.tesla.tesla-hvac")
}
controlTile("fanSpeed", "device.fanSpeed", "enum", width: 2 , height: 2, supportedStates: "device.supportedFanSpeed") {
state("auto", action: "setFanSpeed", label: 'Auto', icon: "st.thermostat.fan-on")
state("1", action: "setFanSpeed", label: 'Min', icon: "st.thermostat.fan-on")
state("2", action: "setFanSpeed", label: 'Low', icon: "st.thermostat.fan-on")
state("3", action: "setFanSpeed", label: 'Medium', icon: "st.thermostat.fan-on")
state("4", action: "setFanSpeed", label: 'High', icon: "st.thermostat.fan-on")
state("5", action: "setFanSpeed", label: 'Max', icon: "st.thermostat.fan-on")
}
controlTile("swingV", "device.swingV", "enum", width: 3 , height: 1, supportedStates: "device.supportedAirConditionerSwingV") {
state("auto", action: "setSwingV", label: 'Auto')
state("off", action: "setSwingV", label: 'Off')
state("min", action: "setSwingV", label: 'Min')
state("low", action: "setSwingV", label: 'Low')
state("mid", action: "setSwingV", label: 'Mid')
state("high", action: "setSwingV", label: 'High')
state("max", action: "setSwingV", label: 'Max')
}
valueTile("spacerV", "spacer", decoration: "flat", inactiveLabel: false, width: 3, height: 1) {
state "default", label:'Swing-V'
}
controlTile("swingH", "device.swingH", "enum", width: 3 , height: 1, supportedStates: "device.supportedAirConditionerSwingH") {
state("auto", action: "setSwingH", label: 'Auto')
state("off", action: "setSwingH", label: 'Off')
state("left max", action: "setSwingH", label: 'Left Max')
state("left", action: "setSwingH", label: 'Left')
state("mid", action: "setSwingH", label: 'Mid')
state("right", action: "setSwingH", label: 'Right')
state("right max", action: "setSwingH", label: 'Right Max')
state("wide", action: "setSwingH", label: 'Wide')
}
valueTile("spacerH", "spacer", decoration: "flat", inactiveLabel: false, width: 3, height: 1) {
state "default", label: 'Swing-H'
}
main "thermostat"
details(["thermostat", "thermostatMode", "fanSpeed", "coolingSetpoint", "swingV", "swingH", "spacerV", "spacerH"])
}
*/
}
def parse(description) {
}
def parseEvents(status, json) {
def events = []
if (status as Integer == 200) {
// Bridge's Last seen
if (json?.lastSeen) {
events << sendEvent(name: "lastSeen", value: json?.lastSeen, displayed: false)
}
}
return events
}
def ping() {
// Intentionally left blank as parent should handle this
}
def installed() {
state?.lastMode = "cool"
sendEvent(name: "checkInterval", value: 30 * 60 + 2 * 60, displayed: false, data: [protocol: "lan", hubHardwareId: device.hub.hardwareID])
sendEvent(name: "supportedThermostatModes", value: JsonOutput.toJson(supportedThermostatModes), displayed: false)
sendEvent(name: "supportedFanSpeed", value: JsonOutput.toJson(supportedFanSpeed), displayed: false)
sendEvent(name: "supportedAirConditionerSwingV", value: JsonOutput.toJson(supportedAirConditionerSwingV), displayed: false)
sendEvent(name: "supportedAirConditionerSwingH", value: JsonOutput.toJson(supportedAirConditionerSwingH), displayed: false)
sendEvent(name: "coolingSetpointRange", value: thermostatSetpointRange, displayed: false)
sendEvent(name: "switch", value: "off", displayed: false)
sendEvent(name: "fanSpeed", value: supportedFanSpeed[0], displayed: false)
sendEvent(name: "coolingSetpoint", value: thermostatSetpointRange[0], unit: getTemperatureScale(), displayed: false)
sendEvent(name: "temperature", value: thermostatSetpointRange[0], unit: getTemperatureScale(), displayed: false)
sendEvent(name: "thermostatMode", value: "off", data:[supportedThermostatModes: JsonOutput.toJson(supportedThermostatModes)], displayed: false)
sendEvent(name: "swingV", value: "auto", displayed: false)
sendEvent(name: "swingH", value: "auto", displayed: false)
}
def updated() {
initialize()
}
def initialize() {
}
def setFanSpeed(String speed) {
def fanSpeed = [name: "fanSpeed"]
if (supportedFanSpeed.contains(speed as String)) {
fanSpeed.value = speed as String
sendEvent(fanSpeed)
done()
} else {
log.debug "Unsupported fan speed: '${speed}'"
}
}
def on() {
if (state?.lastMode) {
setThermostatMode(state?.lastMode)
} else {
setThermostatMode("cool")
}
}
def off() {
setThermostatMode("off")
}
def cool() {
setThermostatMode("cool")
}
def heat() {
setThermostatMode("heat")
}
def auto() {
setThermostatMode("auto")
}
def setThermostatMode(String mode) {
def modeMap = [name: "thermostatMode", data:[supportedThermostatModes: supportedThermostatModes.encodeAsJson()]]
def switchMap = [name: "switch"]
if (supportedThermostatModes.contains(mode)) {
switch (mode) {
case "off":
modeMap.value = "off"
modeMap.displayed = true
switchMap.value = "off"
break
default:
modeMap.value = mode
modeMap.displayed = true
switchMap.value = "on"
state?.lastMode = mode
break
}
sendEvent(modeMap)
sendEvent(switchMap)
done()
} else {
log.debug "Unsupported AC mode: '${mode}'"
}
}
def setCoolingSetpoint(setpoint) {
if (setpoint < thermostatSetpointRange[0]) {
setpoint = thermostatSetpointRange[0]
} else if (setpoint > thermostatSetpointRange[1]) {
setpoint = thermostatSetpointRange[1]
}
sendEvent(name: "coolingSetpoint", value: setpoint, unit: getTemperatureScale(), displayed: false)
sendEvent(name: "temperature", value: setpoint, unit: getTemperatureScale())
done()
}
def setSwingV(verticalSwing) {
if (supportedAirConditionerSwingV.contains(verticalSwing)) {
sendEvent(name: "swingV", value: verticalSwing)
done()
} else {
log.debug "Unsupported vertical swing mode: '${verticalSwing}'"
}
}
def setSwingH(horizontalSwing) {
if (supportedAirConditionerSwingH.contains(horizontalSwing)) {
sendEvent(name: "swingH", value: horizontalSwing)
done()
} else {
log.debug "Unsupported horizontal swing mode: '${horizontalSwing}'"
}
}
def done() {
def bridge = parent.childSetting(device.id, "bridge") ?: null
def vendor = parent.childSetting(device.id, "hvac") ?: null
if (bridge && vendor) {
def command = [:]
def power = device.currentState("switch").value
command.Vendor = vendor
command.Power = power
command.Mode = (power == "off") ? state.lastMode : device.currentState("thermostatMode").value
command.FanSpeed = device.currentState("fanSpeed").value
command.Temp = device.currentState("coolingSetpoint").value
command.SwingV = device.currentState("swingV").value
command.SwingH = device.currentState("swingH").value
if (getTemperatureScale() == "F") {
command.Celsius = 'Off'
}
if (power == "off") {
log.debug "Command 1: " + JsonOutput.toJson(command)
parent.callTasmota(bridge, 'IRhvac ' + JsonOutput.toJson(command))
command.Mode = "off"
log.debug "Command 2: " + JsonOutput.toJson(command)
parent.callTasmota(bridge, 'IRhvac ' + JsonOutput.toJson(command))
} else {
log.debug "Command: " + JsonOutput.toJson(command)
parent.callTasmota(bridge, 'IRhvac ' + JsonOutput.toJson(command))
}
} else {
log.debug "Error: Please specify an IR bridge and air conditioner brand"
}
}
def getThermostatSetpointRange() {
(getTemperatureScale() == "C") ? [16, 31] : [60, 87]
}
def getSupportedThermostatModes() {
["off", "cool", "heat", "auto"]
}
def getSupportedFanSpeed() {
["auto", "1", "2", "3", "4", "5"]
}
def getSupportedAirConditionerSwingV() {
["auto", "off", "min", "low", "mid", "high", "max"]
}
def getSupportedAirConditionerSwingH() {
["auto", "off", "left max", "left", "mid", "right", "right max", "wide"]
}
The more I look at this ST DTH, the more confused I get. I think the original author created custom capabilities using the New ST API. These are not supported on Hubitat. So, I am not sure if this DTH will ever work properly without a significant rewrite on Hubitat.
Do you have this working on SmartThings today?