Help with some of my coding

Hello,

I am new to coding, I often just use others devices and smart apps, however i am trying to get some apps to do what i want them to do. I have been using https://github.com/midyear66/SmartApp-HVAC-circ-with-switch app to control my nest fan and it has been working great. I now however want the app to not only to control my nest but also my window ac units and fan switches. I have a forced heating system with no AC so i circulate the fan only. So theres a part on the code i edited that im not sure if im going to run into issues with. I want the circulation to start at one set point and the window AC units to start at another, when it gets warmer. Can someone just look at this part of my code and tell me if how its written will it work as i described above.

def start_circulate(){
DEBUG(“start_circulate()”)
if (sensor.currentValue(“temperature”) >= runTemp)
{ DEBUG (“into start_circulate() if statement”)
thermostat.fanOn()
}
if (sensor.currentValue(“temperature”) >= swTemp)
{ DEBUG (“into start_circulate() if statement”)
switches.on()
}

This are my notes…

def start_circulate(){
DEBUG("start_circulate()")
if (sensor.currentValue("temperature") >= runTemp){ //this will turn on the fan when the temp is above the runTemp value	
       DEBUG ("into start_circulate() if statement")
       thermostat.fanOn()
       //turn off switches here?
}
else if (sensor.currentValue("temperature") >= swTemp){	//This should turn on the switch when the temp is greater then the swTemp value
       DEBUG ("into start_circulate() if statement")
       switches.on()
       //maybe add thermostat.fanOff() here to turn fan off??
}

I would want the AC units on as well as having the circulation on at the same time, so i wouldn’t want to else if.

1 Like

You da boss my friend :slight_smile: But yeah what you have there should work for you. Not seeing the rest of the code makes it hard to say whether it will work in practice but those actions will happen based on temp :smile:

Nice thank you for taking a look at it. I have a device i would love you to take a look at for me now.

This is code form https://github.com/jwsf/device-type.ted5000/blob/master/device-type.ted5000.groovy and i made changes again so it works best for me. Here is what it looks like on my phone. I want to make the read outs different and cant figure out how and where to put my conversions. the 83 USD should really read $0.83 USD the 7614 USD should read $76.14 USD (this if the month to date) and the 1170 V to read 117.0 volts. So really i just need to know where and how to put the / 100 for the USD and the / 10 for the volts.

 preferences {
    input("url", "text", title: "URL", description: "The URL (including port number) of your TED5000 device (must be available to the public internet - example http://12.34.56.78:4444)", required: true)
    input("usr", "email", title: "Username", description: "The username configured in Network Settings on your TED5000", required: true)
    input("pass", "password", title: "Password", description: "The password configured in Network Settings on your TED5000", required: true)
    input(type: "enum", name: "chartGranularity", title: "Chart Granularity", options: granularityOptions(), defaultValue: "Daily", style: "segmented")
}

metadata {
	// Automatically generated. Make future change here.
	definition (name: "TED-5000", author: "tom") {
		capability "Energy Meter"
		capability "Polling"
		capability "Refresh"
        capability "Sensor"
		capability "Power Meter"
	}

	// simulator metadata
	simulator {
		for (int i = 100; i <= 3000; i += 200) {
			status "power  ${i} W": new physicalgraph.zwave.Zwave().meterV1.meterReport(
				scaledMeterValue: i, precision: 3, meterType: 4, scale: 2, size: 4).incomingMessage()
		}
		for (int i = 0; i <= 100; i += 10) {
			status "energy  ${i} kWh": new physicalgraph.zwave.Zwave().meterV1.meterReport(
				scaledMeterValue: i, precision: 3, meterType: 0, scale: 0, size: 4).incomingMessage()
		}
	}
	// UI tile definitions
	tiles {
	    
		
       
  
        
        valueTile(	"power", "device.power", canChangeBackground:true
                 ) 
        
        {state(	"power",
                    label:'${currentValue} W', 
                  	backgroundColors:[
					[value: 1, color: "#153591"],
					[value: 500, color: "#1e9cbb"],
					[value: 1000, color: "#90d2a7"],
					[value: 2500, color: "#44b621"],
					[value: 4000, color: "#f1d801"],
					[value: 6000, color: "#d04e00"],
					[value: 8000, color: "#bc2323"]
				    ]
                 )
		}
        
        
        
        
        
        valueTile(	"volts", 
                  "device.volts", decoration: "flat"
                 ) 
        {
            state("volts",
                    label:'${currentValue} V'
                 )
		}
 
        valueTile(	"cost", 
                  "device.cost", decoration: "flat"
                 ) 
        {
            state("cost",
                    label:'${currentValue} USD'
                 )
		}
     
       valueTile(	"costmtd", 
                  "device.costmtd", decoration: "flat"
                 ) 
        {
            state("costmtd",
                    label:'${currentValue} USD'
                 )
		}
        
        
        
        
        
        standardTile("refresh", "device.power") {
			state "default", action:"refresh.refresh", icon:"st.secondary.refresh"
		}







		main(["power", "cost", "volts"])
		details(["power", "cost", "costmtd", "volts", "refresh"])
	}
}



def poll() {
	doUpdate()
}

def refresh() {
	doUpdate()
}

def doUpdate() {

    // Build auth string
    def auth = settings.usr + ":" + settings.pass
	auth = auth.getBytes()
    auth = auth.encodeBase64()
    String authString = auth

	// Build URL
    def URL = settings.url + "/api/LiveData.xml"
    log.debug "Connecting to " + URL
    
    def params = [
        uri: URL,
        headers: [
            'Authorization': "Basic ${authString}"
        ]
    ]
    
    // This closure is called to parse the XML if it is successfully retrieved
    def successClosure = { response ->
    	log.debug "Request to TED5000 was successful"
        def power = response.data.Power.Total.PowerNow
        def volts = response.data.Voltage.Total.VoltageNow
        def cost = response.data.Cost.Total.CostNow
        def costmtd = response.data.Cost.Total.CostMTD
      	log.debug "Sending event - power: $power W Volts: $voltageNow V Cost: $costNow and CostMTD: $costMTD"
        sendEvent (name: "cost", value: cost, unit:"USD")
        sendEvent (name: "volts", value: volts, unit:"V")
   		sendEvent (name: "power", value: power, unit:"W")
        sendEvent (name: "costmtd", value: costmtd, unit:"USD")
        
        
	}
    
    try {
    
        // Get the XML from the TED5000
    	httpGet(params,  successClosure)
    } catch ( java.net.UnknownHostException e) {
    	log.error "Unknown host - check the URL and PORT for your device"
    	sendEvent name: "power", value: "Unknown host"
   	} catch (java.net.NoRouteToHostException t) {
    	log.error "No route to host - check the URL and PORT for your device " + URL
    	sendEvent name: "power", value: "No route to host"
    } catch (java.io.FileNotFoundException fnf) {
    	log.error "File not found - check the URL and PORT for your device " + URL
        sendEvent name: "power", value: "XML not found"
    } catch (java.io.IOException e) {
    	log.error "Authentication error - check USERNAME and PASSWORD. This can also occur if the TED5000 cannot be reached"
        sendEvent name: "power", value: "Auth error"
    } catch (any) {
    	log.error "General error trying to connect to TED and retrieve data " URL
    	sendEvent name: "power", value: "ERROR"
    }
}


def getVisualizationData(attribute) {
	log.debug "getChartData for $attribute"
	def keyBase = "measure.${attribute}${getGranularity()}"
	log.debug "getChartData state = $state"

	def dateBuckets = state[keyBase]

	//convert to the right format
	def results = dateBuckets?.sort { it.key }.collect {
		[
			date: Date.parse("yyyy-MM-dd", it.key),
			average: it.value.average,
			min: it.value.min,
			max: it.value.max
		]
	}

	log.debug "getChartData results = $results"
	results
}


private storeData(attribute, value, dateString = getKeyFromDateDaily()) {
	log.debug "storeData initial state: $state"
	def keyBase = "measure.${attribute}"
	def numberValue = value.toBigDecimal()

	// create bucket if it doesn't exist
	if (!state[keyBase]) {
		state[keyBase] = [:]
		log.debug "storeData - attribute not found. New state: $state"
	}

	if (!state[keyBase][dateString]) {
		//no date bucket yet, fill with initial values
		state[keyBase][dateString] = [:]
		state[keyBase][dateString].average = numberValue
		state[keyBase][dateString].runningSum = numberValue
		state[keyBase][dateString].runningCount = 1
		state[keyBase][dateString].min = numberValue
		state[keyBase][dateString].max = numberValue

		log.debug "storeData date bucket not found. New state: $state"

		// remove old buckets
		def old = getKeyFromDateDaily(new Date() - 10)
		state[keyBase].findAll { it.key < old }.collect { it.key }.each { state[keyBase].remove(it) }
	} else {
		//re-calculate average/min/max for this bucket
		state[keyBase][dateString].runningSum = (state[keyBase][dateString].runningSum.toBigDecimal()) + numberValue
		state[keyBase][dateString].runningCount = state[keyBase][dateString].runningCount.toInteger() + 1
		state[keyBase][dateString].average = state[keyBase][dateString].runningSum.toBigDecimal() / state[keyBase][dateString].runningCount.toInteger()

		log.debug "storeData after average calculations. New state: $state"

		if (state[keyBase][dateString].min == null) {
			state[keyBase][dateString].min = numberValue
		} else if (numberValue < state[keyBase][dateString].min.toBigDecimal()) {
			state[keyBase][dateString].min = numberValue
		}
		if (state[keyBase][dateString].max == null) {
			state[keyBase][dateString].max = numberValue
		} else if (numberValue > state[keyBase][dateString].max.toBigDecimal()) {
			state[keyBase][dateString].max = numberValue
		}
	}
	log.debug "storeData after min/max calculations. New state: $state"
}



// This next method is only used from the simulator
def parse(String description) {
	def result = null
	def cmd = zwave.parse(description, [0x31: 1, 0x32: 1, 0x60: 3])
	if (cmd) {
		result = createEvent(zwaveEvent(cmd))
	}
	log.debug "Parse returned ${result?.descriptionText}"
	return result
}

// This next method is only used from the simulator
def zwaveEvent(physicalgraph.zwave.commands.meterv1.MeterReport cmd) {
	if (cmd.scale == 0) {
		[name: "energy", value: cmd.scaledMeterValue, unit: "kWh"]
	} else if (cmd.scale == 1) {
		[name: "energy", value: cmd.scaledMeterValue, unit: "kVAh"]
	}
	else {
		[name: "power", value: Math.round(cmd.scaledMeterValue), unit: "W"]
	}
}




def getGranularity() {
	chartGranularity ?: "Daily"
}

def granularityOptions() { ["Daily", "Hourly"] }

private getKeyFromDateDaily(date = new Date()) {
	date.format("yyyy-MM-dd")
}

private getKeyFromDateHourly(date = new Date()) {
	date.format("yyyy-MM-dd:HH")
}

Thank you for your help. Here is the rest of the code incase you or anyone else is interested.
Again main code is form https://github.com/midyear66/SmartApp-HVAC-circ-with-switch

definition(
    name: "Keep-it-cool",
    namespace: "tomforti",
    author: "Tom",
    description: "Run circulate every X minutes if AC or heat has not been on",
    category: "Green Living",
    iconUrl: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience.png",
    iconX2Url: "https://s3.amazonaws.com/smartapp-icons/Convenience/Cat-Convenience%402x.png")


preferences {
	section("Title") {
		paragraph "Run circulate in HVAC and trigger switch or outlet"
	}
	section("About") {
        	paragraph "Run circulate every X minutes if AC or heat has not been on"
            paragraph "Turn on a switch or outlet every X minutes if AC or heat has not been on"
            paragraph "Additional setpoint can be used to determine minimum run temperature."
          
    }
    	section("Controlled Devices") {
        	input "thermostat", "capability.thermostat", title:"Select thermostat to be controlled"
            input "switches", "capability.switch", title:"Select switch or outlet to be controlled", multiple: true
        	input "interval", "number", title:"Set time between circulation cycles (in minutes)", defaultValue:30
        	input "length", "number", title:"Set of length of circulation cycle (in minutes)", defaultValue:5
		}
        section("Choose a temperature sensor... "){
			input "sensor", "capability.temperatureMeasurement", title: "Temperature Sensor used to establish minimum run temperature"
		}
		section("Operation") {
			input "runTemp", "number", title:"Choose a temperature to set the minimum run temperature for circulate.", defaultValue:70
            input "swTemp", "number", title:"Choose a temperature to set the minimum run temperature for switch or outlet.", defaultValue:70
			input "onoff", "capability.switch", title:"Select switch to control operation.  Typically a virtual switch created in the IDE" 
        }
}

def installed() {
	DEBUG("Installed with settings: ${settings}")
    initialize()
}

def updated() {
	DEBUG("Updated with settings: ${settings}")
	unsubscribe()
	unschedule()
   	initialize()

}

def onHandler(evt) {
	DEBUG(evt.value)
	LOG("Running Switch On Event")
    scheduler()
}

def offHandler(evt) {
	DEBUG(evt.value)
	LOG("Running Switch Off Event")
    unschedule()
    thermostat.fanAuto()
    switches.off()
}

def scheduler(){
	DEBUG ("scheduler()")
    thermostat.fanAuto()
    switches.off()
	def interval = settings.interval.toInteger() * 60
	def length = settings.length.toInteger() * 60
	DEBUG("Interval in seconds: ${interval}, Length in seconds: ${length}")
	runIn(interval, start_circulate)
	runIn(interval+length, scheduler)
}
        
def start_circulate(){
	DEBUG("start_circulate()")
      if (sensor.currentValue("temperature") >= runTemp)
	{	DEBUG ("into start_circulate() if statement")
		thermostat.fanOn()
   	}
    if (sensor.currentValue("temperature") >= swTemp)
	{	DEBUG ("into start_circulate() if statement")
		switches.on()
   	}
  
    
}

def initialize() {
	DEBUG("initialize()")
    subscribe(onoff, "switch.on", onHandler)
    subscribe(onoff, "switch.off", offHandler)
    subscribe(device, "thermostatOperatingState", eventHandler)
    DEBUG ("running_state: ${thermostat.currentValue("thermostatOperatingState")}")
    DEBUG ("On/Off Switch: ${onoff.currentswitch}")
	if(thermostat.currentValue("thermostatOperatingState") == "idle" && onoff.currentSwitch == "on"){
		scheduler()
    }
}
    
// TODO: implement event handlers

def eventHandler(evt){
	DEBUG("eventHandler: ${evt.value}: ${evt}, ${settings}")
	if(evt.value == "idle"){
    	LOG("idle - running scheduler()")
		scheduler()
	}
	if(evt.value == "heating"|| evt.value == "cooling"){
		LOG("not idle - running unschedule()")
    		unschedule()
    		thermostat.fanAuto()
            switches.off()
   }
}

private def LOG(message){
	log.info message
}

private def DEBUG(message){
	//log.debug message
}
1 Like

I actually just discovered an issue. So the way the code is it won’t kick on the window ac unit u too the interval time is over. So if the target temp for the circulation is hit and that starts up and the temp keeps rising the ac unit (switch or outlet) won’t kick on until the schedule is over. Ideas?

Tomforti,

I added your TED5000 device type to my ST, but it doesn’t show up under my Things.

How do I get my TED5000 to show up?

Thanks!

If your device is already in the system, but the wrong type, edit the type of your device to be the new device type.

FYI the device type works good for me but never figured out how to fix the issue with the dollar value or volts. I recommend you connect up ur ted5000 to bidgely.