@homebridge-plugins/homebridge-roomba
Version:
homebridge-plugin for Roomba devices
140 lines • 5.79 kB
JavaScript
import { readFileSync } from 'node:fs';
import RoombaAccessory from './accessory.js';
import { getRoombas } from './roomba.js';
import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
export default class RoombaPlatform {
Service;
Characteristic;
api;
log;
config;
accessories = new Map();
version;
constructor(log, config, api) {
this.Service = api.hap.Service;
this.Characteristic = api.hap.Characteristic;
this.api = api;
this.config = config;
const debug = !!config.debug;
try {
this.verifyConfig();
log.debug('Configuration:', JSON.stringify(this.config, null, 2));
}
catch (e) {
log.error('Error in configuration:', e.message ?? e);
return;
}
this.log = !debug
? log
: Object.assign(log, { debug: (message, ...parameters) => { log.info(`DEBUG: ${message}`, ...parameters); } });
this.version = this.getVersion();
this.api.on('didFinishLaunching', () => {
this.discoverDevices();
});
}
verifyConfig() {
if (this.config.disableDiscovery === undefined) {
this.config.disableDiscovery = false;
}
}
configureAccessory(accessory) {
this.log(`Configuring accessory: ${accessory.displayName}`);
this.accessories.set(accessory.UUID, accessory);
}
async discoveryMethod() {
if (this.config.email && this.config.password) {
const robots = await getRoombas(this.config.email, this.config.password, this.log, this.config);
return robots.map((robot) => {
const deviceConfig = this.config.devices?.find(device => device.blid === robot.blid) || {};
return {
...robot,
...deviceConfig,
};
});
}
else if (this.config.devices) {
return this.config.devices.map(device => ({
...device,
}));
}
else {
this.log.error('No configuration provided for devices.');
return [];
}
}
async discoverDevices() {
const devices = await this.discoveryMethod();
const configuredAccessoryUUIDs = new Set();
for (const device of devices) {
const uuid = this.api.hap.uuid.generate(device.blid);
const existingAccessory = this.accessories.get(uuid);
if (existingAccessory) {
this.log.debug('existingAccessory device: %s', JSON.stringify(device));
this.log.debug('Restoring existing accessory from cache:', existingAccessory.displayName);
existingAccessory.context.device = device;
const { serialNumber, deviceInfo } = this.serialNum(device);
existingAccessory.context.serialNumber = serialNumber;
existingAccessory.context.deviceInfo = deviceInfo;
existingAccessory.context.model = device.model;
existingAccessory.context.firmwareRevision = device.softwareVer ?? this.version ?? '0.0.0';
this.api.updatePlatformAccessories([existingAccessory]);
new RoombaAccessory(this, existingAccessory, this.log, {
...device,
}, this.config, this.api);
}
else {
this.log.debug('accessory device: %s', JSON.stringify(device));
this.log.info('Adding new accessory:', device.name);
const accessory = new this.api.platformAccessory(device.name, uuid);
accessory.context.device = device;
const { serialNumber, deviceInfo } = this.serialNum(device);
accessory.context.serialNumber = serialNumber;
accessory.context.deviceInfo = deviceInfo;
accessory.context.model = device.model;
accessory.context.firmwareRevision = device.softwareVer ?? this.version ?? '0.0.0';
new RoombaAccessory(this, accessory, this.log, {
...device,
}, this.config, this.api);
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
}
configuredAccessoryUUIDs.add(uuid);
}
const accessoriesToRemove = [];
for (const [uuid, accessory] of this.accessories) {
if (!configuredAccessoryUUIDs.has(uuid)) {
accessoriesToRemove.push(accessory);
}
}
if (accessoriesToRemove.length) {
this.log.info('Removing existing accessories from cache:', accessoriesToRemove.map(a => a.displayName).join(', '));
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, accessoriesToRemove);
}
}
serialNum(device) {
let deviceInfo;
let serialNumber;
const serialNum = device.ipaddress ?? device.ip;
if (device.info) {
deviceInfo = device.info;
if (device.info.serialNum) {
serialNumber = device.info.serialNum;
return { serialNumber, deviceInfo };
}
else {
serialNumber = serialNum;
return { serialNumber, deviceInfo };
}
}
else {
deviceInfo = undefined;
serialNumber = serialNum;
return { serialNumber, deviceInfo };
}
}
getVersion() {
const { version } = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf-8'));
this.log.debug(`Plugin Version: ${version}`);
return version;
}
}
//# sourceMappingURL=platform.js.map