homebridge-enphase-envoy 10.3.1-beta.1 → 10.3.1-beta.11
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/config.schema.json +1 -3
- package/package.json +2 -2
- package/src/constants.js +0 -4
- package/src/customcharacteristics.js +16 -0
- package/src/envoydata.js +30 -31
- package/src/envoydevice.js +39 -36
- package/src/functions.js +24 -3
package/config.schema.json
CHANGED
|
@@ -1432,8 +1432,7 @@
|
|
|
1432
1432
|
]
|
|
1433
1433
|
}
|
|
1434
1434
|
],
|
|
1435
|
-
"description": "Accessory type for Home app"
|
|
1436
|
-
"required": true
|
|
1435
|
+
"description": "Accessory type for Home app"
|
|
1437
1436
|
},
|
|
1438
1437
|
"name": {
|
|
1439
1438
|
"title": "Accessory name",
|
|
@@ -3066,7 +3065,6 @@
|
|
|
3066
3065
|
]
|
|
3067
3066
|
}
|
|
3068
3067
|
],
|
|
3069
|
-
"required": true,
|
|
3070
3068
|
"condition": {
|
|
3071
3069
|
"functionBody": "return model.devices[arrayIndices[0]].generatorModeControls[arrayIndices[1]].displayType > 0;"
|
|
3072
3070
|
}
|
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.11",
|
|
6
6
|
"description": "Homebridge p7ugin for Photovoltaic Energy System manufactured by Enphase.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "grzegorz914",
|
|
@@ -36,7 +36,7 @@
|
|
|
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 }
|
|
@@ -3518,16 +3527,10 @@ class EnvoyDevice extends EventEmitter {
|
|
|
3518
3527
|
powerPeak: pcu.powerPeak,
|
|
3519
3528
|
});
|
|
3520
3529
|
|
|
3521
|
-
if (this.logInfo) {
|
|
3522
|
-
this.emit('info', `Microinverter, ${pcuData.serialNumber}, power: ${pcuData.power} W`);
|
|
3523
|
-
this.emit('info', `Microinverter, ${pcuData.serialNumber}, phase: ${pcuData.phase}`);
|
|
3524
|
-
}
|
|
3525
|
-
|
|
3526
3530
|
// Add characteristics
|
|
3527
3531
|
characteristics.push(
|
|
3528
3532
|
{ type: Characteristic.PowerW, value: pcuData.power },
|
|
3529
|
-
{ type: Characteristic.PowerPeakW, value: pcuData.powerPeak }
|
|
3530
|
-
);
|
|
3533
|
+
{ type: Characteristic.PowerPeakW, value: pcuData.powerPeak });
|
|
3531
3534
|
}
|
|
3532
3535
|
|
|
3533
3536
|
// Add detailed info if supported
|
|
@@ -3627,9 +3630,9 @@ class EnvoyDevice extends EventEmitter {
|
|
|
3627
3630
|
plcLevel: nsrb.plcLevel,
|
|
3628
3631
|
};
|
|
3629
3632
|
|
|
3630
|
-
if (this.
|
|
3631
|
-
this.emit('
|
|
3632
|
-
this.emit('
|
|
3633
|
+
if (this.logDebug) {
|
|
3634
|
+
this.emit('debug', `Q-Rela state:`, nsrbData.relay);
|
|
3635
|
+
this.emit('debug', `Q-Relay lines:`, nsrbData.linesCount);
|
|
3633
3636
|
}
|
|
3634
3637
|
|
|
3635
3638
|
// Create characteristics
|
|
@@ -4332,10 +4335,10 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4332
4335
|
// Add to ensemble summary characteristics if live data not supported
|
|
4333
4336
|
if (!this.feature.liveData.supported || !this.feature.meters.storage.enabled) {
|
|
4334
4337
|
ensembleSummaryCharacteristics.push(
|
|
4335
|
-
{ type: Characteristic.AggSoc, value: secctrl.aggSoc },
|
|
4336
4338
|
{ type: Characteristic.AggMaxEnergy, value: secctrl.aggMaxEnergyKw },
|
|
4337
|
-
{ type: Characteristic.
|
|
4338
|
-
{ type: Characteristic.
|
|
4339
|
+
{ type: Characteristic.EncAggBackupEnergy, value: secctrl.encAggBackupEnergy },
|
|
4340
|
+
{ type: Characteristic.AggSoc, value: secctrl.aggSoc },
|
|
4341
|
+
{ type: Characteristic.encAggSoc, value: secctrl.encAggSoc });
|
|
4339
4342
|
}
|
|
4340
4343
|
|
|
4341
4344
|
if (phaseA) {
|
|
@@ -4833,8 +4836,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4833
4836
|
const info = tariffData.tariff ?? {};
|
|
4834
4837
|
const tariff = {};
|
|
4835
4838
|
tariff.info = {
|
|
4836
|
-
currencyCode: info.currency.code,
|
|
4837
|
-
logger: info.logger,
|
|
4839
|
+
currencyCode: info.currency.code ?? '',
|
|
4840
|
+
logger: info.logger ?? '',
|
|
4838
4841
|
date: this.functions.formatTimestamp(info.date, this.pv.homeData.timeZone),
|
|
4839
4842
|
};
|
|
4840
4843
|
|
|
@@ -4842,7 +4845,7 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4842
4845
|
const s = info.storage_settings ?? {};
|
|
4843
4846
|
tariff.storageSettings = {
|
|
4844
4847
|
mode: s.mode,
|
|
4845
|
-
operationModeSubType: s.operation_mode_sub_type,
|
|
4848
|
+
operationModeSubType: s.operation_mode_sub_type ?? '',
|
|
4846
4849
|
reservedSoc: s.reserved_soc,
|
|
4847
4850
|
veryLowSoc: s.very_low_soc,
|
|
4848
4851
|
chargeFromGrid: !!s.charge_from_grid,
|
|
@@ -4889,16 +4892,16 @@ class EnvoyDevice extends EventEmitter {
|
|
|
4889
4892
|
// Schedule
|
|
4890
4893
|
const sched = tariffData.schedule ?? {};
|
|
4891
4894
|
tariff.schedule = {
|
|
4892
|
-
fileName: sched.filename,
|
|
4893
|
-
source: sched.source,
|
|
4895
|
+
fileName: sched.filename ?? '',
|
|
4896
|
+
source: sched.source ?? '',
|
|
4894
4897
|
date: this.functions.formatTimestamp(sched.date, this.pv.homeData.timeZone),
|
|
4895
|
-
version: sched.version,
|
|
4898
|
+
version: sched.version ?? '',
|
|
4896
4899
|
reservedSoc: sched.reserved_soc,
|
|
4897
4900
|
veryLowSoc: sched.very_low_soc,
|
|
4898
4901
|
chargeFromGrid: !!sched.charge_from_grid,
|
|
4899
|
-
battMode: sched.batt_mode,
|
|
4900
|
-
batteryMode: sched.battery_mode,
|
|
4901
|
-
operationModeSubType: sched.operation_mode_sub_type,
|
|
4902
|
+
battMode: sched.batt_mode ?? '',
|
|
4903
|
+
batteryMode: sched.battery_mode ?? '',
|
|
4904
|
+
operationModeSubType: sched.operation_mode_sub_type ?? '',
|
|
4902
4905
|
override: !!sched.override,
|
|
4903
4906
|
overrideBackupSoc: sched.override_backup_soc,
|
|
4904
4907
|
overrideChgDischargeRate: sched.override_chg_discharge_rate,
|
|
@@ -5071,8 +5074,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
5071
5074
|
gridActionBool: settings.gridAction !== 'none',
|
|
5072
5075
|
microGridAction: settings.microGridAction,
|
|
5073
5076
|
genAction: settings.genAction,
|
|
5074
|
-
essentialStartTime: settings.essentialStartTime,
|
|
5075
|
-
essentialEndTime: settings.essentialEndTime,
|
|
5077
|
+
essentialStartTime: settings.essentialStartTime ?? '',
|
|
5078
|
+
essentialEndTime: settings.essentialEndTime ?? '',
|
|
5076
5079
|
priority: settings.priority,
|
|
5077
5080
|
blackSStart: settings.blackSStart,
|
|
5078
5081
|
override: settings.override ?? 'false',
|
|
@@ -5590,8 +5593,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
5590
5593
|
|
|
5591
5594
|
// Agg Energy and Soc
|
|
5592
5595
|
const characteristics = [
|
|
5593
|
-
{ type: Characteristic.AggSoc, value: percentFullSum, valueKey: 'aggSoc' },
|
|
5594
5596
|
{ type: Characteristic.AggMaxEnergy, value: energySumKw, valueKey: 'aggMaxEnergyKw' },
|
|
5597
|
+
{ type: Characteristic.AggSoc, value: percentFullSum, valueKey: 'aggSoc' },
|
|
5595
5598
|
];
|
|
5596
5599
|
|
|
5597
5600
|
// Update storage summary services
|
|
@@ -5660,8 +5663,8 @@ class EnvoyDevice extends EventEmitter {
|
|
|
5660
5663
|
// Update ensemble summary service
|
|
5661
5664
|
if (this.feature.inventory.esubs.secctrl.supported) {
|
|
5662
5665
|
const characteristics = [
|
|
5663
|
-
{ type: Characteristic.EncAggSoc, value: percentFullSumEnc, valueKey: 'encAggSoc' },
|
|
5664
5666
|
{ type: Characteristic.EncAggBackupEnergy, value: energySumEncKw, valueKey: 'encAggBackupEnergy' },
|
|
5667
|
+
{ type: Characteristic.EncAggSoc, value: percentFullSumEnc, valueKey: 'encAggSoc' },
|
|
5665
5668
|
];
|
|
5666
5669
|
|
|
5667
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
|
|