@mega-yfue/eufy-sdk 0.4.0-beta.31 → 0.4.0-beta.33
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/dist/index.js
CHANGED
|
@@ -3273,7 +3273,7 @@ function propertiesOf(members, ctx) {
|
|
|
3273
3273
|
unit: m.unit,
|
|
3274
3274
|
enumValues: enumValues2,
|
|
3275
3275
|
provenance: m.provenance,
|
|
3276
|
-
invert: promoted?.invert ?? m.invert,
|
|
3276
|
+
invert: promoted?.invert ?? (ctx ? m.invertFor?.(ctx) : void 0) ?? m.invert,
|
|
3277
3277
|
decode: m.coerce,
|
|
3278
3278
|
// A member with a getter-side `decode` reads a field out of a structured payload, so the
|
|
3279
3279
|
// stored value is that payload — see `PropertySpec.raw`.
|
|
@@ -5205,8 +5205,10 @@ var AUDIO = {
|
|
|
5205
5205
|
|
|
5206
5206
|
// dist/model/capabilities/camera.js
|
|
5207
5207
|
var CAMERA_CMD = {
|
|
5208
|
-
/** Camera on/off.
|
|
5208
|
+
/** Camera on/off. Read and write polarity depend on the family and topology. */
|
|
5209
5209
|
CAMERA_ENABLE: 1035,
|
|
5210
|
+
/** Wrapped T8410 power switch on HomeBase 3. */
|
|
5211
|
+
PRIVACY_MODE: 6250,
|
|
5210
5212
|
/**
|
|
5211
5213
|
* Camera status LED on/off — the "power/recording" indicator. The
|
|
5212
5214
|
* app JS has a sibling param `1056` (`APP_CMD_LIVEVIEW_LED_SWITCH`) for the SAME UI "Status Light"
|
|
@@ -5426,7 +5428,27 @@ var ENABLE_BIT_FLOODLIGHT_TYPES = /* @__PURE__ */ new Set([
|
|
|
5426
5428
|
function powerValue(on, ctx) {
|
|
5427
5429
|
return isEnableBitPolarity(ctx) ? on ? 1 : 0 : on ? 0 : 1;
|
|
5428
5430
|
}
|
|
5431
|
+
function isT8410HomeBase3(ctx) {
|
|
5432
|
+
return ctx.model === "T8410" && ctx.stationSerial?.startsWith("T8030") === true;
|
|
5433
|
+
}
|
|
5434
|
+
function usesHomeBasePowerPayload(ctx) {
|
|
5435
|
+
if (!isT8410HomeBase3(ctx) || !ctx.firmwareVersion || !/^\d+(?:\.\d+){2,3}$/.test(ctx.firmwareVersion))
|
|
5436
|
+
return false;
|
|
5437
|
+
const version = ctx.firmwareVersion.split(".").map(Number);
|
|
5438
|
+
const minimum = [2, 3, 1, 0];
|
|
5439
|
+
for (let i = 0; i < minimum.length; i++) {
|
|
5440
|
+
const difference = (version[i] ?? 0) - minimum[i];
|
|
5441
|
+
if (difference !== 0)
|
|
5442
|
+
return difference > 0;
|
|
5443
|
+
}
|
|
5444
|
+
return true;
|
|
5445
|
+
}
|
|
5446
|
+
function hasUnreflectedHomeBasePower(ctx) {
|
|
5447
|
+
return usesHomeBasePowerPayload(ctx) && !ctx.paramIds.has(2001);
|
|
5448
|
+
}
|
|
5429
5449
|
function powerCommand(on, ctx) {
|
|
5450
|
+
if (usesHomeBasePowerPayload(ctx))
|
|
5451
|
+
return setPayload(CAMERA_CMD.PRIVACY_MODE, { switch: on ? 0 : 1 }, ctx, 0);
|
|
5430
5452
|
return setScalar(CAMERA_CMD.CAMERA_ENABLE, powerValue(on, ctx), ctx, "auto");
|
|
5431
5453
|
}
|
|
5432
5454
|
function privacyCommand(enabled, channel) {
|
|
@@ -5444,28 +5466,34 @@ function enablementReflection(on, ctx) {
|
|
|
5444
5466
|
const alias = CAMERA_MEMBERS.enabled.readAliases[0].paramType;
|
|
5445
5467
|
if (ctx.paramIds.has(alias))
|
|
5446
5468
|
return { param: alias, expected: on, observed: on };
|
|
5469
|
+
if (hasUnreflectedHomeBasePower(ctx))
|
|
5470
|
+
return void 0;
|
|
5447
5471
|
if (ctx.paramIds.has(CAMERA_CMD.CAMERA_ENABLE)) {
|
|
5448
|
-
return {
|
|
5472
|
+
return {
|
|
5473
|
+
param: CAMERA_CMD.CAMERA_ENABLE,
|
|
5474
|
+
expected: powerValue(on, ctx),
|
|
5475
|
+
observed: on
|
|
5476
|
+
};
|
|
5449
5477
|
}
|
|
5450
5478
|
return void 0;
|
|
5451
5479
|
}
|
|
5452
5480
|
function refuseWhenDisabled(ctx, read) {
|
|
5453
|
-
if (read("enabled")?.value === false)
|
|
5481
|
+
if (!hasUnreflectedHomeBasePower(ctx) && read("enabled")?.value === false)
|
|
5454
5482
|
throw new CameraDisabledError(ctx.name ?? ctx.serial);
|
|
5455
5483
|
}
|
|
5456
5484
|
var CAMERA_MEMBERS = {
|
|
5457
5485
|
/**
|
|
5458
|
-
* The READ is the *disable*-bit convention (1035 "0" ⇒ ON, 2001 direct); the WRITE polarity is
|
|
5486
|
+
* The default READ is the *disable*-bit convention (1035 "0" ⇒ ON, 2001 direct); the WRITE polarity is
|
|
5459
5487
|
* family-dependent — see `powerValue` / `isEnableBitPolarity`. Battery/solo cams report the state under
|
|
5460
5488
|
* 1035, standalone indoor/outdoor cams under 2001 OPEN_DEVICE with direct polarity, so 2001 is a
|
|
5461
5489
|
* read-alias. Both verified live, and the write polarity is confirmed against the app's own frames.
|
|
5462
5490
|
*
|
|
5463
|
-
*
|
|
5464
|
-
*
|
|
5491
|
+
* T8410 on HomeBase 3 reports 1035 as an enable bit ("1" ⇒ ON). That reported state does not reliably
|
|
5492
|
+
* reflect the privacy command. `readReflectsWrite` states this distinction.
|
|
5465
5493
|
*
|
|
5466
5494
|
* The privacy param (6250) is reported by the outdoor-PT family and by no other camera measured, and both
|
|
5467
5495
|
* of its polarities are observed. It is deliberately NOT aliased here: it moved in the same step as 1035, so
|
|
5468
|
-
* the reading cannot say whether power and privacy are one state or two
|
|
5496
|
+
* the reading cannot say whether power and privacy are one state or two — so
|
|
5469
5497
|
* aliasing a second param could only fold two possible states into one getter for no gain.
|
|
5470
5498
|
*/
|
|
5471
5499
|
enabled: {
|
|
@@ -5474,8 +5502,10 @@ var CAMERA_MEMBERS = {
|
|
|
5474
5502
|
kind: "boolean",
|
|
5475
5503
|
provenance: "verified",
|
|
5476
5504
|
invert: true,
|
|
5505
|
+
invertFor: (ctx) => isT8410HomeBase3(ctx) ? false : void 0,
|
|
5477
5506
|
readAliases: [{ paramType: 2001, invert: false }],
|
|
5478
|
-
|
|
5507
|
+
readReflectsWrite: (ctx) => !hasUnreflectedHomeBasePower(ctx),
|
|
5508
|
+
description: "Camera enabled. Family-dependent wire param: 1035 CMD_DEVS_SWITCH (enable bit on T8410/HomeBase 3, disable bit on battery/solo cams) or 2001 OPEN_DEVICE (standalone indoor/outdoor). Reported on/off state; unreflectedMembers identifies commands whose effect this report does not reliably reflect.",
|
|
5479
5509
|
observation: {
|
|
5480
5510
|
event: "cameraEnabledChanged",
|
|
5481
5511
|
reflects: (value, ctx) => enablementReflection(asBool(value), ctx),
|
|
@@ -5702,7 +5732,7 @@ var CAMERA_MEMBERS = {
|
|
|
5702
5732
|
* value, and it exists only on a device bound to a provider. Each is declared once, with its
|
|
5703
5733
|
* signature taken FROM {@link MediaProvider} — so a change there is a compile error here, not a drift.
|
|
5704
5734
|
*
|
|
5705
|
-
* Every pull is refused where {@link CAMERA_MEMBERS.enabled} reads false, with {@link CameraDisabledError} —
|
|
5735
|
+
* Every pull is refused where a reliable {@link CAMERA_MEMBERS.enabled} reads false, with {@link CameraDisabledError} —
|
|
5706
5736
|
* `live`, `snapshotLive`, `record`, `openReadable` and `recordFragments` alike, since each opens media on a
|
|
5707
5737
|
* camera that serves none. That reading is the on/off source; a live probe is not one, since a disabled
|
|
5708
5738
|
* camera answers a start with audio and never a video frame.
|
|
@@ -11160,7 +11190,8 @@ function resolveProperties(rec, codec, capabilities) {
|
|
|
11160
11190
|
model: rec.model,
|
|
11161
11191
|
category: rec.category,
|
|
11162
11192
|
capabilities: new Set(capabilities),
|
|
11163
|
-
paramIds
|
|
11193
|
+
paramIds,
|
|
11194
|
+
stationSerial: rec.parentSn
|
|
11164
11195
|
});
|
|
11165
11196
|
}
|
|
11166
11197
|
|
|
@@ -13350,7 +13381,8 @@ var Device = class _Device {
|
|
|
13350
13381
|
codec: this.codec,
|
|
13351
13382
|
model: this.model,
|
|
13352
13383
|
capabilities: new Set(this.capabilities),
|
|
13353
|
-
homeBaseAttached: this.stationSn !== this.sn
|
|
13384
|
+
homeBaseAttached: this.stationSn !== this.sn,
|
|
13385
|
+
stationSerial: this.stationSn
|
|
13354
13386
|
})
|
|
13355
13387
|
};
|
|
13356
13388
|
}
|
|
@@ -16214,8 +16246,17 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16214
16246
|
this.send(this.connectAddress, RequestMessageType.DATA, data);
|
|
16215
16247
|
return true;
|
|
16216
16248
|
}
|
|
16217
|
-
/**
|
|
16218
|
-
|
|
16249
|
+
/**
|
|
16250
|
+
* Stop the realtime media stream (`CMD_STOP_REALTIME_MEDIA`, 1004) on a camera `channel`, in the shape
|
|
16251
|
+
* its runtime topology takes, as {@link startLiveMedia} selects its start:
|
|
16252
|
+
* - `homeBaseAttached`: `CMD_SET_PAYLOAD` (1350) wrapping `{cmd:1004, mChannel:channel}` at level-2.
|
|
16253
|
+
* - own-session at level-2: the direct 1004 frame whose entire plaintext is the camera channel as a
|
|
16254
|
+
* `uint32`, the same 4-byte body as the attached talkback frames. The app sends this frame on closing
|
|
16255
|
+
* an own-session camera's live view; the camera stops streaming on it within a second, and keeps
|
|
16256
|
+
* streaming through the 1350-wrapped form.
|
|
16257
|
+
* - without a level-2 key: the bare 1004 command.
|
|
16258
|
+
*/
|
|
16259
|
+
stopLiveMedia(channel = STATION_CHANNEL3, accountId = "", homeBaseAttached = false) {
|
|
16219
16260
|
this.liveStartedChannels.delete(channel);
|
|
16220
16261
|
for (const [sequence, pending] of this.unackedLiveStarts) {
|
|
16221
16262
|
if (pending.channel === channel)
|
|
@@ -16225,7 +16266,11 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
16225
16266
|
clearInterval(this.liveStartRetransmitTimer);
|
|
16226
16267
|
this.liveStartRetransmitTimer = void 0;
|
|
16227
16268
|
}
|
|
16228
|
-
if (this.level2Key) {
|
|
16269
|
+
if (this.level2Key && !homeBaseAttached) {
|
|
16270
|
+
const body = Buffer.allocUnsafe(4);
|
|
16271
|
+
body.writeUInt32LE(channel >>> 0, 0);
|
|
16272
|
+
this.sendRawLevel2Bytes(body, channel, CMD_STOP_REALTIME_MEDIA, 8);
|
|
16273
|
+
} else if (this.level2Key) {
|
|
16229
16274
|
this.sendMediaPayloadLevel2(CMD_STOP_REALTIME_MEDIA, channel, accountId, {});
|
|
16230
16275
|
} else {
|
|
16231
16276
|
this.sendCommand(CMD_STOP_REALTIME_MEDIA, channel);
|
|
@@ -17991,7 +18036,7 @@ var LiveStream = class extends EventEmitter3 {
|
|
|
17991
18036
|
clearTimeout(this.stallTimer);
|
|
17992
18037
|
this.stallTimer = void 0;
|
|
17993
18038
|
try {
|
|
17994
|
-
this.session.stopLiveMedia(this.opts.channel, this.opts.accountId);
|
|
18039
|
+
this.session.stopLiveMedia(this.opts.channel, this.opts.accountId, this.opts.homeBaseAttached);
|
|
17995
18040
|
} catch (e) {
|
|
17996
18041
|
this.logger.debug(`[live] stopLiveMedia ignored: ${e instanceof Error ? e.message : e}`);
|
|
17997
18042
|
}
|
|
@@ -27297,6 +27342,7 @@ var EufyMega = class extends EventEmitter9 {
|
|
|
27297
27342
|
model: rec.model,
|
|
27298
27343
|
category: dev.category,
|
|
27299
27344
|
serial: sn,
|
|
27345
|
+
stationSerial: rec.parentSn,
|
|
27300
27346
|
// Identity metadata for `info`, for a host's device-registry surface. `name` = the app-shown
|
|
27301
27347
|
// device_name (registry's `name`), not the resolved codec/inferred name. firmware/hardware come
|
|
27302
27348
|
// straight off the device record: `main_sw_version` / `main_hw_version` — the same fields the v6
|