eslint compliance

This commit is contained in:
Luis Riegger 2021-05-10 20:51:29 +02:00
parent 9a9789328f
commit 82808d7850
8 changed files with 334 additions and 277 deletions

View File

@ -1,19 +1,21 @@
import type { Characteristic, WithUUID } from 'homebridge'; import type { Characteristic, WithUUID } from 'homebridge';
import { Formats, Perms } from 'homebridge'; import { Formats, Perms } from 'homebridge';
export default function spotHeight(CustomCharacteristic: typeof Characteristic): WithUUID<new () => Characteristic> { export default function spotHeight(
return class SpotHeight extends CustomCharacteristic { CustomCharacteristic: typeof Characteristic,
static readonly UUID = 'CA282DB2-62BF-4325-A1BE-F8BB5478781A'; ): WithUUID<new () => Characteristic> {
return class SpotHeight extends CustomCharacteristic {
static readonly UUID = 'CA282DB2-62BF-4325-A1BE-F8BB5478781A';
constructor() { constructor() {
super('Spot ↕', SpotHeight.UUID, { super('Spot ↕', SpotHeight.UUID, {
format: Formats.INT, format: Formats.INT,
unit: 'cm', unit: 'cm',
maxValue: 400, maxValue: 400,
minValue: 100, minValue: 100,
minStep: 50, minStep: 50,
perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE] perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE],
}); });
} }
}; };
} }

View File

@ -1,15 +1,17 @@
import type { Characteristic, WithUUID } from 'homebridge'; import type { Characteristic, WithUUID } from 'homebridge';
import { Formats, Perms } from 'homebridge'; import { Formats, Perms } from 'homebridge';
export default function spotRepeat(CustomCharacteristic: typeof Characteristic): WithUUID<new () => Characteristic> { export default function spotRepeat(
return class SpotRepeat extends CustomCharacteristic { CustomCharacteristic: typeof Characteristic,
static readonly UUID = '1E79C603-63B8-4E6A-9CE1-D31D67981831'; ): WithUUID<new () => Characteristic> {
return class SpotRepeat extends CustomCharacteristic {
static readonly UUID = '1E79C603-63B8-4E6A-9CE1-D31D67981831';
constructor() { constructor() {
super('Spot 2x', SpotRepeat.UUID, { super('Spot 2x', SpotRepeat.UUID, {
format: Formats.BOOL, format: Formats.BOOL,
perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE] perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE],
}); });
} }
}; };
} }

View File

@ -1,19 +1,21 @@
import type { Characteristic, WithUUID } from 'homebridge'; import type { Characteristic, WithUUID } from 'homebridge';
import { Formats, Perms } from 'homebridge'; import { Formats, Perms } from 'homebridge';
export default function spotWidth(CustomCharacteristic: typeof Characteristic): WithUUID<new () => Characteristic> { export default function spotWidth(
return class SpotWidth extends CustomCharacteristic { CustomCharacteristic: typeof Characteristic,
static readonly UUID = 'A7889A9A-2F27-4293-BEF8-3FE805B36F4E'; ): WithUUID<new () => Characteristic> {
return class SpotWidth extends CustomCharacteristic {
static readonly UUID = 'A7889A9A-2F27-4293-BEF8-3FE805B36F4E';
constructor() { constructor() {
super('Spot ↔', SpotWidth.UUID, { super('Spot ↔', SpotWidth.UUID, {
format: Formats.INT, format: Formats.INT,
unit: 'cm', unit: 'cm',
maxValue: 400, maxValue: 400,
minValue: 100, minValue: 100,
minStep: 50, minStep: 50,
perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE] perms: [Perms.PAIRED_READ, Perms.PAIRED_WRITE],
}); });
} }
}; };
} }

View File

@ -1,6 +1,6 @@
import { RobotService } from "./models/services"; import { RobotService } from './models/services';
export const BACKGROUND_INTERVAL = 30; export const BACKGROUND_INTERVAL = 30;
export const PREFIX = false; export const PREFIX = false;
export const ALL_SERVICES = new Set(Object.values(RobotService)); export const ALL_SERVICES = new Set(Object.values(RobotService));
export const LOCALE = "en" export const LOCALE = 'en';

View File

@ -1,219 +1,273 @@
import {API, Characteristic, DynamicPlatformPlugin, Logger, PlatformAccessory, PlatformConfig, Service} from "homebridge"; import {
import KoboldApi from "node-kobold-control"; API,
import {PLATFORM_NAME, PLUGIN_NAME} from "./settings"; Characteristic,
import {KoboldVacuumRobotAccessory} from "./accessories/koboldVacuumRobot"; DynamicPlatformPlugin,
Logger,
PlatformAccessory,
PlatformConfig,
Service,
} from 'homebridge';
import KoboldApi from 'node-kobold-control';
import { PLATFORM_NAME, PLUGIN_NAME } from './settings';
import { KoboldVacuumRobotAccessory } from './accessories/koboldVacuumRobot';
/** /**
* HomebridgePlatform * HomebridgePlatform
* This class is the main constructor for your plugin, this is where you should * This class is the main constructor for your plugin, this is where you should
* parse the user config and discover/register accessories with Homebridge. * parse the user config and discover/register accessories with Homebridge.
*/ */
export class HomebridgeKoboldPlatform implements DynamicPlatformPlugin export class HomebridgeKoboldPlatform implements DynamicPlatformPlugin {
{ public readonly Service: typeof Service = this.api.hap.Service;
public readonly Service: typeof Service = this.api.hap.Service; public readonly Characteristic: typeof Characteristic =
public readonly Characteristic: typeof Characteristic = this.api.hap.Characteristic; this.api.hap.Characteristic;
// this is used to track restored cached accessories // this is used to track restored cached accessories
public readonly cachedRobotAccessories: PlatformAccessory[] = []; public readonly cachedRobotAccessories: PlatformAccessory[] = [];
constructor( constructor(
public readonly log: Logger, public readonly log: Logger,
public readonly config: PlatformConfig, public readonly config: PlatformConfig,
public readonly api: API) public readonly api: API,
{ ) {
this.api.on("didFinishLaunching", () => { this.api.on('didFinishLaunching', () => {
this.discoverRobots(); this.discoverRobots();
}); });
} }
/** /**
* This function is invoked when homebridge restores cached accessories from disk at startup. * This function is invoked when homebridge restores cached accessories from disk at startup.
* It should be used to setup event handlers for characteristics and update respective values. * It should be used to setup event handlers for characteristics and update respective values.
*/ */
configureAccessory(accessory: PlatformAccessory) configureAccessory(accessory: PlatformAccessory) {
{ // add the restored accessory to the accessories cache so we can track if it has already been registered
// add the restored accessory to the accessories cache so we can track if it has already been registered this.cachedRobotAccessories.push(accessory);
this.cachedRobotAccessories.push(accessory); }
}
discoverRobots() {
discoverRobots() const client = new KoboldApi.Client();
{
const client = new KoboldApi.Client();
try try {
{ // Login
// Login client.authorize(this.config['token'], (error) => {
client.authorize((this.config)["token"], (error) => { if (error) {
if (error) this.log.error(
{ `Cannot connect to Vorwerk server.
this.log.error("Cannot connect to Vorwerk server. No new robots will be found and existing robots will be unresponsive. Retrying in 5 minutes."); No new robots will be found and existing robots will be unresponsive.
this.log.error("Error: " + error); Retrying in 5 minutes.`,
);
this.log.error('Error: ' + error);
setTimeout(() => { setTimeout(() => {
this.discoverRobots(); this.discoverRobots();
}, 5 * 60 * 1000); }, 5 * 60 * 1000);
return; return;
} }
// Get all robots from account // Get all robots from account
client.getRobots((error, robots) => { client.getRobots((error, robots) => {
if (error) if (error) {
{ this.log.error(
this.log.error("Successful login but can't list the robots in your Vorwerk robots. Retrying in 5 minutes."); 'Successful login but can\'t list the robots in your Vorwerk robots. Retrying in 5 minutes.',
this.log.error("Error: " + error); );
this.log.error('Error: ' + error);
setTimeout(() => { setTimeout(() => {
this.discoverRobots(); this.discoverRobots();
}, 5 * 60 * 1000); }, 5 * 60 * 1000);
return; return;
} }
// Vorwerk robots in account // Vorwerk robots in account
if (robots.length === 0) if (robots.length === 0) {
{ this.log.error('Vorwerk account has no robots.');
this.log.error("Vorwerk account has no robots."); } else {
} this.log.info(
else 'Vorwerk account has ' +
{ robots.length +
this.log.info("Vorwerk account has " + robots.length + " robot" + (robots.length === 1 ? "" : "s")); ' robot' +
} (robots.length === 1 ? '' : 's'),
);
}
// Vorwerk robots in cache // Vorwerk robots in cache
this.log.debug("Plugin Cache has " + this.cachedRobotAccessories.length + " robot" + (this.cachedRobotAccessories.length === 1 ? "" : "s")); this.log.debug(
for (let cachedRobot of this.cachedRobotAccessories) 'Plugin Cache has ' +
{ this.cachedRobotAccessories.length +
let accountRobot = robots.find(robot => this.api.hap.uuid.generate(robot._serial) === cachedRobot.UUID); ' robot' +
if (accountRobot) (this.cachedRobotAccessories.length === 1 ? '' : 's'),
{ );
this.log.debug("[" + cachedRobot.displayName + "] Cached robot found in Vorwerk account."); for (const cachedRobot of this.cachedRobotAccessories) {
} const accountRobot = robots.find(
else (robot) =>
{ this.api.hap.uuid.generate(robot._serial) === cachedRobot.UUID,
this.log.error("[" + cachedRobot.displayName + "] Cached robot not found in Vorwerk account. Robot will now be removed from homebridge."); );
this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [cachedRobot]); if (accountRobot) {
} this.log.debug(
} '[' +
cachedRobot.displayName +
'] Cached robot found in Vorwerk account.',
);
} else {
this.log.error(
'[' +
cachedRobot.displayName +
'] Cached robot not found in Vorwerk account. Robot will now be removed from homebridge.',
);
this.api.unregisterPlatformAccessories(
PLUGIN_NAME,
PLATFORM_NAME,
[cachedRobot],
);
}
}
// Add / Update homebridge accessories with robot information from Vorwerk. This must be done for new and existing robots to reflect changes in the name, firmware, pluginconfig etc. // Add / Update homebridge accessories with robot information from Vorwerk.
for (let robot of robots) // This must be done for new and existing robots to reflect changes in the name, firmware, pluginconfig etc.
{ for (const robot of robots) {
// Check if robot already exists as an accessory // Check if robot already exists as an accessory
const uuid = this.api.hap.uuid.generate(robot._serial); const uuid = this.api.hap.uuid.generate(robot._serial);
const cachedRobot = this.cachedRobotAccessories.find(accessory => accessory.UUID === uuid); const cachedRobot = this.cachedRobotAccessories.find(
(accessory) => accessory.UUID === uuid,
);
if (cachedRobot) if (cachedRobot) {
{ this.log.debug(
this.log.debug("[" + robot.name + "] Connecting to cached robot and updating information."); '[' +
} robot.name +
else '] Connecting to cached robot and updating information.',
{ );
this.log.debug("[" + robot.name + "] Connecting to new robot and updating information."); } else {
} this.log.debug(
'[' +
robot.name +
'] Connecting to new robot and updating information.',
);
}
robot.getState((error, state) => { robot.getState((error, state) => {
if (error) if (error) {
{ this.log.error(
this.log.error("[" + robot.name + "] Cannot connect to robot. Is the robot connected to the internet? Retrying in 5 minutes."); '[' +
this.log.error("Error: " + error); robot.name +
setTimeout(() => { '] Cannot connect to robot. Is the robot connected to the internet? Retrying in 5 minutes.',
this.discoverRobots(); );
}, 5 * 60 * 1000); this.log.error('Error: ' + error);
} setTimeout(() => {
else this.discoverRobots();
{ }, 5 * 60 * 1000);
try } else {
{ try {
robot.meta = state.meta; robot.meta = state.meta;
robot.availableServices = state.availableServices; robot.availableServices = state.availableServices;
// Update existing robot accessor // Update existing robot accessor
if (cachedRobot) if (cachedRobot) {
{ // TODO update maps
// TODO update maps
cachedRobot.context.robot = robot; cachedRobot.context.robot = robot;
this.api.updatePlatformAccessories([cachedRobot]); this.api.updatePlatformAccessories([cachedRobot]);
new KoboldVacuumRobotAccessory(this, cachedRobot, this.config); new KoboldVacuumRobotAccessory(
this.log.info("[" + robot.name + "] Successfully loaded robot from cache"); this,
} cachedRobot,
// Create new robot accessory this.config,
else );
{ this.log.info(
// TODO get maps '[' +
robot.name +
'] Successfully loaded robot from cache',
);
} else {
// Create new robot accessory
// TODO get maps
const newRobot = new this.api.platformAccessory(robot.name, uuid); const newRobot = new this.api.platformAccessory(
newRobot.context.robot = robot; robot.name,
new KoboldVacuumRobotAccessory(this, newRobot, this.config); uuid,
this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [newRobot]); );
this.log.info("[" + robot.name + "] Successfully created as new robot"); newRobot.context.robot = robot;
} new KoboldVacuumRobotAccessory(this, newRobot, this.config);
} this.api.registerPlatformAccessories(
catch (error) PLUGIN_NAME,
{ PLATFORM_NAME,
this.log.error("[" + robot.name + "] Creating accessory failed. Error: " + error); [newRobot],
throw new this.api.hap.HapStatusError(this.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE); );
} this.log.info(
} '[' + robot.name + '] Successfully created as new robot',
);
}
} catch (error) {
this.log.error(
'[' +
robot.name +
'] Creating accessory failed. Error: ' +
error,
);
throw new this.api.hap.HapStatusError(
this.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE,
);
}
}
// // Get all maps for each robot // // Get all maps for each robot
// robot.getPersistentMaps((error, maps) => { // robot.getPersistentMaps((error, maps) => {
// if (error) // if (error)
// { // {
// this.log.error("Error updating persistent maps: " + error + ": " + maps); // this.log.error("Error updating persistent maps: " + error + ": " + maps);
// callback(); // callback();
// } // }
// // Robot has no maps // // Robot has no maps
// else if (maps.length === 0) // else if (maps.length === 0)
// { // {
// robot.maps = []; // robot.maps = [];
// this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices}); // this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices});
// loadedRobots++; // loadedRobots++;
// if (loadedRobots === robots.length) // if (loadedRobots === robots.length)
// { // {
// callback(); // callback();
// } // }
// } // }
// // Robot has maps // // Robot has maps
// else // else
// { // {
// robot.maps = maps; // robot.maps = maps;
// let loadedMaps = 0; // let loadedMaps = 0;
// robot.maps.forEach((map) => { // robot.maps.forEach((map) => {
// // Save zones in each map // // Save zones in each map
// robot.getMapBoundaries(map.id, (error, result) => { // robot.getMapBoundaries(map.id, (error, result) => {
// if (error) // if (error)
// { // {
// this.log.error("Error getting boundaries: " + error + ": " + result) // this.log.error("Error getting boundaries: " + error + ": " + result)
// } // }
// else // else
// { // {
// map.boundaries = result.boundaries; // map.boundaries = result.boundaries;
// } // }
// loadedMaps++; // loadedMaps++;
// //
// // Robot is completely requested if zones for all maps are loaded // // Robot is completely requested if zones for all maps are loaded
// if (loadedMaps === robot.maps.length) // if (loadedMaps === robot.maps.length)
// { // {
// this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices}); // this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices});
// loadedRobots++; // loadedRobots++;
// if (loadedRobots === robots.length) // if (loadedRobots === robots.length)
// { // {
// callback(); // callback();
// } // }
// } // }
// }) // })
// }); // });
// } // }
// }); // });
}); });
} }
}); });
}); });
} } catch (error) {
catch (error) this.log.error(
{ `Can't log on to Vorwerk cloud. Please check your internet connection and your credentials.
this.log.error("Can't log on to Vorwerk cloud. Please check your internet connection and your credentials. Try again later if the neato servers have issues. Error: " + error); Try again later if the neato servers have issues. Error: ` +
} error,
} );
}
}
} }

View File

@ -1,12 +1,11 @@
import {API} from "homebridge"; import { API } from 'homebridge';
import {PLATFORM_NAME} from "./settings"; import { PLATFORM_NAME } from './settings';
import {HomebridgeKoboldPlatform} from "./homebridgeKoboldPlatform"; import { HomebridgeKoboldPlatform } from './homebridgeKoboldPlatform';
/** /**
* This method registers the platform with Homebridge * This method registers the platform with Homebridge
*/ */
export = (api: API) => export = (api: API) => {
{ api.registerPlatform(PLATFORM_NAME, HomebridgeKoboldPlatform);
api.registerPlatform(PLATFORM_NAME, HomebridgeKoboldPlatform);
}; };

View File

@ -1,21 +1,19 @@
export class Options export class Options {
{ public eco: boolean;
public eco: boolean; public extraCare: boolean;
public extraCare: boolean; public noGoLines: boolean;
public noGoLines: boolean; public spotCharacteristics: boolean;
public spotCharacteristics: boolean; public spotRepeat: boolean;
public spotRepeat: boolean; public spotWidth: number;
public spotWidth: number; public spotHeight: number;
public spotHeight: number;
constructor() {
constructor() this.eco = false;
{ this.extraCare = false;
this.eco = false; this.noGoLines = false;
this.extraCare = false; this.spotCharacteristics = false;
this.noGoLines = false; this.spotRepeat = false;
this.spotCharacteristics = false; this.spotWidth = 200;
this.spotRepeat = false; this.spotHeight = 200;
this.spotWidth = 200; }
this.spotHeight = 200; }
}
}

View File

@ -4,16 +4,16 @@ export enum CleanType {
} }
export enum RobotService { export enum RobotService {
CLEAN = "clean", CLEAN = 'clean',
CLEAN_SPOT = "cleanSpot", CLEAN_SPOT = 'cleanSpot',
CLEAN_ZONE = "cleanZone", CLEAN_ZONE = 'cleanZone',
GO_TO_DOCK = "goToDock", GO_TO_DOCK = 'goToDock',
DOCKED = "dockState", DOCKED = 'dockState',
BIN_FULL = "binFull", BIN_FULL = 'binFull',
FIND_ME = "findMe", FIND_ME = 'findMe',
SCHEDULE = "schedule", SCHEDULE = 'schedule',
ECO = "eco", ECO = 'eco',
NOGO_LINES = "noGoLines", NOGO_LINES = 'noGoLines',
EXTRA_CARE = "extraCare", EXTRA_CARE = 'extraCare',
BATTERY = "battery", BATTERY = 'battery',
} }