Skip to content

Commit

Permalink
refacor/code & fixes/brightness-slider (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
RaresAil authored May 22, 2022
1 parent bcf9a15 commit 9494022
Show file tree
Hide file tree
Showing 12 changed files with 549 additions and 311 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ jobs:

strategy:
matrix:
node-version: [12.x, 13.x, 14.x, 15.x, 16.x]
node-version: [14.x, 15.x, 16.x, 17.x, 18.x]

steps:
- uses: actions/checkout@v2
Expand Down
30 changes: 13 additions & 17 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"private": false,
"displayName": "TPLink Tapo",
"name": "homebridge-tp-link-tapo",
"version": "3.0.2",
"version": "3.1.0",
"description": "A platform to implement the tp-link tapo device and Adaptive Lighting for light bulbs",
"license": "Apache-2.0",
"repository": {
Expand All @@ -25,7 +25,6 @@
"dev": "nodemon src/index.ts",
"lint": "eslint src/**.ts --max-warnings=0",
"watch": "npm run build && npm link && nodemon",
"watch-fast": "nodemon",
"build": "rimraf ./dist && tsc",
"prepublishOnly": "npm run lint && npm run build"
},
Expand All @@ -44,25 +43,22 @@
"smart"
],
"dependencies": {
"async-lock": "^1.3.0",
"axios": "^0.24.0",
"uuid": "^8.3.2"
"async-lock": "^1.3.1",
"axios": "^0.27.2"
},
"resolutions": {
"follow-redirects": "^1.14.8",
"ansi-regex": "^5.0.1"
"minimist": "^1.2.6"
},
"devDependencies": {
"@types/async-lock": "^1.1.3",
"@types/node": "^17.0.8",
"@types/uuid": "^8.3.4",
"@typescript-eslint/eslint-plugin": "^5.9.1",
"@typescript-eslint/parser": "^5.9.1",
"eslint": "^8.7.0",
"homebridge": "^1.3.9",
"nodemon": "^2.0.15",
"@types/async-lock": "^1.1.5",
"@types/node": "^17.0.35",
"@typescript-eslint/eslint-plugin": "^5.25.0",
"@typescript-eslint/parser": "^5.25.0",
"eslint": "^8.16.0",
"homebridge": "^1.4.1",
"nodemon": "^2.0.16",
"rimraf": "^3.0.2",
"ts-node": "^10.4.0",
"typescript": "^4.5.4"
"ts-node": "^10.8.0",
"typescript": "^4.6.4"
}
}
40 changes: 40 additions & 0 deletions src/@types/Accessory.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { Logger, PlatformAccessory } from 'homebridge';

import DeviceInfo from '../api/@types/DeviceInfo';
import TPLink from '../api/TPLink';
import Platform from '../platform';
import Context from './Context';

export enum AccessoryType {
LightBulb = 'LightBulb',
Unknown = 'Unknown'
}

abstract class Accessory {
protected readonly tpLink: TPLink;
protected readonly model: string;
protected readonly mac: string;

public static GetType(deviceInfo: DeviceInfo): AccessoryType {
if (deviceInfo?.type?.includes('BULB')) {
return AccessoryType.LightBulb;
}

return AccessoryType.Unknown;
}

public abstract get UUID(): string;

constructor(
protected readonly platform: Platform,
protected readonly accessory: PlatformAccessory<Context>,
protected readonly log: Logger,
protected readonly deviceInfo: DeviceInfo
) {
this.tpLink = accessory.context.tpLink;
this.model = deviceInfo.model;
this.mac = deviceInfo.mac;
}
}

export default Accessory;
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Nullable
} from 'homebridge';

import { AccessoryThisType } from '../LightBulbAccessory';
import { AccessoryThisType } from '..';

const characteristic: {
get: CharacteristicGetHandler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@ import {
Nullable
} from 'homebridge';

import { AccessoryThisType } from '../LightBulbAccessory';
import { AccessoryThisType } from '..';

import {
toHomeKitValues,
toTPLinkValues,
TP_LINK_VALUES
} from '../utils/translateColorTemp';
} from '../../../utils/translateColorTemp';

const characteristic: {
get: CharacteristicGetHandler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Nullable
} from 'homebridge';

import { AccessoryThisType } from '../LightBulbAccessory';
import { AccessoryThisType } from '..';

const characteristic: {
get: CharacteristicGetHandler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Nullable
} from 'homebridge';

import { AccessoryThisType } from '../LightBulbAccessory';
import { AccessoryThisType } from '..';

const characteristic: {
get: CharacteristicGetHandler;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
Nullable
} from 'homebridge';

import { AccessoryThisType } from '../LightBulbAccessory';
import { AccessoryThisType } from '..';

const characteristic: {
get: CharacteristicGetHandler;
Expand Down
56 changes: 36 additions & 20 deletions src/LightBulbAccessory.ts → src/accessories/LightBulb/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
import { PlatformAccessory, Characteristic, Service, Logger } from 'homebridge';

import ColorTemperature from './characteristics/ColorTemperature';
import { HOME_KIT_VALUES } from './utils/translateColorTemp';
import Brightness from './characteristics/Brightness';
import Saturation from './characteristics/Saturation';
import Hue from './characteristics/Hue';
import Context from './@types/Context';
import On from './characteristics/On';
import TPLink from './api/TPLink';
import Platform from './platform';

import { HOME_KIT_VALUES } from '../../utils/translateColorTemp';
import DeviceInfo from '../../api/@types/DeviceInfo';
import Accessory from '../../@types/Accessory';
import Context from '../../@types/Context';
import TPLink from '../../api/TPLink';
import Platform from '../../platform';

export type AccessoryThisType = ThisType<{
readonly powerChar: Characteristic;
Expand All @@ -19,10 +22,9 @@ export type AccessoryThisType = ThisType<{
hue: number;
}>;

export default class LightBulbAccessory {
export default class LightBulbAccessory extends Accessory {
private readonly powerChar: Characteristic;
private readonly service: Service;
private readonly tpLink: TPLink;

private _hue?: number;
private _saturation?: number;
Expand All @@ -42,23 +44,35 @@ export default class LightBulbAccessory {
}

constructor(
private readonly platform: Platform,
private readonly accessory: PlatformAccessory<Context>,
private readonly log: Logger,
public readonly model: string,
public readonly mac: string,
public readonly hasColors: boolean
platform: Platform,
accessory: PlatformAccessory<Context>,
log: Logger,
deviceInfo: DeviceInfo
) {
this.tpLink = accessory.context.tpLink;
super(platform, accessory, log, deviceInfo);

let hasBrightness = false;
let hasColors = false;
if (
deviceInfo.color_temp !== undefined ||
deviceInfo.saturation !== undefined ||
deviceInfo.hue !== undefined
) {
hasColors = true;
}

if (deviceInfo.brightness !== undefined) {
hasBrightness = true;
}

this.accessory
.getService(this.platform.Service.AccessoryInformation)!
.setCharacteristic(
this.platform.Characteristic.Manufacturer,
'TP-Link Technologies'
)
.setCharacteristic(this.platform.Characteristic.Model, model)
.setCharacteristic(this.platform.Characteristic.SerialNumber, mac);
.setCharacteristic(this.platform.Characteristic.Model, this.model)
.setCharacteristic(this.platform.Characteristic.SerialNumber, this.mac);

this.service =
this.accessory.getService(this.platform.Service.Lightbulb) ||
Expand All @@ -69,12 +83,14 @@ export default class LightBulbAccessory {
.onGet(On.get.bind(this))
.onSet(On.set.bind(this));

this.service
.getCharacteristic(this.platform.Characteristic.Brightness)
.onGet(Brightness.get.bind(this))
.onSet(Brightness.set.bind(this));
if (hasBrightness) {
this.service
.getCharacteristic(this.platform.Characteristic.Brightness)
.onGet(Brightness.get.bind(this))
.onSet(Brightness.set.bind(this));
}

if (this.hasColors) {
if (hasColors) {
this.service
.getCharacteristic(this.platform.Characteristic.ColorTemperature)
.setProps({
Expand Down
3 changes: 1 addition & 2 deletions src/api/TPLink.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import AsyncLock from 'async-lock';
import crypto from 'crypto';
import axios from 'axios';
import { v4 } from 'uuid';

import DeviceInfo from './@types/DeviceInfo';
import TpLinkCipher from './TpLinkCipher';
Expand Down Expand Up @@ -49,7 +48,7 @@ export default class TPLink {
) {
this.email = TpLinkCipher.toBase64(TpLinkCipher.encodeUsername(this.email));
this.password = TpLinkCipher.toBase64(this.password);
this.terminalUUID = v4();
this.terminalUUID = crypto.randomUUID();
this.lock = new AsyncLock();
}

Expand Down
74 changes: 44 additions & 30 deletions src/platform.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@ import {
Characteristic
} from 'homebridge';

import LightBulbAccessory from './LightBulbAccessory';
import Accessory, { AccessoryType } from './@types/Accessory';
import LightBulbAccessory from './accessories/LightBulb';
import { PLATFORM_NAME, PLUGIN_NAME } from './settings';
import DeviceInfo from './api/@types/DeviceInfo';
import Context from './@types/Context';
import TPLink from './api/TPLink';
import delay from './utils/delay';
Expand All @@ -22,7 +24,7 @@ export default class Platform implements DynamicPlatformPlugin {
this.api.hap.Characteristic;

public readonly accessories: PlatformAccessory<Context>[] = [];
public readonly registeredDevices: LightBulbAccessory[] = [];
public readonly registeredDevices: Accessory[] = [];
private readonly deviceRetry: {
[key: string]: number;
} = {};
Expand Down Expand Up @@ -111,15 +113,6 @@ export default class Platform implements DynamicPlatformPlugin {
(accessory) => accessory.UUID === uuid
);

let hasColors = false;
if (
deviceInfo.color_temp !== undefined ||
deviceInfo.saturation !== undefined ||
deviceInfo.hue !== undefined
) {
hasColors = true;
}

if (existingAccessory) {
this.log.info(
'Restoring existing accessory from cache:',
Expand All @@ -130,16 +123,20 @@ export default class Platform implements DynamicPlatformPlugin {
tpLink
};

this.registeredDevices.push(
new LightBulbAccessory(
this,
existingAccessory,
this.log,
deviceInfo.model,
deviceInfo.mac,
hasColors
)
const registeredAccessory = this.registerAccessory(
existingAccessory,
deviceInfo
);
if (!registeredAccessory) {
this.log.error(
'Failed to register accessory "%s" of type "%s"',
deviceName,
Accessory.GetType(deviceInfo)
);
return;
}

this.registeredDevices.push(registeredAccessory);
return;
}

Expand All @@ -153,16 +150,17 @@ export default class Platform implements DynamicPlatformPlugin {
tpLink
};

this.registeredDevices.push(
new LightBulbAccessory(
this,
accessory,
this.log,
deviceInfo.model,
deviceInfo.mac,
hasColors
)
);
const registeredAccessory = this.registerAccessory(accessory, deviceInfo);
if (!registeredAccessory) {
this.log.error(
'Failed to register accessory "%s" of type "%s"',
deviceName,
Accessory.GetType(deviceInfo)
);
return;
}

this.registeredDevices.push(registeredAccessory);

return this.api.registerPlatformAccessories(PLUGIN_NAME, PLATFORM_NAME, [
accessory
Expand All @@ -188,4 +186,20 @@ export default class Platform implements DynamicPlatformPlugin {
}
});
}

private readonly accessoryClasses = {
[AccessoryType.LightBulb]: LightBulbAccessory
};

private registerAccessory(
accessory: PlatformAccessory<Context>,
deviceInfo: DeviceInfo
): Accessory | null {
const AccessoryClass = this.accessoryClasses[Accessory.GetType(deviceInfo)];
if (!AccessoryClass) {
return null;
}

return new AccessoryClass(this, accessory, this.log, deviceInfo);
}
}
Loading

0 comments on commit 9494022

Please sign in to comment.