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.
123 lines • 6.05 kB
JavaScript
// Matterbridge plugin for Dyson robot vacuum and air treatment devices
// Copyright © 2025-2026 Alexander Thoukydides
import { DysonCloudAPIUserAgent } from './dyson-cloud-api-ua.js';
import { checkers } from './ti/dyson-cloud-types.js';
import { checkers as checkers360 } from './ti/dyson-360-cloud-types.js';
import { checkers as checkersAir } from './ti/dyson-air-cloud-types.js';
import { assertIsDefined } from './utils.js';
// Default locale
const DEFAULT_COUNTRY = 'GB';
const DEFAULT_LANGUAGE = 'en-GB';
// Dyson cloud API client for a single device
export class DysonCloudAPIDevice {
log;
config;
china;
token;
manifest;
// User agent used for all requests
ua;
// Construct a new Dyson cloud API client
constructor(log, config, china, token, manifest) {
this.log = log;
this.config = config;
this.china = china;
this.token = token;
this.manifest = manifest;
// Create an authenticated user agent
this.ua = new DysonCloudAPIUserAgent(log, config, china);
this.ua.setBearerToken(token);
}
// Interesting information about this device
get serialNumber() { return this.manifest.serialNumber; }
get modelNumber() { return this.manifest.model; }
get modelName() { return this.manifest.productName; }
get mqttRootTopic() { return this.connectedConfiguration.mqtt.mqttRootTopicLevel; }
get firmwareVersion() { return this.connectedConfiguration.firmware.version; }
// Shortcut to nested (and optional but always present) object
get connectedConfiguration() {
assertIsDefined(this.manifest.connectedConfiguration);
return this.manifest.connectedConfiguration;
}
// Retrieve the AWS IoT credentials for a specific device
getIoTCredentials() {
const body = { Serial: this.serialNumber };
const path = '/v2/authorize/iot-credentials';
return this.ua.postJSON(checkers.DysonIoTCredentialsResponse, path, body);
}
// Identify the timezone of the device
getTimezone() {
const path = `/v1/machine/${this.serialNumber}/timezone`;
return this.ua.getJSON(checkers.DysonTimezoneResponse, path);
}
// Check the registration status of the device
async getOwnership(countryCode = DEFAULT_COUNTRY) {
const path = `/v1/userregistration/ownership?country=${countryCode}&serial=${this.serialNumber}`;
const response = await this.ua.getJSON(checkers.DysonOwnershipResponse, path);
return response.deviceStatus;
}
// Retrieve list of scheduled events for the device
getScheduledEvents(checker) {
const path = `/v1/unifiedscheduler/${this.serialNumber}/events?productType=${this.mqttRootTopic}`;
return this.ua.getJSON(checker, path);
}
// =========================================================================
// Dyson robot vacuum device API methods...
// Retrieve list of scheduled events for the device
getScheduledEvents360() {
return this.getScheduledEvents(checkers360.Dyson360UnifiedschedulerEventsResponse);
}
// Retrieve the cleaning history for the device (360 Eye only)
getCleaningHistory360(languageCode = DEFAULT_LANGUAGE) {
const path = `/v1/assets/devices/${this.serialNumber}/cleanhistory?culture=${languageCode}`;
return this.ua.getJSON(checkers360.Dyson360CleanHistoryResponse, path);
}
// Retrieve the map image for a specific cleaning session (360 Eye only)
getMapImage360(clean) {
const path = `/v1/mapvisualizer/devices/${this.serialNumber}/map/${clean}`;
return this.ua.getBinary(path, 'image/png');
}
// Retrieve the zone definitions for all persistent maps (360 Vis Nav only)
getPersistentMapMetadata360() {
const path = `/v1/app/${this.serialNumber}/persistent-map-metadata`;
return this.ua.getJSON(checkers360.Dyson360PersistentMapMetadataResponse, path);
}
// Retrieve the full details of a specific persistent map (360 Vis Nav only)
getPersistentMap360(mapId) {
const path = `/v1/app/${this.serialNumber}/persistent-maps/${mapId}`;
return this.ua.getJSON(checkers360.Dyson360PersistentMapResponse, path);
}
// Retrieve details of recent cleaning sessions (360 Vis Nav only)
getCleanMaps360() {
const path = `/v1/${this.serialNumber}/clean-maps?dustMap=total`;
return this.ua.getJSON(checkers360.Dyson360CleanMapsResponse, path);
}
// Request details of the recommended clean (360 Vis Nav only)
getRecommendedCleans360() {
const path = `/v1/app/${this.serialNumber}/recommended-cleans`;
return this.ua.getJSON(checkers360.Dyson360RecommendedCleansResponse, path);
}
// Set the cleaning strategy for a single zone (360 Vis Nav only)
setZoneBehaviour360(mapId, zoneId, cleaningStrategy) {
const body = { cleaningStrategy };
const path = `/v1/app/${this.serialNumber}/persistent-maps/${mapId}/zones/${zoneId}/behaviour`;
return this.ua.put(path, body);
}
// =========================================================================
// Dyson air treatment device API methods...
// Retrieve list of scheduled events for the device
getScheduledEventsAir() {
return this.getScheduledEvents(checkersAir.DysonAirUnifiedschedulerEventsResponse);
}
// Retrieve current environmental data for the device
getEnvironmentalDataAir(languageCode = DEFAULT_LANGUAGE) {
const path = `/v1/environment/devices/${this.serialNumber}/data?language=${languageCode}`;
return this.ua.getJSON(checkersAir.DysonAirEnvironmentResponse, path);
}
// Retrieve daily history of environmental data for the device
getEnvironmentalDataDailyAir() {
const path = `/v1/messageprocessor/devices/${this.serialNumber}/environmentdata/daily`;
return this.ua.getJSON(checkersAir.DysonAirEnvironmentDataDailyResponse, path);
}
}
//# sourceMappingURL=dyson-cloud-api-device.js.map