homebridge-rainforest-eagle3 1.1.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.
- package/README.md +60 -2
- package/config.schema.json +72 -1
- package/dist/eveCharacteristics.d.ts +7 -0
- package/dist/eveCharacteristics.d.ts.map +1 -1
- package/dist/eveCharacteristics.js +12 -0
- package/dist/eveCharacteristics.js.map +1 -1
- package/dist/exportMeterAccessory.d.ts +2 -0
- package/dist/exportMeterAccessory.d.ts.map +1 -1
- package/dist/exportMeterAccessory.js +13 -6
- package/dist/exportMeterAccessory.js.map +1 -1
- package/dist/gridMeterAccessory.d.ts +2 -0
- package/dist/gridMeterAccessory.d.ts.map +1 -1
- package/dist/gridMeterAccessory.js +13 -6
- package/dist/gridMeterAccessory.js.map +1 -1
- package/dist/matterEnergy.d.ts +47 -22
- package/dist/matterEnergy.d.ts.map +1 -1
- package/dist/matterEnergy.js +130 -60
- package/dist/matterEnergy.js.map +1 -1
- package/dist/platform.d.ts +11 -0
- package/dist/platform.d.ts.map +1 -1
- package/dist/platform.js +38 -2
- package/dist/platform.js.map +1 -1
- package/dist/powerSwitch.d.ts +24 -0
- package/dist/powerSwitch.d.ts.map +1 -0
- package/dist/powerSwitch.js +70 -0
- package/dist/powerSwitch.js.map +1 -0
- package/dist/settings.d.ts +6 -0
- package/dist/settings.d.ts.map +1 -1
- package/dist/updatePolicy.d.ts +43 -0
- package/dist/updatePolicy.d.ts.map +1 -0
- package/dist/updatePolicy.js +115 -0
- package/dist/updatePolicy.js.map +1 -0
- package/package.json +3 -2
package/dist/matterEnergy.js
CHANGED
|
@@ -75,16 +75,31 @@
|
|
|
75
75
|
* features compose once at registration, so PeriodicEnergy must already be
|
|
76
76
|
* present in the *initial* cluster state passed to registerPlatformAccessories()
|
|
77
77
|
* — declaring it for the first time in a later updateAccessoryState() call
|
|
78
|
-
* would not retroactively add the feature.
|
|
79
|
-
* zero-energy periodic fragment (no timestamps yet)
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
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.
|
|
88
103
|
*
|
|
89
104
|
* Requirements
|
|
90
105
|
* ------------
|
|
@@ -110,22 +125,34 @@ function kWhToMilliWh(value) {
|
|
|
110
125
|
const n = Number(value);
|
|
111
126
|
return Number.isFinite(n) ? Math.round(Math.max(0, n) * 1000000) : 0;
|
|
112
127
|
}
|
|
128
|
+
const ENERGY_KINDS = {
|
|
129
|
+
imported: ['imported'],
|
|
130
|
+
exported: ['exported'],
|
|
131
|
+
bidirectional: ['imported', 'exported'],
|
|
132
|
+
};
|
|
113
133
|
class MatterEnergyBridge {
|
|
114
|
-
constructor(api, log, direction) {
|
|
134
|
+
constructor(api, log, direction, nowMs = Date.now) {
|
|
115
135
|
this.log = log;
|
|
116
136
|
this.direction = direction;
|
|
137
|
+
this.nowMs = nowMs;
|
|
117
138
|
this.uuid = null;
|
|
118
139
|
this.registered = false;
|
|
119
140
|
this.warnedUpdate = false;
|
|
120
|
-
|
|
121
|
-
//
|
|
122
|
-
|
|
123
|
-
//
|
|
124
|
-
this.
|
|
125
|
-
|
|
126
|
-
|
|
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 },
|
|
127
151
|
};
|
|
152
|
+
// True while the last emitted period carried no energy (and at startup).
|
|
153
|
+
this.idle = true;
|
|
128
154
|
this.api = api;
|
|
155
|
+
this.kinds = ENERGY_KINDS[direction];
|
|
129
156
|
}
|
|
130
157
|
/**
|
|
131
158
|
* Whether this Homebridge build exposes everything needed to publish this
|
|
@@ -147,49 +174,82 @@ class MatterEnergyBridge {
|
|
|
147
174
|
}
|
|
148
175
|
return true;
|
|
149
176
|
}
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
}
|
|
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() };
|
|
160
188
|
return {
|
|
161
189
|
electricalPowerMeasurement: { activePower: wToMilliW(r.powerW) },
|
|
162
|
-
electricalEnergyMeasurement:
|
|
190
|
+
electricalEnergyMeasurement: this.energyFields(mWh, true),
|
|
163
191
|
};
|
|
164
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
|
+
}
|
|
165
206
|
/**
|
|
166
|
-
*
|
|
167
|
-
* periodic
|
|
168
|
-
* always from register(), before any real reading exists — seeds a
|
|
169
|
-
* zero-energy fragment with no timestamps, purely so the PeriodicEnergy
|
|
170
|
-
* feature composes at registration. Every call after that reports a real
|
|
171
|
-
* delta against the last periodic baseline once MIN_PERIODIC_INTERVAL_S
|
|
172
|
-
* has elapsed.
|
|
207
|
+
* Decide which energy fields this poll should send, updating the cumulative
|
|
208
|
+
* and periodic bookkeeping. Returns an empty object when nothing is due.
|
|
173
209
|
*/
|
|
174
|
-
|
|
175
|
-
const
|
|
176
|
-
const
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
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;
|
|
181
220
|
}
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
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
|
+
}
|
|
191
240
|
}
|
|
192
|
-
|
|
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);
|
|
193
253
|
}
|
|
194
254
|
/**
|
|
195
255
|
* Register this meter as a Matter electrical sensor.
|
|
@@ -212,7 +272,7 @@ class MatterEnergyBridge {
|
|
|
212
272
|
serialNumber,
|
|
213
273
|
manufacturer: 'Rainforest Automation',
|
|
214
274
|
model: 'EAGLE-3',
|
|
215
|
-
clusters: this.
|
|
275
|
+
clusters: this.buildInitialClusters(readings),
|
|
216
276
|
};
|
|
217
277
|
try {
|
|
218
278
|
await matter.registerPlatformAccessories(settings_1.PLUGIN_NAME, settings_1.PLATFORM_NAME, [accessory]);
|
|
@@ -236,12 +296,19 @@ class MatterEnergyBridge {
|
|
|
236
296
|
const matter = this.api.matter;
|
|
237
297
|
if (!matter)
|
|
238
298
|
return;
|
|
239
|
-
const
|
|
299
|
+
const energy = this.buildEnergyUpdate(readings);
|
|
240
300
|
try {
|
|
241
|
-
|
|
242
|
-
matter.updateAccessoryState(this.uuid, 'electricalPowerMeasurement',
|
|
243
|
-
|
|
244
|
-
|
|
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);
|
|
245
312
|
}
|
|
246
313
|
catch (err) {
|
|
247
314
|
// Log the first failure at warn, the rest at debug, so a persistently
|
|
@@ -258,5 +325,8 @@ class MatterEnergyBridge {
|
|
|
258
325
|
}
|
|
259
326
|
}
|
|
260
327
|
exports.MatterEnergyBridge = MatterEnergyBridge;
|
|
261
|
-
|
|
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;
|
|
262
332
|
//# sourceMappingURL=matterEnergy.js.map
|
package/dist/matterEnergy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matterEnergy.js","sourceRoot":"","sources":["../src/matterEnergy.ts"],"names":[],"mappings":";AAAA
|
|
1
|
+
{"version":3,"file":"matterEnergy.js","sourceRoot":"","sources":["../src/matterEnergy.ts"],"names":[],"mappings":"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"}
|
package/dist/platform.d.ts
CHANGED
|
@@ -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;
|
|
@@ -11,15 +14,23 @@ export declare class EAGLEPlatform implements DynamicPlatformPlugin {
|
|
|
11
14
|
readonly showExportMeter: boolean;
|
|
12
15
|
readonly exportMeterName: string;
|
|
13
16
|
readonly matterEnabled: boolean;
|
|
17
|
+
readonly updatePolicy: UpdatePolicyOptions;
|
|
18
|
+
readonly eveThrottle: EveUpdateThrottle;
|
|
19
|
+
private readonly switchStats;
|
|
14
20
|
private readonly client;
|
|
15
21
|
private readonly pollIntervalMs;
|
|
16
22
|
private gridMeterAccessory?;
|
|
17
23
|
private exportMeterAccessory?;
|
|
18
24
|
private gridMatterBridge?;
|
|
19
25
|
private pollTimer?;
|
|
26
|
+
private throttleStatsTimer?;
|
|
20
27
|
private pollInFlight;
|
|
21
28
|
private backedOff;
|
|
22
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;
|
|
23
34
|
configureAccessory(accessory: PlatformAccessory): void;
|
|
24
35
|
private discoverDevices;
|
|
25
36
|
private registerOrRestoreAccessory;
|
package/dist/platform.d.ts.map
CHANGED
|
@@ -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;
|
|
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"}
|
package/dist/platform.js
CHANGED
|
@@ -7,21 +7,27 @@ const gridMeterAccessory_1 = require("./gridMeterAccessory");
|
|
|
7
7
|
const exportMeterAccessory_1 = require("./exportMeterAccessory");
|
|
8
8
|
const eveCharacteristics_1 = require("./eveCharacteristics");
|
|
9
9
|
const matterEnergy_1 = require("./matterEnergy");
|
|
10
|
+
const updatePolicy_1 = require("./updatePolicy");
|
|
11
|
+
const powerSwitch_1 = require("./powerSwitch");
|
|
10
12
|
const MIN_POLL_INTERVAL = 5;
|
|
11
13
|
const DISCOVER_RETRY_MS = 30000;
|
|
12
14
|
const NO_METER_RETRY_MS = 60000;
|
|
13
15
|
const AUTH_BACKOFF_MS = 60000;
|
|
16
|
+
const THROTTLE_STATS_INTERVAL_MS = 60 * 60 * 1000;
|
|
14
17
|
class EAGLEPlatform {
|
|
15
18
|
constructor(log, config, api) {
|
|
16
19
|
this.log = log;
|
|
17
20
|
this.api = api;
|
|
18
21
|
this.accessories = [];
|
|
22
|
+
this.switchStats = new updatePolicy_1.UpdateStats();
|
|
19
23
|
this.pollInFlight = false;
|
|
20
24
|
this.backedOff = false;
|
|
21
25
|
this.Service = api.hap.Service;
|
|
22
26
|
this.Characteristic = api.hap.Characteristic;
|
|
23
27
|
this.eveChars = (0, eveCharacteristics_1.createEveCharacteristics)(api);
|
|
24
28
|
const eagleConfig = config;
|
|
29
|
+
this.updatePolicy = (0, updatePolicy_1.resolveUpdatePolicy)(eagleConfig);
|
|
30
|
+
this.eveThrottle = new updatePolicy_1.EveUpdateThrottle(this.updatePolicy, new updatePolicy_1.UpdateStats(), (message) => this.log.debug(message));
|
|
25
31
|
if (!eagleConfig.cloudId || !eagleConfig.installCode) {
|
|
26
32
|
this.log.error('Missing required config: cloudId and installCode are required.');
|
|
27
33
|
// Platform will do nothing; Homebridge still loads cleanly.
|
|
@@ -57,8 +63,21 @@ class EAGLEPlatform {
|
|
|
57
63
|
if (this.pollTimer) {
|
|
58
64
|
clearInterval(this.pollTimer);
|
|
59
65
|
}
|
|
66
|
+
if (this.throttleStatsTimer) {
|
|
67
|
+
clearInterval(this.throttleStatsTimer);
|
|
68
|
+
}
|
|
60
69
|
});
|
|
61
70
|
}
|
|
71
|
+
/** Push an Eve power/energy value, subject to the evePowerUpdates mode. */
|
|
72
|
+
updateEve(service, characteristic, key, value, unit) {
|
|
73
|
+
if (this.eveThrottle.shouldSend(key, value, unit)) {
|
|
74
|
+
service.updateCharacteristic(characteristic, value);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
/** On/off state for a power-derived On characteristic, with deadband and hold. */
|
|
78
|
+
createPowerSwitch(key) {
|
|
79
|
+
return new powerSwitch_1.PowerSwitch(key, this.updatePolicy.switchHoldSeconds, this.switchStats, (message) => this.log.debug(message));
|
|
80
|
+
}
|
|
62
81
|
configureAccessory(accessory) {
|
|
63
82
|
this.log.info('Loading accessory from cache:', accessory.displayName);
|
|
64
83
|
this.accessories.push(accessory);
|
|
@@ -140,7 +159,20 @@ class EAGLEPlatform {
|
|
|
140
159
|
}
|
|
141
160
|
}
|
|
142
161
|
startPolling(meterAddress) {
|
|
143
|
-
|
|
162
|
+
const p = this.updatePolicy;
|
|
163
|
+
const eveDesc = p.evePowerUpdates === 'throttled'
|
|
164
|
+
? `throttled (max(${p.minChangeWatts} W, ${p.minChangePercent}%), ${p.minChangeKwh} kWh, every ${p.maxIntervalSeconds}s)`
|
|
165
|
+
: p.evePowerUpdates;
|
|
166
|
+
this.log.info(`Eve power updates: ${eveDesc}; On switch hold: ${p.switchHoldSeconds}s`);
|
|
167
|
+
if (p.evePowerUpdates !== 'live' || p.switchHoldSeconds > 0) {
|
|
168
|
+
this.throttleStatsTimer = setInterval(() => {
|
|
169
|
+
const eve = this.eveThrottle.stats.take();
|
|
170
|
+
const sw = this.switchStats.take();
|
|
171
|
+
this.log.info(`HomeKit updates in the last hour: Eve power ${eve.sent} sent, ${eve.suppressed} suppressed; ` +
|
|
172
|
+
`On switches ${sw.sent} sent, ${sw.suppressed} held`);
|
|
173
|
+
}, THROTTLE_STATS_INTERVAL_MS);
|
|
174
|
+
}
|
|
175
|
+
const poll = async () => {
|
|
144
176
|
if (this.pollInFlight) {
|
|
145
177
|
this.log.debug('Poll skipped — previous request still in flight');
|
|
146
178
|
return;
|
|
@@ -188,7 +220,11 @@ class EAGLEPlatform {
|
|
|
188
220
|
finally {
|
|
189
221
|
this.pollInFlight = false;
|
|
190
222
|
}
|
|
191
|
-
}
|
|
223
|
+
};
|
|
224
|
+
// Poll once right away so HomeKit has the correct values on startup,
|
|
225
|
+
// rather than placeholders until the first interval elapses.
|
|
226
|
+
void poll();
|
|
227
|
+
this.pollTimer = setInterval(poll, this.pollIntervalMs);
|
|
192
228
|
}
|
|
193
229
|
enterBackoff(durationMs) {
|
|
194
230
|
this.backedOff = true;
|
package/dist/platform.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":";;;AAUA,yCAAqE;AACrE,+CAAuD;AACvD,6DAA0D;AAC1D,iEAA8D;AAC9D,6DAA0E;AAC1E,iDAAoD;
|
|
1
|
+
{"version":3,"file":"platform.js","sourceRoot":"","sources":["../src/platform.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { UpdateStats } from './updatePolicy';
|
|
2
|
+
/** Switch turns on when power rises above this many watts. */
|
|
3
|
+
export declare const SWITCH_ON_ABOVE_W = 50;
|
|
4
|
+
/** Switch turns off when power falls below this many watts. */
|
|
5
|
+
export declare const SWITCH_OFF_BELOW_W = 20;
|
|
6
|
+
export declare class PowerSwitch {
|
|
7
|
+
private readonly key;
|
|
8
|
+
private readonly holdSeconds;
|
|
9
|
+
private readonly stats;
|
|
10
|
+
private readonly debug;
|
|
11
|
+
private readonly now;
|
|
12
|
+
private reported;
|
|
13
|
+
private pendingSince;
|
|
14
|
+
constructor(key: string, holdSeconds: number, stats?: UpdateStats, debug?: (message: string) => void, now?: () => number);
|
|
15
|
+
/** The state last reported to HomeKit (false before the first reading). */
|
|
16
|
+
get state(): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Feed a new power reading. Returns the state to push to HomeKit, or null
|
|
19
|
+
* when the reported state should not change. The first reading is always
|
|
20
|
+
* reported immediately.
|
|
21
|
+
*/
|
|
22
|
+
update(watts: number): boolean | null;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=powerSwitch.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"powerSwitch.d.ts","sourceRoot":"","sources":["../src/powerSwitch.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,8DAA8D;AAC9D,eAAO,MAAM,iBAAiB,KAAK,CAAC;AACpC,+DAA+D;AAC/D,eAAO,MAAM,kBAAkB,KAAK,CAAC;AAErC,qBAAa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,GAAG;IACpB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAC5B,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG;IARtB,OAAO,CAAC,QAAQ,CAAwB;IACxC,OAAO,CAAC,YAAY,CAAuB;gBAGxB,GAAG,EAAE,MAAM,EACX,WAAW,EAAE,MAAM,EACnB,KAAK,GAAE,WAA+B,EACtC,KAAK,GAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAe,EAC3C,GAAG,GAAE,MAAM,MAAiB;IAG/C,2EAA2E;IAC3E,IAAI,KAAK,IAAI,OAAO,CAEnB;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,GAAG,IAAI;CAgCtC"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// On/off state derived from a power reading, for the standard HomeKit On
|
|
3
|
+
// characteristic. Stays evented so Home automations keep working, but with
|
|
4
|
+
// two safeguards against flapping:
|
|
5
|
+
//
|
|
6
|
+
// - Deadband: turns on above SWITCH_ON_ABOVE_W and off below SWITCH_OFF_BELOW_W.
|
|
7
|
+
// - Hold: a new state must persist for holdSeconds before it is reported
|
|
8
|
+
// (0 disables the hold). Automations triggered by the switch can therefore
|
|
9
|
+
// fire up to holdSeconds (plus one poll) after the underlying change.
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.PowerSwitch = exports.SWITCH_OFF_BELOW_W = exports.SWITCH_ON_ABOVE_W = void 0;
|
|
12
|
+
const updatePolicy_1 = require("./updatePolicy");
|
|
13
|
+
/** Switch turns on when power rises above this many watts. */
|
|
14
|
+
exports.SWITCH_ON_ABOVE_W = 50;
|
|
15
|
+
/** Switch turns off when power falls below this many watts. */
|
|
16
|
+
exports.SWITCH_OFF_BELOW_W = 20;
|
|
17
|
+
class PowerSwitch {
|
|
18
|
+
constructor(key, holdSeconds, stats = new updatePolicy_1.UpdateStats(), debug = () => { }, now = Date.now) {
|
|
19
|
+
this.key = key;
|
|
20
|
+
this.holdSeconds = holdSeconds;
|
|
21
|
+
this.stats = stats;
|
|
22
|
+
this.debug = debug;
|
|
23
|
+
this.now = now;
|
|
24
|
+
this.reported = null;
|
|
25
|
+
this.pendingSince = null;
|
|
26
|
+
}
|
|
27
|
+
/** The state last reported to HomeKit (false before the first reading). */
|
|
28
|
+
get state() {
|
|
29
|
+
return this.reported ?? false;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Feed a new power reading. Returns the state to push to HomeKit, or null
|
|
33
|
+
* when the reported state should not change. The first reading is always
|
|
34
|
+
* reported immediately.
|
|
35
|
+
*/
|
|
36
|
+
update(watts) {
|
|
37
|
+
if (this.reported === null) {
|
|
38
|
+
this.reported = watts > exports.SWITCH_ON_ABOVE_W;
|
|
39
|
+
this.stats.sent++;
|
|
40
|
+
return this.reported;
|
|
41
|
+
}
|
|
42
|
+
const target = this.reported ? watts >= exports.SWITCH_OFF_BELOW_W : watts > exports.SWITCH_ON_ABOVE_W;
|
|
43
|
+
if (target === this.reported) {
|
|
44
|
+
if (this.pendingSince !== null) {
|
|
45
|
+
this.debug(`${this.key}: pending change cancelled at ${watts} W, staying ${onOff(target)}`);
|
|
46
|
+
this.pendingSince = null;
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
const now = this.now();
|
|
51
|
+
if (this.pendingSince === null) {
|
|
52
|
+
this.pendingSince = now;
|
|
53
|
+
}
|
|
54
|
+
const heldS = (now - this.pendingSince) / 1000;
|
|
55
|
+
if (heldS >= this.holdSeconds) {
|
|
56
|
+
this.reported = target;
|
|
57
|
+
this.pendingSince = null;
|
|
58
|
+
this.stats.sent++;
|
|
59
|
+
return target;
|
|
60
|
+
}
|
|
61
|
+
this.stats.suppressed++;
|
|
62
|
+
this.debug(`${this.key}: holding change to ${onOff(target)} at ${watts} W (${heldS}s of ${this.holdSeconds}s)`);
|
|
63
|
+
return null;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
exports.PowerSwitch = PowerSwitch;
|
|
67
|
+
function onOff(state) {
|
|
68
|
+
return state ? 'on' : 'off';
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=powerSwitch.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"powerSwitch.js","sourceRoot":"","sources":["../src/powerSwitch.ts"],"names":[],"mappings":";AAAA,yEAAyE;AACzE,2EAA2E;AAC3E,mCAAmC;AACnC,EAAE;AACF,kFAAkF;AAClF,0EAA0E;AAC1E,8EAA8E;AAC9E,yEAAyE;;;AAEzE,iDAA6C;AAE7C,8DAA8D;AACjD,QAAA,iBAAiB,GAAG,EAAE,CAAC;AACpC,+DAA+D;AAClD,QAAA,kBAAkB,GAAG,EAAE,CAAC;AAErC,MAAa,WAAW;IAItB,YACmB,GAAW,EACX,WAAmB,EACnB,QAAqB,IAAI,0BAAW,EAAE,EACtC,QAAmC,GAAG,EAAE,GAAE,CAAC,EAC3C,MAAoB,IAAI,CAAC,GAAG;QAJ5B,QAAG,GAAH,GAAG,CAAQ;QACX,gBAAW,GAAX,WAAW,CAAQ;QACnB,UAAK,GAAL,KAAK,CAAiC;QACtC,UAAK,GAAL,KAAK,CAAsC;QAC3C,QAAG,GAAH,GAAG,CAAyB;QARvC,aAAQ,GAAmB,IAAI,CAAC;QAChC,iBAAY,GAAkB,IAAI,CAAC;IAQxC,CAAC;IAEJ,2EAA2E;IAC3E,IAAI,KAAK;QACP,OAAO,IAAI,CAAC,QAAQ,IAAI,KAAK,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,KAAa;QAClB,IAAI,IAAI,CAAC,QAAQ,KAAK,IAAI,EAAE,CAAC;YAC3B,IAAI,CAAC,QAAQ,GAAG,KAAK,GAAG,yBAAiB,CAAC;YAC1C,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,IAAI,CAAC,QAAQ,CAAC;QACvB,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,KAAK,IAAI,0BAAkB,CAAC,CAAC,CAAC,KAAK,GAAG,yBAAiB,CAAC;QACvF,IAAI,MAAM,KAAK,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;gBAC/B,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,iCAAiC,KAAK,eAAe,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;gBAC5F,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YAC3B,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,IAAI,IAAI,CAAC,YAAY,KAAK,IAAI,EAAE,CAAC;YAC/B,IAAI,CAAC,YAAY,GAAG,GAAG,CAAC;QAC1B,CAAC;QACD,MAAM,KAAK,GAAG,CAAC,GAAG,GAAG,IAAI,CAAC,YAAY,CAAC,GAAG,IAAI,CAAC;QAC/C,IAAI,KAAK,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC;YACvB,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC;YACzB,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC;YAClB,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,GAAG,uBAAuB,KAAK,CAAC,MAAM,CAAC,OAAO,KAAK,OAAO,KAAK,QAAQ,IAAI,CAAC,WAAW,IAAI,CAAC,CAAC;QAChH,OAAO,IAAI,CAAC;IACd,CAAC;CACF;AAtDD,kCAsDC;AAED,SAAS,KAAK,CAAC,KAAc;IAC3B,OAAO,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC;AAC9B,CAAC"}
|
package/dist/settings.d.ts
CHANGED
|
@@ -10,5 +10,11 @@ export interface EAGLEConfig extends PlatformConfig {
|
|
|
10
10
|
showExportMeter?: boolean;
|
|
11
11
|
exportMeterName?: string;
|
|
12
12
|
matter?: boolean;
|
|
13
|
+
evePowerUpdates?: 'throttled' | 'pollOnly' | 'live';
|
|
14
|
+
minChangeWatts?: number;
|
|
15
|
+
minChangePercent?: number;
|
|
16
|
+
minChangeKwh?: number;
|
|
17
|
+
maxIntervalSeconds?: number;
|
|
18
|
+
switchHoldSeconds?: number;
|
|
13
19
|
}
|
|
14
20
|
//# sourceMappingURL=settings.d.ts.map
|
package/dist/settings.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,WAAW,iCAAiC,CAAC;AAE1D,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../src/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C,eAAO,MAAM,aAAa,UAAU,CAAC;AACrC,eAAO,MAAM,WAAW,iCAAiC,CAAC;AAE1D,MAAM,WAAW,WAAY,SAAQ,cAAc;IACjD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,eAAe,CAAC,EAAE,WAAW,GAAG,UAAU,GAAG,MAAM,CAAC;IACpD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export type EvePowerUpdates = 'throttled' | 'pollOnly' | 'live';
|
|
2
|
+
export declare const EVE_POWER_UPDATE_MODES: readonly EvePowerUpdates[];
|
|
3
|
+
export type EveUnit = 'W' | 'kWh';
|
|
4
|
+
export interface UpdatePolicyOptions {
|
|
5
|
+
evePowerUpdates: EvePowerUpdates;
|
|
6
|
+
minChangeWatts: number;
|
|
7
|
+
minChangePercent: number;
|
|
8
|
+
minChangeKwh: number;
|
|
9
|
+
maxIntervalSeconds: number;
|
|
10
|
+
switchHoldSeconds: number;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_UPDATE_POLICY: UpdatePolicyOptions;
|
|
13
|
+
/** Builds options from raw config values, falling back to defaults for missing/invalid entries. */
|
|
14
|
+
export declare function resolveUpdatePolicy(config: Record<string, unknown>): UpdatePolicyOptions;
|
|
15
|
+
/** Sent/suppressed counters for the hourly summary log. */
|
|
16
|
+
export declare class UpdateStats {
|
|
17
|
+
sent: number;
|
|
18
|
+
suppressed: number;
|
|
19
|
+
/** Returns the counts since the previous call and resets them. */
|
|
20
|
+
take(): {
|
|
21
|
+
sent: number;
|
|
22
|
+
suppressed: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Decides, per accessory+characteristic key, whether an Eve value is pushed. */
|
|
26
|
+
export declare class EveUpdateThrottle {
|
|
27
|
+
private readonly options;
|
|
28
|
+
readonly stats: UpdateStats;
|
|
29
|
+
private readonly debug;
|
|
30
|
+
private readonly now;
|
|
31
|
+
private readonly lastSent;
|
|
32
|
+
constructor(options: UpdatePolicyOptions, stats?: UpdateStats, debug?: (message: string) => void, now?: () => number);
|
|
33
|
+
/** Whether Eve characteristics should advertise NOTIFY (false in pollOnly mode). */
|
|
34
|
+
get notify(): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Returns true if `value` should be pushed for `key`. The first value for a
|
|
37
|
+
* key is always pushed in throttled mode, so HomeKit gets the correct value
|
|
38
|
+
* immediately on startup.
|
|
39
|
+
*/
|
|
40
|
+
shouldSend(key: string, value: number, unit: EveUnit): boolean;
|
|
41
|
+
private isSignificant;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=updatePolicy.d.ts.map
|