homebridge-smartsystem 6.8.18 → 7.0.3
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/.vscode/launch.json +15 -4
- package/MIXINS-GUIDE.md +210 -0
- package/README.md +31 -0
- package/SETTINGS-UPDATE.md +195 -0
- package/TESTING-GUIDE.md +220 -0
- package/WEBSOCKET-API.md +303 -0
- package/config.json +57 -19
- package/duotecno/types.js +48 -2
- package/duotecno/types.ts +79 -1
- package/package.json +7 -3
- package/raspberry-pi-setup.sh +80 -0
- package/server/HA-API.js +4 -1
- package/server/HA-API.ts +4 -1
- package/server/HB.js +6 -1
- package/server/HB.ts +5 -1
- package/server/mDNS.js +168 -0
- package/server/mDNS.ts +198 -0
- package/server/platform.js +7 -0
- package/server/platform.ts +8 -0
- package/server/proxy.js +58 -19
- package/server/proxy.ts +31 -3
- package/server/smartapp.js +412 -18
- package/server/smartapp.ts +450 -20
- package/server/socapp.js +2 -1
- package/server/socapp.ts +2 -1
- package/server/views/assets/Duotecno_logo_black.svg +10 -0
- package/server/views/assets/Duotecno_logo_white.svg +10 -0
- package/server/views/device-details.ejs +139 -0
- package/server/views/device-list.ejs +44 -0
- package/server/views/footer.ejs +0 -1
- package/server/views/head.ejs +9 -0
- package/server/views/homekit.ejs +2 -9
- package/server/views/link-details.ejs +2 -15
- package/server/views/link-list.ejs +2 -9
- package/server/views/login.ejs +8 -9
- package/server/views/master-detail.ejs +3 -9
- package/server/views/master-list.ejs +3 -10
- package/server/views/nav.ejs +44 -11
- package/server/views/node-details.ejs +1 -8
- package/server/views/power-binding.ejs +3 -10
- package/server/views/power-rule.ejs +3 -10
- package/server/views/power.ejs +8 -15
- package/server/views/proxy.ejs +1 -8
- package/server/views/scripts.ejs +10 -0
- package/server/views/service-list.ejs +2 -9
- package/server/views/settings.ejs +61 -22
- package/server/views/style.ejs +49 -5
- package/server/views/switch-details.ejs +2 -9
- package/server/views/switch-list.ejs +2 -9
- package/server/webapp.js +150 -11
- package/server/webapp.ts +166 -14
- package/{index.spec.js → testHB.js} +1 -1
- package/{run.js → testProxy.js} +2 -2
- package/{run.ts → testProxy.ts} +1 -1
- package/testWS.js +137 -0
- package/testWS.ts +174 -0
- package/run9998.js +0 -7
- package/run9998.ts +0 -6
- package/run9999.js +0 -7
- package/run9999.ts +0 -6
- /package/{index.spec.ts → testHB.ts} +0 -0
package/.vscode/launch.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"request": "launch",
|
|
7
7
|
"smartStep": true,
|
|
8
8
|
"sourceMaps": true,
|
|
9
|
-
"name": "Test Platform",
|
|
10
|
-
"program": "${workspaceFolder}/
|
|
9
|
+
"name": "Test HB Platform",
|
|
10
|
+
"program": "${workspaceFolder}/testHB.js",
|
|
11
11
|
"skipFiles": [
|
|
12
12
|
"<node_internals>/**"
|
|
13
13
|
]
|
|
@@ -17,8 +17,19 @@
|
|
|
17
17
|
"request": "launch",
|
|
18
18
|
"smartStep": true,
|
|
19
19
|
"sourceMaps": true,
|
|
20
|
-
"name": "Run SmartSocket",
|
|
21
|
-
"program": "${workspaceFolder}/
|
|
20
|
+
"name": "Run SmartSocket Proxy",
|
|
21
|
+
"program": "${workspaceFolder}/testProxy.js",
|
|
22
|
+
"skipFiles": [
|
|
23
|
+
"<node_internals>/**"
|
|
24
|
+
]
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
"type": "node",
|
|
28
|
+
"request": "launch",
|
|
29
|
+
"smartStep": true,
|
|
30
|
+
"sourceMaps": true,
|
|
31
|
+
"name": "Run Test Websockets",
|
|
32
|
+
"program": "${workspaceFolder}/testWS.js",
|
|
22
33
|
"skipFiles": [
|
|
23
34
|
"<node_internals>/**"
|
|
24
35
|
]
|
package/MIXINS-GUIDE.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# TypeScript Mixins Pattern for SmartApp
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
Your SmartApp is getting large because it handles multiple concerns:
|
|
6
|
+
- Device management (WebSocket, power measurements)
|
|
7
|
+
- Link management (Homebridge accessories)
|
|
8
|
+
- Switch management (HTTP switches)
|
|
9
|
+
- Power management (Smappee, P1, Shelly)
|
|
10
|
+
- Proxy configuration
|
|
11
|
+
- Settings management
|
|
12
|
+
|
|
13
|
+
TypeScript doesn't support multiple inheritance, but **mixins** provide a similar capability.
|
|
14
|
+
|
|
15
|
+
## Solution Options
|
|
16
|
+
|
|
17
|
+
### **Option 1: Mixin Pattern** (Most Flexible)
|
|
18
|
+
|
|
19
|
+
Create separate mixin functions that add functionality to your class:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
// server/mixins/DeviceMixin.ts
|
|
23
|
+
type Constructor<T = {}> = new (...args: any[]) => T;
|
|
24
|
+
|
|
25
|
+
export interface DeviceMixinBase {
|
|
26
|
+
devices: Array<Device>;
|
|
27
|
+
system: System;
|
|
28
|
+
power: Power;
|
|
29
|
+
// ... other required properties
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function DeviceMixin<TBase extends Constructor<DeviceMixinBase>>(Base: TBase) {
|
|
33
|
+
return class extends Base {
|
|
34
|
+
setupWebSocketServers() { /* ... */ }
|
|
35
|
+
sendDeviceList(ws: WebSocket) { /* ... */ }
|
|
36
|
+
getDeviceList() { /* ... */ }
|
|
37
|
+
// ... all device-related methods
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Usage in smartapp.ts
|
|
42
|
+
import { DeviceMixin } from './mixins/DeviceMixin';
|
|
43
|
+
import { LinkMixin } from './mixins/LinkMixin';
|
|
44
|
+
import { SwitchMixin } from './mixins/SwitchMixin';
|
|
45
|
+
|
|
46
|
+
// Apply mixins
|
|
47
|
+
const SmartAppBase = SwitchMixin(LinkMixin(DeviceMixin(WebApp)));
|
|
48
|
+
|
|
49
|
+
export class SmartApp extends SmartAppBase {
|
|
50
|
+
// Only SmartApp-specific logic here
|
|
51
|
+
constructor(system: System, power: Power, platform: Platform) {
|
|
52
|
+
super("smartapp");
|
|
53
|
+
// ...
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
**Pros:**
|
|
59
|
+
- True composition - each mixin is independent
|
|
60
|
+
- Can be reused across different classes
|
|
61
|
+
- TypeScript type-safe
|
|
62
|
+
- Easy to test mixins individually
|
|
63
|
+
|
|
64
|
+
**Cons:**
|
|
65
|
+
- Requires some boilerplate
|
|
66
|
+
- Mixing order matters
|
|
67
|
+
- Can be confusing at first
|
|
68
|
+
|
|
69
|
+
---
|
|
70
|
+
|
|
71
|
+
### **Option 2: Delegate Pattern** (Simpler)
|
|
72
|
+
|
|
73
|
+
Create separate service/manager classes and delegate to them:
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
// server/services/DeviceManager.ts
|
|
77
|
+
export class DeviceManager {
|
|
78
|
+
constructor(
|
|
79
|
+
private devices: Array<Device>,
|
|
80
|
+
private system: System,
|
|
81
|
+
private power: Power
|
|
82
|
+
) {}
|
|
83
|
+
|
|
84
|
+
setupWebSocketServers(servers: http.Server[]) { /* ... */ }
|
|
85
|
+
getDeviceList() { /* ... */ }
|
|
86
|
+
// ... all device methods
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// server/services/LinkManager.ts
|
|
90
|
+
export class LinkManager {
|
|
91
|
+
constructor(
|
|
92
|
+
private links: Array<Link>,
|
|
93
|
+
private system: System
|
|
94
|
+
) {}
|
|
95
|
+
|
|
96
|
+
initLinks() { /* ... */ }
|
|
97
|
+
updateLink(inx: number, link: Link) { /* ... */ }
|
|
98
|
+
// ... all link methods
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// In smartapp.ts
|
|
102
|
+
export class SmartApp extends WebApp {
|
|
103
|
+
private deviceManager: DeviceManager;
|
|
104
|
+
private linkManager: LinkManager;
|
|
105
|
+
|
|
106
|
+
constructor(system: System, power: Power, platform: Platform) {
|
|
107
|
+
super("smartapp");
|
|
108
|
+
|
|
109
|
+
this.deviceManager = new DeviceManager(this.devices, this.system, this.power);
|
|
110
|
+
this.linkManager = new LinkManager(this.links, this.system);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Delegate to managers
|
|
114
|
+
setupWebSocketServers() {
|
|
115
|
+
this.deviceManager.setupWebSocketServers(this.servers);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
initLinks() {
|
|
119
|
+
this.linkManager.initLinks();
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Pros:**
|
|
125
|
+
- Simple and intuitive
|
|
126
|
+
- Easy to understand
|
|
127
|
+
- Good separation of concerns
|
|
128
|
+
- Easy to unit test
|
|
129
|
+
|
|
130
|
+
**Cons:**
|
|
131
|
+
- More delegation boilerplate
|
|
132
|
+
- Not as "clean" as mixins
|
|
133
|
+
- Managers need access to SmartApp state
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
### **Option 3: Module Pattern** (Most Practical)
|
|
138
|
+
|
|
139
|
+
Split into separate modules but keep in same class:
|
|
140
|
+
|
|
141
|
+
```typescript
|
|
142
|
+
// server/smartapp/devices.ts
|
|
143
|
+
export class DeviceManagement {
|
|
144
|
+
static setupWebSocketServers(app: SmartApp) { /* ... */ }
|
|
145
|
+
static getDeviceList(app: SmartApp) { /* ... */ }
|
|
146
|
+
// ... all device methods as static functions
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// server/smartapp/links.ts
|
|
150
|
+
export class LinkManagement {
|
|
151
|
+
static initLinks(app: SmartApp) { /* ... */ }
|
|
152
|
+
static updateLink(app: SmartApp, inx: number, link: Link) { /* ... */ }
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// In smartapp.ts
|
|
156
|
+
import { DeviceManagement } from './smartapp/devices';
|
|
157
|
+
import { LinkManagement } from './smartapp/links';
|
|
158
|
+
|
|
159
|
+
export class SmartApp extends WebApp {
|
|
160
|
+
setupWebSocketServers() {
|
|
161
|
+
DeviceManagement.setupWebSocketServers(this);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
initLinks() {
|
|
165
|
+
LinkManagement.initLinks(this);
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
**Pros:**
|
|
171
|
+
- Simple to implement
|
|
172
|
+
- Code is organized in separate files
|
|
173
|
+
- No complex patterns needed
|
|
174
|
+
- Easy to refactor incrementally
|
|
175
|
+
|
|
176
|
+
**Cons:**
|
|
177
|
+
- Still some methods in main class
|
|
178
|
+
- Not true composition
|
|
179
|
+
- Methods take `app` parameter
|
|
180
|
+
|
|
181
|
+
---
|
|
182
|
+
|
|
183
|
+
## **Recommended Approach**
|
|
184
|
+
|
|
185
|
+
For your situation, I'd recommend **Option 2 (Delegate Pattern)** or **Option 3 (Module Pattern)**.
|
|
186
|
+
|
|
187
|
+
Here's why:
|
|
188
|
+
1. **Easier to understand** - no complex mixin magic
|
|
189
|
+
2. **Incremental refactoring** - move one feature at a time
|
|
190
|
+
3. **Better testability** - each manager/module is isolated
|
|
191
|
+
4. **Clearer dependencies** - you see what each part needs
|
|
192
|
+
|
|
193
|
+
### Quick Win: Module Pattern
|
|
194
|
+
|
|
195
|
+
Split your 1680-line smartapp.ts into:
|
|
196
|
+
|
|
197
|
+
```
|
|
198
|
+
server/
|
|
199
|
+
smartapp.ts (main class, ~300 lines)
|
|
200
|
+
smartapp/
|
|
201
|
+
devices.ts (WebSocket & power, ~300 lines)
|
|
202
|
+
links.ts (Homebridge links, ~200 lines)
|
|
203
|
+
switches.ts (HTTP switches, ~200 lines)
|
|
204
|
+
power.ts (Power bindings, ~150 lines)
|
|
205
|
+
proxy.ts (Proxy config, ~150 lines)
|
|
206
|
+
routes.ts (HTTP routing, ~200 lines)
|
|
207
|
+
units.ts (Unit management, ~150 lines)
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
Would you like me to help you refactor SmartApp using one of these patterns?
|
package/README.md
CHANGED
|
@@ -317,6 +317,9 @@ Homebridge UI version
|
|
|
317
317
|
- 11: use new DNS entries + exponential backoff for new connections, give up after 16 seconds.
|
|
318
318
|
- 12, 13: small changes for missing value for Target...
|
|
319
319
|
|
|
320
|
+
### v7.0.0 - 12/11/2025
|
|
321
|
+
- 0: added mDNS/Bonjour + always port 80 + don't preload EJS files if system.debug == true
|
|
322
|
+
|
|
320
323
|
## Hardware
|
|
321
324
|
A Raspberry Pi that connects to a Duotecno IP Node
|
|
322
325
|
and (if configured) to a Smappee Infinity (power and plugs)
|
|
@@ -348,6 +351,34 @@ and linked to HB accessories (from v6.7)
|
|
|
348
351
|
* scenes (a collection of units + a state) that are triggers by a status change (moods, inputs, ...)
|
|
349
352
|
* backup / restore
|
|
350
353
|
|
|
354
|
+
* Jullix:
|
|
355
|
+
|
|
356
|
+
* I would now like to have a websocket server (on the same ports as the SmartApp) that uses JSON as format.
|
|
357
|
+
* The client that connects can send 2 things: see below, but we should always answer with a number of "switchable items" (relays) together with the power/energy usaged, either measured of estimated (measured: false).
|
|
358
|
+
* An example we could send:
|
|
359
|
+
```
|
|
360
|
+
[
|
|
361
|
+
{ "id": 1, "name": "Airco", "power": 1.0, "energy": 10.0, "voltage": 230.0, "current": 1.0, "relay": true, "measured": true},
|
|
362
|
+
{ "id": 2, "name": "Zwembad pomp", "power": 1.0, "energy": 10.0, "voltage": 230.0, "current": 1.0, "relay": true, "measured": false}
|
|
363
|
+
]
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
* What we send / what is in this array needs to be configured though a new section in the web interface.
|
|
367
|
+
|
|
368
|
+
|
|
369
|
+
The id's of the relays should be node-numbers * 256 + unit-numbers of Duotecno units (of the first master) and the web/config-page should allow the user to add a "Device" and fill in the details (no id given) + edit a device already in the list. (pass id) (similar as in link-list.ejs and link-details.ejs)
|
|
370
|
+
|
|
371
|
+
* Messages we could receive:
|
|
372
|
+
[] (empty array) keep of keep alice / poll for status
|
|
373
|
+
```
|
|
374
|
+
[
|
|
375
|
+
{ "id": 513 "relay": true },
|
|
376
|
+
{ "id": 258, "relay": false }
|
|
377
|
+
]
|
|
378
|
+
```
|
|
379
|
+
which would mean: turn unit 1 in node 2 (from 513=2*256+1) "on" and turn unit 2 of node 1 "off" (from 258=1*256+2)
|
|
380
|
+
|
|
381
|
+
|
|
351
382
|
|
|
352
383
|
## How to set up
|
|
353
384
|
1. Configure IP address of the Raspberry on the SDCard on a PC or Mac (put it in, edit cmdline.txt and you’re done), perhaps DHCP? WiFi?
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# Settings Page Update
|
|
2
|
+
|
|
3
|
+
## Changes Made
|
|
4
|
+
|
|
5
|
+
### 1. Cleaned Up Settings Page
|
|
6
|
+
- **Removed** conflicting buttons from header (Reset to DHCP, Install IP Settings, Reboot PI)
|
|
7
|
+
- **Added** proper "Save Settings" button with icon
|
|
8
|
+
- **Added** "Restart Server" button (functional) with icon
|
|
9
|
+
- **Commented out** temporarily disabled network configuration fields
|
|
10
|
+
- **Commented out** temporarily disabled system action buttons
|
|
11
|
+
|
|
12
|
+
### 2. Added Save Functionality
|
|
13
|
+
- New "Save Settings" button that saves the mDNS configuration
|
|
14
|
+
- Success message displayed after saving
|
|
15
|
+
- Reminder to restart server for changes to take effect
|
|
16
|
+
|
|
17
|
+
### 3. Temporarily Disabled Features
|
|
18
|
+
The following features are commented out with TODO notes pending proper implementation:
|
|
19
|
+
|
|
20
|
+
**Network Configuration (commented in EJS):**
|
|
21
|
+
- Primary Fixed IP Address / netmask
|
|
22
|
+
- Gateway
|
|
23
|
+
- Nameservers
|
|
24
|
+
- Secondary IP configuration
|
|
25
|
+
|
|
26
|
+
**System Actions (commented in EJS):**
|
|
27
|
+
- Reboot System button
|
|
28
|
+
- Reset to DHCP button
|
|
29
|
+
- Install IP Settings button
|
|
30
|
+
|
|
31
|
+
**Backend Handlers (commented in smartapp.ts):**
|
|
32
|
+
- `install` action - writeDHCP functionality
|
|
33
|
+
- `reset` action - resetDHCP and reboot
|
|
34
|
+
- `reboot` action - system reboot
|
|
35
|
+
|
|
36
|
+
### 4. Active Features
|
|
37
|
+
Currently working features in Settings:
|
|
38
|
+
|
|
39
|
+
✅ **mDNS Service Name Configuration**
|
|
40
|
+
- Input field for mDNS name
|
|
41
|
+
- Default value: "duotecno-gateway"
|
|
42
|
+
- Help text showing resulting .local address
|
|
43
|
+
- Save button stores configuration
|
|
44
|
+
|
|
45
|
+
✅ **Save Settings**
|
|
46
|
+
- Saves mDNS configuration to settings file
|
|
47
|
+
- Shows success message
|
|
48
|
+
- Logs configuration change
|
|
49
|
+
|
|
50
|
+
✅ **Restart Server**
|
|
51
|
+
- Functional restart button (orange color)
|
|
52
|
+
- Restarts the Node.js process
|
|
53
|
+
- Allows mDNS changes to take effect
|
|
54
|
+
|
|
55
|
+
### 5. UI Improvements
|
|
56
|
+
|
|
57
|
+
**Message Display:**
|
|
58
|
+
- Green success message when settings saved
|
|
59
|
+
- Orange info message for disabled features
|
|
60
|
+
- Icon indicators (checkmark for success, info icon for warnings)
|
|
61
|
+
|
|
62
|
+
**Button Styling:**
|
|
63
|
+
- Save button: Blue with save icon
|
|
64
|
+
- Restart button: Orange with refresh icon
|
|
65
|
+
- Disabled buttons: Commented out (red for reboot, grey for reset, blue for install)
|
|
66
|
+
|
|
67
|
+
**Layout:**
|
|
68
|
+
- Clear section header: "mDNS Configuration"
|
|
69
|
+
- TODO comment explaining why network settings are disabled
|
|
70
|
+
- Clean, focused interface for current functionality
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
### To Configure mDNS Name:
|
|
75
|
+
|
|
76
|
+
1. Navigate to `/settings`
|
|
77
|
+
2. Enter desired mDNS name (e.g., "garage-gateway")
|
|
78
|
+
3. Click "Save Settings"
|
|
79
|
+
4. See success message
|
|
80
|
+
5. Click "Restart Server" to apply changes
|
|
81
|
+
6. Access gateway at: `http://{your-name}.local/`
|
|
82
|
+
|
|
83
|
+
### Current Button Actions:
|
|
84
|
+
|
|
85
|
+
| Button | Action | Status |
|
|
86
|
+
|--------|--------|--------|
|
|
87
|
+
| Save Settings | Saves mDNS config | ✅ Working |
|
|
88
|
+
| Restart Server | Restarts Node.js process | ✅ Working |
|
|
89
|
+
| Reboot System | System reboot | ⏸️ Disabled (commented) |
|
|
90
|
+
| Reset to DHCP | Reset network config | ⏸️ Disabled (commented) |
|
|
91
|
+
| Install IP Settings | Write DHCP config | ⏸️ Disabled (commented) |
|
|
92
|
+
|
|
93
|
+
## Technical Details
|
|
94
|
+
|
|
95
|
+
### Settings File Structure
|
|
96
|
+
```json
|
|
97
|
+
{
|
|
98
|
+
"network": {
|
|
99
|
+
"ip1": "",
|
|
100
|
+
"gateway1": "",
|
|
101
|
+
"nameservers": "",
|
|
102
|
+
"ip2": "",
|
|
103
|
+
"gateway2": ""
|
|
104
|
+
},
|
|
105
|
+
"mdnsName": "duotecno-gateway"
|
|
106
|
+
}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Handler Logic (smartapp.ts)
|
|
110
|
+
|
|
111
|
+
**Save Action:**
|
|
112
|
+
```typescript
|
|
113
|
+
if (context.action === "save") {
|
|
114
|
+
config = this.scrapeSettings(context);
|
|
115
|
+
this.write("settings", config);
|
|
116
|
+
message = "Settings saved successfully. Restart the server for changes to take effect.";
|
|
117
|
+
log("smartapp", "Settings saved. mDNS name updated to: " + config.mdnsName);
|
|
118
|
+
}
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
**Restart Action:**
|
|
122
|
+
```typescript
|
|
123
|
+
else if (context.action === "restart") {
|
|
124
|
+
context.request = "restart";
|
|
125
|
+
return this.doRestart(false)
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
**Disabled Actions:**
|
|
130
|
+
```typescript
|
|
131
|
+
else if (context.action === "install") {
|
|
132
|
+
message = "Network IP configuration is temporarily disabled. Use 'Save Settings' for mDNS configuration.";
|
|
133
|
+
// TODO: Re-implement DHCP configuration
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Future Work
|
|
138
|
+
|
|
139
|
+
### TODO List:
|
|
140
|
+
1. ✅ Test Devices WebSocket functionality (priority)
|
|
141
|
+
2. ⏳ Re-implement DHCP configuration properly
|
|
142
|
+
3. ⏳ Re-enable network IP settings fields
|
|
143
|
+
4. ⏳ Re-enable system reboot functionality
|
|
144
|
+
5. ⏳ Add validation for mDNS name format
|
|
145
|
+
6. ⏳ Test network configuration on actual Raspberry Pi
|
|
146
|
+
7. ⏳ Add confirmation dialog for reboot action
|
|
147
|
+
|
|
148
|
+
### Implementation Notes:
|
|
149
|
+
|
|
150
|
+
**DHCP Configuration Issues:**
|
|
151
|
+
- Writing to `/etc/dhcpcd.conf` may require root privileges
|
|
152
|
+
- Need to test on actual Raspberry Pi hardware
|
|
153
|
+
- Consider using `nmcli` or `netplan` for modern systems
|
|
154
|
+
- Add error handling for file write failures
|
|
155
|
+
|
|
156
|
+
**Reboot Functionality:**
|
|
157
|
+
- Requires appropriate system permissions
|
|
158
|
+
- May need `sudo` or specific user group membership
|
|
159
|
+
- Consider adding confirmation dialog
|
|
160
|
+
- Add timeout before reboot to allow user to see message
|
|
161
|
+
|
|
162
|
+
## Testing
|
|
163
|
+
|
|
164
|
+
### Test Save Settings:
|
|
165
|
+
1. Navigate to `/settings`
|
|
166
|
+
2. Change mDNS name to "test-gateway"
|
|
167
|
+
3. Click "Save Settings"
|
|
168
|
+
4. Verify success message appears
|
|
169
|
+
5. Check console log for: "Settings saved. mDNS name updated to: test-gateway"
|
|
170
|
+
6. Verify settings file updated: `cat server/config.json | grep mdnsName`
|
|
171
|
+
|
|
172
|
+
### Test Restart Server:
|
|
173
|
+
1. Click "Restart Server" button
|
|
174
|
+
2. Server should restart gracefully
|
|
175
|
+
3. mDNS service should re-register with new name
|
|
176
|
+
4. Verify accessible at: `http://test-gateway.local/`
|
|
177
|
+
|
|
178
|
+
### Verify Disabled Features:
|
|
179
|
+
1. Network IP fields should be commented out (not visible)
|
|
180
|
+
2. System action buttons should be commented out (not visible)
|
|
181
|
+
3. No errors in console when loading `/settings`
|
|
182
|
+
4. Form should only show mDNS configuration and two buttons
|
|
183
|
+
|
|
184
|
+
## Summary
|
|
185
|
+
|
|
186
|
+
The Settings page is now **focused and functional** with:
|
|
187
|
+
- ✅ mDNS name configuration working
|
|
188
|
+
- ✅ Save button added
|
|
189
|
+
- ✅ Restart server button working
|
|
190
|
+
- ✅ Success/info messages displayed
|
|
191
|
+
- ✅ Clean UI with proper icons
|
|
192
|
+
- 🔒 Network configuration temporarily disabled pending fixes
|
|
193
|
+
- 📝 Clear TODO notes for future implementation
|
|
194
|
+
|
|
195
|
+
Priority remains on testing the Devices WebSocket functionality before re-enabling network configuration features.
|
package/TESTING-GUIDE.md
ADDED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Testing WebSocket Device Control
|
|
2
|
+
|
|
3
|
+
## Setup Complete ✅
|
|
4
|
+
|
|
5
|
+
I've added 2 test devices to your `config.json`:
|
|
6
|
+
|
|
7
|
+
1. **Test Lamp** (Node 3, Unit 34, ID: 802)
|
|
8
|
+
- Estimated power: 100W
|
|
9
|
+
- Maps to your existing "Lamp-Bottom" unit
|
|
10
|
+
|
|
11
|
+
2. **Blue LED** (Node 3, Unit 30, ID: 798)
|
|
12
|
+
- Estimated power: 50W
|
|
13
|
+
- Maps to your existing "Blue LED" unit
|
|
14
|
+
|
|
15
|
+
## Testing Steps
|
|
16
|
+
|
|
17
|
+
### **Step 1: Start the Server (in Debug Mode)**
|
|
18
|
+
|
|
19
|
+
1. Open VS Code debugger
|
|
20
|
+
2. Set breakpoints if needed:
|
|
21
|
+
- `server/smartapp.ts` line ~165 (setupWebSocketServers)
|
|
22
|
+
- `server/smartapp.ts` line ~230 (handleDeviceMessage)
|
|
23
|
+
3. Run the debugger with testHB.ts configuration
|
|
24
|
+
- Or: `ts-node testHB.ts` in terminal
|
|
25
|
+
|
|
26
|
+
The server should start on port 5002 (from your config)
|
|
27
|
+
|
|
28
|
+
### **Step 2: Verify Server Started**
|
|
29
|
+
|
|
30
|
+
You should see log messages:
|
|
31
|
+
```
|
|
32
|
+
✓ WebSocket server 0 set up on path /devices
|
|
33
|
+
✓ WebApp - Listening on port 5002
|
|
34
|
+
✓ mDNS service registered
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
### **Step 3: Test WebSocket Connection**
|
|
38
|
+
|
|
39
|
+
In a **separate terminal**, run the test client:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
# Using mDNS name (recommended)
|
|
43
|
+
ts-node testWS.ts ws://duotecno-gateway.local/devices
|
|
44
|
+
|
|
45
|
+
# Or specify IP address if needed
|
|
46
|
+
ts-node testWS.ts ws://192.168.0.99/devices
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### **Step 4: Expected Test Client Output**
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
╔════════════════════════════════════════════════════════════════════╗
|
|
53
|
+
║ WebSocket Device Control Test Client ║
|
|
54
|
+
║ Press Ctrl+C to exit ║
|
|
55
|
+
╚════════════════════════════════════════════════════════════════════╝
|
|
56
|
+
|
|
57
|
+
🔌 Connecting to WebSocket server: ws://duotecno-gateway.local/devices
|
|
58
|
+
✅ Connected to WebSocket server
|
|
59
|
+
|
|
60
|
+
📊 Received 2 device(s):
|
|
61
|
+
════════════════════════════════════════════════════════════════════════
|
|
62
|
+
ID | Name | Power(W) | Current(A) | Voltage(V) | Relay | Measured
|
|
63
|
+
────────────────────────────────────────────────────────────────────────
|
|
64
|
+
802 | Test Lamp | 0.0 | 0.00 | 230.0 | 🔴 OFF | 📝
|
|
65
|
+
798 | Blue LED | 0.0 | 0.00 | 230.0 | 🔴 OFF | 📝
|
|
66
|
+
════════════════════════════════════════════════════════════════════════
|
|
67
|
+
|
|
68
|
+
⏱️ Sending keep-alive poll...
|
|
69
|
+
|
|
70
|
+
🎲 Sending random control commands:
|
|
71
|
+
→ Test Lamp (node=3, unit=34, id=802): 🟢 ON
|
|
72
|
+
→ Blue LED (node=3, unit=30, id=798): 🟢 ON
|
|
73
|
+
|
|
74
|
+
📊 Received 2 device(s):
|
|
75
|
+
════════════════════════════════════════════════════════════════════════
|
|
76
|
+
ID | Name | Power(W) | Current(A) | Voltage(V) | Relay | Measured
|
|
77
|
+
────────────────────────────────────────────────────────────────────────
|
|
78
|
+
802 | Test Lamp | 100.0 | 0.43 | 230.0 | 🟢 ON | 📝
|
|
79
|
+
798 | Blue LED | 50.0 | 0.22 | 230.0 | 🟢 ON | 📝
|
|
80
|
+
════════════════════════════════════════════════════════════════════════
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Notice:
|
|
84
|
+
- Power goes to estimated value (100W, 50W) when relay is ON
|
|
85
|
+
- Power goes to 0 when relay is OFF
|
|
86
|
+
- Current is calculated (Power / 230V)
|
|
87
|
+
- Measured flag shows 📝 (estimated) not 📊 (measured)
|
|
88
|
+
|
|
89
|
+
### **Step 5: Test Web UI (Optional)**
|
|
90
|
+
|
|
91
|
+
1. Open browser: `http://duotecno-gateway.local/devices`
|
|
92
|
+
2. You should see the 2 test devices listed
|
|
93
|
+
3. Click a device to edit:
|
|
94
|
+
- Change name
|
|
95
|
+
- Change power source (P1, Shelly, Smappee, or Non-measured)
|
|
96
|
+
- Change estimated power
|
|
97
|
+
- Save changes
|
|
98
|
+
|
|
99
|
+
### **Step 6: Test Manual WebSocket Commands**
|
|
100
|
+
|
|
101
|
+
You can also test manually using a WebSocket client like `wscat`:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
# Install wscat if needed
|
|
105
|
+
npm install -g wscat
|
|
106
|
+
|
|
107
|
+
# Connect using mDNS name
|
|
108
|
+
wscat -c ws://duotecno-gateway.local/devices
|
|
109
|
+
|
|
110
|
+
# You'll receive device list immediately
|
|
111
|
+
|
|
112
|
+
# Send keep-alive (poll)
|
|
113
|
+
[]
|
|
114
|
+
|
|
115
|
+
# Turn device ON
|
|
116
|
+
[{"id": 802, "relay": true}]
|
|
117
|
+
|
|
118
|
+
# Turn device OFF
|
|
119
|
+
[{"id": 802, "relay": false}]
|
|
120
|
+
|
|
121
|
+
# Control multiple devices
|
|
122
|
+
[{"id": 802, "relay": true}, {"id": 798, "relay": false}]
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
## What to Look For
|
|
126
|
+
|
|
127
|
+
### **✅ Success Indicators:**
|
|
128
|
+
|
|
129
|
+
1. **WebSocket connects** without errors
|
|
130
|
+
2. **Device list received** with correct IDs (802, 798)
|
|
131
|
+
3. **Relay control works** - devices turn on/off
|
|
132
|
+
4. **Power values update** - shows estimated power when ON, 0 when OFF
|
|
133
|
+
5. **Test client runs** for 30+ seconds without errors
|
|
134
|
+
6. **Random commands sent** every 10-15 seconds
|
|
135
|
+
|
|
136
|
+
### **❌ Common Issues:**
|
|
137
|
+
|
|
138
|
+
1. **Connection refused**
|
|
139
|
+
- Server not running
|
|
140
|
+
- Wrong port (use 5002 from config)
|
|
141
|
+
- Check firewall
|
|
142
|
+
|
|
143
|
+
2. **No devices received**
|
|
144
|
+
- Check config.json saved correctly
|
|
145
|
+
- Check server logs for device initialization
|
|
146
|
+
- Verify devices array is not empty
|
|
147
|
+
|
|
148
|
+
3. **Relay control doesn't work**
|
|
149
|
+
- Master not connected (192.168.0.97:5001)
|
|
150
|
+
- Node/Unit don't exist
|
|
151
|
+
- Check server logs for "Node X not found" errors
|
|
152
|
+
|
|
153
|
+
4. **Power always 0**
|
|
154
|
+
- estimatedPower not set in config
|
|
155
|
+
- powerSource not "none"
|
|
156
|
+
- Check device configuration
|
|
157
|
+
|
|
158
|
+
## Debugging
|
|
159
|
+
|
|
160
|
+
### **VS Code Debugger Breakpoints:**
|
|
161
|
+
|
|
162
|
+
Set breakpoints at:
|
|
163
|
+
- `setupWebSocketServers()` - Verify WebSocket server created
|
|
164
|
+
- `handleDeviceMessage()` - See incoming commands
|
|
165
|
+
- `setDeviceRelay()` - Check relay control logic
|
|
166
|
+
- `getDeviceList()` - Verify device data calculation
|
|
167
|
+
|
|
168
|
+
### **Check Server Logs:**
|
|
169
|
+
|
|
170
|
+
Look for these messages:
|
|
171
|
+
```
|
|
172
|
+
"WebSocket server 0 set up on path /devices"
|
|
173
|
+
"WebSocket client connected on server 0"
|
|
174
|
+
"Setting device 802 (node=3, unit=34) to true"
|
|
175
|
+
"Init 2 Devices -> add units"
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### **Common Debug Scenarios:**
|
|
179
|
+
|
|
180
|
+
1. **Devices not initialized:**
|
|
181
|
+
```
|
|
182
|
+
"** error ** missing device unit: 0x3/0x22 **"
|
|
183
|
+
```
|
|
184
|
+
→ Unit doesn't exist in master
|
|
185
|
+
|
|
186
|
+
2. **WebSocket connection fails:**
|
|
187
|
+
```
|
|
188
|
+
"WebSocket error on server 0: ..."
|
|
189
|
+
```
|
|
190
|
+
→ Check port, network, or code issues
|
|
191
|
+
|
|
192
|
+
3. **Invalid messages:**
|
|
193
|
+
```
|
|
194
|
+
"Invalid WebSocket message: ..."
|
|
195
|
+
```
|
|
196
|
+
→ Check message format (must be JSON array)
|
|
197
|
+
|
|
198
|
+
## Next Steps After Testing
|
|
199
|
+
|
|
200
|
+
Once everything works:
|
|
201
|
+
1. ✅ Confirm device control works
|
|
202
|
+
2. ✅ Verify power measurements (estimated)
|
|
203
|
+
3. 🔄 Add real power source (Smappee/P1/Shelly)
|
|
204
|
+
4. 🔄 Configure power channels
|
|
205
|
+
5. 🔄 Test with real measurements
|
|
206
|
+
6. 🔄 Then proceed with Module refactoring
|
|
207
|
+
|
|
208
|
+
## Quick Commands
|
|
209
|
+
|
|
210
|
+
```bash
|
|
211
|
+
# Terminal 1: Start server
|
|
212
|
+
ts-node testHB.ts
|
|
213
|
+
|
|
214
|
+
# Terminal 2: Run test client
|
|
215
|
+
ts-node testWS.ts ws://duotecno-gateway.local/devices
|
|
216
|
+
|
|
217
|
+
# Press Ctrl+C in either terminal to stop
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
Good luck! 🚀
|