homebridge-rainforest-eagle3 1.0.0 → 1.2.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.
@@ -0,0 +1,176 @@
1
+ /**
2
+ * matterEnergy.ts
3
+ *
4
+ * Publishes the EAGLE grid meter to Matter controllers as a single
5
+ * bidirectional ElectricalSensor reporting live power and cumulative /
6
+ * periodic energy, so it feeds the Apple Home Energy view (iOS 27+).
7
+ *
8
+ * Background
9
+ * ----------
10
+ * Apple Home's Energy view is driven by Matter electrical-measurement
11
+ * clusters, not by classic HomeKit/HAP characteristics. HAP has no native
12
+ * power/energy characteristic, so the Eve custom characteristics this plugin
13
+ * also exposes (see eveCharacteristics.ts) are only ever read by Eve-class
14
+ * apps and never populate the native Energy tile.
15
+ *
16
+ * Device type: ElectricalSensor, not OnOffOutlet
17
+ * -----------------------------------------------
18
+ * A pure metering device type like ElectricalSensor has no actionable
19
+ * primary cluster, so its tile in the Home app shows "Not Supported" as its
20
+ * headline status. That's an accepted tradeoff here: the meter is not
21
+ * actually controllable, and an on/off state would only ever be a workaround
22
+ * for the tile headline — the wattage still rolls into the Home aggregate
23
+ * and (via PeriodicEnergy, below) into this accessory's own Energy-view
24
+ * attribution either way.
25
+ *
26
+ * powerW -> electricalPowerMeasurement.activePower (mW, signed)
27
+ * energyKWh -> electricalEnergyMeasurement.cumulativeEnergyImported.energy (mWh)
28
+ * and .cumulativeEnergyExported.energy, since the grid meter is
29
+ * bidirectional (see EnergyDirection below).
30
+ *
31
+ * Matter expresses power in milliwatts and energy in milliwatt-hours, hence
32
+ * the x1000 / x1,000,000 conversions. cumulativeEnergyImported/Exported are
33
+ * themselves structs (EnergyMeasurementStruct — { energy, startTimestamp?,
34
+ * endTimestamp?, ... }), not plain numbers: Homebridge's updateAccessoryState()
35
+ * accepts and normalizes a flat number for convenience, but the *initial*
36
+ * state passed at registration goes straight to matter.js's struct-typed
37
+ * attribute and must already be an object, or registration fails with
38
+ * "Cannot manage number because it is not a struct".
39
+ *
40
+ * Homebridge derives the mandatory cluster attributes (powerMode, accuracy,
41
+ * numberOfMeasurementTypes) and the feature-gated ElectricalEnergyMeasurement
42
+ * features from the declared state — declaring `cumulativeEnergyImported`
43
+ * selects the ImportedEnergy + CumulativeEnergy features, `cumulativeEnergyExported`
44
+ * selects ExportedEnergy + CumulativeEnergy, and both together (for a
45
+ * bidirectional meter) select both pairs at once. No voltage/current data is
46
+ * available from the EAGLE's local API, so only activePower is declared;
47
+ * voltage/activeCurrent are optional per the Matter spec and are simply
48
+ * omitted.
49
+ *
50
+ * Imported vs. exported energy is always two separate attributes
51
+ * ------------------------------------------------------------
52
+ * `activePower` is a signed attribute (positive = importing, negative =
53
+ * exporting), so this single bidirectional meter can report live direction
54
+ * with one accessory. Cumulative/periodic *energy* has no equivalent signed
55
+ * "net" attribute, though: Imported and Exported are distinct lifetime
56
+ * running totals per the Matter spec (you don't want a day's export and
57
+ * import cancelling each other out), so the meter declares both
58
+ * `cumulativeEnergyImported` and `cumulativeEnergyExported` (and their
59
+ * periodic counterparts) together on the same cluster. This is how the grid
60
+ * meter is published as a single Matter accessory even though it remains two
61
+ * separate accessories in Eve/HomeKit (Grid Meter - Import / Grid Meter -
62
+ * Export) when `showExportMeter` is enabled, since that split is purely
63
+ * about Eve's inability to represent a negative watt value, not a Matter
64
+ * limitation.
65
+ *
66
+ * Cumulative vs. periodic energy
67
+ * ------------------------------
68
+ * Alongside the cumulative (lifetime) total, this module also declares the
69
+ * PeriodicEnergy feature (`periodicEnergyImported`/`periodicEnergyExported`)
70
+ * — a per-interval delta with its own start/end timestamps. Per prior art in
71
+ * homebridge-shelly-matter (github.com/keremerkan/homebridge-shelly-matter,
72
+ * shellyAccessory.ts), this is what drives Apple Home's per-device energy
73
+ * attribution in the Energy view, not the cumulative total alone. Matter
74
+ * features compose once at registration, so PeriodicEnergy must already be
75
+ * present in the *initial* cluster state passed to registerPlatformAccessories()
76
+ * — declaring it for the first time in a later updateAccessoryState() call
77
+ * would not retroactively add the feature. register() therefore seeds a
78
+ * zero-energy periodic fragment (no timestamps yet).
79
+ *
80
+ * Event rate
81
+ * ----------
82
+ * Homebridge routes every energy field passed to updateAccessoryState() through
83
+ * matter.js setMeasurement(), which records a CumulativeEnergyMeasured or
84
+ * PeriodicEnergyMeasured event for each one. Sending both on every poll
85
+ * (default 15s) produced events that almost always repeated the previous
86
+ * total or reported 0 energy, so update() includes each field only when it
87
+ * carries news:
88
+ *
89
+ * - Cumulative: when the total (in mWh) has changed since the last one sent,
90
+ * or CUMULATIVE_HEARTBEAT_S has passed, so controllers still get a periodic
91
+ * heartbeat while the meter is idle.
92
+ * - Periodic: energy is accumulated across polls (per-poll deltas, so a meter
93
+ * counter that steps backwards doesn't produce a negative period) and
94
+ * emitted once per PERIODIC_INTERVAL_S, with start/end timestamps covering
95
+ * the whole period. If the previous period was idle (zero energy) and energy
96
+ * starts flowing, the period is emitted immediately and a new one starts, so
97
+ * a new session starts reporting promptly instead of up to 15 minutes later.
98
+ *
99
+ * The periodic baseline is taken from the first real poll, not from the
100
+ * placeholder readings register() is called with. The first update() after
101
+ * registration always sends both fields, as before.
102
+ *
103
+ * Requirements
104
+ * ------------
105
+ * - Homebridge 2.4.0+
106
+ * - Matter enabled on this plugin's child bridge (Homebridge UI ->
107
+ * plugin settings -> Bridge Settings -> enable Matter)
108
+ * - iOS/iPadOS 27+ on the device used to view the Apple Home Energy view
109
+ *
110
+ * Everything here is feature-detected and guarded: on a Homebridge build
111
+ * without the Matter API, or with Matter disabled, isSupported() returns
112
+ * false and the plugin runs HAP/Eve-only exactly as before.
113
+ */
114
+ import type { API, Logger } from 'homebridge';
115
+ export type EnergyDirection = 'imported' | 'exported' | 'bidirectional';
116
+ export interface EnergyReadings {
117
+ /** Signed for a 'bidirectional' meter (positive = importing, negative = exporting). */
118
+ powerW: number;
119
+ /** Required when direction is 'imported' or 'bidirectional'. */
120
+ importedEnergyKWh?: number;
121
+ /** Required when direction is 'exported' or 'bidirectional'. */
122
+ exportedEnergyKWh?: number;
123
+ }
124
+ export declare class MatterEnergyBridge {
125
+ private readonly log;
126
+ private readonly direction;
127
+ private readonly nowMs;
128
+ /** Re-send an unchanged cumulative total at least this often. */
129
+ static readonly CUMULATIVE_HEARTBEAT_S: number;
130
+ /** Length of one PeriodicEnergyMeasured period. */
131
+ static readonly PERIODIC_INTERVAL_S: number;
132
+ private readonly api;
133
+ private readonly kinds;
134
+ private uuid;
135
+ private registered;
136
+ private warnedUpdate;
137
+ private sentFirstUpdate;
138
+ private lastCumulative;
139
+ private lastReadingKWh;
140
+ private periodStartS;
141
+ private periodKWh;
142
+ private lastPeriodic;
143
+ private idle;
144
+ constructor(api: API, log: Logger, direction: EnergyDirection, nowMs?: () => number);
145
+ /**
146
+ * Whether this Homebridge build exposes everything needed to publish this
147
+ * meter. Logs at debug level so unsupported builds stay quiet.
148
+ */
149
+ isSupported(): boolean;
150
+ private nowS;
151
+ private static readingsByKind;
152
+ /** Initial cluster state for register(): every energy field, periodic seeded at zero. */
153
+ private buildInitialClusters;
154
+ private energyFields;
155
+ /**
156
+ * Decide which energy fields this poll should send, updating the cumulative
157
+ * and periodic bookkeeping. Returns an empty object when nothing is due.
158
+ */
159
+ private buildEnergyUpdate;
160
+ /**
161
+ * Register this meter as a Matter electrical sensor.
162
+ *
163
+ * @param seedKey - unique per-meter key used to derive this accessory's
164
+ * Matter UUID, distinct from the HAP accessory's UUID
165
+ * @param displayName
166
+ * @param serialNumber
167
+ * @param readings - initial readings to seed the clusters with
168
+ */
169
+ register(seedKey: string, displayName: string, serialNumber: string, readings: EnergyReadings): Promise<boolean>;
170
+ /**
171
+ * Push fresh readings to the registered Matter accessory. No-op until
172
+ * registration has succeeded.
173
+ */
174
+ update(readings: EnergyReadings): Promise<void>;
175
+ }
176
+ //# sourceMappingURL=matterEnergy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matterEnergy.d.ts","sourceRoot":"","sources":["../src/matterEnergy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgHG;AAEH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAkB9C,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,UAAU,GAAG,eAAe,CAAC;AAExE,MAAM,WAAW,cAAc;IAC7B,uFAAuF;IACvF,MAAM,EAAE,MAAM,CAAC;IACf,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gEAAgE;IAChE,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAyDD,qBAAa,kBAAkB;IA6B3B,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IA9BxB,iEAAiE;IACjE,MAAM,CAAC,QAAQ,CAAC,sBAAsB,SAAW;IACjD,mDAAmD;IACnD,MAAM,CAAC,QAAQ,CAAC,mBAAmB,SAAW;IAE9C,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAgB;IACpC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,IAAI,CAAuB;IACnC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,eAAe,CAAS;IAGhC,OAAO,CAAC,cAAc,CAAmE;IAGzF,OAAO,CAAC,cAAc,CAA2C;IACjE,OAAO,CAAC,YAAY,CAAK;IACzB,OAAO,CAAC,SAAS,CAA4D;IAC7E,OAAO,CAAC,YAAY,CAGlB;IAEF,OAAO,CAAC,IAAI,CAAQ;gBAGlB,GAAG,EAAE,GAAG,EACS,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,eAAe,EAC1B,KAAK,GAAE,MAAM,MAAiB;IAMjD;;;OAGG;IACH,WAAW,IAAI,OAAO;IAiBtB,OAAO,CAAC,IAAI;IAIZ,OAAO,CAAC,MAAM,CAAC,cAAc;IAI7B,yFAAyF;IACzF,OAAO,CAAC,oBAAoB;IAU5B,OAAO,CAAC,YAAY;IAiBpB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAgDzB;;;;;;;;OAQG;IACG,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,OAAO,CAAC;IA2BtH;;;OAGG;IACG,MAAM,CAAC,QAAQ,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CA+BtD"}
@@ -0,0 +1,332 @@
1
+ "use strict";
2
+ /**
3
+ * matterEnergy.ts
4
+ *
5
+ * Publishes the EAGLE grid meter to Matter controllers as a single
6
+ * bidirectional ElectricalSensor reporting live power and cumulative /
7
+ * periodic energy, so it feeds the Apple Home Energy view (iOS 27+).
8
+ *
9
+ * Background
10
+ * ----------
11
+ * Apple Home's Energy view is driven by Matter electrical-measurement
12
+ * clusters, not by classic HomeKit/HAP characteristics. HAP has no native
13
+ * power/energy characteristic, so the Eve custom characteristics this plugin
14
+ * also exposes (see eveCharacteristics.ts) are only ever read by Eve-class
15
+ * apps and never populate the native Energy tile.
16
+ *
17
+ * Device type: ElectricalSensor, not OnOffOutlet
18
+ * -----------------------------------------------
19
+ * A pure metering device type like ElectricalSensor has no actionable
20
+ * primary cluster, so its tile in the Home app shows "Not Supported" as its
21
+ * headline status. That's an accepted tradeoff here: the meter is not
22
+ * actually controllable, and an on/off state would only ever be a workaround
23
+ * for the tile headline — the wattage still rolls into the Home aggregate
24
+ * and (via PeriodicEnergy, below) into this accessory's own Energy-view
25
+ * attribution either way.
26
+ *
27
+ * powerW -> electricalPowerMeasurement.activePower (mW, signed)
28
+ * energyKWh -> electricalEnergyMeasurement.cumulativeEnergyImported.energy (mWh)
29
+ * and .cumulativeEnergyExported.energy, since the grid meter is
30
+ * bidirectional (see EnergyDirection below).
31
+ *
32
+ * Matter expresses power in milliwatts and energy in milliwatt-hours, hence
33
+ * the x1000 / x1,000,000 conversions. cumulativeEnergyImported/Exported are
34
+ * themselves structs (EnergyMeasurementStruct — { energy, startTimestamp?,
35
+ * endTimestamp?, ... }), not plain numbers: Homebridge's updateAccessoryState()
36
+ * accepts and normalizes a flat number for convenience, but the *initial*
37
+ * state passed at registration goes straight to matter.js's struct-typed
38
+ * attribute and must already be an object, or registration fails with
39
+ * "Cannot manage number because it is not a struct".
40
+ *
41
+ * Homebridge derives the mandatory cluster attributes (powerMode, accuracy,
42
+ * numberOfMeasurementTypes) and the feature-gated ElectricalEnergyMeasurement
43
+ * features from the declared state — declaring `cumulativeEnergyImported`
44
+ * selects the ImportedEnergy + CumulativeEnergy features, `cumulativeEnergyExported`
45
+ * selects ExportedEnergy + CumulativeEnergy, and both together (for a
46
+ * bidirectional meter) select both pairs at once. No voltage/current data is
47
+ * available from the EAGLE's local API, so only activePower is declared;
48
+ * voltage/activeCurrent are optional per the Matter spec and are simply
49
+ * omitted.
50
+ *
51
+ * Imported vs. exported energy is always two separate attributes
52
+ * ------------------------------------------------------------
53
+ * `activePower` is a signed attribute (positive = importing, negative =
54
+ * exporting), so this single bidirectional meter can report live direction
55
+ * with one accessory. Cumulative/periodic *energy* has no equivalent signed
56
+ * "net" attribute, though: Imported and Exported are distinct lifetime
57
+ * running totals per the Matter spec (you don't want a day's export and
58
+ * import cancelling each other out), so the meter declares both
59
+ * `cumulativeEnergyImported` and `cumulativeEnergyExported` (and their
60
+ * periodic counterparts) together on the same cluster. This is how the grid
61
+ * meter is published as a single Matter accessory even though it remains two
62
+ * separate accessories in Eve/HomeKit (Grid Meter - Import / Grid Meter -
63
+ * Export) when `showExportMeter` is enabled, since that split is purely
64
+ * about Eve's inability to represent a negative watt value, not a Matter
65
+ * limitation.
66
+ *
67
+ * Cumulative vs. periodic energy
68
+ * ------------------------------
69
+ * Alongside the cumulative (lifetime) total, this module also declares the
70
+ * PeriodicEnergy feature (`periodicEnergyImported`/`periodicEnergyExported`)
71
+ * — a per-interval delta with its own start/end timestamps. Per prior art in
72
+ * homebridge-shelly-matter (github.com/keremerkan/homebridge-shelly-matter,
73
+ * shellyAccessory.ts), this is what drives Apple Home's per-device energy
74
+ * attribution in the Energy view, not the cumulative total alone. Matter
75
+ * features compose once at registration, so PeriodicEnergy must already be
76
+ * present in the *initial* cluster state passed to registerPlatformAccessories()
77
+ * — declaring it for the first time in a later updateAccessoryState() call
78
+ * would not retroactively add the feature. register() therefore seeds a
79
+ * zero-energy periodic fragment (no timestamps yet).
80
+ *
81
+ * Event rate
82
+ * ----------
83
+ * Homebridge routes every energy field passed to updateAccessoryState() through
84
+ * matter.js setMeasurement(), which records a CumulativeEnergyMeasured or
85
+ * PeriodicEnergyMeasured event for each one. Sending both on every poll
86
+ * (default 15s) produced events that almost always repeated the previous
87
+ * total or reported 0 energy, so update() includes each field only when it
88
+ * carries news:
89
+ *
90
+ * - Cumulative: when the total (in mWh) has changed since the last one sent,
91
+ * or CUMULATIVE_HEARTBEAT_S has passed, so controllers still get a periodic
92
+ * heartbeat while the meter is idle.
93
+ * - Periodic: energy is accumulated across polls (per-poll deltas, so a meter
94
+ * counter that steps backwards doesn't produce a negative period) and
95
+ * emitted once per PERIODIC_INTERVAL_S, with start/end timestamps covering
96
+ * the whole period. If the previous period was idle (zero energy) and energy
97
+ * starts flowing, the period is emitted immediately and a new one starts, so
98
+ * a new session starts reporting promptly instead of up to 15 minutes later.
99
+ *
100
+ * The periodic baseline is taken from the first real poll, not from the
101
+ * placeholder readings register() is called with. The first update() after
102
+ * registration always sends both fields, as before.
103
+ *
104
+ * Requirements
105
+ * ------------
106
+ * - Homebridge 2.4.0+
107
+ * - Matter enabled on this plugin's child bridge (Homebridge UI ->
108
+ * plugin settings -> Bridge Settings -> enable Matter)
109
+ * - iOS/iPadOS 27+ on the device used to view the Apple Home Energy view
110
+ *
111
+ * Everything here is feature-detected and guarded: on a Homebridge build
112
+ * without the Matter API, or with Matter disabled, isSupported() returns
113
+ * false and the plugin runs HAP/Eve-only exactly as before.
114
+ */
115
+ Object.defineProperty(exports, "__esModule", { value: true });
116
+ exports.MatterEnergyBridge = void 0;
117
+ const settings_1 = require("./settings");
118
+ /** Matter expresses power in milliwatts. */
119
+ function wToMilliW(value) {
120
+ const n = Number(value);
121
+ return Number.isFinite(n) ? Math.round(n * 1000) : 0;
122
+ }
123
+ /** Matter expresses energy in milliwatt-hours; EAGLE readings are in kWh. */
124
+ function kWhToMilliWh(value) {
125
+ const n = Number(value);
126
+ return Number.isFinite(n) ? Math.round(Math.max(0, n) * 1000000) : 0;
127
+ }
128
+ const ENERGY_KINDS = {
129
+ imported: ['imported'],
130
+ exported: ['exported'],
131
+ bidirectional: ['imported', 'exported'],
132
+ };
133
+ class MatterEnergyBridge {
134
+ constructor(api, log, direction, nowMs = Date.now) {
135
+ this.log = log;
136
+ this.direction = direction;
137
+ this.nowMs = nowMs;
138
+ this.uuid = null;
139
+ this.registered = false;
140
+ this.warnedUpdate = false;
141
+ this.sentFirstUpdate = false;
142
+ // Cumulative energy last sent (mWh) and when.
143
+ this.lastCumulative = null;
144
+ // Periodic-energy bookkeeping — see "Event rate" at the top of this file.
145
+ this.lastReadingKWh = null;
146
+ this.periodStartS = 0;
147
+ this.periodKWh = { imported: 0, exported: 0 };
148
+ this.lastPeriodic = {
149
+ imported: { energy: 0 },
150
+ exported: { energy: 0 },
151
+ };
152
+ // True while the last emitted period carried no energy (and at startup).
153
+ this.idle = true;
154
+ this.api = api;
155
+ this.kinds = ENERGY_KINDS[direction];
156
+ }
157
+ /**
158
+ * Whether this Homebridge build exposes everything needed to publish this
159
+ * meter. Logs at debug level so unsupported builds stay quiet.
160
+ */
161
+ isSupported() {
162
+ const matter = this.api.matter;
163
+ if (!matter) {
164
+ this.log.debug('[matter] api.matter unavailable — Matter energy export disabled. Requires Homebridge 2.4.0+ with Matter enabled on this plugin\'s child bridge.');
165
+ return false;
166
+ }
167
+ if (!matter.deviceTypes?.ElectricalSensor) {
168
+ this.log.debug('[matter] api.matter.deviceTypes.ElectricalSensor unavailable — Matter energy export disabled. Requires a newer Homebridge build.');
169
+ return false;
170
+ }
171
+ if (typeof matter.registerPlatformAccessories !== 'function' || typeof matter.updateAccessoryState !== 'function') {
172
+ this.log.debug('[matter] Matter registration/update API unavailable — Matter energy export disabled.');
173
+ return false;
174
+ }
175
+ return true;
176
+ }
177
+ nowS() {
178
+ return Math.floor(this.nowMs() / 1000);
179
+ }
180
+ static readingsByKind(r) {
181
+ return { imported: r.importedEnergyKWh ?? 0, exported: r.exportedEnergyKWh ?? 0 };
182
+ }
183
+ /** Initial cluster state for register(): every energy field, periodic seeded at zero. */
184
+ buildInitialClusters(r) {
185
+ const kWh = MatterEnergyBridge.readingsByKind(r);
186
+ const mWh = { imported: kWhToMilliWh(kWh.imported), exported: kWhToMilliWh(kWh.exported) };
187
+ this.lastCumulative = { mWh, timeS: this.nowS() };
188
+ return {
189
+ electricalPowerMeasurement: { activePower: wToMilliW(r.powerW) },
190
+ electricalEnergyMeasurement: this.energyFields(mWh, true),
191
+ };
192
+ }
193
+ energyFields(cumulativeMWh, includePeriodic) {
194
+ const out = {};
195
+ for (const kind of this.kinds) {
196
+ const suffix = kind === 'imported' ? 'Imported' : 'Exported';
197
+ if (cumulativeMWh) {
198
+ out[`cumulativeEnergy${suffix}`] = { energy: cumulativeMWh[kind] };
199
+ }
200
+ if (includePeriodic) {
201
+ out[`periodicEnergy${suffix}`] = this.lastPeriodic[kind];
202
+ }
203
+ }
204
+ return out;
205
+ }
206
+ /**
207
+ * Decide which energy fields this poll should send, updating the cumulative
208
+ * and periodic bookkeeping. Returns an empty object when nothing is due.
209
+ */
210
+ buildEnergyUpdate(r) {
211
+ const nowS = this.nowS();
212
+ const kWh = MatterEnergyBridge.readingsByKind(r);
213
+ const first = !this.sentFirstUpdate;
214
+ this.sentFirstUpdate = true;
215
+ // Periodic: accumulate this poll's delta, emit at the end of a period or
216
+ // as soon as energy starts flowing after an idle period.
217
+ let emitPeriodic = false;
218
+ if (this.lastReadingKWh === null) {
219
+ this.periodStartS = nowS;
220
+ }
221
+ else {
222
+ for (const kind of this.kinds) {
223
+ this.periodKWh[kind] += Math.max(0, kWh[kind] - this.lastReadingKWh[kind]);
224
+ }
225
+ const hasEnergy = this.kinds.some((k) => kWhToMilliWh(this.periodKWh[k]) > 0);
226
+ const periodOver = nowS - this.periodStartS >= MatterEnergyBridge.PERIODIC_INTERVAL_S;
227
+ if (periodOver || (this.idle && hasEnergy)) {
228
+ emitPeriodic = true;
229
+ for (const kind of this.kinds) {
230
+ this.lastPeriodic[kind] = {
231
+ energy: kWhToMilliWh(this.periodKWh[kind]),
232
+ startTimestamp: this.periodStartS,
233
+ endTimestamp: nowS,
234
+ };
235
+ this.periodKWh[kind] = 0;
236
+ }
237
+ this.idle = !hasEnergy;
238
+ this.periodStartS = nowS;
239
+ }
240
+ }
241
+ this.lastReadingKWh = kWh;
242
+ // Cumulative: send on change or heartbeat.
243
+ const mWh = { imported: kWhToMilliWh(kWh.imported), exported: kWhToMilliWh(kWh.exported) };
244
+ const last = this.lastCumulative;
245
+ const sendCumulative = first ||
246
+ last === null ||
247
+ this.kinds.some((k) => mWh[k] !== last.mWh[k]) ||
248
+ nowS - last.timeS >= MatterEnergyBridge.CUMULATIVE_HEARTBEAT_S;
249
+ if (sendCumulative) {
250
+ this.lastCumulative = { mWh, timeS: nowS };
251
+ }
252
+ return this.energyFields(sendCumulative ? mWh : null, first || emitPeriodic);
253
+ }
254
+ /**
255
+ * Register this meter as a Matter electrical sensor.
256
+ *
257
+ * @param seedKey - unique per-meter key used to derive this accessory's
258
+ * Matter UUID, distinct from the HAP accessory's UUID
259
+ * @param displayName
260
+ * @param serialNumber
261
+ * @param readings - initial readings to seed the clusters with
262
+ */
263
+ async register(seedKey, displayName, serialNumber, readings) {
264
+ if (!this.isSupported())
265
+ return false;
266
+ const matter = this.api.matter;
267
+ this.uuid = matter.uuid.generate(`${settings_1.PLUGIN_NAME}:matter:${seedKey}`);
268
+ const accessory = {
269
+ UUID: this.uuid,
270
+ displayName,
271
+ deviceType: matter.deviceTypes.ElectricalSensor,
272
+ serialNumber,
273
+ manufacturer: 'Rainforest Automation',
274
+ model: 'EAGLE-3',
275
+ clusters: this.buildInitialClusters(readings),
276
+ };
277
+ try {
278
+ await matter.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
279
+ this.registered = true;
280
+ this.log.info(`[matter] Published "${displayName}" as a Matter electrical sensor — live power should feed the Apple Home Energy view.`);
281
+ return true;
282
+ }
283
+ catch (err) {
284
+ this.log.warn(`[matter] Failed to register Matter accessory for "${displayName}" (${err instanceof Error ? err.message : err}). Continuing with HomeKit/Eve only.`);
285
+ this.registered = false;
286
+ return false;
287
+ }
288
+ }
289
+ /**
290
+ * Push fresh readings to the registered Matter accessory. No-op until
291
+ * registration has succeeded.
292
+ */
293
+ async update(readings) {
294
+ if (!this.registered || !this.uuid)
295
+ return;
296
+ const matter = this.api.matter;
297
+ if (!matter)
298
+ return;
299
+ const energy = this.buildEnergyUpdate(readings);
300
+ try {
301
+ const updates = [
302
+ matter.updateAccessoryState(this.uuid, 'electricalPowerMeasurement', {
303
+ activePower: wToMilliW(readings.powerW),
304
+ }),
305
+ ];
306
+ // Every energy field sent records a Matter event, so skip the call
307
+ // entirely when nothing is due.
308
+ if (Object.keys(energy).length > 0) {
309
+ updates.push(matter.updateAccessoryState(this.uuid, 'electricalEnergyMeasurement', energy));
310
+ }
311
+ await Promise.all(updates);
312
+ }
313
+ catch (err) {
314
+ // Log the first failure at warn, the rest at debug, so a persistently
315
+ // unhappy Matter server can't flood the log on every poll.
316
+ const message = `[matter] Failed to update Matter state: ${err instanceof Error ? err.message : err}`;
317
+ if (!this.warnedUpdate) {
318
+ this.warnedUpdate = true;
319
+ this.log.warn(message);
320
+ }
321
+ else {
322
+ this.log.debug(message);
323
+ }
324
+ }
325
+ }
326
+ }
327
+ exports.MatterEnergyBridge = MatterEnergyBridge;
328
+ /** Re-send an unchanged cumulative total at least this often. */
329
+ MatterEnergyBridge.CUMULATIVE_HEARTBEAT_S = 15 * 60;
330
+ /** Length of one PeriodicEnergyMeasured period. */
331
+ MatterEnergyBridge.PERIODIC_INTERVAL_S = 15 * 60;
332
+ //# sourceMappingURL=matterEnergy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"matterEnergy.js","sourceRoot":"","sources":["../src/matterEnergy.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,8 @@
1
1
  import { API, Characteristic, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service } from 'homebridge';
2
2
  import { EveChars } from './eveCharacteristics';
3
+ import { EveUnit, EveUpdateThrottle, UpdatePolicyOptions } from './updatePolicy';
4
+ import { PowerSwitch } from './powerSwitch';
5
+ import { EveCharClass } from './eveCharacteristics';
3
6
  export declare class EAGLEPlatform implements DynamicPlatformPlugin {
4
7
  readonly log: Logger;
5
8
  readonly api: API;
@@ -10,14 +13,24 @@ export declare class EAGLEPlatform implements DynamicPlatformPlugin {
10
13
  readonly meterName: string;
11
14
  readonly showExportMeter: boolean;
12
15
  readonly exportMeterName: string;
16
+ readonly matterEnabled: boolean;
17
+ readonly updatePolicy: UpdatePolicyOptions;
18
+ readonly eveThrottle: EveUpdateThrottle;
19
+ private readonly switchStats;
13
20
  private readonly client;
14
21
  private readonly pollIntervalMs;
15
22
  private gridMeterAccessory?;
16
23
  private exportMeterAccessory?;
24
+ private gridMatterBridge?;
17
25
  private pollTimer?;
26
+ private throttleStatsTimer?;
18
27
  private pollInFlight;
19
28
  private backedOff;
20
29
  constructor(log: Logger, config: PlatformConfig, api: API);
30
+ /** Push an Eve power/energy value, subject to the evePowerUpdates mode. */
31
+ updateEve(service: Service, characteristic: EveCharClass, key: string, value: number, unit: EveUnit): void;
32
+ /** On/off state for a power-derived On characteristic, with deadband and hold. */
33
+ createPowerSwitch(key: string): PowerSwitch;
21
34
  configureAccessory(accessory: PlatformAccessory): void;
22
35
  private discoverDevices;
23
36
  private registerOrRestoreAccessory;
@@ -1 +1 @@
1
- {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,cAAc,EACd,qBAAqB,EACrB,MAAM,EACN,iBAAiB,EACjB,cAAc,EACd,OAAO,EACR,MAAM,YAAY,CAAC;AAMpB,OAAO,EAA4B,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAO1E,qBAAa,aAAc,YAAW,qBAAqB;aAoBvC,GAAG,EAAE,MAAM;aAEX,GAAG,EAAE,GAAG;IArB1B,SAAgB,OAAO,EAAE,OAAO,OAAO,CAAC;IACxC,SAAgB,cAAc,EAAE,OAAO,cAAc,CAAC;IAEtD,SAAgB,WAAW,EAAE,iBAAiB,EAAE,CAAM;IACtD,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IACnC,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,eAAe,EAAE,OAAO,CAAC;IACzC,SAAgB,eAAe,EAAE,MAAM,CAAC;IAExC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,oBAAoB,CAAC,CAAuB;IACpD,OAAO,CAAC,SAAS,CAAC,CAAiC;IACnD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;gBAGR,GAAG,EAAE,MAAM,EAC3B,MAAM,EAAE,cAAc,EACN,GAAG,EAAE,GAAG;IAyD1B,kBAAkB,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAKtD,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,0BAA0B;IAqDlC,OAAO,CAAC,YAAY;IA6CpB,OAAO,CAAC,YAAY;CAOrB"}
1
+ {"version":3,"file":"platform.d.ts","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,GAAG,EACH,cAAc,EACd,qBAAqB,EACrB,MAAM,EACN,iBAAiB,EACjB,cAAc,EACd,OAAO,EACR,MAAM,YAAY,CAAC;AAMpB,OAAO,EAA4B,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AAE1E,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAoC,MAAM,gBAAgB,CAAC;AACnH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAQpD,qBAAa,aAAc,YAAW,qBAAqB;aAgCvC,GAAG,EAAE,MAAM;aAEX,GAAG,EAAE,GAAG;IAjC1B,SAAgB,OAAO,EAAE,OAAO,OAAO,CAAC;IACxC,SAAgB,cAAc,EAAE,OAAO,cAAc,CAAC;IAEtD,SAAgB,WAAW,EAAE,iBAAiB,EAAE,CAAM;IACtD,SAAgB,QAAQ,EAAE,QAAQ,CAAC;IACnC,SAAgB,SAAS,EAAE,MAAM,CAAC;IAClC,SAAgB,eAAe,EAAE,OAAO,CAAC;IACzC,SAAgB,eAAe,EAAE,MAAM,CAAC;IACxC,SAAgB,aAAa,EAAE,OAAO,CAAC;IAEvC,SAAgB,YAAY,EAAE,mBAAmB,CAAC;IAClD,SAAgB,WAAW,EAAE,iBAAiB,CAAC;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAqB;IAEjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAc;IACrC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAS;IAExC,OAAO,CAAC,kBAAkB,CAAC,CAAqB;IAChD,OAAO,CAAC,oBAAoB,CAAC,CAAuB;IAMpD,OAAO,CAAC,gBAAgB,CAAC,CAAqB;IAC9C,OAAO,CAAC,SAAS,CAAC,CAAiC;IACnD,OAAO,CAAC,kBAAkB,CAAC,CAAiC;IAC5D,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,SAAS,CAAS;gBAGR,GAAG,EAAE,MAAM,EAC3B,MAAM,EAAE,cAAc,EACN,GAAG,EAAE,GAAG;IAoE1B,2EAA2E;IAC3E,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,YAAY,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,IAAI;IAM1G,kFAAkF;IAClF,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW;IAS3C,kBAAkB,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAKtD,OAAO,CAAC,eAAe;IAgBvB,OAAO,CAAC,0BAA0B;IAuElC,OAAO,CAAC,YAAY;IAyEpB,OAAO,CAAC,YAAY;CAOrB"}