Skip to content

Commit

Permalink
Merge pull request #45 from bisand/bisand/issue12
Browse files Browse the repository at this point in the history
Added total power and energy to Harvi device, together with a few more capabilities
  • Loading branch information
bisand authored Oct 5, 2022
2 parents 1656c6a + 17fdac3 commit 5c9b136
Show file tree
Hide file tree
Showing 25 changed files with 3,635 additions and 1,199 deletions.
2 changes: 2 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules/**/*.*
build/**/*.*
22 changes: 22 additions & 0 deletions .eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"env": {
"browser": true,
"es2021": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended"
],
"overrides": [
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": "latest",
"sourceType": "module"
},
"plugins": [
"@typescript-eslint"
],
"rules": {
}
}
2 changes: 1 addition & 1 deletion .homeycompose/app.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"id": "net.biseth.myenergi",
"version": "1.6.1",
"version": "1.7.0",
"compatibility": ">=5.0.0",
"sdk": 3,
"brandColor": "#2bcc64",
Expand Down
4 changes: 3 additions & 1 deletion api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@ import { MyEnergiApp } from './app';

module.exports = {

// eslint-disable-next-line @typescript-eslint/no-explicit-any
async postLogin(data: { homey: Homey, body: any }) {
const app = data.homey.app as MyEnergiApp;
const response = await app.validateCredentials(data.body);
const response = await app.validateCredentials(data.body).catch(this.error);
console.log(response);
return (response);
},

// eslint-disable-next-line @typescript-eslint/no-unused-vars, @typescript-eslint/no-explicit-any
async getTest(data: { homey: Homey, query: any }) {
// you can access query parameters like "/?foo=bar" through `query.foo`

Expand Down
167 changes: 162 additions & 5 deletions app.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"_comment": "This file is generated. Please edit .homeycompose/app.json instead.",
"id": "net.biseth.myenergi",
"version": "1.6.1",
"version": "1.7.0",
"compatibility": ">=5.0.0",
"sdk": 3,
"brandColor": "#2bcc64",
Expand Down Expand Up @@ -169,13 +169,45 @@
},
"class": "sensor",
"capabilities": [
"meter_power",
"measure_power",
"ct1_type",
"measure_power_ct1",
"ct2_type",
"measure_power_ct2",
"ct3_type",
"measure_power_ct3"
"measure_power_ct3",
"button.reset_meter",
"button.reload_capabilities"
],
"capabilitiesOptions": {
"button.reset_meter": {
"maintenanceAction": true,
"title": {
"en": "Reset energy meter",
"no": "Tilbakestill strømmåler",
"nl": "Reset energiemeter",
"se": "Återställ energimätaren",
"de": "Energiezähler zurücksetzen"
},
"desc": {
"en": "Reset the accumulated energy usage (kWh), this can not be restored.",
"no": "Tilbakestill akkumulert strømforbruk (kWh), dette kan ikke gjenopprettes.",
"nl": "Reset het geaccumuleerde stroomverbruik (kWh), dit kan niet worden hersteld.",
"de": "Setzen Sie den kumulierten Stromverbrauch zurück (kWh), dieser kann nicht wiederhergestellt werden.",
"se": "Återställ den ackumulerade strömförbrukningen (kWh), detta kan inte återställas"
}
},
"button.reload_capabilities": {
"maintenanceAction": true,
"title": {
"en": "Reload capabilities"
},
"desc": {
"en": "Reload sensor capabilities. Use this to reload sensor capabilities in case some of them are missing or are out of order."
}
}
},
"platforms": [
"local"
],
Expand All @@ -200,7 +232,132 @@
"small": "/drivers/harvi/assets/images/small.png",
"large": "/drivers/harvi/assets/images/large.png"
},
"id": "harvi"
"id": "harvi",
"settings": [
{
"id": "totalEnergyOffset",
"type": "number",
"value": 0,
"label": {
"en": "Total energy consumption offset",
"no": "Totalt energiforbruk offset",
"nl": "Totaal energieverbruik offset",
"sv": "Total energiförbrukning offset",
"de": "Gesamtenergieverbrauch offset"
},
"units": {
"en": "kWh"
},
"hint": {
"en": "If you want, you can add an offset to the total energi consumption. This setting will add the value to the current energy consumtion and reset itself back to zero."
}
},
{
"type": "group",
"label": {
"en": "Power calculations",
"nl": "Vermogen berekenen",
"de": "Leistungsberechnungen",
"sv": "Effektberäkningar"
},
"children": [
{
"id": "powerCalculationMode",
"type": "dropdown",
"value": "automatic",
"label": {
"en": "Default mode",
"nl": "Standaard modus",
"de": "Standardmodus",
"sv": "Standardläge"
},
"values": [
{
"id": "automatic",
"label": {
"en": "Automatically select CTs",
"nl": "Selecteer CT's automatisch",
"de": "CTs automatisch auswählen",
"sv": "Välj CT automatiskt"
}
},
{
"id": "manual",
"label": {
"en": "Manual override CTs",
"nl": "Handmatige instelling CT's",
"de": "CTs manuell Überbrücken",
"sv": "Manuell CT konfiguration"
}
}
]
},
{
"id": "includeCT1",
"type": "checkbox",
"label": {
"en": "Include CT 1",
"nl": "CT 1 meenemen",
"de": "Inklusive CT 1",
"sv": "Inkludera CT 1"
},
"value": true,
"hint": {
"en": "Include CT 1 in the power calculation.",
"nl": "CT 1 meenemen in berekening.",
"de": "Beziehen Sie CT 1 in die Leistungsberechnung ein.",
"sv": "Inkludera CT 1 i effektberäkningen."
}
},
{
"id": "includeCT2",
"type": "checkbox",
"label": {
"en": "Include CT 2",
"nl": "CT 2 meenemen",
"de": "Inklusive CT 2",
"sv": "Inkludera CT 2"
},
"value": true,
"hint": {
"en": "Include CT 2 in the power calculation.",
"nl": "CT 2 meenemen in berekening.",
"de": "Beziehen Sie CT 2 in die Leistungsberechnung ein.",
"sv": "Inkludera CT 2 i effektberäkningen."
}
},
{
"id": "includeCT3",
"type": "checkbox",
"label": {
"en": "Include CT 3",
"nl": "CT 3 meenemen",
"de": "Inklusive CT 3",
"sv": "Inkludera CT 3"
},
"value": true,
"hint": {
"en": "Include CT 3 in the power calculation.",
"nl": "CT 3 meenemen in berekening.",
"de": "Beziehen Sie CT 3 in die Leistungsberechnung ein.",
"sv": "Inkludera CT 3 i effektberäkningen."
}
}
]
},
{
"id": "showNegativeValues",
"type": "checkbox",
"value": true,
"label": {
"en": "Show negative values",
"no": "Vis negative verdier",
"nl": "Negatieve waarden weergeven",
"sv": "Visa negativa värden",
"de": "Negative Werte anzeigen"
}
}
]
},
{
"name": {
Expand Down Expand Up @@ -242,14 +399,14 @@
"button.reset_meter": {
"maintenanceAction": true,
"title": {
"en": "Reset power meter",
"en": "Reset energy meter",
"no": "Tilbakestill strømmåler",
"nl": "Reset energiemeter",
"se": "Återställ energimätaren",
"de": "Energiezähler zurücksetzen"
},
"desc": {
"en": "Reset the accumulated power usage (kWh), this can not be restored.",
"en": "Reset the accumulated energy usage (kWh), this can not be restored.",
"no": "Tilbakestill akkumulert strømforbruk (kWh), dette kan ikke gjenopprettes.",
"nl": "Reset het geaccumuleerde stroomverbruik (kWh), dit kan niet worden hersteld.",
"de": "Setzen Sie den kumulierten Stromverbrauch zurück (kWh), dieser kann nicht wiederhergestellt werden.",
Expand Down
76 changes: 45 additions & 31 deletions app.ts
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
import sourceMapSupport from 'source-map-support';
sourceMapSupport.install();
// import sourceMapSupport from 'source-map-support';
// sourceMapSupport.install();

import Homey from 'homey';
import { MyEnergi } from 'myenergi-api';
import { Credential } from './models/Credential';
import { MyEnergiHub } from './models/MyEnergiHub';
import { Response } from './models/Result';
import { SchedulerService } from './services/SchedulerService';

export class MyEnergiApp extends Homey.App {

private _dataUpdateInterval: number = 60 * 1000;
private _dataUpdateId!: NodeJS.Timeout;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
private _dataUpdateCallbacks: any[] = [];
private _apiBaseUrl: string = 'https://s18.myenergi.net';
private _apiBaseUrl = 'https://s18.myenergi.net';

public clients: any;
public clients: { [name: string]: MyEnergi } = {};
private _schedulerService!: SchedulerService;

private async initClients(hubs: any) {
private async initClients(hubs: MyEnergiHub[]) {
this.log(`Starting client init...`);
if (this.clients) {
Object.keys(this.clients).forEach((key, i, arr) => {
Object.keys(this.clients).forEach((key: string) => {
this.log(key);
delete this.clients[key];
});
}
if (hubs) {
this.clients = {};
hubs.forEach((hub: any, index: number) => {
hubs.forEach((hub: MyEnergiHub, index: number) => {
this.log(hub);
this.clients[`${hub.hubname}_${hub.username}`] = new MyEnergi(hub.username, hub.password, this._apiBaseUrl);
if (index === 0) {
Expand All @@ -34,37 +38,48 @@ export class MyEnergiApp extends Homey.App {
this.log(`Added hub ${hub.hubname} with url ${this._apiBaseUrl}`);
});
}

const runDataUpdate = () => {
const updateInterval: number = this._dataUpdateInterval / 1000;
this.log(`Starting scheduled data update. Running every ${updateInterval} seconds.`);
if (this.clients) {
Object.keys(this.clients).forEach(async c => {
this.log(`Fetching data for ${c}`);
const client: MyEnergi = this.clients[c] as MyEnergi;
const data = await client.getStatusAll().catch(this.error);
if (data)
this._dataUpdateCallbacks.forEach(callback => {
try {
callback(data);
} catch (error) {
this.error(error);
}
});
});
}
}

runDataUpdate();
if (!this._schedulerService) {
this._schedulerService = new SchedulerService(runDataUpdate, this._dataUpdateInterval);
} else {
this._schedulerService.stop();
}

this._schedulerService.start(this._dataUpdateInterval);

this.log(`Client init complete.`);
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
public registerDataUpdateCallback(callback: any) {
this._dataUpdateCallbacks.push(callback);
}

private runDataUpdate() {
const updateInterval: number = this._dataUpdateInterval / 1000;
this.log(`Starting scheduled data update. Running every ${updateInterval} seconds.`);
clearTimeout(this._dataUpdateId);
if (this.clients) {
Object.keys(this.clients).forEach(async c => {
this.log(`Fetching data for ${c}`);
const client: MyEnergi = this.clients[c] as MyEnergi;
const data = await client.getStatusAll().catch(this.error);
if (data)
this._dataUpdateCallbacks.forEach(callback => {
callback(data);
});
});
}
this._dataUpdateId = setTimeout(() => {
this.runDataUpdate();
}, this._dataUpdateInterval);
}

private async checkCredential(apiBaseUrl: string, username: string, password: string): Promise<boolean> {
try {
const client = new MyEnergi(username, password, apiBaseUrl);
const data = await client.getStatusAll();
const data = await client.getStatusAll().catch(this.error);
this.log(`Credential check: ${JSON.stringify(data)}`);
if (data && Array.isArray(data)) {
return true;
Expand All @@ -82,7 +97,7 @@ export class MyEnergiApp extends Homey.App {

// Start debuger
if (process.env.DEBUG === '1') {
require('inspector').open(9229, '0.0.0.0', true);
// require('inspector').open(9229, '0.0.0.0', false);
// debugger;
}

Expand All @@ -108,7 +123,6 @@ export class MyEnergiApp extends Homey.App {
this.initClients(hubs);
});

this.runDataUpdate();
this.log('myenergi app has been initialized');
}

Expand All @@ -121,7 +135,7 @@ export class MyEnergiApp extends Homey.App {
* @param body Credentials
*/
public async validateCredentials(body: Credential): Promise<Response> {
const res = await this.checkCredential(this._apiBaseUrl, body.username, body.password);
const res = await this.checkCredential(this._apiBaseUrl, body.username, body.password).catch(this.error);
return res ? { result: 'ok' } : { result: 'error' } as Response;
}
}
Expand Down
Loading

0 comments on commit 5c9b136

Please sign in to comment.