@apocaliss92/nodedreame 1.11.0 → 1.11.2
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 +134 -28
- 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 +132 -28
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -1849,6 +1849,31 @@ declare function extractMowerConsumableValues(result: unknown): number[] | null;
|
|
|
1849
1849
|
* maintenance) with remaining %. Returns null on a malformed response.
|
|
1850
1850
|
*/
|
|
1851
1851
|
declare function parseMowerConsumables(result: unknown): readonly MowerConsumableReading[] | null;
|
|
1852
|
+
/** Decoded mowing task sub-state (heartbeat byte 13), or null when no mowing
|
|
1853
|
+
* session is in progress. Ported from antondaubert/dreame-mower
|
|
1854
|
+
* `property_misc.py` Property11Handler. */
|
|
1855
|
+
type MowerTaskSubState = 'idle' | 'starting' | 'mowing' | 'paused' | 'finished' | 'failed' | 'exit' | 'returning-to-dock';
|
|
1856
|
+
/** Ordered sub-state table; the heartbeat encodes `subState = base + index`. */
|
|
1857
|
+
declare const MOWER_TASK_SUBSTATES: readonly MowerTaskSubState[];
|
|
1858
|
+
/** Typed heartbeat decode: battery byte, main-state, and (when mowing) the task
|
|
1859
|
+
* sub-state. */
|
|
1860
|
+
interface MowerHeartbeat {
|
|
1861
|
+
/** Raw battery byte (byte 11) — percent with a charging flag in the high bits. */
|
|
1862
|
+
readonly rawBattery: number;
|
|
1863
|
+
/** `(byte12 & 0x0F) - 1`; 4 = mowing. */
|
|
1864
|
+
readonly mainState: number;
|
|
1865
|
+
/** Raw sub-state byte (byte 13). */
|
|
1866
|
+
readonly subStateRaw: number;
|
|
1867
|
+
/** Decoded sub-state when a mowing session is active, else null. */
|
|
1868
|
+
readonly taskSubState: MowerTaskSubState | null;
|
|
1869
|
+
}
|
|
1870
|
+
/**
|
|
1871
|
+
* Decode the 20-byte HEARTBEAT (1:1) blob. Returns null when the payload is not a
|
|
1872
|
+
* well-formed heartbeat (wrong length / missing 0xCE sentinels). The task
|
|
1873
|
+
* sub-state is only meaningful while `mainState === 4` (mowing); in any other
|
|
1874
|
+
* main state there is no active mowing task (returns `taskSubState: null`).
|
|
1875
|
+
*/
|
|
1876
|
+
declare function parseMowerHeartbeat(value: unknown): MowerHeartbeat | null;
|
|
1852
1877
|
|
|
1853
1878
|
/**
|
|
1854
1879
|
* Per-model mower capability records + a resolver adapting the rich record into
|
|
@@ -2053,6 +2078,14 @@ declare class MowerDevice extends BaseDevice {
|
|
|
2053
2078
|
* code — which still surfaces as the raw number via {@link faultRaw}.
|
|
2054
2079
|
*/
|
|
2055
2080
|
get fault(): MowerFault | null;
|
|
2081
|
+
/**
|
|
2082
|
+
* Live mowing task sub-state decoded from the HEARTBEAT (1:1) blob —
|
|
2083
|
+
* idle/starting/mowing/paused/finished/failed/exit/returning-to-dock — or null
|
|
2084
|
+
* when no mowing session is in progress (or the heartbeat is absent). This is
|
|
2085
|
+
* the donor's "current task" sensor; the heartbeat is push-only (the mower does
|
|
2086
|
+
* not answer live reads), so it tracks the device while it is actively mowing.
|
|
2087
|
+
*/
|
|
2088
|
+
get taskSubState(): MowerTaskSubState | null;
|
|
2056
2089
|
/** Parsed scheduling task descriptor (2:50), or null. */
|
|
2057
2090
|
get task(): MowerTaskDescriptor | null;
|
|
2058
2091
|
/**
|
|
@@ -2135,6 +2168,9 @@ declare class MowerDevice extends BaseDevice {
|
|
|
2135
2168
|
mapSvg(opts?: RenderMowerSvgOptions): Promise<string>;
|
|
2136
2169
|
/** Props worth seeding on start() / polling — exported for the facade. */
|
|
2137
2170
|
static readonly DEFAULT_PROPS: readonly [{
|
|
2171
|
+
readonly siid: 1;
|
|
2172
|
+
readonly piid: 1;
|
|
2173
|
+
}, {
|
|
2138
2174
|
readonly siid: 2;
|
|
2139
2175
|
readonly piid: 1;
|
|
2140
2176
|
}, {
|
|
@@ -2493,4 +2529,4 @@ declare function createDumper(target: DumperDevice, options?: DumperOptions): Du
|
|
|
2493
2529
|
*/
|
|
2494
2530
|
declare function createClientDumper(client: Nodreame, options?: DumperOptions): Dumper[];
|
|
2495
2531
|
|
|
2496
|
-
export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, AUTO_SWITCH_JSON_KEY, type AiDetectionRaw, type AutoSwitchKey, type AutoSwitchRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type ConsumableReading, type ConsumableSpec, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameConsumableKey, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapColorScheme, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerConsumableKey, type MowerConsumableReading, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, VACUUM_CONSUMABLES, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, consumableSpec, createClientDumper, createDumper, decodeAiFeature, decodeAutoSwitch, decodeAutoSwitchAll, encodeAiFeatureWrite, encodeAutoSwitchWrite, extractMowerConsumableValues, getMowerCapabilities, getVacuumCapabilities, isDreameConsumableKey, mowerConsumableIndex, parseMowerConsumables, renderMowerSvg, renderVacuumPng, resolveCapabilities, supportedAutoSwitchKeys };
|
|
2532
|
+
export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, AUTO_SWITCH_JSON_KEY, type AiDetectionRaw, type AutoSwitchKey, type AutoSwitchRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type ConsumableReading, type ConsumableSpec, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameConsumableKey, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, MOWER_TASK_SUBSTATES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapColorScheme, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerConsumableKey, type MowerConsumableReading, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerHeartbeat, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerTaskSubState, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, VACUUM_CONSUMABLES, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, consumableSpec, createClientDumper, createDumper, decodeAiFeature, decodeAutoSwitch, decodeAutoSwitchAll, encodeAiFeatureWrite, encodeAutoSwitchWrite, extractMowerConsumableValues, getMowerCapabilities, getVacuumCapabilities, isDreameConsumableKey, mowerConsumableIndex, parseMowerConsumables, parseMowerHeartbeat, renderMowerSvg, renderVacuumPng, resolveCapabilities, supportedAutoSwitchKeys };
|
package/dist/index.d.ts
CHANGED
|
@@ -1849,6 +1849,31 @@ declare function extractMowerConsumableValues(result: unknown): number[] | null;
|
|
|
1849
1849
|
* maintenance) with remaining %. Returns null on a malformed response.
|
|
1850
1850
|
*/
|
|
1851
1851
|
declare function parseMowerConsumables(result: unknown): readonly MowerConsumableReading[] | null;
|
|
1852
|
+
/** Decoded mowing task sub-state (heartbeat byte 13), or null when no mowing
|
|
1853
|
+
* session is in progress. Ported from antondaubert/dreame-mower
|
|
1854
|
+
* `property_misc.py` Property11Handler. */
|
|
1855
|
+
type MowerTaskSubState = 'idle' | 'starting' | 'mowing' | 'paused' | 'finished' | 'failed' | 'exit' | 'returning-to-dock';
|
|
1856
|
+
/** Ordered sub-state table; the heartbeat encodes `subState = base + index`. */
|
|
1857
|
+
declare const MOWER_TASK_SUBSTATES: readonly MowerTaskSubState[];
|
|
1858
|
+
/** Typed heartbeat decode: battery byte, main-state, and (when mowing) the task
|
|
1859
|
+
* sub-state. */
|
|
1860
|
+
interface MowerHeartbeat {
|
|
1861
|
+
/** Raw battery byte (byte 11) — percent with a charging flag in the high bits. */
|
|
1862
|
+
readonly rawBattery: number;
|
|
1863
|
+
/** `(byte12 & 0x0F) - 1`; 4 = mowing. */
|
|
1864
|
+
readonly mainState: number;
|
|
1865
|
+
/** Raw sub-state byte (byte 13). */
|
|
1866
|
+
readonly subStateRaw: number;
|
|
1867
|
+
/** Decoded sub-state when a mowing session is active, else null. */
|
|
1868
|
+
readonly taskSubState: MowerTaskSubState | null;
|
|
1869
|
+
}
|
|
1870
|
+
/**
|
|
1871
|
+
* Decode the 20-byte HEARTBEAT (1:1) blob. Returns null when the payload is not a
|
|
1872
|
+
* well-formed heartbeat (wrong length / missing 0xCE sentinels). The task
|
|
1873
|
+
* sub-state is only meaningful while `mainState === 4` (mowing); in any other
|
|
1874
|
+
* main state there is no active mowing task (returns `taskSubState: null`).
|
|
1875
|
+
*/
|
|
1876
|
+
declare function parseMowerHeartbeat(value: unknown): MowerHeartbeat | null;
|
|
1852
1877
|
|
|
1853
1878
|
/**
|
|
1854
1879
|
* Per-model mower capability records + a resolver adapting the rich record into
|
|
@@ -2053,6 +2078,14 @@ declare class MowerDevice extends BaseDevice {
|
|
|
2053
2078
|
* code — which still surfaces as the raw number via {@link faultRaw}.
|
|
2054
2079
|
*/
|
|
2055
2080
|
get fault(): MowerFault | null;
|
|
2081
|
+
/**
|
|
2082
|
+
* Live mowing task sub-state decoded from the HEARTBEAT (1:1) blob —
|
|
2083
|
+
* idle/starting/mowing/paused/finished/failed/exit/returning-to-dock — or null
|
|
2084
|
+
* when no mowing session is in progress (or the heartbeat is absent). This is
|
|
2085
|
+
* the donor's "current task" sensor; the heartbeat is push-only (the mower does
|
|
2086
|
+
* not answer live reads), so it tracks the device while it is actively mowing.
|
|
2087
|
+
*/
|
|
2088
|
+
get taskSubState(): MowerTaskSubState | null;
|
|
2056
2089
|
/** Parsed scheduling task descriptor (2:50), or null. */
|
|
2057
2090
|
get task(): MowerTaskDescriptor | null;
|
|
2058
2091
|
/**
|
|
@@ -2135,6 +2168,9 @@ declare class MowerDevice extends BaseDevice {
|
|
|
2135
2168
|
mapSvg(opts?: RenderMowerSvgOptions): Promise<string>;
|
|
2136
2169
|
/** Props worth seeding on start() / polling — exported for the facade. */
|
|
2137
2170
|
static readonly DEFAULT_PROPS: readonly [{
|
|
2171
|
+
readonly siid: 1;
|
|
2172
|
+
readonly piid: 1;
|
|
2173
|
+
}, {
|
|
2138
2174
|
readonly siid: 2;
|
|
2139
2175
|
readonly piid: 1;
|
|
2140
2176
|
}, {
|
|
@@ -2493,4 +2529,4 @@ declare function createDumper(target: DumperDevice, options?: DumperOptions): Du
|
|
|
2493
2529
|
*/
|
|
2494
2530
|
declare function createClientDumper(client: Nodreame, options?: DumperOptions): Dumper[];
|
|
2495
2531
|
|
|
2496
|
-
export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, AUTO_SWITCH_JSON_KEY, type AiDetectionRaw, type AutoSwitchKey, type AutoSwitchRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type ConsumableReading, type ConsumableSpec, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameConsumableKey, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapColorScheme, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerConsumableKey, type MowerConsumableReading, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, VACUUM_CONSUMABLES, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, consumableSpec, createClientDumper, createDumper, decodeAiFeature, decodeAutoSwitch, decodeAutoSwitchAll, encodeAiFeatureWrite, encodeAutoSwitchWrite, extractMowerConsumableValues, getMowerCapabilities, getVacuumCapabilities, isDreameConsumableKey, mowerConsumableIndex, parseMowerConsumables, renderMowerSvg, renderVacuumPng, resolveCapabilities, supportedAutoSwitchKeys };
|
|
2532
|
+
export { AI_FEATURE_BIT, AI_FEATURE_JSON_KEY, AUTO_SWITCH_JSON_KEY, type AiDetectionRaw, type AutoSwitchKey, type AutoSwitchRaw, BaseDevice, type BaseDeviceEvents, type BatchDeviceDataFetcher, type CapabilityResolver, ChargingStatus, type CleanOpts, CleaningMode, type ConsumableReading, type ConsumableSpec, type CreateDeviceArgs, DefaultCapabilityResolver, type DeviceCapabilities, type DeviceDump, type DeviceEvent, type DreameAiFeature, DreameApiError, DreameAuthError, type DreameCloudState, type DreameConsumableKey, type DreameDevice, DreameDeviceOfflineError, DreameError, type DreameRegion, type DreameSession, DreameTransportError, type DumperOptions, LIBRARY_NAME, MODEL_CAPABILITIES as MOWER_MODEL_CAPABILITIES, MOWER_TASK_SUBSTATES, type MapBoundingBox, type MapCleanedAreaOverlay, type MapColorScheme, type MapDimensions, type MapFrameType, type MapLayer, type MapLayerType, type MapLowLyingArea, type MapObstacle, type MapPath, type MapPathType, type MapPoint, type MapPose, type MapRestrictedArea, type MapRoom, type MapRoomWall, type MapRun, type MapSegment, type MapStorey, type MapVirtualWall, type MapWallsInfo, type MiotAction, MiotError, type MiotProp, MiotState, type MowerAvailableMap, type MowerCapabilities, MowerCapabilityResolver, MowerChargingStatus, type MowerConsumableKey, type MowerConsumableReading, type MowerContour, MowerControlAction, type MowerControlState, MowerDevice, type MowerDeviceInput, MowerFault, type MowerHeartbeat, type MowerMap, type MowerMapBoundary, type MowerMowPath, type MowerPathEntry, type MowerPoint, type MowerSpotArea, MowerStatus, type MowerTaskDescriptor, MowerTaskStatus, type MowerTaskSubState, type MowerZone, Nodreame, type NodreameDeps, type NodreameEvents, type NodreameOptions, type OssFetchInput, type OssFetcherLike, type PropertyChangedEvent, type PropertyResult, type PropertyState, type PropertyWrite, type RenderMowerSvgOptions, type RenderVacuumPngOptions, type StateChangedEvent, SuctionLevel, TaskStatus, VACUUM_CONSUMABLES, MODEL_CAPABILITIES$1 as VACUUM_MODEL_CAPABILITIES, type VacuumCapabilities, VacuumCapabilityResolver, VacuumDevice, type VacuumGetMapInput, type VacuumMap, WaterVolume, consumableSpec, createClientDumper, createDumper, decodeAiFeature, decodeAutoSwitch, decodeAutoSwitchAll, encodeAiFeatureWrite, encodeAutoSwitchWrite, extractMowerConsumableValues, getMowerCapabilities, getVacuumCapabilities, isDreameConsumableKey, mowerConsumableIndex, parseMowerConsumables, parseMowerHeartbeat, renderMowerSvg, renderVacuumPng, resolveCapabilities, supportedAutoSwitchKeys };
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// src/support/version.ts
|
|
2
2
|
var LIBRARY_NAME = "nodedreame";
|
|
3
|
-
var LIBRARY_VERSION = "1.11.
|
|
3
|
+
var LIBRARY_VERSION = "1.11.2";
|
|
4
4
|
|
|
5
5
|
// src/transport/errors.ts
|
|
6
6
|
var DreameError = class extends Error {
|
|
@@ -616,6 +616,7 @@ var DreamePush = class extends TypedEmitter {
|
|
|
616
616
|
#region;
|
|
617
617
|
#connect;
|
|
618
618
|
#backoffMs;
|
|
619
|
+
#keepaliveSeconds;
|
|
619
620
|
#rejectUnauthorized;
|
|
620
621
|
#topic;
|
|
621
622
|
#client = null;
|
|
@@ -636,6 +637,7 @@ var DreamePush = class extends TypedEmitter {
|
|
|
636
637
|
this.#region = input.region;
|
|
637
638
|
this.#connect = input.connect ?? defaultConnect;
|
|
638
639
|
this.#backoffMs = input.reconnectBackoffMs ?? 5e3;
|
|
640
|
+
this.#keepaliveSeconds = input.keepaliveSeconds ?? 60;
|
|
639
641
|
this.#rejectUnauthorized = input.rejectUnauthorized ?? false;
|
|
640
642
|
this.#topic = buildStatusTopic(this.#device, this.#session.uid, this.#region);
|
|
641
643
|
this.#onClose = () => {
|
|
@@ -693,6 +695,7 @@ var DreamePush = class extends TypedEmitter {
|
|
|
693
695
|
reconnectPeriod: 0,
|
|
694
696
|
// we drive reconnect ourselves
|
|
695
697
|
connectTimeout: 15e3,
|
|
698
|
+
keepalive: this.#keepaliveSeconds,
|
|
696
699
|
rejectUnauthorized: this.#rejectUnauthorized,
|
|
697
700
|
clean: true
|
|
698
701
|
});
|
|
@@ -700,25 +703,37 @@ var DreamePush = class extends TypedEmitter {
|
|
|
700
703
|
client.on("message", (_topic, payload) => this.#handleMessage(payload));
|
|
701
704
|
client.on("error", (err) => this.emit("error", err));
|
|
702
705
|
client.on("close", this.#onClose);
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
706
|
+
try {
|
|
707
|
+
await new Promise((resolve, reject) => {
|
|
708
|
+
const onConnect = () => {
|
|
709
|
+
client.removeListener("error", onError);
|
|
710
|
+
client.subscribe(this.#topic, { qos: 0 }, (err) => {
|
|
711
|
+
if (err) {
|
|
712
|
+
reject(new DreameTransportError(`mqtt subscribe failed: ${err.message}`, err));
|
|
713
|
+
return;
|
|
714
|
+
}
|
|
715
|
+
this.emit("connect");
|
|
716
|
+
resolve();
|
|
717
|
+
});
|
|
718
|
+
};
|
|
719
|
+
const onError = (err) => {
|
|
720
|
+
client.removeListener("connect", onConnect);
|
|
721
|
+
reject(new DreameTransportError(`mqtt connect failed: ${err.message}`, err));
|
|
722
|
+
};
|
|
723
|
+
client.once("connect", onConnect);
|
|
724
|
+
client.once("error", onError);
|
|
725
|
+
});
|
|
726
|
+
} catch (err) {
|
|
727
|
+
client.removeListener("close", this.#onClose);
|
|
728
|
+
try {
|
|
729
|
+
client.end(true, {}, () => void 0);
|
|
730
|
+
} catch {
|
|
731
|
+
}
|
|
732
|
+
if (this.#client === client) {
|
|
733
|
+
this.#client = null;
|
|
734
|
+
}
|
|
735
|
+
throw err;
|
|
736
|
+
}
|
|
722
737
|
}
|
|
723
738
|
#scheduleReconnect() {
|
|
724
739
|
if (this.#closed || this.#reconnectTimer) {
|
|
@@ -1560,7 +1575,9 @@ function encodeAiFeatureWrite(raw, feature, value) {
|
|
|
1560
1575
|
if (typeof raw === "number") {
|
|
1561
1576
|
const bit = AI_FEATURE_BIT[feature];
|
|
1562
1577
|
if (bit === void 0) {
|
|
1563
|
-
throw new Error(
|
|
1578
|
+
throw new Error(
|
|
1579
|
+
`encodeAiFeatureWrite: feature "${feature}" has no int-bitmask representation`
|
|
1580
|
+
);
|
|
1564
1581
|
}
|
|
1565
1582
|
return value ? raw | bit : raw & ~bit;
|
|
1566
1583
|
}
|
|
@@ -1677,18 +1694,53 @@ function encodeAutoSwitchWrite(key2, value) {
|
|
|
1677
1694
|
|
|
1678
1695
|
// src/models/vacuum/consumables.ts
|
|
1679
1696
|
var VACUUM_CONSUMABLES = [
|
|
1680
|
-
{
|
|
1681
|
-
|
|
1697
|
+
{
|
|
1698
|
+
key: "main-brush",
|
|
1699
|
+
label: "Main Brush",
|
|
1700
|
+
life: { siid: 9, piid: 2 },
|
|
1701
|
+
reset: { siid: 9, aiid: 1 }
|
|
1702
|
+
},
|
|
1703
|
+
{
|
|
1704
|
+
key: "side-brush",
|
|
1705
|
+
label: "Side Brush",
|
|
1706
|
+
life: { siid: 10, piid: 2 },
|
|
1707
|
+
reset: { siid: 10, aiid: 1 }
|
|
1708
|
+
},
|
|
1682
1709
|
{ key: "filter", label: "Filter", life: { siid: 11, piid: 1 }, reset: { siid: 11, aiid: 1 } },
|
|
1683
1710
|
{ key: "sensor", label: "Sensor", life: { siid: 16, piid: 1 }, reset: { siid: 16, aiid: 1 } },
|
|
1684
|
-
{
|
|
1711
|
+
{
|
|
1712
|
+
key: "tank-filter",
|
|
1713
|
+
label: "Tank Filter",
|
|
1714
|
+
life: { siid: 17, piid: 1 },
|
|
1715
|
+
reset: { siid: 17, aiid: 1 }
|
|
1716
|
+
},
|
|
1685
1717
|
{ key: "mop-pad", label: "Mop Pad", life: { siid: 18, piid: 1 }, reset: { siid: 18, aiid: 1 } },
|
|
1686
|
-
{
|
|
1687
|
-
|
|
1718
|
+
{
|
|
1719
|
+
key: "silver-ion",
|
|
1720
|
+
label: "Silver-ion",
|
|
1721
|
+
life: { siid: 19, piid: 2 },
|
|
1722
|
+
reset: { siid: 19, aiid: 1 }
|
|
1723
|
+
},
|
|
1724
|
+
{
|
|
1725
|
+
key: "detergent",
|
|
1726
|
+
label: "Detergent",
|
|
1727
|
+
life: { siid: 20, piid: 1 },
|
|
1728
|
+
reset: { siid: 20, aiid: 1 }
|
|
1729
|
+
},
|
|
1688
1730
|
{ key: "squeegee", label: "Squeegee", life: { siid: 24, piid: 1 }, reset: { siid: 24, aiid: 1 } },
|
|
1689
|
-
{
|
|
1731
|
+
{
|
|
1732
|
+
key: "deodorizer",
|
|
1733
|
+
label: "Deodorizer",
|
|
1734
|
+
life: { siid: 29, piid: 2 },
|
|
1735
|
+
reset: { siid: 29, aiid: 1 }
|
|
1736
|
+
},
|
|
1690
1737
|
{ key: "wheel", label: "Wheel", life: { siid: 30, piid: 2 }, reset: { siid: 30, aiid: 1 } },
|
|
1691
|
-
{
|
|
1738
|
+
{
|
|
1739
|
+
key: "scale-inhibitor",
|
|
1740
|
+
label: "Scale Inhibitor",
|
|
1741
|
+
life: { siid: 31, piid: 2 },
|
|
1742
|
+
reset: { siid: 31, aiid: 1 }
|
|
1743
|
+
},
|
|
1692
1744
|
{ key: "dust-bag", label: "Dust Bag", life: { siid: 27, piid: 17 }, reset: null }
|
|
1693
1745
|
];
|
|
1694
1746
|
function consumableSpec(key2) {
|
|
@@ -3803,6 +3855,9 @@ var VacuumDevice = class _VacuumDevice extends BaseDevice {
|
|
|
3803
3855
|
|
|
3804
3856
|
// src/models/mower/properties.ts
|
|
3805
3857
|
var MOWER_PROP = {
|
|
3858
|
+
/** VERIFIED-by-donor — 20-byte heartbeat (sentinel 0xCE at [0]/[19]); byte 11
|
|
3859
|
+
* battery, byte 12 main-state, byte 13 task sub-state. See parseHeartbeat. */
|
|
3860
|
+
HEARTBEAT: { siid: 1, piid: 1 },
|
|
3806
3861
|
/** VERIFIED-by-donor — pose + coverage telemetry (binary). P4 uses progress % only. */
|
|
3807
3862
|
POSE_COVERAGE: { siid: 1, piid: 4 },
|
|
3808
3863
|
/** VERIFIED-by-donor — MowerStatus (DeviceStatus). */
|
|
@@ -4152,6 +4207,39 @@ function parseMowerConsumables(result) {
|
|
|
4152
4207
|
};
|
|
4153
4208
|
});
|
|
4154
4209
|
}
|
|
4210
|
+
var MOWER_TASK_SUBSTATES = [
|
|
4211
|
+
"idle",
|
|
4212
|
+
"starting",
|
|
4213
|
+
"mowing",
|
|
4214
|
+
"paused",
|
|
4215
|
+
"finished",
|
|
4216
|
+
"failed",
|
|
4217
|
+
"exit",
|
|
4218
|
+
"returning-to-dock"
|
|
4219
|
+
];
|
|
4220
|
+
var HEARTBEAT_SENTINEL = 206;
|
|
4221
|
+
var HEARTBEAT_SUBSTATE_BASE = 33;
|
|
4222
|
+
var HEARTBEAT_MAIN_STATE_MOWING = 4;
|
|
4223
|
+
function parseMowerHeartbeat(value) {
|
|
4224
|
+
if (!Array.isArray(value) || value.length < 14) {
|
|
4225
|
+
return null;
|
|
4226
|
+
}
|
|
4227
|
+
const bytes = [];
|
|
4228
|
+
for (const b of value) {
|
|
4229
|
+
if (typeof b !== "number") {
|
|
4230
|
+
return null;
|
|
4231
|
+
}
|
|
4232
|
+
bytes.push(b);
|
|
4233
|
+
}
|
|
4234
|
+
if (bytes[0] !== HEARTBEAT_SENTINEL || bytes[bytes.length - 1] !== HEARTBEAT_SENTINEL) {
|
|
4235
|
+
return null;
|
|
4236
|
+
}
|
|
4237
|
+
const rawBattery = bytes[11] ?? 0;
|
|
4238
|
+
const mainState = ((bytes[12] ?? 0) & 15) - 1;
|
|
4239
|
+
const subStateRaw = bytes[13] ?? 0;
|
|
4240
|
+
const taskSubState = mainState === HEARTBEAT_MAIN_STATE_MOWING ? MOWER_TASK_SUBSTATES[subStateRaw - HEARTBEAT_SUBSTATE_BASE] ?? null : null;
|
|
4241
|
+
return { rawBattery, mainState, subStateRaw, taskSubState };
|
|
4242
|
+
}
|
|
4155
4243
|
|
|
4156
4244
|
// src/models/mower/capabilities.ts
|
|
4157
4245
|
var FALLBACK2 = {
|
|
@@ -4825,6 +4913,19 @@ var MowerDevice = class _MowerDevice extends BaseDevice {
|
|
|
4825
4913
|
get fault() {
|
|
4826
4914
|
return FAULT(this.faultRaw);
|
|
4827
4915
|
}
|
|
4916
|
+
/**
|
|
4917
|
+
* Live mowing task sub-state decoded from the HEARTBEAT (1:1) blob —
|
|
4918
|
+
* idle/starting/mowing/paused/finished/failed/exit/returning-to-dock — or null
|
|
4919
|
+
* when no mowing session is in progress (or the heartbeat is absent). This is
|
|
4920
|
+
* the donor's "current task" sensor; the heartbeat is push-only (the mower does
|
|
4921
|
+
* not answer live reads), so it tracks the device while it is actively mowing.
|
|
4922
|
+
*/
|
|
4923
|
+
get taskSubState() {
|
|
4924
|
+
const hb = parseMowerHeartbeat(
|
|
4925
|
+
this.getProperty(MOWER_PROP.HEARTBEAT.siid, MOWER_PROP.HEARTBEAT.piid)?.value
|
|
4926
|
+
);
|
|
4927
|
+
return hb?.taskSubState ?? null;
|
|
4928
|
+
}
|
|
4828
4929
|
/** Parsed scheduling task descriptor (2:50), or null. */
|
|
4829
4930
|
get task() {
|
|
4830
4931
|
return parseTaskDescriptor(
|
|
@@ -5016,6 +5117,7 @@ var MowerDevice = class _MowerDevice extends BaseDevice {
|
|
|
5016
5117
|
}
|
|
5017
5118
|
/** Props worth seeding on start() / polling — exported for the facade. */
|
|
5018
5119
|
static DEFAULT_PROPS = [
|
|
5120
|
+
MOWER_PROP.HEARTBEAT,
|
|
5019
5121
|
MOWER_PROP.STATUS,
|
|
5020
5122
|
MOWER_PROP.DEVICE_CODE,
|
|
5021
5123
|
MOWER_PROP.BATTERY,
|
|
@@ -5643,6 +5745,7 @@ export {
|
|
|
5643
5745
|
DreameTransportError,
|
|
5644
5746
|
LIBRARY_NAME,
|
|
5645
5747
|
MODEL_CAPABILITIES2 as MOWER_MODEL_CAPABILITIES,
|
|
5748
|
+
MOWER_TASK_SUBSTATES,
|
|
5646
5749
|
MiotError,
|
|
5647
5750
|
MiotState,
|
|
5648
5751
|
MowerCapabilityResolver,
|
|
@@ -5674,6 +5777,7 @@ export {
|
|
|
5674
5777
|
isDreameConsumableKey,
|
|
5675
5778
|
mowerConsumableIndex,
|
|
5676
5779
|
parseMowerConsumables,
|
|
5780
|
+
parseMowerHeartbeat,
|
|
5677
5781
|
renderMowerSvg,
|
|
5678
5782
|
renderVacuumPng,
|
|
5679
5783
|
resolveCapabilities,
|