homebridge-connect-my-pool
Version:
Partially complete HomeKit integration for Astral Viron Gateway
318 lines • 17.2 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.AstralGatewayAPI = void 0;
const events_1 = __importDefault(require("events"));
const request_promise_1 = __importDefault(require("request-promise"));
const cheerio_1 = __importDefault(require("cheerio"));
const tough_cookie_1 = require("tough-cookie");
const constants_1 = require("./constants");
const ajaxResponse_1 = require("./ajaxResponse");
const BASE_URL = 'https://connectmypool.com.au';
class AstralGatewayAPI extends events_1.default {
constructor(config, logger) {
super();
this.log = logger;
this.username = config.username || 'email';
this.password = config.password || 'password';
this.cookieJar = request_promise_1.default.jar();
}
get ConfiguredZones() {
return [
{
name: 'Pool Pumps',
type: "pool_and_spa" /* POOL_AND_SPA */
},
{
name: 'Pool Lighting',
type: "lighting" /* LIGHTING */
},
{
name: 'Pool Heater',
type: "heating" /* HEATING */
},
{
name: 'Pool Solar Heater',
type: "solar" /* SOLAR */
}
];
}
request(url, method = 'GET', formData, headers) {
return new Promise((success, fail) => {
var baseUrl = BASE_URL;
var options = {
method: method,
resolveWithFullResponse: true,
simple: false,
uri: baseUrl + url
};
if (headers)
options.headers = headers;
if (!(method === 'GET' && url === constants_1.URLS.login_url))
options.jar = this.cookieJar;
if (formData)
options.form = formData;
request_promise_1.default(options)
.then(async (response) => {
var body = response.body;
var resp = new ajaxResponse_1.AjaxResponse(response.statusCode, body, response.headers);
if (response.statusCode === 200) {
//success!
const $ = cheerio_1.default.load(body);
if ($('#ucLogin1$txtUserName').length > 0) {
await this.login();
return this.request(url, method, formData, headers);
}
else {
var p = $("input");
//var inputs : InputField[] = [];
p.each((index, e) => {
var i = e;
resp.inputs.push(new ajaxResponse_1.InputField(i.attribs.name, i.attribs.value, i.attribs.id));
});
}
}
else {
// if ('location' in response.headers) {
// resp.url = response.headers.location;
// }
}
if (response.headers['set-cookie']) {
var cookies;
if (response.headers['set-cookie'] instanceof Array)
cookies = response.headers['set-cookie'].map(c => tough_cookie_1.Cookie.parse(c));
else {
var cookie = tough_cookie_1.Cookie.parse(response.headers['set-cookie']);
if (cookie)
cookies = [cookie];
}
if (cookies) {
cookies.forEach(c => {
if (c)
this.cookieJar.setCookie(c, baseUrl);
});
}
}
resp.cookies = this.cookieJar;
success(resp);
})
.catch(function (err) {
fail(err);
//handle error
});
});
}
async getFavourites(inputs) {
var response = await this.request(constants_1.URLS.favourites_url);
var favourites = new ajaxResponse_1.ZoneResponse("favourites" /* FAVOURITES */, response.inputs);
this.emit("ZONE" /* ZONE */, favourites);
return favourites;
}
async getPoolSpa(inputs) {
var _a, _b;
var response = await this.request(constants_1.URLS.pool_spa_url);
const $ = cheerio_1.default.load(response.body);
var poolSpaMode = $(constants_1.COMMANDS.POOL_SPA.id_pump_mode_pool);
var modePoolSpa = null;
if (poolSpaMode.length > 0) {
modePoolSpa = poolSpaMode[0].attribs.class === 'btn_blue' ? "POOL" /* POOL */ : "SPA" /* SPA */;
}
var poolPumpMode = $(constants_1.COMMANDS.POOL_SPA.id_pool_filter);
var poolPumpModeState = null;
if (poolPumpMode.length > 0) {
poolPumpModeState = $(poolPumpMode[0]).text();
}
var spaJetMode = $(constants_1.COMMANDS.POOL_SPA.id_spa_jets);
var spaJetsModeState = null;
if (spaJetMode.length > 0) {
spaJetsModeState = $(spaJetMode[0]).text();
}
var spaBlowerMode = $(constants_1.COMMANDS.POOL_SPA.id_spa_blower);
var spaBlowerModeState = null;
if (spaBlowerMode.length > 0) {
spaBlowerModeState = $(spaBlowerMode[0]).text();
}
var isPoolPumpRunning = $(constants_1.COMMANDS.POOL_SPA.id_pool_filter_is_running).length > 0;
var isSpaJetsRunning = $(constants_1.COMMANDS.POOL_SPA.id_spa_jets_is_running).length > 0;
var isSpaBlowerRunning = $(constants_1.COMMANDS.POOL_SPA.id_spa_blower_is_running).length > 0;
var poolSpa = new ajaxResponse_1.PoolSpaResponse("pool_and_spa" /* POOL_AND_SPA */, modePoolSpa, poolPumpModeState, isPoolPumpRunning, spaJetsModeState, isSpaJetsRunning, spaBlowerModeState, isSpaBlowerRunning, response.inputs);
if (inputs && !modePoolSpa) {
(_a = this.log) === null || _a === void 0 ? void 0 : _a.info('PoolSpaResponse No Status', response.body);
}
else
(_b = this.log) === null || _b === void 0 ? void 0 : _b.info('PoolSpaResponse', inputs ? 'With Inputs' : 'No Inputs', poolSpa.poolSpaMode, poolSpa.poolFilterMode, poolSpa.isPoolFilterRunning, poolSpa.spaJetsMode, poolSpa.isSpaJetsRunning, poolSpa.spaBlowerMode, poolSpa.isSpaBlowerRunning);
this.emit("ZONE" /* ZONE */, poolSpa);
return poolSpa;
}
async getLighting(inputs) {
var response = await this.request(constants_1.URLS.lighting_url);
var lighting = new ajaxResponse_1.ZoneResponse("lighting" /* LIGHTING */, response.inputs);
this.emit("ZONE" /* ZONE */, lighting);
return lighting;
}
async getHeating(inputs) {
var _a, _b;
var response;
// if (inputs) {
// var formData: FormData = {};
// formData['ctl00$ScriptManager2'] = 'ctl00$ScriptManager2|ctl00$cpPageContent$tmrAutoPost';
// inputs.forEach(i => {
// if (i.name.includes('$hdn') || i.name.startsWith('__'))
// formData[i.name] = i.value ? i.value : '';
// })
// formData['__EVENTTARGET'] = 'ctl00$cpPageContent$tmrAutoPost';
// formData['__EVENTARGUMENT'] = null;
// formData['__LASTFOCUS'] = null;
// formData['ctl00$ddlPool'] = this.poolId
// formData['__ASYNCPOST'] = true;
// var headers: {key: string, value: string}[] = [];
// headers.push({key: "content-type", value: "application/x-www-form-urlencoded; charset=UTF-8"});
// headers.push({key: 'user-agent', value:'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.101 Safari/537.36'});
// headers.push({key: 'x-microsoftajax', value:'Delta=true'});
// headers.push({ key: 'x-requested-with', value: 'XMLHttpRequest' });
// headers.push({ key: 'origin', value: BASE_URL});
// headers.push({ key: 'referer', value: BASE_URL + URLS.heating_url});
// headers.push({ key: 'accept', value: '*.*'});
// response = await this.request(URLS.heating_url, 'POST', formData, headers)
// if (response.body.includes('ScriptManager.SupportsPartialRendering'))
// {
// this.log?.error('getHeating', 'Partial Rendering error', headers)
// response = await this.request(URLS.heating_url);
// }
// }
// else
response = await this.request(constants_1.URLS.heating_url);
const $ = cheerio_1.default.load(response.body);
var currentTemp = $(constants_1.COMMANDS.HEATING.id_current_temp);
var status = response.inputs.find(i => i.id === constants_1.COMMANDS.HEATING.status);
var heatingMode = response.inputs.find(i => i.id === constants_1.COMMANDS.HEATING.mode_pool_spa);
var modePoolSpa = heatingMode ? heatingMode.value === '1' ? "POOL" /* POOL */ : "SPA" /* SPA */ : null;
var statusOnOff = status ? status.value === '1' ? "ON" /* ON */ : "OFF" /* OFF */ : null;
var isRunning = $(constants_1.COMMANDS.HEATING.id_is_running).length > 0;
var currentId = constants_1.COMMANDS.HEATING.pool_temp;
if (modePoolSpa === "SPA" /* SPA */)
currentId = constants_1.COMMANDS.HEATING.spa_temp;
var currentValue = response.inputs.find(i => i.id === currentId);
var heating = new ajaxResponse_1.HeatingResponse("heating" /* HEATING */, statusOnOff, isRunning, currentTemp ? Number(currentTemp.text()) : null, currentValue ? Number(currentValue.value) : null, modePoolSpa, response.inputs);
if (inputs && !status) {
(_a = this.log) === null || _a === void 0 ? void 0 : _a.info('HeatingResponse No Status', response.body);
}
else
(_b = this.log) === null || _b === void 0 ? void 0 : _b.info('HeatingResponse', inputs ? 'With Inputs' : 'No Inputs', heating.status, heating.isRunning, heating.heatingMode, heating.currentTemp, heating.targetTemp);
this.emit("ZONE" /* ZONE */, heating);
return heating;
}
async getSolar(inputs) {
var _a, _b;
var response = await this.request(constants_1.URLS.solar_url);
const $ = cheerio_1.default.load(response.body);
var currentTemp = $(constants_1.COMMANDS.SOLAR.id_current_temp);
var status = response.inputs.find(i => i.id === constants_1.COMMANDS.SOLAR.status);
var rooftemp = $(constants_1.COMMANDS.SOLAR.id_roof_temp);
var statusOnOffAuto = status ? status.value === '2' ? "ON" /* ON */ : status.value === '1' ? "AUTO" /* AUTO */ : "OFF" /* OFF */ : null;
var running = $(constants_1.COMMANDS.SOLAR.id_is_running);
var isRunning = running.length > 0;
var currentId = constants_1.COMMANDS.SOLAR.pool_temp;
var currentValue = response.inputs.find(i => i.id === currentId);
var solar = new ajaxResponse_1.SolarResponse("solar" /* SOLAR */, statusOnOffAuto, isRunning, currentTemp ? Number(currentTemp.text()) : null, currentValue ? Number(currentValue.value) : null, rooftemp ? Number(rooftemp.text()) : null, response.inputs);
if (inputs && !status) {
(_a = this.log) === null || _a === void 0 ? void 0 : _a.info('SolarResponse No Status', response.body);
}
else
(_b = this.log) === null || _b === void 0 ? void 0 : _b.info('SolarResponse', inputs ? 'With Inputs' : 'No Inputs', solar.status, solar.isRunning, solar.currentTemp, solar.roofTemp, solar.targetTemp);
this.emit("ZONE" /* ZONE */, solar);
return solar;
}
async getChemistry(inputs) {
var response = await this.request(constants_1.URLS.chemistry_url);
var chemistry = new ajaxResponse_1.ZoneResponse("chemistry" /* CHEMISTRY */, response.inputs);
this.emit("ZONE" /* ZONE */, chemistry);
return chemistry;
}
getFormData(inputs, target, targetArgument) {
var _a, _b, _c, _d, _e, _f;
var viewstate = null;
var viewstategenerator = null;
var eventvalidation = null;
if (inputs) {
viewstate = (_b = (_a = inputs.find(s => s.name === '__VIEWSTATE')) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null;
viewstategenerator = (_d = (_c = inputs.find(s => s.name === '__VIEWSTATEGENERATOR')) === null || _c === void 0 ? void 0 : _c.value) !== null && _d !== void 0 ? _d : null;
eventvalidation = (_f = (_e = inputs.find(s => s.name === '__EVENTVALIDATION')) === null || _e === void 0 ? void 0 : _e.value) !== null && _f !== void 0 ? _f : null;
}
return {
['__LASTFOCUS']: null,
['__EVENTTARGET']: target !== null && target !== void 0 ? target : null,
['__EVENTARGUMENT']: targetArgument !== null && targetArgument !== void 0 ? targetArgument : null,
['__VIEWSTATE']: viewstate,
['__VIEWSTATEGENERATOR']: viewstategenerator,
['__EVENTVALIDATION']: eventvalidation,
};
}
getPoolId(html) {
const $ = cheerio_1.default.load(html);
return parseInt($('#ddlPool option:selected').val(), 10);
}
async login() {
var response = await this.request(constants_1.URLS.login_url);
var formData = this.getFormData(response.inputs);
formData['ucLogin1$txtUserName'] = this.username;
formData['ucLogin1$txtPassword'] = this.password;
formData['ucLogin1$btnLogin'] = 'Login';
response = await this.request(constants_1.URLS.login_url, 'POST', formData);
if (response.statusCode === 302) {
response = await this.request(constants_1.URLS.home_url);
this.poolId = this.getPoolId(response.body);
formData = this.getFormData(response.inputs, 'ctl00$ddlPool');
formData['ctl00$ddlPool'] = this.poolId;
response = await this.request(constants_1.URLS.home_url, 'POST', formData);
return response;
}
else
throw new Error("Unable to Login");
}
getSystemStatus(status) {
var self = this;
return new Promise((success, fail) => {
var _a, _b, _c, _d, _e, _f, _g;
var Promises = [];
Promises.push(self.getFavourites((_a = status === null || status === void 0 ? void 0 : status.favourites) === null || _a === void 0 ? void 0 : _a.inputs));
Promises.push(self.getPoolSpa((_b = status === null || status === void 0 ? void 0 : status.poolSpa) === null || _b === void 0 ? void 0 : _b.inputs));
Promises.push(self.getLighting((_c = status === null || status === void 0 ? void 0 : status.lighting) === null || _c === void 0 ? void 0 : _c.inputs));
Promises.push(self.getHeating((_d = status === null || status === void 0 ? void 0 : status.heating) === null || _d === void 0 ? void 0 : _d.inputs));
Promises.push(self.getSolar((_e = status === null || status === void 0 ? void 0 : status.solar) === null || _e === void 0 ? void 0 : _e.inputs));
Promises.push(self.getChemistry((_f = status === null || status === void 0 ? void 0 : status.chemistry) === null || _f === void 0 ? void 0 : _f.inputs));
(_g = this.log) === null || _g === void 0 ? void 0 : _g.debug("Getting System Status");
Promise.all(Promises).then((responses) => {
//this.log?.debug('Responses', responses);
var status = {
favourites: responses[0],
poolSpa: responses[1],
lighting: responses[2],
heating: responses[3],
solar: responses[4],
chemistry: responses[5],
};
self.emit("SYSTEM_STATUS" /* SYSTEM_STATUS */, status);
success(status);
}).catch((error) => {
fail("Error in Getting System Status " + error);
});
});
}
async connect() {
return new Promise((success, fail) => {
this.login().then(() => {
success(this.getSystemStatus());
}).catch((error) => {
fail('Unable to login ' + error);
});
});
}
async close() {
this.emit("close" /* CLOSE */);
}
}
exports.AstralGatewayAPI = AstralGatewayAPI;
//# sourceMappingURL=astralGatewayAPI.js.map