homebridge-enphase-envoy
Version:
Homebridge plugin for Photovoltaic Energy System manufactured by Enphase.
100 lines (84 loc) • 3.28 kB
JavaScript
import axios from 'axios';
import { URLSearchParams } from 'url';
import EventEmitter from 'events';
import { EnphaseUrls } from './constants.js';
class EnvoyToken extends EventEmitter {
constructor(config) {
super();
this.user = config.user;
this.passwd = config.passwd;
this.serialNumber = config.serialNumber;
this.logWarn = config.logWarn;
this.logError = config.logError;
}
async refreshToken() {
try {
const cookie = await this.loginToEnlighten();
if (!cookie) return null;
const tokenData = await this.getToken(cookie);
if (!tokenData) return null;
// Determine if token is installer or user (12h = 43200 seconds)
const installerToken = (tokenData.expires_at - tokenData.generation_time) === 43200;
tokenData.installer = installerToken;
this.emit('success', `Token ${installerToken ? 'installer' : 'user'}, expires at: ${new Date(tokenData.expires_at * 1000).toLocaleString()}`);
return tokenData;
} catch (error) {
throw new Error(`Refresh token error: ${error}`);
}
}
async loginToEnlighten() {
try {
const form = new URLSearchParams();
form.append('user[email]', this.user);
form.append('user[password]', this.passwd);
const response = await axios({
method: 'POST',
baseURL: EnphaseUrls.BaseUrl,
url: EnphaseUrls.Login,
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
data: form,
timeout: 10000
});
if (response.status !== 200) {
if (this.logError) this.emit('error', `Login failed with status code: ${response.status}`);
return null;
}
const cookie = response.headers['set-cookie'];
if (!cookie) {
if (this.logWarn) this.emit('warn', `No cookie returned from login. Response headers: ${JSON.stringify(response.headers)}`);
return null;
}
return cookie;
} catch (error) {
throw new Error(`Login to Enlighten error: ${error}`);
}
}
async getToken(cookie) {
try {
const response = await axios({
method: 'GET',
baseURL: EnphaseUrls.BaseUrl,
url: EnphaseUrls.EntrezAuthToken,
params: {
serial_num: this.serialNumber
},
headers: {
Accept: 'application/json',
Cookie: cookie
},
timeout: 10000
});
const tokenData = response.data;
if (!tokenData.token || !tokenData.expires_at || !tokenData.generation_time) {
if (this.logWarn) this.emit('warn', `Incomplete token data: ${JSON.stringify(tokenData)}`);
return null;
}
return tokenData;
} catch (error) {
throw new Error(`Get token error: ${error}`);
}
}
}
export default EnvoyToken;