homebridge-enphase-envoy 10.2.3-beta.9 → 10.2.4

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 CHANGED
@@ -9,6 +9,15 @@ 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.3] - (15.10.2025)
13
+
14
+ ## Changes
15
+
16
+ - fix [#215](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/215)
17
+ - epdate EVE Energy monitor
18
+ - other small fixes
19
+ - cleanup
20
+
12
21
  ## [10.2.2] - (12.10.2025)
13
22
 
14
23
  ## Changes
package/index.js CHANGED
@@ -133,7 +133,6 @@ class EnvoyPlatform {
133
133
  }
134
134
 
135
135
  configureAccessory(accessory) {
136
- accessory.log = this.log;
137
136
  this.accessories.push(accessory);
138
137
  }
139
138
  }
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.3-beta.9",
5
+ "version": "10.2.4",
6
6
  "description": "Homebridge p7ugin for Photovoltaic Energy System manufactured by Enphase.",
7
7
  "license": "MIT",
8
8
  "author": "grzegorz914",
@@ -2256,7 +2256,7 @@ export default (api) => {
2256
2256
  Service.LiveDataService = LiveDataService;
2257
2257
 
2258
2258
  // EVE electric meter
2259
- class EveCurrentConsumption extends Characteristic {
2259
+ class EvePower extends Characteristic {
2260
2260
  constructor() {
2261
2261
  super('Power', 'E863F10D-079E-48FF-8F27-9C2605A29F52');
2262
2262
  this.setProps({
@@ -2270,9 +2270,9 @@ export default (api) => {
2270
2270
  this.value = this.getDefaultValue();
2271
2271
  }
2272
2272
  }
2273
- Characteristic.EveCurrentConsumption = EveCurrentConsumption;
2273
+ Characteristic.EvePower = EvePower;
2274
2274
 
2275
- class EveTotalConsumption extends Characteristic {
2275
+ class EveEnergyLifetime extends Characteristic {
2276
2276
  constructor() {
2277
2277
  super('Energy', 'E863F10C-079E-48FF-8F27-9C2605A29F52');
2278
2278
  this.setProps({
@@ -2286,7 +2286,7 @@ export default (api) => {
2286
2286
  this.value = this.getDefaultValue();
2287
2287
  }
2288
2288
  }
2289
- Characteristic.EveTotalConsumption = EveTotalConsumption;
2289
+ Characteristic.EveEnergyLifetime = EveEnergyLifetime;
2290
2290
 
2291
2291
  class EveVoltage extends Characteristic {
2292
2292
  constructor() {
@@ -2324,7 +2324,7 @@ export default (api) => {
2324
2324
  constructor() {
2325
2325
  super('Reset time', 'E863F112-079E-48FF-8F27-9C2605A29F52');
2326
2326
  this.setProps({
2327
- format: Formats.UInt32,
2327
+ format: Formats.UINT32,
2328
2328
  perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE, Perms.NOTIFY]
2329
2329
  });
2330
2330
  this.value = this.getDefaultValue();
@@ -2338,8 +2338,8 @@ export default (api) => {
2338
2338
  constructor(displayName, subtype) {
2339
2339
  super(displayName, 'E863F130-079E-48FF-8F27-9C2605A29F52', subtype);
2340
2340
  // Mandatory Characteristics
2341
- this.addCharacteristic(Characteristic.EveCurrentConsumption);
2342
- this.addCharacteristic(Characteristic.EveTotalConsumption);
2341
+ this.addCharacteristic(Characteristic.EvePower);
2342
+ this.addCharacteristic(Characteristic.EveEnergyLifetime);
2343
2343
  // Optional Characteristics
2344
2344
  this.addOptionalCharacteristic(Characteristic.EveVoltage);
2345
2345
  this.addOptionalCharacteristic(Characteristic.EveCurrent);
@@ -27,7 +27,7 @@ class EnergyMeter extends EventEmitter {
27
27
  this.envoyFirmware7xxTokenGenerationMode = envoyFirmware7xxTokenGenerationMode;
28
28
  this.envoyPasswd = envoyPasswd;
29
29
  this.enlightenUser = enlightenUser;
30
- this.enlightenPassword = enlightenPasswd;
30
+ this.enlightenPasswd = enlightenPasswd;
31
31
  this.envoyToken = envoyToken;
32
32
  this.envoyTokenInstaller = envoyTokenInstaller;
33
33
  this.powerProductionSummary = device.powerProductionSummary || 1;
@@ -51,6 +51,7 @@ class EnergyMeter extends EventEmitter {
51
51
  this.fakegatoHistory = fakegato(api);
52
52
  this.prefDir = prefDir;
53
53
  this.energyMeterHistoryFileName = energyMeterHistoryFileName;
54
+ this.lastReset = 0;
54
55
 
55
56
  //url
56
57
  this.url = envoyFirmware7xxTokenGenerationMode > 0 ? `https://${this.host}` : `http://${this.host}`;
@@ -975,42 +976,43 @@ class EnergyMeter extends EventEmitter {
975
976
 
976
977
  try {
977
978
  const powerAndEnergy = [];
978
- const dataArr = [
979
+ const powerAndEnergyTypeArr = [
979
980
  { type: 'production', state: this.feature.meters.production.enabled },
980
- { type: 'consumptionNet', state: this.feature.meters.consumptionNet.enabled },
981
- { type: 'consumptionTotal', state: this.feature.meters.consumptionTotal.enabled }
981
+ { type: 'net-consumption', state: this.feature.meters.consumptionNet.enabled },
982
+ { type: 'total-consumption', state: this.feature.meters.consumptionTotal.enabled }
982
983
  ];
983
984
 
984
- for (const [index, data] of dataArr.entries()) {
985
- const { type: key, state: meterEnabled } = data;
985
+ for (const [index, data] of powerAndEnergyTypeArr.entries()) {
986
+ const { type: meterType, state: meterEnabled } = data;
987
+ if (meterType !== 'production' && !meterEnabled) continue;
986
988
 
987
- if (key !== 'production' && !meterEnabled) continue;
988
-
989
- let sourceMeter, sourceEnergy, measurementType;
990
- let power;
989
+ const key = MetersKeyMap[meterType];
990
+ const measurementType = ApiCodes[meterType];
991
991
 
992
+ let sourceMeter, sourceEnergy;
993
+ let power, energyLifetime;
992
994
  switch (key) {
993
995
  case 'production': {
994
- measurementType = 'Production';
995
996
  const sourcePcu = this.pv.powerAndEnergy[key].pcu;
996
997
  const sourceEim = this.pv.powerAndEnergy[key].eim;
997
998
  sourceMeter = meterEnabled ? this.pv.meters.find(m => m.measurementType === 'production') : sourcePcu;
998
999
  sourceEnergy = meterEnabled ? sourceEim : sourcePcu;
999
1000
  power = this.functions.isValidValue(sourceMeter.power) ? sourceMeter.power : null;
1001
+ energyLifetime = this.functions.isValidValue(sourceMeter.energyLifetime) ? sourceMeter.energyLifetime / 1000 : null;
1000
1002
  break;
1001
1003
  }
1002
1004
  case 'consumptionNet': {
1003
- measurementType = 'Consumption Net';
1004
1005
  sourceMeter = this.pv.meters.find(m => m.measurementType === 'net-consumption');
1005
1006
  sourceEnergy = this.pv.powerAndEnergy.consumptionNet;
1006
1007
  power = this.functions.isValidValue(sourceMeter.power) ? sourceMeter.power : null;
1008
+ energyLifetime = this.functions.isValidValue(sourceMeter.energyLifetime) ? sourceMeter.energyLifetime / 1000 : null;
1007
1009
  break;
1008
1010
  }
1009
1011
  case 'consumptionTotal': {
1010
- measurementType = 'Consumption Total';
1011
1012
  sourceMeter = this.pv.meters.find(m => m.measurementType === 'total-consumption');
1012
1013
  sourceEnergy = this.pv.powerAndEnergy.consumptionTotal;
1013
1014
  power = this.functions.isValidValue(sourceMeter.power) ? sourceMeter.power : null;
1015
+ energyLifetime = this.functions.isValidValue(sourceMeter.energyLifetime) ? sourceMeter.energyLifetime / 1000 : null;
1014
1016
  break;
1015
1017
  }
1016
1018
  }
@@ -1027,12 +1029,20 @@ class EnergyMeter extends EventEmitter {
1027
1029
  type,
1028
1030
  measurementType,
1029
1031
  power,
1032
+ energyLifetime,
1030
1033
  gridQualityState: meterEnabled,
1031
1034
  };
1032
1035
 
1036
+ // Add to fakegato history
1037
+ this.fakegatoHistoryService?.addEntry({
1038
+ time: Math.floor(Date.now() / 1000),
1039
+ power: power
1040
+ });
1041
+
1033
1042
  // Create characteristics energy meter
1034
1043
  const characteristics = [
1035
- { type: Characteristic.EveCurrentConsumption, value: obj.power },
1044
+ { type: Characteristic.EvePower, value: obj.power },
1045
+ { type: Characteristic.EveEnergyLifetime, value: obj.energyLifetime },
1036
1046
  ];
1037
1047
 
1038
1048
  // Create characteristics energy meter
@@ -1054,12 +1064,6 @@ class EnergyMeter extends EventEmitter {
1054
1064
  this.energyMeterServices?.[index]?.updateCharacteristic(type, value);
1055
1065
  };
1056
1066
 
1057
- // FakeGato history per energy meter service
1058
- this.fakegatoHistoryService?.addEntry({
1059
- time: Math.floor(Date.now() / 1000),
1060
- power: obj.power
1061
- });
1062
-
1063
1067
  powerAndEnergy.push(obj);
1064
1068
  }
1065
1069
  }
@@ -1097,6 +1101,7 @@ class EnergyMeter extends EventEmitter {
1097
1101
  const accessoryUUID = AccessoryUUID.generate(envoySerialNumber + 'Energy Meter');
1098
1102
  const accessoryCategory = Categories.SENSOR;
1099
1103
  const accessory = new Accessory(accessoryName, accessoryUUID, accessoryCategory);
1104
+ accessory.log = this.log;
1100
1105
 
1101
1106
  // Accessory Info Service
1102
1107
  if (this.logDebug) this.emit('debug', `Prepare Information Service`);
@@ -1106,31 +1111,33 @@ class EnergyMeter extends EventEmitter {
1106
1111
  .setCharacteristic(Characteristic.SerialNumber, envoySerialNumber ?? 'Serial Number')
1107
1112
  .setCharacteristic(Characteristic.FirmwareRevision, this.pv.info.software?.replace(/[a-zA-Z]/g, '') ?? '0');
1108
1113
 
1114
+ // Create FakeGatoHistory
1115
+ if (this.logDebug) this.emit('debug', `Prepare Fakegato Service`);
1116
+ this.fakegatoHistoryService = new this.fakegatoHistory(`energy`, accessory, {
1117
+ storage: 'fs',
1118
+ disableRepeatLastData: true,
1119
+ disableTimer: false,
1120
+ path: this.prefDir,
1121
+ filename: this.energyMeterHistoryFileName
1122
+ })
1123
+ this.fakegatoHistoryService.addEntry({
1124
+ time: Math.floor(Date.now() / 1000),
1125
+ power: this.pv.powerAndEnergy.data[0].power
1126
+ });
1127
+
1109
1128
  // Energy Meter Service
1110
1129
  this.energyMeterServices = [];
1111
1130
  for (const source of this.pv.powerAndEnergy.data) {
1112
1131
  const measurementType = source.measurementType;
1113
1132
 
1114
- // Create FakeGatoHistory
1115
- if (this.logDebug) this.emit('debug', `Prepare Fakegato ${measurementType} Service`);
1116
- this.fakegatoHistoryService = new this.fakegatoHistory(`energy`, accessory, {
1117
- log: this.log,
1118
- storage: 'fs',
1119
- disableRepeatLastData: true,
1120
- disableTimer: false
1121
- })
1122
- this.fakegatoHistoryService.addEntry({
1123
- time: Math.floor(Date.now() / 1000),
1124
- power: source.power
1125
- });
1126
-
1127
1133
  if (this.logDebug) this.emit('debug', `Prepare Meter ${measurementType} Service`);
1128
1134
  const energyMeterService = accessory.addService(Service.EvePowerMeter, `Energy Meter ${measurementType}`, `energyMeterService${measurementType}`);
1129
1135
  energyMeterService.setCharacteristic(Characteristic.ConfiguredName, `Energy Meter ${measurementType}`);
1130
1136
 
1131
1137
  // Create characteristics
1132
1138
  const characteristics = [
1133
- { type: Characteristic.EveCurrentConsumption, label: 'power', value: source.power, unit: 'W' },
1139
+ { type: Characteristic.EvePower, label: 'power', value: source.power, unit: 'W' },
1140
+ { type: Characteristic.EveEnergyLifetime, label: 'energy lifetime', value: source.energyLifetime, unit: 'kWh' },
1134
1141
  ];
1135
1142
 
1136
1143
  if (source.gridQualityState) {
@@ -1151,6 +1158,20 @@ class EnergyMeter extends EventEmitter {
1151
1158
  });
1152
1159
  }
1153
1160
 
1161
+ energyMeterService.getCharacteristic(Characteristic.EveResetTime)
1162
+ .onGet(async () => {
1163
+ const resetTime = this.lastReset;
1164
+ if (this.logInfo) this.emit('info', `${measurementType}, reset time: ${resetTime}`);
1165
+ return resetTime;
1166
+ })
1167
+ .onSet(async (value) => {
1168
+ try {
1169
+ this.lastReset = value;
1170
+ } catch (error) {
1171
+ if (this.logWarn) this.emit('warn', `${measurementType}, Reset time error: ${error}`);
1172
+ }
1173
+ });
1174
+
1154
1175
  this.energyMeterServices.push(energyMeterService);
1155
1176
  }
1156
1177