AI Driver

Hi Tony, I did used AI to write several Hubitat codes - including one for Hubitat integration with Airzone Local API. Here's mine, you can just copy paste from below

metadata {
    definition(name: "Airzone Aidoo Pro (Local API)", namespace: "my hubitat", author: "AP'") {
        capability "TemperatureMeasurement"
        capability "RelativeHumidityMeasurement"
        capability "Thermostat"
        capability "Refresh"
        capability "Polling"

        attribute "connectivity", "string"
        attribute "ecoMode", "string"
        attribute "ecoCoolPoint", "number"
        attribute "ecoHeatPoint", "number"
        attribute "roomTemp", "number"
        attribute "zoneID", "number"
        attribute "systemID", "number"
        attribute "modeText", "string"
        attribute "fanModeText", "string"
        attribute "supportedThermostatModes", "JSON_OBJECT"
        attribute "supportedThermostatFanModes", "JSON_OBJECT"

        command "setThermostatMode", [[name:"Thermostat mode*", type:"ENUM", constraints:["off","heat","cool","auto"]]]
        command "setThermostatFanMode", [[name:"Fan mode*", type:"ENUM", constraints:["auto","on"]]]
        command "setHeatingSetpoint", [[name:"Heating setpoint*", type:"NUMBER", description:"Set Heating Point (°C)"]]
        command "setCoolingSetpoint", [[name:"Cooling setpoint*", type:"NUMBER", description:"Set Cooling Point (°C)"]]
        command "refresh"
    }
    preferences {
        input("ip", "string", title:"Aidoo IP Address", description:"Device local IP, e.g. 192.168.1.73", required: true)
        input("systemID", "number", title:"System ID", description:"Usually 1", defaultValue:1, required: true)
        input("zoneID", "number", title:"Zone ID", description:"Usually 1", defaultValue:1, required: true)
        input("pollInterval", "number", title:"Polling interval (mins)", defaultValue:2, required: false)
    }
}

def installed() { initialize() }
def updated() { unschedule(); initialize() }
def initialize() {
    state.lastPoll = now()
    if (settings.pollInterval) runEveryNMinutes("refresh", settings.pollInterval as int)
    refresh()
}

// Main polling function - pulls latest zone/system state
def refresh() {
    def apiUrl = "http://${settings.ip}:3000/api/v1/hvac"
    def body = [systemID: settings.systemID, zoneID: settings.zoneID]
    def params = [
        uri: apiUrl,
        contentType: "application/json",
        body: groovy.json.JsonOutput.toJson(body),
        timeout: 5
    ]
    try {
        httpPost(params) { resp ->
            if(resp.status == 200 && resp.data?.data) {
                parseApiResponse(resp.data.data[0])
                sendEvent(name: "connectivity", value: "ONLINE")
            } else {
                sendEvent(name: "connectivity", value: "OFFLINE")
            }
        }
    } catch (e) {
        log.warn "Airzone API error: $e"
        sendEvent(name: "connectivity", value: "OFFLINE")
    }
}

def parseApiResponse(data) {
    // Standard states
    sendEvent(name: "temperature", value: data.roomTemp ?: data.setpoint)
    sendEvent(name: "humidity", value: data.humidity ?: 0)
    sendEvent(name: "heatingSetpoint", value: data.heatsetpoint ?: 0)
    sendEvent(name: "coolingSetpoint", value: data.coolsetpoint ?: 0)
    sendEvent(name: "thermostatMode", value: modeMap(data.mode))
    sendEvent(name: "thermostatOperatingState", value: data.on ? "heating" : "idle")
    sendEvent(name: "thermostatFanMode", value: fanModeMap(data.speed))

    // Update available modes for drop-downs (always in sync)
    sendEvent(name: "supportedThermostatModes", value: groovy.json.JsonOutput.toJson(["off","heat","cool","auto"]))
    sendEvent(name: "supportedThermostatFanModes", value: groovy.json.JsonOutput.toJson(["auto","on"]))

    // Custom states
    sendEvent(name: "ecoMode", value: data.eco_mode ? "ON" : "OFF")
    sendEvent(name: "ecoCoolPoint", value: data.ecoCoolPoint)
    sendEvent(name: "ecoHeatPoint", value: data.ecoHeatPoint)
    sendEvent(name: "roomTemp", value: data.roomTemp)
    sendEvent(name: "zoneID", value: data.zoneID)
    sendEvent(name: "systemID", value: data.systemID)
    sendEvent(name: "modeText", value: modeMap(data.mode))
    sendEvent(name: "fanModeText", value: fanModeMap(data.speed))
}

def modeMap(n) {
    switch(n as int) {
        case 1: return "heat"
        case 2: return "cool"
        case 3: return "auto"
        case 4: return "off"
        default: return "off"
    }
}
def fanModeMap(n) {
    switch(n as int) {
        case 0: return "auto"
        case 1: return "on"
        default: return "auto"
    }
}

// Set Thermostat Mode
def setThermostatMode(String mode) {
    def modeVal = modeStrToApi(mode)
    sendEvent(name: "thermostatMode", value: mode)   // <-- UI stays in sync immediately
    sendPut([systemID: settings.systemID, zoneID: settings.zoneID, mode: modeVal])
}
def setThermostatFanMode(String fanMode) {
    def speedVal = (fanMode == "on") ? 1 : 0
    sendEvent(name: "thermostatFanMode", value: fanMode)
    sendPut([systemID: settings.systemID, zoneID: settings.zoneID, speed: speedVal])
}
def setHeatingSetpoint(setpoint) {
    sendPut([systemID: settings.systemID, zoneID: settings.zoneID, heatsetpoint: setpoint as int])
}
def setCoolingSetpoint(setpoint) {
    sendPut([systemID: settings.systemID, zoneID: settings.zoneID, coolsetpoint: setpoint as int])
}
def sendPut(bodyMap) {
    def apiUrl = "http://${settings.ip}:3000/api/v1/hvac"
    def params = [
        uri: apiUrl,
        contentType: "application/json",
        body: groovy.json.JsonOutput.toJson(bodyMap),
        timeout: 5
    ]
    try {
        httpPut(params) { resp ->
            if(resp.status == 200) {
                log.info "Set succeeded: ${resp.data}"
                refresh()
            } else {
                log.warn "Set failed: ${resp.data}"
            }
        }
    } catch (e) {
        log.warn "Put error: $e"
    }
}
def modeStrToApi(mode) {
    switch(mode) {
        case "heat": return 1
        case "cool": return 2
        case "auto": return 3
        case "off": return 0
        default: return 0
    }
}
1 Like