homebridge-enphase-envoy 10.3.1-beta.0 → 10.3.1-beta.10
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/package.json +3 -3
- package/src/constants.js +0 -4
- package/src/customcharacteristics.js +16 -0
- package/src/envoydata.js +30 -31
- package/src/envoydevice.js +36 -27
- package/src/functions.js +24 -3
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.3.1-beta.
|
|
5
|
+
"version": "10.3.1-beta.10",
|
|
6
6
|
"description": "Homebridge p7ugin for Photovoltaic Energy System manufactured by Enphase.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "grzegorz914",
|
|
@@ -31,12 +31,12 @@
|
|
|
31
31
|
"LICENSE"
|
|
32
32
|
],
|
|
33
33
|
"engines": {
|
|
34
|
-
"homebridge": "^1.9.0 || ^2.0.0 || ^2.0.0-beta.30 || ^2.0.0-alpha.
|
|
34
|
+
"homebridge": "^1.9.0 || ^2.0.0 || ^2.0.0-beta.30 || ^2.0.0-alpha.60",
|
|
35
35
|
"node": "^20 || ^22 || ^24"
|
|
36
36
|
},
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"async-mqtt": "^2.6.3",
|
|
39
|
-
"axios": "^1.
|
|
39
|
+
"axios": "^1.13.1",
|
|
40
40
|
"express": "^5.1.0",
|
|
41
41
|
"fast-xml-parser": "^5.3.0",
|
|
42
42
|
"fakegato-history": "^0.6.7"
|
package/src/constants.js
CHANGED
|
@@ -174,13 +174,10 @@ export const ApiCodes = {
|
|
|
174
174
|
"ENCHG_STATE_DISCHARGING": "Encharge state discharging",
|
|
175
175
|
"ENCHG_STATE_IDLE": "Encharge state idle",
|
|
176
176
|
"ENCHG_STATE_READY": "Encharge state ready",
|
|
177
|
-
"ENCMN_MDE_BMU_READY": "Encharge BMU ready",
|
|
178
177
|
"ENCMN_MDE_ENCHARGE_READY": "Encharge mode ready",
|
|
179
178
|
"ENCMN_MDE_ON_GRID": "Encharge mode on grid",
|
|
180
179
|
"ENCMN_MDE_OFF_GRID": "Encharge mode off grid",
|
|
181
|
-
"ENCMN_MDE_PCU_READY": "Encharge Microinverter ready",
|
|
182
180
|
"ENCMN_C6_CC_READY": "C6 Combiner Controller ready",
|
|
183
|
-
"ENCMN_C6_RGM_DEV_CONNECTED": "C6 Revenue Grade Meter connected",
|
|
184
181
|
"ENPOWER": "Enpower",
|
|
185
182
|
"ENS_DEVICE_STATE_READY": "Ensemble state ready",
|
|
186
183
|
"ENPWR_STATE_GRIDMODE_CONFIRM": "Enpower state grid mode confirm",
|
|
@@ -205,7 +202,6 @@ export const ApiCodes = {
|
|
|
205
202
|
"check-wiring": "Check Wiring",
|
|
206
203
|
"close": "Close",
|
|
207
204
|
"closed": "Closed",
|
|
208
|
-
"configured": "Configured",
|
|
209
205
|
"connected": "Connected",
|
|
210
206
|
"consumption": "Consumption Net",
|
|
211
207
|
"discharging": "Discharging",
|
|
@@ -1554,6 +1554,22 @@ export default (api) => {
|
|
|
1554
1554
|
}
|
|
1555
1555
|
Characteristic.EncAggSoc = EncAggSoc;
|
|
1556
1556
|
|
|
1557
|
+
class EncAggRatedPower extends Characteristic {
|
|
1558
|
+
constructor() {
|
|
1559
|
+
super('ENC rated power', '00000208-000B-1000-8000-0026BB765291');
|
|
1560
|
+
this.setProps({
|
|
1561
|
+
format: Formats.FLOAT,
|
|
1562
|
+
unit: 'kW',
|
|
1563
|
+
maxValue: 1000,
|
|
1564
|
+
minValue: -1000,
|
|
1565
|
+
minStep: 0.001,
|
|
1566
|
+
perms: [Perms.PAIRED_READ, Perms.NOTIFY]
|
|
1567
|
+
});
|
|
1568
|
+
this.value = this.getDefaultValue();
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
Characteristic.EncAggRatedPower = EncAggRatedPower;
|
|
1572
|
+
|
|
1557
1573
|
class EncAggBackupEnergy extends Characteristic {
|
|
1558
1574
|
constructor() {
|
|
1559
1575
|
super('ENC backup energy', '00000209-000B-1000-8000-0026BB765291');
|
package/src/envoydata.js
CHANGED
|
@@ -338,6 +338,7 @@ class EnvoyData extends EventEmitter {
|
|
|
338
338
|
devices: [],
|
|
339
339
|
settings: {},
|
|
340
340
|
tariff: {},
|
|
341
|
+
tariffRaw: {},
|
|
341
342
|
ratedPowerSumKw: null,
|
|
342
343
|
realPowerSumKw: null,
|
|
343
344
|
phaseA: false,
|
|
@@ -412,7 +413,7 @@ class EnvoyData extends EventEmitter {
|
|
|
412
413
|
.on('updateEnsemble', () => this.handleWithLock('updateEnsemble', async () => {
|
|
413
414
|
const updateEnsemble = this.feature.ensemble.inventory.supported ? await this.updateEnsembleInventory() : false;
|
|
414
415
|
if (updateEnsemble && this.feature.ensemble.status.supported) await this.updateEnsembleStatus();
|
|
415
|
-
if (updateEnsemble && this.feature.
|
|
416
|
+
if (updateEnsemble && this.feature.inventory.esubs.encharges.power.supported) await this.updateEnsemblePower();
|
|
416
417
|
|
|
417
418
|
const updateEnchargeSettings = updateEnsemble && this.feature.inventory.esubs.encharges.settings.supported ? await this.updateEnchargesSettings() : false;
|
|
418
419
|
if (updateEnchargeSettings && this.feature.inventory.esubs.encharges.tariff.supported) await this.updateTariff();
|
|
@@ -587,13 +588,12 @@ class EnvoyData extends EventEmitter {
|
|
|
587
588
|
// Load token from file on startup, only if mode is 1
|
|
588
589
|
if (this.envoyFirmware7xxTokenGenerationMode === 1 && start) {
|
|
589
590
|
try {
|
|
590
|
-
const data = await this.functions.readData(this.envoyTokenFile);
|
|
591
|
+
const data = await this.functions.readData(this.envoyTokenFile, true);
|
|
591
592
|
try {
|
|
592
|
-
const
|
|
593
|
-
const fileTokenExist = parsedData.token ? 'Exist' : 'Missing';
|
|
593
|
+
const fileTokenExist = data.token ? 'Exist' : 'Missing';
|
|
594
594
|
if (this.logDebug) this.emit('debug', `Token from file: ${fileTokenExist}`);
|
|
595
|
-
if (
|
|
596
|
-
this.feature.info.jwtToken =
|
|
595
|
+
if (data.token) {
|
|
596
|
+
this.feature.info.jwtToken = data;
|
|
597
597
|
}
|
|
598
598
|
} catch (error) {
|
|
599
599
|
if (this.logWarn) this.emit('warn', `Token parse error: ${error}`);
|
|
@@ -1962,7 +1962,7 @@ class EnvoyData extends EventEmitter {
|
|
|
1962
1962
|
};
|
|
1963
1963
|
|
|
1964
1964
|
// Calculate encharges rated power summary in kW
|
|
1965
|
-
this.pv.inventory.esubs.encharges.ratedPowerSumKw = enchargesRatedPowerSummary.length > 0 ? enchargesRatedPowerSummary.reduce((total, num) => total + num, 0) / 1000 : null;
|
|
1965
|
+
this.pv.inventory.esubs.encharges.ratedPowerSumKw = enchargesRatedPowerSummary.length > 0 ? (enchargesRatedPowerSummary.reduce((total, num) => total + num, 0) / enchargesRatedPowerSummary.length) / 1000 : null;
|
|
1966
1966
|
}
|
|
1967
1967
|
|
|
1968
1968
|
// Update enpowers statuses if installed
|
|
@@ -2038,17 +2038,18 @@ class EnvoyData extends EventEmitter {
|
|
|
2038
2038
|
|
|
2039
2039
|
try {
|
|
2040
2040
|
const response = await this.axiosInstance.get(ApiUrls.EnsemblePower);
|
|
2041
|
-
const responseData = response.data
|
|
2041
|
+
const responseData = response.data;
|
|
2042
2042
|
if (this.logDebug) this.emit('debug', `Ensemble power response:`, responseData);
|
|
2043
2043
|
|
|
2044
|
-
const devices = responseData.devices
|
|
2045
|
-
if (devices.length === 0) return false;
|
|
2044
|
+
const devices = responseData.devices ?? [];
|
|
2045
|
+
if (!devices.length === 0) return false;
|
|
2046
2046
|
|
|
2047
2047
|
// update encharges
|
|
2048
2048
|
const enchargesRealPowerSummary = [];
|
|
2049
2049
|
const encharges = this.pv.inventory.esubs.encharges.devices || [];
|
|
2050
|
-
for (const
|
|
2051
|
-
const
|
|
2050
|
+
for (const device of devices) {
|
|
2051
|
+
const serialNumber = device.serial_num;
|
|
2052
|
+
const encharge = encharges.find(device => device.serialNumber === serialNumber);
|
|
2052
2053
|
if (this.logDebug) this.emit('debug', `Ensemble device power:`, device);
|
|
2053
2054
|
if (!device) continue;
|
|
2054
2055
|
|
|
@@ -2059,12 +2060,12 @@ class EnvoyData extends EventEmitter {
|
|
|
2059
2060
|
soc: device.soc,
|
|
2060
2061
|
};
|
|
2061
2062
|
|
|
2062
|
-
this.feature.inventory.esubs.encharges.power.supported = true;
|
|
2063
2063
|
if (this.functions.isValidValue(encharge.power.realPower)) enchargesRealPowerSummary.push(encharge.power.realPower);
|
|
2064
|
+
this.feature.inventory.esubs.encharges.power.supported = true;
|
|
2064
2065
|
}
|
|
2065
2066
|
|
|
2066
2067
|
// Calculate encharges real power summary in kW
|
|
2067
|
-
this.pv.inventory.esubs.encharges.realPowerSumKw = enchargesRealPowerSummary.length > 0 ? enchargesRealPowerSummary.reduce((total, num) => total + num, 0) /
|
|
2068
|
+
this.pv.inventory.esubs.encharges.realPowerSumKw = enchargesRealPowerSummary.length > 0 ? (enchargesRealPowerSummary.reduce((total, num) => total + num, 0) / enchargesRealPowerSummary.length) / 1000 : null;
|
|
2068
2069
|
|
|
2069
2070
|
// ensemble power supported
|
|
2070
2071
|
this.feature.ensemble.power.supported = true;
|
|
@@ -2090,14 +2091,15 @@ class EnvoyData extends EventEmitter {
|
|
|
2090
2091
|
const enchargesSettingsSupported = 'enc_settings' in enchargesSettings;
|
|
2091
2092
|
if (!enchargesSettingsSupported) return false;
|
|
2092
2093
|
|
|
2093
|
-
const settings =
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2094
|
+
const settings = enchargesSettings.enc_settings;
|
|
2095
|
+
const encharges = this.pv.inventory.esubs.encharges;
|
|
2096
|
+
encharges.settings = {
|
|
2097
|
+
enable: settings.enable, // boolean
|
|
2098
|
+
country: settings.country, // string
|
|
2099
|
+
currentLimit: settings.current_limit, // float
|
|
2100
|
+
perPhase: settings.per_phase // boolean
|
|
2098
2101
|
};
|
|
2099
2102
|
|
|
2100
|
-
this.pv.inventory.esubs.encharges.settings = settings;
|
|
2101
2103
|
this.feature.inventory.esubs.encharges.settings.supported = true;
|
|
2102
2104
|
|
|
2103
2105
|
// RESTFul and MQTT update
|
|
@@ -2116,11 +2118,12 @@ class EnvoyData extends EventEmitter {
|
|
|
2116
2118
|
try {
|
|
2117
2119
|
const response = await this.axiosInstance.get(ApiUrls.TariffSettingsGetPut);
|
|
2118
2120
|
const tariffSettings = response.data;
|
|
2121
|
+
|
|
2119
2122
|
if (this.logDebug) this.emit('debug', 'Tariff:', tariffSettings);
|
|
2120
2123
|
|
|
2121
2124
|
const enchargesTariffSupported = 'tariff' in tariffSettings;
|
|
2122
2125
|
if (!enchargesTariffSupported) return false;
|
|
2123
|
-
|
|
2126
|
+
this.pv.inventory.esubs.encharges.tariffRaw = tariffSettings;
|
|
2124
2127
|
this.pv.inventory.esubs.encharges.tariff = tariffSettings;
|
|
2125
2128
|
this.feature.inventory.esubs.encharges.tariff.supported = true;
|
|
2126
2129
|
|
|
@@ -2545,7 +2548,7 @@ class EnvoyData extends EventEmitter {
|
|
|
2545
2548
|
if (this.logDebug) this.emit('debug', `Requesting set encharge settings`);
|
|
2546
2549
|
|
|
2547
2550
|
try {
|
|
2548
|
-
const tariff = this.pv.inventory.esubs.encharges.
|
|
2551
|
+
const tariff = this.pv.inventory.esubs.encharges.tariffRaw.tariff;
|
|
2549
2552
|
tariff.storage_settings.mode = profile;
|
|
2550
2553
|
tariff.storage_settings.reserved_soc = reservedSoc;
|
|
2551
2554
|
tariff.storage_settings.charge_from_grid = chargeFromGrid;
|
|
@@ -2771,16 +2774,12 @@ class EnvoyData extends EventEmitter {
|
|
|
2771
2774
|
const getEnsemble = tokenRequired && this.feature.inventory.esubs.supported ? await this.updateEnsembleInventory() : false;
|
|
2772
2775
|
if (getEnsemble) {
|
|
2773
2776
|
await this.updateEnsembleStatus();
|
|
2774
|
-
if (this.feature.inventory.esubs.encharges.installed)
|
|
2775
|
-
|
|
2776
|
-
|
|
2777
|
-
await this.updateTariff();
|
|
2778
|
-
}
|
|
2777
|
+
if (this.feature.inventory.esubs.encharges.installed) await this.updateEnsemblePower();
|
|
2778
|
+
const getEnchargeSettings = this.feature.inventory.esubs.encharges.installed ? await this.updateEnchargesSettings() : false;
|
|
2779
|
+
if (getEnchargeSettings) await this.updateTariff();
|
|
2779
2780
|
|
|
2780
|
-
|
|
2781
|
-
|
|
2782
|
-
await this.updateDryContactsSettings();
|
|
2783
|
-
}
|
|
2781
|
+
const getDryContacts = this.feature.inventory.esubs.enpowers.installed ? await this.updateDryContacts() : false;
|
|
2782
|
+
if (getDryContacts) await this.updateDryContactsSettings();
|
|
2784
2783
|
|
|
2785
2784
|
const getGenerator = await this.updateGenerator();
|
|
2786
2785
|
if (getGenerator && this.feature.inventory.esubs.generator.installed) await this.updateGeneratorSettings();
|
package/src/envoydevice.js
CHANGED
|
@@ -1988,8 +1988,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
1988
1988
|
}
|
|
1989
1989
|
|
|
1990
1990
|
if (ensemblesCountersSupported) characteristics.push({ type: Characteristic.RestPower, label: 'rest power', value: counters.restPowerKw, unit: 'kW' });
|
|
1991
|
-
if (enchargesStatusSupported) characteristics.push({ type: Characteristic.RatedPower, label: 'rated power', value: this.pv.inventoryData.esubs.
|
|
1992
|
-
if (enchargesPowerSupported) characteristics.push({ type: Characteristic.RealPower, label: 'real power', value: this.pv.inventoryData.esubs.
|
|
1991
|
+
if (enchargesStatusSupported) characteristics.push({ type: Characteristic.RatedPower, label: 'rated power', value: this.pv.inventoryData.esubs.ratedPowerSumKw, unit: 'kW' });
|
|
1992
|
+
if (enchargesPowerSupported) characteristics.push({ type: Characteristic.RealPower, label: 'real power', value: this.pv.inventoryData.esubs.realPowerSumKw, unit: 'kW' });
|
|
1993
1993
|
|
|
1994
1994
|
for (const { type, label, value, unit = '', postfix = '' } of characteristics) {
|
|
1995
1995
|
if (!this.functions.isValidValue(value)) continue;
|
|
@@ -2257,14 +2257,22 @@ class EnvoyDevice extends EventEmitter {
|
|
|
2257
2257
|
{ type: Characteristic.ReadingTime, label: 'reading time', value: encharge.readingTime },
|
|
2258
2258
|
];
|
|
2259
2259
|
|
|
2260
|
-
if (gridProfileSupported)
|
|
2260
|
+
if (gridProfileSupported) {
|
|
2261
|
+
characteristics.push(
|
|
2262
|
+
{ type: Characteristic.GridProfile, label: 'grid profile', value: encharge.gridProfile }
|
|
2263
|
+
);
|
|
2264
|
+
}
|
|
2265
|
+
|
|
2261
2266
|
if (enchargesStatusSupported && encharge.status) {
|
|
2262
2267
|
characteristics.push(
|
|
2263
2268
|
{ type: Characteristic.CommInterface, label: 'comm interface', value: encharge.status.commInterfaceStr },
|
|
2264
2269
|
{ type: Characteristic.RatedPower, label: 'rated power', value: encharge.status.ratedPowerKw, unit: 'kW' }
|
|
2265
2270
|
);
|
|
2266
2271
|
}
|
|
2267
|
-
|
|
2272
|
+
|
|
2273
|
+
if (enchargesPowerSupported && encharge.power) {
|
|
2274
|
+
characteristics.push({ type: Characteristic.RealPower, label: 'real power', value: encharge.power.realPowerKw, unit: 'kW' });
|
|
2275
|
+
}
|
|
2268
2276
|
|
|
2269
2277
|
for (const { type, label, value, unit = '', postfix = '' } of characteristics) {
|
|
2270
2278
|
if (!this.functions.isValidValue(value)) continue;
|
|
@@ -2391,23 +2399,24 @@ class EnvoyDevice extends EventEmitter {
|
|
|
2391
2399
|
if (this.logDebug) this.emit('debug', `Prepare ${enchargeName} Profile Sensor Services`);
|
|
2392
2400
|
|
|
2393
2401
|
this.enchargeProfileSensorsServices = [];
|
|
2402
|
+
|
|
2394
2403
|
for (let i = 0; i < this.enchargeProfileSensors.length; i++) {
|
|
2395
2404
|
const sensor = this.enchargeProfileSensors[i];
|
|
2396
2405
|
const { namePrefix, name, serviceType, characteristicType } = sensor;
|
|
2397
2406
|
const serviceName = namePrefix ? `${accessoryName} ${name}` : name;
|
|
2398
2407
|
|
|
2399
|
-
const
|
|
2400
|
-
|
|
2401
|
-
|
|
2408
|
+
const service = accessory.addService(serviceType, serviceName, `enchargeProfileSensorService${i}`);
|
|
2409
|
+
service.addOptionalCharacteristic(Characteristic.ConfiguredName);
|
|
2410
|
+
service.setCharacteristic(Characteristic.ConfiguredName, serviceName);
|
|
2402
2411
|
|
|
2403
|
-
|
|
2412
|
+
service.getCharacteristic(characteristicType)
|
|
2404
2413
|
.onGet(async () => {
|
|
2405
2414
|
const currentState = sensor.state;
|
|
2406
2415
|
if (this.logInfo) this.emit('info', `${enchargeName} profile: ${name}, state: ${currentState ? 'Active' : 'Not Active'}`);
|
|
2407
2416
|
return currentState;
|
|
2408
2417
|
});
|
|
2409
2418
|
|
|
2410
|
-
this.enchargeProfileSensorsServices.push(
|
|
2419
|
+
this.enchargeProfileSensorsServices.push(service);
|
|
2411
2420
|
}
|
|
2412
2421
|
}
|
|
2413
2422
|
}
|
|
@@ -2686,7 +2695,7 @@ class EnvoyDevice extends EventEmitter {
|
|
|
2686
2695
|
{ type: Characteristic.AdminState, label: 'admin state', value: collar.adminStateStr },
|
|
2687
2696
|
{ type: Characteristic.Status, label: 'status', value: collar.deviceStatus },
|
|
2688
2697
|
{ type: Characteristic.MidState, label: 'mid state', value: collar.midState },
|
|
2689
|
-
{ type: Characteristic.GridState, label: '
|
|
2698
|
+
{ type: Characteristic.GridState, label: 'mid state', value: collar.gridState },
|
|
2690
2699
|
{ type: Characteristic.Communicating, label: 'communicating', value: collar.communicating, postfix: collar.communicating ? 'Yes' : 'No' },
|
|
2691
2700
|
{ type: Characteristic.Temperature, label: 'temperature', value: collar.temperature, unit: '°C' },
|
|
2692
2701
|
{ type: Characteristic.ReadingTime, label: 'reading time', value: collar.readingTime }
|
|
@@ -3622,7 +3631,7 @@ class EnvoyDevice extends EventEmitter {
|
|
|
3622
3631
|
};
|
|
3623
3632
|
|
|
3624
3633
|
if (this.logDebug) {
|
|
3625
|
-
this.emit('debug', `Q-
|
|
3634
|
+
this.emit('debug', `Q-Rela state:`, nsrbData.relay);
|
|
3626
3635
|
this.emit('debug', `Q-Relay lines:`, nsrbData.linesCount);
|
|
3627
3636
|
}
|
|
3628
3637
|
|
|
@@ -4326,10 +4335,10 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4326
4335
|
// Add to ensemble summary characteristics if live data not supported
|
|
4327
4336
|
if (!this.feature.liveData.supported || !this.feature.meters.storage.enabled) {
|
|
4328
4337
|
ensembleSummaryCharacteristics.push(
|
|
4329
|
-
{ type: Characteristic.AggSoc, value: secctrl.aggSoc },
|
|
4330
4338
|
{ type: Characteristic.AggMaxEnergy, value: secctrl.aggMaxEnergyKw },
|
|
4331
|
-
{ type: Characteristic.
|
|
4332
|
-
{ type: Characteristic.
|
|
4339
|
+
{ type: Characteristic.EncAggBackupEnergy, value: secctrl.encAggBackupEnergy },
|
|
4340
|
+
{ type: Characteristic.AggSoc, value: secctrl.aggSoc },
|
|
4341
|
+
{ type: Characteristic.encAggSoc, value: secctrl.encAggSoc });
|
|
4333
4342
|
}
|
|
4334
4343
|
|
|
4335
4344
|
if (phaseA) {
|
|
@@ -4827,8 +4836,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4827
4836
|
const info = tariffData.tariff ?? {};
|
|
4828
4837
|
const tariff = {};
|
|
4829
4838
|
tariff.info = {
|
|
4830
|
-
currencyCode: info.currency.code,
|
|
4831
|
-
logger: info.logger,
|
|
4839
|
+
currencyCode: info.currency.code ?? '',
|
|
4840
|
+
logger: info.logger ?? '',
|
|
4832
4841
|
date: this.functions.formatTimestamp(info.date, this.pv.homeData.timeZone),
|
|
4833
4842
|
};
|
|
4834
4843
|
|
|
@@ -4836,7 +4845,7 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4836
4845
|
const s = info.storage_settings ?? {};
|
|
4837
4846
|
tariff.storageSettings = {
|
|
4838
4847
|
mode: s.mode,
|
|
4839
|
-
operationModeSubType: s.operation_mode_sub_type,
|
|
4848
|
+
operationModeSubType: s.operation_mode_sub_type ?? '',
|
|
4840
4849
|
reservedSoc: s.reserved_soc,
|
|
4841
4850
|
veryLowSoc: s.very_low_soc,
|
|
4842
4851
|
chargeFromGrid: !!s.charge_from_grid,
|
|
@@ -4883,16 +4892,16 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4883
4892
|
// Schedule
|
|
4884
4893
|
const sched = tariffData.schedule ?? {};
|
|
4885
4894
|
tariff.schedule = {
|
|
4886
|
-
fileName: sched.filename,
|
|
4887
|
-
source: sched.source,
|
|
4895
|
+
fileName: sched.filename ?? '',
|
|
4896
|
+
source: sched.source ?? '',
|
|
4888
4897
|
date: this.functions.formatTimestamp(sched.date, this.pv.homeData.timeZone),
|
|
4889
|
-
version: sched.version,
|
|
4898
|
+
version: sched.version ?? '',
|
|
4890
4899
|
reservedSoc: sched.reserved_soc,
|
|
4891
4900
|
veryLowSoc: sched.very_low_soc,
|
|
4892
4901
|
chargeFromGrid: !!sched.charge_from_grid,
|
|
4893
|
-
battMode: sched.batt_mode,
|
|
4894
|
-
batteryMode: sched.battery_mode,
|
|
4895
|
-
operationModeSubType: sched.operation_mode_sub_type,
|
|
4902
|
+
battMode: sched.batt_mode ?? '',
|
|
4903
|
+
batteryMode: sched.battery_mode ?? '',
|
|
4904
|
+
operationModeSubType: sched.operation_mode_sub_type ?? '',
|
|
4896
4905
|
override: !!sched.override,
|
|
4897
4906
|
overrideBackupSoc: sched.override_backup_soc,
|
|
4898
4907
|
overrideChgDischargeRate: sched.override_chg_discharge_rate,
|
|
@@ -5065,8 +5074,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
5065
5074
|
gridActionBool: settings.gridAction !== 'none',
|
|
5066
5075
|
microGridAction: settings.microGridAction,
|
|
5067
5076
|
genAction: settings.genAction,
|
|
5068
|
-
essentialStartTime: settings.essentialStartTime,
|
|
5069
|
-
essentialEndTime: settings.essentialEndTime,
|
|
5077
|
+
essentialStartTime: settings.essentialStartTime ?? '',
|
|
5078
|
+
essentialEndTime: settings.essentialEndTime ?? '',
|
|
5070
5079
|
priority: settings.priority,
|
|
5071
5080
|
blackSStart: settings.blackSStart,
|
|
5072
5081
|
override: settings.override ?? 'false',
|
|
@@ -5584,8 +5593,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
5584
5593
|
|
|
5585
5594
|
// Agg Energy and Soc
|
|
5586
5595
|
const characteristics = [
|
|
5587
|
-
{ type: Characteristic.AggSoc, value: percentFullSum, valueKey: 'aggSoc' },
|
|
5588
5596
|
{ type: Characteristic.AggMaxEnergy, value: energySumKw, valueKey: 'aggMaxEnergyKw' },
|
|
5597
|
+
{ type: Characteristic.AggSoc, value: percentFullSum, valueKey: 'aggSoc' },
|
|
5589
5598
|
];
|
|
5590
5599
|
|
|
5591
5600
|
// Update storage summary services
|
|
@@ -5654,8 +5663,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
5654
5663
|
// Update ensemble summary service
|
|
5655
5664
|
if (this.feature.inventory.esubs.secctrl.supported) {
|
|
5656
5665
|
const characteristics = [
|
|
5657
|
-
{ type: Characteristic.EncAggSoc, value: percentFullSumEnc, valueKey: 'encAggSoc' },
|
|
5658
5666
|
{ type: Characteristic.EncAggBackupEnergy, value: energySumEncKw, valueKey: 'encAggBackupEnergy' },
|
|
5667
|
+
{ type: Characteristic.EncAggSoc, value: percentFullSumEnc, valueKey: 'encAggSoc' },
|
|
5659
5668
|
];
|
|
5660
5669
|
|
|
5661
5670
|
// Update storage summary services
|
package/src/functions.js
CHANGED
|
@@ -17,12 +17,33 @@ class Functions {
|
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
async readData(path) {
|
|
20
|
+
async readData(path, parseJson = false) {
|
|
21
21
|
try {
|
|
22
|
-
const data = await fsPromises.readFile(path);
|
|
22
|
+
const data = await fsPromises.readFile(path, 'utf8');
|
|
23
|
+
|
|
24
|
+
if (parseJson) {
|
|
25
|
+
if (!data.trim()) {
|
|
26
|
+
// Empty file when expecting JSON
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(data);
|
|
31
|
+
} catch (jsonError) {
|
|
32
|
+
throw new Error(`JSON parse error in file "${path}": ${jsonError.message}`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// For non-JSON, just return file content (can be empty string)
|
|
23
37
|
return data;
|
|
24
38
|
} catch (error) {
|
|
25
|
-
|
|
39
|
+
if (error.code === 'ENOENT') {
|
|
40
|
+
// File does not exist
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
// Preserve original error details
|
|
44
|
+
const wrappedError = new Error(`Read data error for "${path}": ${error.message}`);
|
|
45
|
+
wrappedError.original = error;
|
|
46
|
+
throw wrappedError;
|
|
26
47
|
}
|
|
27
48
|
}
|
|
28
49
|
|