UNPKG

matterbridge-dyson-robot

Version:

A Matterbridge plugin that connects Dyson robot vacuums and air treatment devices to the Matter smart home ecosystem via their local or cloud MQTT APIs.

114 lines 4.85 kB
// Matterbridge plugin for Dyson robot vacuum and air treatment devices // Copyright © 2025-2026 Alexander Thoukydides import { DysonMqtt } from './dyson-mqtt.js'; import { checkers as dysonMsgCheckers360 } from './ti/dyson-360-msg-types.js'; import { tryListener } from './utils.js'; import { Dyson360CleaningMode, Dyson360CleaningStrategy, Dyson360CleaningType } from './dyson-360-types.js'; import { DysonModeReason } from './dyson-types.js'; // Configuration of a Dyson MQTT client for robot vacuums const DYSON_MQTT_CONFIG_360 = { topics: { command: '@/@/command', subscribe: ['@/@/status'], other: ['@/initialconnection/credentials', '@/initialconnection/status'] }, messages: { prefix: 'Dyson360Msg', checkers: dysonMsgCheckers360 } }; // Dyson MQTT client for robot vacuums export class DysonMqtt360 extends DysonMqtt { // Construct a new MQTT client constructor(log, config, persist, device) { super(log, config, persist, device, DYSON_MQTT_CONFIG_360); // Handle MQTT events this.on('subscribed', tryListener(this, async () => // Request the current status when (re)connected this.publish('REQUEST-CURRENT-STATE', {}))).on('message', tryListener(this, msg => { // Update the robot vacuum state from the received messages switch (msg.msg) { case 'STATE-CHANGE': msg = this.convertStateChange(msg); // (fallthrough) case 'CURRENT-STATE': this.updateState(msg); break; } })); } // Convert a STATE-CHANGE message to CURRENT-STATE format convertStateChange(msg) { const { // Discard unmapped or replaced fields msg: _, endOfClean, oldActiveFaults, oldOutOfBoxState, oldstate, oldZoneId, // Capture renamed or modified fields newActiveFaults, newOutOfBoxState, newstate, newZoneId, // Everything else is copied unchanged ...rest } = msg; return { msg: 'CURRENT-STATE', ...rest, activeFaults: newActiveFaults ?? rest.activeFaults, outOfBoxState: newOutOfBoxState, state: newstate, zoneId: newZoneId, batteryChargeLevel: rest.batteryChargeLevel ?? 0 // (may be omitted on power on) }; } // Update the robot vacuum state from a received message updateState(msg) { // Clear fields from the state that might have disappeared const DELETE_KEYS = [ 'activeFaults', 'cleanDuration', 'cleanId', 'cleaningProgramme', 'faults', 'globalPosition', 'persistentMapId', 'sessionId', 'traverseTargetId', 'zoneId', 'zonesDefinitionVersion', 'zoneStatus' ]; for (const key of DELETE_KEYS) this.status[key] = undefined; // Copy status fields from the message to the state const { msg: _msg, time, ...status } = msg; Object.assign(this.status, status); // State is fully initialised after the first message has been received this.updateInitialised(); } commandAction(msg, cleaningProgramme) { switch (msg) { case 'START': return this.publish('START', cleaningProgramme ? { 'mode-reason': DysonModeReason.LocalApp, fullCleanType: Dyson360CleaningType.Immediate, cleaningMode: Dyson360CleaningMode.ZoneConfigured, cleaningProgramme } : { 'mode-reason': DysonModeReason.LocalApp, fullCleanType: Dyson360CleaningType.Immediate, cleaningMode: this.status.defaultCleaningMode && Dyson360CleaningMode.Global, cleaningStrategy: this.status.defaultCleaningStrategy && Dyson360CleaningStrategy.Auto }); case 'PAUSE': case 'RESUME': case 'ABORT': return this.publish(msg, { 'mode-reason': DysonModeReason.LocalApp }); } } // Publish a robot vacuum command to set the default power level (360 Eye) commandSetPowerMode(defaultVacuumPowerMode) { return this.publish('STATE-SET', { 'mode-reason': DysonModeReason.LocalApp, data: { defaultVacuumPowerMode } }); } // Publish a robot vacuum command to set the default power level (360 Vis Nav) commandSetCleaningStrategy(defaultCleaningStrategy) { return this.publish('STATE-SET', { 'mode-reason': DysonModeReason.LocalApp, defaults: { defaultCleaningStrategy } }); } } //# sourceMappingURL=dyson-mqtt-360.js.map