Compare commits
11 Commits
Author | SHA1 | Date | |
---|---|---|---|
03022f9220
|
|||
8329bb22d7
|
|||
2d382dda65
|
|||
1f83be8e10
|
|||
e1c775b8a8
|
|||
562a9993aa | |||
973f01ae37 | |||
9e11d830d6 | |||
b8cf9a1801 | |||
a25b0ff3b2 | |||
7907430e95 |
51
README.md
51
README.md
@ -91,6 +91,15 @@ finder.on('serverFound', function(server) {
|
||||
})
|
||||
```
|
||||
|
||||
### constructor(port, address)
|
||||
|
||||
Port is an integer. Address is an IPv4 address of the server as a string.
|
||||
|
||||
Examples:
|
||||
```javascript
|
||||
var client = new ScreenLogic.UnitConnection(80, '10.0.0.85')
|
||||
```
|
||||
|
||||
### connect()
|
||||
|
||||
Connects to the server passed to its constructor.
|
||||
@ -125,14 +134,19 @@ Requests salt cell status/configuration from the connected unit (requires an Int
|
||||
|
||||
Requests controller configuration from the connected unit. Emits the `controllerConfig` event when the response comes back.
|
||||
|
||||
### setCircuitState(controllerId, circuitId, circuitState)
|
||||
|
||||
Activates or deactivates a circuit. See [`SLSetCircuitStateMessage`](#slsetcircuitstatemessage) documentation for argument values. Emits the `circuitStateChanged` event when response is acknowledged.
|
||||
|
||||
### Events
|
||||
|
||||
* `loggedIn`
|
||||
* `loggedIn` - Indicates that a connection to the server has been established and the login process completed. `get` methods can be called once this event has been emitted.
|
||||
* `version` - Indicates that a response to `getVersion()` has been received. Event handler receives a [`SLVersionMessage`](#slversionmessage) object.
|
||||
* `poolStatus` - Indicates that a response to `getPoolStatus()` has been received. Event handler receives a [`SLPoolStatusMessage`](#slpoolstatusmessage) object.
|
||||
* `chemicalData` - Indicates that a response to `getChemicalData()` has been received. Event handler receives a [`SLChemDataMessage`](#slchemdatamessage) object.
|
||||
* `saltCellConfig` - Indicates that a response to `getSaltCellConfig()` has been received. Event handler receives a [`SLSaltCellConfigMessage`](#slsaltcellconfigmessage) object.
|
||||
* `controllerConfig` - Indicates that a response to `getControllerConfig()` has been received. Event handler receives a [`SLControllerConfigMessage`](#slcontrollerconfigmessage) object.
|
||||
* `circuitStateChanged` - Indicates that a response to `setCircuitState()` has been received. Event handler receives a [`SLSetCircuitStateMessage`](#slsetcircuitstatemessage) object.
|
||||
|
||||
### Properties
|
||||
|
||||
@ -184,11 +198,11 @@ Returns a bool indicating whether the pool is currently active or not.
|
||||
* `spaDelay` - byte
|
||||
* `cleanerDelay` - byte
|
||||
* `airTemp` - integer representing the current temperature (check controller config to see if it's in celsius or fahrenheit)
|
||||
* `currentTemp` - array of size 0-2 indicating current temperature of each body as an integer (spa/pool) (check controller config to see if it's in celsius or fahrenheit)
|
||||
* `heatStatus` - array of size 0-2 indicating whether heat is active or not for each body as an integer (spa/pool)
|
||||
* `setPoint` - array of size 0-2 holding the heating set point for each body as an integer (spa/pool) (check controller config to see if it's in celsius or fahrenheit)
|
||||
* `coolSetPoint` - array of size 0-2 holding the cooling set point for each body as an integer (spa/pool) (check controller config to see if it's in celsius or fahrenheit)
|
||||
* `heatMode` - array of size 0-2 indicating whether heating is enabled or not for each body as an integer (spa/pool)
|
||||
* `currentTemp` - array of size 0-2 indicating current temperature of each body as an integer (pool: 0, spa: 1) (check controller config to see if it's in celsius or fahrenheit)
|
||||
* `heatStatus` - array of size 0-2 indicating whether heat is active or not for each body as an integer (pool: 0, spa: 1)
|
||||
* `setPoint` - array of size 0-2 holding the heating set point for each body as an integer (pool: 0, spa: 1) (check controller config to see if it's in celsius or fahrenheit)
|
||||
* `coolSetPoint` - array of size 0-2 holding the cooling set point for each body as an integer (pool: 0, spa: 1) (check controller config to see if it's in celsius or fahrenheit)
|
||||
* `heatMode` - array of size 0-2 indicating whether heating is enabled or not for each body as an integer (pool: 0, spa: 1)
|
||||
* `circuitArray` - array holding all circuits in the system
|
||||
* `id` - integer representing the circuit's ID (spa is 500, pool is 505)
|
||||
* `state` - integer indicating whether the circuit is on or not (0/1)
|
||||
@ -248,8 +262,8 @@ Passed as an argument to the emitted `controllerConfig` event handler.
|
||||
### Properties
|
||||
|
||||
* `controllerId` - integer indicating the controller's ID
|
||||
* `minSetPoint` - array (size 2) indicating the minimum setpoint available for the pool or spa
|
||||
* `maxSetPoint` - array (size 2) indicating the maximum setpoint available for the pool or spa
|
||||
* `minSetPoint` - array (size 2) indicating the minimum setpoint available for the pool (index 0) or spa (index 1)
|
||||
* `maxSetPoint` - array (size 2) indicating the maximum setpoint available for the pool (index 0) or spa (index 1)
|
||||
* `degC` - boolean indicating whether the system is using the centigrade scale for temperatures or not
|
||||
* `controllerType` - byte
|
||||
* `hwType` - byte
|
||||
@ -274,3 +288,24 @@ Passed as an argument to the emitted `controllerConfig` event handler.
|
||||
* `pumpCircArray` - array (size 8) holding data about pumps attached to the system
|
||||
* `interfaceTabFlags` - integer
|
||||
* `showAlarms` - integer
|
||||
|
||||
## SLSetCircuitStateMessage
|
||||
|
||||
Passed as an argument to the emitted `circuitStateChanged`. The passed version is empty, however, since the response is just an acknowledgement of receipt of the set command.
|
||||
|
||||
### Properties
|
||||
|
||||
* `controllerId` - integer indicating the ID of the controller to send this command to.
|
||||
* Note that while `SLControllerConfigMessage` includes a controllerId, this ID, in my experience, should always be 0.
|
||||
* `circuitId` - integer indicating the ID of the circuit to set the state of.
|
||||
* This ID can be retrieved from `SLControllerConfigMessage`'s `bodyArray` property.
|
||||
* `circuitState` - integer indicating whether to switch the circuit on (`1`) or off (`0`).
|
||||
|
||||
# Changelog
|
||||
|
||||
## v1.0.1
|
||||
* Added direct connection support.
|
||||
|
||||
## v1.1.0
|
||||
* Added ability to set circuit state.
|
||||
* Fixed FindUnits.sendServerBroadcast() failing in certain environments.
|
||||
|
32
example.js
32
example.js
@ -2,14 +2,23 @@ const ScreenLogic = require('./index');
|
||||
|
||||
var finder = new ScreenLogic.FindUnits();
|
||||
finder.on('serverFound', function(server) {
|
||||
var client = new ScreenLogic.UnitConnection(server);
|
||||
finder.close();
|
||||
connect(new ScreenLogic.UnitConnection(server));
|
||||
});
|
||||
|
||||
finder.search();
|
||||
|
||||
// use this instead of the above `finder` logic if you want to use a direct connection
|
||||
//connect(new ScreenLogic.UnitConnection(80, '10.0.0.85'));
|
||||
|
||||
function connect(client) {
|
||||
client.on('loggedIn', function() {
|
||||
this.getVersion();
|
||||
}).on('version', function(version) {
|
||||
this.getPoolStatus();
|
||||
this.getChemicalData();
|
||||
this.getSaltCellConfig();
|
||||
this.getControllerConfig();
|
||||
console.log(" version=" + version.version);
|
||||
}).on('poolStatus', function(status) {
|
||||
this.getChemicalData();
|
||||
console.log(" pool ok=" + status.ok);
|
||||
console.log(" air temp=" + status.airTemp);
|
||||
console.log(" salt ppm=" + status.saltPPM);
|
||||
@ -17,21 +26,18 @@ finder.on('serverFound', function(server) {
|
||||
console.log(" saturation=" + status.saturation);
|
||||
console.log(" spa active=" + status.isSpaActive());
|
||||
console.log(" pool active=" + status.isPoolActive());
|
||||
}).on('controllerConfig', function(config) {
|
||||
console.log(" controller is in celsius=" + config.degC);
|
||||
client.close();
|
||||
finder.close();
|
||||
}).on('chemicalData', function(chemData) {
|
||||
this.getSaltCellConfig();
|
||||
console.log(" calcium=" + chemData.calcium);
|
||||
console.log(" cyanuric acid=" + chemData.cyanuricAcid);
|
||||
console.log(" alkalinity=" + chemData.alkalinity);
|
||||
}).on('saltCellConfig', function(saltCellConfig) {
|
||||
this.getControllerConfig();
|
||||
console.log(" salt cell installed=" + saltCellConfig.installed);
|
||||
}).on('version', function(version) {
|
||||
console.log(" version=" + version.version);
|
||||
}).on('controllerConfig', function(config) {
|
||||
console.log(" controller is in celsius=" + config.degC);
|
||||
client.close();
|
||||
});
|
||||
|
||||
client.connect();
|
||||
});
|
||||
|
||||
finder.search();
|
||||
}
|
||||
|
22
index.js
22
index.js
@ -44,7 +44,7 @@ class FindUnits extends EventEmitter {
|
||||
}
|
||||
|
||||
sendServerBroadcast() {
|
||||
var message = new Uint8Array(8);
|
||||
var message = Buffer.alloc(8);
|
||||
message[0] = 1;
|
||||
this.finder.send(message, 0, message.length, 1444, "255.255.255.255");
|
||||
//console.log("Looking for ScreenLogic hosts...");
|
||||
@ -56,9 +56,15 @@ class FindUnits extends EventEmitter {
|
||||
}
|
||||
|
||||
class UnitConnection extends EventEmitter {
|
||||
constructor(server) {
|
||||
constructor(server, address) {
|
||||
super();
|
||||
this.server = server;
|
||||
if (typeof server === 'object') {
|
||||
this.serverPort = server.port;
|
||||
this.serverAddress = server.address;
|
||||
} else {
|
||||
this.serverPort = server;
|
||||
this.serverAddress = address;
|
||||
}
|
||||
|
||||
this.client = new net.Socket();
|
||||
var _this = this;
|
||||
@ -76,7 +82,7 @@ class UnitConnection extends EventEmitter {
|
||||
connect() {
|
||||
//console.log("connecting...");
|
||||
var _this = this;
|
||||
this.client.connect(this.server.port, this.server.address, function() {
|
||||
this.client.connect(this.serverPort, this.serverAddress, function() {
|
||||
_this.onConnected();
|
||||
});
|
||||
}
|
||||
@ -121,6 +127,10 @@ class UnitConnection extends EventEmitter {
|
||||
this.client.write(new messages.SLVersionMessage().toBuffer());
|
||||
}
|
||||
|
||||
setCircuitState(controllerId, circuitId, circuitState) {
|
||||
this.client.write(new messages.SLSetCircuitStateMessage(controllerId, circuitId, circuitState).toBuffer());
|
||||
}
|
||||
|
||||
onClientMessage(msg) {
|
||||
//console.log('received message of length ' + msg.length);
|
||||
if (msg.length < 4) {
|
||||
@ -157,6 +167,10 @@ class UnitConnection extends EventEmitter {
|
||||
//console.log(" it's version");
|
||||
this.emit('version', new messages.SLVersionMessage(msg));
|
||||
break;
|
||||
case messages.SLSetCircuitStateMessage.getResponseId():
|
||||
//console.log(" it's circuit toggle ack");
|
||||
this.emit('circuitStateChanged', new messages.SLSetCircuitStateMessage());
|
||||
break;
|
||||
default:
|
||||
//console.log(" it's unknown. type: " + msgType);
|
||||
break;
|
||||
|
6
messages/SLMessage.js
Executable file → Normal file
6
messages/SLMessage.js
Executable file → Normal file
@ -10,6 +10,8 @@ exports.SLMessage = class SLMessage extends SmartBuffer {
|
||||
}
|
||||
|
||||
toBuffer() {
|
||||
this.encode();
|
||||
|
||||
if (this._wroteSize === false) {
|
||||
this.insertInt32LE(this.length - 4, 4);
|
||||
this._wroteSize = true;
|
||||
@ -54,4 +56,8 @@ exports.SLMessage = class SLMessage extends SmartBuffer {
|
||||
this.messageId = this.readUInt16LE();
|
||||
this.dataLength = this.readInt32LE();
|
||||
}
|
||||
|
||||
encode() {
|
||||
|
||||
}
|
||||
}
|
||||
|
25
messages/SLSetCircuitStateMessage.js
Normal file
25
messages/SLSetCircuitStateMessage.js
Normal file
@ -0,0 +1,25 @@
|
||||
const SLMessage = require('./SLMessage.js').SLMessage;
|
||||
|
||||
const MSG_ID = 12530;
|
||||
|
||||
exports.SLSetCircuitStateMessage = class SLSetCircuitStateMessage extends SLMessage {
|
||||
constructor(controllerId, circuitId, circuitState) {
|
||||
super(0, MSG_ID);
|
||||
|
||||
this.controllerId = controllerId;
|
||||
this.circuitId = circuitId;
|
||||
this.circuitState = circuitState;
|
||||
}
|
||||
|
||||
encode() {
|
||||
this.writeInt32LE(this.controllerId || 0);
|
||||
this.writeInt32LE(this.circuitId || 0);
|
||||
this.writeInt32LE(this.circuitState || 0);
|
||||
|
||||
super.encode();
|
||||
}
|
||||
|
||||
static getResponseId() {
|
||||
return MSG_ID + 1;
|
||||
}
|
||||
}
|
1
messages/index.js
Executable file → Normal file
1
messages/index.js
Executable file → Normal file
@ -5,3 +5,4 @@ exports.SLLoginMessage = require("./SLLoginMessage.js").SLLoginMessage;
|
||||
exports.SLChemDataMessage = require("./SLChemDataMessage.js").SLChemDataMessage;
|
||||
exports.SLSaltCellConfigMessage = require("./SLSaltCellConfigMessage.js").SLSaltCellConfigMessage;
|
||||
exports.SLVersionMessage = require("./SLVersionMessage.js").SLVersionMessage;
|
||||
exports.SLSetCircuitStateMessage = require("./SLSetCircuitStateMessage.js").SLSetCircuitStateMessage;
|
||||
|
@ -1,11 +1,17 @@
|
||||
{
|
||||
"name": "node-screenlogic",
|
||||
"description": "Tool for connecting to Pentair ScreenLogic systems on the local network",
|
||||
"version": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"main": "index.js",
|
||||
"license": "MIT",
|
||||
"repository": "https://github.com/parnic/node-screenlogic.git",
|
||||
"main": "index.js",
|
||||
"keywords": [
|
||||
"pentair",
|
||||
"pool",
|
||||
"screenlogic",
|
||||
"swimmingpool"
|
||||
],
|
||||
"dependencies": {
|
||||
"smart-buffer": "~4.0.1"
|
||||
}
|
||||
|
Reference in New Issue
Block a user