@say4n/homebridge-tapo-smart-light 1.0.2 → 1.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,9 @@
1
+ {
2
+ "permissions": {
3
+ "allow": [
4
+ "Bash(npm run build:*)",
5
+ "Bash(npm install:*)",
6
+ "Bash(npm run lint)"
7
+ ]
8
+ }
9
+ }
@@ -1,4 +1,4 @@
1
- import { cloudLogin } from 'tp-link-tapo-connect';
1
+ import { cloudLogin } from './tapo-client/index.js';
2
2
  import { TapoPlatformAccessory } from './TapoPlatformAccessory.js';
3
3
  import { PLATFORM_NAME, PLUGIN_NAME } from './settings.js';
4
4
  export class TapoHomebridgePlatform {
@@ -1 +1 @@
1
- {"version":3,"file":"TapoHomebridgePlatform.js","sourceRoot":"","sources":["../src/TapoHomebridgePlatform.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TapoHomebridgePlatform.js","sourceRoot":"","sources":["../src/TapoHomebridgePlatform.ts"],"names":[],"mappings":"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"}
@@ -6,8 +6,13 @@ export declare class TapoPlatformAccessory {
6
6
  private service;
7
7
  private tapoDevice;
8
8
  private loginPromise;
9
+ private pendingUpdates;
10
+ private updateTimeout;
11
+ private readonly debounceMs;
9
12
  constructor(platform: TapoHomebridgePlatform, accessory: PlatformAccessory);
10
13
  getTapoDevice(): Promise<any>;
14
+ private scheduleUpdate;
15
+ private applyPendingUpdates;
11
16
  setOn(value: CharacteristicValue): Promise<void>;
12
17
  getOn(): Promise<CharacteristicValue>;
13
18
  setBrightness(value: CharacteristicValue): Promise<void>;
@@ -1,4 +1,4 @@
1
- import { loginDevice } from 'tp-link-tapo-connect';
1
+ import { loginDevice } from './tapo-client/index.js';
2
2
  export class TapoPlatformAccessory {
3
3
  platform;
4
4
  accessory;
@@ -7,6 +7,10 @@ export class TapoPlatformAccessory {
7
7
  tapoDevice;
8
8
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
9
9
  loginPromise = null;
10
+ // Debouncing state
11
+ pendingUpdates = {};
12
+ updateTimeout = null;
13
+ debounceMs = 300; // 300ms debounce
10
14
  constructor(platform, accessory) {
11
15
  this.platform = platform;
12
16
  this.accessory = accessory;
@@ -46,21 +50,54 @@ export class TapoPlatformAccessory {
46
50
  });
47
51
  return this.loginPromise;
48
52
  }
49
- async setOn(value) {
53
+ scheduleUpdate() {
54
+ // Clear existing timeout
55
+ if (this.updateTimeout) {
56
+ clearTimeout(this.updateTimeout);
57
+ }
58
+ // Schedule new update
59
+ this.updateTimeout = setTimeout(() => {
60
+ this.applyPendingUpdates();
61
+ }, this.debounceMs);
62
+ }
63
+ async applyPendingUpdates() {
64
+ const updates = { ...this.pendingUpdates };
65
+ this.pendingUpdates = {};
66
+ this.updateTimeout = null;
67
+ if (Object.keys(updates).length === 0) {
68
+ return;
69
+ }
50
70
  try {
51
71
  const device = await this.getTapoDevice();
52
- if (value) {
53
- await device.turnOn();
72
+ // Handle on/off state first if present
73
+ if (updates.on !== undefined) {
74
+ if (updates.on) {
75
+ await device.turnOn();
76
+ this.platform.log.debug('Set device On');
77
+ }
78
+ else {
79
+ await device.turnOff();
80
+ this.platform.log.debug('Set device Off');
81
+ return; // If turning off, skip other updates
82
+ }
54
83
  }
55
- else {
56
- await device.turnOff();
84
+ // Handle color/brightness updates together
85
+ if (updates.hue !== undefined || updates.saturation !== undefined || updates.brightness !== undefined) {
86
+ const hue = updates.hue ?? this.service.getCharacteristic(this.platform.Characteristic.Hue).value;
87
+ const saturation = updates.saturation ?? this.service.getCharacteristic(this.platform.Characteristic.Saturation).value;
88
+ const brightness = updates.brightness ?? this.service.getCharacteristic(this.platform.Characteristic.Brightness).value;
89
+ await device.setHSL(hue, saturation, brightness);
90
+ this.platform.log.debug('Set HSL ->', { hue, saturation, brightness });
57
91
  }
58
- this.platform.log.debug('Set Characteristic On ->', value);
59
92
  }
60
93
  catch (error) {
61
- this.platform.log.error('Failed to set On characteristic:', error);
94
+ this.platform.log.error('Failed to apply pending updates:', error);
62
95
  }
63
96
  }
97
+ async setOn(value) {
98
+ this.pendingUpdates.on = value;
99
+ this.scheduleUpdate();
100
+ }
64
101
  async getOn() {
65
102
  try {
66
103
  const device = await this.getTapoDevice();
@@ -75,39 +112,17 @@ export class TapoPlatformAccessory {
75
112
  }
76
113
  }
77
114
  async setBrightness(value) {
78
- try {
79
- const device = await this.getTapoDevice();
80
- const brightnessLevel = typeof value === 'number' ? Math.max(0, Math.min(100, value)) : 100;
81
- await device.setBrightness(brightnessLevel);
82
- this.platform.log.debug('Set Characteristic Brightness -> ', brightnessLevel);
83
- }
84
- catch (error) {
85
- this.platform.log.error('Failed to set Brightness characteristic:', error);
86
- }
115
+ const brightnessLevel = typeof value === 'number' ? Math.max(0, Math.min(100, value)) : 100;
116
+ this.pendingUpdates.brightness = brightnessLevel;
117
+ this.scheduleUpdate();
87
118
  }
88
119
  async setHue(value) {
89
- try {
90
- const device = await this.getTapoDevice();
91
- const saturation = this.service.getCharacteristic(this.platform.Characteristic.Saturation).value;
92
- const brightness = this.service.getCharacteristic(this.platform.Characteristic.Brightness).value;
93
- await device.setHSL(value, saturation, brightness);
94
- this.platform.log.debug('Set Characteristic Hue -> ', value);
95
- }
96
- catch (error) {
97
- this.platform.log.error('Failed to set Hue characteristic:', error);
98
- }
120
+ this.pendingUpdates.hue = value;
121
+ this.scheduleUpdate();
99
122
  }
100
123
  async setSaturation(value) {
101
- try {
102
- const device = await this.getTapoDevice();
103
- const hue = this.service.getCharacteristic(this.platform.Characteristic.Hue).value;
104
- const brightness = this.service.getCharacteristic(this.platform.Characteristic.Brightness).value;
105
- await device.setHSL(hue, value, brightness);
106
- this.platform.log.debug('Set Characteristic Saturation -> ', value);
107
- }
108
- catch (error) {
109
- this.platform.log.error('Failed to set Saturation characteristic:', error);
110
- }
124
+ this.pendingUpdates.saturation = value;
125
+ this.scheduleUpdate();
111
126
  }
112
127
  }
113
128
  //# sourceMappingURL=TapoPlatformAccessory.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TapoPlatformAccessory.js","sourceRoot":"","sources":["../src/TapoPlatformAccessory.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"TapoPlatformAccessory.js","sourceRoot":"","sources":["../src/TapoPlatformAccessory.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { TapoDevice } from './types.js';
2
+ export declare function cloudLogin(email: string, password: string): Promise<{
3
+ listDevices: () => Promise<TapoDevice[]>;
4
+ listDevicesByType: (deviceType: string) => Promise<TapoDevice[]>;
5
+ }>;
@@ -0,0 +1,43 @@
1
+ import axios from 'axios';
2
+ import { v4 as uuidv4 } from 'uuid';
3
+ const BASE_URL = 'https://eu-wap.tplinkcloud.com/';
4
+ function checkError(response) {
5
+ if (response.error_code !== 0) {
6
+ throw new Error(`Tapo Cloud API error ${response.error_code}: ${response.msg || 'Unknown error'}`);
7
+ }
8
+ }
9
+ export async function cloudLogin(email, password) {
10
+ const loginRequest = {
11
+ method: 'login',
12
+ params: {
13
+ appType: 'Tapo_Ios',
14
+ cloudPassword: password,
15
+ cloudUserName: email,
16
+ terminalUUID: uuidv4(),
17
+ },
18
+ };
19
+ const response = await axios.post(BASE_URL, loginRequest);
20
+ checkError(response.data);
21
+ const cloudToken = response.data.result.token;
22
+ const listDevices = async () => {
23
+ const getDeviceRequest = {
24
+ method: 'getDeviceList',
25
+ };
26
+ const deviceResponse = await axios.post(BASE_URL, getDeviceRequest, {
27
+ params: {
28
+ token: cloudToken,
29
+ },
30
+ });
31
+ checkError(deviceResponse.data);
32
+ return deviceResponse.data.result.deviceList;
33
+ };
34
+ const listDevicesByType = async (deviceType) => {
35
+ const devices = await listDevices();
36
+ return devices.filter((d) => d.deviceType === deviceType);
37
+ };
38
+ return {
39
+ listDevices,
40
+ listDevicesByType,
41
+ };
42
+ }
43
+ //# sourceMappingURL=cloud-api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cloud-api.js","sourceRoot":"","sources":["../../src/tapo-client/cloud-api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAC1B,OAAO,EAAE,EAAE,IAAI,MAAM,EAAE,MAAM,MAAM,CAAC;AAGpC,MAAM,QAAQ,GAAG,iCAAiC,CAAC;AAgBnD,SAAS,UAAU,CAAC,QAA8C;IAChE,IAAI,QAAQ,CAAC,UAAU,KAAK,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,UAAU,KAAK,QAAQ,CAAC,GAAG,IAAI,eAAe,EAAE,CAAC,CAAC;IACrG,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,KAAa,EAAE,QAAgB;IAC9D,MAAM,YAAY,GAAG;QACnB,MAAM,EAAE,OAAO;QACf,MAAM,EAAE;YACN,OAAO,EAAE,UAAU;YACnB,aAAa,EAAE,QAAQ;YACvB,aAAa,EAAE,KAAK;YACpB,YAAY,EAAE,MAAM,EAAE;SACvB;KACF,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,IAAI,CAAqB,QAAQ,EAAE,YAAY,CAAC,CAAC;IAC9E,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;IAE1B,MAAM,UAAU,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC;IAE9C,MAAM,WAAW,GAAG,KAAK,IAA2B,EAAE;QACpD,MAAM,gBAAgB,GAAG;YACvB,MAAM,EAAE,eAAe;SACxB,CAAC;QAEF,MAAM,cAAc,GAAG,MAAM,KAAK,CAAC,IAAI,CACrC,QAAQ,EACR,gBAAgB,EAChB;YACE,MAAM,EAAE;gBACN,KAAK,EAAE,UAAU;aAClB;SACF,CACF,CAAC;QAEF,UAAU,CAAC,cAAc,CAAC,IAAI,CAAC,CAAC;QAChC,OAAO,cAAc,CAAC,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC;IAC/C,CAAC,CAAC;IAEF,MAAM,iBAAiB,GAAG,KAAK,EAAE,UAAkB,EAAyB,EAAE;QAC5E,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;QACpC,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC,CAAC;IAC5D,CAAC,CAAC;IAEF,OAAO;QACL,WAAW;QACX,iBAAiB;KAClB,CAAC;AACJ,CAAC"}
@@ -0,0 +1,19 @@
1
+ import type { TapoDevice, TapoDeviceClient } from './types.js';
2
+ export type { TapoDevice, TapoDeviceInfo, TapoDeviceClient } from './types.js';
3
+ export { cloudLogin } from './cloud-api.js';
4
+ /**
5
+ * Login to a Tapo device and return a client interface
6
+ * @param email - Tapo account email
7
+ * @param password - Tapo account password
8
+ * @param device - Device information including MAC address
9
+ * @returns TapoDeviceClient interface for controlling the device
10
+ */
11
+ export declare function loginDevice(email: string, password: string, device: TapoDevice): Promise<TapoDeviceClient>;
12
+ /**
13
+ * Login to a Tapo device by IP address
14
+ * @param email - Tapo account email
15
+ * @param password - Tapo account password
16
+ * @param deviceIp - Device IP address
17
+ * @returns TapoDeviceClient interface for controlling the device
18
+ */
19
+ export declare function loginDeviceByIp(email: string, password: string, deviceIp: string): Promise<TapoDeviceClient>;
@@ -0,0 +1,33 @@
1
+ import { createKlapClient } from './klap-protocol.js';
2
+ import { resolveMacToIp } from './network-utils.js';
3
+ export { cloudLogin } from './cloud-api.js';
4
+ /**
5
+ * Login to a Tapo device and return a client interface
6
+ * @param email - Tapo account email
7
+ * @param password - Tapo account password
8
+ * @param device - Device information including MAC address
9
+ * @returns TapoDeviceClient interface for controlling the device
10
+ */
11
+ export async function loginDevice(email, password, device) {
12
+ // If device already has IP, use it directly
13
+ if (device.deviceIp) {
14
+ return createKlapClient(email, password, device.deviceIp);
15
+ }
16
+ // Otherwise, resolve MAC to IP
17
+ const localIp = await resolveMacToIp(device.deviceMac);
18
+ if (!localIp) {
19
+ throw new Error(`Local IP of device with MAC address ${device.deviceMac} not found. Make sure the device is on the same network.`);
20
+ }
21
+ return createKlapClient(email, password, localIp);
22
+ }
23
+ /**
24
+ * Login to a Tapo device by IP address
25
+ * @param email - Tapo account email
26
+ * @param password - Tapo account password
27
+ * @param deviceIp - Device IP address
28
+ * @returns TapoDeviceClient interface for controlling the device
29
+ */
30
+ export async function loginDeviceByIp(email, password, deviceIp) {
31
+ return createKlapClient(email, password, deviceIp);
32
+ }
33
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tapo-client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAIpD,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAE5C;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,KAAa,EACb,QAAgB,EAChB,MAAkB;IAElB,4CAA4C;IAC5C,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,OAAO,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC;IAC5D,CAAC;IAED,+BAA+B;IAC/B,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IAEvD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,uCAAuC,MAAM,CAAC,SAAS,0DAA0D,CAAC,CAAC;IACrI,CAAC;IAED,OAAO,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,CAAC,CAAC;AACpD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,KAAa,EACb,QAAgB,EAChB,QAAgB;IAEhB,OAAO,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC;AACrD,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { TapoDeviceClient } from './types.js';
2
+ export declare function createKlapClient(email: string, password: string, deviceIp: string): Promise<TapoDeviceClient>;
@@ -0,0 +1,163 @@
1
+ import axios from 'axios';
2
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'crypto';
3
+ const AES_CIPHER_ALGORITHM = 'aes-128-cbc';
4
+ function sha256(data) {
5
+ return createHash('sha256').update(data).digest();
6
+ }
7
+ function sha1(data) {
8
+ return createHash('sha1').update(data).digest();
9
+ }
10
+ function encode(text) {
11
+ return Buffer.from(text, 'utf-8');
12
+ }
13
+ function generateAuthHash(email, password) {
14
+ return sha256(Buffer.concat([sha1(encode(email)), sha1(encode(password))]));
15
+ }
16
+ function handshake1AuthHash(localSeed, remoteSeed, authHash) {
17
+ return sha256(Buffer.concat([localSeed, remoteSeed, authHash]));
18
+ }
19
+ function handshake2AuthHash(localSeed, remoteSeed, authHash) {
20
+ return sha256(Buffer.concat([remoteSeed, localSeed, authHash]));
21
+ }
22
+ function deriveKey(localSeed, remoteSeed, userHash) {
23
+ return sha256(Buffer.concat([encode('lsk'), localSeed, remoteSeed, userHash])).slice(0, 16);
24
+ }
25
+ function deriveIv(localSeed, remoteSeed, userHash) {
26
+ return sha256(Buffer.concat([encode('iv'), localSeed, remoteSeed, userHash]));
27
+ }
28
+ function deriveSig(localSeed, remoteSeed, userHash) {
29
+ return sha256(Buffer.concat([encode('ldk'), localSeed, remoteSeed, userHash])).slice(0, 28);
30
+ }
31
+ function deriveSeqFromIv(iv) {
32
+ return iv.slice(iv.length - 4);
33
+ }
34
+ function ivWithSeq(iv, seq) {
35
+ return Buffer.concat([iv.slice(0, 12), seq]);
36
+ }
37
+ function incrementSeq(seq) {
38
+ const buffer = Buffer.alloc(4);
39
+ buffer.writeInt32BE(seq.readInt32BE() + 1);
40
+ return buffer;
41
+ }
42
+ export async function createKlapClient(email, password, deviceIp) {
43
+ // Handshake 1
44
+ const localSeed = randomBytes(16);
45
+ const handshake1Response = await axios.post(`http://${deviceIp}/app/handshake1`, localSeed, {
46
+ responseType: 'arraybuffer',
47
+ withCredentials: true,
48
+ timeout: 10000,
49
+ });
50
+ const responseBytes = Buffer.from(handshake1Response.data);
51
+ const setCookieHeader = handshake1Response.headers['set-cookie']?.[0];
52
+ if (!setCookieHeader) {
53
+ throw new Error('No session cookie received from device');
54
+ }
55
+ const sessionCookie = setCookieHeader.substring(0, setCookieHeader.indexOf(';'));
56
+ const remoteSeed = responseBytes.slice(0, 16);
57
+ const serverHash = responseBytes.slice(16);
58
+ const localAuthHash = generateAuthHash(email, password);
59
+ const localSeedAuthHash = handshake1AuthHash(localSeed, remoteSeed, localAuthHash);
60
+ if (localSeedAuthHash.compare(serverHash) !== 0) {
61
+ throw new Error('Authentication failed: email or password incorrect');
62
+ }
63
+ // Handshake 2
64
+ const payload = handshake2AuthHash(localSeed, remoteSeed, localAuthHash);
65
+ await axios.post(`http://${deviceIp}/app/handshake2`, payload, {
66
+ responseType: 'arraybuffer',
67
+ headers: {
68
+ Cookie: sessionCookie,
69
+ },
70
+ timeout: 10000,
71
+ });
72
+ // Create encryption session
73
+ const key = deriveKey(localSeed, remoteSeed, localAuthHash);
74
+ const iv = deriveIv(localSeed, remoteSeed, localAuthHash);
75
+ const sig = deriveSig(localSeed, remoteSeed, localAuthHash);
76
+ let seq = deriveSeqFromIv(iv);
77
+ const encrypt = (payload) => {
78
+ const payloadJson = JSON.stringify(payload);
79
+ const cipher = createCipheriv(AES_CIPHER_ALGORITHM, key, ivWithSeq(iv, seq));
80
+ const ciphertext = cipher.update(encode(payloadJson));
81
+ return Buffer.concat([ciphertext, cipher.final()]);
82
+ };
83
+ const decrypt = (payload) => {
84
+ const cipher = createDecipheriv(AES_CIPHER_ALGORITHM, key, ivWithSeq(iv, seq));
85
+ const ciphertext = cipher.update(payload.slice(32));
86
+ return JSON.parse(Buffer.concat([ciphertext, cipher.final()]).toString());
87
+ };
88
+ const encryptAndSign = (payload) => {
89
+ const ciphertext = encrypt(payload);
90
+ const signature = sha256(Buffer.concat([sig, seq, ciphertext]));
91
+ return Buffer.concat([signature, ciphertext]);
92
+ };
93
+ const send = async (deviceRequest) => {
94
+ seq = incrementSeq(seq);
95
+ const encryptedRequest = encryptAndSign(deviceRequest);
96
+ const response = await axios({
97
+ method: 'post',
98
+ url: `http://${deviceIp}/app/request`,
99
+ data: encryptedRequest,
100
+ responseType: 'arraybuffer',
101
+ headers: {
102
+ Cookie: sessionCookie,
103
+ },
104
+ params: {
105
+ seq: seq.readInt32BE(),
106
+ },
107
+ timeout: 10000,
108
+ });
109
+ const decryptedResponse = decrypt(response.data);
110
+ if (decryptedResponse.error_code && decryptedResponse.error_code !== 0) {
111
+ throw new Error(`Device error: ${decryptedResponse.error_code}`);
112
+ }
113
+ return decryptedResponse.result;
114
+ };
115
+ // Return device client interface
116
+ return {
117
+ async turnOn() {
118
+ await send({
119
+ method: 'set_device_info',
120
+ params: {
121
+ device_on: true,
122
+ },
123
+ });
124
+ },
125
+ async turnOff() {
126
+ await send({
127
+ method: 'set_device_info',
128
+ params: {
129
+ device_on: false,
130
+ },
131
+ });
132
+ },
133
+ async setBrightness(level) {
134
+ const normalizedLevel = Math.max(0, Math.min(100, level));
135
+ await send({
136
+ method: 'set_device_info',
137
+ params: {
138
+ brightness: normalizedLevel,
139
+ },
140
+ });
141
+ },
142
+ async setHSL(hue, saturation, brightness) {
143
+ const normalizedHue = hue % 360;
144
+ const normalizedSat = Math.max(0, Math.min(100, saturation));
145
+ const normalizedBrightness = Math.max(0, Math.min(100, brightness));
146
+ await send({
147
+ method: 'set_device_info',
148
+ params: {
149
+ hue: normalizedHue,
150
+ saturation: normalizedSat,
151
+ brightness: normalizedBrightness,
152
+ },
153
+ });
154
+ },
155
+ async getDeviceInfo() {
156
+ const result = (await send({
157
+ method: 'get_device_info',
158
+ }));
159
+ return result;
160
+ },
161
+ };
162
+ }
163
+ //# sourceMappingURL=klap-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"klap-protocol.js","sourceRoot":"","sources":["../../src/tapo-client/klap-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function resolveMacToIp(macAddress: string): Promise<string | null>;
@@ -0,0 +1,28 @@
1
+ import { exec } from 'child_process';
2
+ import { promisify } from 'util';
3
+ const execAsync = promisify(exec);
4
+ export async function resolveMacToIp(macAddress) {
5
+ try {
6
+ // Normalize MAC address format
7
+ const normalizedMac = macAddress.toLowerCase().replace(/[:-]/g, '');
8
+ // Try arp -a command (works on macOS and Linux)
9
+ const { stdout } = await execAsync('arp -a');
10
+ const lines = stdout.split('\n');
11
+ for (const line of lines) {
12
+ const lineMac = line.toLowerCase().replace(/[:-]/g, '');
13
+ if (lineMac.includes(normalizedMac)) {
14
+ // Extract IP address - format is typically: hostname (192.168.1.x) at mac [ether] on interface
15
+ const ipMatch = line.match(/\(([0-9.]+)\)/);
16
+ if (ipMatch && ipMatch[1]) {
17
+ return ipMatch[1];
18
+ }
19
+ }
20
+ }
21
+ return null;
22
+ }
23
+ catch (error) {
24
+ console.error('Failed to resolve MAC to IP:', error);
25
+ return null;
26
+ }
27
+ }
28
+ //# sourceMappingURL=network-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network-utils.js","sourceRoot":"","sources":["../../src/tapo-client/network-utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AACrC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AAEjC,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;AAElC,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAkB;IACrD,IAAI,CAAC;QACH,+BAA+B;QAC/B,MAAM,aAAa,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAEpE,gDAAgD;QAChD,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAEjC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,MAAM,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;YACxD,IAAI,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;gBACpC,+FAA+F;gBAC/F,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAC,CAAC;gBAC5C,IAAI,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;oBAC1B,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,8BAA8B,EAAE,KAAK,CAAC,CAAC;QACrD,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,25 @@
1
+ export interface TapoDevice {
2
+ deviceType: string;
3
+ deviceModel: string;
4
+ deviceId: string;
5
+ deviceMac: string;
6
+ alias: string;
7
+ deviceIp?: string;
8
+ }
9
+ export interface TapoDeviceInfo {
10
+ device_id: string;
11
+ device_on: boolean;
12
+ brightness?: number;
13
+ hue?: number;
14
+ saturation?: number;
15
+ color_temp?: number;
16
+ nickname?: string;
17
+ ssid?: string;
18
+ }
19
+ export interface TapoDeviceClient {
20
+ turnOn(): Promise<void>;
21
+ turnOff(): Promise<void>;
22
+ setBrightness(level: number): Promise<void>;
23
+ setHSL(hue: number, saturation: number, brightness: number): Promise<void>;
24
+ getDeviceInfo(): Promise<TapoDeviceInfo>;
25
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/tapo-client/types.ts"],"names":[],"mappings":""}
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@say4n/homebridge-tapo-smart-light",
3
3
  "displayName": "Homebridge Tapo L630",
4
4
  "type": "module",
5
- "version": "1.0.2",
5
+ "version": "1.0.4",
6
6
  "description": "A Homebridge plugin for Tapo L630 smart lights.",
7
7
  "author": "say4n",
8
8
  "license": "Apache-2.0",
@@ -30,8 +30,9 @@
30
30
  "watch": "npm run build && npm link && nodemon"
31
31
  },
32
32
  "dependencies": {
33
+ "axios": "^1.7.9",
33
34
  "homebridge-lib": "^7.1.12",
34
- "tp-link-tapo-connect": "^2.0.8"
35
+ "uuid": "^11.0.5"
35
36
  },
36
37
  "devDependencies": {
37
38
  "@eslint/js": "^9.39.1",