homebridge-pvs6 1.3.0 → 1.5.0

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.
Files changed (37) hide show
  1. package/README.md +96 -6
  2. package/config.schema.json +97 -1
  3. package/dist/gridExportAccessory.d.ts +1 -0
  4. package/dist/gridExportAccessory.d.ts.map +1 -1
  5. package/dist/gridExportAccessory.js +4 -23
  6. package/dist/gridExportAccessory.js.map +1 -1
  7. package/dist/gridImportAccessory.d.ts +1 -0
  8. package/dist/gridImportAccessory.d.ts.map +1 -1
  9. package/dist/gridImportAccessory.js +4 -23
  10. package/dist/gridImportAccessory.js.map +1 -1
  11. package/dist/homeConsumptionAccessory.d.ts +1 -0
  12. package/dist/homeConsumptionAccessory.d.ts.map +1 -1
  13. package/dist/homeConsumptionAccessory.js +4 -23
  14. package/dist/homeConsumptionAccessory.js.map +1 -1
  15. package/dist/matterEnergy.d.ts +152 -0
  16. package/dist/matterEnergy.d.ts.map +1 -0
  17. package/dist/matterEnergy.js +263 -0
  18. package/dist/matterEnergy.js.map +1 -0
  19. package/dist/meterCharacteristics.d.ts +15 -0
  20. package/dist/meterCharacteristics.d.ts.map +1 -0
  21. package/dist/meterCharacteristics.js +71 -0
  22. package/dist/meterCharacteristics.js.map +1 -0
  23. package/dist/platform.d.ts +8 -0
  24. package/dist/platform.d.ts.map +1 -1
  25. package/dist/platform.js +112 -56
  26. package/dist/platform.js.map +1 -1
  27. package/dist/settings.d.ts +6 -0
  28. package/dist/settings.d.ts.map +1 -1
  29. package/dist/solarAccessory.d.ts +3 -1
  30. package/dist/solarAccessory.d.ts.map +1 -1
  31. package/dist/solarAccessory.js +28 -27
  32. package/dist/solarAccessory.js.map +1 -1
  33. package/dist/throttle.d.ts +53 -0
  34. package/dist/throttle.d.ts.map +1 -0
  35. package/dist/throttle.js +163 -0
  36. package/dist/throttle.js.map +1 -0
  37. package/package.json +3 -2
package/README.md CHANGED
@@ -1,4 +1,7 @@
1
1
  # homebridge-pvs6
2
+ [![License: MIT](https://img.shields.io/github/license/dacarson/homebridge-pvs6)](LICENSE)
3
+ [![Version](https://img.shields.io/github/v/release/dacarson/homebridge-pvs6)](https://github.com/dacarson/homebridge-pvs6/releases)
4
+ [![npm downloads](https://img.shields.io/npm/dt/homebridge-pvs6)](https://www.npmjs.com/package/homebridge-pvs6)
2
5
 
3
6
  A [Homebridge](https://homebridge.io) plugin for the [SunStrong PVS6](https://sunstrong.com) solar monitoring system. Exposes solar production and grid metering as **Eve Energy** accessories in Apple HomeKit, with real-time power, cumulative energy, and native Eve app history.
4
7
 
@@ -26,7 +29,7 @@ A [Homebridge](https://homebridge.io) plugin for the [SunStrong PVS6](https://su
26
29
  - Polls the PVS6 **local** FCGI API — no SunStrong Connect, no cloud dependency
27
30
  - **Auto-discovers** the PVS6 on your local network via mDNS — no IP address or serial number required in config
28
31
  - Automatically identifies production and consumption CT meters from the PVS6 device list
29
- - Designed to complement [homebridge-rainforest-eagle3](https://github.com/dacarson/homebridge-rainforest-eagle3) for a complete solar + grid picture in Apple Home
32
+ - Optional: live watts in the Apple Home **Energy** view via Matter (see [Apple Home Energy & Matter](#apple-home-energy--matter))
30
33
 
31
34
  ---
32
35
 
@@ -62,7 +65,7 @@ Grid Import and Grid Export are always registered together — enabling `accesso
62
65
 
63
66
  ## Requirements
64
67
 
65
- - [Homebridge](https://homebridge.io) v2.0 or later
68
+ - [Homebridge](https://homebridge.io) v2.0 or later (v2.3.0+ if you want the optional Apple Home Energy view via Matter)
66
69
  - Node.js 18 or later
67
70
  - SunStrong PVS6 on the same local network as your Homebridge host
68
71
 
@@ -132,6 +135,12 @@ Uncheck **Auto Discover** and supply the host and serial number directly. This s
132
135
  "host": "pvs.local",
133
136
  "serialNumber": "ZT231385000549A1234",
134
137
  "pollInterval": 10,
138
+ "matter": true,
139
+ "evePowerUpdates": "throttled",
140
+ "minChangeWatts": 25,
141
+ "minChangePercent": 2,
142
+ "minChangeKwh": 0.1,
143
+ "switchHoldSeconds": 60,
135
144
  "accessories": {
136
145
  "grid": true,
137
146
  "homeConsumption": true
@@ -154,6 +163,12 @@ Uncheck **Auto Discover** and supply the host and serial number directly. This s
154
163
  | `host` | string | no* | — | IP address or hostname of the PVS6. Used only when `autoDiscover` is `false` |
155
164
  | `serialNumber` | string | no* | — | Full PVS6 serial number. The last 5 characters are used as the API password. Used only when `autoDiscover` is `false` |
156
165
  | `pollInterval` | integer | no | `10` | Seconds between polls. Minimum enforced: `5` |
166
+ | `matter` | boolean | no | `false` | Also publish each enabled meter over Matter with live electrical measurements, so it shows watts on its tile in the Apple Home Energy view (see [Apple Home Energy & Matter](#apple-home-energy--matter)) |
167
+ | `evePowerUpdates` | string | no | `"throttled"` | How Eve Watts and Eve kWh are sent to HomeKit: `"throttled"`, `"pollOnly"` or `"live"`. See [HomeKit Updates & Automations](#homekit-updates--automations) |
168
+ | `minChangeWatts` | number | no | `25` | Throttled mode: push Eve Watts once it has changed by this many watts, or by `minChangePercent` if that is larger |
169
+ | `minChangePercent` | number | no | `2` | Throttled mode: push Eve Watts once it has changed by this percentage of the last value pushed |
170
+ | `minChangeKwh` | number | no | `0.1` | Throttled mode: push Eve kWh once it has changed by this much |
171
+ | `switchHoldSeconds` | integer | no | `60` | A power-derived On switch only changes once the new state has held this long. `0` disables the hold |
157
172
  | `accessories.grid` | boolean | no | `true` | Enable the Grid Import + Grid Export accessory pair. Set `false` to disable both |
158
173
  | `accessories.homeConsumption` | boolean | no | `false` | Enable the Home Consumption accessory. Opt-in; off by default |
159
174
  | `solarName` | string | no | `"Solar Production"` | HomeKit display name for the Solar Production accessory |
@@ -163,6 +178,35 @@ Uncheck **Auto Discover** and supply the host and serial number directly. This s
163
178
 
164
179
  \* Required when `autoDiscover` is `false`.
165
180
 
181
+ ### HomeKit Updates & Automations
182
+
183
+ The PVS6 is polled every ~10 seconds, and each reading differs from the last by a few watts. If every reading were pushed to HomeKit, each accessory's Eve Watts and Eve kWh values would send an event on every poll, adding up to about 1,000 events per hour. The settings below reduce that without breaking your automations.
184
+
185
+ #### Eve power and energy values (`evePowerUpdates`)
186
+
187
+ Eve Watts and Eve kWh are Eve custom characteristics. The Home app doesn't show them, but **Eve and Home+ automations can trigger on them** ("when power rises above 3 kW") **or check them as conditions**. Choose a mode with that in mind:
188
+
189
+ | Mode | What is pushed | Effect on automations |
190
+ |---|---|---|
191
+ | `throttled` (default) | Eve Watts when it changes by at least `max(minChangeWatts, minChangePercent%)` (defaults 25 W / 2%, so 25 W below 1,250 W and 2% above). Eve kWh when it changes by at least `minChangeKwh` (default 0.1 kWh). Either value is also pushed every 5 minutes, even if it hasn't changed much | Triggers and conditions keep working. Values are accurate to within the configured thresholds |
192
+ | `pollOnly` | Nothing. Event notifications are removed from these characteristics, and apps get the newest reading when they read the accessory | Lowest traffic, but **triggers on these values stop firing**. Use it only if no automation uses them |
193
+ | `live` | Every reading, on every poll | Original behaviour; highest traffic |
194
+
195
+ In every mode, reading an accessory returns the latest value, and the current values are reported as soon as the plugin starts.
196
+
197
+ #### On switches
198
+
199
+ Each accessory's **On** switch is a standard HomeKit characteristic. It always sends events, so Home app automations that use it keep working. To keep the switches from flickering at sunrise, at sunset, or when a cloud passes, each one is derived from power with:
200
+
201
+ - **a deadband:** it turns on above 50 W and off below 20 W
202
+ - **a hold:** a new state must last `switchHoldSeconds` (default 60) before it's reported. If power goes back first, the change is dropped. Set it to `0` to report changes on the next poll
203
+
204
+ Because of the hold, **automations triggered by these switches can fire up to `switchHoldSeconds` later** than the underlying change in power.
205
+
206
+ #### Logging
207
+
208
+ At debug level, each suppressed Eve update and each held or cancelled switch change is logged. Once an hour a single debug line reports how many updates were sent and how many were suppressed.
209
+
166
210
  ### Finding Your Serial Number
167
211
 
168
212
  The serial number is printed on the label on the PVS6 unit (format: `ZT...`). It is also visible in the SunStrong Connect app and is broadcast by the PVS6 itself via mDNS (which is how Auto Discover retrieves it). The last 5 characters are used as the local API login password — no separate password configuration is required.
@@ -175,7 +219,7 @@ The serial number is printed on the label on the PVS6 unit (format: `ZT...`). It
175
219
 
176
220
  | Characteristic | Source | Notes |
177
221
  |---|---|---|
178
- | On | `pv_p > 0` | True when panels are actively generating |
222
+ | On | `pv_p` | True when panels are generating: on above 50 W, off below 20 W, after the state has held for `switchHoldSeconds` |
179
223
  | OutletInUse | Always `true` | Required by Eve Energy |
180
224
  | Eve Watts | `pv_p × 1000` | Real-time solar output in Watts |
181
225
  | Eve kWh | `pv_en` | Lifetime generation in kWh |
@@ -184,7 +228,7 @@ The serial number is printed on the label on the PVS6 unit (format: `ZT...`). It
184
228
 
185
229
  | Characteristic | Source | Notes |
186
230
  |---|---|---|
187
- | On | `net_p > 0` | True when importing from grid |
231
+ | On | `max(0, net_p)` | True when importing from the grid: on above 50 W, off below 20 W, after the state has held for `switchHoldSeconds` |
188
232
  | OutletInUse | Always `true` | Required by Eve Energy |
189
233
  | Eve Watts | `max(0, net_p) × 1000` | Import watts; zero when net-exporting |
190
234
  | Eve kWh | `posLtea3phsumKwh` | Lifetime imported energy from consumption CT meter |
@@ -193,7 +237,7 @@ The serial number is printed on the label on the PVS6 unit (format: `ZT...`). It
193
237
 
194
238
  | Characteristic | Source | Notes |
195
239
  |---|---|---|
196
- | On | `net_p < 0` | True when net-exporting solar to the grid |
240
+ | On | `max(0, −net_p)` | True when net-exporting to the grid: on above 50 W, off below 20 W, after the state has held for `switchHoldSeconds` |
197
241
  | OutletInUse | Always `true` | Required by Eve Energy |
198
242
  | Eve Watts | `max(0, −net_p) × 1000` | Export watts; zero when importing |
199
243
  | Eve kWh | `negLtea3phsumKwh` | Lifetime exported energy from consumption CT meter |
@@ -204,7 +248,7 @@ Shows the total real-time load of the home and a derived lifetime consumption fi
204
248
 
205
249
  | Characteristic | Source | Notes |
206
250
  |---|---|---|
207
- | On | `site_load_p > 0` | True when the house is drawing power (always true in practice) |
251
+ | On | `site_load_p` | True when the house is drawing power (on above 50 W, off below 20 W, after the state has held for `switchHoldSeconds`; always on in practice) |
208
252
  | OutletInUse | Always `true` | Required by Eve Energy |
209
253
  | Eve Watts | `site_load_p × 1000` | Real-time site load in Watts |
210
254
  | Eve kWh | `pv_en + posLtea3phsumKwh − negLtea3phsumKwh` | Derived lifetime consumption — all solar generated, plus grid imported, minus grid exported |
@@ -213,6 +257,46 @@ The derived kWh formula is exact without a battery: solar energy either goes to
213
257
 
214
258
  ---
215
259
 
260
+ ## Apple Home Energy & Matter
261
+
262
+ <table>
263
+ <td>
264
+ <img width="600" alt="MatterEnergy" src="https://github.com/user-attachments/assets/fcff5f12-54cb-4431-a944-8ac04c6e044f" />
265
+ <br><sub>Apple Energy view with other Energy accessories</sub>
266
+ </td>
267
+ </table>
268
+
269
+ Apple Home's native **Energy** view is driven by **Matter** electrical-measurement clusters, **not** by classic HomeKit/HAP characteristics. HAP has no power or energy characteristic at all, so the Eve characteristics above (which only Eve-class apps read) can never populate it — no matter how the HomeKit accessory is shaped.
270
+
271
+ With `"matter": true`, this plugin publishes an **`ElectricalSensor`** Matter accessory for Solar Production and Grid, carrying live power and cumulative/periodic energy — no on/off, no controllable state, purely metering:
272
+
273
+ | Meter | Matter accessory | Matter power attribute | Matter energy attributes |
274
+ |---|---|---|---|
275
+ | Solar Production | "Solar Production" | `electricalPowerMeasurement.activePower` (always negative — see below) | `electricalEnergyMeasurement.cumulativeEnergyExported` |
276
+ | Grid | "Grid" | `electricalPowerMeasurement.activePower` (signed: positive = importing, negative = exporting) | `electricalEnergyMeasurement.cumulativeEnergyImported` **and** `cumulativeEnergyExported`, together |
277
+
278
+ Power is sent in milliwatts, energy in milliwatt-hours, per the Matter spec. Matter's `activePower` sign convention is positive = the accessory is *drawing* power, negative = it's *supplying* power — Solar Production only ever supplies (so its wattage is negated before being sent), and Grid does both depending on live direction.
279
+
280
+ **Home Consumption is intentionally not published over Matter.** Its energy is mathematically derived from the other two (`homeConsumptionKWh = pvEnergyKWh + gridImportKWh − gridExportKWh`, see [How It Works](#how-it-works)) rather than an independent measurement, so exposing all three to Apple Home's own aggregate power total risked double-counting rather than isolating grid draw. Home Consumption still works exactly as before in Eve/HomeKit.
281
+
282
+ **Grid Import and Grid Export stay two separate accessories in Eve/HomeKit** (see [HomeKit Accessories](#homekit-accessories) below) — that split exists only because Eve's custom Energy characteristic can't represent a negative wattage. Matter's `activePower` attribute *is* signed, so on the Matter side the grid meter is published as a single **"Grid"** accessory instead, with power flipping sign as the meter crosses between importing and exporting. Matter's cumulative/periodic *energy* attributes have no equivalent signed "net" value — Imported and Exported are always separate running totals per the Matter spec — so the Grid accessory reports both simultaneously on the one accessory rather than needing two.
283
+
284
+ **Why a pure sensor and not an outlet:** this device type has no on/off cluster, so its tile in the Home app shows "Not Supported" as its headline status — Home's tile face wants a primary characteristic (on/off, a reading, etc.) to display, and a pure measurement cluster doesn't provide one. An earlier version of this feature used Matter's `OnOffOutlet` device type specifically to get a tile headline (the same approach [homebridge-chargepoint](https://github.com/dacarson/homebridge-chargepoint) uses), at the cost of declaring a fake on/off state that couldn't actually be switched. That tradeoff was reversed: the tile headline isn't worth carrying dead on/off state for, as long as the wattage still rolls into the Home aggregate and — via periodic energy, below — into each accessory's own Energy-view attribution, which it does either way.
285
+
286
+ **Cumulative and periodic energy:** each meter reports both the lifetime total (`cumulativeEnergyImported`/`Exported`) and a periodic delta (`periodicEnergyImported`/`Exported`, at most once a minute) with its own start/end timestamps. The periodic figure is what drives Apple Home's per-device energy attribution in the Energy view, not the cumulative total alone.
287
+
288
+ Requirements:
289
+
290
+ - **Homebridge 2.3.0 or later**
291
+ - **Matter enabled on this plugin's child bridge** — in the Homebridge UI: plugin settings → **Bridge Settings** → enable Matter, then pair the Matter bridge in the Home app
292
+ - An Apple Home setup on **iOS/tvOS 26 or later** for the Energy view itself
293
+
294
+ If the Matter API isn't available (older Homebridge, or Matter not enabled), the plugin detects that, logs a single informational line, and continues to work exactly as before over HomeKit/Eve.
295
+
296
+ **Upgrading from an earlier version:** since this changes the Matter device type (and merges Grid Import/Export into one accessory), Apple Home will likely need the old Matter tiles removed and the Matter bridge re-paired to pick up the new endpoints cleanly.
297
+
298
+ ---
299
+
216
300
  ## Error Handling
217
301
 
218
302
  The plugin is designed to be resilient to transient PVS6 failures:
@@ -238,6 +322,12 @@ npm install
238
322
  npm run build
239
323
  ```
240
324
 
325
+ To run the unit tests:
326
+
327
+ ```bash
328
+ npm test
329
+ ```
330
+
241
331
  To develop with live rebuilds:
242
332
 
243
333
  ```bash
@@ -35,6 +35,75 @@
35
35
  "minimum": 5,
36
36
  "description": "How often to poll the PVS6 for new data. Minimum 5 seconds."
37
37
  },
38
+ "matter": {
39
+ "title": "Show in the Apple Home Energy view (via Matter)",
40
+ "type": "boolean",
41
+ "default": false,
42
+ "description": "Also publish Solar and Grid (import/export combined) over Matter as electrical sensors with live power and cumulative/periodic energy, feeding your Apple Home Energy view. Home Consumption is not published over Matter, since its energy is derived from Solar + Grid rather than an independent measurement. Requires Homebridge 2.3.0+ with Matter enabled on this plugin's child bridge; skipped safely otherwise."
43
+ },
44
+ "evePowerUpdates": {
45
+ "title": "Eve power/energy updates",
46
+ "type": "string",
47
+ "default": "throttled",
48
+ "oneOf": [
49
+ {
50
+ "title": "Throttled \u2014 push on meaningful change or every 5 minutes (recommended)",
51
+ "enum": [
52
+ "throttled"
53
+ ]
54
+ },
55
+ {
56
+ "title": "Poll only \u2014 never push; lowest traffic, breaks Eve/Home+ triggers on these values",
57
+ "enum": [
58
+ "pollOnly"
59
+ ]
60
+ },
61
+ {
62
+ "title": "Live \u2014 push every poll (original behaviour)",
63
+ "enum": [
64
+ "live"
65
+ ]
66
+ }
67
+ ],
68
+ "description": "How Eve Watts and Eve kWh values are sent to HomeKit. Eve and Home+ automations can trigger on or check these values. Throttled keeps those automations working with values accurate to within the thresholds below. Poll only gives the lowest traffic, but automations triggered by these values stop firing; use it only if no automation uses them."
69
+ },
70
+ "minChangeWatts": {
71
+ "title": "Minimum power change (W)",
72
+ "type": "number",
73
+ "default": 25,
74
+ "minimum": 0,
75
+ "description": "Throttled: push Eve Watts when it has changed by at least this many watts, or by the percentage below if that is larger.",
76
+ "condition": {
77
+ "functionBody": "return !model.evePowerUpdates || model.evePowerUpdates === 'throttled';"
78
+ }
79
+ },
80
+ "minChangePercent": {
81
+ "title": "Minimum power change (%)",
82
+ "type": "number",
83
+ "default": 2,
84
+ "minimum": 0,
85
+ "description": "Throttled: push Eve Watts when it has changed by at least this percentage of the last value pushed, or by the watts above if that is larger.",
86
+ "condition": {
87
+ "functionBody": "return !model.evePowerUpdates || model.evePowerUpdates === 'throttled';"
88
+ }
89
+ },
90
+ "minChangeKwh": {
91
+ "title": "Minimum energy change (kWh)",
92
+ "type": "number",
93
+ "default": 0.1,
94
+ "minimum": 0,
95
+ "description": "Throttled: push Eve kWh when it has changed by at least this much.",
96
+ "condition": {
97
+ "functionBody": "return !model.evePowerUpdates || model.evePowerUpdates === 'throttled';"
98
+ }
99
+ },
100
+ "switchHoldSeconds": {
101
+ "title": "Switch hold (seconds)",
102
+ "type": "integer",
103
+ "default": 60,
104
+ "minimum": 0,
105
+ "description": "The On switches derived from power (on above 50 W, off below 20 W) only change once the new state has held for this long. Automations triggered by these switches can fire up to this much later than the underlying change. 0 disables the hold."
106
+ },
38
107
  "accessories": {
39
108
  "title": "Accessories",
40
109
  "type": "object",
@@ -78,5 +147,32 @@
78
147
  }
79
148
  },
80
149
  "required": []
81
- }
150
+ },
151
+ "layout": [
152
+ "name",
153
+ "autoDiscover",
154
+ "host",
155
+ "serialNumber",
156
+ "pollInterval",
157
+ "matter",
158
+ {
159
+ "type": "fieldset",
160
+ "title": "HomeKit Updates",
161
+ "expandable": true,
162
+ "expanded": false,
163
+ "description": "Control how often power readings are sent to HomeKit.",
164
+ "items": [
165
+ "evePowerUpdates",
166
+ "minChangeWatts",
167
+ "minChangePercent",
168
+ "minChangeKwh",
169
+ "switchHoldSeconds"
170
+ ]
171
+ },
172
+ "accessories",
173
+ "solarName",
174
+ "gridName",
175
+ "gridExportName",
176
+ "homeConsumptionName"
177
+ ]
82
178
  }
@@ -7,6 +7,7 @@ export declare class GridExportAccessory {
7
7
  private readonly historyService;
8
8
  private lastPowerW;
9
9
  private lastEnergyKWh;
10
+ private readonly meter;
10
11
  constructor(platform: PVS6Platform, accessory: PlatformAccessory, FakeGatoHistoryService: any, displayName: string, serialNumber: string);
11
12
  updateValues(reading: PVS6Reading): void;
12
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gridExportAccessory.d.ts","sourceRoot":"","sources":["../src/gridExportAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,qBAAa,mBAAmB;IAS5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IAErC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;gBAGP,QAAQ,EAAE,YAAY,EACvC,SAAS,EAAE,iBAAiB,EAE5B,sBAAsB,EAAE,GAAG,EAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM;IA2CtB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CAoBzC"}
1
+ {"version":3,"file":"gridExportAccessory.d.ts","sourceRoot":"","sources":["../src/gridExportAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAI3C,qBAAa,mBAAmB;IAU5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAT3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IAErC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;gBAG1B,QAAQ,EAAE,YAAY,EACvC,SAAS,EAAE,iBAAiB,EAE5B,sBAAsB,EAAE,GAAG,EAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM;IAyBtB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CAczC"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GridExportAccessory = void 0;
4
4
  const eveCharacteristics_1 = require("./eveCharacteristics");
5
+ const meterCharacteristics_1 = require("./meterCharacteristics");
5
6
  class GridExportAccessory {
6
7
  constructor(platform, accessory,
7
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -10,7 +11,6 @@ class GridExportAccessory {
10
11
  this.lastPowerW = 0;
11
12
  this.lastEnergyKWh = 0;
12
13
  const { Characteristic } = platform;
13
- const { EveWatts, EveKWh } = platform.eveChars;
14
14
  const infoService = accessory.getService(platform.Service.AccessoryInformation) ??
15
15
  accessory.addService(platform.Service.AccessoryInformation);
16
16
  infoService
@@ -21,34 +21,15 @@ class GridExportAccessory {
21
21
  this.service = existingService ??
22
22
  accessory.addService(new platform.api.hap.Service(displayName, eveCharacteristics_1.EVE_ENERGY_SERVICE_UUID));
23
23
  this.service.setCharacteristic(Characteristic.Name, displayName);
24
- // On = true when exporting (lastPowerW > 0); always non-negative so the comparison is natural.
25
- this.service
26
- .getCharacteristic(Characteristic.On)
27
- .onGet(() => this.lastPowerW > 0)
28
- .onSet(async () => {
29
- this.service.updateCharacteristic(Characteristic.On, this.lastPowerW > 0);
30
- });
31
- this.service
32
- .getCharacteristic(Characteristic.OutletInUse)
33
- .onGet(() => true);
34
- this.service
35
- .getCharacteristic(EveWatts)
36
- .onGet(() => this.lastPowerW);
37
- this.service
38
- .getCharacteristic(EveKWh)
39
- .onGet(() => this.lastEnergyKWh);
24
+ // On (power-derived, with deadband + hold), OutletInUse, Eve Watts, Eve kWh.
25
+ this.meter = new meterCharacteristics_1.MeterCharacteristics(platform, accessory, this.service, 'grid-export', displayName);
40
26
  this.historyService = new FakeGatoHistoryService('energy', accessory, { storage: 'fs' });
41
27
  }
42
28
  updateValues(reading) {
43
- const { Characteristic } = this.platform;
44
- const { EveWatts, EveKWh } = this.platform.eveChars;
45
29
  // Non-negative: positive when net-exporting, zero when importing.
46
30
  this.lastPowerW = Math.max(0, -reading.netPowerW);
47
31
  this.lastEnergyKWh = reading.gridExportKWh;
48
- this.service.updateCharacteristic(Characteristic.On, this.lastPowerW > 0);
49
- this.service.updateCharacteristic(Characteristic.OutletInUse, true);
50
- this.service.updateCharacteristic(EveWatts, this.lastPowerW);
51
- this.service.updateCharacteristic(EveKWh, this.lastEnergyKWh);
32
+ this.meter.update(this.lastPowerW, this.lastEnergyKWh);
52
33
  this.historyService.addEntry({
53
34
  time: Math.round(Date.now() / 1000),
54
35
  power: this.lastPowerW,
@@ -1 +1 @@
1
- {"version":3,"file":"gridExportAccessory.js","sourceRoot":"","sources":["../src/gridExportAccessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gridExportAccessory.js","sourceRoot":"","sources":["../src/gridExportAccessory.ts"],"names":[],"mappings":";;;AAGA,6DAA+D;AAC/D,iEAA8D;AAE9D,MAAa,mBAAmB;IAS9B,YACmB,QAAsB,EACvC,SAA4B;IAC5B,8DAA8D;IAC9D,sBAA2B,EAC3B,WAAmB,EACnB,YAAoB;QALH,aAAQ,GAAR,QAAQ,CAAc;QALjC,eAAU,GAAG,CAAC,CAAC;QACf,kBAAa,GAAG,CAAC,CAAC;QAWxB,MAAM,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;QAEpC,MAAM,WAAW,GACf,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC;YAC3D,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAE9D,WAAW;aACR,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,WAAW,CAAC;aAC3D,iBAAiB,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC;aAC/C,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,GAAG,YAAY,cAAc,CAAC,CAAC;QAEjF,MAAM,eAAe,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,4CAAuB,CAAC,CAAC;QACzF,IAAI,CAAC,OAAO,GAAG,eAAe;YAC5B,SAAS,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,4CAAuB,CAAC,CAAC,CAAC;QAE3F,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAEjE,6EAA6E;QAC7E,IAAI,CAAC,KAAK,GAAG,IAAI,2CAAoB,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QAErG,IAAI,CAAC,cAAc,GAAG,IAAI,sBAAsB,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,YAAY,CAAC,OAAoB;QAC/B,kEAAkE;QAClE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAE3C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEvD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACnC,KAAK,EAAE,IAAI,CAAC,UAAU;SACvB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC;IACxF,CAAC;CACF;AAtDD,kDAsDC"}
@@ -7,6 +7,7 @@ export declare class GridImportAccessory {
7
7
  private readonly historyService;
8
8
  private lastPowerW;
9
9
  private lastEnergyKWh;
10
+ private readonly meter;
10
11
  constructor(platform: PVS6Platform, accessory: PlatformAccessory, FakeGatoHistoryService: any, displayName: string, serialNumber: string);
11
12
  updateValues(reading: PVS6Reading): void;
12
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"gridImportAccessory.d.ts","sourceRoot":"","sources":["../src/gridImportAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,qBAAa,mBAAmB;IAS5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IAErC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;gBAGP,QAAQ,EAAE,YAAY,EACvC,SAAS,EAAE,iBAAiB,EAE5B,sBAAsB,EAAE,GAAG,EAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM;IA2CtB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CAoBzC"}
1
+ {"version":3,"file":"gridImportAccessory.d.ts","sourceRoot":"","sources":["../src/gridImportAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAI3C,qBAAa,mBAAmB;IAU5B,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAT3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IAErC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;gBAG1B,QAAQ,EAAE,YAAY,EACvC,SAAS,EAAE,iBAAiB,EAE5B,sBAAsB,EAAE,GAAG,EAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM;IAyBtB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CAczC"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.GridImportAccessory = void 0;
4
4
  const eveCharacteristics_1 = require("./eveCharacteristics");
5
+ const meterCharacteristics_1 = require("./meterCharacteristics");
5
6
  class GridImportAccessory {
6
7
  constructor(platform, accessory,
7
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -10,7 +11,6 @@ class GridImportAccessory {
10
11
  this.lastPowerW = 0;
11
12
  this.lastEnergyKWh = 0;
12
13
  const { Characteristic } = platform;
13
- const { EveWatts, EveKWh } = platform.eveChars;
14
14
  const infoService = accessory.getService(platform.Service.AccessoryInformation) ??
15
15
  accessory.addService(platform.Service.AccessoryInformation);
16
16
  infoService
@@ -21,34 +21,15 @@ class GridImportAccessory {
21
21
  this.service = existingService ??
22
22
  accessory.addService(new platform.api.hap.Service(displayName, eveCharacteristics_1.EVE_ENERGY_SERVICE_UUID));
23
23
  this.service.setCharacteristic(Characteristic.Name, displayName);
24
- // On = true when importing (lastPowerW > 0); always non-negative so the comparison is natural.
25
- this.service
26
- .getCharacteristic(Characteristic.On)
27
- .onGet(() => this.lastPowerW > 0)
28
- .onSet(async () => {
29
- this.service.updateCharacteristic(Characteristic.On, this.lastPowerW > 0);
30
- });
31
- this.service
32
- .getCharacteristic(Characteristic.OutletInUse)
33
- .onGet(() => true);
34
- this.service
35
- .getCharacteristic(EveWatts)
36
- .onGet(() => this.lastPowerW);
37
- this.service
38
- .getCharacteristic(EveKWh)
39
- .onGet(() => this.lastEnergyKWh);
24
+ // On (power-derived, with deadband + hold), OutletInUse, Eve Watts, Eve kWh.
25
+ this.meter = new meterCharacteristics_1.MeterCharacteristics(platform, accessory, this.service, 'grid-import', displayName);
40
26
  this.historyService = new FakeGatoHistoryService('energy', accessory, { storage: 'fs' });
41
27
  }
42
28
  updateValues(reading) {
43
- const { Characteristic } = this.platform;
44
- const { EveWatts, EveKWh } = this.platform.eveChars;
45
29
  // Non-negative: zero when net-exporting, positive when importing.
46
30
  this.lastPowerW = Math.max(0, reading.netPowerW);
47
31
  this.lastEnergyKWh = reading.gridImportKWh;
48
- this.service.updateCharacteristic(Characteristic.On, this.lastPowerW > 0);
49
- this.service.updateCharacteristic(Characteristic.OutletInUse, true);
50
- this.service.updateCharacteristic(EveWatts, this.lastPowerW);
51
- this.service.updateCharacteristic(EveKWh, this.lastEnergyKWh);
32
+ this.meter.update(this.lastPowerW, this.lastEnergyKWh);
52
33
  this.historyService.addEntry({
53
34
  time: Math.round(Date.now() / 1000),
54
35
  power: this.lastPowerW,
@@ -1 +1 @@
1
- {"version":3,"file":"gridImportAccessory.js","sourceRoot":"","sources":["../src/gridImportAccessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"gridImportAccessory.js","sourceRoot":"","sources":["../src/gridImportAccessory.ts"],"names":[],"mappings":";;;AAGA,6DAA+D;AAC/D,iEAA8D;AAE9D,MAAa,mBAAmB;IAS9B,YACmB,QAAsB,EACvC,SAA4B;IAC5B,8DAA8D;IAC9D,sBAA2B,EAC3B,WAAmB,EACnB,YAAoB;QALH,aAAQ,GAAR,QAAQ,CAAc;QALjC,eAAU,GAAG,CAAC,CAAC;QACf,kBAAa,GAAG,CAAC,CAAC;QAWxB,MAAM,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;QAEpC,MAAM,WAAW,GACf,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC;YAC3D,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAE9D,WAAW;aACR,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,WAAW,CAAC;aAC3D,iBAAiB,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC;aAC/C,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,GAAG,YAAY,OAAO,CAAC,CAAC;QAE1E,MAAM,eAAe,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,4CAAuB,CAAC,CAAC;QACzF,IAAI,CAAC,OAAO,GAAG,eAAe;YAC5B,SAAS,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,4CAAuB,CAAC,CAAC,CAAC;QAE3F,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAEjE,6EAA6E;QAC7E,IAAI,CAAC,KAAK,GAAG,IAAI,2CAAoB,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,CAAC,CAAC;QAErG,IAAI,CAAC,cAAc,GAAG,IAAI,sBAAsB,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,YAAY,CAAC,OAAoB;QAC/B,kEAAkE;QAClE,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC;QACjD,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC;QAE3C,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEvD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACnC,KAAK,EAAE,IAAI,CAAC,UAAU;SACvB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC,aAAa,KAAK,CAAC,CAAC;IACxF,CAAC;CACF;AAtDD,kDAsDC"}
@@ -7,6 +7,7 @@ export declare class HomeConsumptionAccessory {
7
7
  private readonly historyService;
8
8
  private lastPowerW;
9
9
  private lastEnergyKWh;
10
+ private readonly meter;
10
11
  constructor(platform: PVS6Platform, accessory: PlatformAccessory, FakeGatoHistoryService: any, displayName: string, serialNumber: string);
11
12
  updateValues(reading: PVS6Reading): void;
12
13
  }
@@ -1 +1 @@
1
- {"version":3,"file":"homeConsumptionAccessory.d.ts","sourceRoot":"","sources":["../src/homeConsumptionAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG3C,qBAAa,wBAAwB;IASjC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAR3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IAErC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;gBAGP,QAAQ,EAAE,YAAY,EACvC,SAAS,EAAE,iBAAiB,EAE5B,sBAAsB,EAAE,GAAG,EAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM;IA2CtB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CAmBzC"}
1
+ {"version":3,"file":"homeConsumptionAccessory.d.ts","sourceRoot":"","sources":["../src/homeConsumptionAccessory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAW,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAI3C,qBAAa,wBAAwB;IAUjC,OAAO,CAAC,QAAQ,CAAC,QAAQ;IAT3B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAU;IAElC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAM;IAErC,OAAO,CAAC,UAAU,CAAK;IACvB,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuB;gBAG1B,QAAQ,EAAE,YAAY,EACvC,SAAS,EAAE,iBAAiB,EAE5B,sBAAsB,EAAE,GAAG,EAC3B,WAAW,EAAE,MAAM,EACnB,YAAY,EAAE,MAAM;IAyBtB,YAAY,CAAC,OAAO,EAAE,WAAW,GAAG,IAAI;CAazC"}
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.HomeConsumptionAccessory = void 0;
4
4
  const eveCharacteristics_1 = require("./eveCharacteristics");
5
+ const meterCharacteristics_1 = require("./meterCharacteristics");
5
6
  class HomeConsumptionAccessory {
6
7
  constructor(platform, accessory,
7
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -10,7 +11,6 @@ class HomeConsumptionAccessory {
10
11
  this.lastPowerW = 0;
11
12
  this.lastEnergyKWh = 0;
12
13
  const { Characteristic } = platform;
13
- const { EveWatts, EveKWh } = platform.eveChars;
14
14
  const infoService = accessory.getService(platform.Service.AccessoryInformation) ??
15
15
  accessory.addService(platform.Service.AccessoryInformation);
16
16
  infoService
@@ -21,33 +21,14 @@ class HomeConsumptionAccessory {
21
21
  this.service = existingService ??
22
22
  accessory.addService(new platform.api.hap.Service(displayName, eveCharacteristics_1.EVE_ENERGY_SERVICE_UUID));
23
23
  this.service.setCharacteristic(Characteristic.Name, displayName);
24
- // On = true when site is drawing power (always true in practice).
25
- this.service
26
- .getCharacteristic(Characteristic.On)
27
- .onGet(() => this.lastPowerW > 0)
28
- .onSet(async () => {
29
- this.service.updateCharacteristic(Characteristic.On, this.lastPowerW > 0);
30
- });
31
- this.service
32
- .getCharacteristic(Characteristic.OutletInUse)
33
- .onGet(() => true);
34
- this.service
35
- .getCharacteristic(EveWatts)
36
- .onGet(() => this.lastPowerW);
37
- this.service
38
- .getCharacteristic(EveKWh)
39
- .onGet(() => this.lastEnergyKWh);
24
+ // On (power-derived, with deadband + hold), OutletInUse, Eve Watts, Eve kWh.
25
+ this.meter = new meterCharacteristics_1.MeterCharacteristics(platform, accessory, this.service, 'home', displayName);
40
26
  this.historyService = new FakeGatoHistoryService('energy', accessory, { storage: 'fs' });
41
27
  }
42
28
  updateValues(reading) {
43
- const { Characteristic } = this.platform;
44
- const { EveWatts, EveKWh } = this.platform.eveChars;
45
29
  this.lastPowerW = reading.siteLoadPowerW;
46
30
  this.lastEnergyKWh = reading.homeConsumptionKWh;
47
- this.service.updateCharacteristic(Characteristic.On, this.lastPowerW > 0);
48
- this.service.updateCharacteristic(Characteristic.OutletInUse, true);
49
- this.service.updateCharacteristic(EveWatts, this.lastPowerW);
50
- this.service.updateCharacteristic(EveKWh, this.lastEnergyKWh);
31
+ this.meter.update(this.lastPowerW, this.lastEnergyKWh);
51
32
  this.historyService.addEntry({
52
33
  time: Math.round(Date.now() / 1000),
53
34
  power: this.lastPowerW,
@@ -1 +1 @@
1
- {"version":3,"file":"homeConsumptionAccessory.js","sourceRoot":"","sources":["../src/homeConsumptionAccessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"homeConsumptionAccessory.js","sourceRoot":"","sources":["../src/homeConsumptionAccessory.ts"],"names":[],"mappings":";;;AAGA,6DAA+D;AAC/D,iEAA8D;AAE9D,MAAa,wBAAwB;IASnC,YACmB,QAAsB,EACvC,SAA4B;IAC5B,8DAA8D;IAC9D,sBAA2B,EAC3B,WAAmB,EACnB,YAAoB;QALH,aAAQ,GAAR,QAAQ,CAAc;QALjC,eAAU,GAAG,CAAC,CAAC;QACf,kBAAa,GAAG,CAAC,CAAC;QAWxB,MAAM,EAAE,cAAc,EAAE,GAAG,QAAQ,CAAC;QAEpC,MAAM,WAAW,GACf,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC;YAC3D,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC;QAE9D,WAAW;aACR,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,WAAW,CAAC;aAC3D,iBAAiB,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC;aAC/C,iBAAiB,CAAC,cAAc,CAAC,YAAY,EAAE,GAAG,YAAY,OAAO,CAAC,CAAC;QAE1E,MAAM,eAAe,GAAG,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,4CAAuB,CAAC,CAAC;QACzF,IAAI,CAAC,OAAO,GAAG,eAAe;YAC5B,SAAS,CAAC,UAAU,CAAC,IAAI,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,4CAAuB,CAAC,CAAC,CAAC;QAE3F,IAAI,CAAC,OAAO,CAAC,iBAAiB,CAAC,cAAc,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QAEjE,6EAA6E;QAC7E,IAAI,CAAC,KAAK,GAAG,IAAI,2CAAoB,CAAC,QAAQ,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,CAAC;QAE9F,IAAI,CAAC,cAAc,GAAG,IAAI,sBAAsB,CAAC,QAAQ,EAAE,SAAS,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;IAC3F,CAAC;IAED,YAAY,CAAC,OAAoB;QAC/B,IAAI,CAAC,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC;QACzC,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,kBAAkB,CAAC;QAEhD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,aAAa,CAAC,CAAC;QAEvD,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC;YAC3B,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC;YACnC,KAAK,EAAE,IAAI,CAAC,UAAU;SACvB,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,CAAC,qBAAqB,IAAI,CAAC,UAAU,MAAM,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IACxG,CAAC;CACF;AArDD,4DAqDC"}