homebridge-enphase-envoy 10.2.5-beta.8 → 10.2.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -1
- package/index.js +3 -2
- package/package.json +1 -1
- package/src/energymeter.js +17 -20
- package/src/envoydata.js +4 -8
- package/src/envoydevice.js +4 -3
package/CHANGELOG.md
CHANGED
|
@@ -9,12 +9,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
9
9
|
|
|
10
10
|
- after update to v10.0.0 and above the accessory and bridge need to be removed from the homebridge / Home.app and added again
|
|
11
11
|
|
|
12
|
+
## [10.2.5] - (17.10.2025)
|
|
13
|
+
|
|
14
|
+
## Changes
|
|
15
|
+
|
|
16
|
+
- update EVE Energy Meter
|
|
17
|
+
- cleanup
|
|
18
|
+
|
|
12
19
|
## [10.2.3] - (15.10.2025)
|
|
13
20
|
|
|
14
21
|
## Changes
|
|
15
22
|
|
|
16
23
|
- fix [#215](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/215)
|
|
17
|
-
-
|
|
24
|
+
- update EVE Energy Meter
|
|
18
25
|
- other small fixes
|
|
19
26
|
- cleanup
|
|
20
27
|
|
package/index.js
CHANGED
|
@@ -90,6 +90,7 @@ class EnvoyPlatform {
|
|
|
90
90
|
}
|
|
91
91
|
|
|
92
92
|
try {
|
|
93
|
+
const url = envoyFirmware7xxTokenGenerationMode > 0 ? `https://${host}` : `http://${host}`;
|
|
93
94
|
const devicesClass = device.energyMeter ? [EnvoyDevice, EnergyMeter] : [EnvoyDevice];
|
|
94
95
|
for (const [index, DeviceClass] of devicesClass.entries()) {
|
|
95
96
|
const accessoryName = index === 0 ? deviceName : 'Energy Meter';
|
|
@@ -98,7 +99,7 @@ class EnvoyPlatform {
|
|
|
98
99
|
const impulseGenerator = new ImpulseGenerator()
|
|
99
100
|
.on('start', async () => {
|
|
100
101
|
try {
|
|
101
|
-
const envoyDevice = new DeviceClass(api, log, device, envoyIdFile, envoyTokenFile, prefDir, energyMeterHistoryFileName)
|
|
102
|
+
const envoyDevice = new DeviceClass(api, log, url, accessoryName, device, envoyIdFile, envoyTokenFile, prefDir, energyMeterHistoryFileName)
|
|
102
103
|
.on('devInfo', (info) => logLevel.devInfo && log.info(info))
|
|
103
104
|
.on('success', (msg) => logLevel.success && log.success(`Device: ${host} ${accessoryName}, ${msg}`))
|
|
104
105
|
.on('info', (msg) => logLevel.info && log.info(`Device: ${host} ${accessoryName}, ${msg}`))
|
|
@@ -111,7 +112,7 @@ class EnvoyPlatform {
|
|
|
111
112
|
api.publishExternalAccessories(PluginName, [accessory]);
|
|
112
113
|
if (logLevel.success) log.success(`Device: ${host} ${accessoryName}, Published as external accessory.`);
|
|
113
114
|
|
|
114
|
-
await impulseGenerator.
|
|
115
|
+
await impulseGenerator.state(false);
|
|
115
116
|
await envoyDevice.startStopImpulseGenerator(true);
|
|
116
117
|
}
|
|
117
118
|
} catch (error) {
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"private": false,
|
|
3
3
|
"displayName": "Enphase Envoy",
|
|
4
4
|
"name": "homebridge-enphase-envoy",
|
|
5
|
-
"version": "10.2.5
|
|
5
|
+
"version": "10.2.5",
|
|
6
6
|
"description": "Homebridge p7ugin for Photovoltaic Energy System manufactured by Enphase.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "grzegorz914",
|
package/src/energymeter.js
CHANGED
|
@@ -8,7 +8,7 @@ import fakegato from 'fakegato-history';
|
|
|
8
8
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
9
9
|
|
|
10
10
|
class EnergyMeter extends EventEmitter {
|
|
11
|
-
constructor(api, log, device, envoyIdFile, envoyTokenFile, prefDir, energyMeterHistoryFileName) {
|
|
11
|
+
constructor(api, log, url, deviceName, device, envoyIdFile, envoyTokenFile, prefDir, energyMeterHistoryFileName) {
|
|
12
12
|
super();
|
|
13
13
|
|
|
14
14
|
Accessory = api.platformAccessory;
|
|
@@ -19,7 +19,8 @@ class EnergyMeter extends EventEmitter {
|
|
|
19
19
|
|
|
20
20
|
//device configuration
|
|
21
21
|
this.log = log;
|
|
22
|
-
this.
|
|
22
|
+
this.url = url;
|
|
23
|
+
this.name = deviceName;
|
|
23
24
|
this.host = device.host;
|
|
24
25
|
|
|
25
26
|
this.envoyFirmware7xxTokenGenerationMode = device.envoyFirmware7xxTokenGenerationMode;
|
|
@@ -47,9 +48,6 @@ class EnergyMeter extends EventEmitter {
|
|
|
47
48
|
this.energyMeterHistoryFileName = energyMeterHistoryFileName;
|
|
48
49
|
this.lastReset = 0;
|
|
49
50
|
|
|
50
|
-
//url
|
|
51
|
-
this.url = device.envoyFirmware7xxTokenGenerationMode > 0 ? `https://${this.host}` : `http://${this.host}`;
|
|
52
|
-
|
|
53
51
|
//supported functions
|
|
54
52
|
this.feature = {
|
|
55
53
|
info: {
|
|
@@ -713,7 +711,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
713
711
|
const obj = {
|
|
714
712
|
type: 'pcu',
|
|
715
713
|
activeCount: this.feature.inventory.pcus.count,
|
|
716
|
-
measurementType: '
|
|
714
|
+
measurementType: 'production',
|
|
717
715
|
readingTime,
|
|
718
716
|
power: production.wattsNow,
|
|
719
717
|
energyToday: production.wattHoursToday,
|
|
@@ -744,7 +742,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
744
742
|
// PCU
|
|
745
743
|
const pcu = {
|
|
746
744
|
type: 'pcu',
|
|
747
|
-
measurementType: '
|
|
745
|
+
measurementType: 'production',
|
|
748
746
|
activeCount: this.feature.inventory?.pcus?.count,
|
|
749
747
|
readingTime,
|
|
750
748
|
power: data.watts_now_pcu,
|
|
@@ -759,7 +757,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
759
757
|
const eimActive = !!data.there_is_an_active_eim;
|
|
760
758
|
const eim = {
|
|
761
759
|
type: 'eim',
|
|
762
|
-
measurementType: '
|
|
760
|
+
measurementType: 'production',
|
|
763
761
|
activeCount: 1,
|
|
764
762
|
readingTime,
|
|
765
763
|
active: eimActive,
|
|
@@ -775,7 +773,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
775
773
|
const rgmActive = !!data.there_is_an_active_rgm;
|
|
776
774
|
const rgm = {
|
|
777
775
|
type: 'rgm',
|
|
778
|
-
measurementType: '
|
|
776
|
+
measurementType: 'production',
|
|
779
777
|
activeCount: 1,
|
|
780
778
|
readingTime,
|
|
781
779
|
active: rgmActive,
|
|
@@ -791,7 +789,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
791
789
|
const pmuActive = !!data.there_is_an_active_pmu;
|
|
792
790
|
const pmu = {
|
|
793
791
|
type: 'pmu',
|
|
794
|
-
measurementType: '
|
|
792
|
+
measurementType: 'production',
|
|
795
793
|
activeCount: 1,
|
|
796
794
|
readingTime,
|
|
797
795
|
active: pmuActive,
|
|
@@ -829,7 +827,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
829
827
|
const obj = {
|
|
830
828
|
type,
|
|
831
829
|
activeCount: 1,
|
|
832
|
-
measurementType: '
|
|
830
|
+
measurementType: 'production',
|
|
833
831
|
readingTime,
|
|
834
832
|
power: data.wattsNow,
|
|
835
833
|
energyToday: data.wattHoursToday,
|
|
@@ -849,7 +847,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
849
847
|
const obj = {
|
|
850
848
|
type: 'eim',
|
|
851
849
|
activeCount: 1,
|
|
852
|
-
measurementType: '
|
|
850
|
+
measurementType: 'net-consumption',
|
|
853
851
|
readingTime,
|
|
854
852
|
power: data.wattsNow,
|
|
855
853
|
energyToday: data.wattHoursToday,
|
|
@@ -893,7 +891,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
893
891
|
const obj = {
|
|
894
892
|
type: 'eim',
|
|
895
893
|
activeCount: 1,
|
|
896
|
-
measurementType:
|
|
894
|
+
measurementType: productionEim.measurementType,
|
|
897
895
|
readingTime: productionEim.readingTime,
|
|
898
896
|
power: productionEim.wNow,
|
|
899
897
|
energyToday,
|
|
@@ -913,14 +911,13 @@ class EnergyMeter extends EventEmitter {
|
|
|
913
911
|
// --- Consumption: EIM ---
|
|
914
912
|
if (keys.includes('consumption') && Array.isArray(data.consumption) && this.feature.meters.consumptionNet.enabled) {
|
|
915
913
|
for (const item of data.consumption) {
|
|
916
|
-
const
|
|
917
|
-
const key = MetersKeyMap[type];
|
|
914
|
+
const key = MetersKeyMap[item.measurementType];
|
|
918
915
|
const energyToday = (item.lines[0]?.whToday || 0) + (item.lines[1]?.whToday || 0) + (item.lines[2]?.whToday || 0);
|
|
919
916
|
const energyLastSevenDays = (item.lines[0]?.whLastSevenDays || 0) + (item.lines[1]?.whLastSevenDays || 0) + (item.lines[2]?.whLastSevenDays || 0);
|
|
920
917
|
const energyLifetime = (item.lines[0]?.whLifetime || 0) + (item.lines[1]?.whLifetime || 0) + (item.lines[2]?.whLifetime || 0);
|
|
921
918
|
const obj = {
|
|
922
919
|
type: 'eim',
|
|
923
|
-
measurementType:
|
|
920
|
+
measurementType: item.measurementType,
|
|
924
921
|
activeCount: 1,
|
|
925
922
|
readingTime: item.readingTime,
|
|
926
923
|
power: item.wNow,
|
|
@@ -965,7 +962,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
965
962
|
const key = MetersKeyMap[meterType];
|
|
966
963
|
const measurementType = ApiCodes[meterType];
|
|
967
964
|
|
|
968
|
-
let sourceMeter, sourceEnergy;
|
|
965
|
+
let sourceMeter, sourceEnergy, energyLifetimeWithOffset;
|
|
969
966
|
let power, energyLifetime;
|
|
970
967
|
switch (key) {
|
|
971
968
|
case 'production': {
|
|
@@ -1076,7 +1073,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
1076
1073
|
if (this.logDebug) this.emit('debug', `Prepare accessory`);
|
|
1077
1074
|
|
|
1078
1075
|
const envoySerialNumber = this.pv.info.serialNumber;
|
|
1079
|
-
const accessoryName = this.name
|
|
1076
|
+
const accessoryName = `${this.name} ${this.pv.powerAndEnergy.data[0].measurementType}`;
|
|
1080
1077
|
const accessoryUUID = AccessoryUUID.generate(envoySerialNumber + 'Energy Meter');
|
|
1081
1078
|
const accessoryCategory = Categories.SENSOR;
|
|
1082
1079
|
const accessory = new Accessory(accessoryName, accessoryUUID, accessoryCategory);
|
|
@@ -1091,7 +1088,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
1091
1088
|
.setCharacteristic(Characteristic.FirmwareRevision, this.pv.info.software?.replace(/[a-zA-Z]/g, '') ?? '0');
|
|
1092
1089
|
|
|
1093
1090
|
// Create FakeGatoHistory
|
|
1094
|
-
if (this.logDebug) this.emit('debug', `Prepare Fakegato Service`);
|
|
1091
|
+
if (this.logDebug) this.emit('debug', `Prepare Fakegato ${this.pv.powerAndEnergy.data[0].measurementType} Service`);
|
|
1095
1092
|
this.fakegatoHistoryService = new this.fakegatoHistory(`energy`, accessory, {
|
|
1096
1093
|
storage: 'fs',
|
|
1097
1094
|
disableRepeatLastData: true,
|
|
@@ -1109,7 +1106,7 @@ class EnergyMeter extends EventEmitter {
|
|
|
1109
1106
|
for (const source of this.pv.powerAndEnergy.data) {
|
|
1110
1107
|
const measurementType = source.measurementType;
|
|
1111
1108
|
|
|
1112
|
-
if (this.logDebug) this.emit('debug', `Prepare Meter ${measurementType} Service`);
|
|
1109
|
+
if (this.logDebug) this.emit('debug', `Prepare Energy Meter ${measurementType} Service`);
|
|
1113
1110
|
const energyMeterService = accessory.addService(Service.EvePowerMeter, `Energy Meter ${measurementType}`, `energyMeterService${measurementType}`);
|
|
1114
1111
|
energyMeterService.setCharacteristic(Characteristic.ConfiguredName, `Energy Meter ${measurementType}`);
|
|
1115
1112
|
|
package/src/envoydata.js
CHANGED
|
@@ -8,17 +8,16 @@ import Functions from './functions.js';
|
|
|
8
8
|
import { ApiUrls, PartNumbers, Authorization, ApiCodes, MetersKeyMap } from './constants.js';
|
|
9
9
|
|
|
10
10
|
class EnvoyData extends EventEmitter {
|
|
11
|
-
constructor(device, envoyIdFile, envoyTokenFile) {
|
|
11
|
+
constructor(url, device, envoyIdFile, envoyTokenFile) {
|
|
12
12
|
super();
|
|
13
13
|
|
|
14
14
|
//device configuration
|
|
15
|
+
this.url = url;
|
|
15
16
|
this.host = device.host;
|
|
16
17
|
this.envoyFirmware7xxTokenGenerationMode = device.envoyFirmware7xxTokenGenerationMode;
|
|
17
18
|
this.envoyPasswd = device.envoyPasswd;
|
|
18
19
|
this.enlightenUser = device.enlightenUser;
|
|
19
20
|
this.enlightenPasswd = device.enlightenPasswd;
|
|
20
|
-
this.envoyToken = device.envoyToken;
|
|
21
|
-
this.envoyTokenInstaller = device.envoyTokenInstaller;
|
|
22
21
|
this.envoyIdFile = envoyIdFile;
|
|
23
22
|
this.envoyTokenFile = envoyTokenFile;
|
|
24
23
|
|
|
@@ -38,9 +37,6 @@ class EnvoyData extends EventEmitter {
|
|
|
38
37
|
this.functions = new Functions();
|
|
39
38
|
this.checkTokenRunning = false;
|
|
40
39
|
|
|
41
|
-
//url
|
|
42
|
-
this.url = device.envoyFirmware7xxTokenGenerationMode > 0 ? `https://${this.host}` : `http://${this.host}`;
|
|
43
|
-
|
|
44
40
|
//supported functions
|
|
45
41
|
this.feature = {
|
|
46
42
|
info: {
|
|
@@ -53,9 +49,9 @@ class EnvoyData extends EventEmitter {
|
|
|
53
49
|
cookie: '',
|
|
54
50
|
jwtToken: {
|
|
55
51
|
generation_time: 0,
|
|
56
|
-
token: envoyToken,
|
|
52
|
+
token: device.envoyToken,
|
|
57
53
|
expires_at: 0,
|
|
58
|
-
installer:
|
|
54
|
+
installer: device.envoyFirmware7xxTokenGenerationMode === 2 ? device.envoyTokenInstaller : false
|
|
59
55
|
}
|
|
60
56
|
},
|
|
61
57
|
backboneApp: {
|
package/src/envoydevice.js
CHANGED
|
@@ -7,7 +7,7 @@ import { PartNumbers, ApiCodes, MetersKeyMap, DeviceTypeMap, LedStatus } from '.
|
|
|
7
7
|
let Accessory, Characteristic, Service, Categories, AccessoryUUID;
|
|
8
8
|
|
|
9
9
|
class EnvoyDevice extends EventEmitter {
|
|
10
|
-
constructor(api, log, device, envoyIdFile, envoyTokenFile) {
|
|
10
|
+
constructor(api, log, url, deviceName, device, envoyIdFile, envoyTokenFile) {
|
|
11
11
|
super();
|
|
12
12
|
|
|
13
13
|
Accessory = api.platformAccessory;
|
|
@@ -17,8 +17,9 @@ class EnvoyDevice extends EventEmitter {
|
|
|
17
17
|
AccessoryUUID = api.hap.uuid;
|
|
18
18
|
|
|
19
19
|
//device configuration
|
|
20
|
+
this.url = url;
|
|
20
21
|
this.device = device;
|
|
21
|
-
this.name =
|
|
22
|
+
this.name = deviceName;
|
|
22
23
|
this.host = device.host;
|
|
23
24
|
this.displayType = device.displayType;
|
|
24
25
|
|
|
@@ -2959,7 +2960,7 @@ class EnvoyDevice extends EventEmitter {
|
|
|
2959
2960
|
|
|
2960
2961
|
try {
|
|
2961
2962
|
// Envoy Data
|
|
2962
|
-
this.envoyData = new EnvoyData(this.device, this.envoyIdFile, this.envoyTokenFile)
|
|
2963
|
+
this.envoyData = new EnvoyData(this.url, this.device, this.envoyIdFile, this.envoyTokenFile)
|
|
2963
2964
|
.on('deviceInfo', (feature, info, timeZone) => {
|
|
2964
2965
|
this.feature = Object.assign(this.feature, feature);
|
|
2965
2966
|
this.pv.info = info;
|