homebridge-enphase-envoy 10.2.0-beta.21 → 10.2.0-beta.211
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 +2 -0
- package/README.md +5 -2
- package/config.schema.json +32 -33
- package/index.js +138 -112
- package/package.json +3 -2
- package/src/constants.js +5 -0
- package/src/customcharacteristics.js +27 -13
- package/src/energymeter.js +1517 -0
- package/src/envoydevice.js +1526 -2281
package/CHANGELOG.md
CHANGED
|
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
13
13
|
|
|
14
14
|
## Changes
|
|
15
15
|
|
|
16
|
+
- fix encharge profile control UI interface
|
|
17
|
+
- added to encharge profile controls option to allow charge from grid
|
|
16
18
|
- fix [#206](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/206)
|
|
17
19
|
- fix [#205](https://github.com/grzegorz914/homebridge-enphase-envoy/issues/205)
|
|
18
20
|
- refactor code of ensemble section
|
package/README.md
CHANGED
|
@@ -111,6 +111,7 @@ The `homebridge-enphase-envoy` plugin integrates Enphase Envoy solar energy moni
|
|
|
111
111
|
| `envoyTokenInstaller` | | boolean | Enable if you are using the installer token |
|
|
112
112
|
| `lockControl` | | boolean | Enables auto lock control accessory |
|
|
113
113
|
| `lockControlPrefix` | | boolean | Use accessory name for prefix |
|
|
114
|
+
| `energyMeter` | | boolean | Enables energy meter as a axtra accessory to display charts in EVE app |
|
|
114
115
|
| `productionStateSensor` | | key | `Production State Sensor` for production state monitoring |
|
|
115
116
|
| | `name` | string | Accessory name for Home app |
|
|
116
117
|
| | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Motion Sensor, `2` - Occupancy Sensor, `3` - Contact Sensor |
|
|
@@ -220,6 +221,8 @@ The `homebridge-enphase-envoy` plugin integrates Enphase Envoy solar energy moni
|
|
|
220
221
|
| | `name` | string | Accessory name for Home app |
|
|
221
222
|
| | `profile` | string | Profile: `Savings`, `Economy`, `Full Backup`, `Self Consumption` |
|
|
222
223
|
| | `displayType` | number | Accessory type to be displayed in Home app: `0` - None/Disabled, `1` - Lightbulb |
|
|
224
|
+
| | `chargeFromGrid` | boolean | Allow charge from grid |
|
|
225
|
+
| | `namePrefix` | boolean | Use accessory name for prefix |
|
|
223
226
|
| `enchargeProfileSensors` | | key | `Encharge Profile Sensors` for monitoring. If the `Profile` matches, the contact was opened. |
|
|
224
227
|
| | `name` | string | Accessory name for Home app |
|
|
225
228
|
| | `profile` | string | Profile: `Savings`, `Economy`, `Full Backup`, `Self Consumption` |
|
|
@@ -317,7 +320,7 @@ Path `status` response all available paths.
|
|
|
317
320
|
| POST | `http//ip:port` | `DataSampling` | `true`, `false` | boolean | Data sampling Start/Stop |
|
|
318
321
|
| | `http//ip:port` | `PowerProductionState` | `true`, `false` | boolean | Production state On/Off |
|
|
319
322
|
| | `http//ip:port` | `PlcLevel` | `true` | boolean | Check Plc Level On |
|
|
320
|
-
| | `http//ip:port` | `EnchargeProfile` | `self-consumption`, `savings`, `economy`, `
|
|
323
|
+
| | `http//ip:port` | `EnchargeProfile` | `self-consumption`, `savings-mode`, `economy`, `backup` | string | Set encharge profile |
|
|
321
324
|
| | `http//ip:port` | `EnpowerGridState` | `true`, `false` | boolean | Grid state On/Off |
|
|
322
325
|
| | `http//ip:port` | `GeneratorMode` | `off`, `on`, `auto` | string | Generator mode Off/On/Auto |
|
|
323
326
|
|
|
@@ -334,6 +337,6 @@ Subscribe using JSON `{ "EnchargeProfile": "savings" }`
|
|
|
334
337
|
| Subscribe | `Set` | `DataSampling` | `true`, `false` | boolean | Data sampling Start/Stop |
|
|
335
338
|
| | `Set` | `ProductionState` | `true`, `false` | boolean | Production state On/Off |
|
|
336
339
|
| | `Set` | `PlcLevel` | `true` | boolean | Check Plc Level On |
|
|
337
|
-
| | `Set` | `EnchargeProfile` | `self-consumption`, `savings`, `economy`, `
|
|
340
|
+
| | `Set` | `EnchargeProfile` | `self-consumption`, `savings-mode`, `economy`, `backup` | string | Set encharge profile |
|
|
338
341
|
| | `Set` | `EnpowerGridState` | `true`, `false` | boolean | Grid state On/Off |
|
|
339
342
|
| | `Set` | `GeneratorMode` | `off`, `on`, `auto` | string | Generator mode Off/On/Auto |
|
package/config.schema.json
CHANGED
|
@@ -170,6 +170,13 @@
|
|
|
170
170
|
"functionBody": "return model.devices[arrayIndices].lockControl === true"
|
|
171
171
|
}
|
|
172
172
|
},
|
|
173
|
+
"energyMeter": {
|
|
174
|
+
"title": "Energy Meter",
|
|
175
|
+
"type": "boolean",
|
|
176
|
+
"default": false,
|
|
177
|
+
"description": "Enables energy meter as a axtra accessory to display charts in EVE app",
|
|
178
|
+
"required": false
|
|
179
|
+
},
|
|
173
180
|
"productionStateSensor": {
|
|
174
181
|
"title": "Production State Sensor",
|
|
175
182
|
"type": "object",
|
|
@@ -2057,7 +2064,7 @@
|
|
|
2057
2064
|
"default": "backup",
|
|
2058
2065
|
"oneOf": [
|
|
2059
2066
|
{
|
|
2060
|
-
"title": "Savings",
|
|
2067
|
+
"title": "Savings Mode",
|
|
2061
2068
|
"enum": [
|
|
2062
2069
|
"savings-mode"
|
|
2063
2070
|
]
|
|
@@ -2079,23 +2086,18 @@
|
|
|
2079
2086
|
"enum": [
|
|
2080
2087
|
"self-consumption"
|
|
2081
2088
|
]
|
|
2082
|
-
},
|
|
2083
|
-
{
|
|
2084
|
-
"title": "Grid Tied",
|
|
2085
|
-
"enum": [
|
|
2086
|
-
"grid-tied"
|
|
2087
|
-
]
|
|
2088
|
-
},
|
|
2089
|
-
{
|
|
2090
|
-
"title": "Grid Forming",
|
|
2091
|
-
"enum": [
|
|
2092
|
-
"grid-forming"
|
|
2093
|
-
]
|
|
2094
2089
|
}
|
|
2095
2090
|
],
|
|
2096
2091
|
"description": "Here select the profile.",
|
|
2097
2092
|
"required": true
|
|
2098
2093
|
},
|
|
2094
|
+
"chargeFromGrid": {
|
|
2095
|
+
"title": "Charge From Grid",
|
|
2096
|
+
"type": "boolean",
|
|
2097
|
+
"default": false,
|
|
2098
|
+
"description": "Here allow charge from grid",
|
|
2099
|
+
"required": false
|
|
2100
|
+
},
|
|
2099
2101
|
"namePrefix": {
|
|
2100
2102
|
"title": "Prefix",
|
|
2101
2103
|
"type": "boolean",
|
|
@@ -2160,7 +2162,7 @@
|
|
|
2160
2162
|
"default": "backup",
|
|
2161
2163
|
"oneOf": [
|
|
2162
2164
|
{
|
|
2163
|
-
"title": "Savings",
|
|
2165
|
+
"title": "Savings Mode",
|
|
2164
2166
|
"enum": [
|
|
2165
2167
|
"savings-mode"
|
|
2166
2168
|
]
|
|
@@ -2182,18 +2184,6 @@
|
|
|
2182
2184
|
"enum": [
|
|
2183
2185
|
"self-consumption"
|
|
2184
2186
|
]
|
|
2185
|
-
},
|
|
2186
|
-
{
|
|
2187
|
-
"title": "Grid Tied",
|
|
2188
|
-
"enum": [
|
|
2189
|
-
"grid-tied"
|
|
2190
|
-
]
|
|
2191
|
-
},
|
|
2192
|
-
{
|
|
2193
|
-
"title": "Grid Forming",
|
|
2194
|
-
"enum": [
|
|
2195
|
-
"grid-forming"
|
|
2196
|
-
]
|
|
2197
2187
|
}
|
|
2198
2188
|
],
|
|
2199
2189
|
"description": "Here select the profile.",
|
|
@@ -3383,8 +3373,7 @@
|
|
|
3383
3373
|
"key": "devices[]",
|
|
3384
3374
|
"title": "Envoy",
|
|
3385
3375
|
"items": [
|
|
3386
|
-
"devices[].
|
|
3387
|
-
"devices[].lockControlPrefix",
|
|
3376
|
+
"devices[].energyMeter",
|
|
3388
3377
|
{
|
|
3389
3378
|
"key": "devices[]",
|
|
3390
3379
|
"type": "tabarray",
|
|
@@ -3465,6 +3454,15 @@
|
|
|
3465
3454
|
]
|
|
3466
3455
|
}
|
|
3467
3456
|
]
|
|
3457
|
+
},
|
|
3458
|
+
{
|
|
3459
|
+
"key": "devices[]",
|
|
3460
|
+
"type": "section",
|
|
3461
|
+
"title": "System Control",
|
|
3462
|
+
"items": [
|
|
3463
|
+
"devices[].lockControl",
|
|
3464
|
+
"devices[].lockControlPrefix"
|
|
3465
|
+
]
|
|
3468
3466
|
}
|
|
3469
3467
|
]
|
|
3470
3468
|
}
|
|
@@ -4025,14 +4023,15 @@
|
|
|
4025
4023
|
"expanded": false,
|
|
4026
4024
|
"items": [
|
|
4027
4025
|
{
|
|
4028
|
-
"key": "devices[].
|
|
4026
|
+
"key": "devices[].enchargeProfileControls",
|
|
4029
4027
|
"type": "tabarray",
|
|
4030
4028
|
"title": "{{ value.name || 'control' }}",
|
|
4031
4029
|
"items": [
|
|
4032
|
-
"devices[].
|
|
4033
|
-
"devices[].
|
|
4034
|
-
"devices[].
|
|
4035
|
-
"devices[].
|
|
4030
|
+
"devices[].enchargeProfileControls[].displayType",
|
|
4031
|
+
"devices[].enchargeProfileControls[].name",
|
|
4032
|
+
"devices[].enchargeProfileControls[].profile",
|
|
4033
|
+
"devices[].enchargeProfileControls[].chargeFromGrid",
|
|
4034
|
+
"devices[].enchargeProfileControls[].namePrefix"
|
|
4036
4035
|
]
|
|
4037
4036
|
}
|
|
4038
4037
|
]
|
package/index.js
CHANGED
|
@@ -1,21 +1,23 @@
|
|
|
1
1
|
import { join } from 'path';
|
|
2
2
|
import { mkdirSync, existsSync, writeFileSync } from 'fs';
|
|
3
3
|
import EnvoyDevice from './src/envoydevice.js';
|
|
4
|
+
import EnergyMeter from './src/energymeter.js';
|
|
4
5
|
import ImpulseGenerator from './src/impulsegenerator.js';
|
|
5
6
|
import { PluginName, PlatformName } from './src/constants.js';
|
|
6
7
|
import CustomCharacteristics from './src/customcharacteristics.js';
|
|
8
|
+
import fakegato from 'fakegato-history';
|
|
7
9
|
|
|
8
10
|
class EnvoyPlatform {
|
|
9
11
|
constructor(log, config, api) {
|
|
10
|
-
// only load if configured
|
|
11
12
|
if (!config || !Array.isArray(config.devices)) {
|
|
12
13
|
log.warn(`No configuration found for ${PluginName}.`);
|
|
13
14
|
return;
|
|
14
15
|
}
|
|
15
|
-
this.accessories = [];
|
|
16
16
|
|
|
17
|
+
this.log = log;
|
|
18
|
+
this.accessories = [];
|
|
19
|
+
this.FakeGatoHistoryService = fakegato(api);
|
|
17
20
|
|
|
18
|
-
//check if prefs directory exist
|
|
19
21
|
const prefDir = join(api.user.storagePath(), 'enphaseEnvoy');
|
|
20
22
|
try {
|
|
21
23
|
mkdirSync(prefDir, { recursive: true });
|
|
@@ -25,146 +27,170 @@ class EnvoyPlatform {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
api.on('didFinishLaunching', async () => {
|
|
28
|
-
let i =
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
//check accessory is enabled
|
|
30
|
+
for (let i = 0; i < config.devices.length; i++) {
|
|
31
|
+
const device = config.devices[i];
|
|
32
32
|
const displayType = device.displayType || 0;
|
|
33
|
-
if (displayType === 0)
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
33
|
+
if (displayType === 0) continue;
|
|
36
34
|
|
|
37
35
|
const deviceName = device.name;
|
|
38
|
-
const host = device.host || (i ===
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
const host = device.host || (i === 0 ? 'envoy.local' : `envoy-${i + 1}.local`);
|
|
37
|
+
const {
|
|
38
|
+
envoyFirmware7xxTokenGenerationMode = 0,
|
|
39
|
+
envoyPasswd,
|
|
40
|
+
envoyToken,
|
|
41
|
+
envoyTokenInstaller = false,
|
|
42
|
+
enlightenUser,
|
|
43
|
+
enlightenPasswd,
|
|
44
|
+
enableDebugMode = false,
|
|
45
|
+
disableLogDeviceInfo = false,
|
|
46
|
+
disableLogInfo = false,
|
|
47
|
+
disableLogSuccess = false,
|
|
48
|
+
disableLogWarn = false,
|
|
49
|
+
disableLogError = false
|
|
50
|
+
} = device;
|
|
51
|
+
|
|
47
52
|
if (!deviceName) {
|
|
48
|
-
log.warn(`Device: ${host}
|
|
49
|
-
|
|
53
|
+
log.warn(`Device: ${host}, Name missing.`);
|
|
54
|
+
continue;
|
|
50
55
|
}
|
|
51
56
|
|
|
52
57
|
if (envoyFirmware7xxTokenGenerationMode === 1 && (!enlightenUser || !enlightenPasswd)) {
|
|
53
|
-
log.warn(`Device: ${host} ${deviceName},
|
|
54
|
-
|
|
58
|
+
log.warn(`Device: ${host} ${deviceName}, missing Enlighten credentials.`);
|
|
59
|
+
continue;
|
|
55
60
|
}
|
|
56
61
|
|
|
57
62
|
if (envoyFirmware7xxTokenGenerationMode === 2 && !envoyToken) {
|
|
58
|
-
log.warn(`Device: ${host} ${deviceName}, Envoy
|
|
59
|
-
|
|
63
|
+
log.warn(`Device: ${host} ${deviceName}, missing Envoy token.`);
|
|
64
|
+
continue;
|
|
60
65
|
}
|
|
61
66
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
envoyToken: 'removed',
|
|
74
|
-
enlightenPasswd: 'removed',
|
|
75
|
-
mqtt: {
|
|
76
|
-
...device.mqtt,
|
|
77
|
-
passwd: 'removed'
|
|
78
|
-
}
|
|
79
|
-
};
|
|
80
|
-
const debug1 = !enableDebugMode ? false : log.info(`Device: ${host} ${deviceName}, Config: ${JSON.stringify(config, null, 2)}.`);
|
|
67
|
+
if (enableDebugMode) {
|
|
68
|
+
log.info(`Device: ${host} ${deviceName}, did finish launching.`);
|
|
69
|
+
const redactedConfig = JSON.stringify({
|
|
70
|
+
...device,
|
|
71
|
+
envoyPasswd: 'removed',
|
|
72
|
+
envoyToken: 'removed',
|
|
73
|
+
enlightenPasswd: 'removed',
|
|
74
|
+
mqtt: { ...device.mqtt, passwd: 'removed' }
|
|
75
|
+
}, null, 2);
|
|
76
|
+
log.info(`Device: ${host} ${deviceName}, Config: ${redactedConfig}`);
|
|
77
|
+
}
|
|
81
78
|
|
|
82
|
-
//check files exists, if not then create it
|
|
83
79
|
const postFix = host.split('.').join('');
|
|
84
80
|
const envoyIdFile = join(prefDir, `envoyId_${postFix}`);
|
|
85
81
|
const envoyTokenFile = join(prefDir, `envoyToken_${postFix}`);
|
|
82
|
+
const energyMeterHistory = join(prefDir, `energyMeterHistory_${postFix}`);
|
|
86
83
|
|
|
87
84
|
try {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
envoyTokenFile,
|
|
91
|
-
];
|
|
92
|
-
|
|
93
|
-
files.forEach((file) => {
|
|
94
|
-
if (!existsSync(file)) {
|
|
95
|
-
writeFileSync(file, '0');
|
|
96
|
-
}
|
|
85
|
+
[envoyIdFile, envoyTokenFile].forEach(file => {
|
|
86
|
+
if (!existsSync(file)) writeFileSync(file, '0');
|
|
97
87
|
});
|
|
98
88
|
} catch (error) {
|
|
99
|
-
|
|
100
|
-
|
|
89
|
+
if (!disableLogError) log.error(`Device: ${host} ${deviceName}, File init error: ${error}`);
|
|
90
|
+
continue;
|
|
101
91
|
}
|
|
102
92
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
93
|
+
const devicesClass = device.energyMeter ? [EnvoyDevice, EnergyMeter] : [EnvoyDevice];
|
|
94
|
+
for (const [index, DeviceClass] of devicesClass.entries()) {
|
|
95
|
+
try {
|
|
96
|
+
const accessoryName = index === 0 ? deviceName : 'Energy Meter';
|
|
97
|
+
const envoyDevice = new DeviceClass(
|
|
98
|
+
api,
|
|
99
|
+
log,
|
|
100
|
+
accessoryName,
|
|
101
|
+
host,
|
|
102
|
+
displayType,
|
|
103
|
+
envoyFirmware7xxTokenGenerationMode,
|
|
104
|
+
envoyPasswd,
|
|
105
|
+
envoyToken,
|
|
106
|
+
envoyTokenInstaller,
|
|
107
|
+
enlightenUser,
|
|
108
|
+
enlightenPasswd,
|
|
109
|
+
envoyIdFile,
|
|
110
|
+
envoyTokenFile,
|
|
111
|
+
device,
|
|
112
|
+
energyMeterHistory,
|
|
113
|
+
index === 1 ? this.FakeGatoHistoryService : undefined
|
|
114
|
+
);
|
|
115
|
+
|
|
116
|
+
this.attachEventHandlers(api, envoyDevice, log, {
|
|
117
|
+
host,
|
|
118
|
+
deviceName: accessoryName,
|
|
119
|
+
enableDebugMode,
|
|
120
|
+
disableLogDeviceInfo,
|
|
121
|
+
disableLogInfo,
|
|
122
|
+
disableLogSuccess,
|
|
123
|
+
disableLogWarn,
|
|
124
|
+
disableLogError
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
const impulseGenerator = new ImpulseGenerator();
|
|
128
|
+
let lock = false;
|
|
129
|
+
|
|
130
|
+
impulseGenerator
|
|
131
|
+
.on('start', async () => {
|
|
132
|
+
if (lock) return;
|
|
133
|
+
lock = true;
|
|
134
|
+
try {
|
|
135
|
+
const started = await envoyDevice.start();
|
|
136
|
+
if (started) {
|
|
137
|
+
await impulseGenerator.stop();
|
|
138
|
+
await envoyDevice.startImpulseGenerator();
|
|
139
|
+
}
|
|
140
|
+
} catch (error) {
|
|
141
|
+
if (!disableLogError) log.error(`Device: ${host} ${accessoryName}, ${error}, retrying.`);
|
|
142
|
+
} finally {
|
|
143
|
+
lock = false;
|
|
144
|
+
}
|
|
145
|
+
})
|
|
146
|
+
.on('state', state => {
|
|
147
|
+
if (enableDebugMode) log.info(`Device: ${host} ${accessoryName}, Impulse generator ${state ? 'started' : 'stopped'}.`);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
await impulseGenerator.start([{ name: 'start', sampling: 60000 }]);
|
|
151
|
+
} catch (error) {
|
|
152
|
+
log.error(`Device: ${host} ${deviceName}, Initialization error: ${error}`);
|
|
153
|
+
}
|
|
155
154
|
}
|
|
156
|
-
i++;
|
|
157
155
|
}
|
|
158
|
-
})
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
attachEventHandlers(api, envoyDevice, log, { host, deviceName, enableDebugMode, disableLogDeviceInfo, disableLogInfo, disableLogSuccess, disableLogWarn, disableLogError }) {
|
|
160
|
+
envoyDevice
|
|
161
|
+
.on('publishAccessory', accessory => {
|
|
162
|
+
api.publishExternalAccessories(PluginName, [accessory]);
|
|
163
|
+
if (!disableLogSuccess) log.success(`Device: ${host} ${deviceName}, Published as external accessory.`);
|
|
164
|
+
})
|
|
165
|
+
.on('devInfo', devInfo => {
|
|
166
|
+
if (!disableLogDeviceInfo) log.info(devInfo);
|
|
167
|
+
})
|
|
168
|
+
.on('success', msg => {
|
|
169
|
+
if (!disableLogSuccess) log.success(`Device: ${host} ${deviceName}, ${msg}`);
|
|
170
|
+
})
|
|
171
|
+
.on('info', msg => {
|
|
172
|
+
if (!disableLogInfo) log.info(`Device: ${host} ${deviceName}, ${msg}`);
|
|
173
|
+
})
|
|
174
|
+
.on('debug', (msg, data) => {
|
|
175
|
+
if (enableDebugMode) log.info(`Device: ${host} ${deviceName}, debug: ${data ? `${msg} ${JSON.stringify(data, null, 2)}` : msg}`);
|
|
176
|
+
})
|
|
177
|
+
.on('warn', msg => {
|
|
178
|
+
if (!disableLogWarn) log.warn(`Device: ${host} ${deviceName}, ${msg}`);
|
|
179
|
+
})
|
|
180
|
+
.on('error', error => {
|
|
181
|
+
if (!disableLogError) log.error(`Device: ${host} ${deviceName}, ${error}`);
|
|
182
|
+
});
|
|
159
183
|
}
|
|
160
184
|
|
|
161
185
|
configureAccessory(accessory) {
|
|
186
|
+
accessory.log = this.log;
|
|
187
|
+
this.loggingService = new fakegato('energy', accessory, 4032);
|
|
162
188
|
this.accessories.push(accessory);
|
|
163
189
|
}
|
|
164
190
|
}
|
|
165
191
|
|
|
166
192
|
export default (api) => {
|
|
167
|
-
//import and register custom characteristics
|
|
168
193
|
CustomCharacteristics(api);
|
|
169
194
|
api.registerPlatform(PluginName, PlatformName, EnvoyPlatform);
|
|
170
|
-
}
|
|
195
|
+
};
|
|
196
|
+
|
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.0-beta.
|
|
5
|
+
"version": "10.2.0-beta.211",
|
|
6
6
|
"description": "Homebridge plugin for Photovoltaic Energy System manufactured by Enphase.",
|
|
7
7
|
"license": "MIT",
|
|
8
8
|
"author": "grzegorz914",
|
|
@@ -38,7 +38,8 @@
|
|
|
38
38
|
"async-mqtt": "^2.6.3",
|
|
39
39
|
"axios": "^1.10.0",
|
|
40
40
|
"express": "^5.1.0",
|
|
41
|
-
"fast-xml-parser": "^5.2.5"
|
|
41
|
+
"fast-xml-parser": "^5.2.5",
|
|
42
|
+
"fakegato-history": "^0.6.7"
|
|
42
43
|
},
|
|
43
44
|
"keywords": [
|
|
44
45
|
"homebridge",
|
package/src/constants.js
CHANGED
|
@@ -160,6 +160,10 @@ export const PartNumbers = {
|
|
|
160
160
|
|
|
161
161
|
export const ApiCodes = {
|
|
162
162
|
"unknown": "Unknown",
|
|
163
|
+
"backup": "Full backup",
|
|
164
|
+
"economy": "Economy",
|
|
165
|
+
"savings-mode": "Savings",
|
|
166
|
+
"self-consumption": "Self consumption",
|
|
163
167
|
"on": "On",
|
|
164
168
|
"off": "Off",
|
|
165
169
|
"auto": "Auto",
|
|
@@ -211,6 +215,7 @@ export const ApiCodes = {
|
|
|
211
215
|
"ENCHG_STATE_IDLE": "Encharge state idle",
|
|
212
216
|
"ENCHG_STATE_CHARGING": "Encharge state charging",
|
|
213
217
|
"ENCHG_STATE_DISCHARGING": "Encharge state discharging",
|
|
218
|
+
"StorageTouMode_DEFAULT_TOU_MODE": "Default tou mode",
|
|
214
219
|
"ready": "Ready",
|
|
215
220
|
"idle": "Idle",
|
|
216
221
|
"full": "Full",
|
|
@@ -2126,7 +2126,7 @@ export default (api) => {
|
|
|
2126
2126
|
Service.LiveDataService = LiveDataService;
|
|
2127
2127
|
|
|
2128
2128
|
// EVE electric meter
|
|
2129
|
-
class
|
|
2129
|
+
class EveCurrentConsumption extends Characteristic {
|
|
2130
2130
|
constructor() {
|
|
2131
2131
|
super('Power', 'E863F10D-079E-48FF-8F27-9C2605A29F52');
|
|
2132
2132
|
this.setProps({
|
|
@@ -2140,23 +2140,23 @@ export default (api) => {
|
|
|
2140
2140
|
this.value = this.getDefaultValue();
|
|
2141
2141
|
}
|
|
2142
2142
|
}
|
|
2143
|
-
Characteristic.
|
|
2143
|
+
Characteristic.EveCurrentConsumption = EveCurrentConsumption;
|
|
2144
2144
|
|
|
2145
|
-
class
|
|
2145
|
+
class EveTotalConsumption extends Characteristic {
|
|
2146
2146
|
constructor() {
|
|
2147
2147
|
super('Energy', 'E863F10C-079E-48FF-8F27-9C2605A29F52');
|
|
2148
2148
|
this.setProps({
|
|
2149
2149
|
format: Formats.FLOAT,
|
|
2150
2150
|
unit: 'kWh',
|
|
2151
|
-
maxValue:
|
|
2152
|
-
minValue:
|
|
2151
|
+
maxValue: 4294967295,
|
|
2152
|
+
minValue: 0,
|
|
2153
2153
|
minStep: 0.001,
|
|
2154
2154
|
perms: [Perms.PAIRED_READ, Perms.NOTIFY]
|
|
2155
2155
|
});
|
|
2156
2156
|
this.value = this.getDefaultValue();
|
|
2157
2157
|
}
|
|
2158
2158
|
}
|
|
2159
|
-
Characteristic.
|
|
2159
|
+
Characteristic.EveTotalConsumption = EveTotalConsumption;
|
|
2160
2160
|
|
|
2161
2161
|
class EveVoltage extends Characteristic {
|
|
2162
2162
|
constructor() {
|
|
@@ -2174,7 +2174,7 @@ export default (api) => {
|
|
|
2174
2174
|
}
|
|
2175
2175
|
Characteristic.EveVoltage = EveVoltage;
|
|
2176
2176
|
|
|
2177
|
-
class
|
|
2177
|
+
class EveElectricCurrent extends Characteristic {
|
|
2178
2178
|
constructor() {
|
|
2179
2179
|
super('Current', 'E863F126-079E-48FF-8F27-9C2605A29F52');
|
|
2180
2180
|
this.setProps({
|
|
@@ -2188,20 +2188,34 @@ export default (api) => {
|
|
|
2188
2188
|
this.value = this.getDefaultValue();
|
|
2189
2189
|
}
|
|
2190
2190
|
}
|
|
2191
|
-
Characteristic.
|
|
2191
|
+
Characteristic.EveElectricCurrent = EveElectricCurrent;
|
|
2192
|
+
|
|
2193
|
+
class EveResetTime extends Characteristic {
|
|
2194
|
+
constructor() {
|
|
2195
|
+
super('Reset time', 'E863F112-079E-48FF-8F27-9C2605A29F52');
|
|
2196
|
+
this.setProps({
|
|
2197
|
+
format: Formats.UInt32,
|
|
2198
|
+
perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE, Perms.NOTIFY]
|
|
2199
|
+
});
|
|
2200
|
+
this.value = this.getDefaultValue();
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
Characteristic.EveResetTime = EveResetTime;
|
|
2204
|
+
|
|
2192
2205
|
|
|
2193
2206
|
// Eve Power‑Meter service
|
|
2194
|
-
class
|
|
2207
|
+
class EvePowerMeter extends Service {
|
|
2195
2208
|
constructor(displayName, subtype) {
|
|
2196
2209
|
super(displayName, 'E863F130-079E-48FF-8F27-9C2605A29F52', subtype);
|
|
2197
2210
|
// Mandatory Characteristics
|
|
2198
|
-
this.addCharacteristic(Characteristic.
|
|
2199
|
-
this.addCharacteristic(Characteristic.
|
|
2211
|
+
this.addCharacteristic(Characteristic.EveCurrentConsumption);
|
|
2212
|
+
this.addCharacteristic(Characteristic.EveTotalConsumption);
|
|
2200
2213
|
// Optional Characteristics
|
|
2201
2214
|
this.addOptionalCharacteristic(Characteristic.EveVoltage);
|
|
2202
|
-
this.addOptionalCharacteristic(Characteristic.
|
|
2215
|
+
this.addOptionalCharacteristic(Characteristic.EveElectricCurrent);
|
|
2216
|
+
this.addOptionalCharacteristic(Characteristic.EveResetTime);
|
|
2203
2217
|
this.addOptionalCharacteristic(Characteristic.ConfiguredName);
|
|
2204
2218
|
}
|
|
2205
2219
|
}
|
|
2206
|
-
Service.
|
|
2220
|
+
Service.EvePowerMeter = EvePowerMeter;
|
|
2207
2221
|
};
|