iobroker.homewizard 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/LICENSE +21 -0
- package/README.md +190 -0
- package/admin/homewizard.svg +6 -0
- package/admin/i18n/de/translations.json +16 -0
- package/admin/i18n/en/translations.json +16 -0
- package/admin/i18n/es/translations.json +16 -0
- package/admin/i18n/fr/translations.json +16 -0
- package/admin/i18n/it/translations.json +16 -0
- package/admin/i18n/nl/translations.json +16 -0
- package/admin/i18n/pl/translations.json +16 -0
- package/admin/i18n/pt/translations.json +16 -0
- package/admin/i18n/ru/translations.json +16 -0
- package/admin/i18n/uk/translations.json +16 -0
- package/admin/i18n/zh-cn/translations.json +16 -0
- package/admin/jsonConfig.json +99 -0
- package/build/lib/discovery.js +103 -0
- package/build/lib/discovery.js.map +7 -0
- package/build/lib/homewizard-client.js +193 -0
- package/build/lib/homewizard-client.js.map +7 -0
- package/build/lib/state-manager.js +749 -0
- package/build/lib/state-manager.js.map +7 -0
- package/build/lib/types.js +17 -0
- package/build/lib/types.js.map +7 -0
- package/build/lib/websocket-client.js +151 -0
- package/build/lib/websocket-client.js.map +7 -0
- package/build/main.js +441 -0
- package/build/main.js.map +7 -0
- package/io-package.json +136 -0
- package/package.json +77 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 krobi <krobi@power-dreams.com>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# ioBroker.homewizard
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/iobroker.homewizard)
|
|
4
|
+

|
|
5
|
+

|
|
6
|
+
[](LICENSE)
|
|
7
|
+
[](https://www.npmjs.com/package/iobroker.homewizard)
|
|
8
|
+

|
|
9
|
+
[](https://ko-fi.com/krobipd)
|
|
10
|
+
[](https://paypal.me/krobipd)
|
|
11
|
+
|
|
12
|
+
<img src="https://raw.githubusercontent.com/krobipd/ioBroker.homewizard/main/admin/homewizard.svg" width="100" />
|
|
13
|
+
|
|
14
|
+
Real-time energy monitoring from HomeWizard devices via API v2 with WebSocket push (~1 update/second).
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Features
|
|
19
|
+
|
|
20
|
+
- **WebSocket push** for real-time energy data (~1 update per second)
|
|
21
|
+
- **Automatic device discovery** via mDNS (zero configuration)
|
|
22
|
+
- **Hue-style pairing** — press the button on the device to connect
|
|
23
|
+
- **Multi-device support** — manage all HomeWizard devices in one adapter instance
|
|
24
|
+
- **Battery control** — manage HomeWizard Plug-In Batteries (mode, permissions)
|
|
25
|
+
- **System control** — LED brightness, cloud toggle, reboot, identify
|
|
26
|
+
- **REST fallback** — automatic polling when WebSocket is unavailable
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Requirements
|
|
31
|
+
|
|
32
|
+
- **Node.js >= 20**
|
|
33
|
+
- **ioBroker js-controller >= 7.0.0**
|
|
34
|
+
- **ioBroker Admin >= 7.6.20**
|
|
35
|
+
- **HomeWizard device with API v2 support** (firmware 4.x+ with local API enabled)
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Supported Devices
|
|
40
|
+
|
|
41
|
+
| Device | Product Type | WebSocket | Battery Control |
|
|
42
|
+
|--------|-------------|-----------|-----------------|
|
|
43
|
+
| P1 Meter | HWE-P1 | Yes | Yes (as controller) |
|
|
44
|
+
| kWh Meter 1-Phase | HWE-KWH1 / SDM230 | Yes | Yes (as controller) |
|
|
45
|
+
| kWh Meter 3-Phase | HWE-KWH3 / SDM630 | Yes | Yes (as controller) |
|
|
46
|
+
| Plug-In Battery | HWE-BAT | Yes | Controlled via P1/kWh |
|
|
47
|
+
|
|
48
|
+
> **Note:** Energy Socket (HWE-SKT) and Watermeter (HWE-WTR) only support API v1 and are not yet supported. Support will be added when HomeWizard releases API v2 for these devices.
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
Devices are added via the **pairing mode**, not manually:
|
|
55
|
+
|
|
56
|
+
1. Open the **Objects** tab in ioBroker Admin
|
|
57
|
+
2. Set `homewizard.0.startPairing` to `true`
|
|
58
|
+
3. **Press the physical button** on your HomeWizard device within 60 seconds
|
|
59
|
+
4. The device is discovered automatically and appears in the adapter settings
|
|
60
|
+
|
|
61
|
+
The Admin UI shows all paired devices. You can update the IP address if a device gets a new one.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## State Tree
|
|
66
|
+
|
|
67
|
+
```
|
|
68
|
+
homewizard.0.
|
|
69
|
+
├── info.connection — Overall connection status (bool)
|
|
70
|
+
├── startPairing — Activate pairing mode (button)
|
|
71
|
+
└── {productType}_{serial}/ — e.g. hwe-p1_5c2fafaabbcc
|
|
72
|
+
├── info/
|
|
73
|
+
│ ├── productName — Device name (string)
|
|
74
|
+
│ ├── productType — Product type (string)
|
|
75
|
+
│ ├── firmware — Firmware version (string)
|
|
76
|
+
│ ├── connected — WebSocket connection status (bool)
|
|
77
|
+
│ ├── wifi_rssi_db — WiFi signal strength (number, dB)
|
|
78
|
+
│ └── uptime_s — Device uptime (number, s)
|
|
79
|
+
├── power_w — Total power (number, W)
|
|
80
|
+
├─�� power_l1_w .. l3_w — Power per phase (number, W)
|
|
81
|
+
├── voltage_l1_v .. l3_v — Voltage per phase (number, V)
|
|
82
|
+
├── current_l1_a .. l3_a — Current per phase (number, A)
|
|
83
|
+
├── frequency_hz — Grid frequency (number, Hz)
|
|
84
|
+
├── energy_import_kwh — Total import (number, kWh)
|
|
85
|
+
├── energy_import_t1..t4_kwh — Import per tariff (number, kWh)
|
|
86
|
+
├── energy_export_kwh — Total export (number, kWh)
|
|
87
|
+
├── energy_export_t1..t4_kwh — Export per tariff (number, kWh)
|
|
88
|
+
├── tariff — Active tariff (number)
|
|
89
|
+
├── quality/ — Power quality counters
|
|
90
|
+
│ ├── voltage_sag_l1..l3_count
|
|
91
|
+
│ ├── voltage_swell_l1..l3_count
|
|
92
|
+
│ ├── power_fail_count
|
|
93
|
+
│ └── long_power_fail_count
|
|
94
|
+
├── external/ — External meters (gas, water, heat)
|
|
95
|
+
│ └── {type}_{id}/
|
|
96
|
+
│ ├── value — Meter reading (number)
|
|
97
|
+
│ ���── unit — Unit (string)
|
|
98
|
+
│ └── timestamp — Last update (string)
|
|
99
|
+
├── battery/ — Battery control (if batteries connected)
|
|
100
|
+
│ ├── mode — zero / to_full / standby (string, R/W)
|
|
101
|
+
│ ├── permissions — JSON array (string, R/W)
|
|
102
|
+
│ ├── battery_count — Connected batteries (number)
|
|
103
|
+
│ ├── power_w — Battery power (number, W)
|
|
104
|
+
│ ├── target_power_w — Target power (number, W)
|
|
105
|
+
│ ├── max_consumption_w — Max consumption (number, W)
|
|
106
|
+
│ └── max_production_w — Max production (number, W)
|
|
107
|
+
└── system/ — System settings
|
|
108
|
+
├── cloud_enabled — Cloud communication (bool, R/W)
|
|
109
|
+
├── status_led_brightness_pct — LED brightness 0-100 (number, R/W)
|
|
110
|
+
├── api_v1_enabled — Legacy API v1 (bool, R/W)
|
|
111
|
+
├── reboot — Reboot device (button)
|
|
112
|
+
└── identify — Blink LED (button)
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
> States are created dynamically based on what the device reports. Not all devices have all states.
|
|
116
|
+
|
|
117
|
+
---
|
|
118
|
+
|
|
119
|
+
## Troubleshooting
|
|
120
|
+
|
|
121
|
+
### Device not found during pairing
|
|
122
|
+
- Make sure the device is on the same network/VLAN as the ioBroker server
|
|
123
|
+
- Verify that **local API** is enabled in the HomeWizard app (Settings > Meters > your device > Local API)
|
|
124
|
+
- Check that multicast/mDNS traffic is not blocked by your router/firewall
|
|
125
|
+
|
|
126
|
+
### WebSocket keeps disconnecting
|
|
127
|
+
- Check WiFi signal strength (`info.wifi_rssi_db`) — consider moving the device closer to the router
|
|
128
|
+
- The adapter automatically reconnects with exponential backoff and falls back to REST polling
|
|
129
|
+
|
|
130
|
+
### Token invalid after factory reset
|
|
131
|
+
- Remove the device from the adapter settings and pair again
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## Changelog
|
|
136
|
+
|
|
137
|
+
### 0.1.0 (2026-04-04)
|
|
138
|
+
- Initial release
|
|
139
|
+
- HomeWizard API v2 with Bearer Token authentication
|
|
140
|
+
- WebSocket push for real-time energy data
|
|
141
|
+
- mDNS device discovery
|
|
142
|
+
- Hue-style multi-device pairing
|
|
143
|
+
- Battery control and system settings
|
|
144
|
+
- REST fallback when WebSocket unavailable
|
|
145
|
+
|
|
146
|
+
Older changelog: [CHANGELOG.md](CHANGELOG.md)
|
|
147
|
+
|
|
148
|
+
---
|
|
149
|
+
|
|
150
|
+
## Support
|
|
151
|
+
|
|
152
|
+
- [ioBroker Forum](https://forum.iobroker.net/)
|
|
153
|
+
- [GitHub Issues](https://github.com/krobipd/ioBroker.homewizard/issues)
|
|
154
|
+
|
|
155
|
+
### Support Development
|
|
156
|
+
|
|
157
|
+
This adapter is free and open source. If you find it useful, consider buying me a coffee:
|
|
158
|
+
|
|
159
|
+
[](https://ko-fi.com/krobipd)
|
|
160
|
+
[](https://paypal.me/krobipd)
|
|
161
|
+
|
|
162
|
+
---
|
|
163
|
+
|
|
164
|
+
## License
|
|
165
|
+
|
|
166
|
+
MIT License
|
|
167
|
+
|
|
168
|
+
Copyright (c) 2026 krobi <krobi@power-dreams.com>
|
|
169
|
+
|
|
170
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
171
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
172
|
+
in the Software without restriction, including without limitation the rights
|
|
173
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
174
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
175
|
+
furnished to do so, subject to the following conditions:
|
|
176
|
+
|
|
177
|
+
The above copyright notice and this permission notice shall be included in all
|
|
178
|
+
copies or substantial portions of the Software.
|
|
179
|
+
|
|
180
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
181
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
182
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
183
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
184
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
185
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
186
|
+
SOFTWARE.
|
|
187
|
+
|
|
188
|
+
---
|
|
189
|
+
|
|
190
|
+
*Developed with assistance from Claude.ai*
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="100" height="100">
|
|
2
|
+
<circle cx="50" cy="50" r="48" fill="#00B4D8" stroke="#0077B6" stroke-width="2"/>
|
|
3
|
+
<path d="M30 65 L50 25 L70 65" fill="none" stroke="#FFFFFF" stroke-width="6" stroke-linecap="round" stroke-linejoin="round"/>
|
|
4
|
+
<line x1="38" y1="50" x2="62" y2="50" stroke="#FFFFFF" stroke-width="6" stroke-linecap="round"/>
|
|
5
|
+
<line x1="50" y1="65" x2="50" y2="80" stroke="#FFFFFF" stroke-width="6" stroke-linecap="round"/>
|
|
6
|
+
</svg>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Gekoppelte Geräte",
|
|
3
|
+
"devicesInfo": "Geräte werden automatisch über den Pairing-Modus hinzugefügt. Verwende den Datenpunkt 'startPairing' im Objekte-Tab, um ein neues Gerät zu koppeln. Die IP-Adresse kann hier aktualisiert werden, falls sich diese ändert.",
|
|
4
|
+
"labelDevices": "Geräte",
|
|
5
|
+
"colProductName": "Name",
|
|
6
|
+
"colProductType": "Typ",
|
|
7
|
+
"colSerial": "Seriennummer",
|
|
8
|
+
"colIP": "IP-Adresse",
|
|
9
|
+
"colToken": "Token",
|
|
10
|
+
"headerPairing": "Kopplung",
|
|
11
|
+
"pairingInfo": "Um ein neues Gerät hinzuzufügen: Setze den Datenpunkt 'startPairing' auf true und drücke dann innerhalb von 60 Sekunden den physischen Knopf am HomeWizard-Gerät. Das Gerät wird automatisch erkannt und zur Liste hinzugefügt.",
|
|
12
|
+
"supportHeader": "Unterstützung",
|
|
13
|
+
"aboutInfo": "Dieser Adapter ist kostenlos und Open Source. Wenn er dir nützlich ist, erwäge die Entwicklung zu unterstützen:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Paired Devices",
|
|
3
|
+
"devicesInfo": "Devices are added automatically via the pairing mode. Use the 'startPairing' data point in the Objects tab to pair a new device. You can update the IP address here if a device gets a new one.",
|
|
4
|
+
"labelDevices": "Devices",
|
|
5
|
+
"colProductName": "Name",
|
|
6
|
+
"colProductType": "Type",
|
|
7
|
+
"colSerial": "Serial",
|
|
8
|
+
"colIP": "IP Address",
|
|
9
|
+
"colToken": "Token",
|
|
10
|
+
"headerPairing": "Pairing",
|
|
11
|
+
"pairingInfo": "To add a new device: Set the 'startPairing' data point to true, then press the physical button on your HomeWizard device within 60 seconds. The device will be discovered automatically and added to the list above.",
|
|
12
|
+
"supportHeader": "Support",
|
|
13
|
+
"aboutInfo": "This adapter is free and open source. If you find it useful, consider supporting the development:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Dispositivos emparejados",
|
|
3
|
+
"devicesInfo": "Los dispositivos se añaden automáticamente a través del modo de emparejamiento. Usa el punto de datos 'startPairing' en la pestaña Objetos para emparejar un nuevo dispositivo. La dirección IP se puede actualizar aquí si cambia.",
|
|
4
|
+
"labelDevices": "Dispositivos",
|
|
5
|
+
"colProductName": "Nombre",
|
|
6
|
+
"colProductType": "Tipo",
|
|
7
|
+
"colSerial": "Número de serie",
|
|
8
|
+
"colIP": "Dirección IP",
|
|
9
|
+
"colToken": "Token",
|
|
10
|
+
"headerPairing": "Emparejamiento",
|
|
11
|
+
"pairingInfo": "Para añadir un dispositivo: establece el punto de datos 'startPairing' en true y luego presiona el botón físico en tu dispositivo HomeWizard dentro de 60 segundos. El dispositivo se descubrirá automáticamente.",
|
|
12
|
+
"supportHeader": "Apoyo",
|
|
13
|
+
"aboutInfo": "Este adaptador es gratuito y de código abierto. Si te resulta útil, considera apoyar el desarrollo:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Appareils appairés",
|
|
3
|
+
"devicesInfo": "Les appareils sont ajoutés automatiquement via le mode d'appairage. Utilisez le point de données 'startPairing' dans l'onglet Objets pour appairer un nouvel appareil. L'adresse IP peut être mise à jour ici si elle change.",
|
|
4
|
+
"labelDevices": "Appareils",
|
|
5
|
+
"colProductName": "Nom",
|
|
6
|
+
"colProductType": "Type",
|
|
7
|
+
"colSerial": "Numéro de série",
|
|
8
|
+
"colIP": "Adresse IP",
|
|
9
|
+
"colToken": "Jeton",
|
|
10
|
+
"headerPairing": "Appairage",
|
|
11
|
+
"pairingInfo": "Pour ajouter un appareil : définissez le point de données 'startPairing' sur true, puis appuyez sur le bouton physique de votre appareil HomeWizard dans les 60 secondes. L'appareil sera découvert automatiquement.",
|
|
12
|
+
"supportHeader": "Soutien",
|
|
13
|
+
"aboutInfo": "Cet adaptateur est gratuit et open source. Si vous le trouvez utile, envisagez de soutenir le développement :",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Dispositivi associati",
|
|
3
|
+
"devicesInfo": "I dispositivi vengono aggiunti automaticamente tramite la modalità di associazione. Usa il punto dati 'startPairing' nella scheda Oggetti per associare un nuovo dispositivo. L'indirizzo IP può essere aggiornato qui se cambia.",
|
|
4
|
+
"labelDevices": "Dispositivi",
|
|
5
|
+
"colProductName": "Nome",
|
|
6
|
+
"colProductType": "Tipo",
|
|
7
|
+
"colSerial": "Numero di serie",
|
|
8
|
+
"colIP": "Indirizzo IP",
|
|
9
|
+
"colToken": "Token",
|
|
10
|
+
"headerPairing": "Associazione",
|
|
11
|
+
"pairingInfo": "Per aggiungere un dispositivo: imposta il punto dati 'startPairing' su true, poi premi il pulsante fisico sul dispositivo HomeWizard entro 60 secondi. Il dispositivo verrà scoperto automaticamente.",
|
|
12
|
+
"supportHeader": "Supporto",
|
|
13
|
+
"aboutInfo": "Questo adattatore è gratuito e open source. Se lo trovi utile, considera di supportare lo sviluppo:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Gekoppelde apparaten",
|
|
3
|
+
"devicesInfo": "Apparaten worden automatisch toegevoegd via de koppelmodus. Gebruik het datapunt 'startPairing' in het tabblad Objecten om een nieuw apparaat te koppelen. Het IP-adres kan hier worden bijgewerkt als dit verandert.",
|
|
4
|
+
"labelDevices": "Apparaten",
|
|
5
|
+
"colProductName": "Naam",
|
|
6
|
+
"colProductType": "Type",
|
|
7
|
+
"colSerial": "Serienummer",
|
|
8
|
+
"colIP": "IP-adres",
|
|
9
|
+
"colToken": "Token",
|
|
10
|
+
"headerPairing": "Koppelen",
|
|
11
|
+
"pairingInfo": "Om een apparaat toe te voegen: zet het datapunt 'startPairing' op true en druk vervolgens binnen 60 seconden op de fysieke knop op je HomeWizard-apparaat. Het apparaat wordt automatisch gevonden en toegevoegd.",
|
|
12
|
+
"supportHeader": "Ondersteuning",
|
|
13
|
+
"aboutInfo": "Deze adapter is gratis en open source. Als je het nuttig vindt, overweeg dan de ontwikkeling te steunen:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Sparowane urządzenia",
|
|
3
|
+
"devicesInfo": "Urządzenia są dodawane automatycznie przez tryb parowania. Użyj punktu danych 'startPairing' w zakładce Obiekty, aby sparować nowe urządzenie. Adres IP można zaktualizować tutaj, jeśli się zmieni.",
|
|
4
|
+
"labelDevices": "Urządzenia",
|
|
5
|
+
"colProductName": "Nazwa",
|
|
6
|
+
"colProductType": "Typ",
|
|
7
|
+
"colSerial": "Numer seryjny",
|
|
8
|
+
"colIP": "Adres IP",
|
|
9
|
+
"colToken": "Token",
|
|
10
|
+
"headerPairing": "Parowanie",
|
|
11
|
+
"pairingInfo": "Aby dodać urządzenie: ustaw punkt danych 'startPairing' na true, a następnie naciśnij fizyczny przycisk na urządzeniu HomeWizard w ciągu 60 sekund. Urządzenie zostanie wykryte automatycznie.",
|
|
12
|
+
"supportHeader": "Wsparcie",
|
|
13
|
+
"aboutInfo": "Ten adapter jest darmowy i otwartoźródłowy. Jeśli uważasz go za przydatny, rozważ wsparcie rozwoju:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Dispositivos emparelhados",
|
|
3
|
+
"devicesInfo": "Os dispositivos são adicionados automaticamente através do modo de emparelhamento. Use o ponto de dados 'startPairing' na aba Objetos para emparelhar um novo dispositivo. O endereço IP pode ser atualizado aqui se mudar.",
|
|
4
|
+
"labelDevices": "Dispositivos",
|
|
5
|
+
"colProductName": "Nome",
|
|
6
|
+
"colProductType": "Tipo",
|
|
7
|
+
"colSerial": "Número de série",
|
|
8
|
+
"colIP": "Endereço IP",
|
|
9
|
+
"colToken": "Token",
|
|
10
|
+
"headerPairing": "Emparelhamento",
|
|
11
|
+
"pairingInfo": "Para adicionar um dispositivo: defina o ponto de dados 'startPairing' como true e pressione o botão físico no dispositivo HomeWizard dentro de 60 segundos. O dispositivo será descoberto automaticamente.",
|
|
12
|
+
"supportHeader": "Apoio",
|
|
13
|
+
"aboutInfo": "Este adaptador é gratuito e de código aberto. Se você achar útil, considere apoiar o desenvolvimento:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Сопряженные устройства",
|
|
3
|
+
"devicesInfo": "Устройства добавляются автоматически через режим сопряжения. Используйте точку данных 'startPairing' на вкладке объектов для добавления нового устройства. IP-адрес можно обновить здесь, если он изменился.",
|
|
4
|
+
"labelDevices": "Устройства",
|
|
5
|
+
"colProductName": "Имя",
|
|
6
|
+
"colProductType": "Тип",
|
|
7
|
+
"colSerial": "Серийный номер",
|
|
8
|
+
"colIP": "IP-адрес",
|
|
9
|
+
"colToken": "Токен",
|
|
10
|
+
"headerPairing": "Сопряжение",
|
|
11
|
+
"pairingInfo": "Чтобы добавить устройство: установите точку данных 'startPairing' в true, затем нажмите физическую кнопку на устройстве HomeWizard в течение 60 секунд. Устройство будет обнаружено автоматически.",
|
|
12
|
+
"supportHeader": "Поддержка",
|
|
13
|
+
"aboutInfo": "Этот адаптер бесплатный и с открытым исходным кодом. Если он вам полезен, рассмотрите поддержку разработки:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "Сполучені пристрої",
|
|
3
|
+
"devicesInfo": "Пристрої додаються автоматично через режим сполучення. Використовуйте точку даних 'startPairing' на вкладці Об'єкти для сполучення нового пристрою. IP-адресу можна оновити тут, якщо вона змінилася.",
|
|
4
|
+
"labelDevices": "Пристрої",
|
|
5
|
+
"colProductName": "Назва",
|
|
6
|
+
"colProductType": "Тип",
|
|
7
|
+
"colSerial": "Серійний номер",
|
|
8
|
+
"colIP": "IP-адреса",
|
|
9
|
+
"colToken": "Токен",
|
|
10
|
+
"headerPairing": "Сполучення",
|
|
11
|
+
"pairingInfo": "Щоб додати пристрій: встановіть точку даних 'startPairing' на true, потім натисніть фізичну кнопку на пристрої HomeWizard протягом 60 секунд. Пристрій буде виявлено автоматично.",
|
|
12
|
+
"supportHeader": "Підтримка",
|
|
13
|
+
"aboutInfo": "Цей адаптер безкоштовний і з відкритим кодом. Якщо він вам корисний, розгляньте підтримку розробки:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"headerDevices": "已配对设备",
|
|
3
|
+
"devicesInfo": "设备通过配对模式自动添加。使用对象选项卡中的 'startPairing' 数据点来配对新设备。如果设备的 IP 地址发生变化,可以在此处更新。",
|
|
4
|
+
"labelDevices": "设备",
|
|
5
|
+
"colProductName": "名称",
|
|
6
|
+
"colProductType": "类型",
|
|
7
|
+
"colSerial": "序列号",
|
|
8
|
+
"colIP": "IP 地址",
|
|
9
|
+
"colToken": "令牌",
|
|
10
|
+
"headerPairing": "配对",
|
|
11
|
+
"pairingInfo": "要添加新设备:将 'startPairing' 数据点设置为 true,然后在 60 秒内按下 HomeWizard 设备上的物理按钮。设备将被自动发现并添加到上面的列表中。",
|
|
12
|
+
"supportHeader": "支持",
|
|
13
|
+
"aboutInfo": "此适配器免费且开源。如果您觉得有用,请考虑支持开发:",
|
|
14
|
+
"donateKofi": "Ko-fi",
|
|
15
|
+
"donatePaypal": "PayPal"
|
|
16
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
{
|
|
2
|
+
"i18n": true,
|
|
3
|
+
"type": "panel",
|
|
4
|
+
"items": {
|
|
5
|
+
"_headerDevices": {
|
|
6
|
+
"type": "header",
|
|
7
|
+
"text": "headerDevices",
|
|
8
|
+
"size": 3
|
|
9
|
+
},
|
|
10
|
+
"_devicesInfo": {
|
|
11
|
+
"type": "staticText",
|
|
12
|
+
"text": "devicesInfo",
|
|
13
|
+
"style": { "fontSize": 14, "marginBottom": 16 }
|
|
14
|
+
},
|
|
15
|
+
"devices": {
|
|
16
|
+
"type": "table",
|
|
17
|
+
"label": "labelDevices",
|
|
18
|
+
"sm": 12,
|
|
19
|
+
"items": [
|
|
20
|
+
{
|
|
21
|
+
"type": "text",
|
|
22
|
+
"attr": "productName",
|
|
23
|
+
"title": "colProductName",
|
|
24
|
+
"width": "20%",
|
|
25
|
+
"readOnly": true
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
"type": "text",
|
|
29
|
+
"attr": "productType",
|
|
30
|
+
"title": "colProductType",
|
|
31
|
+
"width": "15%",
|
|
32
|
+
"readOnly": true
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
"type": "text",
|
|
36
|
+
"attr": "serial",
|
|
37
|
+
"title": "colSerial",
|
|
38
|
+
"width": "20%",
|
|
39
|
+
"readOnly": true
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"type": "text",
|
|
43
|
+
"attr": "ip",
|
|
44
|
+
"title": "colIP",
|
|
45
|
+
"width": "20%"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"type": "text",
|
|
49
|
+
"attr": "token",
|
|
50
|
+
"title": "colToken",
|
|
51
|
+
"width": "25%",
|
|
52
|
+
"readOnly": true
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
"noDelete": false
|
|
56
|
+
},
|
|
57
|
+
"_headerPairing": {
|
|
58
|
+
"newLine": true,
|
|
59
|
+
"type": "header",
|
|
60
|
+
"text": "headerPairing",
|
|
61
|
+
"size": 4
|
|
62
|
+
},
|
|
63
|
+
"_pairingInfo": {
|
|
64
|
+
"type": "staticText",
|
|
65
|
+
"text": "pairingInfo",
|
|
66
|
+
"style": { "fontSize": 14, "marginBottom": 16 }
|
|
67
|
+
},
|
|
68
|
+
"_supportHeader": {
|
|
69
|
+
"newLine": true,
|
|
70
|
+
"type": "header",
|
|
71
|
+
"text": "supportHeader",
|
|
72
|
+
"size": 5
|
|
73
|
+
},
|
|
74
|
+
"_aboutInfo": {
|
|
75
|
+
"type": "staticText",
|
|
76
|
+
"text": "aboutInfo",
|
|
77
|
+
"xs": 12, "sm": 12, "md": 12, "lg": 12, "xl": 12,
|
|
78
|
+
"style": { "fontSize": 14, "marginBottom": 16 }
|
|
79
|
+
},
|
|
80
|
+
"_kofiLink": {
|
|
81
|
+
"type": "staticLink",
|
|
82
|
+
"href": "https://ko-fi.com/krobipd",
|
|
83
|
+
"label": "donateKofi",
|
|
84
|
+
"button": true,
|
|
85
|
+
"variant": "outlined",
|
|
86
|
+
"color": "primary",
|
|
87
|
+
"xs": 12, "sm": 6, "md": 4, "lg": 4, "xl": 4
|
|
88
|
+
},
|
|
89
|
+
"_paypalLink": {
|
|
90
|
+
"type": "staticLink",
|
|
91
|
+
"href": "https://paypal.me/krobipd",
|
|
92
|
+
"label": "donatePaypal",
|
|
93
|
+
"button": true,
|
|
94
|
+
"variant": "outlined",
|
|
95
|
+
"color": "primary",
|
|
96
|
+
"xs": 12, "sm": 6, "md": 4, "lg": 4, "xl": 4
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var discovery_exports = {};
|
|
30
|
+
__export(discovery_exports, {
|
|
31
|
+
HomeWizardDiscovery: () => HomeWizardDiscovery
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(discovery_exports);
|
|
34
|
+
var import_bonjour_service = __toESM(require("bonjour-service"));
|
|
35
|
+
class HomeWizardDiscovery {
|
|
36
|
+
bonjour = null;
|
|
37
|
+
browser = null;
|
|
38
|
+
log;
|
|
39
|
+
/**
|
|
40
|
+
* @param log Logger interface
|
|
41
|
+
* @param log.debug Debug log function
|
|
42
|
+
* @param log.warn Warning log function
|
|
43
|
+
*/
|
|
44
|
+
constructor(log) {
|
|
45
|
+
this.log = log;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Start scanning for HomeWizard devices
|
|
49
|
+
*
|
|
50
|
+
* @param callback Called for each discovered device
|
|
51
|
+
*/
|
|
52
|
+
start(callback) {
|
|
53
|
+
this.stop();
|
|
54
|
+
this.bonjour = new import_bonjour_service.default();
|
|
55
|
+
this.log.debug("mDNS: browsing for _hwenergy._tcp");
|
|
56
|
+
this.browser = this.bonjour.find(
|
|
57
|
+
{ type: "hwenergy", protocol: "tcp" },
|
|
58
|
+
(service) => {
|
|
59
|
+
const device = this.parseService(service);
|
|
60
|
+
if (device) {
|
|
61
|
+
this.log.debug(
|
|
62
|
+
`mDNS: found ${device.name} (${device.productType}) at ${device.ip}`
|
|
63
|
+
);
|
|
64
|
+
callback(device);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
);
|
|
68
|
+
}
|
|
69
|
+
/** Stop scanning */
|
|
70
|
+
stop() {
|
|
71
|
+
if (this.browser) {
|
|
72
|
+
this.browser.stop();
|
|
73
|
+
this.browser = null;
|
|
74
|
+
}
|
|
75
|
+
if (this.bonjour) {
|
|
76
|
+
this.bonjour.destroy();
|
|
77
|
+
this.bonjour = null;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Parse a Bonjour service into a DiscoveredDevice
|
|
82
|
+
*
|
|
83
|
+
* @param service Bonjour service record
|
|
84
|
+
*/
|
|
85
|
+
parseService(service) {
|
|
86
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
87
|
+
const ip = (_a = service.addresses) == null ? void 0 : _a.find((addr) => addr.includes("."));
|
|
88
|
+
if (!ip) {
|
|
89
|
+
this.log.debug(`mDNS: no IPv4 address for ${service.name}`);
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
const txt = service.txt;
|
|
93
|
+
const productType = (_c = (_b = txt == null ? void 0 : txt.product_type) != null ? _b : txt == null ? void 0 : txt.type) != null ? _c : "unknown";
|
|
94
|
+
const serial = (_e = (_d = txt == null ? void 0 : txt.serial) != null ? _d : service.name) != null ? _e : "unknown";
|
|
95
|
+
const name = (_g = (_f = txt == null ? void 0 : txt.product_name) != null ? _f : service.name) != null ? _g : productType;
|
|
96
|
+
return { ip, productType, serial, name };
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
100
|
+
0 && (module.exports = {
|
|
101
|
+
HomeWizardDiscovery
|
|
102
|
+
});
|
|
103
|
+
//# sourceMappingURL=discovery.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/lib/discovery.ts"],
|
|
4
|
+
"sourcesContent": ["import Bonjour, { type Service } from \"bonjour-service\";\nimport type { DiscoveredDevice } from \"./types\";\n\n/** Callback for discovered devices */\nexport type DiscoveryCallback = (device: DiscoveredDevice) => void;\n\n/**\n * mDNS discovery for HomeWizard Energy devices.\n * Browses for `_hwenergy._tcp` services on the local network.\n */\nexport class HomeWizardDiscovery {\n private bonjour: Bonjour | null = null;\n private browser: ReturnType<Bonjour[\"find\"]> | null = null;\n private readonly log: {\n debug: (msg: string) => void;\n warn: (msg: string) => void;\n };\n\n /**\n * @param log Logger interface\n * @param log.debug Debug log function\n * @param log.warn Warning log function\n */\n constructor(log: {\n debug: (msg: string) => void;\n warn: (msg: string) => void;\n }) {\n this.log = log;\n }\n\n /**\n * Start scanning for HomeWizard devices\n *\n * @param callback Called for each discovered device\n */\n start(callback: DiscoveryCallback): void {\n this.stop();\n\n this.bonjour = new Bonjour();\n this.log.debug(\"mDNS: browsing for _hwenergy._tcp\");\n\n this.browser = this.bonjour.find(\n { type: \"hwenergy\", protocol: \"tcp\" },\n (service: Service) => {\n const device = this.parseService(service);\n if (device) {\n this.log.debug(\n `mDNS: found ${device.name} (${device.productType}) at ${device.ip}`,\n );\n callback(device);\n }\n },\n );\n }\n\n /** Stop scanning */\n stop(): void {\n if (this.browser) {\n this.browser.stop();\n this.browser = null;\n }\n if (this.bonjour) {\n this.bonjour.destroy();\n this.bonjour = null;\n }\n }\n\n /**\n * Parse a Bonjour service into a DiscoveredDevice\n *\n * @param service Bonjour service record\n */\n private parseService(service: Service): DiscoveredDevice | null {\n // IPv4 address\n const ip = service.addresses?.find((addr) => addr.includes(\".\"));\n if (!ip) {\n this.log.debug(`mDNS: no IPv4 address for ${service.name}`);\n return null;\n }\n\n // TXT records contain product_type, serial, etc.\n const txt = service.txt as Record<string, string> | undefined;\n const productType = txt?.product_type ?? txt?.type ?? \"unknown\";\n const serial = txt?.serial ?? service.name ?? \"unknown\";\n const name = txt?.product_name ?? service.name ?? productType;\n\n return { ip, productType, serial, name };\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,6BAAsC;AAU/B,MAAM,oBAAoB;AAAA,EACvB,UAA0B;AAAA,EAC1B,UAA8C;AAAA,EACrC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUjB,YAAY,KAGT;AACD,SAAK,MAAM;AAAA,EACb;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,UAAmC;AACvC,SAAK,KAAK;AAEV,SAAK,UAAU,IAAI,uBAAAA,QAAQ;AAC3B,SAAK,IAAI,MAAM,mCAAmC;AAElD,SAAK,UAAU,KAAK,QAAQ;AAAA,MAC1B,EAAE,MAAM,YAAY,UAAU,MAAM;AAAA,MACpC,CAAC,YAAqB;AACpB,cAAM,SAAS,KAAK,aAAa,OAAO;AACxC,YAAI,QAAQ;AACV,eAAK,IAAI;AAAA,YACP,eAAe,OAAO,IAAI,KAAK,OAAO,WAAW,QAAQ,OAAO,EAAE;AAAA,UACpE;AACA,mBAAS,MAAM;AAAA,QACjB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,OAAa;AACX,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,KAAK;AAClB,WAAK,UAAU;AAAA,IACjB;AACA,QAAI,KAAK,SAAS;AAChB,WAAK,QAAQ,QAAQ;AACrB,WAAK,UAAU;AAAA,IACjB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,aAAa,SAA2C;AAxElE;AA0EI,UAAM,MAAK,aAAQ,cAAR,mBAAmB,KAAK,CAAC,SAAS,KAAK,SAAS,GAAG;AAC9D,QAAI,CAAC,IAAI;AACP,WAAK,IAAI,MAAM,6BAA6B,QAAQ,IAAI,EAAE;AAC1D,aAAO;AAAA,IACT;AAGA,UAAM,MAAM,QAAQ;AACpB,UAAM,eAAc,sCAAK,iBAAL,YAAqB,2BAAK,SAA1B,YAAkC;AACtD,UAAM,UAAS,sCAAK,WAAL,YAAe,QAAQ,SAAvB,YAA+B;AAC9C,UAAM,QAAO,sCAAK,iBAAL,YAAqB,QAAQ,SAA7B,YAAqC;AAElD,WAAO,EAAE,IAAI,aAAa,QAAQ,KAAK;AAAA,EACzC;AACF;",
|
|
6
|
+
"names": ["Bonjour"]
|
|
7
|
+
}
|