WIP dynamic platform
This commit is contained in:
		
							
								
								
									
										9
									
								
								homebridge-neato.iml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								homebridge-neato.iml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,9 @@
 | 
				
			|||||||
 | 
					<?xml version="1.0" encoding="UTF-8"?>
 | 
				
			||||||
 | 
					<module type="WEB_MODULE" version="4">
 | 
				
			||||||
 | 
					  <component name="NewModuleRootManager" inherit-compiler-output="true">
 | 
				
			||||||
 | 
					    <exclude-output />
 | 
				
			||||||
 | 
					    <content url="file://$MODULE_DIR$" />
 | 
				
			||||||
 | 
					    <orderEntry type="inheritedJdk" />
 | 
				
			||||||
 | 
					    <orderEntry type="sourceFolder" forTests="false" />
 | 
				
			||||||
 | 
					  </component>
 | 
				
			||||||
 | 
					</module>
 | 
				
			||||||
							
								
								
									
										2841
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
							
						
						
									
										2841
									
								
								package-lock.json
									
									
									
										generated
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -48,7 +48,7 @@
 | 
				
			|||||||
  "dependencies": {
 | 
					  "dependencies": {
 | 
				
			||||||
    "colors": "^1.4.0",
 | 
					    "colors": "^1.4.0",
 | 
				
			||||||
    "debug": "^4.1.1",
 | 
					    "debug": "^4.1.1",
 | 
				
			||||||
    "node-botvac": "^0.4.0",
 | 
					    "node-botvac": "^0.4.1",
 | 
				
			||||||
    "uuid": "^3.3.2"
 | 
					    "uuid": "^3.3.2"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "devDependencies": {
 | 
					  "devDependencies": {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
import {CharacteristicValue, PlatformAccessory, Service} from 'homebridge';
 | 
					import {CharacteristicValue, Logger, PlatformAccessory, Service} from 'homebridge';
 | 
				
			||||||
import {HomebridgeNeatoPlatform} from '../homebridgeNeatoPlatform';
 | 
					import {HomebridgeNeatoPlatform} from '../homebridgeNeatoPlatform';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const debug = require('debug')('my-app:my-module');
 | 
					const debug = require('debug')('my-app:my-module');
 | 
				
			||||||
@@ -10,14 +10,15 @@ const debug = require('debug')('my-app:my-module');
 | 
				
			|||||||
export class NeatoVacuumRobotAccessory
 | 
					export class NeatoVacuumRobotAccessory
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	private cleanService: Service;
 | 
						private cleanService: Service;
 | 
				
			||||||
 | 
						private findMeService: Service;
 | 
				
			||||||
	private robot: any;
 | 
						private robot: any;
 | 
				
			||||||
 | 
						private log: Logger;
 | 
				
			||||||
	// private goToDockService: Service;
 | 
						// private goToDockService: Service;
 | 
				
			||||||
	// private dockStateService: Service;
 | 
						// private dockStateService: Service;
 | 
				
			||||||
	// private ecoService: Service;
 | 
						// private ecoService: Service;
 | 
				
			||||||
	// private noGoLinesService: Service;
 | 
						// private noGoLinesService: Service;
 | 
				
			||||||
	// private extraCareService: Service;
 | 
						// private extraCareService: Service;
 | 
				
			||||||
	// private scheduleService: Service;
 | 
						// private scheduleService: Service;
 | 
				
			||||||
	// private findMeService: Service;
 | 
					 | 
				
			||||||
	// private spotCleanService: Service;
 | 
						// private spotCleanService: Service;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/**
 | 
						/**
 | 
				
			||||||
@@ -31,6 +32,7 @@ export class NeatoVacuumRobotAccessory
 | 
				
			|||||||
			private readonly isNew: Boolean)
 | 
								private readonly isNew: Boolean)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		this.robot = accessory.context.robot;
 | 
							this.robot = accessory.context.robot;
 | 
				
			||||||
 | 
							this.log = platform.log;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// set accessory information
 | 
							// set accessory information
 | 
				
			||||||
		this.accessory.getService(this.platform.Service.AccessoryInformation)!
 | 
							this.accessory.getService(this.platform.Service.AccessoryInformation)!
 | 
				
			||||||
@@ -40,13 +42,17 @@ export class NeatoVacuumRobotAccessory
 | 
				
			|||||||
				.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.robot.meta.firmware)
 | 
									.setCharacteristic(this.platform.Characteristic.FirmwareRevision, this.robot.meta.firmware)
 | 
				
			||||||
				.setCharacteristic(this.platform.Characteristic.Name, this.robot.name);
 | 
									.setCharacteristic(this.platform.Characteristic.Name, this.robot.name);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							let cleanServiceName = this.robot.name + " Clean";
 | 
				
			||||||
		let cleanServiceName = robot.name + " Clean";
 | 
					 | 
				
			||||||
		this.cleanService = this.accessory.getService(cleanServiceName) || this.accessory.addService(this.platform.Service.Switch, cleanServiceName, "CLEAN");
 | 
							this.cleanService = this.accessory.getService(cleanServiceName) || this.accessory.addService(this.platform.Service.Switch, cleanServiceName, "CLEAN");
 | 
				
			||||||
 | 
							let findMeServiceName = this.robot.name + " Find Me";
 | 
				
			||||||
 | 
							this.findMeService = this.accessory.getService(findMeServiceName) || this.accessory.addService(this.platform.Service.Switch, findMeServiceName, "FIND_ME");
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
		this.cleanService.getCharacteristic(this.platform.Characteristic.On)
 | 
							this.cleanService.getCharacteristic(this.platform.Characteristic.On)
 | 
				
			||||||
				.onSet(this.setClean.bind(this))
 | 
									.onSet(this.setClean.bind(this))
 | 
				
			||||||
				.onGet(this.getClean.bind(this));
 | 
									.onGet(this.getClean.bind(this));
 | 
				
			||||||
 | 
							this.findMeService.getCharacteristic(this.platform.Characteristic.On)
 | 
				
			||||||
 | 
									.onSet(this.setFindMe.bind(this))
 | 
				
			||||||
 | 
									.onGet(this.getFindMe.bind(this));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// /**
 | 
							// /**
 | 
				
			||||||
		//  * Updating characteristics values asynchronously.
 | 
							//  * Updating characteristics values asynchronously.
 | 
				
			||||||
@@ -75,33 +81,33 @@ export class NeatoVacuumRobotAccessory
 | 
				
			|||||||
	async setClean(on: CharacteristicValue)
 | 
						async setClean(on: CharacteristicValue)
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// TODO debug(this.robot.name + ": " + (on ? "Enabled ".brightGreen : "Disabled".red) + " Clean " + (this.boundary ? JSON.stringify(this.boundary) : ''));
 | 
							// TODO debug(this.robot.name + ": " + (on ? "Enabled ".brightGreen : "Disabled".red) + " Clean " + (this.boundary ? JSON.stringify(this.boundary) : ''));
 | 
				
			||||||
		this.platform.updateRobot(this.robot._serial, (error, result) =>
 | 
							try
 | 
				
			||||||
		{
 | 
							{
 | 
				
			||||||
 | 
								await this.updateRobot();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			// Start
 | 
								// Start
 | 
				
			||||||
			if (on)
 | 
								if (on)
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				// No room given or same room
 | 
									// No room given or same room
 | 
				
			||||||
				if (this.boundary == null || this.robot.cleaningBoundaryId === this.boundary.id)
 | 
									if (this.robot.boundary == null || this.robot.cleaningBoundaryId === this.robot.boundary.id)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					// Resume cleaning
 | 
										// Resume cleaning
 | 
				
			||||||
					if (this.robot.canResume)
 | 
										if (this.robot.canResume)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						debug(this.name + ": ## Resume cleaning");
 | 
											debug(this.robot.name + ": ## Resume cleaning");
 | 
				
			||||||
						this.robot.resumeCleaning((error) =>
 | 
											await this.robot.resumeCleaning();
 | 
				
			||||||
						{
 | 
											return;
 | 
				
			||||||
							callback(error);
 | 
					 | 
				
			||||||
						});
 | 
					 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					// Start cleaning
 | 
										// Start cleaning
 | 
				
			||||||
					else if (this.robot.canStart)
 | 
										else if (this.robot.canStart)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						this.clean(callback);
 | 
											// TODO this.clean(callback);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					// Cannot start
 | 
										// Cannot start
 | 
				
			||||||
					else
 | 
										else
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						debug(this.name + ": Cannot start, maybe already cleaning (expected)");
 | 
											// TODO debug(this.name + ": Cannot start, maybe already cleaning (expected)");
 | 
				
			||||||
						callback();
 | 
											return;
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				// Different room given
 | 
									// Different room given
 | 
				
			||||||
@@ -110,18 +116,18 @@ export class NeatoVacuumRobotAccessory
 | 
				
			|||||||
					// Return to dock
 | 
										// Return to dock
 | 
				
			||||||
					if (this.robot.canPause || this.robot.canResume)
 | 
										if (this.robot.canPause || this.robot.canResume)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						debug(this.name + ": ## Returning to dock to start cleaning of new room");
 | 
											// debug(this.name + ": ## Returning to dock to start cleaning of new room");
 | 
				
			||||||
						this.setGoToDock(true, (error, result) =>
 | 
											// this.setGoToDock(true, (error, result) =>
 | 
				
			||||||
						{
 | 
											// {
 | 
				
			||||||
							this.nextRoom = this.boundary.id;
 | 
											// 	this.nextRoom = this.boundary.id;
 | 
				
			||||||
							callback();
 | 
											// 	callback();
 | 
				
			||||||
						});
 | 
											// });
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					// Start new cleaning of new room
 | 
										// Start new cleaning of new room
 | 
				
			||||||
					else
 | 
										else
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						debug(this.name + ": ## Start cleaning of new room");
 | 
											// debug(this.name + ": ## Start cleaning of new room");
 | 
				
			||||||
						this.clean(callback);
 | 
											// this.clean(callback);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
@@ -130,32 +136,99 @@ export class NeatoVacuumRobotAccessory
 | 
				
			|||||||
			{
 | 
								{
 | 
				
			||||||
				if (this.robot.canPause)
 | 
									if (this.robot.canPause)
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					debug(this.name + ": ## Pause cleaning");
 | 
										// debug(this.name + ": ## Pause cleaning");
 | 
				
			||||||
					this.robot.pauseCleaning((error) =>
 | 
										// this.robot.pauseCleaning((error) => {
 | 
				
			||||||
					{
 | 
										// 	callback(error);
 | 
				
			||||||
						callback(error);
 | 
										// });
 | 
				
			||||||
					});
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				else
 | 
									else
 | 
				
			||||||
				{
 | 
									{
 | 
				
			||||||
					debug(this.name + ": Already paused");
 | 
										// debug(this.name + ": Already paused");
 | 
				
			||||||
					callback();
 | 
										// callback();
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
							catch (error)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								this.log.warn("Cannot start cleaning: " + error);
 | 
				
			||||||
 | 
								throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	async getClean(): Promise<CharacteristicValue>
 | 
						async getClean(): Promise<CharacteristicValue>
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		// implement your own code to check if the device is on
 | 
							try
 | 
				
			||||||
		const isOn = this.exampleStates.On;
 | 
							{
 | 
				
			||||||
 | 
								await this.updateRobot();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		this.platform.log.debug('Get Characteristic On ->', isOn);
 | 
								let cleaning;
 | 
				
			||||||
 | 
								if (this.robot.boundary == null)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									cleaning = this.robot.canPause;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								else
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									cleaning = this.robot.canPause && (this.robot.cleaningBoundaryId === this.robot.boundary.id)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// if you need to return an error to show the device as "Not Responding" in the Home app:
 | 
								// TODO debug(this.robot.name + ": Cleaning is " + (cleaning ? 'ON'.brightGreen : 'OFF'.red));
 | 
				
			||||||
		// throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
								return cleaning;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							catch (error)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								this.log.warn("Cannot get cleaning status: " + error);
 | 
				
			||||||
 | 
								throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		return isOn;
 | 
					
 | 
				
			||||||
 | 
						getFindMe()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async setFindMe(on: CharacteristicValue)
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							if (on)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								// TODO debug(this.name + ": ## Find me");
 | 
				
			||||||
 | 
								setTimeout(() => {
 | 
				
			||||||
 | 
									this.findMeService.updateCharacteristic(this.platform.Characteristic.On, false);
 | 
				
			||||||
 | 
								}, 1000);
 | 
				
			||||||
 | 
								
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									await this.robot.findMe();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (error)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									this.log.warn("Cannot start find me: " + error);
 | 
				
			||||||
 | 
									throw new this.platform.api.hap.HapStatusError(this.platform.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						async updateRobot()
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							// Data is up to date
 | 
				
			||||||
 | 
							if (typeof (this.robot.lastUpdate) !== 'undefined' && new Date().getTime() - this.robot.lastUpdate < 2000)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							else
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								debug(this.robot.name + ": ++ Updating robot state");
 | 
				
			||||||
 | 
								this.robot.lastUpdate = new Date().getTime();
 | 
				
			||||||
 | 
								try
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									await this.robot.getState();
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								catch (error)
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									this.log.error("Cannot update robot " + this.robot.name + ". Check if robot is online. " + error);
 | 
				
			||||||
 | 
									return false;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,135 +49,148 @@ export class HomebridgeNeatoPlatform implements DynamicPlatformPlugin
 | 
				
			|||||||
		debug("Discovering new robots");
 | 
							debug("Discovering new robots");
 | 
				
			||||||
		let client = new NeatoApi.Client();
 | 
							let client = new NeatoApi.Client();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// Login
 | 
							try
 | 
				
			||||||
		client.authorize((this.config)['email'], (this.config)['password'], false, (error) => {
 | 
							{
 | 
				
			||||||
			if (error)
 | 
								// Login
 | 
				
			||||||
			{
 | 
								client.authorize((this.config)['email'], (this.config)['password'], false, (error) => {
 | 
				
			||||||
				this.log.error("Can't log on to neato cloud. Please check your internet connection and your credentials. Try again later if the neato servers have issues: " + error);
 | 
									if (error)
 | 
				
			||||||
				return;
 | 
									{
 | 
				
			||||||
			}
 | 
										throw new this.api.hap.HapStatusError(this.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
			else
 | 
									}
 | 
				
			||||||
			{
 | 
					
 | 
				
			||||||
				// Get all robots
 | 
									// Get all robots from account
 | 
				
			||||||
				client.getRobots((error, robots) => {
 | 
									client.getRobots((error, robots) => {
 | 
				
			||||||
					if (error)
 | 
										if (error)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						this.log.error("Successful login but can't connect to your neato robot: " + error);
 | 
											this.log.error("Successful login but can't connect to your neato robot: " + error);
 | 
				
			||||||
						return;
 | 
											throw new this.api.hap.HapStatusError(this.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					else if (robots.length === 0)
 | 
										else if (robots.length === 0)
 | 
				
			||||||
					{
 | 
										{
 | 
				
			||||||
						this.log.error("Successful login but no robots associated with your account.");
 | 
											this.log.error("Successful login but no robots associated with your account.");
 | 
				
			||||||
						return;
 | 
											throw new this.api.hap.HapStatusError(this.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					else
 | 
					 | 
				
			||||||
					{
 | 
					 | 
				
			||||||
						debug("Found " + robots.length + " robots");
 | 
					 | 
				
			||||||
						let loadedRobots = 0;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
						robots.forEach((robot) => {
 | 
										debug("Found " + robots.length + " robots");
 | 
				
			||||||
							// Get additional information for the robot
 | 
										let loadedRobots = 0;
 | 
				
			||||||
							robot.getState((error, state) => {
 | 
					
 | 
				
			||||||
								if (error)
 | 
										for (let robot of robots)
 | 
				
			||||||
 | 
										{
 | 
				
			||||||
 | 
											// Get additional information for the robot
 | 
				
			||||||
 | 
											robot.getState((error, state) => {
 | 
				
			||||||
 | 
												this.log.debug("Got state for robot: " + robot.name);
 | 
				
			||||||
 | 
												robot.meta = state.meta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												if (error)
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													this.log.error("Error getting robot meta information: " + error + ": " + state);
 | 
				
			||||||
 | 
													throw new this.api.hap.HapStatusError(this.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												try
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													const uuid = this.api.hap.uuid.generate(robot._serial);
 | 
				
			||||||
 | 
													const existingAccessory = this.robotAccessories.find(accessory => accessory.UUID === uuid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
													if (existingAccessory)
 | 
				
			||||||
								{
 | 
													{
 | 
				
			||||||
									this.log.error("Error getting robot meta information: " + error + ": " + state);
 | 
														// the accessory already exists
 | 
				
			||||||
									return;
 | 
														this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
 | 
				
			||||||
 | 
														existingAccessory.context.robot = robot;
 | 
				
			||||||
 | 
														// TODO update maps
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
 | 
				
			||||||
 | 
														// existingAccessory.context.device = device;
 | 
				
			||||||
 | 
														// this.api.updatePlatformAccessories([existingAccessory]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														// create the accessory handler for the restored accessory
 | 
				
			||||||
 | 
														// this is imported from `platformAccessory.ts`
 | 
				
			||||||
 | 
														new NeatoVacuumRobotAccessory(this, existingAccessory, false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														// it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, eg.:
 | 
				
			||||||
 | 
														// remove platform accessories when no longer present
 | 
				
			||||||
 | 
														// this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
 | 
				
			||||||
 | 
														// this.log.info('Removing existing accessory from cache:', existingAccessory.displayName);
 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
								else
 | 
													else
 | 
				
			||||||
								{
 | 
													{
 | 
				
			||||||
									const uuid = this.api.hap.uuid.generate(robot._serial);
 | 
														this.log.info('Adding new accessory: ', robot.name);
 | 
				
			||||||
									const existingAccessory = this.robotAccessories.find(accessory => accessory.UUID === uuid);
 | 
														const accessory = new this.api.platformAccessory(robot.name, uuid);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
									if (existingAccessory)
 | 
														accessory.context.robot = robot;
 | 
				
			||||||
									{
 | 
														new NeatoVacuumRobotAccessory(this, accessory, true);
 | 
				
			||||||
										// the accessory already exists
 | 
					 | 
				
			||||||
										this.log.info('Restoring existing accessory from cache:', existingAccessory.displayName);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
										// TODO update maps
 | 
														// link the accessory to your platform
 | 
				
			||||||
 | 
														this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
 | 
				
			||||||
										// if you need to update the accessory.context then you should run `api.updatePlatformAccessories`. eg.:
 | 
														// TODO get maps
 | 
				
			||||||
										// existingAccessory.context.device = device;
 | 
					 | 
				
			||||||
										// this.api.updatePlatformAccessories([existingAccessory]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										// create the accessory handler for the restored accessory
 | 
					 | 
				
			||||||
										// this is imported from `platformAccessory.ts`
 | 
					 | 
				
			||||||
										new NeatoVacuumRobotAccessory(this, existingAccessory, false);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										// it is possible to remove platform accessories at any time using `api.unregisterPlatformAccessories`, eg.:
 | 
					 | 
				
			||||||
										// remove platform accessories when no longer present
 | 
					 | 
				
			||||||
										// this.api.unregisterPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [existingAccessory]);
 | 
					 | 
				
			||||||
										// this.log.info('Removing existing accessory from cache:', existingAccessory.displayName);
 | 
					 | 
				
			||||||
									}
 | 
					 | 
				
			||||||
									else
 | 
					 | 
				
			||||||
									{
 | 
					 | 
				
			||||||
										this.log.info('Adding new accessory: ', robot.name);
 | 
					 | 
				
			||||||
										const accessory = new this.api.platformAccessory(robot.name, uuid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										accessory.context.robot = robot;
 | 
					 | 
				
			||||||
										new NeatoVacuumRobotAccessory(this, accessory, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
										// link the accessory to your platform
 | 
					 | 
				
			||||||
										this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [accessory]);
 | 
					 | 
				
			||||||
										// TODO get maps
 | 
					 | 
				
			||||||
									}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
									// // Get all maps for each robot
 | 
					 | 
				
			||||||
									// robot.getPersistentMaps((error, maps) => {
 | 
					 | 
				
			||||||
									// 	if (error)
 | 
					 | 
				
			||||||
									// 	{
 | 
					 | 
				
			||||||
									// 		this.log.error("Error updating persistent maps: " + error + ": " + maps);
 | 
					 | 
				
			||||||
									// 		callback();
 | 
					 | 
				
			||||||
									// 	}
 | 
					 | 
				
			||||||
									// 	// Robot has no maps
 | 
					 | 
				
			||||||
									// 	else if (maps.length === 0)
 | 
					 | 
				
			||||||
									// 	{
 | 
					 | 
				
			||||||
									// 		robot.maps = [];
 | 
					 | 
				
			||||||
									// 		this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices});
 | 
					 | 
				
			||||||
									// 		loadedRobots++;
 | 
					 | 
				
			||||||
									// 		if (loadedRobots === robots.length)
 | 
					 | 
				
			||||||
									// 		{
 | 
					 | 
				
			||||||
									// 			callback();
 | 
					 | 
				
			||||||
									// 		}
 | 
					 | 
				
			||||||
									// 	}
 | 
					 | 
				
			||||||
									// 	// Robot has maps
 | 
					 | 
				
			||||||
									// 	else
 | 
					 | 
				
			||||||
									// 	{
 | 
					 | 
				
			||||||
									// 		robot.maps = maps;
 | 
					 | 
				
			||||||
									// 		let loadedMaps = 0;
 | 
					 | 
				
			||||||
									// 		robot.maps.forEach((map) => {
 | 
					 | 
				
			||||||
									// 			// Save zones in each map
 | 
					 | 
				
			||||||
									// 			robot.getMapBoundaries(map.id, (error, result) => {
 | 
					 | 
				
			||||||
									// 				if (error)
 | 
					 | 
				
			||||||
									// 				{
 | 
					 | 
				
			||||||
									// 					this.log.error("Error getting boundaries: " + error + ": " + result)
 | 
					 | 
				
			||||||
									// 				}
 | 
					 | 
				
			||||||
									// 				else
 | 
					 | 
				
			||||||
									// 				{
 | 
					 | 
				
			||||||
									// 					map.boundaries = result.boundaries;
 | 
					 | 
				
			||||||
									// 				}
 | 
					 | 
				
			||||||
									// 				loadedMaps++;
 | 
					 | 
				
			||||||
									//
 | 
					 | 
				
			||||||
									// 				// Robot is completely requested if zones for all maps are loaded
 | 
					 | 
				
			||||||
									// 				if (loadedMaps === robot.maps.length)
 | 
					 | 
				
			||||||
									// 				{
 | 
					 | 
				
			||||||
									// 					this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices});
 | 
					 | 
				
			||||||
									// 					loadedRobots++;
 | 
					 | 
				
			||||||
									// 					if (loadedRobots === robots.length)
 | 
					 | 
				
			||||||
									// 					{
 | 
					 | 
				
			||||||
									// 						callback();
 | 
					 | 
				
			||||||
									// 					}
 | 
					 | 
				
			||||||
									// 				}
 | 
					 | 
				
			||||||
									// 			})
 | 
					 | 
				
			||||||
									// 		});
 | 
					 | 
				
			||||||
									// 	}
 | 
					 | 
				
			||||||
									// });
 | 
					 | 
				
			||||||
								}
 | 
													}
 | 
				
			||||||
							});
 | 
												}
 | 
				
			||||||
 | 
												catch (error)
 | 
				
			||||||
 | 
												{
 | 
				
			||||||
 | 
													this.log.error("Error creating robot accessory: " + robot.name);
 | 
				
			||||||
 | 
													this.log.error(error);
 | 
				
			||||||
 | 
													throw new this.api.hap.HapStatusError(this.api.hap.HAPStatus.SERVICE_COMMUNICATION_FAILURE);
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
												// // Get all maps for each robot
 | 
				
			||||||
 | 
												// robot.getPersistentMaps((error, maps) => {
 | 
				
			||||||
 | 
												// 	if (error)
 | 
				
			||||||
 | 
												// 	{
 | 
				
			||||||
 | 
												// 		this.log.error("Error updating persistent maps: " + error + ": " + maps);
 | 
				
			||||||
 | 
												// 		callback();
 | 
				
			||||||
 | 
												// 	}
 | 
				
			||||||
 | 
												// 	// Robot has no maps
 | 
				
			||||||
 | 
												// 	else if (maps.length === 0)
 | 
				
			||||||
 | 
												// 	{
 | 
				
			||||||
 | 
												// 		robot.maps = [];
 | 
				
			||||||
 | 
												// 		this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices});
 | 
				
			||||||
 | 
												// 		loadedRobots++;
 | 
				
			||||||
 | 
												// 		if (loadedRobots === robots.length)
 | 
				
			||||||
 | 
												// 		{
 | 
				
			||||||
 | 
												// 			callback();
 | 
				
			||||||
 | 
												// 		}
 | 
				
			||||||
 | 
												// 	}
 | 
				
			||||||
 | 
												// 	// Robot has maps
 | 
				
			||||||
 | 
												// 	else
 | 
				
			||||||
 | 
												// 	{
 | 
				
			||||||
 | 
												// 		robot.maps = maps;
 | 
				
			||||||
 | 
												// 		let loadedMaps = 0;
 | 
				
			||||||
 | 
												// 		robot.maps.forEach((map) => {
 | 
				
			||||||
 | 
												// 			// Save zones in each map
 | 
				
			||||||
 | 
												// 			robot.getMapBoundaries(map.id, (error, result) => {
 | 
				
			||||||
 | 
												// 				if (error)
 | 
				
			||||||
 | 
												// 				{
 | 
				
			||||||
 | 
												// 					this.log.error("Error getting boundaries: " + error + ": " + result)
 | 
				
			||||||
 | 
												// 				}
 | 
				
			||||||
 | 
												// 				else
 | 
				
			||||||
 | 
												// 				{
 | 
				
			||||||
 | 
												// 					map.boundaries = result.boundaries;
 | 
				
			||||||
 | 
												// 				}
 | 
				
			||||||
 | 
												// 				loadedMaps++;
 | 
				
			||||||
 | 
												//
 | 
				
			||||||
 | 
												// 				// Robot is completely requested if zones for all maps are loaded
 | 
				
			||||||
 | 
												// 				if (loadedMaps === robot.maps.length)
 | 
				
			||||||
 | 
												// 				{
 | 
				
			||||||
 | 
												// 					this.robotAccessories.push({device: robot, meta: state.meta, availableServices: state.availableServices});
 | 
				
			||||||
 | 
												// 					loadedRobots++;
 | 
				
			||||||
 | 
												// 					if (loadedRobots === robots.length)
 | 
				
			||||||
 | 
												// 					{
 | 
				
			||||||
 | 
												// 						callback();
 | 
				
			||||||
 | 
												// 					}
 | 
				
			||||||
 | 
												// 				}
 | 
				
			||||||
 | 
												// 			})
 | 
				
			||||||
 | 
												// 		});
 | 
				
			||||||
 | 
												// 	}
 | 
				
			||||||
 | 
												// });
 | 
				
			||||||
						});
 | 
											});
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				});
 | 
									});
 | 
				
			||||||
			}
 | 
								});
 | 
				
			||||||
		});
 | 
							}
 | 
				
			||||||
 | 
							catch (error)
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								this.log.error("Can't log on to neato cloud. Please check your internet connection and your credentials. Try again later if the neato servers have issues: " + error);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
import { API } from 'homebridge';
 | 
					import { API } from 'homebridge';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { PLATFORM_NAME } from './settings';
 | 
					import { PLATFORM_NAME } from './settings';
 | 
				
			||||||
import { HomebridgeNeatoPlatform } from './platform';
 | 
					import { HomebridgeNeatoPlatform } from './homebridgeNeatoPlatform';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This method registers the platform with Homebridge
 | 
					 * This method registers the platform with Homebridge
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user