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.
143 lines • 6.65 kB
JavaScript
// Matterbridge plugin for Dyson robot vacuum and air treatment devices
// Copyright © 2025-2026 Alexander Thoukydides
import { ModeBase, RvcOperationalState, ServiceArea } from 'matterbridge/matter/clusters';
import { VENDOR_ERROR_360 } from './endpoint-360-behavior.js';
// RVC Operational State errors
export class RvcOperationalStateError extends Error {
id;
label;
details;
// Create a new error
constructor(id, label, // (if a manufacturer-specific id, otherwise undefined)
details, options) {
const idName = RvcOperationalState.ErrorState[id] ?? `0x${id.toString(16)}`;
let message = label ?? idName;
if (details)
message += ` (${details})`;
super(message, options);
this.id = id;
this.label = label;
this.details = details;
Error.captureStackTrace(this, RvcOperationalStateError);
this.name = `RvcOperationalStateError[${idName}]`;
}
// Convert an arbitrary error (or nullish for success) to an ErrorStateStruct
static toStruct(err, defaultId = VENDOR_ERROR_360) {
return err instanceof RvcOperationalStateError ? {
errorStateId: err.id,
errorStateLabel: err.label?.substring(0, 64) ?? undefined,
errorStateDetails: err.details?.substring(0, 64) ?? ''
} : err ? {
errorStateId: defaultId,
errorStateLabel: err instanceof Error ? err.message.substring(0, 64) : 'Unknown error',
errorStateDetails: ''
} : {
errorStateId: RvcOperationalState.ErrorState.NoError,
errorStateDetails: ''
};
}
// Convert an arbitrary error (or nullish for success) to an OperationalCommandResponse
static toResponse(err, defaultId) {
return { commandResponseState: RvcOperationalStateError.toStruct(err, defaultId) };
}
// Helper function to create a new error class with a specific status code
static create(idName) {
return class extends RvcOperationalStateError {
constructor(details, options) {
const id = RvcOperationalState.ErrorState[idName];
super(id, undefined, details, options);
}
};
}
// Standard error codes defined by the RVC Operational State Cluster
static NoError = this.create('NoError');
static UnableToStartOrResume = this.create('UnableToStartOrResume');
static UnableToCompleteOperation = this.create('UnableToCompleteOperation');
static CommandInvalidInState = this.create('CommandInvalidInState');
static FailedToFindChargingDock = this.create('FailedToFindChargingDock');
static Stuck = this.create('Stuck');
static DustBinMissing = this.create('DustBinMissing');
static DustBinFull = this.create('DustBinFull');
static WaterTankEmpty = this.create('WaterTankEmpty');
static WaterTankMissing = this.create('WaterTankMissing');
static WaterTankLidOpen = this.create('WaterTankLidOpen');
static MopCleaningPadMissing = this.create('MopCleaningPadMissing');
static LowBattery = this.create('LowBattery');
static CannotReachTargetArea = this.create('CannotReachTargetArea');
static DirtyWaterTankFull = this.create('DirtyWaterTankFull');
static DirtyWaterTankMissing = this.create('DirtyWaterTankMissing');
static WheelsJammed = this.create('WheelsJammed');
static BrushJammed = this.create('BrushJammed');
static NavigationSensorObscured = this.create('NavigationSensorObscured');
}
// RVC Clean/Run Mode ChangeToMode errors
export class ChangeToModeError extends Error {
status;
// Create a new error
constructor(status, message, options) {
super(message, options);
this.status = status;
Error.captureStackTrace(this, ChangeToModeError);
const statusName = ModeBase.ModeChangeStatus[status];
this.name = `ChangeToModeError[${statusName ?? `0x${status.toString(16)}`}]`;
}
// Convert an arbitrary error (or nullish for success) to a ChangeToModeResponse
static toResponse(err) {
return {
status: err instanceof ChangeToModeError ? err.status
: ModeBase.ModeChangeStatus[err ? 'GenericFailure' : 'Success'],
statusText: err instanceof Error ? err.message.substring(0, 64) : 'Unable to change mode'
};
}
// Helper function to create a new error class with a specific status code
static create(statusName) {
const statusCode = ModeBase.ModeChangeStatus[statusName];
return class extends ChangeToModeError {
constructor(message, options) {
message ??= `ChangeToMode status ${statusName}`;
super(statusCode, message, options);
}
};
}
// Standard status codes defined by the Mode Base Cluster
static Success = this.create('Success');
static UnsupportedMode = this.create('UnsupportedMode');
static GenericFailure = this.create('GenericFailure');
static InvalidInMode = this.create('InvalidInMode');
}
// Service Area SelectAreas errors
export class SelectAreaError extends Error {
status;
// Create a new error
constructor(status, message, options) {
super(message, options);
this.status = status;
Error.captureStackTrace(this, SelectAreaError);
const statusName = ServiceArea.SelectAreasStatus[status];
this.name = `SelectAreaError[${statusName ?? `0x${status.toString(16)}`}]`;
}
// Convert an arbitrary error (or nullish for success) to a SelectAreasResponse
static toResponse(err) {
return {
status: err instanceof SelectAreaError ? err.status
: ServiceArea.SelectAreasStatus[err ? 'InvalidInMode' : 'Success'],
statusText: err instanceof Error ? err.message.substring(0, 256) : 'Unable to select areas'
};
}
// Helper function to create a new error class with a specific status code
static create(statusName) {
const statusCode = ServiceArea.SelectAreasStatus[statusName];
return class extends SelectAreaError {
constructor(message, options) {
message ??= `SelectArea status ${statusName}`;
super(statusCode, message, options);
}
};
}
// Standard status codes defined by the Service Area cluster
static Success = this.create('Success');
static UnsupportedArea = this.create('UnsupportedArea');
static InvalidInMode = this.create('InvalidInMode');
static InvalidSet = this.create('InvalidSet');
}
//# sourceMappingURL=error-360.js.map