UNPKG

matterbridge-aeg-robot

Version:

A Matterbridge plugin that connects AEG RX 9 / Electrolux Pure i9 robot vacuums to the Matter smart home ecosystem.

252 lines 11.3 kB
// Matterbridge plugin for AEG RX9 / Electrolux Pure i9 robot vacuum // Copyright © 2025 Alexander Thoukydides import { bridgedNode, MatterbridgeEndpoint, powerSource, roboticVacuumCleaner } from 'matterbridge'; import { BridgedDeviceBasicInformationServer, PowerSourceServer } from 'matterbridge/matter/behaviors'; import { PowerSource, RvcCleanMode, RvcRunMode } from 'matterbridge/matter/clusters'; import { BehaviorDeviceRX9, BehaviorRX9, RvcCleanModeRX9, RvcCleanModeServerRX9, RvcOperationalStateRX9, RvcOperationalStateServerRX9, RvcRunModeRX9, RvcRunModeServerRX9 } from './behavior-rx9.js'; import { PLUGIN_URL } from './settings.js'; import { RvcOperationalStateError } from './error-rx9.js'; // A Matterbridge endpoint with robot vacuum cleaner clusters export class EndpointRX9 extends MatterbridgeEndpoint { config; information; // Command handlers behaviorDeviceRX9; // Construct a new endpoint constructor(log, config, information) { const definition = [roboticVacuumCleaner, bridgedNode, powerSource]; const debug = config.debugFeatures.includes('Log Endpoint Debug'); super(definition, { uniqueStorageKey: information.uniqueStorageKey }, debug); this.config = config; this.information = information; // Use supplied logger instead of the one created by the base class this.log = log; // Create the clusters this.createDefaultIdentifyClusterServer() .createBridgedDeviceBasicInformationClusterServer() .createPowerSourceClusterServer() .createRvcRunModeClusterServer() .createRvcCleanModeClusterServer() .createRvcOperationalStateClusterServer(); // Add a command handler behavior this.behaviorDeviceRX9 = new BehaviorDeviceRX9(this.log); this.behaviors.require(BehaviorRX9, { device: this.behaviorDeviceRX9 }); } // Create the Bridged Device Basic Information cluster createBridgedDeviceBasicInformationClusterServer() { // Copy of values (possibly) required by Matterbridge this.deviceName = this.information.nodeLabel; this.serialNumber = this.information.serialNumber; this.uniqueId = this.information.uniqueId; this.productId = undefined; this.productName = this.information.productName; this.vendorId = undefined; this.vendorName = this.information.vendorName; this.softwareVersion = parseInt(this.information.softwareVersion, 10); this.softwareVersionString = this.information.softwareVersion; this.hardwareVersion = parseInt(this.information.hardwareVersion, 10); this.hardwareVersionString = this.information.hardwareVersion; // Create the cluster this.behaviors.require(BridgedDeviceBasicInformationServer.enable({ events: { leave: true, reachableChanged: true } }), { // Constant attributes uniqueId: this.information.uniqueId.substring(0, 32), vendorName: this.information.vendorName.substring(0, 32), productName: this.information.productName.substring(0, 32), nodeLabel: this.information.nodeLabel.substring(0, 32), hardwareVersion: parseInt(this.information.hardwareVersion, 10), hardwareVersionString: this.information.hardwareVersion.substring(0, 64), manufacturingDate: this.information.manufacturingDate, partNumber: this.information.partNumber.substring(0, 32), productUrl: PLUGIN_URL, productLabel: this.information.productLabel.substring(0, 64), serialNumber: this.information.serialNumber.substring(0, 32), productAppearance: this.information.productAppearance, // Variable attributes reachable: true, softwareVersion: parseInt(this.information.softwareVersion, 10), softwareVersionString: this.information.softwareVersion.substring(0, 64), // Unsupported attributes (no certified AEG/Electrolux Matter products) vendorId: undefined, productId: undefined }); return this; } // Create the Power Source cluster for the rechargeable battery createPowerSourceClusterServer() { this.behaviors.require(PowerSourceServer.withFeatures(PowerSource.Feature.Battery, PowerSource.Feature.Rechargeable, PowerSource.Feature.Replaceable), { // Constant attributes order: 0, description: 'Primary Batteries', batReplacementNeeded: false, batPresent: true, batReplaceability: PowerSource.BatReplaceability.UserReplaceable, batReplacementDescription: 'Electrolux OSBP72L125 / AEG OSBP72LI (2 × 7.2V Li-ion)', batApprovedChemistry: PowerSource.BatApprovedChemistry.LithiumIon, batCapacity: 2500, // 18Wh at 7.2V = 2.5Ah batQuantity: 2, batFunctionalWhileCharging: false, endpointList: [], // Variable attributes (with dummy defaults) status: PowerSource.PowerSourceStatus.Active, batPercentRemaining: null, batChargeLevel: PowerSource.BatChargeLevel.Ok, batChargeState: PowerSource.BatChargeState.Unknown, // Unsupported attributes batVoltage: null, batTimeRemaining: undefined, activeBatFaults: undefined, batCommonDesignation: undefined, batAnsiDesignation: undefined, batIecDesignation: undefined, batTimeToFullCharge: undefined, batChargingCurrent: undefined, activeBatChargeFaults: undefined }); return this; } // Create the RVC Run Mode cluster createRvcRunModeClusterServer() { this.behaviors.require(RvcRunModeServerRX9.enable({ commands: { changeToMode: true } }), { // Constant attributes supportedModes: [{ label: 'Idle', mode: RvcRunModeRX9.Idle, modeTags: [{ value: RvcRunMode.ModeTag.Idle }] }, { label: 'Cleaning', mode: RvcRunModeRX9.Cleaning, modeTags: [{ value: RvcRunMode.ModeTag.Cleaning }] }], // Variable attributes (with dummy defaults) currentMode: RvcRunModeRX9.Idle }); return this; } // Create the RVC Clean Mode cluster createRvcCleanModeClusterServer() { const tag = RvcCleanMode.ModeTag; this.behaviors.require(RvcCleanModeServerRX9.enable({ commands: { changeToMode: true } }), { // Constant attributes supportedModes: [{ label: 'Quiet Cleaning', mode: RvcCleanModeRX9.Quiet, modeTags: [ { value: tag.Vacuum }, { value: tag.Quiet }, { value: tag.LowNoise }, { value: tag.LowEnergy }, { value: tag.Min } ] }, { label: 'Smart Cleaning', mode: RvcCleanModeRX9.Smart, modeTags: [ { value: tag.Vacuum }, { value: tag.Auto } ] }, { label: 'Power Cleaning', mode: RvcCleanModeRX9.Power, modeTags: [ { value: tag.Vacuum }, { value: tag.Max }, { value: tag.DeepClean } ] }, { label: 'Quiet Spot Cleaning', mode: RvcCleanModeRX9.QuietSpot, modeTags: [ { value: tag.Vacuum }, { value: tag.Quick }, { value: tag.Quiet }, { value: tag.LowNoise }, { value: tag.LowEnergy }, { value: tag.Min } ] }, { label: 'Smart Spot Cleaning', mode: RvcCleanModeRX9.SmartSpot, modeTags: [ { value: tag.Vacuum }, { value: tag.Quick }, { value: tag.Auto } ] }, { label: 'Power Spot Cleaning', mode: RvcCleanModeRX9.PowerSpot, modeTags: [ { value: tag.Vacuum }, { value: tag.Quick }, { value: tag.Max }, { value: tag.DeepClean } ] }].filter(mode => this.information.smartPowerCapable || mode.modeTags.some(t => t.value !== tag.Auto)), // Variable attributes (with dummy defaults) currentMode: RvcCleanModeRX9.Quiet }); return this; } // Create the RVC Operational State cluster createRvcOperationalStateClusterServer() { this.behaviors.require(RvcOperationalStateServerRX9.enable({ events: { operationalError: true, operationCompletion: true }, commands: { pause: true, resume: true, goHome: true } }), { // Constant attributes operationalStateList: [{ operationalStateId: RvcOperationalStateRX9.Stopped }, { operationalStateId: RvcOperationalStateRX9.Running }, { operationalStateId: RvcOperationalStateRX9.Paused }, { operationalStateId: RvcOperationalStateRX9.Error }, { operationalStateId: RvcOperationalStateRX9.SeekingCharger }, { operationalStateId: RvcOperationalStateRX9.Charging }, { operationalStateId: RvcOperationalStateRX9.Docked }, { operationalStateId: RvcOperationalStateRX9.ManualSteering, operationalStateLabel: 'Manual Steering' }, { operationalStateId: RvcOperationalStateRX9.FirmwareUpgrade, operationalStateLabel: 'Firmware Upgrade' }], // Variable attributes (with dummy defaults) operationalState: RvcOperationalStateRX9.Stopped, operationalError: RvcOperationalStateError.toStruct(), // Unsupported attributes phaseList: null, currentPhase: null, countdownTime: null }); return this; } // Set a command handler setCommandHandlerRX9(command, handler) { this.behaviorDeviceRX9.setCommandHandler(command, handler); return this; } } //# sourceMappingURL=endpoint-rx9.js.map