@apocaliss92/nodedreame 1.11.1 → 1.11.3
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.cjs +108 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +37 -1
- package/dist/index.d.ts +37 -1
- package/dist/index.js +106 -14
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -44,6 +44,7 @@ __export(index_exports, {
|
|
|
44
44
|
DreameTransportError: () => DreameTransportError,
|
|
45
45
|
LIBRARY_NAME: () => LIBRARY_NAME,
|
|
46
46
|
MOWER_MODEL_CAPABILITIES: () => MODEL_CAPABILITIES2,
|
|
47
|
+
MOWER_TASK_SUBSTATES: () => MOWER_TASK_SUBSTATES,
|
|
47
48
|
MiotError: () => MiotError,
|
|
48
49
|
MiotState: () => MiotState,
|
|
49
50
|
MowerCapabilityResolver: () => MowerCapabilityResolver,
|
|
@@ -75,6 +76,7 @@ __export(index_exports, {
|
|
|
75
76
|
isDreameConsumableKey: () => isDreameConsumableKey,
|
|
76
77
|
mowerConsumableIndex: () => mowerConsumableIndex,
|
|
77
78
|
parseMowerConsumables: () => parseMowerConsumables,
|
|
79
|
+
parseMowerHeartbeat: () => parseMowerHeartbeat,
|
|
78
80
|
renderMowerSvg: () => renderMowerSvg,
|
|
79
81
|
renderVacuumPng: () => renderVacuumPng,
|
|
80
82
|
resolveCapabilities: () => resolveCapabilities,
|
|
@@ -84,7 +86,7 @@ module.exports = __toCommonJS(index_exports);
|
|
|
84
86
|
|
|
85
87
|
// src/support/version.ts
|
|
86
88
|
var LIBRARY_NAME = "nodedreame";
|
|
87
|
-
var LIBRARY_VERSION = "1.11.
|
|
89
|
+
var LIBRARY_VERSION = "1.11.3";
|
|
88
90
|
|
|
89
91
|
// src/transport/errors.ts
|
|
90
92
|
var DreameError = class extends Error {
|
|
@@ -142,8 +144,11 @@ function buildRlcHeader(region, lang, country) {
|
|
|
142
144
|
function randomMqttClientId() {
|
|
143
145
|
return "p_" + (0, import_node_crypto.randomBytes)(8).toString("hex");
|
|
144
146
|
}
|
|
147
|
+
var MAX_REQUEST_ID = 16777215;
|
|
148
|
+
var nextRequestId = Math.floor(Math.random() * 100) + 1;
|
|
145
149
|
function randomRequestId() {
|
|
146
|
-
|
|
150
|
+
nextRequestId = nextRequestId >= MAX_REQUEST_ID ? 1 : nextRequestId + 1;
|
|
151
|
+
return nextRequestId;
|
|
147
152
|
}
|
|
148
153
|
|
|
149
154
|
// src/auth/config.ts
|
|
@@ -342,7 +347,7 @@ var OAuthTokenResponseSchema = import_zod.z.object({
|
|
|
342
347
|
error: import_zod.z.string().optional(),
|
|
343
348
|
error_description: import_zod.z.string().optional(),
|
|
344
349
|
code: import_zod.z.number().optional(),
|
|
345
|
-
msg: import_zod.z.string().
|
|
350
|
+
msg: import_zod.z.string().nullish()
|
|
346
351
|
}).passthrough();
|
|
347
352
|
var RawDeviceSchema = import_zod.z.object({
|
|
348
353
|
did: import_zod.z.union([import_zod.z.string(), import_zod.z.number()]).optional(),
|
|
@@ -357,7 +362,7 @@ var RawDeviceSchema = import_zod.z.object({
|
|
|
357
362
|
}).passthrough();
|
|
358
363
|
var DeviceListResponseSchema = import_zod.z.object({
|
|
359
364
|
code: import_zod.z.number().optional(),
|
|
360
|
-
msg: import_zod.z.string().
|
|
365
|
+
msg: import_zod.z.string().nullish(),
|
|
361
366
|
data: import_zod.z.object({
|
|
362
367
|
page: import_zod.z.object({ records: import_zod.z.array(RawDeviceSchema).optional() }).partial().optional(),
|
|
363
368
|
records: import_zod.z.array(RawDeviceSchema).optional()
|
|
@@ -377,12 +382,12 @@ var CachedPropEntrySchema = import_zod.z.object({
|
|
|
377
382
|
}).passthrough();
|
|
378
383
|
var CachedPropsResponseSchema = import_zod.z.object({
|
|
379
384
|
code: import_zod.z.number().optional(),
|
|
380
|
-
msg: import_zod.z.string().
|
|
385
|
+
msg: import_zod.z.string().nullish(),
|
|
381
386
|
data: import_zod.z.array(CachedPropEntrySchema).optional()
|
|
382
387
|
}).passthrough();
|
|
383
388
|
var SendCommandResponseSchema = import_zod.z.object({
|
|
384
389
|
code: import_zod.z.number().optional(),
|
|
385
|
-
msg: import_zod.z.string().
|
|
390
|
+
msg: import_zod.z.string().nullish(),
|
|
386
391
|
data: import_zod.z.object({ result: import_zod.z.unknown().optional() }).passthrough().optional(),
|
|
387
392
|
result: import_zod.z.unknown().optional()
|
|
388
393
|
}).passthrough();
|
|
@@ -1659,7 +1664,9 @@ function encodeAiFeatureWrite(raw, feature, value) {
|
|
|
1659
1664
|
if (typeof raw === "number") {
|
|
1660
1665
|
const bit = AI_FEATURE_BIT[feature];
|
|
1661
1666
|
if (bit === void 0) {
|
|
1662
|
-
throw new Error(
|
|
1667
|
+
throw new Error(
|
|
1668
|
+
`encodeAiFeatureWrite: feature "${feature}" has no int-bitmask representation`
|
|
1669
|
+
);
|
|
1663
1670
|
}
|
|
1664
1671
|
return value ? raw | bit : raw & ~bit;
|
|
1665
1672
|
}
|
|
@@ -1776,18 +1783,53 @@ function encodeAutoSwitchWrite(key2, value) {
|
|
|
1776
1783
|
|
|
1777
1784
|
// src/models/vacuum/consumables.ts
|
|
1778
1785
|
var VACUUM_CONSUMABLES = [
|
|
1779
|
-
{
|
|
1780
|
-
|
|
1786
|
+
{
|
|
1787
|
+
key: "main-brush",
|
|
1788
|
+
label: "Main Brush",
|
|
1789
|
+
life: { siid: 9, piid: 2 },
|
|
1790
|
+
reset: { siid: 9, aiid: 1 }
|
|
1791
|
+
},
|
|
1792
|
+
{
|
|
1793
|
+
key: "side-brush",
|
|
1794
|
+
label: "Side Brush",
|
|
1795
|
+
life: { siid: 10, piid: 2 },
|
|
1796
|
+
reset: { siid: 10, aiid: 1 }
|
|
1797
|
+
},
|
|
1781
1798
|
{ key: "filter", label: "Filter", life: { siid: 11, piid: 1 }, reset: { siid: 11, aiid: 1 } },
|
|
1782
1799
|
{ key: "sensor", label: "Sensor", life: { siid: 16, piid: 1 }, reset: { siid: 16, aiid: 1 } },
|
|
1783
|
-
{
|
|
1800
|
+
{
|
|
1801
|
+
key: "tank-filter",
|
|
1802
|
+
label: "Tank Filter",
|
|
1803
|
+
life: { siid: 17, piid: 1 },
|
|
1804
|
+
reset: { siid: 17, aiid: 1 }
|
|
1805
|
+
},
|
|
1784
1806
|
{ key: "mop-pad", label: "Mop Pad", life: { siid: 18, piid: 1 }, reset: { siid: 18, aiid: 1 } },
|
|
1785
|
-
{
|
|
1786
|
-
|
|
1807
|
+
{
|
|
1808
|
+
key: "silver-ion",
|
|
1809
|
+
label: "Silver-ion",
|
|
1810
|
+
life: { siid: 19, piid: 2 },
|
|
1811
|
+
reset: { siid: 19, aiid: 1 }
|
|
1812
|
+
},
|
|
1813
|
+
{
|
|
1814
|
+
key: "detergent",
|
|
1815
|
+
label: "Detergent",
|
|
1816
|
+
life: { siid: 20, piid: 1 },
|
|
1817
|
+
reset: { siid: 20, aiid: 1 }
|
|
1818
|
+
},
|
|
1787
1819
|
{ key: "squeegee", label: "Squeegee", life: { siid: 24, piid: 1 }, reset: { siid: 24, aiid: 1 } },
|
|
1788
|
-
{
|
|
1820
|
+
{
|
|
1821
|
+
key: "deodorizer",
|
|
1822
|
+
label: "Deodorizer",
|
|
1823
|
+
life: { siid: 29, piid: 2 },
|
|
1824
|
+
reset: { siid: 29, aiid: 1 }
|
|
1825
|
+
},
|
|
1789
1826
|
{ key: "wheel", label: "Wheel", life: { siid: 30, piid: 2 }, reset: { siid: 30, aiid: 1 } },
|
|
1790
|
-
{
|
|
1827
|
+
{
|
|
1828
|
+
key: "scale-inhibitor",
|
|
1829
|
+
label: "Scale Inhibitor",
|
|
1830
|
+
life: { siid: 31, piid: 2 },
|
|
1831
|
+
reset: { siid: 31, aiid: 1 }
|
|
1832
|
+
},
|
|
1791
1833
|
{ key: "dust-bag", label: "Dust Bag", life: { siid: 27, piid: 17 }, reset: null }
|
|
1792
1834
|
];
|
|
1793
1835
|
function consumableSpec(key2) {
|
|
@@ -3902,6 +3944,9 @@ var VacuumDevice = class _VacuumDevice extends BaseDevice {
|
|
|
3902
3944
|
|
|
3903
3945
|
// src/models/mower/properties.ts
|
|
3904
3946
|
var MOWER_PROP = {
|
|
3947
|
+
/** VERIFIED-by-donor — 20-byte heartbeat (sentinel 0xCE at [0]/[19]); byte 11
|
|
3948
|
+
* battery, byte 12 main-state, byte 13 task sub-state. See parseHeartbeat. */
|
|
3949
|
+
HEARTBEAT: { siid: 1, piid: 1 },
|
|
3905
3950
|
/** VERIFIED-by-donor — pose + coverage telemetry (binary). P4 uses progress % only. */
|
|
3906
3951
|
POSE_COVERAGE: { siid: 1, piid: 4 },
|
|
3907
3952
|
/** VERIFIED-by-donor — MowerStatus (DeviceStatus). */
|
|
@@ -4251,6 +4296,39 @@ function parseMowerConsumables(result) {
|
|
|
4251
4296
|
};
|
|
4252
4297
|
});
|
|
4253
4298
|
}
|
|
4299
|
+
var MOWER_TASK_SUBSTATES = [
|
|
4300
|
+
"idle",
|
|
4301
|
+
"starting",
|
|
4302
|
+
"mowing",
|
|
4303
|
+
"paused",
|
|
4304
|
+
"finished",
|
|
4305
|
+
"failed",
|
|
4306
|
+
"exit",
|
|
4307
|
+
"returning-to-dock"
|
|
4308
|
+
];
|
|
4309
|
+
var HEARTBEAT_SENTINEL = 206;
|
|
4310
|
+
var HEARTBEAT_SUBSTATE_BASE = 33;
|
|
4311
|
+
var HEARTBEAT_MAIN_STATE_MOWING = 4;
|
|
4312
|
+
function parseMowerHeartbeat(value) {
|
|
4313
|
+
if (!Array.isArray(value) || value.length < 14) {
|
|
4314
|
+
return null;
|
|
4315
|
+
}
|
|
4316
|
+
const bytes = [];
|
|
4317
|
+
for (const b of value) {
|
|
4318
|
+
if (typeof b !== "number") {
|
|
4319
|
+
return null;
|
|
4320
|
+
}
|
|
4321
|
+
bytes.push(b);
|
|
4322
|
+
}
|
|
4323
|
+
if (bytes[0] !== HEARTBEAT_SENTINEL || bytes[bytes.length - 1] !== HEARTBEAT_SENTINEL) {
|
|
4324
|
+
return null;
|
|
4325
|
+
}
|
|
4326
|
+
const rawBattery = bytes[11] ?? 0;
|
|
4327
|
+
const mainState = ((bytes[12] ?? 0) & 15) - 1;
|
|
4328
|
+
const subStateRaw = bytes[13] ?? 0;
|
|
4329
|
+
const taskSubState = mainState === HEARTBEAT_MAIN_STATE_MOWING ? MOWER_TASK_SUBSTATES[subStateRaw - HEARTBEAT_SUBSTATE_BASE] ?? null : null;
|
|
4330
|
+
return { rawBattery, mainState, subStateRaw, taskSubState };
|
|
4331
|
+
}
|
|
4254
4332
|
|
|
4255
4333
|
// src/models/mower/capabilities.ts
|
|
4256
4334
|
var FALLBACK2 = {
|
|
@@ -4924,6 +5002,19 @@ var MowerDevice = class _MowerDevice extends BaseDevice {
|
|
|
4924
5002
|
get fault() {
|
|
4925
5003
|
return FAULT(this.faultRaw);
|
|
4926
5004
|
}
|
|
5005
|
+
/**
|
|
5006
|
+
* Live mowing task sub-state decoded from the HEARTBEAT (1:1) blob —
|
|
5007
|
+
* idle/starting/mowing/paused/finished/failed/exit/returning-to-dock — or null
|
|
5008
|
+
* when no mowing session is in progress (or the heartbeat is absent). This is
|
|
5009
|
+
* the donor's "current task" sensor; the heartbeat is push-only (the mower does
|
|
5010
|
+
* not answer live reads), so it tracks the device while it is actively mowing.
|
|
5011
|
+
*/
|
|
5012
|
+
get taskSubState() {
|
|
5013
|
+
const hb = parseMowerHeartbeat(
|
|
5014
|
+
this.getProperty(MOWER_PROP.HEARTBEAT.siid, MOWER_PROP.HEARTBEAT.piid)?.value
|
|
5015
|
+
);
|
|
5016
|
+
return hb?.taskSubState ?? null;
|
|
5017
|
+
}
|
|
4927
5018
|
/** Parsed scheduling task descriptor (2:50), or null. */
|
|
4928
5019
|
get task() {
|
|
4929
5020
|
return parseTaskDescriptor(
|
|
@@ -5115,6 +5206,7 @@ var MowerDevice = class _MowerDevice extends BaseDevice {
|
|
|
5115
5206
|
}
|
|
5116
5207
|
/** Props worth seeding on start() / polling — exported for the facade. */
|
|
5117
5208
|
static DEFAULT_PROPS = [
|
|
5209
|
+
MOWER_PROP.HEARTBEAT,
|
|
5118
5210
|
MOWER_PROP.STATUS,
|
|
5119
5211
|
MOWER_PROP.DEVICE_CODE,
|
|
5120
5212
|
MOWER_PROP.BATTERY,
|
|
@@ -5743,6 +5835,7 @@ function createClientDumper(client, options) {
|
|
|
5743
5835
|
DreameTransportError,
|
|
5744
5836
|
LIBRARY_NAME,
|
|
5745
5837
|
MOWER_MODEL_CAPABILITIES,
|
|
5838
|
+
MOWER_TASK_SUBSTATES,
|
|
5746
5839
|
MiotError,
|
|
5747
5840
|
MiotState,
|
|
5748
5841
|
MowerCapabilityResolver,
|
|
@@ -5774,6 +5867,7 @@ function createClientDumper(client, options) {
|
|
|
5774
5867
|
isDreameConsumableKey,
|
|
5775
5868
|
mowerConsumableIndex,
|
|
5776
5869
|
parseMowerConsumables,
|
|
5870
|
+
parseMowerHeartbeat,
|
|
5777
5871
|
renderMowerSvg,
|
|
5778
5872
|
renderVacuumPng,
|
|
5779
5873
|
resolveCapabilities,
|