homebridge-cync-app 0.0.2 → 0.1.0
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.
- package/CHANGELOG.md +9 -0
- package/README.md +7 -4
- package/dist/cync/config-client.d.ts +6 -0
- package/dist/cync/config-client.js +38 -0
- package/dist/cync/config-client.js.map +1 -1
- package/dist/cync/cync-client.d.ts +16 -11
- package/dist/cync/cync-client.js +175 -23
- package/dist/cync/cync-client.js.map +1 -1
- package/dist/cync/tcp-client.d.ts +45 -8
- package/dist/cync/tcp-client.js +359 -17
- package/dist/cync/tcp-client.js.map +1 -1
- package/dist/cync/token-store.d.ts +2 -0
- package/dist/cync/token-store.js.map +1 -1
- package/dist/platform.d.ts +5 -2
- package/dist/platform.js +103 -36
- package/dist/platform.js.map +1 -1
- package/docs/cync-api-notes.md +121 -7
- package/package.json +1 -1
- package/src/cync/config-client.ts +55 -0
- package/src/cync/cync-client.ts +221 -35
- package/src/cync/tcp-client.ts +488 -21
- package/src/cync/token-store.ts +3 -1
- package/src/platform.ts +176 -50
- package/homebridge-cync-app-v0.0.1.zip +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.1.0 – LAN Control Preview
|
|
4
|
+
|
|
5
|
+
- Implemented TCP client for Cync LAN bridge using the cloud-provided login code.
|
|
6
|
+
- Added real on/off control for Cync smart plugs directly from HomeKit.
|
|
7
|
+
- Wired HomeKit `On` characteristic handlers to TCP transport.
|
|
8
|
+
- Subscribed to Cync device updates and propagate state changes back into HomeKit.
|
|
9
|
+
- Improved logging around cloud configuration loading, LAN login, and TCP connection lifecycle.
|
|
10
|
+
- Known scope: tested only with Cync smart plugs; other device types are currently untested and may not appear or function correctly.
|
|
11
|
+
|
|
3
12
|
## v0.0.2 – Cloud 2FA + device discovery
|
|
4
13
|
|
|
5
14
|
**Release Date:** 2025-11-23
|
package/README.md
CHANGED
|
@@ -8,6 +8,8 @@ It currently supports:
|
|
|
8
8
|
- Discovery of Cync “meshes” and devices from the cloud
|
|
9
9
|
- Exposing Cync outlets as HomeKit switches with their Cync `displayName`
|
|
10
10
|
|
|
11
|
+
> Status: **Early LAN preview.** Tested with Cync smart plugs only. Other device types may not appear or may behave incorrectly.
|
|
12
|
+
|
|
11
13
|
## Installation
|
|
12
14
|
|
|
13
15
|
1. Install via Homebridge UI (Plugins tab) or from the command line:
|
|
@@ -61,7 +63,8 @@ Add a platform entry to your Homebridge `config.json`:
|
|
|
61
63
|
- ✅ 2FA cloud login and token persistence
|
|
62
64
|
- ✅ Cloud discovery of meshes and outlets
|
|
63
65
|
- ✅ Basic HomeKit switch accessories with real Cync names
|
|
64
|
-
- **0.0
|
|
65
|
-
-
|
|
66
|
-
-
|
|
67
|
-
-
|
|
66
|
+
- **0.1.0** – Individual accessories for plugs; per-device control. Switches, sensors and lights have not yet been tested and may not work.
|
|
67
|
+
- HomeKit can now control Cync smart plugs directly over the Cync LAN bridge.
|
|
68
|
+
- Switch states update independently and stay in sync between the Cync app and HomeKit.
|
|
69
|
+
- Cloud config is still used for login + topology, but ongoing control is via TCP.
|
|
70
|
+
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export interface CyncLoginSession {
|
|
2
2
|
accessToken: string;
|
|
3
3
|
userId: string;
|
|
4
|
+
authorize?: string;
|
|
4
5
|
raw: unknown;
|
|
5
6
|
}
|
|
6
7
|
export interface CyncDevice {
|
|
@@ -10,6 +11,9 @@ export interface CyncDevice {
|
|
|
10
11
|
device_id?: string;
|
|
11
12
|
mac?: string;
|
|
12
13
|
sn?: string;
|
|
14
|
+
switch_id?: string;
|
|
15
|
+
switch_controller?: number | string;
|
|
16
|
+
mesh_id?: number | string;
|
|
13
17
|
[key: string]: unknown;
|
|
14
18
|
}
|
|
15
19
|
export interface CyncDeviceMesh {
|
|
@@ -39,6 +43,7 @@ export declare class ConfigClient {
|
|
|
39
43
|
private readonly log;
|
|
40
44
|
private accessToken;
|
|
41
45
|
private userId;
|
|
46
|
+
private authorize;
|
|
42
47
|
constructor(logger?: CyncLogger);
|
|
43
48
|
/**
|
|
44
49
|
* Request that Cync send a one-time 2FA verification code to the given email.
|
|
@@ -73,5 +78,6 @@ export declare class ConfigClient {
|
|
|
73
78
|
userId: string | null;
|
|
74
79
|
};
|
|
75
80
|
private ensureSession;
|
|
81
|
+
static buildLanLoginCode(userId: string, authorize: string): Uint8Array;
|
|
76
82
|
private static randomLoginResource;
|
|
77
83
|
}
|
|
@@ -17,6 +17,7 @@ export class ConfigClient {
|
|
|
17
17
|
// These are populated after a successful 2FA login.
|
|
18
18
|
accessToken = null;
|
|
19
19
|
userId = null;
|
|
20
|
+
authorize = null;
|
|
20
21
|
constructor(logger) {
|
|
21
22
|
this.log = logger ?? defaultLogger;
|
|
22
23
|
}
|
|
@@ -89,22 +90,28 @@ export class ConfigClient {
|
|
|
89
90
|
// Accept both snake_case and camelCase, and both string/number user_id.
|
|
90
91
|
const accessTokenRaw = obj.access_token ?? obj.accessToken;
|
|
91
92
|
const userIdRaw = obj.user_id ?? obj.userId;
|
|
93
|
+
const authorizeRaw = obj.authorize;
|
|
92
94
|
const accessToken = typeof accessTokenRaw === 'string' && accessTokenRaw.length > 0
|
|
93
95
|
? accessTokenRaw
|
|
94
96
|
: undefined;
|
|
95
97
|
const userId = userIdRaw !== undefined && userIdRaw !== null
|
|
96
98
|
? String(userIdRaw)
|
|
97
99
|
: undefined;
|
|
100
|
+
const authorize = typeof authorizeRaw === 'string' && authorizeRaw.length > 0
|
|
101
|
+
? authorizeRaw
|
|
102
|
+
: undefined;
|
|
98
103
|
if (!accessToken || !userId) {
|
|
99
104
|
this.log.error('Cync login missing access_token or user_id: %o', json);
|
|
100
105
|
throw new Error('Cync login response missing access_token or user_id');
|
|
101
106
|
}
|
|
102
107
|
this.accessToken = accessToken;
|
|
103
108
|
this.userId = userId;
|
|
109
|
+
this.authorize = authorize ?? null;
|
|
104
110
|
this.log.info('Cync login successful; userId=%s', userId);
|
|
105
111
|
return {
|
|
106
112
|
accessToken,
|
|
107
113
|
userId,
|
|
114
|
+
authorize,
|
|
108
115
|
raw: json,
|
|
109
116
|
};
|
|
110
117
|
}
|
|
@@ -210,6 +217,37 @@ export class ConfigClient {
|
|
|
210
217
|
throw new Error('Cync session not initialised. Call loginWithTwoFactor() first.');
|
|
211
218
|
}
|
|
212
219
|
}
|
|
220
|
+
// ### 🧩 LAN Login Blob Builder: Generates the auth_code payload used by Cync LAN TCP
|
|
221
|
+
static buildLanLoginCode(userId, authorize) {
|
|
222
|
+
const authBytes = Buffer.from(authorize, 'ascii');
|
|
223
|
+
const lengthByte = 10 + authBytes.length;
|
|
224
|
+
if (lengthByte > 0xff) {
|
|
225
|
+
throw new Error('Cync LAN authorize token too long to encode.');
|
|
226
|
+
}
|
|
227
|
+
const userIdNum = Number.parseInt(userId, 10);
|
|
228
|
+
if (!Number.isFinite(userIdNum) || userIdNum < 0) {
|
|
229
|
+
throw new Error(`Invalid Cync userId for LAN auth: ${userId}`);
|
|
230
|
+
}
|
|
231
|
+
const header = Buffer.from('13000000', 'hex');
|
|
232
|
+
const lenBuf = Buffer.alloc(1);
|
|
233
|
+
lenBuf.writeUInt8(lengthByte & 0xff, 0);
|
|
234
|
+
const cmdBuf = Buffer.from('03', 'hex');
|
|
235
|
+
const userIdBuf = Buffer.alloc(4);
|
|
236
|
+
userIdBuf.writeUInt32BE(userIdNum >>> 0, 0);
|
|
237
|
+
const authLenBuf = Buffer.alloc(2);
|
|
238
|
+
authLenBuf.writeUInt16BE(authBytes.length, 0);
|
|
239
|
+
const tail = Buffer.from('0000b4', 'hex');
|
|
240
|
+
const loginBuf = Buffer.concat([
|
|
241
|
+
header,
|
|
242
|
+
lenBuf,
|
|
243
|
+
cmdBuf,
|
|
244
|
+
userIdBuf,
|
|
245
|
+
authLenBuf,
|
|
246
|
+
authBytes,
|
|
247
|
+
tail,
|
|
248
|
+
]);
|
|
249
|
+
return new Uint8Array(loginBuf);
|
|
250
|
+
}
|
|
213
251
|
static randomLoginResource() {
|
|
214
252
|
const chars = 'abcdefghijklmnopqrstuvwxyz';
|
|
215
253
|
let out = '';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-client.js","sourceRoot":"","sources":["../../src/cync/config-client.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,2CAA2C;AAC3C,qFAAqF;AACrF,EAAE;AACF,+EAA+E;AAC/E,wEAAwE;AAExE,MAAM,aAAa,GAAG,gCAAgC,CAAC;AACvD,MAAM,OAAO,GAAG,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"config-client.js","sourceRoot":"","sources":["../../src/cync/config-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -8,12 +8,19 @@ export declare class CyncClient {
|
|
|
8
8
|
private tokenData;
|
|
9
9
|
private session;
|
|
10
10
|
private cloudConfig;
|
|
11
|
+
private homeDevices;
|
|
12
|
+
private homeControllers;
|
|
13
|
+
private switchIdToHomeId;
|
|
11
14
|
private readonly loginConfig;
|
|
15
|
+
private lanUpdateHandler;
|
|
16
|
+
onLanDeviceUpdate(handler: (update: unknown) => void): void;
|
|
17
|
+
getLanLoginCode(): Uint8Array;
|
|
12
18
|
constructor(configClient: ConfigClient, tcpClient: TcpClient, loginConfig: {
|
|
13
19
|
email: string;
|
|
14
20
|
password: string;
|
|
15
21
|
twoFactor?: string;
|
|
16
22
|
}, storagePath: string, logger?: CyncLogger);
|
|
23
|
+
private buildLanLoginCode;
|
|
17
24
|
/**
|
|
18
25
|
* Ensure we are logged in:
|
|
19
26
|
* 1) Try stored token.
|
|
@@ -56,21 +63,19 @@ export declare class CyncClient {
|
|
|
56
63
|
submitTwoFactor(email: string, password: string, code: string): Promise<CyncLoginSession>;
|
|
57
64
|
/**
|
|
58
65
|
* Fetch and cache the cloud configuration (meshes/devices) for the logged-in user.
|
|
66
|
+
* Also builds HA-style LAN topology mappings:
|
|
67
|
+
* - homeDevices[homeId][meshIndex] -> deviceId
|
|
68
|
+
* - homeControllers[homeId] -> controllerIds[]
|
|
69
|
+
* - switchIdToHomeId[controllerId] -> homeId
|
|
59
70
|
*/
|
|
60
71
|
loadConfiguration(): Promise<CyncCloudConfig>;
|
|
61
|
-
/**
|
|
62
|
-
* Start the LAN/TCP transport (stub for now).
|
|
63
|
-
*/
|
|
64
72
|
startTransport(config: CyncCloudConfig, loginCode: Uint8Array): Promise<void>;
|
|
65
|
-
stopTransport(): Promise<void>;
|
|
66
|
-
/**
|
|
67
|
-
* High-level helper for toggling a switch/plug.
|
|
68
|
-
*/
|
|
69
|
-
setSwitchState(deviceId: string, params: {
|
|
70
|
-
on: boolean;
|
|
71
|
-
[key: string]: unknown;
|
|
72
|
-
}): Promise<void>;
|
|
73
73
|
getSessionSnapshot(): CyncLoginSession | null;
|
|
74
74
|
getCloudConfigSnapshot(): CyncCloudConfig | null;
|
|
75
|
+
getLanTopology(): {
|
|
76
|
+
homeDevices: Record<string, string[]>;
|
|
77
|
+
homeControllers: Record<string, number[]>;
|
|
78
|
+
switchIdToHomeId: Record<number, string>;
|
|
79
|
+
};
|
|
75
80
|
private ensureSession;
|
|
76
81
|
}
|
package/dist/cync/cync-client.js
CHANGED
|
@@ -14,8 +14,32 @@ export class CyncClient {
|
|
|
14
14
|
// Populated after successful login.
|
|
15
15
|
session = null;
|
|
16
16
|
cloudConfig = null;
|
|
17
|
+
// ### 🧩 LAN Topology Cache: mirrors HA's home_devices / home_controllers / switchID_to_homeID
|
|
18
|
+
homeDevices = {};
|
|
19
|
+
homeControllers = {};
|
|
20
|
+
switchIdToHomeId = {};
|
|
17
21
|
// Credentials from config.json, used to drive 2FA bootstrap.
|
|
18
22
|
loginConfig;
|
|
23
|
+
// Optional LAN update hook for the platform
|
|
24
|
+
lanUpdateHandler = null;
|
|
25
|
+
// ### 🧩 LAN Update Bridge: allow platform to handle device updates
|
|
26
|
+
onLanDeviceUpdate(handler) {
|
|
27
|
+
this.lanUpdateHandler = handler;
|
|
28
|
+
}
|
|
29
|
+
// ### 🧩 LAN Auth Blob Getter: Returns the LAN login code if available
|
|
30
|
+
getLanLoginCode() {
|
|
31
|
+
if (!this.tokenData?.lanLoginCode) {
|
|
32
|
+
this.log.debug('CyncClient: getLanLoginCode() → no LAN blob in token store.');
|
|
33
|
+
return new Uint8Array();
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
return Uint8Array.from(Buffer.from(this.tokenData.lanLoginCode, 'base64'));
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
this.log.warn('CyncClient: stored LAN login code is invalid base64.');
|
|
40
|
+
return new Uint8Array();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
19
43
|
constructor(configClient, tcpClient, loginConfig, storagePath, logger) {
|
|
20
44
|
this.configClient = configClient;
|
|
21
45
|
this.tcpClient = tcpClient;
|
|
@@ -23,6 +47,27 @@ export class CyncClient {
|
|
|
23
47
|
this.loginConfig = loginConfig;
|
|
24
48
|
this.tokenStore = new CyncTokenStore(storagePath);
|
|
25
49
|
}
|
|
50
|
+
// ### 🧩 LAN Login Code Builder
|
|
51
|
+
buildLanLoginCode(authorize, userId) {
|
|
52
|
+
const authorizeBytes = Buffer.from(authorize, 'ascii');
|
|
53
|
+
const head = Buffer.from('13000000', 'hex');
|
|
54
|
+
const lengthByte = Buffer.from([10 + authorizeBytes.length]);
|
|
55
|
+
const tag = Buffer.from('03', 'hex');
|
|
56
|
+
const userIdBytes = Buffer.alloc(4);
|
|
57
|
+
userIdBytes.writeUInt32BE(userId);
|
|
58
|
+
const authLenBytes = Buffer.alloc(2);
|
|
59
|
+
authLenBytes.writeUInt16BE(authorizeBytes.length);
|
|
60
|
+
const tail = Buffer.from('0000b4', 'hex');
|
|
61
|
+
return Buffer.concat([
|
|
62
|
+
head,
|
|
63
|
+
lengthByte,
|
|
64
|
+
tag,
|
|
65
|
+
userIdBytes,
|
|
66
|
+
authLenBytes,
|
|
67
|
+
authorizeBytes,
|
|
68
|
+
tail,
|
|
69
|
+
]);
|
|
70
|
+
}
|
|
26
71
|
/**
|
|
27
72
|
* Ensure we are logged in:
|
|
28
73
|
* 1) Try stored token.
|
|
@@ -55,11 +100,25 @@ export class CyncClient {
|
|
|
55
100
|
// We have a 2FA code – complete login and persist token
|
|
56
101
|
this.log.info('Cync: completing 2FA login for %s', email);
|
|
57
102
|
const loginResult = await this.completeTwoFactorLogin(email, password, String(twoFactor).trim());
|
|
103
|
+
// Build LAN login code
|
|
104
|
+
let authorize;
|
|
105
|
+
let lanLoginCode;
|
|
106
|
+
const raw = loginResult.raw;
|
|
107
|
+
if (typeof raw.authorize === 'string') {
|
|
108
|
+
authorize = raw.authorize;
|
|
109
|
+
const lanBlob = this.buildLanLoginCode(authorize, Number(loginResult.userId));
|
|
110
|
+
lanLoginCode = Buffer.from(lanBlob).toString('base64');
|
|
111
|
+
}
|
|
112
|
+
else {
|
|
113
|
+
this.log.warn('CyncClient: login response missing "authorize"; LAN login will be disabled.');
|
|
114
|
+
}
|
|
58
115
|
const tokenData = {
|
|
59
116
|
userId: String(loginResult.userId),
|
|
60
117
|
accessToken: loginResult.accessToken,
|
|
61
118
|
refreshToken: loginResult.refreshToken,
|
|
62
119
|
expiresAt: loginResult.expiresAt ?? undefined,
|
|
120
|
+
authorize,
|
|
121
|
+
lanLoginCode,
|
|
63
122
|
};
|
|
64
123
|
await this.tokenStore.save(tokenData);
|
|
65
124
|
this.tokenData = tokenData;
|
|
@@ -80,6 +139,12 @@ export class CyncClient {
|
|
|
80
139
|
*/
|
|
81
140
|
async completeTwoFactorLogin(email, password, code) {
|
|
82
141
|
const session = await this.submitTwoFactor(email, password, code);
|
|
142
|
+
// Extract authorize field from session.raw (Cync returns it)
|
|
143
|
+
const raw = session.raw;
|
|
144
|
+
const authorize = typeof raw?.authorize === 'string' ? raw.authorize : undefined;
|
|
145
|
+
if (!authorize) {
|
|
146
|
+
throw new Error('CyncClient: missing "authorize" field from login response; LAN login cannot be generated.');
|
|
147
|
+
}
|
|
83
148
|
const s = session;
|
|
84
149
|
const access = s.accessToken ?? s.jwt;
|
|
85
150
|
if (!access) {
|
|
@@ -90,6 +155,7 @@ export class CyncClient {
|
|
|
90
155
|
accessToken: access,
|
|
91
156
|
refreshToken: s.refreshToken ?? s.refreshJwt,
|
|
92
157
|
expiresAt: s.expiresAt,
|
|
158
|
+
authorize,
|
|
93
159
|
};
|
|
94
160
|
}
|
|
95
161
|
/**
|
|
@@ -116,6 +182,14 @@ export class CyncClient {
|
|
|
116
182
|
expiresAt: tokenData.expiresAt,
|
|
117
183
|
},
|
|
118
184
|
};
|
|
185
|
+
// Restore LAN auth blob into memory
|
|
186
|
+
if (tokenData.authorize && tokenData.lanLoginCode) {
|
|
187
|
+
this.log.debug('CyncClient: LAN login code restored from token store.');
|
|
188
|
+
// nothing else needed — getLanLoginCode() will use it
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
this.log.debug('CyncClient: token store missing LAN login fields.');
|
|
192
|
+
}
|
|
119
193
|
this.log.debug('CyncClient: access token applied from %s; userId=%s, expiresAt=%s', 'tokenStore', tokenData.userId, tokenData.expiresAt ? new Date(tokenData.expiresAt).toISOString() : 'unknown');
|
|
120
194
|
}
|
|
121
195
|
/**
|
|
@@ -153,15 +227,27 @@ export class CyncClient {
|
|
|
153
227
|
}
|
|
154
228
|
/**
|
|
155
229
|
* Fetch and cache the cloud configuration (meshes/devices) for the logged-in user.
|
|
230
|
+
* Also builds HA-style LAN topology mappings:
|
|
231
|
+
* - homeDevices[homeId][meshIndex] -> deviceId
|
|
232
|
+
* - homeControllers[homeId] -> controllerIds[]
|
|
233
|
+
* - switchIdToHomeId[controllerId] -> homeId
|
|
156
234
|
*/
|
|
157
235
|
async loadConfiguration() {
|
|
158
236
|
this.ensureSession();
|
|
159
237
|
this.log.info('CyncClient: loading Cync cloud configuration…');
|
|
160
238
|
const cfg = await this.configClient.getCloudConfig();
|
|
239
|
+
// Reset LAN topology caches on each reload
|
|
240
|
+
this.homeDevices = {};
|
|
241
|
+
this.homeControllers = {};
|
|
242
|
+
this.switchIdToHomeId = {};
|
|
161
243
|
// Debug: inspect per-mesh properties so we can find the real devices.
|
|
162
244
|
for (const mesh of cfg.meshes) {
|
|
163
245
|
const meshName = mesh.name ?? mesh.id;
|
|
246
|
+
const homeId = String(mesh.id);
|
|
164
247
|
this.log.debug('CyncClient: probing properties for mesh %s (id=%s, product_id=%s)', meshName, mesh.id, mesh.product_id);
|
|
248
|
+
// Per-home maps, mirroring HA's CyncUserData.get_cync_config()
|
|
249
|
+
const homeDevices = [];
|
|
250
|
+
const homeControllers = [];
|
|
165
251
|
try {
|
|
166
252
|
const props = await this.configClient.getDeviceProperties(mesh.product_id, mesh.id);
|
|
167
253
|
this.log.debug('CyncClient: mesh %s properties keys=%o', meshName, Object.keys(props));
|
|
@@ -169,25 +255,82 @@ export class CyncClient {
|
|
|
169
255
|
if (Array.isArray(bulbsArray)) {
|
|
170
256
|
this.log.info('CyncClient: mesh %s bulbsArray length=%d; first item keys=%o', meshName, bulbsArray.length, bulbsArray[0] ? Object.keys(bulbsArray[0]) : []);
|
|
171
257
|
const rawDevices = bulbsArray;
|
|
172
|
-
|
|
258
|
+
const devicesForMesh = [];
|
|
259
|
+
for (const raw of rawDevices) {
|
|
173
260
|
const d = raw;
|
|
174
261
|
const displayName = d.displayName;
|
|
175
|
-
|
|
262
|
+
// deviceID can be number or string – normalize to string
|
|
263
|
+
const deviceIdRaw = (d.deviceID ?? d.deviceId);
|
|
264
|
+
const deviceIdStr = deviceIdRaw !== undefined && deviceIdRaw !== null
|
|
265
|
+
? String(deviceIdRaw)
|
|
266
|
+
: undefined;
|
|
176
267
|
const wifiMac = d.wifiMac;
|
|
177
268
|
const productId = d.product_id ?? mesh.product_id;
|
|
269
|
+
// Reproduce HA's mesh index calculation:
|
|
270
|
+
// current_index = ((deviceID % home_id) % 1000) + (int((deviceID % home_id) / 1000) * 256)
|
|
271
|
+
const homeIdNum = Number(mesh.id);
|
|
272
|
+
const deviceIdNum = typeof deviceIdRaw === 'number'
|
|
273
|
+
? deviceIdRaw
|
|
274
|
+
: deviceIdRaw !== undefined && deviceIdRaw !== null
|
|
275
|
+
? Number(deviceIdRaw)
|
|
276
|
+
: NaN;
|
|
277
|
+
let meshIndex;
|
|
278
|
+
if (!Number.isNaN(homeIdNum) && !Number.isNaN(deviceIdNum) && homeIdNum !== 0) {
|
|
279
|
+
const mod = deviceIdNum % homeIdNum;
|
|
280
|
+
meshIndex = (mod % 1000) + Math.floor(mod / 1000) * 256;
|
|
281
|
+
}
|
|
282
|
+
// Controller ID used by LAN packets (HA's switch_controller)
|
|
283
|
+
const switchController = d.switchID;
|
|
178
284
|
// Use deviceID first, then wifiMac (stripped), then a mesh-based fallback.
|
|
179
|
-
const id =
|
|
285
|
+
const id = deviceIdStr ??
|
|
180
286
|
(wifiMac ? wifiMac.replace(/:/g, '') : undefined) ??
|
|
181
287
|
`${mesh.id}-${productId ?? 'unknown'}`;
|
|
182
|
-
|
|
288
|
+
// Mirror HA's home_devices[homeId][meshIndex] = deviceId
|
|
289
|
+
if (meshIndex !== undefined && deviceIdStr) {
|
|
290
|
+
while (homeDevices.length <= meshIndex) {
|
|
291
|
+
homeDevices.push('');
|
|
292
|
+
}
|
|
293
|
+
homeDevices[meshIndex] = deviceIdStr;
|
|
294
|
+
}
|
|
295
|
+
// Mirror HA's switchID_to_homeID + home_controllers
|
|
296
|
+
if (switchController !== undefined && Number.isFinite(switchController) && switchController > 0) {
|
|
297
|
+
if (!this.switchIdToHomeId[switchController]) {
|
|
298
|
+
this.switchIdToHomeId[switchController] = homeId;
|
|
299
|
+
}
|
|
300
|
+
if (!homeControllers.includes(switchController)) {
|
|
301
|
+
homeControllers.push(switchController);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
devicesForMesh.push({
|
|
183
305
|
id,
|
|
184
306
|
name: displayName ?? undefined,
|
|
185
307
|
product_id: productId,
|
|
186
|
-
device_id:
|
|
308
|
+
device_id: deviceIdStr,
|
|
187
309
|
mac: wifiMac,
|
|
310
|
+
mesh_id: meshIndex,
|
|
311
|
+
switch_controller: switchController,
|
|
188
312
|
raw: d,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
// Attach per-mesh devices to the cloud config (what platform.ts already uses)
|
|
316
|
+
mesh.devices = devicesForMesh;
|
|
317
|
+
// Persist per-home topology maps for TCP parsing later
|
|
318
|
+
if (homeDevices.length > 0) {
|
|
319
|
+
this.homeDevices[homeId] = homeDevices;
|
|
320
|
+
}
|
|
321
|
+
if (homeControllers.length > 0) {
|
|
322
|
+
this.homeControllers[homeId] = homeControllers;
|
|
323
|
+
}
|
|
324
|
+
// Maintain the legacy controller→device mapping for now so existing TCP code keeps working.
|
|
325
|
+
for (const dev of devicesForMesh) {
|
|
326
|
+
const record = dev;
|
|
327
|
+
const controllerId = record.switch_controller;
|
|
328
|
+
const deviceId = record.device_id ??
|
|
329
|
+
record.id;
|
|
330
|
+
if (controllerId !== undefined && deviceId) {
|
|
331
|
+
this.tcpClient.registerSwitchMapping(controllerId, deviceId);
|
|
332
|
+
}
|
|
333
|
+
}
|
|
191
334
|
}
|
|
192
335
|
else {
|
|
193
336
|
this.log.info('CyncClient: mesh %s has no bulbsArray in properties; props keys=%o', meshName, Object.keys(props));
|
|
@@ -201,32 +344,41 @@ export class CyncClient {
|
|
|
201
344
|
this.log.info('CyncClient: cloud configuration loaded; meshes=%d', cfg.meshes.length);
|
|
202
345
|
return cfg;
|
|
203
346
|
}
|
|
204
|
-
/**
|
|
205
|
-
* Start the LAN/TCP transport (stub for now).
|
|
206
|
-
*/
|
|
207
347
|
async startTransport(config, loginCode) {
|
|
208
348
|
this.ensureSession();
|
|
209
|
-
this.log.info('CyncClient: starting TCP transport
|
|
349
|
+
this.log.info('CyncClient: starting TCP transport…');
|
|
350
|
+
// Push current LAN topology (built in loadConfiguration) into the TCP client
|
|
351
|
+
const topology = this.getLanTopology();
|
|
352
|
+
this.tcpClient.applyLanTopology(topology);
|
|
353
|
+
// Optional: dump all frames as hex for debugging
|
|
354
|
+
this.tcpClient.onRawFrame((frame) => {
|
|
355
|
+
this.log.debug('[Cync TCP] raw frame (%d bytes): %s', frame.byteLength, frame.toString('hex'));
|
|
356
|
+
});
|
|
357
|
+
// REQUIRED: subscribe to parsed device updates
|
|
358
|
+
this.tcpClient.onDeviceUpdate((update) => {
|
|
359
|
+
if (this.lanUpdateHandler) {
|
|
360
|
+
this.lanUpdateHandler(update);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
// Fallback: log only
|
|
364
|
+
this.log.info('[Cync TCP] device update callback fired; payload=%o', update);
|
|
365
|
+
}
|
|
366
|
+
});
|
|
210
367
|
await this.tcpClient.connect(loginCode, config);
|
|
211
368
|
}
|
|
212
|
-
async stopTransport() {
|
|
213
|
-
this.log.info('CyncClient: stopping TCP transport…');
|
|
214
|
-
await this.tcpClient.disconnect();
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* High-level helper for toggling a switch/plug.
|
|
218
|
-
*/
|
|
219
|
-
async setSwitchState(deviceId, params) {
|
|
220
|
-
this.ensureSession();
|
|
221
|
-
this.log.debug('CyncClient: setSwitchState stub; deviceId=%s params=%o', deviceId, params);
|
|
222
|
-
await this.tcpClient.setSwitchState(deviceId, params);
|
|
223
|
-
}
|
|
224
369
|
getSessionSnapshot() {
|
|
225
370
|
return this.session;
|
|
226
371
|
}
|
|
227
372
|
getCloudConfigSnapshot() {
|
|
228
373
|
return this.cloudConfig;
|
|
229
374
|
}
|
|
375
|
+
getLanTopology() {
|
|
376
|
+
return {
|
|
377
|
+
homeDevices: this.homeDevices,
|
|
378
|
+
homeControllers: this.homeControllers,
|
|
379
|
+
switchIdToHomeId: this.switchIdToHomeId,
|
|
380
|
+
};
|
|
381
|
+
}
|
|
230
382
|
ensureSession() {
|
|
231
383
|
if (!this.session) {
|
|
232
384
|
throw new Error('Cync session not initialised; complete 2FA login first.');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cync-client.js","sourceRoot":"","sources":["../../src/cync/cync-client.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cync-client.js","sourceRoot":"","sources":["../../src/cync/cync-client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,33 +1,70 @@
|
|
|
1
1
|
import { CyncCloudConfig, CyncLogger } from './config-client.js';
|
|
2
2
|
export type DeviceUpdateCallback = (payload: unknown) => void;
|
|
3
|
+
export type RawFrameListener = (frame: Buffer) => void;
|
|
3
4
|
export declare class TcpClient {
|
|
5
|
+
registerSwitchMapping(controllerId: number, deviceId: string): void;
|
|
6
|
+
private homeDevices;
|
|
7
|
+
private switchIdToHomeId;
|
|
4
8
|
private readonly log;
|
|
9
|
+
private loginCode;
|
|
10
|
+
private config;
|
|
11
|
+
private meshSockets;
|
|
5
12
|
private deviceUpdateCb;
|
|
6
13
|
private roomUpdateCb;
|
|
7
14
|
private motionUpdateCb;
|
|
8
15
|
private ambientUpdateCb;
|
|
16
|
+
private socket;
|
|
17
|
+
private seq;
|
|
18
|
+
private readBuffer;
|
|
19
|
+
private heartbeatTimer;
|
|
20
|
+
private rawFrameListeners;
|
|
21
|
+
private controllerToDevice;
|
|
22
|
+
private parseSwitchStateFrame;
|
|
23
|
+
private parseLanSwitchUpdate;
|
|
9
24
|
constructor(logger?: CyncLogger);
|
|
10
25
|
/**
|
|
11
26
|
* Establish a TCP session to one or more Cync devices.
|
|
12
27
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* For now this is a no-op that simply logs the request.
|
|
28
|
+
* For Homebridge:
|
|
29
|
+
* - We cache loginCode + config here.
|
|
30
|
+
* - Actual socket creation happens in ensureConnected()/establishSocket().
|
|
18
31
|
*/
|
|
19
32
|
connect(loginCode: Uint8Array, config: CyncCloudConfig): Promise<void>;
|
|
33
|
+
applyLanTopology(topology: {
|
|
34
|
+
homeDevices: Record<string, string[]>;
|
|
35
|
+
switchIdToHomeId: Record<number, string>;
|
|
36
|
+
}): void;
|
|
37
|
+
/**
|
|
38
|
+
* Ensure we have an open, logged-in socket.
|
|
39
|
+
* If the socket is closed or missing, attempt to reconnect.
|
|
40
|
+
*/
|
|
41
|
+
private ensureConnected;
|
|
42
|
+
/**
|
|
43
|
+
* Open a new socket to cm.gelighting.com and send the loginCode,
|
|
44
|
+
* mirroring the HA integration’s behavior.
|
|
45
|
+
*/
|
|
46
|
+
private establishSocket;
|
|
47
|
+
private openTlsSocket;
|
|
48
|
+
private openTcpSocket;
|
|
49
|
+
private startHeartbeat;
|
|
50
|
+
private nextSeq;
|
|
51
|
+
private buildPowerPacket;
|
|
20
52
|
disconnect(): Promise<void>;
|
|
21
53
|
onDeviceUpdate(cb: DeviceUpdateCallback): void;
|
|
22
54
|
onRoomUpdate(cb: DeviceUpdateCallback): void;
|
|
23
55
|
onMotionUpdate(cb: DeviceUpdateCallback): void;
|
|
24
56
|
onAmbientUpdate(cb: DeviceUpdateCallback): void;
|
|
57
|
+
onRawFrame(listener: RawFrameListener): void;
|
|
25
58
|
/**
|
|
26
|
-
* High-level API to change switch state.
|
|
27
|
-
*
|
|
59
|
+
* High-level API to change switch state.
|
|
60
|
+
* Ensures we have a live socket before sending.
|
|
28
61
|
*/
|
|
29
62
|
setSwitchState(deviceId: string, params: {
|
|
30
63
|
on: boolean;
|
|
31
|
-
[key: string]: unknown;
|
|
32
64
|
}): Promise<void>;
|
|
65
|
+
private findDevice;
|
|
66
|
+
private attachSocketListeners;
|
|
67
|
+
private processIncoming;
|
|
68
|
+
private sendRawCommand;
|
|
69
|
+
private handleIncomingFrame;
|
|
33
70
|
}
|