Files
MMM-IntelliCenter/node_helper.js

284 lines
7.7 KiB
JavaScript

/* global module require clearInterval clearTimeout setTimeout setInterval config */
var NodeHelper = require("node_helper");
let FindUnits;
let Unit;
import("node-intellicenter").then((x) => {
FindUnits = x.FindUnits;
Unit = x.Unit;
});
let messages;
import("node-intellicenter/messages").then((x) => {
messages = x.messages;
});
const Log = require("logger");
const reconnectDelayMs = 10 * 1000;
const unitFinderTimeoutMs = 5 * 1000;
let foundUnit = false;
const poolData = {};
let refreshTimer;
let unitFinderRetry;
let unitReconnectTimer;
module.exports = NodeHelper.create({
setCircuit(circuitState) {
this.setCircuitState(circuitState, (poolStatus) => {
this.sendSocketNotification("INTELLICENTER_CIRCUIT_DONE", {
circuitState,
status: poolStatus,
});
});
},
setHeatpoint(heatpoint) {
this.setHeatpointState(heatpoint, (poolStatus) => {
this.sendSocketNotification("INTELLICENTER_HEATPOINT_DONE", {
heatpoint,
status: poolStatus,
});
});
},
setHeatstate(heatstate) {
this.setHeatstateState(heatstate, (poolStatus) => {
this.sendSocketNotification("INTELLICENTER_HEATSTATE_DONE", {
heatstate,
status: poolStatus,
});
});
},
setLightcmd(lightCmd) {
this.setLights(lightCmd, (poolStatus) => {
this.sendSocketNotification("INTELLICENTER_LIGHTCMD_DONE", {
lightCmd,
status: poolStatus,
});
});
},
notifyReconnecting() {
this.sendSocketNotification("INTELLICENTER_RECONNECTING");
},
socketNotificationReceived(notification, payload) {
if (notification === "INTELLICENTER_CONFIG") {
if (!this.config) {
this.config = payload;
this.connect(
(status) => {
this.sendSocketNotification("INTELLICENTER_RESULT", status);
},
() => {
this.notifyReconnecting();
},
);
} else if (poolData.status) {
this.sendSocketNotification("INTELLICENTER_RESULT", poolData);
}
// If we don't have a status yet, assume the initial connection is still in progress and this socket notification will be delivered when setup is done
}
if (notification === "INTELLICENTER_CIRCUIT") {
this.setCircuit(payload);
}
if (notification === "INTELLICENTER_HEATPOINT") {
this.setHeatpoint(payload);
}
if (notification === "INTELLICENTER_HEATSTATE") {
this.setHeatstate(payload);
}
if (notification === "INTELLICENTER_LIGHTCMD") {
this.setLightcmd(payload);
}
},
resetFoundUnit() {
foundUnit = null;
if (refreshTimer) {
clearInterval(refreshTimer);
refreshTimer = null;
}
if (unitFinderRetry) {
clearInterval(unitFinderRetry);
unitFinderRetry = null;
}
if (unitReconnectTimer) {
clearTimeout(unitReconnectTimer);
unitReconnectTimer = null;
}
},
setupUnit(cb, reconnectCb) {
Log.info("[MMM-IntelliCenter] initial connection to unit...");
foundUnit
.on("error", (e) => {
Log.error(
`[MMM-IntelliCenter] error in unit connection. restarting the connection process in ${reconnectDelayMs / 1000} seconds`,
);
Log.error(e);
reconnectCb();
this.resetFoundUnit();
unitReconnectTimer = setTimeout(() => {
this.connect(cb, reconnectCb);
}, reconnectDelayMs);
})
.on("close", () => {
Log.error(
`[MMM-IntelliCenter] unit connection closed unexpectedly. restarting the connection process in ${reconnectDelayMs / 1000} seconds`,
);
reconnectCb();
this.resetFoundUnit();
unitReconnectTimer = setTimeout(() => {
this.connect(cb, reconnectCb);
}, reconnectDelayMs);
})
.once("connected", () => {
Log.info(
"[MMM-IntelliCenter] logged into unit. getting basic configuration...",
);
foundUnit.send(new messages.GetSystemInformation()).then(() => {
Log.info("[MMM-IntelliCenter] got it!");
});
})
.once("controllerConfig", (config) => {
Log.info(
"[MMM-IntelliCenter] configuration received. adding client...",
);
poolData.controllerConfig = config;
poolData.degStr = this.config.degC ? "C" : "F";
foundUnit.addClient(1234);
})
.once("addClient", () => {
Log.info(
"[MMM-IntelliCenter] client added successfully and listening for changes",
);
foundUnit.getPoolStatus();
// Connection seems to time out every 10 minutes without some sort of request made
refreshTimer = setInterval(
() => {
foundUnit.pingServer();
},
1 * 60 * 1000,
);
})
.on("poolStatus", (status) => {
Log.info("[MMM-IntelliCenter] received pool status update");
poolData.status = status;
cb(poolData);
});
foundUnit.connect();
},
findServer(cb, reconnectCb) {
Log.info("[MMM-IntelliCenter] starting search for local units");
const finder = new FindUnits(this.config.multicastInterface);
finder
.on("serverFound", (server) => {
finder.close();
Log.info(
`[MMM-IntelliCenter] local unit found at ${server.addressStr}:${server.port}`,
);
foundUnit = new Unit(server.addressStr, server.port);
this.setupUnit(cb, reconnectCb);
clearInterval(unitFinderRetry);
unitFinderRetry = null;
})
.on("error", (e) => {
Log.error(
`[MMM-IntelliCenter] error trying to find a server. scheduling a retry in ${reconnectDelayMs / 1000} seconds`,
);
Log.error(e);
this.resetFoundUnit();
setTimeout(() => {
this.findServer(cb);
}, reconnectDelayMs);
});
finder.search();
unitFinderRetry = setInterval(() => {
Log.info(
`[MMM-IntelliCenter] didn't find any units within ${unitFinderTimeoutMs / 1000} seconds, trying again...`,
);
finder.search();
}, unitFinderTimeoutMs);
},
connect(cb, reconnectCb) {
if (
!foundUnit &&
typeof config !== "undefined" &&
this.config.serverAddress &&
this.config.serverPort
) {
Log.info(
`[MMM-IntelliCenter] connecting directly to configured unit at ${this.config.serverAddress}:${this.config.serverPort}`,
);
foundUnit = new Unit(this.config.serverAddress, this.config.serverPort);
}
if (foundUnit) {
this.setupUnit(cb, reconnectCb);
} else {
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();
},
});