@homebridge-plugins/homebridge-ewelink 12.6.2 → 12.7.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 +5 -0
- package/CLAUDE.md +144 -0
- package/lib/connection/lan.js +3 -0
- package/lib/utils/constants.js +11 -5
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
package/CLAUDE.md
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
### Development
|
|
8
|
+
- **Lint code**: `npm run lint`
|
|
9
|
+
- **Fix lint issues**: `npm run lint:fix`
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
### Core Structure
|
|
14
|
+
This is a Homebridge plugin that integrates eWeLink devices into HomeKit. The main entry point is `lib/index.js` which registers the platform with Homebridge.
|
|
15
|
+
|
|
16
|
+
### Key Components
|
|
17
|
+
|
|
18
|
+
**Platform Layer** (`lib/platform.js`)
|
|
19
|
+
- Main platform class that coordinates all plugin operations
|
|
20
|
+
- Manages device discovery, initialization, and lifecycle
|
|
21
|
+
- Handles configuration and storage via node-persist
|
|
22
|
+
- Implements request queue with p-queue for rate limiting
|
|
23
|
+
- Routes devices to appropriate handlers based on UIID and configuration
|
|
24
|
+
|
|
25
|
+
**Connection Layer** (`lib/connection/`)
|
|
26
|
+
- `api.js`: Internal HTTP API server for local control
|
|
27
|
+
- `http.js`: eWeLink cloud API client
|
|
28
|
+
- `lan.js`: Local network device control
|
|
29
|
+
- `ws.js`: WebSocket client for real-time updates
|
|
30
|
+
|
|
31
|
+
**Device Layer** (`lib/device/`)
|
|
32
|
+
- Individual device type implementations (switches, lights, sensors, etc.)
|
|
33
|
+
- Each device type extends base functionality with specific HomeKit characteristics
|
|
34
|
+
- Supports various Sonoff/eWeLink device models
|
|
35
|
+
- Device types include:
|
|
36
|
+
- Single/Multi switches with optional power monitoring
|
|
37
|
+
- RGB/CCT/Dimmable lights
|
|
38
|
+
- Sensors (ambient, contact, motion, water)
|
|
39
|
+
- Thermostats, fans, curtains
|
|
40
|
+
- RF Bridge devices
|
|
41
|
+
- Zigbee devices (via bridge)
|
|
42
|
+
- Groups and simulations
|
|
43
|
+
|
|
44
|
+
**Utilities** (`lib/utils/`)
|
|
45
|
+
- `constants.js`: Device configurations and UIID mappings
|
|
46
|
+
- `functions.js`: Shared utility functions
|
|
47
|
+
- `custom-chars.js`: Custom HomeKit characteristics
|
|
48
|
+
- `eve-chars.js`: Eve Home app specific characteristics
|
|
49
|
+
- Language files for internationalization
|
|
50
|
+
|
|
51
|
+
### Device Identification (UIID)
|
|
52
|
+
Every eWeLink device has a UIID (unique interface ID) that determines its capabilities:
|
|
53
|
+
|
|
54
|
+
**Key UIID Categories** (defined in `lib/utils/constants.js`):
|
|
55
|
+
- `switchSingle`: [1, 6, 14, 24, 27, etc.] - Basic on/off switches
|
|
56
|
+
- `switchSinglePower`: [5, 32] - Switches with power monitoring
|
|
57
|
+
- `switchMulti`: [2, 3, 4, 7, 8, 9, etc.] - Multi-channel switches
|
|
58
|
+
- `lightRGB`: [22] - RGB color lights
|
|
59
|
+
- `lightCCT`: [103] - Color temperature lights
|
|
60
|
+
- `lightRGBCCT`: [33, 59, 104, etc.] - Full color + temperature lights
|
|
61
|
+
- `lightDimmer`: [36, 44, 57] - Dimmable lights
|
|
62
|
+
- `sensorContact`: [102, 154] - Door/window sensors
|
|
63
|
+
- `sensorAmbient`: [15, 181] - Temperature/humidity sensors
|
|
64
|
+
- `thermostat`: [127] - Smart thermostats
|
|
65
|
+
- `rfBridge`: [28, 98] - RF 433MHz bridges
|
|
66
|
+
- `zbBridge`: [66, 128, 168] - Zigbee bridges
|
|
67
|
+
- Zigbee prefixed devices (1000-7000 range)
|
|
68
|
+
|
|
69
|
+
**Device Routing Logic** (in `lib/platform.js:initialiseDevice()`):
|
|
70
|
+
1. Checks device UIID against category arrays in constants
|
|
71
|
+
2. Considers user configuration (showAs property for simulations)
|
|
72
|
+
3. Creates appropriate device handler instance
|
|
73
|
+
4. Special handling for:
|
|
74
|
+
- Power monitoring devices (different decimal places)
|
|
75
|
+
- Multi-channel devices (individual switches/outlets)
|
|
76
|
+
- Bridge devices (RF/Zigbee sub-devices)
|
|
77
|
+
- Simulated accessories (garage doors, valves, etc.)
|
|
78
|
+
|
|
79
|
+
### Communication Flow
|
|
80
|
+
1. Plugin authenticates with eWeLink cloud to fetch device list
|
|
81
|
+
2. Attempts local (LAN) control first for supported devices
|
|
82
|
+
3. Falls back to cloud control via HTTP/WebSocket if local fails
|
|
83
|
+
4. Maintains real-time sync through WebSocket connection
|
|
84
|
+
5. Exposes optional internal API for external control
|
|
85
|
+
|
|
86
|
+
### Command & Payload Structure
|
|
87
|
+
|
|
88
|
+
**HTTP Connection** (`lib/connection/http.js`)
|
|
89
|
+
- **Login**: POST to `/v2/user/login`
|
|
90
|
+
- Request: `{email/phoneNumber, password, countryCode}`
|
|
91
|
+
- Response: Returns `at` (access token) and `apikey`
|
|
92
|
+
- Uses HMAC-SHA256 signature with app secret
|
|
93
|
+
- **Get Homes**: GET to `/v2/family`
|
|
94
|
+
- Headers: Bearer token authentication
|
|
95
|
+
- **Get Devices**: GET to `/v2/device` and `/v2/group`
|
|
96
|
+
- Fetches device list per home with full params
|
|
97
|
+
|
|
98
|
+
**WebSocket Connection** (`lib/connection/ws.js`)
|
|
99
|
+
- **Authentication**: Action `userOnline`
|
|
100
|
+
- Payload: `{action: 'userOnline', apikey, appid, at, nonce, sequence, ts, version: 8}`
|
|
101
|
+
- **Device Update**: Action `update`
|
|
102
|
+
- Payload: `{action: 'update', apikey, deviceid, params, sequence, ts: 0, userAgent: 'app'}`
|
|
103
|
+
- Params vary by device type (see below)
|
|
104
|
+
- **Query State**: Action `query`
|
|
105
|
+
- Payload: `{action: 'query', apikey, deviceid, params: [], sequence}`
|
|
106
|
+
- **Heartbeat**: Sends `'ping'` at intervals to keep connection alive
|
|
107
|
+
|
|
108
|
+
**LAN Connection** (`lib/connection/lan.js`)
|
|
109
|
+
- Uses mDNS discovery for `_ewelink._tcp.local` services
|
|
110
|
+
- **Encryption**: AES-128-CBC with MD5 hashed device key
|
|
111
|
+
- **Update Request**: POST to `http://{device_ip}:8081/zeroconf/{suffix}`
|
|
112
|
+
- Suffixes: `switch`, `switches`, `dimmable`, `light`, `fan`, `transmit`, `location`, `monitor`
|
|
113
|
+
- Encrypted payload with IV
|
|
114
|
+
- Data structure: `{data, deviceid, encrypt: true, iv, selfApikey: '123', sequence}`
|
|
115
|
+
- **DNS Monitoring**: Listens for TXT records with encrypted device updates
|
|
116
|
+
|
|
117
|
+
**Common Device Parameters**
|
|
118
|
+
- **Single Switch**: `{switch: 'on'/'off'}`
|
|
119
|
+
- **Multi Switch**: `{switches: [{outlet: 0-3, switch: 'on'/'off'}]}`
|
|
120
|
+
- **SCM Devices**: Uses switches array even for single switch (UIID 77/78/81/107/112/138/160)
|
|
121
|
+
- **Dimmable**: `{brightness: 0-100, mode: 0}`
|
|
122
|
+
- **RGB Light**: `{ltype: 'color'/'white', color: {br, r, g, b}, white: {br, ct}}`
|
|
123
|
+
- **Power Monitor**: `{uiActive: 120}` to request power updates
|
|
124
|
+
- **Curtain/Motor**: `{location: 0-100}` for position
|
|
125
|
+
- **RF Bridge**: `{cmd: 'transmit', rfChl: channel}`
|
|
126
|
+
- **TH10/16**: `{switch, mainSwitch, deviceType: 'normal'}`
|
|
127
|
+
- **Fan (iFan)**: `{light: 'on'/'off', fan: 'on'/'off', speed: 1-3}`
|
|
128
|
+
|
|
129
|
+
**Update Priority**
|
|
130
|
+
1. Try LAN if device supports it (check `constants.devices.lan` array)
|
|
131
|
+
2. Fall back to WebSocket if LAN fails
|
|
132
|
+
3. Queue updates with 250ms intervals to prevent rate limiting
|
|
133
|
+
4. Power monitoring devices poll every 120 seconds
|
|
134
|
+
|
|
135
|
+
### State Management
|
|
136
|
+
- Device states cached using node-persist
|
|
137
|
+
- Queue system (p-queue) prevents API rate limiting
|
|
138
|
+
- Fakegato history service for Eve Home app integration
|
|
139
|
+
|
|
140
|
+
## Important Notes
|
|
141
|
+
- ES modules with Node.js 20/22/24 support required
|
|
142
|
+
- Uses @antfu/eslint-config for code style
|
|
143
|
+
- No test suite - manual testing required
|
|
144
|
+
- Verified Homebridge plugin following official standards
|
package/lib/connection/lan.js
CHANGED
|
@@ -242,6 +242,9 @@ export default class {
|
|
|
242
242
|
} else if (json.params.uiActive && deviceInfo.uiid === 32) {
|
|
243
243
|
params.uiActive = json.params.uiActive
|
|
244
244
|
suffix = 'monitor'
|
|
245
|
+
} else if (json.params.uiActive && [126, 165].includes(deviceInfo.uiid)) {
|
|
246
|
+
// DualR3 uses statistics endpoint in LAN mode
|
|
247
|
+
suffix = 'statistics'
|
|
245
248
|
} else if (json.params.cmd) {
|
|
246
249
|
params.cmd = 'transmit'
|
|
247
250
|
params.rfChl = json.params.rfChl
|
package/lib/utils/constants.js
CHANGED
|
@@ -284,7 +284,7 @@ export default {
|
|
|
284
284
|
211,
|
|
285
285
|
212,
|
|
286
286
|
],
|
|
287
|
-
switchSingle: [1, 6, 14, 24, 27, 226, 1009, 1256, 7004, 7005, 7010],
|
|
287
|
+
switchSingle: [1, 6, 14, 24, 27, 225, 226, 1009, 1256, 7004, 7005, 7010, 7032],
|
|
288
288
|
switchSCM: [77, 78, 81, 107, 112, 138, 160, 191, 209],
|
|
289
289
|
switchSCMPower: [182, 190],
|
|
290
290
|
switchSinglePower: [5, 32],
|
|
@@ -312,18 +312,19 @@ export default {
|
|
|
312
312
|
210,
|
|
313
313
|
211,
|
|
314
314
|
212,
|
|
315
|
+
262,
|
|
315
316
|
2256,
|
|
316
317
|
3256,
|
|
317
318
|
4256,
|
|
318
319
|
],
|
|
319
|
-
switchMultiPower: [126, 165],
|
|
320
|
+
switchMultiPower: [126, 165, 262],
|
|
320
321
|
switchMate: [177],
|
|
321
322
|
switchMan: [174],
|
|
322
323
|
lightDimmer: [36, 44, 57],
|
|
323
324
|
lightRGB: [22],
|
|
324
325
|
lightCCT: [103],
|
|
325
326
|
lightRGBCCT: [33, 59, 104, 135, 136, 137, 173],
|
|
326
|
-
curtain: [11, 67],
|
|
327
|
+
curtain: [11, 67, 91, 258],
|
|
327
328
|
sensorContact: [102, 154],
|
|
328
329
|
sensorAmbient: [15, 181],
|
|
329
330
|
sensorTempHumi: [18],
|
|
@@ -344,7 +345,7 @@ export default {
|
|
|
344
345
|
zbSensorMotion: [2026, 7002],
|
|
345
346
|
zbSensorOccupancy: [7016],
|
|
346
347
|
zbSensorContact: [3026, 7003],
|
|
347
|
-
zbSensorWater: [4026],
|
|
348
|
+
zbSensorWater: [4026, 7019],
|
|
348
349
|
zbSensorSmoke: [5026],
|
|
349
350
|
zbThermostat: [7017],
|
|
350
351
|
zbWaterValve: [7027],
|
|
@@ -468,6 +469,7 @@ export default {
|
|
|
468
469
|
83: 3, // "GSM_SOCKET_3_NO_FLOW"
|
|
469
470
|
84: 4, // "GSM_SOCKET_4_NO_FLOW"
|
|
470
471
|
87: 1, // "EWELINK_IOT_CAMERA" (GK-200MP2B)
|
|
472
|
+
91: 1, // "ROLLING_DOOR" (Cover/Curtain device)
|
|
471
473
|
98: 1, // "DOORBELL_RFBRIDGE"
|
|
472
474
|
102: 1, // "DOOR_MAGNETIC" (OPL-DMA, DW2)
|
|
473
475
|
103: 1, // "WOTEWODE_TEM_LIGHT" (B02-F)
|
|
@@ -506,8 +508,11 @@ export default {
|
|
|
506
508
|
210: 2, // Sonoff Ultimate Switch T5-2C-86
|
|
507
509
|
211: 3, // Sonoff Ultimate Switch T5-3C-86
|
|
508
510
|
212: 4, // Sonoff Ultimate Switch T5-4C-86
|
|
511
|
+
225: 1, // CK-BL602-PCSW-01 (Single switch with power monitoring)
|
|
509
512
|
226: 1, // https://github.com/homebridge-plugins/homebridge-ewelink/issues/636
|
|
510
513
|
243: 1, // Zigbee Bridge Ultra
|
|
514
|
+
258: 1, // Additional Cover device
|
|
515
|
+
262: 4, // CK-BL602-SWP1-02 (4-channel switch with power monitoring)
|
|
511
516
|
1000: 1, // "zigbee_ON_OFF_SWITCH_1000" (button device)
|
|
512
517
|
1009: 1, // "" (Some sort of single switch device)
|
|
513
518
|
1256: 1, // "ZIGBEE_SINGLE_SWITCH"
|
|
@@ -535,7 +540,9 @@ export default {
|
|
|
535
540
|
7014: 1, // some sensor https://github.com/homebridge-plugins/homebridge-ewelink/issues/494
|
|
536
541
|
7016: 1, // https://sonoff.tech/product/gateway-and-sensors/snzb-06p/
|
|
537
542
|
7017: 1, // https://github.com/homebridge-plugins/homebridge-ewelink/issues/518
|
|
543
|
+
7019: 1, // Zigbee Water Sensor
|
|
538
544
|
7027: 1, // Zigbee Smart Water Valve
|
|
545
|
+
7032: 1, // Zigbee Power Monitoring Switch
|
|
539
546
|
},
|
|
540
547
|
|
|
541
548
|
cannotSupportDevices: {
|
|
@@ -582,7 +589,6 @@ export default {
|
|
|
582
589
|
88: 0, // "YK_INFRARED"
|
|
583
590
|
89: 0, // "SMART_OPEN_MACHINE"
|
|
584
591
|
90: 0, // "GSM_RFBridge"
|
|
585
|
-
91: 0, // "ROLLING_DOOR_91"
|
|
586
592
|
93: 0, // "HTHD_AIR_CLEANER"
|
|
587
593
|
94: 0, // "YIAN_ELECTRIC_PROTECT"
|
|
588
594
|
109: 0, // "YK_INFRARED_2"
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"displayName": "Homebridge eWeLink",
|
|
4
4
|
"alias": "eWeLink",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"version": "12.
|
|
6
|
+
"version": "12.7.0",
|
|
7
7
|
"description": "Homebridge plugin to integrate eWeLink devices into HomeKit.",
|
|
8
8
|
"author": {
|
|
9
9
|
"name": "bwp91",
|
|
@@ -62,13 +62,13 @@
|
|
|
62
62
|
},
|
|
63
63
|
"dependencies": {
|
|
64
64
|
"@homebridge/plugin-ui-utils": "^2.1.0",
|
|
65
|
-
"axios": "^1.
|
|
65
|
+
"axios": "^1.12.2",
|
|
66
66
|
"node-persist": "^4.0.4",
|
|
67
|
-
"p-queue": "^8.1.
|
|
67
|
+
"p-queue": "^8.1.1",
|
|
68
68
|
"websocket-as-promised": "^3.0.1",
|
|
69
69
|
"ws": "^8.18.3"
|
|
70
70
|
},
|
|
71
71
|
"devDependencies": {
|
|
72
|
-
"@antfu/eslint-config": "^4.
|
|
72
|
+
"@antfu/eslint-config": "^5.4.1"
|
|
73
73
|
}
|
|
74
74
|
}
|