[OBSOLETE]Intermatic PE653 Pool Control System

Jumping on this thread because it is the reason I ordered my ST hub. I had a few questions before I get started so that I can temper my expectations.

  1. I have a pentair VS Pump connected to my PE653. I have no idea what circuit it is on as I actually access the pump VIA my PE953 remote on a separate screen. When I go to the separate screen I choose the pump speed. Has anyone successfully been able to control the pump speed through the ST app?

  2. My heater is setup so that it will not run unless my pump speed exceeds 750rpm (the heater just needs a strong enough flow). Has anyone setup a 1 button scene to create a scenario wherein the heater will kick in and the pump will turn on?

Anxious to try this stuff out and great work!

1 Like

Ok, something seems strange. I copied the code and did the setup. I even added the device and assigned it device ID12345.

But how does that link the device to my actual pool control? Don’t I have to try to include the device or add a new device? Is that the way I should do it.

Anyone out there? Anyone do anything about the PE953 (the remote?).

@JDogg016 My guess is that the PE953 won’t be necessary if you’re bothering to link the system to SmartThings.

You will add a new device to SmartThings and pair the PE653. I’m not sure what default device type ST will assign it as I don’t have one of these (yet). Once you have paired the device, go into the API and change its device type to the code here. Let us know how it works out for you!

Got it and got it paired. I even got my remote to act as a slave device. Now I just need to get the VSP setup. Any thoughts on that. None of my switches activate the pump because it’s variable.

@JDogg016 Try opening the device under “My Devices” in the API. There should be some options to configure under “Preferences” you can edit. Let us know!

Yeah, you see this is the issue. Since I copied @bigpunk6 code, I cannot simply go into preferences and check boxes anymore.

I looked at his code and with a rudimentary understanding of the code plainly see there is no thermostat control whatsoever. I presume because @bigpunk6 does not have a heater unit, but has a temperature monitoring unit.

There would be two parts to what I need.

  1. Temperature control (up and down)
  2. The ability to activate the variable speed pentair pump to set its speed (modes 1-4).

The pool pump is NOT directly controlled by a switch on the PE653 meaning I don’t hit “1” for example to activate the pump. Instead, I go to the PE953 remote unit and Navigate to a secondary screen that allows me to choose my pump speed. This is important because the pump must run at a certain speed in order to create enough flow to turn on the pool heater. For instance, if I could set the temperature of the pool to 80 degrees, it would be useless to do so unless I can turn the pool pump on to pump water through the heater and back through the pool.

One thought I did have (which I will really have to try out) is to experiment with the PE953 remote unit and create scenes for the remote itself. For example, create a scene on my remote control unit that will turn on the pool pump and the heater and then find a way to get that scene from the pool remote to the Smartthings Hub.

Has anyone in here had any thoughts or experience with operating a z-wave remote control and copying the controls over to another device?

If this all works it will be pretty EPIC!

@JDogg016 It’s possible the Intermatic PE953 could be configured as a secondary controller. Take a look at the instructions about the Intermatic HA07/HA09 here for setup ideas.

@matt_coulter Because your family is in the business, could you please explain whether I need a separate “expansion module” or “load center” like Intermatic sells in this package? How would the actuators otherwise be wired if those items are not necessary? Thanks so much for the clarification! Once I get my hands on one of these, I’ll be much more likely to assist here.

This is a great update. I was able to make the PE953 a secondary controller which is good because I am having all sorts of issues working with @bigpunk6 device type code (they’re are my issues regarding lack of programming ability and not his). Anyway, a few more thoughts

  • Switch 4 controls my light and it is nice to see that switch on the main screen however I cannot automate this switch (ie. turn off ‘Pool Remote’ Switch 4 when I go to bed. Is there a way to do this? Perhaps creating a virtual button.

  • The idea of creating scenes on the remote is useless because the remote only permits you to create scenes by adding extra devices (not through the pool unit itself).

  • Bringing me back to square 1 which is how can a create a thermostat tile and thermostat slider and

  • How do I add a VSP pump to control each level of speed.

Thanks for all your input thus far! You all have been great!

Ok… i sort of tried to work with @bigpunk6 code to at least integrate the heater… so far nothing. This is what I got.

/**

  • PoolSwitch
  • Copyright 2014 bigpunk6
  • Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except
  • in compliance with the License. You may obtain a copy of the License at:
  •  http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  • on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  • for the specific language governing permissions and limitations under the License.

*/
metadata {
definition (name: “PoolSwitch”, author: “bigpunk6”) {
capability "Actuator"
capability "Switch"
capability "Polling"
capability "Configuration"
capability "Refresh"
capability "Temperature Measurement"
capability "Sensor"
capability “Thermostat”

	attribute "switch1", "string"
	attribute "switch2", "string"
	attribute "switch3", "string"
	attribute "switch4", "string"
	attribute "switch5", "string"

	command "onMulti"
	command "offMulti"
    command "on1"
	command "off1"
    command "on2"
	command "off2"
    command "on3"
	command "off3"
    command "on4"
	command "off4"
    command "on5"
	command "off5"
    command "poll"
}

simulator {
	simulator {
	status "off"			: "command: 4003, payload: 00"
	status "heat"			: "command: 4003, payload: 01"
	status "cool"			: "command: 4003, payload: 02"
	status "auto"			: "command: 4003, payload: 03"
	status "emergencyHeat"	: "command: 4003, payload: 04"

	status "fanAuto"		: "command: 4403, payload: 00"
	status "fanOn"			: "command: 4403, payload: 01"
	status "fanCirculate"	: "command: 4403, payload: 06"

	status "heat 60"        : "command: 4303, payload: 01 01 3C"
	status "heat 68"        : "command: 4303, payload: 01 01 44"
	status "heat 72"        : "command: 4303, payload: 01 01 48"

	status "cool 72"        : "command: 4303, payload: 02 01 48"
	status "cool 76"        : "command: 4303, payload: 02 01 4C"
	status "cool 80"        : "command: 4303, payload: 02 01 50"

	status "temp 58"        : "command: 3105, payload: 01 22 02 44"
	status "temp 62"        : "command: 3105, payload: 01 22 02 6C"
	status "temp 70"        : "command: 3105, payload: 01 22 02 BC"
	status "temp 74"        : "command: 3105, payload: 01 22 02 E4"
	status "temp 78"        : "command: 3105, payload: 01 22 03 0C"
	status "temp 82"        : "command: 3105, payload: 01 22 03 34"

	status "idle"			: "command: 4203, payload: 00"
	status "heating"		: "command: 4203, payload: 01"
	status "cooling"		: "command: 4203, payload: 02"
	status "fan only"		: "command: 4203, payload: 03"
	status "pending heat"	: "command: 4203, payload: 04"
	status "pending cool"	: "command: 4203, payload: 05"
	status "vent economizer": "command: 4203, payload: 06"

	// reply messages
	reply "2502": "command: 2503, payload: FF"
}
}

// tile definitions
tiles {
	standardTile("switch1", "device.switch1",canChangeIcon: true) {
		state "on", label: "switch1", action: "off1", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch1", action: "on1", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch2", "device.switch2",canChangeIcon: true) {
		state "on", label: "switch2", action: "off2", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch2", action: "on2", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch3", "device.switch3",canChangeIcon: true) {
		state "on", label: "switch3", action: "off3", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch3", action:"on3", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch4", "device.switch4",canChangeIcon: true) {
		state "on", label: "switch4", action: "off4", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch4", action:"on4", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch5", "device.switch5",canChangeIcon: true) {
		state "on", label: "switch5", action: "off5", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch5", action:"on5", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	
    
    }
	valueTile("temperature", "device.temperature", width: 2, height: 2) {
		state("temperature", label:'${currentValue}°', unit:"F",
			backgroundColors:[
				[value: 31, color: "#153591"],
				[value: 44, color: "#1e9cbb"],
				[value: 59, color: "#90d2a7"],
				[value: 74, color: "#44b621"],
				[value: 84, color: "#f1d801"],
				[value: 95, color: "#d04e00"],
				[value: 96, color: "#bc2323"]
			]
		)
	}
	standardTile("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
		state "off", label:'${name}', action:"switchMode"
		state "heat", label:'${name}', action:"switchMode"
		state "emergencyHeat", label:'${name}', action:"switchMode"
		state "cool", label:'${name}', action:"switchMode"
		state "auto", label:'${name}', action:"switchMode"
	}
	standardTile("fanMode", "device.thermostatFanMode", inactiveLabel: false, decoration: "flat") {
		state "fanAuto", label:'${name}', action:"switchFanMode"
		state "fanOn", label:'${name}', action:"switchFanMode"
		state "fanCirculate", label:'${name}', action:"switchFanMode"
	}
	controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
		state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#d04e00"
	}
	valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") {
		state "heat", label:'${currentValue}° heat', unit:"F", backgroundColor:"#ffffff"
	}
	controlTile("coolSliderControl", "device.coolingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
		state "setCoolingSetpoint", action:"thermostat.setCoolingSetpoint", backgroundColor: "#1e9cbb"
	}
	valueTile("coolingSetpoint", "device.coolingSetpoint", inactiveLabel: false, decoration: "flat") {
		state "cool", label:'${currentValue}° cool', unit:"F", backgroundColor:"#ffffff"
	}
	standardTile("refresh", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
		state "default", action:"polling.poll", icon:"st.secondary.refresh"
	}
	standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
		state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
	}
    
	main (["switch4"])
    details(["switch1","switch2","switch3","switch4","switch5","temperature","thermostat","refresh"])
}

}

import physicalgraph.zwave.commands.*

//Parse
def parse(String description)
{
def map = createEvent(zwaveEvent(zwave.parse(description, [0x42:1, 0x43:2, 0x31:3, 0x80:1])))
if (!map) {
return null
}

def result = [map]
if (map.isStateChange && map.name in ["heatingSetpoint","coolingSetpoint","thermostatMode"]) {
	def map2 = [
		name: "thermostatSetpoint",
		unit: "F"
	]
	if (map.name == "thermostatMode") {
		updateState("lastTriedMode", map.value)
		if (map.value == "cool") {
			map2.value = device.latestValue("coolingSetpoint")
			log.info "THERMOSTAT, latest cooling setpoint = ${map2.value}"
		}
		else {
			map2.value = device.latestValue("heatingSetpoint")
			log.info "THERMOSTAT, latest heating setpoint = ${map2.value}"
		}
	}
	else {
		def mode = device.latestValue("thermostatMode")
		log.info "THERMOSTAT, latest mode = ${mode}"
		if ((map.name == "heatingSetpoint" && mode == "heat") || (map.name == "coolingSetpoint" && mode == "cool")) {
			map2.value = map.value
			map2.unit = map.unit
		}
	}
	if (map2.value != null) {
		log.debug "THERMOSTAT, adding setpoint event: $map"
		result << createEvent(map2)
	}
} else if (map.name == "thermostatFanMode" && map.isStateChange) {
	updateState("lastTriedFanMode", map.value)
}
log.debug "ParseEx returned $result"
result

}

//Reports

def zwaveEvent(physicalgraph.zwave.commands.batteryv1.BatteryReport cmd) {
def nowTime = new Date().time
state.lastBatteryGet = nowTime
def map = [ name: “battery”, unit: “%” ]
if (cmd.batteryLevel == 0xFF || cmd.batteryLevel == 0) {
map.value = 1
map.descriptionText = “$device.displayName battery is low!”
} else {
map.value = cmd.batteryLevel
}
map
}

def zwaveEvent(physicalgraph.zwave.commands.sensormultilevelv3.SensorMultilevelReport cmd)
{
log.debug "SensorMultilevelReport ${cmd}"
def map = [:]
switch (cmd.sensorType) {
case 1:
// temperature
map.value = cmd.scaledSensorValue.toString()
map.unit = cmd.scale == 1 ? “F” : "C"
map.name = "temperature"
break;
case 5:
// humidity
map.value = cmd.scaledSensorValue.toInteger().toString()
map.unit = "%"
map.name = "humidity"
break;
}
map
}

def zwaveEvent(physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport cmd)
{
def map = [:]
switch (cmd.operatingState) {
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_IDLE:
map.value = "idle"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_HEATING:
map.value = "heating"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_COOLING:
map.value = "cooling"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_FAN_ONLY:
map.value = "fan only"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_HEAT:
map.value = "pending heat"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_COOL:
map.value = "pending cool"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_VENT_ECONOMIZER:
map.value = "vent economizer"
break
}
map.name = "thermostatOperatingState"
map
}

def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport cmd) {
def map = [:]
switch (cmd.mode) {
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_OFF:
map.value = "off"
break
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_HEAT:
map.value = "heat"
break
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUXILIARY_HEAT:
map.value = "emergencyHeat"
break
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_COOL:
map.value = "cool"
break
case physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeReport.MODE_AUTO:
map.value = "auto"
break
}
map.name = "thermostatMode"
map
}

def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport cmd) {
def map = [:]
switch (cmd.fanMode) {
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_AUTO_LOW:
map.value = "fanAuto"
break
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_LOW:
map.value = "fanOn"
break
case physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeReport.FAN_MODE_CIRCULATION:
map.value = "fanCirculate"
break
}
map.name = "thermostatFanMode"
map.displayed = false
map
}

def zwaveEvent(physicalgraph.zwave.commands.thermostatmodev2.ThermostatModeSupportedReport cmd) {
def supportedModes = ""
if(cmd.off) { supportedModes += "off " }
if(cmd.heat) { supportedModes += "heat " }
if(cmd.auxiliaryemergencyHeat) { supportedModes += "emergencyHeat " }
if(cmd.cool) { supportedModes += "cool " }
if(cmd.auto) { supportedModes += "auto " }

updateState("supportedModes", supportedModes)

}

def zwaveEvent(physicalgraph.zwave.commands.thermostatfanmodev3.ThermostatFanModeSupportedReport cmd) {
def supportedFanModes = ""
if(cmd.auto) { supportedFanModes += "fanAuto " }
if(cmd.low) { supportedFanModes += "fanOn " }
if(cmd.circulation) { supportedFanModes += "fanCirculate " }

updateState("supportedFanModes", supportedFanModes)

}

def updateState(String name, String value) {
state[name] = value
device.updateDataValue(name, value)
}

def zwaveEvent(physicalgraph.zwave.commands.basicv1.BasicReport cmd) {
log.debug “Zwave event received: $cmd”
}

def zwaveEvent(physicalgraph.zwave.Command cmd) {
log.warn “Unexpected zwave command $cmd”
}
def zwaveEvent(sensormultilevelv1.SensorMultilevelReport cmd)
{
def map = [:]
map.value = cmd.scaledSensorValue.toString()
map.unit = cmd.scale == 1 ? “F” : "C"
map.name = "temperature"
map
}

def zwaveEvent(thermostatsetpointv2.ThermostatSetpointReport cmd)
{
def map = [:]
map.value = cmd.scaledValue.toString()
map.unit = cmd.scale == 1 ? “F” : "C"
map.displayed = false
switch (cmd.setpointType) {
case 1:
map.name = "poolSetpoint"
break;
case 7:
map.name = "spaSetpoint"
break;
default:
return [:]
}
// So we can respond with same format
state.size = cmd.size
state.scale = cmd.scale
state.precision = cmd.precision
map
}

def zwaveEvent(multichannelv3.MultiInstanceReport cmd) {
log.debug “$cmd”
}

def zwaveEvent(multichannelv3.MultiChannelCapabilityReport cmd) {
log.debug “$cmd”
}

def zwaveEvent(multichannelv3.MultiChannelEndPointReport cmd) {
log.debug “$cmd”
}

def zwaveEvent(multichannelv3.MultiInstanceCmdEncap cmd) {
log.debug "$cmd"
def map = [ name: “switch$cmd.instance” ]
if (cmd.commandClass == 37){
if (cmd.parameter == [0]) {
map.value = “off”
}
if (cmd.parameter == [255]) {
map.value = “on”
}
}
createEvent(map)
}

def zwaveEvent(multichannelv3.MultiChannelCmdEncap cmd) {
log.debug "$cmd"
def map = [ name: “switch$cmd.destinationEndPoint” ]
if (cmd.commandClass == 37){
if (cmd.parameter == [0]) {
map.value = “off”
}
if (cmd.parameter == [255]) {
map.value = “on”
}
}
createEvent(map)
}

def zwaveEvent(cmd) {
log.warn “Captured zwave command $cmd”
}

//Commands

private getBattery() { //once every 10 hours
def nowTime = new Date().time
def ageInMinutes = state.lastBatteryGet ? (nowTime - state.lastBatteryGet)/60000 : 600
log.debug "Battery report age: ${ageInMinutes} minutes"
if (ageInMinutes >= 600) {
log.debug "Fetching fresh battery value"
zwave.batteryV1.batteryGet().format()
} else “delay 87”
}

private setClock() { //once a day
def nowTime = new Date().time
def ageInMinutes = state.lastClockSet ? (nowTime - state.lastClockSet)/60000 : 1440
log.debug "Clock set age: ${ageInMinutes} minutes"
if (ageInMinutes >= 1440) {
log.debug "Setting clock"
state.lastClockSet = nowTime
def nowCal = Calendar.getInstance(TimeZone.getTimeZone(“America/New_York”));
zwave.clockV1.clockSet(hour: nowCal.get(Calendar.HOUR_OF_DAY), minute: nowCal.get(Calendar.MINUTE), weekday: nowCal.get(Calendar.DAY_OF_WEEK)).format()
} else “delay 87”
}

def setHeatingSetpoint(degreesF) {
setHeatingSetpoint(degreesF.toDouble())
}

def setHeatingSetpoint(Double degreesF) {
def p = (state.precision == null) ? 1 : state.precision
delayBetween([
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 1, scale: 1, precision: p, scaledValue: degreesF).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format()
])
}

def setCoolingSetpoint(degreesF) {
setCoolingSetpoint(degreesF.toDouble())
}

def setCoolingSetpoint(Double degreesF) {
def p = (state.precision == null) ? 1 : state.precision
delayBetween([
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 2, scale: 1, precision: p, scaledValue: degreesF).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 2).format()
])
}

def configure() {
delayBetween([
zwave.thermostatModeV2.thermostatModeSupportedGet().format(),
zwave.thermostatFanModeV3.thermostatFanModeSupportedGet().format(),
zwave.associationV1.associationSet(groupingIdentifier:1, nodeId:[zwaveHubNodeId]).format()
], 2300)
}

def modes() {
[“off”, “auto”, “emergencyHeat”, “heat”, “cool”]
}

def switchMode() {
def currentMode = device.currentState(“thermostatMode”)?.value
def lastTriedMode = getDataByName(“lastTriedMode”) ?: currentMode ?: "off"
def supportedModes = getDataByName(“supportedModes”)
def modeOrder = modes()
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
def nextMode = next(lastTriedMode)
if (supportedModes?.contains(currentMode)) {
while (!supportedModes.contains(nextMode) && nextMode != “off”) {
nextMode = next(nextMode)
}
}
switchToMode(nextMode)
}

def switchToMode(nextMode) {
def supportedModes = getDataByName(“supportedModes”)
if(supportedModes && !supportedModes.contains(nextMode)) log.warn "thermostat mode ‘$nextMode’ is not supported"
if (nextMode in modes()) {
updateState(“lastTriedMode”, nextMode)
return “$nextMode”()
} else {
log.debug(“no mode method ‘$nextMode’”)
}
}

def switchFanMode() {
def currentMode = device.currentState(“thermostatFanMode”)?.value
def lastTriedMode = getDataByName(“lastTriedFanMode”) ?: currentMode ?: "off"
def supportedModes = getDataByName(“supportedFanModes”) ?: "fanAuto fanOn"
def modeOrder = [“fanAuto”, “fanCirculate”, “fanOn”]
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
def nextMode = next(lastTriedMode)
while (!supportedModes?.contains(nextMode) && nextMode != “fanAuto”) {
nextMode = next(nextMode)
}
switchToFanMode(nextMode)
}

def switchToFanMode(nextMode) {
def supportedFanModes = getDataByName(“supportedFanModes”)
if(supportedFanModes && !supportedFanModes.contains(nextMode)) log.warn “thermostat mode ‘$nextMode’ is not supported”

def returnCommand
if (nextMode == "fanAuto") {
	returnCommand = fanAuto()
} else if (nextMode == "fanOn") {
	returnCommand = fanOn()
} else if (nextMode == "fanCirculate") {
	returnCommand = fanCirculate()
} else {
	log.debug("no fan mode '$nextMode'")
}
if(returnCommand) updateState("lastTriedFanMode", nextMode)
returnCommand

}

def getDataByName(String name) {
state[name] ?: device.getDataValue(name)
}

def getModeMap() { [
“off”: 0,
“heat”: 1,
“cool”: 2,
“emergency heat”: 4
]}

def setThermostatMode(String value) {
delayBetween([
zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[value]).format(),
zwave.thermostatModeV2.thermostatModeGet().format()
])
}

def getFanModeMap() { [
“auto”: 0,
“on”: 1,
“circulate”: 6
]}

def setThermostatFanMode(String value) {
delayBetween([
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: fanModeMap[value]).format(),
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
])
}

def heat() {
delayBetween([
zwave.thermostatModeV2.thermostatModeSet(mode: 1).format(),
zwave.thermostatModeV2.thermostatModeGet().format()
])
}

def emergencyHeat() {
delayBetween([
zwave.thermostatModeV2.thermostatModeSet(mode: 4).format(),
zwave.thermostatModeV2.thermostatModeGet().format()
])
}

def cool() {
delayBetween([
zwave.thermostatModeV2.thermostatModeSet(mode: 2).format(),
zwave.thermostatModeV2.thermostatModeGet().format()
])
}

def auto() {
delayBetween([
zwave.thermostatModeV2.thermostatModeSet(mode: 3).format(),
zwave.thermostatModeV2.thermostatModeGet().format()
])
}

def fanOn() {
delayBetween([
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 1).format(),
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
])
}

def fanAuto() {
delayBetween([
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 0).format(),
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
])
}

def fanCirculate() {
delayBetween([
zwave.thermostatFanModeV3.thermostatFanModeSet(fanMode: 6).format(),
zwave.thermostatFanModeV3.thermostatFanModeGet().format()
])
}

def setPoolSetpoint(degreesF) {
setHeatingSetpoint(degreesF.toDouble())
}

def setPoolSetpoint(Double degreesF) {
def p = (state.precision == null) ? 1 : state.precision
delayBetween([
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 1, scale: 1, precision: p, scaledValue: degreesF).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format()
])
}

def setSpaSetpoint(degreesF) {
setSpaSetpoint(degreesF.toDouble())
}

def setSpaSetpoint(Double degreesF) {
def p = (state.precision == null) ? 1 : state.precision
delayBetween([
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 7, scale: 1, precision: p, scaledValue: degreesF).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 7).format()
])
}

def on() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:2).format()
], 2300)
}

def off() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:2).format()
], 2300)
}

//switch instance
def onMulti(value) {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:2).format()
], 2300)
}

def offMulti(value) {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:2).format()
], 2300)
}

//switch1
def on1() {
onMulti(1)
}

def off1() {
offMulti(1)
}

//switch2
def on2() {
onMulti(2)
}

def off2() {
offMulti(2)
}

//switch3
def on3() {
onMulti(3)
}

def off3() {
offMulti(3)
}

//switch4
def on4() {
onMulti(4)
}

def off4() {
offMulti(4)
}

//switch5
def on5() {
onMulti(5)
}

def off5() {
offMulti(5)
}

def poll() {
zwave.sensorMultilevelV1.sensorMultilevelGet().format()
}

def refresh() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:3, destinationEndPoint:3, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:4, destinationEndPoint:4, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:5, destinationEndPoint:5, commandClass:37, command:2).format(),
zwave.sensorMultilevelV1.sensorMultilevelGet().format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 7).format()
], 2500)
}

I would like to think I have no idea what I am doing.

@mbial The actuators are 24v devices. The PE953 does not have a transformer so you do currently need the P5043ME module to convert to the low voltage for the actuators. The last time I talked to an Intermatic rep, they did claim to be working on a unit that would include the transformer but I do not think that exists yet. You can get any cabinet that contains these Intermatic “clock” size modules, but you do need room for wiring and you need a separate channel for low voltage wiring to be up to code.
Hope that helps you out.

@matt_coulter - Thanks for your reply. I ended up going with the Intermatic PE24065RC package which includes the PE653, remote control, 60 amp panel, enclosure, P4043ME Actuator Control, and 2 PE24VE valve actuators for $489 total here. If anyone else is considering getting these products, I’m pretty sure this package is a great value. I’ll let you know once I have everything installed!

@mbial Yes the P4043ME is just an earlier version of the other module I believe. This kit is a good deal which is why we try to install these over Aqualinks anyway. There are single components in the Aqualinks that if you have to replace, cost more than twice of this whole kit.

Ok. I have worked on the device type a bit more to add a slider (the slider does not work) so some help on that would be great.

However, all of this is for not if I cannot determine a way to get the controller to recognize that I have a VSP. While the pump may be on a switch (I presume switch 1). I am sending commands from the PE953 to turn on the pump at various speeds.

This is what I need to replicate.

/**

  • PoolSwitch
  • Copyright 2014 bigpunk6
  • Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except
  • in compliance with the License. You may obtain a copy of the License at:
  •  http://www.apache.org/licenses/LICENSE-2.0
    
  • Unless required by applicable law or agreed to in writing, software distributed under the License is distributed
  • on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License
  • for the specific language governing permissions and limitations under the License.

*/
metadata {
definition (name: “PoolSwitch”, author: “bigpunk6”) {
capability "Actuator"
capability "Switch"
capability "Polling"
capability "Configuration"
capability "Refresh"
capability "Temperature Measurement"
capability "Sensor"
capability “Thermostat”

	attribute "switch1", "string"
	attribute "switch2", "string"
	attribute "switch3", "string"
	attribute "switch4", "string"
	attribute "switch5", "string"

	command "onMulti"
	command "offMulti"
    command "on1"
	command "off1"
    command "on2"
	command "off2"
    command "on3"
	command "off3"
    command "on4"
	command "off4"
    command "on5"
	command "off5"
}

simulator {
	// TODO: define status and reply messages here
}

// tile definitions
tiles {
	
    }
    
    valueTile("temperature", "device.temperature") {
		state("temperature", label:'${currentValue}°', unit:"F",
			backgroundColors:[
				[value: 32, color: "#153591"],
				[value: 54, color: "#1e9cbb"],
				[value: 64, color: "#90d2a7"],
				[value: 74, color: "#44b621"],
				[value: 90, color: "#f1d801"],
				[value: 98, color: "#d04e00"],
				[value: 110, color: "#bc2323"]
			]
    
    )
    
    }
	controlTile("heatSliderControl", "device.heatingSetpoint", "slider", height: 1, width: 2, inactiveLabel: false) {
		state "setHeatingSetpoint", action:"thermostat.setHeatingSetpoint", backgroundColor:"#d04e00"
	}
	valueTile("heatingSetpoint", "device.heatingSetpoint", inactiveLabel: false, decoration: "flat") {
		state "heat", label:'${currentValue}° heat', unit:"F", backgroundColor:"#ffffff"
    
    }
	standardTile("mode", "device.thermostatMode", inactiveLabel: false, decoration: "flat") {
		state "off", label:'${name}', action:"switchMode"
		state "heat", label:'${name}', action:"switchMode"
		state "emergencyHeat", label:'${name}', action:"switchMode"
		state "cool", label:'${name}', action:"switchMode"
		state "auto", label:'${name}', action:"switchMode"
    }
    standardTile("switch1", "device.switch1",canChangeIcon: true) {
		state "on", label: "switch1", action: "off1", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch1", action: "on1", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch2", "device.switch2",canChangeIcon: true) {
		state "on", label: "switch2", action: "off2", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch2", action: "on2", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch3", "device.switch3",canChangeIcon: true) {
		state "on", label: "switch3", action: "off3", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch3", action:"on3", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch4", "device.switch4",canChangeIcon: true) {
		state "on", label: "switch4", action: "off4", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch4", action:"on4", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    standardTile("switch5", "device.switch5",canChangeIcon: true) {
		state "on", label: "switch5", action: "off5", icon: "st.switches.switch.on", backgroundColor: "#79b821"
		state "off", label: "switch5", action:"on5", icon: "st.switches.switch.off", backgroundColor: "#ffffff"
	}
    
    standardTile("refresh", "device.switch", inactiveLabel: false, decoration: "flat") {
		state "default", label:'', action:"refresh.refresh", icon:"st.secondary.refresh"
	}
    
    standardTile("configure", "device.configure", inactiveLabel: false, decoration: "flat") {
		state "configure", label:'', action:"configuration.configure", icon:"st.secondary.configure"
	

	}
    
	main(["temperature","heatSliderControl","switch1","switch2","switch3","switch4","switch5"])
    details(["temperature","heatSliderControl","switch1","switch2","switch3","switch4","switch5","refresh"])
}

import physicalgraph.zwave.commands.*

//Parse

def parse(String description)
{
def map = createEvent(zwaveEvent(zwave.parse(description, [0x20: 1, 0x70: 2, 0x86: 1, 0x60:3, 0x31:1, 0x25:1, 0x81:1])))
if (!map) {
return null
}

def result = [map]
if (map.isStateChange && map.name in ["heatingSetpoint","coolingSetpoint","thermostatMode"]) {
	def map2 = [
		name: "thermostatSetpoint",
		unit: "F"
	]
	if (map.name == "thermostatMode") {
		updateState("lastTriedMode", map.value)
		if (map.value == "cool") {
			map2.value = device.latestValue("coolingSetpoint")
			log.info "THERMOSTAT, latest cooling setpoint = ${map2.value}"
		}
		else {
			map2.value = device.latestValue("heatingSetpoint")
			log.info "THERMOSTAT, latest heating setpoint = ${map2.value}"
		}
	}
	else {
		def mode = device.latestValue("thermostatMode")
		log.info "THERMOSTAT, latest mode = ${mode}"
		if ((map.name == "heatingSetpoint" && mode == "heat") || (map.name == "coolingSetpoint" && mode == "cool")) {
			map2.value = map.value
			map2.unit = map.unit
		}
	}
	if (map2.value != null) {
		log.debug "THERMOSTAT, adding setpoint event: $map"
		result << createEvent(map2)
	}
} else if (map.name == "thermostatFanMode" && map.isStateChange) {
	updateState("lastTriedFanMode", map.value)
}
log.debug "ParseEx returned $result"
result

}

//Reports
def zwaveEvent(sensormultilevelv1.SensorMultilevelReport cmd)
{
def map = [:]
map.value = cmd.scaledSensorValue.toString()
map.unit = cmd.scale == 1 ? “F” : "C"
map.name = "temperature"
map
}

def zwaveEvent(thermostatsetpointv2.ThermostatSetpointReport cmd)
{
def map = [:]
map.value = cmd.scaledValue.toString()
map.unit = cmd.scale == 1 ? “F” : "C"
map.displayed = false
switch (cmd.setpointType) {
case 1:
map.name = "poolSetpoint"
break;
case 7:
map.name = "spaSetpoint"
break;
default:
return [:]
}
// So we can respond with same format
state.size = cmd.size
state.scale = cmd.scale
state.precision = cmd.precision
map
}

def zwaveEvent(multichannelv3.MultiInstanceReport cmd) {
log.debug “$cmd”
}

def zwaveEvent(multichannelv3.MultiChannelCapabilityReport cmd) {
log.debug “$cmd”
}

def zwaveEvent(multichannelv3.MultiChannelEndPointReport cmd) {
log.debug “$cmd”
}

def zwaveEvent(multichannelv3.MultiInstanceCmdEncap cmd) {
log.debug "$cmd"
def map = [ name: “switch$cmd.instance” ]
if (cmd.commandClass == 37){
if (cmd.parameter == [0]) {
map.value = “off”
}
if (cmd.parameter == [255]) {
map.value = “on”
}
}
createEvent(map)
}

def zwaveEvent(multichannelv3.MultiChannelCmdEncap cmd) {
log.debug "$cmd"
def map = [ name: “switch$cmd.destinationEndPoint” ]
if (cmd.commandClass == 37){
if (cmd.parameter == [0]) {
map.value = “off”
}
if (cmd.parameter == [255]) {
map.value = “on”
}
}
createEvent(map)
}

def zwaveEvent(cmd) {
log.warn “Captured zwave command $cmd”
}

def zwaveEvent(physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport cmd)
{
def map = [:]
switch (cmd.operatingState) {
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_IDLE:
map.value = "idle"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_HEATING:
map.value = "heating"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_COOLING:
map.value = "cooling"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_FAN_ONLY:
map.value = "fan only"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_HEAT:
map.value = "pending heat"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_PENDING_COOL:
map.value = "pending cool"
break
case physicalgraph.zwave.commands.thermostatoperatingstatev1.ThermostatOperatingStateReport.OPERATING_STATE_VENT_ECONOMIZER:
map.value = "vent economizer"
break
}
map.name = "thermostatOperatingState"
map
}

//Commands

def setThermostatMode(String value) {
delayBetween([
zwave.thermostatModeV2.thermostatModeSet(mode: modeMap[value]).format(),
zwave.thermostatModeV2.thermostatModeGet().format()
])
}

def modes() {
[“off”, “auto”, “emergencyHeat”, “heat”, “cool”]
}

def switchMode() {
def currentMode = device.currentState(“thermostatMode”)?.value
def lastTriedMode = getDataByName(“lastTriedMode”) ?: currentMode ?: "off"
def supportedModes = getDataByName(“supportedModes”)
def modeOrder = modes()
def next = { modeOrder[modeOrder.indexOf(it) + 1] ?: modeOrder[0] }
def nextMode = next(lastTriedMode)
if (supportedModes?.contains(currentMode)) {
while (!supportedModes.contains(nextMode) && nextMode != “off”) {
nextMode = next(nextMode)
}
}
switchToMode(nextMode)
}

def switchToMode(nextMode) {
def supportedModes = getDataByName(“supportedModes”)
if(supportedModes && !supportedModes.contains(nextMode)) log.warn "thermostat mode ‘$nextMode’ is not supported"
if (nextMode in modes()) {
updateState(“lastTriedMode”, nextMode)
return “$nextMode”()
} else {
log.debug(“no mode method ‘$nextMode’”)
}
}

def setPoolSetpoint(degreesF) {
setheatSlidercontrol(degreesF.toDouble())
}

def setPoolSetpoint(Double degreesF) {
def p = (state.precision == null) ? 1 : state.precision
delayBetween([
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 1, scale: 1, precision: p, scaledValue: degreesF).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format()
])
}

def setSpaSetpoint(degreesF) {
setSpaSetpoint(degreesF.toDouble())
}

def setSpaSetpoint(Double degreesF) {
def p = (state.precision == null) ? 1 : state.precision
delayBetween([
zwave.thermostatSetpointV1.thermostatSetpointSet(setpointType: 7, scale: 1, precision: p, scaledValue: degreesF).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 7).format()
])
}

def on() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:2).format()
], 2300)
}

def off() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: 1, destinationEndPoint: 1, commandClass:37, command:2).format()
], 2300)
}

//switch instance
def onMulti(value) {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:1, parameter:[255]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:2).format()
], 2300)
}

def offMulti(value) {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:1, parameter:[0]).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint: value, destinationEndPoint: value, commandClass:37, command:2).format()
], 2300)
}

//switch1
def on1() {
onMulti(1)
}

def off1() {
offMulti(1)
}

//switch2
def on2() {
onMulti(2)
}

def off2() {
offMulti(2)
}

//switch3
def on3() {
onMulti(3)
}

def off3() {
offMulti(3)
}

//switch4
def on4() {
onMulti(4)
}

def off4() {
offMulti(4)
}

//switch5
def on5() {
onMulti(5)
}

def off5() {
offMulti(5)
}

def poll() {
zwave.sensorMultilevelV1.sensorMultilevelGet().format()
}

def refresh() {
delayBetween([
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:1, destinationEndPoint:1, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:2, destinationEndPoint:2, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:3, destinationEndPoint:3, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:4, destinationEndPoint:4, commandClass:37, command:2).format(),
zwave.multiChannelV3.multiChannelCmdEncap(sourceEndPoint:5, destinationEndPoint:5, commandClass:37, command:2).format(),
zwave.sensorMultilevelV1.sensorMultilevelGet().format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 1).format(),
zwave.thermostatSetpointV1.thermostatSetpointGet(setpointType: 7).format()
], 2500)
}

My new Intermatic pool equipment arrived today…hopefully I’ll have some time to get it all set up and I can be of more help.

Looking forward to what you come up with!

OK - Installing the Intermatic equipment today. I’ll keep you posted.

Hey @mbial, having any luck with your installation?

I would like to know as well. A nice person named @cooperglee is attempting to help with some more device functionality such as thermostat control and pump control.

I will get the interface cleaned up a bit - but for me to do some “real” work and make it really nice - with an install and everything - I will need the device - is their a consortium of people willing to buy a “kit” and send it to me… ?? Otherwise I should have a “quick” cleanup in about 48 hours - it would really be better to do “the whole thing” I have just finished up an integration for Rachio which is AWESOME!! and working now to complete one for FlowerPower and also Automatic

Based on the Intermatic documentation it appears that for a “good” ST integration there will really need to be some user input required prior to selecting the ST device-type which is most appropriate for each users’ installation.

• (Switch 1 - “Pump - On”) 1- Speed Pump: Must be powered from Terminal 3.
• (Switch 2 - “Pump - Low Speed / Blower / Lights”) 2-Speed Pump: Must be powered from Terminal 3 for High-Speed and Terminal 4 for Low-Speed. - This switch is also commonly used for the Blower (for Spa) when using a single speed pump
• (Switch 3 - “Booster Pump / Blower / Lights”) Booster Pump: Must be powered from Terminal 6.
• (Switch 4 - "Blower / Actuator / Lights ") Actuator Control: Must be powered from Terminal 7 (used for pool/spa button).
• (Switch 5 - “Heater On”) Heater Control: Must be Terminals 8 & 9.

• Water Sensor (PA122) (for both pool and spa depending on switch position)
• Air Sensor (178PA28A)
• Solar Sensor (PA122)

User can also have a variable speed pump - this is connected via a separate control and Intermatic allows for 4 pre-configured speeds (more on this later)

Additional Configurations - Other accessories for systems that do not have a pool and spa…

Z wave features:
Calibrate temperature offset (pool/air)
Configure Freeze Temperature
Configure The 4 Variable Speed Settings for VS Pumps

From the overview it would seem that “some” user input would be required to setup the appropriate ST device type - and likely more than one device-type seems appropriate at this point (pool, pool/spa, variable speed pump, etc.)… That being said (and from information gleaned from the documentation and users’ input) it seems the likely “high end” configuration (and the first one I am going to write) is:

• 3 different temperature gauges (outside, pool, and spa) NOTE: Only one temperature from Pool/Spa can be measured at a time as there is only one sensor - type depends on position of diverter valve (switch 4) and the pump running
• illuminance or sun up/down depending on what the Intermatic sends based on the light sensor (will be an option to use local sunrise/set or other illuminance or switch and “on for” duration from smartApp)
• emergency temp to prevent freezing - regardless of diverter valve position - is based on air temperature
• Hearting set point for both pool and spa - this again will be dependent on the diverter valve position (time of day programming with have to be from a smartApp or user preferences and will require switching of the diverter valve - it will also require a timing / switching feature if both POOL and SPA temperatures are desired simultaneously which will only work if the SPA is not in use (blower not on))
• light or lights - if not used for blower (or in conduction with - spa) or if a 2 speed pump is not used (switch 2) or (switch 4) if blower is not used

Other iterations of the device type will vary - I think that a “base” pool ONLY device type will have:
• Air and Pool Temp
• Pump on/off (Switch 1)
• Lights - user selectable for switches 2-4
• Other switch(es) names to be user configurable through “Preferences”
• Heater on/off (Switch 5) assuming that most people will have a heater and not some other accessory.

All versions above to work with a new SmartApp that will allow various programmable features and an option (boolean toggle) for each of the 5 switches to create a “Virtual Switch Device-Type” which will create the ST “Thing” Switch with a user configurable name that can then be turned on/off by any other ST application like a regular switch.

Please provide any feedback as I would like to “crank out” both the high-level app and the “high-end” device-type over the weekend.

Since I do not have one of these (community please contribute one for testing and development) I will need some volunteers for testing - which will be a different version of the app/device-types to collect debug information - or invite me as a user (add me as a presence user) to your ST location and I can do remote testing/development (you can kick me out later through account management)

1 Like