diff --git a/MMM-IntelliCenter.js b/MMM-IntelliCenter.js
index 32339e3..eb602c0 100644
--- a/MMM-IntelliCenter.js
+++ b/MMM-IntelliCenter.js
@@ -1,8 +1,8 @@
/* global Module Log document */
-let poolData;
-
Module.register("MMM-IntelliCenter", {
+ poolData: null,
+
defaults: {
showPoolTemp: true,
showSpaTemp: true,
@@ -21,7 +21,7 @@ Module.register("MMM-IntelliCenter", {
showPHTankLevel: true,
pHTankLevelMax: 7,
serverAddress: "",
- serverPort: 0,
+ serverPort: 6680,
multicastInterface: "",
},
@@ -44,7 +44,7 @@ Module.register("MMM-IntelliCenter", {
},
getDom() {
- if (!poolData) {
+ if (!this.poolData) {
const wrapper = document.createElement("div");
wrapper.innerHTML = "Loading IntelliCenter...";
wrapper.className += "dimmed light small text-center";
@@ -74,174 +74,37 @@ Module.register("MMM-IntelliCenter", {
const contents = [];
if (this.config.showPoolTemp) {
- let className = "";
- if (poolData.poolTemp <= this.config.coldTemp) {
- className += " cold-temp";
- } else if (poolData.poolTemp >= this.config.hotTemp) {
- className += " hot-temp";
- }
-
- contents.push({
- header: "Pool temp",
- data: `${poolData.poolTemp}°${!poolData.poolStatus ? " (last)" : ""}`,
- class: this.config.contentClass + className,
- });
+ let poolTemp = this.getPoolTempDom();
+ contents.push(poolTemp);
}
if (this.config.showSpaTemp) {
- let className = "";
- if (poolData.spaTemp <= this.config.coldTemp) {
- className = " cold-temp";
- } else if (poolData.spaTemp >= this.config.hotTemp) {
- className = " hot-temp";
- }
-
- contents.push({
- header: "Spa temp",
- data: `${poolData.spaTemp}°${!poolData.spaStatus ? " (last)" : ""}`,
- class: this.config.contentClass + className,
- });
+ let spaTemp = this.getSpaTempDom();
+ contents.push(spaTemp);
}
if (this.config.showPH) {
- let dataStr = poolData.lastPHVal;
- if (this.config.showPHTankLevel) {
- const percent = Math.round(
- ((poolData.phTank - 1) / this.config.pHTankLevelMax) * 100,
- );
- let cls = "";
- if (this.config.colored) {
- if (percent <= 17) {
- cls = "progress-bar-danger";
- } else if (percent <= 33) {
- cls = "progress-bar-warning";
- } else {
- cls = "progress-bar-success";
- }
- }
- const progBarDiv = `
';
- dataHtml += `
`;
- dataHtml += `
${controlObj.name}: ${temperature}°
`;
- dataHtml += `
`;
-
- contents.push({
- data: dataHtml,
- class: this.config.contentClass,
- });
- } else if (controlObj.type === "heatmode") {
- // todo: if "body" isn't defined in the user's config correctly, this will error out
- const body = controlObj.body.toLowerCase();
- if (body !== "pool" && body !== "spa") {
- Log.warn(
- "Invalid body specified for heatmode. Valid bodies: pool, spa",
- );
- continue;
- }
-
- const on =
- body === "pool"
- ? poolData.poolHeaterStatus
- : poolData.spaHeaterStatus;
- const mode =
- typeof controlObj.heatMode === "number" ? controlObj.heatMode : 3;
-
- let cls = "";
- if (this.config.colored) {
- cls = on ? "control-on" : "control-off";
- }
-
- contents.push({
- data: `
`,
- class: this.config.contentClass,
- });
- } else {
- Log.warn("circuit with unknown type, unable to display:");
- Log.warn(controlObj);
- }
+ let controls = this.getControlsDom();
+ for (const control of controls) {
+ contents.push(control);
}
}
let headerRow = null;
let contentRow = null;
- if (this.config.showFreezeMode && poolData.freezeMode) {
+ if (this.config.showFreezeMode && this.poolData.freezeMode) {
const row = document.createElement("tr");
table.appendChild(row);
row.className = "cold-temp";
@@ -252,7 +115,7 @@ Module.register("MMM-IntelliCenter", {
}
let cols = -1;
- for (const item in contents) {
+ for (const item of contents) {
cols++;
if (cols % this.config.columns === 0) {
headerRow = document.createElement("tr");
@@ -261,32 +124,271 @@ Module.register("MMM-IntelliCenter", {
table.appendChild(contentRow);
}
- if (contents[item].header) {
+ if (item.header) {
const headerCell = document.createElement("th");
- headerCell.innerHTML = contents[item].header;
+ headerCell.innerHTML = item.header;
headerRow.appendChild(headerCell);
}
const contentCell = document.createElement("td");
- contentCell.innerHTML = contents[item].data;
- contentCell.className = contents[item].class;
+ if (item.dom) {
+ contentCell.appendChild(item.dom);
+ } else {
+ contentCell.innerHTML = item.data;
+ }
+ contentCell.className = item.class;
contentRow.appendChild(contentCell);
}
return outermost;
},
+ getPoolTempDom() {
+ let className = "";
+ if (this.poolData.poolTemp <= this.config.coldTemp) {
+ className += " cold-temp";
+ } else if (this.poolData.poolTemp >= this.config.hotTemp) {
+ className += " hot-temp";
+ }
+
+ return {
+ header: "Pool temp",
+ data: `${this.poolData.poolTemp}°${!this.poolData.poolStatus ? " (last)" : ""}`,
+ class: this.config.contentClass + className,
+ };
+ },
+
+ getSpaTempDom() {
+ let className = "";
+ if (this.poolData.spaTemp <= this.config.coldTemp) {
+ className = " cold-temp";
+ } else if (this.poolData.spaTemp >= this.config.hotTemp) {
+ className = " hot-temp";
+ }
+
+ return {
+ header: "Spa temp",
+ data: `${this.poolData.spaTemp}°${!this.poolData.spaStatus ? " (last)" : ""}`,
+ class: this.config.contentClass + className,
+ };
+ },
+
+ getPHDom() {
+ let dataStr = this.poolData.lastPHVal;
+ if (this.config.showPHTankLevel) {
+ const percent = Math.round(
+ ((this.poolData.phTank - 1) / this.config.pHTankLevelMax) * 100,
+ );
+ let cls = "";
+ if (this.config.colored) {
+ if (percent <= 17) {
+ cls = "progress-bar-danger";
+ } else if (percent <= 33) {
+ cls = "progress-bar-warning";
+ } else {
+ cls = "progress-bar-success";
+ }
+ }
+ const progBarDiv = `
`;
+
+ dataStr = `${dataStr} ${progBarDiv}`;
+ }
+
+ return {
+ header: "pH",
+ data: dataStr,
+ class: this.config.contentClass,
+ };
+ },
+
+ getOrpDom() {
+ return {
+ header: "ORP",
+ data: this.poolData.lastOrpVal.toString(),
+ class: this.config.contentClass,
+ };
+ },
+
+ getSaltDom() {
+ return {
+ header: "Salt PPM",
+ data: this.poolData.saltPPM.toString(),
+ class: this.config.contentClass,
+ };
+ },
+
+ getSaturationDom() {
+ return {
+ header: "Saturation",
+ data: this.poolData.saturation.toString(),
+ class: this.config.contentClass,
+ };
+ },
+
+ getControlsDom() {
+ let controls = [];
+
+ for (const controlObj of this.config.controls) {
+ if (controlObj.type === "circuit") {
+ let circuit = this.getCircuitDom(controlObj);
+ controls.push(circuit);
+ } else if (controlObj.type === "heatpoint") {
+ let circuit = this.getHeatpointDom(controlObj);
+ if (circuit) {
+ controls.push(circuit);
+ }
+ } else if (controlObj.type === "heatmode") {
+ let circuit = this.getHeatmodeDom(controlObj);
+ if (circuit) {
+ controls.push(circuit);
+ }
+ } else {
+ Log.warn("circuit with unknown type, unable to display:");
+ Log.warn(controlObj);
+ }
+ }
+
+ return controls;
+ },
+
+ getCircuitDom(controlObj) {
+ let { name } = controlObj;
+ let on = false;
+ if (this.poolData.circuits[controlObj.id]) {
+ name ??= this.poolData.circuits[controlObj.id].name;
+ on = this.poolData.circuits[controlObj.id].status;
+ }
+
+ let cls = "";
+ if (this.config.colored) {
+ cls = on ? "control-on" : "control-off";
+ }
+
+ const button = document.createElement("button");
+ button.id = `sl-control-${controlObj.id}`;
+ button.classList.add("control", cls);
+ button.onclick = (e) => {
+ this.setCircuit(e.currentTarget);
+ };
+ button.dataset.circuit = controlObj.id;
+ button.dataset.state = on ? 1 : 0;
+
+ const content = document.createElement("div");
+ content.classList.add("content");
+ content.innerText = name;
+
+ button.appendChild(content);
+
+ return {
+ dom: button,
+ class: this.config.contentClass,
+ };
+ },
+
+ getHeatpointDom(controlObj) {
+ // todo: if "body" isn't defined in the user's config correctly, this will error out
+ const body = controlObj.body.toLowerCase();
+ if (body !== "pool" && body !== "spa") {
+ Log.warn("Invalid body specified for heatpoint. Valid bodies: pool, spa");
+ return;
+ }
+
+ const temperature =
+ body === "pool"
+ ? this.poolData.poolSetPoint.toString()
+ : this.poolData.spaSetPoint.toString();
+
+ const div = document.createElement("div");
+ div.classList.add("temperature-container");
+
+ const buttonUp = document.createElement("button");
+ buttonUp.id = `sl-temp-up-${controlObj.body}`;
+ buttonUp.classList.add("control-off", "temperature");
+ buttonUp.onclick = (e) => {
+ this.setHeatpoint(e.currentTarget, 1);
+ };
+ buttonUp.dataset.body = controlObj.body;
+ buttonUp.dataset.temperature = temperature;
+
+ const contentUp = document.createElement("div");
+ contentUp.classList.add("content");
+ contentUp.innerText = "+";
+
+ buttonUp.appendChild(contentUp);
+ div.appendChild(buttonUp);
+
+ const label = document.createElement("div");
+ label.classList.add("temperature-label");
+ label.innerHTML = `${controlObj.name}: ${temperature}°`;
+ div.appendChild(label);
+
+ const buttonDown = document.createElement("button");
+ buttonDown.id = `sl-temp-down-${controlObj.body}`;
+ buttonDown.classList.add("control-off", "temperature");
+ buttonDown.onclick = (e) => {
+ this.setHeatpoint(e.currentTarget, -1);
+ };
+ buttonDown.dataset.body = controlObj.body;
+ buttonDown.dataset.temperature = temperature;
+
+ const contentDown = document.createElement("div");
+ contentDown.classList.add("content");
+ contentDown.innerText = "-";
+
+ buttonDown.appendChild(contentDown);
+ div.appendChild(buttonDown);
+
+ return {
+ dom: div,
+ class: this.config.contentClass,
+ };
+ },
+
+ getHeatmodeDom(controlObj) {
+ // todo: if "body" isn't defined in the user's config correctly, this will error out
+ const body = controlObj.body.toLowerCase();
+ if (body !== "pool" && body !== "spa") {
+ Log.warn("Invalid body specified for heatmode. Valid bodies: pool, spa");
+ return;
+ }
+
+ const on =
+ body === "pool"
+ ? this.poolData.poolHeaterStatus
+ : this.poolData.spaHeaterStatus;
+
+ let cls = "";
+ if (this.config.colored) {
+ cls = on ? "control-on" : "control-off";
+ }
+
+ const button = document.createElement("button");
+ button.id = `sl-heat-${controlObj.body}`;
+ button.classList.add("control", cls);
+ button.onclick = (e) => {
+ this.setHeatmode(e.currentTarget);
+ };
+ button.dataset.body = controlObj.body;
+ button.dataset.state = on ? 1 : 0;
+
+ const content = document.createElement("div");
+ content.classList.add("content");
+ content.innerText = controlObj.name;
+
+ button.appendChild(content);
+
+ return {
+ dom: button,
+ class: this.config.contentClass,
+ };
+ },
+
socketNotificationReceived(notification, payload) {
if (notification === "INTELLICENTER_RESULT") {
- poolData = payload;
- this.updateDom();
- this.showReconnectOverlay(false);
- } else if (
- notification === "INTELLICENTER_CIRCUIT_DONE" ||
- notification === "INTELLICENTER_HEATSTATE_DONE" ||
- notification === "INTELLICENTER_HEATPOINT_DONE"
- ) {
- poolData = payload;
+ this.poolData = payload;
this.updateDom();
this.showReconnectOverlay(false);
} else if (notification === "INTELLICENTER_RECONNECTING") {
@@ -306,4 +408,34 @@ Module.register("MMM-IntelliCenter", {
element.classList.add("d-none");
}
},
+
+ setCircuit(e) {
+ const circuitId = e.dataset.circuit;
+ const on = e.dataset.state !== "0";
+ this.sendSocketNotification("INTELLICENTER_CIRCUIT", {
+ id: circuitId,
+ state: on ? 0 : 1,
+ });
+ e.classList.remove("control-on", "control-off");
+ },
+
+ setHeatmode(e) {
+ const bodyId = e.dataset.body;
+ const on = e.dataset.state !== "0";
+ this.sendSocketNotification("INTELLICENTER_HEATSTATE", {
+ body: bodyId,
+ state: on ? 0 : 1,
+ });
+ e.classList.remove("control-on", "control-off");
+ },
+
+ setHeatpoint(e, tempChange) {
+ const bodyId = e.dataset.body;
+ const temp = parseInt(e.dataset.temperature) + tempChange;
+ this.sendSocketNotification("INTELLICENTER_HEATPOINT", {
+ body: bodyId,
+ temperature: temp,
+ });
+ e.classList.remove("control-on", "control-off");
+ },
});
diff --git a/node_helper.js b/node_helper.js
index c0561de..1f8161f 100644
--- a/node_helper.js
+++ b/node_helper.js
@@ -40,39 +40,75 @@ let initialConnectDone = false;
module.exports = NodeHelper.create({
setCircuit(circuitState) {
- this.setCircuitState(circuitState, (poolStatus) => {
- this.sendSocketNotification("INTELLICENTER_CIRCUIT_DONE", {
- circuitState,
- status: poolStatus,
- });
- });
+ if (!foundUnit) {
+ return;
+ }
+
+ Log.info(
+ `[MMM-IntelliCenter] setting circuit ${circuitState.id} to ${!!circuitState.state}`,
+ );
+ foundUnit.send(
+ messages.SetObjectStatus(circuitState.id, !!circuitState.state),
+ );
},
setHeatpoint(heatpoint) {
- this.setHeatpointState(heatpoint, (poolStatus) => {
- this.sendSocketNotification("INTELLICENTER_HEATPOINT_DONE", {
- heatpoint,
- status: poolStatus,
- });
- });
+ if (!foundUnit) {
+ return;
+ }
+
+ let heatObjnam = "";
+ if (heatpoint.body === "spa") {
+ heatObjnam = spaObjnam;
+ } else if (heatpoint.body === "pool") {
+ heatObjnam = poolObjnam;
+ }
+
+ if (!heatObjnam) {
+ Log.error(
+ `[MMM-IntelliCenter] unable to determine objnam from given heatpoint body ${heatpoint.body} - expected "spa" or "pool"`,
+ );
+ return;
+ }
+
+ Log.info(
+ `[MMM-IntelliCenter] setting heatpoint for body ${heatObjnam} to ${heatpoint.temperature} deg`,
+ );
+ foundUnit.send(messages.SetSetpoint(heatObjnam, heatpoint.temperature));
},
setHeatstate(heatstate) {
- this.setHeatstateState(heatstate, (poolStatus) => {
- this.sendSocketNotification("INTELLICENTER_HEATSTATE_DONE", {
- heatstate,
- status: poolStatus,
- });
- });
+ if (!foundUnit) {
+ return;
+ }
+ let heatObjnam = "";
+ if (heatstate.body === "spa") {
+ heatObjnam = spaObjnam;
+ } else if (heatstate.body === "pool") {
+ heatObjnam = poolObjnam;
+ }
+
+ if (!heatObjnam) {
+ Log.error(
+ `[MMM-IntelliCenter] unable to determine objnam from given heatstate body ${heatstate.body} - expected "spa" or "pool"`,
+ );
+ return;
+ }
+
+ Log.info(
+ `[MMM-IntelliCenter] setting heat state for body ${heatObjnam} to ${!!heatstate.state}`,
+ );
+ foundUnit.send(messages.SetHeatMode(heatObjnam, !!heatstate.state));
},
setLightcmd(lightCmd) {
- this.setLights(lightCmd, (poolStatus) => {
- this.sendSocketNotification("INTELLICENTER_LIGHTCMD_DONE", {
- lightCmd,
- status: poolStatus,
- });
- });
+ if (!foundUnit) {
+ return;
+ }
+
+ Log.info(`[MMM-IntelliCenter] sending light command ${lightCmd}`);
+ // NYI in node-intellicenter
+ // foundUnit.send(messages.SendLightCommand(lightCmd));
},
notifyReconnecting() {
@@ -185,9 +221,9 @@ module.exports = NodeHelper.create({
if (obj.params.LOTMP) {
poolData.poolSetPoint = parseInt(obj.params.LOTMP);
}
- // todo: HTSRC probably not the right check for this
- if (obj.params.HTSRC) {
- poolData.poolHeaterStatus = obj.params.HTSRC !== "00000";
+ // todo: is MODE the right check for this?
+ if (obj.params.MODE) {
+ poolData.poolHeaterStatus = obj.params.MODE === "11";
}
if (obj.params.STATUS) {
poolData.poolStatus = obj.params.STATUS === "ON";
@@ -201,9 +237,9 @@ module.exports = NodeHelper.create({
if (obj.params.LOTMP) {
poolData.spaSetPoint = parseInt(obj.params.LOTMP);
}
- // todo: HTSRC probably not the right check for this
- if (obj.params.HTSRC) {
- poolData.spaHeaterStatus = obj.params.HTSRC !== "00000";
+ // todo: is MODE the right check for this?
+ if (obj.params.MODE) {
+ poolData.spaHeaterStatus = obj.params.MODE === "11";
}
if (obj.params.STATUS) {
poolData.spaStatus = obj.params.STATUS === "ON";
@@ -317,7 +353,7 @@ module.exports = NodeHelper.create({
await foundUnit.send(
messages.SubscribeToUpdates(obj, [
"LOTMP",
- "HTSRC",
+ "MODE",
"STATUS",
"LSTTMP",
]),
@@ -413,54 +449,4 @@ module.exports = NodeHelper.create({
this.findServer(cb, reconnectCb);
}
},
-
- setCircuitState(circuitState, cb) {
- if (!foundUnit) {
- cb();
- return;
- }
-
- Log.info(
- `[MMM-IntelliCenter] setting circuit ${circuitState.id} to ${circuitState.state}`,
- );
- foundUnit.setCircuitState(0, circuitState.id, circuitState.state);
- foundUnit.getPoolStatus();
- },
-
- setHeatpointState(heatpoint, cb) {
- if (!foundUnit) {
- cb();
- return;
- }
-
- Log.info(
- `[MMM-IntelliCenter] setting heatpoint for body ${heatpoint.body} to ${heatpoint.temperature} deg`,
- );
- foundUnit.setSetPoint(0, heatpoint.body, heatpoint.temperature);
- foundUnit.getPoolStatus();
- },
-
- setHeatstateState(heatstate, cb) {
- if (!foundUnit) {
- cb();
- return;
- }
-
- Log.info(
- `[MMM-IntelliCenter] setting heat state for body ${heatstate.body} to ${heatstate.state}`,
- );
- foundUnit.setHeatMode(0, heatstate.body, heatstate.state);
- foundUnit.getPoolStatus();
- },
-
- setLights(lightCmd, cb) {
- if (!foundUnit) {
- cb();
- return;
- }
-
- Log.info(`[MMM-IntelliCenter] sending light command ${lightCmd}`);
- foundUnit.sendLightCommand(0, lightCmd);
- foundUnit.getPoolStatus();
- },
});