@mega-yfue/eufy-sdk 0.6.0-beta.41 → 0.6.0-beta.42
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/client/device-registry.d.ts +22 -0
- package/dist/index.js +568 -174
- package/dist/index.js.map +4 -4
- package/dist/model/capabilities/index.d.ts +1 -0
- package/dist/model/capabilities/members.d.ts +18 -3
- package/dist/model/capabilities/rtsp.d.ts +1 -10
- package/dist/model/capabilities/thing-description.d.ts +137 -0
- package/dist/model/capabilities/types.d.ts +9 -0
- package/dist/model/inspect.d.ts +3 -0
- package/dist/model/types.d.ts +3 -0
- package/dist/transport/http/mega-client.d.ts +12 -0
- package/dist/transport/rtc/command-router.d.ts +7 -0
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -47,10 +47,10 @@ function decryptBody(b64, shareKeyHex) {
|
|
|
47
47
|
return Buffer.concat([decipher.update(raw.subarray(16)), decipher.final()]);
|
|
48
48
|
}
|
|
49
49
|
function signRequest(shareKeyHex, ts, once, encBodyB64) {
|
|
50
|
-
const
|
|
50
|
+
const parts2 = [ts, once];
|
|
51
51
|
if (encBodyB64)
|
|
52
|
-
|
|
53
|
-
return createHmac("sha256", signKey(shareKeyHex)).update(
|
|
52
|
+
parts2.push(encBodyB64);
|
|
53
|
+
return createHmac("sha256", signKey(shareKeyHex)).update(parts2.join("+"), "utf-8").digest("hex");
|
|
54
54
|
}
|
|
55
55
|
function prepareKeyExchange(localKeyHex = EUFY_MEGA_LOCAL_KEY_HEX) {
|
|
56
56
|
const localKey = Buffer.from(localKeyHex, "hex");
|
|
@@ -411,8 +411,8 @@ function randomPhoneModel(seed) {
|
|
|
411
411
|
const rnd = rng(seed);
|
|
412
412
|
const pick = (a) => a[Math.floor(rnd() * a.length)];
|
|
413
413
|
const brand = pick(Object.keys(PHONE_MODELS));
|
|
414
|
-
const
|
|
415
|
-
return `${brand}${pick(
|
|
414
|
+
const parts2 = PHONE_MODELS[brand];
|
|
415
|
+
return `${brand}${pick(parts2.first)}${pick(parts2.second)}`.trim();
|
|
416
416
|
}
|
|
417
417
|
function randomUserAgent(seed, model) {
|
|
418
418
|
const rnd = rng(seed);
|
|
@@ -1052,10 +1052,10 @@ function getIdSuffix(p2pDid) {
|
|
|
1052
1052
|
const match = p2pDid.match(/^[A-Z]+-(\d+)-[A-Z]+$/);
|
|
1053
1053
|
if (match?.length === 2) {
|
|
1054
1054
|
const num1 = Number.parseInt(match[1][0]);
|
|
1055
|
-
const
|
|
1055
|
+
const num22 = Number.parseInt(match[1][1]);
|
|
1056
1056
|
const num3 = Number.parseInt(match[1][3]);
|
|
1057
1057
|
const num4 = Number.parseInt(match[1][5]);
|
|
1058
|
-
result = num1 +
|
|
1058
|
+
result = num1 + num22 + num3;
|
|
1059
1059
|
if (num3 < 5)
|
|
1060
1060
|
result = result + num3;
|
|
1061
1061
|
result = result + num4;
|
|
@@ -1735,6 +1735,10 @@ var MegaHttpClient = class {
|
|
|
1735
1735
|
get regionShard() {
|
|
1736
1736
|
return this.region;
|
|
1737
1737
|
}
|
|
1738
|
+
/** The account's country code as configured (e.g. `"FR"`), the one logins are sent with. */
|
|
1739
|
+
get countryCode() {
|
|
1740
|
+
return this.cfg.countryCode;
|
|
1741
|
+
}
|
|
1738
1742
|
/**
|
|
1739
1743
|
* The shard the estimated domain names (`…-ie-…`/`…-ie.` → `ie-pr`), else {@link regionShard}. The
|
|
1740
1744
|
* eu/us classification cannot name shards like `ie-pr`.
|
|
@@ -2069,6 +2073,21 @@ ${this.auth_?.authToken ?? ""}`;
|
|
|
2069
2073
|
getProductDataPoint(code) {
|
|
2070
2074
|
return this.post("things", "/app/things/get_product_data_point", { code });
|
|
2071
2075
|
}
|
|
2076
|
+
/**
|
|
2077
|
+
* Fetch the **thing descriptions** of the given product codes from the mega `things` service: per
|
|
2078
|
+
* product, every named property with its type and offered values, its actions and events. The v6 app
|
|
2079
|
+
* fetches the same list for the products an account holds and reads each setting's options from it.
|
|
2080
|
+
* Product-level data, not account data. `codeTimeMap` names, per product code, the `update_time` of the
|
|
2081
|
+
* description already held: a product whose description has not changed since comes back with that
|
|
2082
|
+
* `update_time` and no properties, one that has (or is not named) comes back in full. Returns the raw
|
|
2083
|
+
* `data`.
|
|
2084
|
+
*/
|
|
2085
|
+
getThingsList(productCodes, codeTimeMap = {}) {
|
|
2086
|
+
return this.post("things", "/app/things/get_things_list", {
|
|
2087
|
+
product_codes: productCodes,
|
|
2088
|
+
code_time_map: codeTimeMap
|
|
2089
|
+
});
|
|
2090
|
+
}
|
|
2072
2091
|
/**
|
|
2073
2092
|
* Fetch the **live param list** from the mega `devicemanage` service. Body keys off a
|
|
2074
2093
|
* `device_sns` ARRAY (a bare `device_sn` 400s with "type mismatch"). Each returned entry is
|
|
@@ -2105,10 +2124,10 @@ ${this.auth_?.authToken ?? ""}`;
|
|
|
2105
2124
|
* host it points at is unconfirmed, and this client's binary path (`downloadMediaResource`) is
|
|
2106
2125
|
* host-allowlisted by design.
|
|
2107
2126
|
*/
|
|
2108
|
-
getCleanRecords(deviceSn,
|
|
2127
|
+
getCleanRecords(deviceSn, num3 = 20, page = 1) {
|
|
2109
2128
|
return this.post("clean", "/app/clean/get_device_clean_record_list", {
|
|
2110
2129
|
device_sn: deviceSn,
|
|
2111
|
-
num:
|
|
2130
|
+
num: num3,
|
|
2112
2131
|
page
|
|
2113
2132
|
});
|
|
2114
2133
|
}
|
|
@@ -2123,11 +2142,11 @@ ${this.auth_?.authToken ?? ""}`;
|
|
|
2123
2142
|
* APK, and the extracted `.so` set contains no clean-native module. Handing over bytes a caller can
|
|
2124
2143
|
* take elsewhere is the honest surface; a decode here would be invention.
|
|
2125
2144
|
*/
|
|
2126
|
-
getDeviceMapList(deviceSn, channelId = 0,
|
|
2145
|
+
getDeviceMapList(deviceSn, channelId = 0, num3 = 1, page = 1, lastOffset = 0) {
|
|
2127
2146
|
return this.post("clean", "/app/clean/get_device_map_list", {
|
|
2128
2147
|
device_sn: deviceSn,
|
|
2129
2148
|
channel_id: channelId,
|
|
2130
|
-
num:
|
|
2149
|
+
num: num3,
|
|
2131
2150
|
page,
|
|
2132
2151
|
last_offset: lastOffset
|
|
2133
2152
|
});
|
|
@@ -2650,15 +2669,15 @@ function subscribeTopics(device) {
|
|
|
2650
2669
|
return [secureTopic(device, "res")];
|
|
2651
2670
|
}
|
|
2652
2671
|
function parseSecureTopic(topic) {
|
|
2653
|
-
const
|
|
2654
|
-
if (
|
|
2672
|
+
const parts2 = topic.split("/");
|
|
2673
|
+
if (parts2.length < 5)
|
|
2655
2674
|
return void 0;
|
|
2656
|
-
const [root, category, model, sn] =
|
|
2675
|
+
const [root, category, model, sn] = parts2;
|
|
2657
2676
|
if (root !== "cmd" && root !== "synq" && root !== "biz" && root !== "dt")
|
|
2658
2677
|
return void 0;
|
|
2659
2678
|
if (!category || !model || !sn)
|
|
2660
2679
|
return void 0;
|
|
2661
|
-
return { root, category, model, sn, tail:
|
|
2680
|
+
return { root, category, model, sn, tail: parts2.slice(4).join("/") };
|
|
2662
2681
|
}
|
|
2663
2682
|
function solixDeviceTopics(appName, productCode, deviceSn) {
|
|
2664
2683
|
const dt = `dt/${appName}/${productCode}/${deviceSn}`;
|
|
@@ -3403,8 +3422,17 @@ function provided(needs, build, description, requiredCapabilities) {
|
|
|
3403
3422
|
function hasRequiredCapabilities(member, capabilities) {
|
|
3404
3423
|
return !member.requiredCapabilities?.some((capability) => !capabilities?.has(capability));
|
|
3405
3424
|
}
|
|
3425
|
+
function thingEnum(m, ctx) {
|
|
3426
|
+
const named = m.enumValues;
|
|
3427
|
+
const property2 = named && m.thing?.map((id) => ctx.things?.properties[id]).find(Boolean);
|
|
3428
|
+
if (!named || !property2)
|
|
3429
|
+
return void 0;
|
|
3430
|
+
const wire = property2.type === "bool" ? [0, 1] : property2.members.map((x) => Number(x.wireValue ?? NaN));
|
|
3431
|
+
const options = Object.fromEntries(wire.filter((v) => v in named).map((v) => [v, named[v]]));
|
|
3432
|
+
return Object.keys(options).length ? options : void 0;
|
|
3433
|
+
}
|
|
3406
3434
|
function resolvedEnum(m, ctx) {
|
|
3407
|
-
const dynamic = ctx ? m.enumValuesFor?.(ctx) : void 0;
|
|
3435
|
+
const dynamic = ctx ? m.enumValuesFor?.(ctx) ?? thingEnum(m, ctx) : void 0;
|
|
3408
3436
|
return dynamic ? { values: dynamic, dynamic: true } : { values: m.enumValues, dynamic: false };
|
|
3409
3437
|
}
|
|
3410
3438
|
function propertiesOf(members, ctx) {
|
|
@@ -3525,6 +3553,46 @@ function wasReported(m, from, ctx) {
|
|
|
3525
3553
|
function installs(m, ctx) {
|
|
3526
3554
|
return reports(m.requires, ctx) && (!m.requiresRead || reads(m, ctx)) && (!m.available || m.available(ctx));
|
|
3527
3555
|
}
|
|
3556
|
+
function kindRoutable(kind, ctx) {
|
|
3557
|
+
return !ctx.refusedCommandKinds?.has(kind);
|
|
3558
|
+
}
|
|
3559
|
+
function probeValues(m, ctx) {
|
|
3560
|
+
if (m.type === "bool")
|
|
3561
|
+
return [false, true];
|
|
3562
|
+
const { values } = resolvedEnum(m, ctx);
|
|
3563
|
+
const keys = values ? Object.keys(values).map(Number) : void 0;
|
|
3564
|
+
if (m.type === "string")
|
|
3565
|
+
return keys && values ? keys.map((k) => values[k]) : [""];
|
|
3566
|
+
if (m.type === "enum")
|
|
3567
|
+
return keys ?? [0];
|
|
3568
|
+
return keys ?? [m.min ?? 0];
|
|
3569
|
+
}
|
|
3570
|
+
function writeRoutable(m, ctx) {
|
|
3571
|
+
if (!ctx.refusedCommandKinds)
|
|
3572
|
+
return true;
|
|
3573
|
+
for (const value of probeValues(m, ctx)) {
|
|
3574
|
+
let kind;
|
|
3575
|
+
try {
|
|
3576
|
+
kind = m.write?.(value, ctx)?.kind;
|
|
3577
|
+
} catch {
|
|
3578
|
+
return true;
|
|
3579
|
+
}
|
|
3580
|
+
if (kind === void 0 || kindRoutable(kind, ctx))
|
|
3581
|
+
return true;
|
|
3582
|
+
}
|
|
3583
|
+
return false;
|
|
3584
|
+
}
|
|
3585
|
+
function actionRoutable(m, ctx) {
|
|
3586
|
+
if (!ctx.refusedCommandKinds)
|
|
3587
|
+
return true;
|
|
3588
|
+
let kind;
|
|
3589
|
+
try {
|
|
3590
|
+
kind = m.action(ctx).kind;
|
|
3591
|
+
} catch {
|
|
3592
|
+
return true;
|
|
3593
|
+
}
|
|
3594
|
+
return kindRoutable(kind, ctx);
|
|
3595
|
+
}
|
|
3528
3596
|
function bindMembers(members, deps) {
|
|
3529
3597
|
const { ctx, sink, read, rawDp: rawDp2 } = deps;
|
|
3530
3598
|
const out = {};
|
|
@@ -3550,7 +3618,7 @@ function bindMembers(members, deps) {
|
|
|
3550
3618
|
continue;
|
|
3551
3619
|
}
|
|
3552
3620
|
if ("action" in m) {
|
|
3553
|
-
if (installs(m, ctx))
|
|
3621
|
+
if (installs(m, ctx) && actionRoutable(m, ctx))
|
|
3554
3622
|
out[name] = describe(m.description, () => sink.dispatch(m.action(ctx)), {});
|
|
3555
3623
|
continue;
|
|
3556
3624
|
}
|
|
@@ -3567,7 +3635,7 @@ function bindMembers(members, deps) {
|
|
|
3567
3635
|
const get = decode ? () => decode(raw(), rawDp2, ctx) : () => narrow(m.type, read, prop, domain);
|
|
3568
3636
|
Object.defineProperty(out, name, { get, enumerable: true, configurable: true });
|
|
3569
3637
|
}
|
|
3570
|
-
if (!m.write || m.unverified || !installs(m, ctx))
|
|
3638
|
+
if (!m.write || m.unverified || !installs(m, ctx) || !writeRoutable(m, ctx))
|
|
3571
3639
|
continue;
|
|
3572
3640
|
if (m.writeOnly)
|
|
3573
3641
|
unobservable.push(name);
|
|
@@ -3683,73 +3751,6 @@ var VIDEO = {
|
|
|
3683
3751
|
detection: { evidenceParams: [1056], codecs: ["camera"] }
|
|
3684
3752
|
};
|
|
3685
3753
|
|
|
3686
|
-
// dist/model/device-family.js
|
|
3687
|
-
var INDOOR_CAMERA_TYPES = /* @__PURE__ */ new Set([
|
|
3688
|
-
DeviceType.INDOOR_CAMERA,
|
|
3689
|
-
DeviceType.INDOOR_CAMERA_1080,
|
|
3690
|
-
DeviceType.INDOOR_PT_CAMERA,
|
|
3691
|
-
DeviceType.INDOOR_PT_CAMERA_1080,
|
|
3692
|
-
DeviceType.INDOOR_OUTDOOR_CAMERA_1080P,
|
|
3693
|
-
DeviceType.INDOOR_OUTDOOR_CAMERA_1080P_NO_LIGHT,
|
|
3694
|
-
DeviceType.INDOOR_OUTDOOR_CAMERA_2K,
|
|
3695
|
-
DeviceType.INDOOR_COST_DOWN_CAMERA,
|
|
3696
|
-
DeviceType.INDOOR_PT_CAMERA_S350,
|
|
3697
|
-
DeviceType.INDOOR_PT_CAMERA_E30,
|
|
3698
|
-
DeviceType.INDOOR_PT_CAMERA_C210,
|
|
3699
|
-
DeviceType.INDOOR_PT_CAMERA_C220,
|
|
3700
|
-
DeviceType.INDOOR_PT_CAMERA_C220_V2
|
|
3701
|
-
]);
|
|
3702
|
-
var INDOOR_PT_S350_TYPES = /* @__PURE__ */ new Set([
|
|
3703
|
-
DeviceType.INDOOR_PT_CAMERA_S350,
|
|
3704
|
-
DeviceType.INDOOR_PT_CAMERA_E30,
|
|
3705
|
-
DeviceType.INDOOR_PT_CAMERA_C210,
|
|
3706
|
-
DeviceType.INDOOR_PT_CAMERA_C220,
|
|
3707
|
-
DeviceType.INDOOR_PT_CAMERA_C220_V2
|
|
3708
|
-
]);
|
|
3709
|
-
var OUTDOOR_PT_TYPES = /* @__PURE__ */ new Set([
|
|
3710
|
-
DeviceType.OUTDOOR_PT_CAMERA,
|
|
3711
|
-
DeviceType.SOLO_CAMERA_E30,
|
|
3712
|
-
DeviceType.CAMERA_S4,
|
|
3713
|
-
DeviceType.SOLOCAM_E42,
|
|
3714
|
-
DeviceType.CAMERA_4G_S330
|
|
3715
|
-
]);
|
|
3716
|
-
var FLOODLIGHT_TYPES = /* @__PURE__ */ new Set([
|
|
3717
|
-
DeviceType.FLOODLIGHT,
|
|
3718
|
-
DeviceType.FLOODLIGHT_CAMERA_8422,
|
|
3719
|
-
DeviceType.FLOODLIGHT_CAMERA_8423,
|
|
3720
|
-
DeviceType.FLOODLIGHT_CAMERA_8424,
|
|
3721
|
-
DeviceType.FLOODLIGHT_CAMERA_8425,
|
|
3722
|
-
DeviceType.FLOODLIGHT_CAMERA_8426
|
|
3723
|
-
]);
|
|
3724
|
-
var WALL_LIGHT_TYPES = /* @__PURE__ */ new Set([
|
|
3725
|
-
DeviceType.WALL_LIGHT_CAM,
|
|
3726
|
-
DeviceType.WALL_LIGHT_CAM_81A0,
|
|
3727
|
-
DeviceType.WALL_LIGHT_CAM_T86C1
|
|
3728
|
-
]);
|
|
3729
|
-
var HOMEBASE_TYPES = /* @__PURE__ */ new Set([
|
|
3730
|
-
DeviceType.STATION,
|
|
3731
|
-
DeviceType.HB3,
|
|
3732
|
-
DeviceType.STATION_9000,
|
|
3733
|
-
DeviceType.MINIBASE_CHIME,
|
|
3734
|
-
DeviceType.HOMEBASE_MINI
|
|
3735
|
-
]);
|
|
3736
|
-
var has = (set, t) => t !== void 0 && set.has(t);
|
|
3737
|
-
var isIndoorCamera = (ctx) => has(INDOOR_CAMERA_TYPES, ctx.deviceType);
|
|
3738
|
-
var isIndoorCamMini = (ctx) => ctx.deviceType === DeviceType.INDOOR_COST_DOWN_CAMERA;
|
|
3739
|
-
var isIndoorPanTiltS350 = (ctx) => has(INDOOR_PT_S350_TYPES, ctx.deviceType);
|
|
3740
|
-
var isHomeBase = (ctx) => has(HOMEBASE_TYPES, ctx.deviceType);
|
|
3741
|
-
var isStation9000 = (ctx) => ctx.deviceType === DeviceType.STATION_9000;
|
|
3742
|
-
var isNvrT8N00 = (ctx) => ctx.model === "T8N00";
|
|
3743
|
-
var NVR_MEDIA_CAMERA_MODELS = /* @__PURE__ */ new Set(["T8E00", "T8P00", "T8P10", "T8162", "T8410", "T8214"]);
|
|
3744
|
-
var isNvrMediaCamera = (ctx) => ctx.model !== void 0 && NVR_MEDIA_CAMERA_MODELS.has(ctx.model);
|
|
3745
|
-
var isNvrDualLensCamera = (ctx) => ctx.model === "T8E00";
|
|
3746
|
-
var isNvrFullHdCamera = (ctx) => ctx.model === "T8E00" || ctx.model === "T8P00";
|
|
3747
|
-
var isCallDoorbell = (ctx) => ctx.model === "T8223" || ctx.model === "T8224";
|
|
3748
|
-
var isAiotVacuum = (ctx) => ctx.category !== "eufy_home_tuya";
|
|
3749
|
-
var isTuyaVacuum = (ctx) => ctx.category === "eufy_home_tuya";
|
|
3750
|
-
var isVideoSmartLock = (ctx) => ctx.deviceType === DeviceType.LOCK_8530;
|
|
3751
|
-
var isClassicWifiLock = (ctx) => ctx.deviceType === DeviceType.LOCK_WIFI && typeof ctx.serial === "string" && ctx.serial.startsWith("T8520") && ctx.serial.charAt(6) === "2";
|
|
3752
|
-
|
|
3753
3754
|
// dist/model/capabilities/rtsp.js
|
|
3754
3755
|
var RTSP_PARAM = {
|
|
3755
3756
|
/**
|
|
@@ -3805,7 +3806,7 @@ var RtspRecordingMode = {
|
|
|
3805
3806
|
Continuous: 1
|
|
3806
3807
|
};
|
|
3807
3808
|
function publishable(ctx) {
|
|
3808
|
-
return
|
|
3809
|
+
return kindRoutable("set-param", ctx);
|
|
3809
3810
|
}
|
|
3810
3811
|
function publishCommand(on, ctx) {
|
|
3811
3812
|
return setScalar(RTSP_PARAM.STREAM_SWITCH, on ? 1 : 0, ctx);
|
|
@@ -3831,8 +3832,7 @@ var RTSP_MEMBERS = {
|
|
|
3831
3832
|
provenance: "apk",
|
|
3832
3833
|
description: "Whether this camera's stream is published over RTSP (1145 NAS_STREAM_SWITHC). Name from the apk; the WRITE is verified live on a HomeBase-attached doorbell and two indoor cameras, both directions (DESCRIBE 404\u2192200 with a real SDP, and back).",
|
|
3833
3834
|
write: (v, ctx) => publishCommand(asBool(v), ctx),
|
|
3834
|
-
aliases: { publish: true, withdraw: false }
|
|
3835
|
-
available: publishable
|
|
3835
|
+
aliases: { publish: true, withdraw: false }
|
|
3836
3836
|
},
|
|
3837
3837
|
/**
|
|
3838
3838
|
* The device-reported RTSP URL — the full `rtsp://user:pass@host/path`, carrying the credentials the
|
|
@@ -4781,8 +4781,8 @@ function decodePowerSource(raw) {
|
|
|
4781
4781
|
return String(raw);
|
|
4782
4782
|
}
|
|
4783
4783
|
}
|
|
4784
|
-
const
|
|
4785
|
-
return Number.isFinite(
|
|
4784
|
+
const num3 = Number(raw);
|
|
4785
|
+
return Number.isFinite(num3) ? num3 : String(raw);
|
|
4786
4786
|
}
|
|
4787
4787
|
function recordSetting(param, value, ctx) {
|
|
4788
4788
|
return setStationScalar(param, value, ctx.channel);
|
|
@@ -5283,6 +5283,73 @@ var CONTACT = {
|
|
|
5283
5283
|
}
|
|
5284
5284
|
};
|
|
5285
5285
|
|
|
5286
|
+
// dist/model/device-family.js
|
|
5287
|
+
var INDOOR_CAMERA_TYPES = /* @__PURE__ */ new Set([
|
|
5288
|
+
DeviceType.INDOOR_CAMERA,
|
|
5289
|
+
DeviceType.INDOOR_CAMERA_1080,
|
|
5290
|
+
DeviceType.INDOOR_PT_CAMERA,
|
|
5291
|
+
DeviceType.INDOOR_PT_CAMERA_1080,
|
|
5292
|
+
DeviceType.INDOOR_OUTDOOR_CAMERA_1080P,
|
|
5293
|
+
DeviceType.INDOOR_OUTDOOR_CAMERA_1080P_NO_LIGHT,
|
|
5294
|
+
DeviceType.INDOOR_OUTDOOR_CAMERA_2K,
|
|
5295
|
+
DeviceType.INDOOR_COST_DOWN_CAMERA,
|
|
5296
|
+
DeviceType.INDOOR_PT_CAMERA_S350,
|
|
5297
|
+
DeviceType.INDOOR_PT_CAMERA_E30,
|
|
5298
|
+
DeviceType.INDOOR_PT_CAMERA_C210,
|
|
5299
|
+
DeviceType.INDOOR_PT_CAMERA_C220,
|
|
5300
|
+
DeviceType.INDOOR_PT_CAMERA_C220_V2
|
|
5301
|
+
]);
|
|
5302
|
+
var INDOOR_PT_S350_TYPES = /* @__PURE__ */ new Set([
|
|
5303
|
+
DeviceType.INDOOR_PT_CAMERA_S350,
|
|
5304
|
+
DeviceType.INDOOR_PT_CAMERA_E30,
|
|
5305
|
+
DeviceType.INDOOR_PT_CAMERA_C210,
|
|
5306
|
+
DeviceType.INDOOR_PT_CAMERA_C220,
|
|
5307
|
+
DeviceType.INDOOR_PT_CAMERA_C220_V2
|
|
5308
|
+
]);
|
|
5309
|
+
var OUTDOOR_PT_TYPES = /* @__PURE__ */ new Set([
|
|
5310
|
+
DeviceType.OUTDOOR_PT_CAMERA,
|
|
5311
|
+
DeviceType.SOLO_CAMERA_E30,
|
|
5312
|
+
DeviceType.CAMERA_S4,
|
|
5313
|
+
DeviceType.SOLOCAM_E42,
|
|
5314
|
+
DeviceType.CAMERA_4G_S330
|
|
5315
|
+
]);
|
|
5316
|
+
var FLOODLIGHT_TYPES = /* @__PURE__ */ new Set([
|
|
5317
|
+
DeviceType.FLOODLIGHT,
|
|
5318
|
+
DeviceType.FLOODLIGHT_CAMERA_8422,
|
|
5319
|
+
DeviceType.FLOODLIGHT_CAMERA_8423,
|
|
5320
|
+
DeviceType.FLOODLIGHT_CAMERA_8424,
|
|
5321
|
+
DeviceType.FLOODLIGHT_CAMERA_8425,
|
|
5322
|
+
DeviceType.FLOODLIGHT_CAMERA_8426
|
|
5323
|
+
]);
|
|
5324
|
+
var WALL_LIGHT_TYPES = /* @__PURE__ */ new Set([
|
|
5325
|
+
DeviceType.WALL_LIGHT_CAM,
|
|
5326
|
+
DeviceType.WALL_LIGHT_CAM_81A0,
|
|
5327
|
+
DeviceType.WALL_LIGHT_CAM_T86C1
|
|
5328
|
+
]);
|
|
5329
|
+
var HOMEBASE_TYPES = /* @__PURE__ */ new Set([
|
|
5330
|
+
DeviceType.STATION,
|
|
5331
|
+
DeviceType.HB3,
|
|
5332
|
+
DeviceType.STATION_9000,
|
|
5333
|
+
DeviceType.MINIBASE_CHIME,
|
|
5334
|
+
DeviceType.HOMEBASE_MINI
|
|
5335
|
+
]);
|
|
5336
|
+
var has = (set, t) => t !== void 0 && set.has(t);
|
|
5337
|
+
var isIndoorCamera = (ctx) => has(INDOOR_CAMERA_TYPES, ctx.deviceType);
|
|
5338
|
+
var isIndoorCamMini = (ctx) => ctx.deviceType === DeviceType.INDOOR_COST_DOWN_CAMERA;
|
|
5339
|
+
var isIndoorPanTiltS350 = (ctx) => has(INDOOR_PT_S350_TYPES, ctx.deviceType);
|
|
5340
|
+
var isHomeBase = (ctx) => has(HOMEBASE_TYPES, ctx.deviceType);
|
|
5341
|
+
var isStation9000 = (ctx) => ctx.deviceType === DeviceType.STATION_9000;
|
|
5342
|
+
var isNvrT8N00 = (ctx) => ctx.model === "T8N00";
|
|
5343
|
+
var NVR_MEDIA_CAMERA_MODELS = /* @__PURE__ */ new Set(["T8E00", "T8P00", "T8P10", "T8162", "T8410", "T8214"]);
|
|
5344
|
+
var isNvrMediaCamera = (ctx) => ctx.model !== void 0 && NVR_MEDIA_CAMERA_MODELS.has(ctx.model);
|
|
5345
|
+
var isNvrDualLensCamera = (ctx) => ctx.model === "T8E00";
|
|
5346
|
+
var isNvrFullHdCamera = (ctx) => ctx.model === "T8E00" || ctx.model === "T8P00";
|
|
5347
|
+
var isCallDoorbell = (ctx) => ctx.model === "T8223" || ctx.model === "T8224";
|
|
5348
|
+
var isAiotVacuum = (ctx) => ctx.category !== "eufy_home_tuya";
|
|
5349
|
+
var isTuyaVacuum = (ctx) => ctx.category === "eufy_home_tuya";
|
|
5350
|
+
var isVideoSmartLock = (ctx) => ctx.deviceType === DeviceType.LOCK_8530;
|
|
5351
|
+
var isClassicWifiLock = (ctx) => ctx.deviceType === DeviceType.LOCK_WIFI && typeof ctx.serial === "string" && ctx.serial.startsWith("T8520") && ctx.serial.charAt(6) === "2";
|
|
5352
|
+
|
|
5286
5353
|
// dist/model/capabilities/audio.js
|
|
5287
5354
|
var AUDIO_CMD = {
|
|
5288
5355
|
/**
|
|
@@ -6057,10 +6124,10 @@ function isT8442(ctx) {
|
|
|
6057
6124
|
function usesHomeBasePowerPayload(ctx) {
|
|
6058
6125
|
if (!isT8410HomeBase3(ctx) || !ctx.firmwareVersion || !/^\d+(?:\.\d+){2,3}$/.test(ctx.firmwareVersion))
|
|
6059
6126
|
return false;
|
|
6060
|
-
const
|
|
6127
|
+
const version2 = ctx.firmwareVersion.split(".").map(Number);
|
|
6061
6128
|
const minimum = [2, 3, 1, 0];
|
|
6062
6129
|
for (let i = 0; i < minimum.length; i++) {
|
|
6063
|
-
const difference = (
|
|
6130
|
+
const difference = (version2[i] ?? 0) - minimum[i];
|
|
6064
6131
|
if (difference !== 0)
|
|
6065
6132
|
return difference > 0;
|
|
6066
6133
|
}
|
|
@@ -7213,17 +7280,17 @@ var SMART_LIGHT = {
|
|
|
7213
7280
|
const params = reportFrom(signal);
|
|
7214
7281
|
if (!params)
|
|
7215
7282
|
return null;
|
|
7216
|
-
const
|
|
7283
|
+
const num3 = (id) => params[id] === void 0 ? void 0 : Number(params[id]);
|
|
7217
7284
|
const bool = (id) => params[id] === void 0 ? void 0 : params[id] === "1";
|
|
7218
7285
|
return {
|
|
7219
7286
|
event: "smartLightState",
|
|
7220
7287
|
payload: {
|
|
7221
7288
|
power: bool(LIGHT_PARAM.POWER),
|
|
7222
|
-
brightness:
|
|
7223
|
-
lightLength:
|
|
7224
|
-
effectId:
|
|
7289
|
+
brightness: num3(LIGHT_PARAM.BRIGHTNESS),
|
|
7290
|
+
lightLength: num3(LIGHT_PARAM.LENGTH),
|
|
7291
|
+
effectId: num3(LIGHT_PARAM.EFFECT_ID),
|
|
7225
7292
|
colorGradient: bool(LIGHT_PARAM.COLOR_GRADIENT),
|
|
7226
|
-
cloudEffectId:
|
|
7293
|
+
cloudEffectId: num3(LIGHT_PARAM.CLOUD_EFFECT_ID)
|
|
7227
7294
|
}
|
|
7228
7295
|
};
|
|
7229
7296
|
},
|
|
@@ -9244,11 +9311,11 @@ function decodeDoNotDisturbTime(raw, codec, field) {
|
|
|
9244
9311
|
const point = codec.nested(window.value)?.find((f) => f.field === field);
|
|
9245
9312
|
if (point?.kind !== "bytes")
|
|
9246
9313
|
return void 0;
|
|
9247
|
-
const
|
|
9248
|
-
if (!
|
|
9314
|
+
const parts2 = codec.nested(point.value);
|
|
9315
|
+
if (!parts2)
|
|
9249
9316
|
return void 0;
|
|
9250
9317
|
const at = (n) => {
|
|
9251
|
-
const hit =
|
|
9318
|
+
const hit = parts2.find((f) => f.field === n);
|
|
9252
9319
|
return hit?.kind === "int" ? Number(hit.value) : 0;
|
|
9253
9320
|
};
|
|
9254
9321
|
return `${String(at(UNDISTURBED_FIELD.HOUR)).padStart(2, "0")}:${String(at(UNDISTURBED_FIELD.MINUTE)).padStart(2, "0")}`;
|
|
@@ -11242,12 +11309,12 @@ function parseDpCatalog(raw) {
|
|
|
11242
11309
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
11243
11310
|
return EMPTY_DP_CATALOG;
|
|
11244
11311
|
const r = raw;
|
|
11245
|
-
const
|
|
11246
|
-
if (!Array.isArray(
|
|
11312
|
+
const list2 = r.data_point_list;
|
|
11313
|
+
if (!Array.isArray(list2) || list2.length === 0)
|
|
11247
11314
|
return EMPTY_DP_CATALOG;
|
|
11248
11315
|
let found = 0;
|
|
11249
11316
|
const enumRanges = /* @__PURE__ */ new Map();
|
|
11250
|
-
for (const entry of
|
|
11317
|
+
for (const entry of list2) {
|
|
11251
11318
|
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
11252
11319
|
continue;
|
|
11253
11320
|
const e = entry;
|
|
@@ -11552,14 +11619,14 @@ function mergeProperties(caps, ctx) {
|
|
|
11552
11619
|
return merged;
|
|
11553
11620
|
}
|
|
11554
11621
|
function hintHaystack(rec) {
|
|
11555
|
-
const
|
|
11622
|
+
const parts2 = [rec.model, rec.category];
|
|
11556
11623
|
const loose = rec;
|
|
11557
11624
|
for (const key of ["name", "device_name", "alias", "product_name"]) {
|
|
11558
11625
|
const v = loose[key];
|
|
11559
11626
|
if (typeof v === "string")
|
|
11560
|
-
|
|
11627
|
+
parts2.push(v);
|
|
11561
11628
|
}
|
|
11562
|
-
return
|
|
11629
|
+
return parts2.filter((p) => typeof p === "string").join(" ");
|
|
11563
11630
|
}
|
|
11564
11631
|
var CODEC_LINE = {
|
|
11565
11632
|
station: "security",
|
|
@@ -11603,7 +11670,7 @@ function detectCapabilities(rec, codec) {
|
|
|
11603
11670
|
matched = d.deviceTypes.includes(rec.deviceType);
|
|
11604
11671
|
}
|
|
11605
11672
|
if (!matched && d.modelHints && haystack.length > 0) {
|
|
11606
|
-
matched = d.modelHints.some((
|
|
11673
|
+
matched = d.modelHints.some((re2) => re2.test(haystack));
|
|
11607
11674
|
}
|
|
11608
11675
|
if (!matched && d.codecs && codec !== void 0) {
|
|
11609
11676
|
matched = d.codecs.includes(codec);
|
|
@@ -11790,9 +11857,9 @@ function memberCommand(m, action, value, ctx) {
|
|
|
11790
11857
|
for (const [name, member] of Object.entries(m.members ?? {})) {
|
|
11791
11858
|
if (!("type" in member))
|
|
11792
11859
|
continue;
|
|
11793
|
-
const
|
|
11860
|
+
const property2 = member.property ?? name;
|
|
11794
11861
|
const aliased = member.aliases?.[action];
|
|
11795
|
-
const claims = action ===
|
|
11862
|
+
const claims = action === property2 || member.intentNames?.includes(action) === true;
|
|
11796
11863
|
if (!claims && aliased === void 0)
|
|
11797
11864
|
continue;
|
|
11798
11865
|
if (member.unverified) {
|
|
@@ -11800,7 +11867,10 @@ function memberCommand(m, action, value, ctx) {
|
|
|
11800
11867
|
}
|
|
11801
11868
|
if (!member.write || !installs(member, ctx))
|
|
11802
11869
|
continue;
|
|
11803
|
-
|
|
11870
|
+
const cmd = memberWrite(name, member, claims ? value : aliased, ctx);
|
|
11871
|
+
if (!kindRoutable(cmd.kind, ctx))
|
|
11872
|
+
continue;
|
|
11873
|
+
return cmd;
|
|
11804
11874
|
}
|
|
11805
11875
|
return void 0;
|
|
11806
11876
|
}
|
|
@@ -12000,6 +12070,7 @@ function resolveProperties(rec, codec, capabilities) {
|
|
|
12000
12070
|
category: rec.category,
|
|
12001
12071
|
capabilities: new Set(capabilities),
|
|
12002
12072
|
paramIds,
|
|
12073
|
+
things: rec.things,
|
|
12003
12074
|
stationSerial: rec.parentSn
|
|
12004
12075
|
});
|
|
12005
12076
|
}
|
|
@@ -14335,11 +14406,11 @@ function parseCleanRecords(raw) {
|
|
|
14335
14406
|
if (!raw || typeof raw !== "object" || Array.isArray(raw))
|
|
14336
14407
|
return EMPTY_CLEAN_RECORD_PAGE;
|
|
14337
14408
|
const r = raw;
|
|
14338
|
-
const
|
|
14339
|
-
if (!Array.isArray(
|
|
14409
|
+
const list2 = r.clean_record_list;
|
|
14410
|
+
if (!Array.isArray(list2))
|
|
14340
14411
|
return EMPTY_CLEAN_RECORD_PAGE;
|
|
14341
14412
|
const records = [];
|
|
14342
|
-
for (const entry of
|
|
14413
|
+
for (const entry of list2) {
|
|
14343
14414
|
if (!entry || typeof entry !== "object" || Array.isArray(entry))
|
|
14344
14415
|
continue;
|
|
14345
14416
|
const e = entry;
|
|
@@ -14401,17 +14472,17 @@ function parseCleanRecordDetail(blob, codec) {
|
|
|
14401
14472
|
const fields = codec.nested(Buffer.from(body));
|
|
14402
14473
|
if (!fields)
|
|
14403
14474
|
return void 0;
|
|
14404
|
-
const
|
|
14475
|
+
const num3 = (field) => {
|
|
14405
14476
|
const found = fields.find((f) => f.field === field);
|
|
14406
14477
|
return found?.kind === "int" ? Number(found.value) : 0;
|
|
14407
14478
|
};
|
|
14408
14479
|
const reason = fields.find((f) => f.field === DETAIL_FIELD.FINISH_REASON);
|
|
14409
14480
|
return {
|
|
14410
|
-
startTime:
|
|
14411
|
-
endTime:
|
|
14412
|
-
duration:
|
|
14413
|
-
area:
|
|
14414
|
-
cleanType:
|
|
14481
|
+
startTime: num3(DETAIL_FIELD.START_TIME),
|
|
14482
|
+
endTime: num3(DETAIL_FIELD.END_TIME),
|
|
14483
|
+
duration: num3(DETAIL_FIELD.DURATION),
|
|
14484
|
+
area: num3(DETAIL_FIELD.AREA),
|
|
14485
|
+
cleanType: num3(DETAIL_FIELD.CLEAN_TYPE),
|
|
14415
14486
|
// An absent reason is the enum's zero member, which is `completed` — the ordinary way a run ends.
|
|
14416
14487
|
finishReason: reason === void 0 ? CLEAN_FINISH_REASONS[0] : reason.kind === "int" ? CLEAN_FINISH_REASONS[Number(reason.value)] : void 0
|
|
14417
14488
|
};
|
|
@@ -14904,6 +14975,7 @@ function inspectParams(rec, sn) {
|
|
|
14904
14975
|
},
|
|
14905
14976
|
suggestedRegistry: { model, entry, exists: !!MODEL_REGISTRY[model.toUpperCase()] },
|
|
14906
14977
|
registrySnippet: buildRegistrySnippet(model, entry),
|
|
14978
|
+
things: rec.things,
|
|
14907
14979
|
dictionarySnippet: buildDictSnippet(model, unknown)
|
|
14908
14980
|
};
|
|
14909
14981
|
}
|
|
@@ -15198,9 +15270,9 @@ function sceneNum(v) {
|
|
|
15198
15270
|
return void 0;
|
|
15199
15271
|
}
|
|
15200
15272
|
function solarbankSceneReadings(scene) {
|
|
15201
|
-
const
|
|
15273
|
+
const list2 = scene.solarbank_info?.solarbank_list ?? [];
|
|
15202
15274
|
const out = [];
|
|
15203
|
-
for (const sb of
|
|
15275
|
+
for (const sb of list2) {
|
|
15204
15276
|
const deviceSn = typeof sb.device_sn === "string" ? sb.device_sn : void 0;
|
|
15205
15277
|
if (!deviceSn)
|
|
15206
15278
|
continue;
|
|
@@ -16428,11 +16500,11 @@ var CMD_CAMERA_INFO = 1103;
|
|
|
16428
16500
|
var GCM_AAD = Buffer.from("eufy security");
|
|
16429
16501
|
var LEVEL2_SEQ_BASE = 16909056;
|
|
16430
16502
|
function paramReport(payload) {
|
|
16431
|
-
const
|
|
16432
|
-
if (!Array.isArray(
|
|
16503
|
+
const list2 = payload?.params;
|
|
16504
|
+
if (!Array.isArray(list2))
|
|
16433
16505
|
return void 0;
|
|
16434
16506
|
const out = {};
|
|
16435
|
-
for (const entry of
|
|
16507
|
+
for (const entry of list2) {
|
|
16436
16508
|
const p = entry;
|
|
16437
16509
|
if (typeof p?.param_type !== "number" || p.param_value == null)
|
|
16438
16510
|
continue;
|
|
@@ -16441,11 +16513,11 @@ function paramReport(payload) {
|
|
|
16441
16513
|
return Object.keys(out).length ? out : void 0;
|
|
16442
16514
|
}
|
|
16443
16515
|
function channelReport(payload) {
|
|
16444
|
-
const
|
|
16445
|
-
if (!Array.isArray(
|
|
16516
|
+
const list2 = payload?.params;
|
|
16517
|
+
if (!Array.isArray(list2))
|
|
16446
16518
|
return void 0;
|
|
16447
16519
|
const out = {};
|
|
16448
|
-
for (const entry of
|
|
16520
|
+
for (const entry of list2) {
|
|
16449
16521
|
const p = entry;
|
|
16450
16522
|
if (typeof p?.dev_type !== "number" || typeof p.param_type !== "number" || p.param_value == null)
|
|
16451
16523
|
continue;
|
|
@@ -18266,19 +18338,19 @@ var P2PSession = class _P2PSession extends EventEmitter2 {
|
|
|
18266
18338
|
if (!this.connectAddress)
|
|
18267
18339
|
throw new Error("not connected");
|
|
18268
18340
|
const channel = opts.channel ?? 0;
|
|
18269
|
-
const
|
|
18341
|
+
const keyed2 = opts.key !== void 0;
|
|
18270
18342
|
const inner = opts.rawValue ?? {
|
|
18271
|
-
...
|
|
18343
|
+
...keyed2 ? { key: opts.key } : {},
|
|
18272
18344
|
account_id: opts.accountId ?? "",
|
|
18273
18345
|
cmd: subCmd,
|
|
18274
18346
|
mChannel: channel,
|
|
18275
18347
|
mValue3: 0,
|
|
18276
18348
|
...opts.omitPayload ? {} : { payload }
|
|
18277
18349
|
};
|
|
18278
|
-
const value =
|
|
18350
|
+
const value = keyed2 ? JSON.stringify(inner).replace(/=/g, "\\u003d") : JSON.stringify(inner);
|
|
18279
18351
|
const body = Buffer.concat([
|
|
18280
18352
|
buildCommandHeader(this.seqNumber, opts.wrapCmd ?? CMD_SET_PAYLOAD),
|
|
18281
|
-
buildStringCommandPayload(value, channel,
|
|
18353
|
+
buildStringCommandPayload(value, channel, keyed2 ? void 0 : this.level1Key, 1)
|
|
18282
18354
|
]);
|
|
18283
18355
|
this.seqNumber = this.seqNumber + 1 & 65535;
|
|
18284
18356
|
this.logger.debug(`[p2p] ${this.cfg.stationSn} sendSetPayload subCmd=${subCmd}`);
|
|
@@ -22091,15 +22163,15 @@ var Fmp4Muxer = class {
|
|
|
22091
22163
|
avcC() {
|
|
22092
22164
|
const ps = this.params;
|
|
22093
22165
|
const sps = ps.sps[0] ?? Buffer.alloc(4);
|
|
22094
|
-
const
|
|
22166
|
+
const parts2 = [
|
|
22095
22167
|
Buffer.from([1, sps[1] ?? 66, sps[2] ?? 0, sps[3] ?? 30, 255, 224 | ps.sps.length])
|
|
22096
22168
|
];
|
|
22097
22169
|
for (const s of ps.sps)
|
|
22098
|
-
|
|
22099
|
-
|
|
22170
|
+
parts2.push(u16(s.length), s);
|
|
22171
|
+
parts2.push(Buffer.from([ps.pps.length]));
|
|
22100
22172
|
for (const p of ps.pps)
|
|
22101
|
-
|
|
22102
|
-
return Buffer.concat(
|
|
22173
|
+
parts2.push(u16(p.length), p);
|
|
22174
|
+
return Buffer.concat(parts2);
|
|
22103
22175
|
}
|
|
22104
22176
|
hvcC() {
|
|
22105
22177
|
const ps = this.params;
|
|
@@ -22143,10 +22215,10 @@ var Fmp4Muxer = class {
|
|
|
22143
22215
|
const push = (nalType, nals) => {
|
|
22144
22216
|
if (!nals.length)
|
|
22145
22217
|
return;
|
|
22146
|
-
const
|
|
22218
|
+
const parts2 = [Buffer.from([128 | nalType]), u16(nals.length)];
|
|
22147
22219
|
for (const n of nals)
|
|
22148
|
-
|
|
22149
|
-
arrays.push(Buffer.concat(
|
|
22220
|
+
parts2.push(u16(n.length), n);
|
|
22221
|
+
arrays.push(Buffer.concat(parts2));
|
|
22150
22222
|
};
|
|
22151
22223
|
push(32, ps.vps);
|
|
22152
22224
|
push(33, ps.sps);
|
|
@@ -22188,11 +22260,11 @@ var Fmp4Muxer = class {
|
|
|
22188
22260
|
*/
|
|
22189
22261
|
trun(samples) {
|
|
22190
22262
|
const flags = 1793;
|
|
22191
|
-
const
|
|
22263
|
+
const parts2 = [u32(flags), u32(samples.length), u32(0)];
|
|
22192
22264
|
for (const s of samples) {
|
|
22193
|
-
|
|
22265
|
+
parts2.push(u32(s.duration), u32(s.data.length), u32(s.keyframe ? 33554432 : 16842752));
|
|
22194
22266
|
}
|
|
22195
|
-
return box("trun", Buffer.concat(
|
|
22267
|
+
return box("trun", Buffer.concat(parts2));
|
|
22196
22268
|
}
|
|
22197
22269
|
hasAudioTrack() {
|
|
22198
22270
|
return !!this.audioCodec && !this.audioDisabled;
|
|
@@ -24745,10 +24817,10 @@ var H264Depacketizer = class {
|
|
|
24745
24817
|
}
|
|
24746
24818
|
if (marker) {
|
|
24747
24819
|
if (!this.broken && !this.fu && this.nals.length) {
|
|
24748
|
-
const
|
|
24820
|
+
const parts2 = [];
|
|
24749
24821
|
for (const n of this.nals)
|
|
24750
|
-
|
|
24751
|
-
this.onUnit(Buffer.concat(
|
|
24822
|
+
parts2.push(START_CODE, n);
|
|
24823
|
+
this.onUnit(Buffer.concat(parts2), timestamp);
|
|
24752
24824
|
}
|
|
24753
24825
|
this.nals = [];
|
|
24754
24826
|
this.fu = void 0;
|
|
@@ -24902,18 +24974,18 @@ var PtcsReassembler = class {
|
|
|
24902
24974
|
if (p.lastIndex === void 0)
|
|
24903
24975
|
return true;
|
|
24904
24976
|
let total = 0;
|
|
24905
|
-
const
|
|
24977
|
+
const parts2 = [];
|
|
24906
24978
|
for (let i = 0; i <= p.lastIndex; i++) {
|
|
24907
24979
|
const c = p.chunks.get(i);
|
|
24908
24980
|
if (!c)
|
|
24909
24981
|
return true;
|
|
24910
|
-
|
|
24982
|
+
parts2.push(c);
|
|
24911
24983
|
total += c.length;
|
|
24912
24984
|
}
|
|
24913
24985
|
this.partials.delete(key);
|
|
24914
24986
|
if (total !== p.frameLength)
|
|
24915
24987
|
return false;
|
|
24916
|
-
this.onFrame(Buffer.concat(
|
|
24988
|
+
this.onFrame(Buffer.concat(parts2, total), p.channel);
|
|
24917
24989
|
return true;
|
|
24918
24990
|
}
|
|
24919
24991
|
/** Drop frames that stopped arriving; call periodically. */
|
|
@@ -25886,6 +25958,11 @@ var StationStreamBusyError = class extends Error {
|
|
|
25886
25958
|
this.name = "StationStreamBusyError";
|
|
25887
25959
|
}
|
|
25888
25960
|
};
|
|
25961
|
+
var RTC_CONTROL_COMMAND_KINDS = /* @__PURE__ */ new Set([
|
|
25962
|
+
"set-payload",
|
|
25963
|
+
"set-json"
|
|
25964
|
+
]);
|
|
25965
|
+
var isRtcControlCommand = (cmd) => RTC_CONTROL_COMMAND_KINDS.has(cmd.kind);
|
|
25889
25966
|
var RtcCommandRouter = class {
|
|
25890
25967
|
deps;
|
|
25891
25968
|
sessions = /* @__PURE__ */ new Map();
|
|
@@ -25899,7 +25976,7 @@ var RtcCommandRouter = class {
|
|
|
25899
25976
|
this.deps = deps;
|
|
25900
25977
|
}
|
|
25901
25978
|
async dispatchCommand(route, cmd) {
|
|
25902
|
-
if (cmd
|
|
25979
|
+
if (!isRtcControlCommand(cmd)) {
|
|
25903
25980
|
throw new Error(`rtc: ${cmd.kind} is not routable over the RTC control channel (only set-payload or set-json)`);
|
|
25904
25981
|
}
|
|
25905
25982
|
if (route.mediaTrack)
|
|
@@ -28462,10 +28539,10 @@ var McsParser = class extends EventEmitter12 {
|
|
|
28462
28539
|
}
|
|
28463
28540
|
}
|
|
28464
28541
|
onVersion() {
|
|
28465
|
-
const
|
|
28542
|
+
const version2 = this.data.readInt8(0);
|
|
28466
28543
|
this.data = this.data.subarray(1);
|
|
28467
|
-
if (
|
|
28468
|
-
throw new Error(`MCS: wrong protocol version ${
|
|
28544
|
+
if (version2 < 38)
|
|
28545
|
+
throw new Error(`MCS: wrong protocol version ${version2}`);
|
|
28469
28546
|
this.onTag();
|
|
28470
28547
|
}
|
|
28471
28548
|
onTag() {
|
|
@@ -29155,7 +29232,272 @@ function mediaFailureTag(error) {
|
|
|
29155
29232
|
return Number.isInteger(status) && status >= 100 && status <= 599 ? { cause, status } : { cause };
|
|
29156
29233
|
}
|
|
29157
29234
|
|
|
29235
|
+
// dist/model/capabilities/thing-description.js
|
|
29236
|
+
var APP_SDK_VERSION = "2.3.3.1";
|
|
29237
|
+
var SUFFIXED_STATION_PREFIXES = ["T8010", "T8020", "T8021", "T8023"];
|
|
29238
|
+
function re(pattern, value) {
|
|
29239
|
+
if (!pattern || !value)
|
|
29240
|
+
return true;
|
|
29241
|
+
if (pattern.length > 512 || value.length > 2048)
|
|
29242
|
+
return false;
|
|
29243
|
+
try {
|
|
29244
|
+
const insensitive = pattern.includes("(?i)");
|
|
29245
|
+
return new RegExp(pattern.replaceAll("(?i)", ""), insensitive ? "i" : "").test(value);
|
|
29246
|
+
} catch {
|
|
29247
|
+
return false;
|
|
29248
|
+
}
|
|
29249
|
+
}
|
|
29250
|
+
var parts = (v) => v.split(".");
|
|
29251
|
+
var intOf = (s) => {
|
|
29252
|
+
const t = (s ?? "0").replace(/[a-zA-Z]+$/, "");
|
|
29253
|
+
return /^[+-]?\d+$/.test(t) ? Number(t) : void 0;
|
|
29254
|
+
};
|
|
29255
|
+
var numericPrefix = (p) => {
|
|
29256
|
+
const i = p.findIndex((s) => intOf(s) === void 0);
|
|
29257
|
+
return i < 0 ? p.length : i;
|
|
29258
|
+
};
|
|
29259
|
+
function versionAbove(a, b) {
|
|
29260
|
+
const pa = parts(a);
|
|
29261
|
+
const pb = parts(b);
|
|
29262
|
+
const n = Math.max(numericPrefix(pa), numericPrefix(pb));
|
|
29263
|
+
for (let i = 0; i < n; i++) {
|
|
29264
|
+
const d = (intOf(pa[i]) ?? 0) - (intOf(pb[i]) ?? 0);
|
|
29265
|
+
if (d !== 0)
|
|
29266
|
+
return d > 0;
|
|
29267
|
+
}
|
|
29268
|
+
const ta = pa.slice(n);
|
|
29269
|
+
const tb = pb.slice(n);
|
|
29270
|
+
if (!ta.length || !tb.length)
|
|
29271
|
+
return ta.length > 0 && !tb.length;
|
|
29272
|
+
const lastInt = (t) => t.findLastIndex((s) => /^[+-]?\d+$/.test(s));
|
|
29273
|
+
const ia = lastInt(ta);
|
|
29274
|
+
const ib = lastInt(tb);
|
|
29275
|
+
const head = (t, i) => (i >= 0 ? t.slice(0, i) : t).join(".");
|
|
29276
|
+
if (head(ta, ia) !== head(tb, ib))
|
|
29277
|
+
return false;
|
|
29278
|
+
return (ia >= 0 ? Number(ta[ia]) : 0) > (ib >= 0 ? Number(tb[ib]) : 0);
|
|
29279
|
+
}
|
|
29280
|
+
function versionEqual(a, b) {
|
|
29281
|
+
const pa = parts(a);
|
|
29282
|
+
const pb = parts(b);
|
|
29283
|
+
const n = Math.max(numericPrefix(pa), numericPrefix(pb));
|
|
29284
|
+
for (let i = 0; i < n; i++)
|
|
29285
|
+
if ((intOf(pa[i]) ?? 0) !== (intOf(pb[i]) ?? 0))
|
|
29286
|
+
return false;
|
|
29287
|
+
return pa.slice(n).join(".") === pb.slice(n).join(".");
|
|
29288
|
+
}
|
|
29289
|
+
function version(current, qualifier, target) {
|
|
29290
|
+
switch (qualifier) {
|
|
29291
|
+
case "<":
|
|
29292
|
+
return versionAbove(target, current);
|
|
29293
|
+
case "<=":
|
|
29294
|
+
return versionAbove(target, current) || versionEqual(current, target);
|
|
29295
|
+
case "=":
|
|
29296
|
+
return versionEqual(current, target);
|
|
29297
|
+
case "!=":
|
|
29298
|
+
return !versionEqual(current, target);
|
|
29299
|
+
case ">=":
|
|
29300
|
+
return versionAbove(current, target) || versionEqual(current, target);
|
|
29301
|
+
case ">":
|
|
29302
|
+
return versionAbove(current, target);
|
|
29303
|
+
case "RE":
|
|
29304
|
+
return re(target, current);
|
|
29305
|
+
default:
|
|
29306
|
+
return false;
|
|
29307
|
+
}
|
|
29308
|
+
}
|
|
29309
|
+
function compare(current, qualifier, target) {
|
|
29310
|
+
if (qualifier === "RE")
|
|
29311
|
+
return re(target, current);
|
|
29312
|
+
switch (qualifier) {
|
|
29313
|
+
case "=":
|
|
29314
|
+
return current === target;
|
|
29315
|
+
case "!=":
|
|
29316
|
+
return current !== target;
|
|
29317
|
+
case "<":
|
|
29318
|
+
return current < target;
|
|
29319
|
+
case "<=":
|
|
29320
|
+
return current <= target;
|
|
29321
|
+
case ">=":
|
|
29322
|
+
return current >= target;
|
|
29323
|
+
case ">":
|
|
29324
|
+
return current > target;
|
|
29325
|
+
default:
|
|
29326
|
+
return false;
|
|
29327
|
+
}
|
|
29328
|
+
}
|
|
29329
|
+
function cameraInfo(facts, qualifier, value) {
|
|
29330
|
+
let spec;
|
|
29331
|
+
try {
|
|
29332
|
+
spec = JSON.parse(value);
|
|
29333
|
+
} catch {
|
|
29334
|
+
return false;
|
|
29335
|
+
}
|
|
29336
|
+
const reported = typeof spec?.param === "number" ? facts.params?.[spec.param] : void 0;
|
|
29337
|
+
if (reported === void 0)
|
|
29338
|
+
return false;
|
|
29339
|
+
if (qualifier === "equals")
|
|
29340
|
+
return typeof spec.value === "string" && spec.value === reported;
|
|
29341
|
+
if (qualifier === "RE")
|
|
29342
|
+
return typeof spec.regex === "string" && re(spec.regex, reported);
|
|
29343
|
+
return false;
|
|
29344
|
+
}
|
|
29345
|
+
function condition(c, facts) {
|
|
29346
|
+
const station = facts.stationSerial ?? facts.serial ?? "";
|
|
29347
|
+
switch (c.type) {
|
|
29348
|
+
case "device_version":
|
|
29349
|
+
return version(facts.firmwareVersion ?? "", c.qualifier, c.value);
|
|
29350
|
+
case "parent_version": {
|
|
29351
|
+
const v = facts.stationFirmwareVersion ?? "";
|
|
29352
|
+
const clean = SUFFIXED_STATION_PREFIXES.some((p) => station.startsWith(p)) ? v.replace(/[^0-9.][^.]*/g, "") : v;
|
|
29353
|
+
return version(clean, c.qualifier, c.value);
|
|
29354
|
+
}
|
|
29355
|
+
case "parent_sn":
|
|
29356
|
+
return re(c.value, station);
|
|
29357
|
+
case "device_sn":
|
|
29358
|
+
return re(c.value, facts.serial ?? "");
|
|
29359
|
+
case "user_country":
|
|
29360
|
+
return re(c.value, facts.country ?? "");
|
|
29361
|
+
case "user_domain":
|
|
29362
|
+
return re(c.value, "");
|
|
29363
|
+
case "sdk_version":
|
|
29364
|
+
return version(APP_SDK_VERSION, c.qualifier, c.value);
|
|
29365
|
+
case "associated_field":
|
|
29366
|
+
case "parent_associated_field":
|
|
29367
|
+
return compare("", c.qualifier, c.value);
|
|
29368
|
+
case "user_permission":
|
|
29369
|
+
return c.qualifier === "in";
|
|
29370
|
+
case "camera_info":
|
|
29371
|
+
return cameraInfo(facts, c.qualifier, c.value);
|
|
29372
|
+
default:
|
|
29373
|
+
return false;
|
|
29374
|
+
}
|
|
29375
|
+
}
|
|
29376
|
+
function conditionsPass(list2, facts) {
|
|
29377
|
+
return list2.length === 0 || list2.some((entry) => entry.every((c) => condition(c, facts)));
|
|
29378
|
+
}
|
|
29379
|
+
var bare = (identifier) => {
|
|
29380
|
+
const i = identifier.toLowerCase().indexOf("__v");
|
|
29381
|
+
return i > 0 ? identifier.slice(0, i) : identifier;
|
|
29382
|
+
};
|
|
29383
|
+
function resolveThing(td, facts) {
|
|
29384
|
+
const properties = /* @__PURE__ */ Object.create(null);
|
|
29385
|
+
const keys = Object.keys(td.properties);
|
|
29386
|
+
for (const base of new Set(keys.map(bare))) {
|
|
29387
|
+
let chosen = base;
|
|
29388
|
+
let most = -1;
|
|
29389
|
+
for (const key of keys) {
|
|
29390
|
+
if (key === base || bare(key) !== base)
|
|
29391
|
+
continue;
|
|
29392
|
+
const p2 = td.properties[key];
|
|
29393
|
+
if (p2.readConditions.length === 0 || !conditionsPass(p2.readConditions, facts))
|
|
29394
|
+
continue;
|
|
29395
|
+
const count2 = p2.readConditions.reduce((n, entry) => n + entry.length, 0);
|
|
29396
|
+
if (count2 > most)
|
|
29397
|
+
[chosen, most] = [key, count2];
|
|
29398
|
+
}
|
|
29399
|
+
const p = td.properties[chosen];
|
|
29400
|
+
if (!p || !conditionsPass(p.availableConditions, facts))
|
|
29401
|
+
continue;
|
|
29402
|
+
properties[base] = conditionsPass(p.writeConditions, facts) ? p : { ...p, accessMode: "R" };
|
|
29403
|
+
}
|
|
29404
|
+
const available = (entries) => {
|
|
29405
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
29406
|
+
for (const [k, v] of Object.entries(entries))
|
|
29407
|
+
if (conditionsPass(v.availableConditions, facts))
|
|
29408
|
+
out[k] = v;
|
|
29409
|
+
return out;
|
|
29410
|
+
};
|
|
29411
|
+
return { ...td, properties, actions: available(td.actions), events: available(td.events) };
|
|
29412
|
+
}
|
|
29413
|
+
var str3 = (v) => typeof v === "string" ? v : v == null ? "" : String(v);
|
|
29414
|
+
var optStr = (v) => v == null || v === "" ? void 0 : str3(v);
|
|
29415
|
+
var num2 = (v) => {
|
|
29416
|
+
const n = typeof v === "number" ? v : typeof v === "string" && v.trim() !== "" ? Number(v) : NaN;
|
|
29417
|
+
return Number.isFinite(n) ? n : void 0;
|
|
29418
|
+
};
|
|
29419
|
+
var list = (v) => Array.isArray(v) ? v.filter((x) => x && typeof x === "object") : [];
|
|
29420
|
+
function conditions(v) {
|
|
29421
|
+
return list(v?.condition_list).map((entry) => list(entry.conditions).map((c) => ({
|
|
29422
|
+
type: str3(c.type),
|
|
29423
|
+
qualifier: str3(c.qualifier),
|
|
29424
|
+
value: str3(c.value),
|
|
29425
|
+
...c.prop_id ? { propId: str3(c.prop_id) } : {}
|
|
29426
|
+
})));
|
|
29427
|
+
}
|
|
29428
|
+
function keyed(entries, parse) {
|
|
29429
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
29430
|
+
for (const e of entries)
|
|
29431
|
+
if (typeof e.identifier === "string" && e.identifier)
|
|
29432
|
+
out[e.identifier] = parse(e);
|
|
29433
|
+
return out;
|
|
29434
|
+
}
|
|
29435
|
+
function property(p) {
|
|
29436
|
+
const specs = p.data_type?.specs ?? {};
|
|
29437
|
+
return {
|
|
29438
|
+
identifier: p.identifier,
|
|
29439
|
+
accessMode: str3(p.access_mode),
|
|
29440
|
+
type: str3(p.data_type?.type),
|
|
29441
|
+
members: list(specs.eunmList).map((m) => ({
|
|
29442
|
+
value: str3(m.value),
|
|
29443
|
+
...m.associatedValue != null ? { wireValue: str3(m.associatedValue) } : {},
|
|
29444
|
+
desc: str3(m.desc),
|
|
29445
|
+
isDefault: m.isDefault === 1 || m.isDefault === true
|
|
29446
|
+
})),
|
|
29447
|
+
...optStr(specs.defaultValue) !== void 0 ? { defaultValue: str3(specs.defaultValue) } : {},
|
|
29448
|
+
...num2(specs.min) !== void 0 ? { min: num2(specs.min) } : {},
|
|
29449
|
+
...num2(specs.max) !== void 0 ? { max: num2(specs.max) } : {},
|
|
29450
|
+
...num2(specs.step) !== void 0 ? { step: num2(specs.step) } : {},
|
|
29451
|
+
...optStr(specs.unit) !== void 0 ? { unit: str3(specs.unit) } : {},
|
|
29452
|
+
readConditions: conditions(p.read_conditions),
|
|
29453
|
+
writeConditions: conditions(p.write_conditions),
|
|
29454
|
+
availableConditions: conditions(p.available_conditions)
|
|
29455
|
+
};
|
|
29456
|
+
}
|
|
29457
|
+
function parseThingsList(raw) {
|
|
29458
|
+
const out = /* @__PURE__ */ Object.create(null);
|
|
29459
|
+
for (const t of list(raw?.things_list)) {
|
|
29460
|
+
const profile = t.profile ?? {};
|
|
29461
|
+
const code = profile.product_code;
|
|
29462
|
+
if (typeof code !== "string" || !code)
|
|
29463
|
+
continue;
|
|
29464
|
+
out[code] = {
|
|
29465
|
+
productCode: code,
|
|
29466
|
+
version: str3(t.version),
|
|
29467
|
+
updateTime: num2(t.update_time) ?? 0,
|
|
29468
|
+
largeVersion: num2(t.large_version) ?? 0,
|
|
29469
|
+
largeVersionUpdateTime: num2(t.large_version_update_time) ?? 0,
|
|
29470
|
+
bundle: {
|
|
29471
|
+
id: str3(profile.plugin_id),
|
|
29472
|
+
path: str3(profile.plugin_path),
|
|
29473
|
+
zipId: str3(profile.plugin_id_zip),
|
|
29474
|
+
zipPath: str3(profile.plugin_path_zip)
|
|
29475
|
+
},
|
|
29476
|
+
properties: keyed(list(t.properties), property),
|
|
29477
|
+
actions: keyed(list(t.actions), (a) => ({
|
|
29478
|
+
identifier: a.identifier,
|
|
29479
|
+
...optStr(a.input_data?.type) ? { inputType: str3(a.input_data.type) } : {},
|
|
29480
|
+
...optStr(a.output_data?.type) ? { outputType: str3(a.output_data.type) } : {},
|
|
29481
|
+
availableConditions: conditions(a.available_conditions)
|
|
29482
|
+
})),
|
|
29483
|
+
events: keyed(list(t.events), (e) => ({
|
|
29484
|
+
identifier: e.identifier,
|
|
29485
|
+
eventType: str3(e.event_type),
|
|
29486
|
+
...optStr(e.output_data?.type) ? { outputType: str3(e.output_data.type) } : {},
|
|
29487
|
+
...optStr(e.output_data?.specs?.defaultValue) ? { defaultValue: str3(e.output_data.specs.defaultValue) } : {},
|
|
29488
|
+
availableConditions: conditions(e.available_conditions)
|
|
29489
|
+
}))
|
|
29490
|
+
};
|
|
29491
|
+
}
|
|
29492
|
+
return out;
|
|
29493
|
+
}
|
|
29494
|
+
|
|
29158
29495
|
// dist/client/device-registry.js
|
|
29496
|
+
function recordString(raw, key) {
|
|
29497
|
+
const nested = raw.deviceParams?.[key];
|
|
29498
|
+
const v = typeof nested === "string" && nested ? nested : raw[key];
|
|
29499
|
+
return typeof v === "string" && v ? v : void 0;
|
|
29500
|
+
}
|
|
29159
29501
|
function mergeParams(raw, params, paramUpdatedAt) {
|
|
29160
29502
|
for (const p of raw ?? []) {
|
|
29161
29503
|
if (!p || p.param_type == null || p.param_value == null)
|
|
@@ -29226,6 +29568,8 @@ var DeviceRegistry = class {
|
|
|
29226
29568
|
deviceCapsCache = /* @__PURE__ */ new Map();
|
|
29227
29569
|
/** Per-serial cloud data points of an AIoT robot, joined beneath the params in {@link record} — see {@link loadCloudDps}. */
|
|
29228
29570
|
cloudDps = /* @__PURE__ */ new Map();
|
|
29571
|
+
/** Per-product-code thing description — see {@link loadThings}; `undefined` for a code the cloud returned none for. */
|
|
29572
|
+
things = /* @__PURE__ */ new Map();
|
|
29229
29573
|
/** Per-serial realtime state, keyed by param id in the device's own namespace (see {@link DeviceRecord.dpParams}). */
|
|
29230
29574
|
dpParams = /* @__PURE__ */ new Map();
|
|
29231
29575
|
/** Callers blocked in {@link awaitRealtimeState}, released by the device's first report. */
|
|
@@ -29339,6 +29683,7 @@ var DeviceRegistry = class {
|
|
|
29339
29683
|
}
|
|
29340
29684
|
}
|
|
29341
29685
|
await this.loadCloudDps(seen);
|
|
29686
|
+
await this.loadThings(seen);
|
|
29342
29687
|
this.lastRefreshPartial = partial;
|
|
29343
29688
|
if (partial) {
|
|
29344
29689
|
for (const prev of this.devices)
|
|
@@ -29465,6 +29810,45 @@ var DeviceRegistry = class {
|
|
|
29465
29810
|
this.cloudDps.set(sn, dps);
|
|
29466
29811
|
}
|
|
29467
29812
|
}
|
|
29813
|
+
/**
|
|
29814
|
+
* The device's product description resolved for this device ({@link resolveThing}): against its serial
|
|
29815
|
+
* and firmware (`main_sw_version`), the station it is reached through and that station's firmware, the
|
|
29816
|
+
* account's country and its reported params.
|
|
29817
|
+
*/
|
|
29818
|
+
thingsFor(dev, station, params) {
|
|
29819
|
+
const td = this.things.get(dev.model ?? "");
|
|
29820
|
+
if (!td)
|
|
29821
|
+
return void 0;
|
|
29822
|
+
const firmware = (d) => recordString(d?.raw ?? {}, "main_sw_version");
|
|
29823
|
+
return resolveThing(td, {
|
|
29824
|
+
serial: dev.sn,
|
|
29825
|
+
firmwareVersion: firmware(dev),
|
|
29826
|
+
stationSerial: station,
|
|
29827
|
+
stationFirmwareVersion: firmware(this.devices.find((d) => d.sn === station)),
|
|
29828
|
+
country: this.mega.countryCode,
|
|
29829
|
+
params
|
|
29830
|
+
});
|
|
29831
|
+
}
|
|
29832
|
+
/**
|
|
29833
|
+
* Fetch, once per start, the thing description of each product code the account has, in one
|
|
29834
|
+
* `get_things_list` call. A failed call is logged and asked again on the next refresh.
|
|
29835
|
+
*/
|
|
29836
|
+
async loadThings(seen) {
|
|
29837
|
+
const codes = [...new Set([...seen.values()].map((d) => d.model ?? ""))].filter((c) => c && !this.things.has(c));
|
|
29838
|
+
if (!codes.length)
|
|
29839
|
+
return;
|
|
29840
|
+
let parsed;
|
|
29841
|
+
try {
|
|
29842
|
+
parsed = parseThingsList(await this.mega.getThingsList(codes));
|
|
29843
|
+
} catch (e) {
|
|
29844
|
+
if (e instanceof SessionExpiredError)
|
|
29845
|
+
throw e;
|
|
29846
|
+
this.logger.debug(`[registry] thing descriptions unavailable: ${e?.message ?? e}`);
|
|
29847
|
+
return;
|
|
29848
|
+
}
|
|
29849
|
+
for (const code of codes)
|
|
29850
|
+
this.things.set(code, parsed[code]);
|
|
29851
|
+
}
|
|
29468
29852
|
/**
|
|
29469
29853
|
* Resolve a serial to a {@link DeviceRecord} with current params: starts from the device-list params, then
|
|
29470
29854
|
* overlays a fresh `get_device_param_list` when that call is available to this account. An AIoT robot's
|
|
@@ -29529,7 +29913,8 @@ var DeviceRegistry = class {
|
|
|
29529
29913
|
parentSn: station === sn ? void 0 : station,
|
|
29530
29914
|
params,
|
|
29531
29915
|
paramUpdatedAt,
|
|
29532
|
-
dpParams: this.dpParams.get(sn)
|
|
29916
|
+
dpParams: this.dpParams.get(sn),
|
|
29917
|
+
things: this.thingsFor(dev, station, params)
|
|
29533
29918
|
};
|
|
29534
29919
|
}
|
|
29535
29920
|
/**
|
|
@@ -29798,11 +30183,6 @@ var PushRepeats = class {
|
|
|
29798
30183
|
};
|
|
29799
30184
|
|
|
29800
30185
|
// dist/client/eufy-mega.js
|
|
29801
|
-
function recordString(raw, key) {
|
|
29802
|
-
const nested = raw.deviceParams?.[key];
|
|
29803
|
-
const v = typeof nested === "string" && nested ? nested : raw[key];
|
|
29804
|
-
return typeof v === "string" && v ? v : void 0;
|
|
29805
|
-
}
|
|
29806
30186
|
function adminUserIdFrom(raw) {
|
|
29807
30187
|
const member = (raw ?? {}).member;
|
|
29808
30188
|
const id = member?.admin_user_id;
|
|
@@ -29823,6 +30203,16 @@ var PUSH_RETRY_MIN_MS = 3e4;
|
|
|
29823
30203
|
var PUSH_RETRY_MAX_MS = 6e5;
|
|
29824
30204
|
var STATION_REOPEN_MIN_MS = 5e3;
|
|
29825
30205
|
var STATION_REOPEN_MAX_MS = 3e5;
|
|
30206
|
+
var PORTAL_COMMAND_KINDS = /* @__PURE__ */ new Set([
|
|
30207
|
+
"set-payload",
|
|
30208
|
+
"set-json",
|
|
30209
|
+
"set-param",
|
|
30210
|
+
"set-json-raw",
|
|
30211
|
+
"p2p-station-scalar",
|
|
30212
|
+
"p2p-int-string",
|
|
30213
|
+
"p2p-privacy-burst"
|
|
30214
|
+
]);
|
|
30215
|
+
var RTC_CONTROL_REFUSED_KINDS = new Set([...PORTAL_COMMAND_KINDS].filter((kind) => !RTC_CONTROL_COMMAND_KINDS.has(kind)));
|
|
29826
30216
|
var RealtimeStartupSupersededError = class extends Error {
|
|
29827
30217
|
};
|
|
29828
30218
|
var RefreshWindowClosedError = class extends Error {
|
|
@@ -31934,6 +32324,8 @@ var EufyMega = class _EufyMega extends EventEmitter14 {
|
|
|
31934
32324
|
const parentRaw = parent?.raw;
|
|
31935
32325
|
const resolved = resolveDevice(rec);
|
|
31936
32326
|
const dpCatalog = (resolved.codec === "vacuum" || resolved.codec === "mower") && rec.model ? await this.fetchDpCatalog(rec.model) : void 0;
|
|
32327
|
+
const rtcRoute = this.rtcRouteFor(sn);
|
|
32328
|
+
const refusedCommandKinds = !rtcRoute ? void 0 : rtcRoute.mediaTrack ? PORTAL_COMMAND_KINDS : RTC_CONTROL_REFUSED_KINDS;
|
|
31937
32329
|
return {
|
|
31938
32330
|
channel,
|
|
31939
32331
|
timezone: recordString(parentRaw ?? {}, "time_zone"),
|
|
@@ -31954,6 +32346,7 @@ var EufyMega = class _EufyMega extends EventEmitter14 {
|
|
|
31954
32346
|
macAddress: recordString(raw, "wifi_mac"),
|
|
31955
32347
|
updateAvailable: raw.needUpdate === true || raw.needUpdate === 1 || raw.needUpdate === "1",
|
|
31956
32348
|
paramIds: new Set([...Object.keys(rec.params), ...Object.keys(rec.dpParams ?? {})].map(Number)),
|
|
32349
|
+
things: rec.things,
|
|
31957
32350
|
capabilities: new Set(resolved.capabilities),
|
|
31958
32351
|
// Member identity for ff09-* command devices (see core/contracts Ff09Identity).
|
|
31959
32352
|
adminUserId: typeof member.admin_user_id === "string" ? member.admin_user_id : void 0,
|
|
@@ -31965,6 +32358,7 @@ var EufyMega = class _EufyMega extends EventEmitter14 {
|
|
|
31965
32358
|
// Topology as the record states it: a parent that isn't the device itself means HomeBase-attached.
|
|
31966
32359
|
homeBaseAttached: !!raw.parent_sn && raw.parent_sn !== dev.sn,
|
|
31967
32360
|
stationDeviceType: this.stationDeviceTypeOf(sn),
|
|
32361
|
+
refusedCommandKinds,
|
|
31968
32362
|
dpCatalog
|
|
31969
32363
|
};
|
|
31970
32364
|
}
|
|
@@ -32473,8 +32867,8 @@ var SolixClient = class _SolixClient {
|
|
|
32473
32867
|
*/
|
|
32474
32868
|
async getSites() {
|
|
32475
32869
|
const data = await this.authed("POST", SOLIX_ENDPOINTS.getSiteList, {});
|
|
32476
|
-
const
|
|
32477
|
-
return
|
|
32870
|
+
const list2 = data?.site_list ?? [];
|
|
32871
|
+
return list2.filter((s) => typeof s?.site_id === "string" && s.site_id.length > 0);
|
|
32478
32872
|
}
|
|
32479
32873
|
/** Per-user AWS-IoT MQTT credentials (cert/key/endpoint/thing) for the real-time device plane. */
|
|
32480
32874
|
async getUserMqttInfo() {
|
|
@@ -32742,21 +33136,21 @@ function solixStateReadings(frame) {
|
|
|
32742
33136
|
continue;
|
|
32743
33137
|
const type = value[0];
|
|
32744
33138
|
const pl = value.subarray(1);
|
|
32745
|
-
let
|
|
33139
|
+
let num3;
|
|
32746
33140
|
if (type === 5 && pl.length >= 4)
|
|
32747
|
-
|
|
33141
|
+
num3 = pl.readFloatLE(0);
|
|
32748
33142
|
else if (type === 2 && pl.length >= 2)
|
|
32749
|
-
|
|
33143
|
+
num3 = pl.readUInt16LE(0);
|
|
32750
33144
|
else if (type === 1 && pl.length >= 1)
|
|
32751
|
-
|
|
33145
|
+
num3 = pl[0];
|
|
32752
33146
|
else if (type === 3 && pl.length >= 2)
|
|
32753
|
-
|
|
32754
|
-
if (
|
|
33147
|
+
num3 = pl[1];
|
|
33148
|
+
if (num3 === void 0)
|
|
32755
33149
|
continue;
|
|
32756
|
-
out[`state_${tag2.toString(16)}`] =
|
|
33150
|
+
out[`state_${tag2.toString(16)}`] = num3;
|
|
32757
33151
|
const name = SOLIX_STATE_FIELD_NAMES[tag2];
|
|
32758
33152
|
if (name)
|
|
32759
|
-
out[name] =
|
|
33153
|
+
out[name] = num3;
|
|
32760
33154
|
}
|
|
32761
33155
|
return out;
|
|
32762
33156
|
}
|
|
@@ -33042,9 +33436,9 @@ var SolixMqtt = class extends EventEmitter15 {
|
|
|
33042
33436
|
const frame = decodeSolixParamFrame(buf);
|
|
33043
33437
|
if (!frame)
|
|
33044
33438
|
return;
|
|
33045
|
-
const
|
|
33046
|
-
const productCode =
|
|
33047
|
-
let deviceSn = frame.deviceSn ??
|
|
33439
|
+
const parts2 = topic.split("/");
|
|
33440
|
+
const productCode = parts2[2] ?? "";
|
|
33441
|
+
let deviceSn = frame.deviceSn ?? parts2[3] ?? "";
|
|
33048
33442
|
if (!this.watched.has(deviceSn)) {
|
|
33049
33443
|
const ofProduct = [...this.watched.values()].filter((d) => d.product_code === productCode);
|
|
33050
33444
|
if (ofProduct.length === 1)
|
|
@@ -33082,9 +33476,9 @@ var SolixMqtt = class extends EventEmitter15 {
|
|
|
33082
33476
|
values.displayTimeoutIndex = a5[1];
|
|
33083
33477
|
if (Object.keys(values).length === 0)
|
|
33084
33478
|
return;
|
|
33085
|
-
const
|
|
33086
|
-
const productCode =
|
|
33087
|
-
let deviceSn = frame.deviceSn ??
|
|
33479
|
+
const parts2 = topic.split("/");
|
|
33480
|
+
const productCode = parts2[2] ?? "";
|
|
33481
|
+
let deviceSn = frame.deviceSn ?? parts2[3] ?? "";
|
|
33088
33482
|
if (!this.watched.has(deviceSn)) {
|
|
33089
33483
|
const ofProduct = [...this.watched.values()].filter((d) => d.product_code === productCode);
|
|
33090
33484
|
if (ofProduct.length === 1)
|