Is anyone willing to take a crack at getting support for Pentair’s ScreenLogic automation protocol? This is a system for Pool automation.
it’s not really needed although a plugin would be nice for quick out of the box operation…
- buy this … it installs as a pentair remote … i installed mine in the outdoor control box inside the high-voltage section it is powered from the pentair 4wire interface … need to run an ethernet cable
Pool Control for Pentair Intellitouch & Easytouch
PC100PI wired version for Pentair Intellitouch & Easytouch systems.
More Info…
$249.99
-
add these switches for each controllable device (on/off) status devices can be handled differently below
switch:- platform: command_line
switches:
pool_pump:
command_on: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit6&value=1”’
command_off: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit6&value=0”’
command_state: ‘curl --user admin:admin -X GET “192.168.1.253/status.xml” | xmllint --xpath “//response/equipment/circuit6/text()” -’
value_template: ‘{{ value == “1” }}’
friendly_name: Pool
spa_pump:
command_on: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit1&value=1”’
command_off: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit1&value=0”’
command_state: ‘curl --user admin:admin -X GET “192.168.1.253/status.xml” | xmllint --xpath “//response/equipment/circuit1/text()” -’
value_template: ‘{{ value == “1” }}’
friendly_name: Spa
spa_air_blower:
command_on: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit3&value=1”’
command_off: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit3&value=0”’
command_state: ‘curl --user admin:admin -X GET “192.168.1.253/status.xml” | xmllint --xpath “//response/equipment/circuit3/text()” -’
value_template: ‘{{ value == “1” }}’
friendly_name: Spa Air Blower
spa_booster_pump:
command_on: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit2&value=1”’
command_off: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit2&value=0”’
command_state: ‘curl --user admin:admin -X GET “192.168.1.253/status.xml” | xmllint --xpath “//response/equipment/circuit2/text()” -’
value_template: ‘{{ value == “1” }}’
friendly_name: Spa Booster Pump
spa_light:
command_on: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit8&value=1”’
command_off: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit8&value=0”’
command_state: ‘curl --user admin:admin -X GET “192.168.1.253/status.xml” | xmllint --xpath “//response/equipment/circuit8/text()” -’
value_template: ‘{{ value == “1” }}’
friendly_name: Spa Light
pool_lights:
command_on: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit4&value=1”’
command_off: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit4&value=0”’
command_state: ‘curl --user admin:admin -X GET “192.168.1.253/status.xml” | xmllint --xpath “//response/equipment/circuit4/text()” -’
value_template: ‘{{ value == “1” }}’
friendly_name: Pool Lights
pool_waterfall:
command_on: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit5&value=1”’
command_off: ‘curl -X GET --user admin:admin “192.168.1.253/set.cgi?name=circuit5&value=0”’
command_state: ‘curl --user admin:admin -X GET “192.168.1.253/status.xml” | xmllint --xpath “//response/equipment/circuit5/text()” -’
value_template: ‘{{ value == “1” }}’
friendly_name: Pool Waterfall
- platform: command_line
-
for status devices …
Pool Controller
- platform: command_line
name: Pool Temp
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{{ value_json["response"]["temp"]["pooltemp"] }}'
unit_of_measurement: "°F"
- platform: command_line
name: Time
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{{ strptime(value_json["response"]["system"]["time"], "%Y-%m-%d") }}'
- platform: command_line
name: Spa Temp
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{{ value_json["response"]["temp"]["spatemp"] }}'
unit_of_measurement: "°F"
- platform: command_line
name: Air Temp
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{{ value_json["response"]["temp"]["airtemp"] }}'
unit_of_measurement: "°F"
- platform: command_line
name: Model
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if value_json["response"]["system"]["model"] == "2" %} Screenlogic i9+3 {% else %} Error {% endif %}'
- platform: command_line
name: AUTELIS
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if value_json["response"]["system"]["runstate"] == "50" %} Ready {% elif value_json["response"]["system"]["runstate"] == "1"%}Starting up{% else %}Getting D$
- platform: command_line
name: Pentair
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if value_json["response"]["system"]["opmode"] == "0" %}Auto{% else %} Service|Timeout {% endif %}'
- platform: command_line
name: Freeze Protect
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if value_json["response"]["system"]["freeze"] == "0" %} OFF {% else %} ON {% endif %}'
- platform: command_line
name: Water Sensor
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if value_json["response"]["system"]["sensor1"] == "0" %} OK {% else %} Error {% endif %}'
- platform: command_line
name: Air Sensor
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if value_json["response"]["system"]["sensor3"] == "0" %} OK {% else %} Error {% endif %}'
- platform: command_line
name: Spa Heater
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if (value_json["response"]["temp"]["htstatus"] | float ) == 2 %} Heating {% else %} OFF {% endif %}'
- platform: command_line
name: Pool Heater
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if (value_json["response"]["temp"]["htstatus"] | float ) == 1 %} Heating {% else %} OFF {% endif %}'
- platform: command_line
name: Pump Status
command: '/home/homeassistant/.homeassistant/bin/pumps.py'
- platform: command_line
name: Floor Cleaner
command: '/home/homeassistant/.homeassistant/bin/poolcontroller.py'
value_template: '{% if value_json["response"]["equipment"]["feature1"] == "0" %} OFF {% else %} ON {% endif %}'
- poolcontroller.py
#!/usr/bin/python
from requests import get
import json
import xmltodict
circuit1 = “SPA”
circuit2 = “BOOSTERPUMP”
circuit3 = “AIR BLOWER”
circuit4 = “POOL LIGHT”
circuit5 = “WATERFALL”
circuit6 = “POOL”
circuit8 = “SPA LIGHT”
feature1 = “FLOOR CLEANER”
url = “http://admin:[email protected]/status.xml”
http = get(url)
json = json.dumps(xmltodict.parse(http.content), indent=4)
print json
- to get pump status
#!/srv/homeassistant/bin/python3
from requests import get
import json
import untangle
import xmltodict
circuit1 = “SPA”
circuit2 = “BOOSTERPUMP”
circuit3 = “AIR BLOWER”
circuit4 = “POOL LIGHT”
circuit5 = “WATERFALL”
circuit6 = “POOL”
circuit8 = “SPA LIGHT”
feature1 = “FLOOR CLEANER”
url = “http://admin:[email protected]/status.xml”
url2 = “http://admin:[email protected]/pumps.xml”
http_status = get(url)
http_pumps = get(url2)
status = untangle.parse(http_status.text)
pumps = untangle.parse(http_pumps.text)
vsp_pool_status = status.response.equipment.circuit6.cdata
vsp_spa_status = status.response.equipment.circuit1.cdata
if vsp_pool_status == ‘0’ and vsp_spa_status == ‘0’:
print(“Pump OFF”)
else :
vsp = pumps.response.pumps.pump1.cdata
vsp = vsp.split(’,’,3)
power = vsp[0]
rpm = vsp[1]
print (power, “Watts”, rpm, “RPM”)
Thanks for this info Dan, but it looks like all of the products are out of stock…maybe they folded??
I own a Pentair ScreenLogic2 > https://www.amazon.com/Pentair-522104-Screenlogic2-Interface-Connection/dp/B00N4SXR64
It looks like your solution relies upon Autelis equipment. Does anyone have the skills to create a ScreenLogic component for HA?
Screen logic is not the protocol and just a pentair product to give you a remove control panel. It connects to the 4 wire RS485 bus that the pentair easytouch and intellitouch systems. For the same money you can get an Autelis which does the same but has an Ethernet port and runs a simple web front end you can use. Or you can use their API to add support into your automation system.
We’ve made progress on the Screenlogic front!
Here’s an early prototype to check out. We’re looking for testors and anyone willing to to help.
Great Add-on @pgregg88! I have it running and it works perfectly. Do you know how to control the pool and spa lights too?
although i’m using Autelis interface adapter and it works well … after reading the above post, i though i would implement this node based system … my solution is slightly different and doesn’t rely on MQTT
-
after installing node … install npm node-screenlogic
-
in the node_modules/node-screenlogic i have the follow code to produce a status JSON message when called (PentairStatus.js) … note i’m using the local interface to screenlogic so you will need to change the IP … i don’t see any reason to use remote access
-
you will then need to add the follow const for your system in node_modules/node-screenlogic/messages/SLPoolStatusMessage.js … my system doesn’t have a pentair chem/salt (based on PoolPilot) … to get a list of circuit IDs write a test.js program and print out this array … keep indexing until it’s undefined to get all your circuits enumerated … you will then need to add functions for each circuit as the default only provider for pool on/off and spa on/off … this functions are located in the same SLPoolStatusMessage.js program
-
you will next need to make a *ON.js and *OFF.js function for each circuit you wish to control via HA, e.g. POOLLIGHTON.js … chmod +x for each js program
-
than add the following package yaml file …
-
i know this message is messy … i will post my config on github this weekend …
package: pool and spa control using node driver (npm node-screenlogic)
SCCS: @(#) 1.2 03/07/19
homeassistant:
customize:Pool
sensor.node_freeze_protect: icon: mdi:snowflake sensor.node_heater_mode: icon: mdi:fire device_class: heat sensor.node_heater_status: icon: mdi:fire device_class: heat switch.node_pool: icon: mdi:swim device_class: power switch.node_spa: icon: mdi:hot-tub device_class: power switch.node_pool_waterfall: icon: mdi:fountain device_class: power switch.node_spa_booster_pump: icon: mdi:water-pump device_class: power switch.node_spa_light: icon: mdi:lightbulb-outline device_class: light switch.node_pool_lights: icon: mdi:lightbulb-outline device_class: light switch.node_spa_air_blower: icon: mdi:weather-windy device_class: power sensor.node_pentair_version: icon: mdi:database
switch to control pool features
switch:
- platform: command_line
switches:
node_pool:
command_on: ‘/home/dan/node_modules/node-screenlogic/POOLON.js’
command_off: ‘/home/dan/node_modules/node-screenlogic/POOLOFF.js’
command_state: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“PoolActive”] == “true” }}’
friendly_name: Pool
node_spa:
command_on: ‘/home/dan/node_modules/node-screenlogic/SPAON.js’
command_off: ‘/home/dan/node_modules/node-screenlogic/SPAOFF.js’
command_state: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“SPAActive”] == “true” }}’
friendly_name: Spa
node_spa_air_blower:
command_on: ‘/home/dan/node_modules/node-screenlogic/AIRBLOWERON.js’
command_off: ‘/home/dan/node_modules/node-screenlogic/AIRBLOWEROFF.js’
command_state: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“SPAAirBlowerActive”] == “true” }}’
friendly_name: Spa Air Blower
node_spa_booster_pump:
command_on: ‘/home/dan/node_modules/node-screenlogic/BOOSTERPUMPON.js’
command_off: ‘/home/dan/node_modules/node-screenlogic/BOOSTERPUMPOFF.js’
command_state: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“SPABoosterPumpActive”] == “true” }}’
friendly_name: Spa Booster Pump
node_spa_light:
command_on: ‘/home/dan/node_modules/node-screenlogic/SPALIGHTON.js’
command_off: ‘/home/dan/node_modules/node-screenlogic/SPALIGHTOFF.js’
command_state: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“SPALightON”] == “true” }}’
friendly_name: Spa Light
node_pool_lights:
command_on: ‘/home/dan/node_modules/node-screenlogic/POOLLIGHTON.js’
command_off: ‘/home/dan/node_modules/node-screenlogic/POOLLIGHTOFF.js’
command_state: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“PoolLightON”] == “true” }}’
friendly_name: Pool Lights
node_pool_waterfall:
command_on: ‘/home/dan/node_modules/node-screenlogic/WATERFALLON.js’
command_off: ‘/home/dan/node_modules/node-screenlogic/WATERFALLOFF.js’
command_state: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“WaterfallActive”] == “true” }}’
friendly_name: Pool Waterfall
Pool Controller via node Pentair.js
sensor:
- platform: command_line
name: Node Pool Temp
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“PoolTemp”] }}’
unit_of_measurement: “°F” - platform: command_line
name: Node Spa Temp
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“SPATemp”] }}’
unit_of_measurement: “°F” - platform: command_line
name: Node Air Temp
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“AirTemp”] }}’
unit_of_measurement: “°F” - platform: command_line
name: Node Pentair Version
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“Version”].split(":")[1] }}’ - platform: command_line
name: Node Freeze Protect
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{% if value_json[“FreezeModeActive”] == 0 %} OFF {% else %} ON {% endif %}’ - platform: command_line
name: Node Pool Mode
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: >
{% if value_json[“PoolMode”] == 1 %}
{{ “Normal” }}
{% elif value_json[“PoolMode”] == 0 %}
{{ “SYNC” }}
{% elif value_json[“PoolMode”] == 2 %}
{{ “Timeout” }}
{% elif value_json[“PoolMode”] == 3 %}
{{ “Service” }}
{% else %}
{{ “UNKNOWN” }}
{% endif %} - platform: command_line
name: Node Heater Mode
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“HeaterStatus”] }}’ - platform: command_line
name: Node Heater Status
command: ‘/home/dan/node_modules/node-screenlogic/PentairStatus.js’
value_template: ‘{{ value_json[“HeaterStatus”] }}’
#!/usr/bin/node
‘use strict’;
const ScreenLogic = require(’./index’);
const POOL_LIGHT_CIRCUIT_ID = 503;connect(new ScreenLogic.UnitConnection(80, ‘192.168.1.59’));
function connect(client) {
client.on(‘loggedIn’, function() {
this.setCircuitState(0, POOL_LIGHT_CIRCUIT_ID, 1);
client.close();
});
client.connect();
}
- platform: command_line
…
this.getControllerConfig();
console.log(‘bodyArray[0] =’, config.bodyArray[0]);
console.log(‘bodyArray[1] =’, config.bodyArray[1]);
console.log(‘bodyArray[2] =’, config.bodyArray[2]);
console.log(‘bodyArray[3] =’, config.bodyArray[3]);
console.log(‘bodyArray[4] =’, config.bodyArray[4]);
console.log(‘bodyArray[5] =’, config.bodyArray[5]);
console.log(‘bodyArray[6] =’, config.bodyArray[6]);
console.log(‘bodyArray[7] =’, config.bodyArray[7]);
const SPA_CIRCUIT_ID = 500;
const POOL_CIRCUIT_ID = 505;
const WATERFALL_CIRCUIT_ID = 504;
const SPA_BOOSTER_PUMP_CIRCUIT_ID = 501;
const SPA_AIR_BLOWER_CIRCUIT_ID = 502;
const SPA_LIGHT_CIRCUIT_ID = 507;
const POOL_LIGHT_CIRCUIT_ID = 503;
const POOL_FLOOR_CLEANER_CIRCUIT_ID = 540;
const INTELLIBRITE_CIRCUIT_ID = 12504;
#!/usr/bin/node
# PentairStatus.js
'use strict';
const ScreenLogic = require('./index');
var PentairData = {};
var HeaterMode;
var HeaterStatus;
connect(new ScreenLogic.UnitConnection(80, '192.168.1.59'));
// generic connection method used by all above examples
function connect(client) {
client.on('loggedIn', function() {
this.getVersion();
}).on('version', function(version) {
this.getPoolStatus();
PentairData['Version'] = version.version;
}).on('poolStatus', function(status) {
PentairData['PoolMode'] = status.ok;
PentairData['PoolTemp'] = status.currentTemp[0];
PentairData['SPATemp'] = status.currentTemp[1];
PentairData['AirTemp'] = status.airTemp;
if (status.isSpaActive()) {
PentairData['SPAActive'] = "true"
}
else {
PentairData['SPAActive'] = "false"
}
if (status.isPoolActive()) {
PentairData['Poolctive'] = "true"
}
else {
PentairData['PoolActive'] = "false"
}
if (status.isFloorCleanerActive()) {
PentairData['FloorCleanerActive'] = "true"
}
else {
PentairData['FloorCleanerActive'] = "false"
}
if (status.isWaterFallActive()) {
PentairData['WaterfallActive'] = "true"
}
else {
PentairData['WaterfallActive'] = "false"
}
if (status.isSPAAirBlowerActive()) {
PentairData['SPAAirBlowerActive'] = "true"
}
else {
PentairData['SPAAirBlowerActive'] = "false"
}
if (status.isSPALightActive()) {
PentairData['SPALightON'] = "true"
}
else {
PentairData['SPALightON'] = "false"
}
if (status.isPoolLightActive()) {
PentairData['PoolLightON'] = "true"
}
else {
PentairData['PoolLightON'] = "false"
}
PentairData['FreezeModeActive'] = status.freezeMode;
if ((status.heatStatus[0] == "1") || (status.heatStatus[1] == "1")) {
HeaterStatus = "ON";
}
else {
HeaterStatus = "OFF";
}
PentairData['HeaterStatus'] = HeaterStatus;
if ((status.heatMode[0] == "0") && (status.heatMode[1] == "0")) {
HeaterMode = "OFF";
}
else if ( status.heatMode[0] == "1") {
HeaterMode = "POOL";
}
else if ( status.heatMode[1] == "1") {
HeaterMode = "SPA";
}
else {
HeaterMode = "UNKNOWN";
}
PentairData['HeaterMode'] = HeaterMode;
console.log(JSON.stringify(PentairData));
client.close();
})
client.connect();
}
@danmarotta5 I am a newbie to all of this but I have been studing what you did with this pentair js and want to emulate. I jave a nodejs script printing my pool info in JSON very close to how you have done and I have studied your command line sensors and switches and understand and will emulate.
What I dont know how to do it get node js and npm running on my RPI4 running hassio. Your step 1 above. Can you elborate? I see other use a docker filew but not sure what is best here. When they say ssh into hassio and clone to addons folder when I ssh into hassio io ls and dir dooesnt work.
Can you advise how to get nodejs and npm running for this on hassio?
i’ve done some searching and i don’t see any indications how to install node/npm under hassio. one wacky way to accomplish this is to get a dedicated pi with stock debian OS, install npm and node, MQTT, get pool functions working … then send out MQTT messages to your hassio system or send remote commands to your dedicated pi to turn on/off function and get status information
OK thanks dan, if I cant figure out this dockerfile then that is what I will do (MQTT from a seperate PI). the Autelis not an option anymore.
Since this topic has been dead for a while I decided to learn from everyone else’s work and create a full addon. You can fine it here: https://github.com/bwoodworth/hassio-addons/tree/master/pentair-screenlogic
It is configurable through the addon page and allows control over every circuit in the controller.
All: if you are not using HASSIO and want to use Brian Woodworth’s amazing work I decoupled it. Here is my walk through on the process: