Skip to content

Commit

Permalink
clean rooms
Browse files Browse the repository at this point in the history
  • Loading branch information
gtalusan committed Sep 5, 2024
1 parent 1b0955e commit c0d16bc
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 34 deletions.
25 changes: 24 additions & 1 deletion config.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"description": "IP Address of your Eufy Robovac",
"type": "string",
"required": true,
"default": "10.0.1.69"
"placeholder": "10.0.1.69"
},
"deviceId": {
"title": "Tuya Device ID",
Expand All @@ -30,6 +30,29 @@
"description": "Tuya/Eufy Device/Local Key (see: https://github.com/markbajaj/eufy-device-id-python)",
"type": "string",
"required": true
},
"roomSwitches": {
"description": "Per-Room Switches",
"type": "array",
"items": {
"title": "Switch",
"type": "object",
"properties": {
"name": {
"title": "Name",
"type": "string",
"placeholder": "Arbitrary name for this switch",
"required": true
},
"rooms": {
"title": "Rooms",
"type": "string",
"placeholder": "A room number or comma-separated list of room numbers",
"pattern": "^[0-9]+(,[0-9]+)*$",
"required": true
}
}
}
}
}
}
Expand Down
38 changes: 6 additions & 32 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,6 @@
"typescript-eslint": "^8.0.1"
},
"dependencies": {
"@george.talusan/eufy-robovac-js": "^0.0.6"
"@george.talusan/eufy-robovac-js": "^0.0.9"
}
}
99 changes: 99 additions & 0 deletions src/cleanRoomsAccessory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import type { CharacteristicValue, PlatformAccessory, Service } from 'homebridge';

import type { EufyRobovacHomebridgePlatform } from './platform.js';

interface RobovacEvent {
command: string;
value: boolean | number | string | object | null;
};

const sleep = (ms: number) => new Promise(r => setTimeout(r, ms));

export class CleanRoomsPlatformAccessory {
private on: boolean;

constructor(
private readonly platform: EufyRobovacHomebridgePlatform,
private readonly accessory: PlatformAccessory,
) {
const displayName = this.accessory.context.displayName;

this.accessory.getService(this.platform.Service.AccessoryInformation)!
.setCharacteristic(this.platform.Characteristic.Manufacturer, 'Eufy')
.setCharacteristic(this.platform.Characteristic.Model, 'Robovac')
.setCharacteristic(this.platform.Characteristic.SerialNumber, 'Default-Serial');

const main: Service = this.accessory.getService(`${displayName}`) ||
this.accessory.addService(this.platform.Service.Switch, `${displayName}`);
main.getCharacteristic(this.platform.Characteristic.On)
.onSet(this.setOn.bind(this))
.onGet(this.getOn.bind(this));

const batteryLevelService: Service = this.accessory.getService(`${displayName} Battery Level`) ||
this.accessory.addService(this.platform.Service.Battery, `${displayName} Battery Level`);

const updateBatteryLevel = () => {
if (!this.connected()) {
return;
}
try {
batteryLevelService.updateCharacteristic(this.platform.Characteristic.BatteryLevel, this.platform.robovac.batteryLevel());
} catch (error: unknown) {
this.platform.log.error(error as string);
}
};

this.platform.robovac.on('tuya.data', updateBatteryLevel);

this.platform.robovac.on('event', (event: RobovacEvent) => {
if (event.command === 'battery') {
updateBatteryLevel();
}
});

this.on = false;
}

connected(): boolean {
if (!this.platform.connected) {
this.platform.log.warn('not connected');
}
return this.platform.connected;
}

async setOn(value: CharacteristicValue) {
if (!this.connected()) {
return;
}
try {
const on: boolean = value as boolean;
if (on) {
const rooms = this.accessory.context.rooms;
console.log('about to clean', rooms);
await this.platform.robovac.cleanRooms(rooms);
} else {
await this.platform.robovac.pause();
await sleep(3000);
await this.platform.robovac.goHome(true);
}
} catch (error: unknown) {
this.platform.log.error(error as string);
}
}

async getOn(): Promise<CharacteristicValue> {
if (!this.connected()) {
return false;
}
try {
if (this.platform.robovac.goingHome() || this.platform.robovac.docked()) {
this.on = false;
return false;
}
return this.on;
} catch (error: unknown) {
this.platform.log.error(error as string);
return false;
}
}
}
22 changes: 22 additions & 0 deletions src/platform.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,19 @@
import type { API, Characteristic, DynamicPlatformPlugin, Logging, PlatformAccessory, PlatformConfig, Service } from 'homebridge';

import { DefaultPlatformAccessory } from './defaultAccessory.js';
import { CleanRoomsPlatformAccessory } from './cleanRoomsAccessory.js';
import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';

import { createRequire } from 'module';
const require = createRequire(import.meta.url);

const { RoboVac } = require('@george.talusan/eufy-robovac-js');

interface RoomSwitch {
name: string;
rooms: string;
};

export class EufyRobovacHomebridgePlatform implements DynamicPlatformPlugin {
public readonly Service: typeof Service;
public readonly Characteristic: typeof Characteristic;
Expand Down Expand Up @@ -82,6 +88,22 @@ export class EufyRobovacHomebridgePlatform implements DynamicPlatformPlugin {
},
];

const roomSwitches = this.config.roomSwitches;
roomSwitches.forEach((roomSwitch: RoomSwitch) => {
accessories.push({
displayName: () => {
return `${roomSwitch.name}`;
},
uuid: () => {
return this.api.hap.uuid.generate(`${this.config.name}-${this.config.ip}-${roomSwitch.name}-${roomSwitch.rooms}`);
},
make: (accessory: PlatformAccessory) => {
accessory.context.rooms = roomSwitch.rooms.split(',').map(Number);
new CleanRoomsPlatformAccessory(this, accessory);
},
});
});

// loop over the discovered devices and register each one if it has not already been registered
for (const a of accessories) {
const uuid = a.uuid();
Expand Down

0 comments on commit c0d16bc

Please sign in to comment.