@thecloudseeker/homebridge-skoda 0.1.3 → 0.3.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 +19 -0
- package/README.md +42 -26
- package/config.schema.json +148 -69
- package/dist/accessory/services/battery.d.ts +21 -0
- package/dist/accessory/services/battery.js +38 -1
- package/dist/accessory/services/battery.js.map +1 -1
- package/dist/accessory/services/body.d.ts +5 -6
- package/dist/accessory/services/body.js +45 -8
- package/dist/accessory/services/body.js.map +1 -1
- package/dist/accessory/services/charging.js +31 -13
- package/dist/accessory/services/charging.js.map +1 -1
- package/dist/accessory/services/climate.js +51 -23
- package/dist/accessory/services/climate.js.map +1 -1
- package/dist/accessory/services/common.d.ts +10 -5
- package/dist/accessory/services/common.js +17 -8
- package/dist/accessory/services/common.js.map +1 -1
- package/dist/accessory/vehicleAccessory.d.ts +11 -2
- package/dist/accessory/vehicleAccessory.js +54 -5
- package/dist/accessory/vehicleAccessory.js.map +1 -1
- package/dist/api/client.d.ts +2 -2
- package/dist/api/client.js +8 -6
- package/dist/api/client.js.map +1 -1
- package/dist/api/rateBudget.d.ts +3 -3
- package/dist/api/rateBudget.js +1 -1
- package/dist/config.d.ts +10 -4
- package/dist/config.js +24 -8
- package/dist/config.js.map +1 -1
- package/dist/platform.js +19 -25
- package/dist/platform.js.map +1 -1
- package/dist/vehicle/mapping.d.ts +12 -0
- package/dist/vehicle/mapping.js +42 -0
- package/dist/vehicle/mapping.js.map +1 -1
- package/dist/vehicle/snapshot.js +47 -0
- package/dist/vehicle/snapshot.js.map +1 -1
- package/dist/vehicle/vehicleController.d.ts +30 -10
- package/dist/vehicle/vehicleController.js +92 -30
- package/dist/vehicle/vehicleController.js.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.3.0
|
|
4
|
+
|
|
5
|
+
- **Window heating** as an optional read-only contact sensor, open while the front or rear window heating is on (`features.windowHeating`). The API has no command for it.
|
|
6
|
+
- **Charging plug lock** as an optional contact sensor, closed while the cable is locked (`features.plugLock`).
|
|
7
|
+
- **Clearer settings in the Homebridge UI.** Settings are grouped by topic, each next to the feature it belongs to, and numbers are entered in text fields instead of sliders.
|
|
8
|
+
- **Removed `commandToken` and `commandRefreshDelaySeconds`.** A second API key brings no extra requests, because the rate limit applies per vehicle, and the expected state after a command makes an extra refresh unnecessary. The plugin uses the API key for everything and warns once if the old options are still in the config.
|
|
9
|
+
- **The log lists what your vehicle supports** after the first update, including features that are supported but turned off, with the setting that turns them on.
|
|
10
|
+
- `airConditioningWithoutExternalPower` is a choice of "Keep the vehicle's setting", "Allow" (`"allow"`) and "Do not allow" (`"deny"`). Existing `true` / `false` values keep working.
|
|
11
|
+
|
|
12
|
+
## 0.2.0
|
|
13
|
+
|
|
14
|
+
- **Commands cost one request.** HomeKit keeps the expected state until a regular update carries the vehicle's new report of that part, at most 15 minutes, instead of an extra refresh after every command. With the default polling interval, that leaves 8 instead of about 4 commands per hour. `commandRefreshDelaySeconds` now defaults to `0` (no refresh); set it to 15–600 to keep the old behaviour. If you set it explicitly, nothing changes for you.
|
|
15
|
+
- **Controls follow the vehicle more carefully.** A control is removed only when two updates report its operation as unsupported, so a single odd response no longer costs you its room and automations in the Home app. A command the vehicle rejects as unsupported (`operation-not-supported`) removes its control as well. Disabled functions (`operation-disabled`) keep their control.
|
|
16
|
+
- **Fixed:** services added to or removed from a vehicle that was already in HomeKit were only saved to Homebridge's accessory cache on a clean shutdown. They are now saved right away.
|
|
17
|
+
- **Fixed:** a request the vehicle declined (`429 vehicle-not-accepting-requests`) was not counted against the request budget. The API counts it.
|
|
18
|
+
- **Fuel level** for petrol, diesel, CNG and LPG vehicles, as a battery "Fuel" that cannot be charged, with low battery below `lowBatteryThreshold`. It is on by default, so existing combustion vehicles get the new service after the update. An optional humidity sensor "Fuel Level" mirrors it for automations, also for plug-in hybrids (`features.fuelLevelSensor`).
|
|
19
|
+
- **Lights** as an optional contact sensor, open while the lights are on (`features.lights`).
|
|
20
|
+
- The log shows at startup how many requests per hour polling uses and how many are left for commands.
|
|
21
|
+
|
|
3
22
|
## 0.1.3
|
|
4
23
|
|
|
5
24
|
- The author link on npm points to [eikedreier.com](https://eikedreier.com/).
|
package/README.md
CHANGED
|
@@ -17,12 +17,17 @@ air conditioning, auxiliary heating, "at home" detection, doors, windows and loc
|
|
|
17
17
|
## Features
|
|
18
18
|
|
|
19
19
|
Each vehicle becomes one HomeKit accessory. A service is only created if it is enabled in the
|
|
20
|
-
config **and** the vehicle reports that it supports it.
|
|
20
|
+
config **and** the vehicle reports that it supports it. For the controls, that is the list of
|
|
21
|
+
remote operations the API reports for the vehicle. If two updates report a control as no longer
|
|
22
|
+
supported, or the vehicle rejects a command as unsupported, the service is removed. A single odd
|
|
23
|
+
update or an unreachable API never removes services.
|
|
21
24
|
|
|
22
25
|
| HomeKit service | Shows | Controls | Default |
|
|
23
26
|
| ---------------------------------------------------------------- | -------------------------------------------------------------- | ---------------------------------------------- | ------- |
|
|
24
27
|
| Battery | State of charge, charging state, low battery below a threshold | – | on |
|
|
25
28
|
| Humidity sensor "State of Charge" | State of charge in %, so you can build automations on it | – | off |
|
|
29
|
+
| Battery "Fuel" | Fuel level, low below the threshold (petrol, diesel, CNG, LPG) | – | on |
|
|
30
|
+
| Humidity sensor "Fuel Level" | Fuel level in %, so you can build automations on it | – | off |
|
|
26
31
|
| Outlet "Charging" | _On_ = charging, _Outlet In Use_ = cable plugged in | Start / stop charging | on |
|
|
27
32
|
| Lightbulb "Charge Limit" | Brightness = charging limit (50–100 % in steps of 10) | Set charging limit | on |
|
|
28
33
|
| Heater Cooler "Climate" | Active, heating / cooling, target temperature | Start / stop air conditioning, set temperature | on |
|
|
@@ -31,6 +36,11 @@ config **and** the vehicle reports that it supports it.
|
|
|
31
36
|
| Occupancy sensor "Home" | Parked within a radius around your home | – | on |
|
|
32
37
|
| Contact sensors "Doors", "Windows", "Trunk", "Bonnet", "Sunroof" | Open / closed | – | on |
|
|
33
38
|
| Contact sensor "Locked" | Closed = locked, open = unlocked | – (the API cannot lock or unlock) | on |
|
|
39
|
+
| Contact sensor "Lights" | Open = lights on | – | off |
|
|
40
|
+
| Contact sensor "Window Heating" | Open = front or rear window heating on | – (the API has no command for it) | off |
|
|
41
|
+
| Contact sensor "Plug Locked" | Closed = charging cable locked | – | off |
|
|
42
|
+
|
|
43
|
+
HomeKit has no services for range or mileage, so the plugin does not show them.
|
|
34
44
|
|
|
35
45
|
What the API does **not** offer, and therefore this plugin neither: locking and unlocking, honking
|
|
36
46
|
and flashing, waking the vehicle up, cabin temperature, and push updates.
|
|
@@ -52,8 +62,15 @@ and flashing, waking the vehicle up, cabin temperature, and push updates.
|
|
|
52
62
|
therefore always shows the reported state: after you switch it on in HomeKit it returns to _off_
|
|
53
63
|
once the vehicle has accepted the start (see the log), and it shows _on_ when the ventilation
|
|
54
64
|
was started in the app.
|
|
65
|
+
- **Fuel.** HomeKit has no fuel service, so combustion vehicles show their fuel level as a battery
|
|
66
|
+
that cannot be charged. Low battery uses `lowBatteryThreshold`. Plug-in hybrids keep the
|
|
67
|
+
high-voltage battery in the battery service; their fuel level is available as the "Fuel Level"
|
|
68
|
+
humidity sensor.
|
|
55
69
|
- **Lock.** Exposed as a read-only contact sensor rather than a lock, because the API cannot
|
|
56
70
|
lock or unlock. A lock tile in the Home app would suggest otherwise.
|
|
71
|
+
- **Expected state after a command.** HomeKit shows the expected state right away and keeps it
|
|
72
|
+
until the vehicle reports that part again, at most 15 minutes. If the vehicle reports something
|
|
73
|
+
else, for example because charging could not start, HomeKit shows what the vehicle reports.
|
|
57
74
|
- **Stale data.** If the last successful update is older than three polling intervals, the sensors
|
|
58
75
|
show a fault (_StatusFault_). Battery, outlet, switches and the heater cooler have no fault
|
|
59
76
|
indicator in HomeKit.
|
|
@@ -93,10 +110,6 @@ days before a key expires. Once it has expired, the plugin logs an error and ret
|
|
|
93
110
|
(failed authentication does not count against the rate limit). Renew the key in the app and
|
|
94
111
|
update the config.
|
|
95
112
|
|
|
96
|
-
You may configure a second key for commands only (_Command API key_), for example to keep
|
|
97
|
-
permissions apart. **A second key does not give you more requests**: the rate limit applies per
|
|
98
|
-
vehicle, and both keys share it.
|
|
99
|
-
|
|
100
113
|
## Configuration
|
|
101
114
|
|
|
102
115
|
The easiest way is the Homebridge UI. In `config.json` it looks like this:
|
|
@@ -117,22 +130,20 @@ The easiest way is the Homebridge UI. In `config.json` it looks like this:
|
|
|
117
130
|
}
|
|
118
131
|
```
|
|
119
132
|
|
|
120
|
-
| Option | Default | Description
|
|
121
|
-
| ------------------------------------- | ----------------------- |
|
|
122
|
-
| `name` | `Škoda <last 4 of VIN>` | Accessory name in HomeKit
|
|
123
|
-
| `vin` | – | Vehicle identification number (required)
|
|
124
|
-
| `token` | – | API key (required)
|
|
125
|
-
| `
|
|
126
|
-
| `
|
|
127
|
-
| `home.
|
|
128
|
-
| `
|
|
129
|
-
| `
|
|
130
|
-
| `
|
|
131
|
-
| `
|
|
132
|
-
| `
|
|
133
|
-
| `
|
|
134
|
-
| `auxiliaryHeatingDurationMinutes` | – | Auxiliary heating run time; unset keeps the vehicle setting |
|
|
135
|
-
| `features.*` | see table above | `battery`, `stateOfChargeSensor`, `charging`, `chargingLimit`, `climate`, `auxiliaryHeating`, `activeVentilation`, `presence`, `doors`, `windows`, `trunk`, `bonnet`, `sunroof`, `lock` |
|
|
133
|
+
| Option | Default | Description |
|
|
134
|
+
| ------------------------------------- | ----------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
135
|
+
| `name` | `Škoda <last 4 of VIN>` | Accessory name in HomeKit |
|
|
136
|
+
| `vin` | – | Vehicle identification number (required) |
|
|
137
|
+
| `token` | – | API key (required) |
|
|
138
|
+
| `spin` | – | S-PIN, only needed for the auxiliary heating |
|
|
139
|
+
| `home.lat`, `home.lon` | – | Home coordinates for the "Home" sensor |
|
|
140
|
+
| `home.radiusMeters` | `150` | Radius around home, at least 10 m |
|
|
141
|
+
| `pollingIntervalMinutes` | `5` | Polling interval, at least 4 (see below) |
|
|
142
|
+
| `lowBatteryThreshold` | `20` | Low battery below this state of charge or fuel level (%) |
|
|
143
|
+
| `climateTemperature` | `21` | Cabin temperature (°C) until the vehicle reports one |
|
|
144
|
+
| `airConditioningWithoutExternalPower` | – | `"allow"` or `"deny"` air conditioning from the drive battery when not plugged in; unset keeps the vehicle setting |
|
|
145
|
+
| `auxiliaryHeatingDurationMinutes` | – | Auxiliary heating run time; unset keeps the vehicle setting |
|
|
146
|
+
| `features.*` | see table above | `battery`, `stateOfChargeSensor`, `fuelLevel`, `fuelLevelSensor`, `charging`, `chargingLimit`, `climate`, `auxiliaryHeating`, `activeVentilation`, `presence`, `doors`, `windows`, `trunk`, `bonnet`, `sunroof`, `lock`, `lights`, `windowHeating`, `plugLock` |
|
|
136
147
|
|
|
137
148
|
## Rate limit
|
|
138
149
|
|
|
@@ -144,11 +155,12 @@ The plugin is built around that limit:
|
|
|
144
155
|
|
|
145
156
|
- **One request per update.** A single call returns all vehicle data.
|
|
146
157
|
- **HomeKit never triggers requests.** Opening the Home app reads from the plugin's cache.
|
|
147
|
-
- **Four requests per hour stay free** for commands
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
- **
|
|
151
|
-
|
|
158
|
+
- **Four requests per hour stay free** for commands. That makes 4 minutes the shortest polling
|
|
159
|
+
interval; shorter values are raised with a warning. The default of 5 minutes uses 12 requests
|
|
160
|
+
per hour and leaves 8 for commands. The log shows this split at startup.
|
|
161
|
+
- **A command costs one request.** The vehicle reports new state with a delay, so instead of an
|
|
162
|
+
extra refresh the plugin keeps the expected state until a regular update carries the vehicle's
|
|
163
|
+
new report.
|
|
152
164
|
- **When the budget is used up**, commands are rejected ("No Response" in the Home app) instead of
|
|
153
165
|
being sent, and polling waits until requests are available again.
|
|
154
166
|
- **Errors back off.** On `429` and `503` the plugin waits for `Retry-After`. On other server and
|
|
@@ -175,6 +187,7 @@ suggests, and a command may take a minute or two to show up.
|
|
|
175
187
|
| `rate limit budget exhausted` | Too many commands in the last hour; try again later |
|
|
176
188
|
| `the vehicle declined the request` | The vehicle refused for now (e.g. low battery); try again later |
|
|
177
189
|
| `this function is currently disabled for the vehicle` | Enable the service for the vehicle in the MyŠkoda app |
|
|
190
|
+
| `The vehicle does not support …` | The vehicle rejected the command; its control is removed |
|
|
178
191
|
|
|
179
192
|
## Development
|
|
180
193
|
|
|
@@ -188,6 +201,9 @@ npm run build
|
|
|
188
201
|
|
|
189
202
|
The tests mock the API completely and contain no real keys or vehicle data.
|
|
190
203
|
|
|
204
|
+
Upstream changes worth following (the API, the Python library and the Home Assistant integration)
|
|
205
|
+
are listed in [MAINTAINING.md](MAINTAINING.md).
|
|
206
|
+
|
|
191
207
|
## License
|
|
192
208
|
|
|
193
209
|
[BSD 3-Clause](LICENSE)
|
package/config.schema.json
CHANGED
|
@@ -33,17 +33,12 @@
|
|
|
33
33
|
"title": "API key",
|
|
34
34
|
"type": "string",
|
|
35
35
|
"required": true,
|
|
36
|
-
"description": "API key from the MyŠkoda app. Used for
|
|
37
|
-
},
|
|
38
|
-
"commandToken": {
|
|
39
|
-
"title": "Command API key (optional)",
|
|
40
|
-
"type": "string",
|
|
41
|
-
"description": "Separate key for commands, e.g. with different permissions. Both keys share the vehicle's rate limit, so a second key does not allow more requests."
|
|
36
|
+
"description": "API key from the MyŠkoda app (Profile › Smart Home). Used for reading the vehicle and for commands."
|
|
42
37
|
},
|
|
43
38
|
"spin": {
|
|
44
39
|
"title": "S-PIN (optional)",
|
|
45
40
|
"type": "string",
|
|
46
|
-
"description": "Security PIN of your MyŠkoda account. Only needed
|
|
41
|
+
"description": "Security PIN of your MyŠkoda account. Only needed to start the auxiliary heating; it is sent with each start and never logged."
|
|
47
42
|
},
|
|
48
43
|
"home": {
|
|
49
44
|
"title": "Home location",
|
|
@@ -70,65 +65,83 @@
|
|
|
70
65
|
}
|
|
71
66
|
},
|
|
72
67
|
"pollingIntervalMinutes": {
|
|
73
|
-
"title": "
|
|
68
|
+
"title": "Update interval (minutes)",
|
|
74
69
|
"type": "integer",
|
|
75
70
|
"minimum": 4,
|
|
76
71
|
"maximum": 1440,
|
|
77
72
|
"placeholder": 5,
|
|
78
|
-
"description": "
|
|
79
|
-
},
|
|
80
|
-
"commandRefreshDelaySeconds": {
|
|
81
|
-
"title": "Refresh after command (seconds)",
|
|
82
|
-
"type": "integer",
|
|
83
|
-
"minimum": 15,
|
|
84
|
-
"maximum": 600,
|
|
85
|
-
"placeholder": 90,
|
|
86
|
-
"description": "Delay before the single follow-up refresh after a command."
|
|
73
|
+
"description": "How often the plugin fetches the vehicle's state. At least 4, default 5: the API allows 20 requests per hour, and 4 are kept free for commands."
|
|
87
74
|
},
|
|
88
75
|
"lowBatteryThreshold": {
|
|
89
|
-
"title": "Low battery
|
|
76
|
+
"title": "Low battery / fuel warning below (%)",
|
|
90
77
|
"type": "integer",
|
|
91
78
|
"minimum": 0,
|
|
92
79
|
"maximum": 100,
|
|
93
|
-
"placeholder": 20
|
|
80
|
+
"placeholder": 20,
|
|
81
|
+
"description": "HomeKit shows low battery when the battery or fuel level drops below this value. Default 20."
|
|
94
82
|
},
|
|
95
83
|
"climateTemperature": {
|
|
96
|
-
"title": "Default
|
|
84
|
+
"title": "Default temperature (°C)",
|
|
97
85
|
"type": "number",
|
|
98
86
|
"minimum": 16,
|
|
99
87
|
"maximum": 29.5,
|
|
100
88
|
"multipleOf": 0.5,
|
|
101
89
|
"placeholder": 21,
|
|
102
|
-
"description": "Used until the vehicle reports its own target temperature."
|
|
90
|
+
"description": "Used for the first start until the vehicle reports its own target temperature. 16-29.5 in steps of 0.5, default 21."
|
|
103
91
|
},
|
|
104
92
|
"airConditioningWithoutExternalPower": {
|
|
105
|
-
"title": "
|
|
106
|
-
"type": "
|
|
107
|
-
"
|
|
93
|
+
"title": "Air conditioning when not plugged in",
|
|
94
|
+
"type": "string",
|
|
95
|
+
"oneOf": [
|
|
96
|
+
{
|
|
97
|
+
"title": "Keep the vehicle's setting",
|
|
98
|
+
"enum": ["vehicle"]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
"title": "Allow (uses the drive battery)",
|
|
102
|
+
"enum": ["allow"]
|
|
103
|
+
},
|
|
104
|
+
{
|
|
105
|
+
"title": "Do not allow",
|
|
106
|
+
"enum": ["deny"]
|
|
107
|
+
}
|
|
108
|
+
],
|
|
109
|
+
"placeholder": "vehicle",
|
|
110
|
+
"description": "For electric vehicles: whether the air conditioning may run from the drive battery when no charging cable is connected."
|
|
108
111
|
},
|
|
109
112
|
"auxiliaryHeatingDurationMinutes": {
|
|
110
|
-
"title": "Auxiliary heating
|
|
113
|
+
"title": "Auxiliary heating run time (minutes, optional)",
|
|
111
114
|
"type": "integer",
|
|
112
115
|
"minimum": 1,
|
|
113
116
|
"maximum": 60,
|
|
114
|
-
"description": "Leave empty to use the vehicle
|
|
117
|
+
"description": "1-60. Leave empty to use the run time set in the vehicle."
|
|
115
118
|
},
|
|
116
119
|
"features": {
|
|
117
120
|
"title": "Features",
|
|
118
121
|
"type": "object",
|
|
119
122
|
"properties": {
|
|
120
123
|
"battery": {
|
|
121
|
-
"title": "Battery",
|
|
124
|
+
"title": "Battery (electric and plug-in hybrid)",
|
|
122
125
|
"type": "boolean",
|
|
123
126
|
"default": true
|
|
124
127
|
},
|
|
125
128
|
"stateOfChargeSensor": {
|
|
126
|
-
"title": "State of charge as
|
|
129
|
+
"title": "State of charge as extra sensor, for automations",
|
|
130
|
+
"type": "boolean",
|
|
131
|
+
"default": false
|
|
132
|
+
},
|
|
133
|
+
"fuelLevel": {
|
|
134
|
+
"title": "Fuel level as battery (petrol, diesel, CNG, LPG)",
|
|
135
|
+
"type": "boolean",
|
|
136
|
+
"default": true
|
|
137
|
+
},
|
|
138
|
+
"fuelLevelSensor": {
|
|
139
|
+
"title": "Fuel level as extra sensor, for automations",
|
|
127
140
|
"type": "boolean",
|
|
128
141
|
"default": false
|
|
129
142
|
},
|
|
130
143
|
"charging": {
|
|
131
|
-
"title": "
|
|
144
|
+
"title": "Start / stop charging (outlet)",
|
|
132
145
|
"type": "boolean",
|
|
133
146
|
"default": true
|
|
134
147
|
},
|
|
@@ -143,17 +156,17 @@
|
|
|
143
156
|
"default": true
|
|
144
157
|
},
|
|
145
158
|
"auxiliaryHeating": {
|
|
146
|
-
"title": "Auxiliary heating (needs S-PIN)",
|
|
159
|
+
"title": "Auxiliary heating (switch, needs S-PIN)",
|
|
147
160
|
"type": "boolean",
|
|
148
161
|
"default": true
|
|
149
162
|
},
|
|
150
163
|
"activeVentilation": {
|
|
151
|
-
"title": "
|
|
164
|
+
"title": "Ventilation (switch)",
|
|
152
165
|
"type": "boolean",
|
|
153
166
|
"default": false
|
|
154
167
|
},
|
|
155
168
|
"presence": {
|
|
156
|
-
"title": "
|
|
169
|
+
"title": "\"Home\" sensor (needs home location)",
|
|
157
170
|
"type": "boolean",
|
|
158
171
|
"default": true
|
|
159
172
|
},
|
|
@@ -183,9 +196,24 @@
|
|
|
183
196
|
"default": true
|
|
184
197
|
},
|
|
185
198
|
"lock": {
|
|
186
|
-
"title": "Locked (
|
|
199
|
+
"title": "Locked (sensor)",
|
|
187
200
|
"type": "boolean",
|
|
188
201
|
"default": true
|
|
202
|
+
},
|
|
203
|
+
"lights": {
|
|
204
|
+
"title": "Lights on (sensor)",
|
|
205
|
+
"type": "boolean",
|
|
206
|
+
"default": false
|
|
207
|
+
},
|
|
208
|
+
"windowHeating": {
|
|
209
|
+
"title": "Window heating on (sensor)",
|
|
210
|
+
"type": "boolean",
|
|
211
|
+
"default": false
|
|
212
|
+
},
|
|
213
|
+
"plugLock": {
|
|
214
|
+
"title": "Charging plug locked (sensor)",
|
|
215
|
+
"type": "boolean",
|
|
216
|
+
"default": false
|
|
189
217
|
}
|
|
190
218
|
}
|
|
191
219
|
}
|
|
@@ -210,24 +238,85 @@
|
|
|
210
238
|
"key": "vehicles[].token",
|
|
211
239
|
"type": "password"
|
|
212
240
|
},
|
|
241
|
+
{
|
|
242
|
+
"type": "help",
|
|
243
|
+
"helpvalue": "<p>The plugin detects what your vehicle supports and only creates those services in HomeKit, so you can keep the defaults below. Switches marked <em>sensor</em> or <em>for automations</em> are off by default. After the first update the Homebridge log lists everything your vehicle supports, including what is turned off.</p>"
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
"type": "fieldset",
|
|
247
|
+
"title": "Doors, windows and lock",
|
|
248
|
+
"expandable": true,
|
|
249
|
+
"expanded": false,
|
|
250
|
+
"items": [
|
|
251
|
+
"vehicles[].features.doors",
|
|
252
|
+
"vehicles[].features.windows",
|
|
253
|
+
"vehicles[].features.trunk",
|
|
254
|
+
"vehicles[].features.bonnet",
|
|
255
|
+
"vehicles[].features.sunroof",
|
|
256
|
+
"vehicles[].features.lock",
|
|
257
|
+
"vehicles[].features.lights"
|
|
258
|
+
]
|
|
259
|
+
},
|
|
213
260
|
{
|
|
214
261
|
"type": "fieldset",
|
|
215
|
-
"title": "
|
|
262
|
+
"title": "Battery and fuel",
|
|
216
263
|
"expandable": true,
|
|
217
264
|
"expanded": false,
|
|
218
265
|
"items": [
|
|
266
|
+
"vehicles[].features.battery",
|
|
267
|
+
"vehicles[].features.stateOfChargeSensor",
|
|
268
|
+
"vehicles[].features.fuelLevel",
|
|
269
|
+
"vehicles[].features.fuelLevelSensor",
|
|
219
270
|
{
|
|
220
|
-
"key": "vehicles[].
|
|
221
|
-
"type": "
|
|
271
|
+
"key": "vehicles[].lowBatteryThreshold",
|
|
272
|
+
"type": "number"
|
|
273
|
+
}
|
|
274
|
+
]
|
|
275
|
+
},
|
|
276
|
+
{
|
|
277
|
+
"type": "fieldset",
|
|
278
|
+
"title": "Charging",
|
|
279
|
+
"description": "Electric and plug-in hybrid vehicles.",
|
|
280
|
+
"expandable": true,
|
|
281
|
+
"expanded": false,
|
|
282
|
+
"items": [
|
|
283
|
+
"vehicles[].features.charging",
|
|
284
|
+
"vehicles[].features.chargingLimit",
|
|
285
|
+
"vehicles[].features.plugLock"
|
|
286
|
+
]
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
"type": "fieldset",
|
|
290
|
+
"title": "Air conditioning and ventilation",
|
|
291
|
+
"expandable": true,
|
|
292
|
+
"expanded": false,
|
|
293
|
+
"items": [
|
|
294
|
+
"vehicles[].features.climate",
|
|
295
|
+
{
|
|
296
|
+
"key": "vehicles[].climateTemperature",
|
|
297
|
+
"type": "number"
|
|
222
298
|
},
|
|
299
|
+
"vehicles[].airConditioningWithoutExternalPower",
|
|
300
|
+
"vehicles[].features.windowHeating",
|
|
301
|
+
"vehicles[].features.activeVentilation"
|
|
302
|
+
]
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
"type": "fieldset",
|
|
306
|
+
"title": "Auxiliary heating",
|
|
307
|
+
"description": "Vehicles with a fuel-operated auxiliary heater.",
|
|
308
|
+
"expandable": true,
|
|
309
|
+
"expanded": false,
|
|
310
|
+
"items": [
|
|
311
|
+
"vehicles[].features.auxiliaryHeating",
|
|
223
312
|
{
|
|
224
313
|
"key": "vehicles[].spin",
|
|
225
314
|
"type": "password"
|
|
226
315
|
},
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
316
|
+
{
|
|
317
|
+
"key": "vehicles[].auxiliaryHeatingDurationMinutes",
|
|
318
|
+
"type": "number"
|
|
319
|
+
}
|
|
231
320
|
]
|
|
232
321
|
},
|
|
233
322
|
{
|
|
@@ -237,48 +326,38 @@
|
|
|
237
326
|
"expandable": true,
|
|
238
327
|
"expanded": false,
|
|
239
328
|
"items": [
|
|
329
|
+
"vehicles[].features.presence",
|
|
240
330
|
{
|
|
241
331
|
"type": "flex",
|
|
242
332
|
"flex-flow": "row wrap",
|
|
243
333
|
"items": [
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
334
|
+
{
|
|
335
|
+
"key": "vehicles[].home.lat",
|
|
336
|
+
"type": "number"
|
|
337
|
+
},
|
|
338
|
+
{
|
|
339
|
+
"key": "vehicles[].home.lon",
|
|
340
|
+
"type": "number"
|
|
341
|
+
},
|
|
342
|
+
{
|
|
343
|
+
"key": "vehicles[].home.radiusMeters",
|
|
344
|
+
"type": "number"
|
|
345
|
+
}
|
|
247
346
|
]
|
|
248
347
|
}
|
|
249
348
|
]
|
|
250
349
|
},
|
|
251
350
|
{
|
|
252
351
|
"type": "fieldset",
|
|
253
|
-
"title": "
|
|
254
|
-
"
|
|
255
|
-
"expanded": false,
|
|
256
|
-
"items": [
|
|
257
|
-
"vehicles[].pollingIntervalMinutes",
|
|
258
|
-
"vehicles[].lowBatteryThreshold"
|
|
259
|
-
]
|
|
260
|
-
},
|
|
261
|
-
{
|
|
262
|
-
"type": "fieldset",
|
|
263
|
-
"title": "Features",
|
|
264
|
-
"description": "Services are only created if the vehicle supports them.",
|
|
352
|
+
"title": "Updates",
|
|
353
|
+
"description": "The default fits most setups.",
|
|
265
354
|
"expandable": true,
|
|
266
355
|
"expanded": false,
|
|
267
356
|
"items": [
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
"vehicles[].features.climate",
|
|
273
|
-
"vehicles[].features.auxiliaryHeating",
|
|
274
|
-
"vehicles[].features.activeVentilation",
|
|
275
|
-
"vehicles[].features.presence",
|
|
276
|
-
"vehicles[].features.doors",
|
|
277
|
-
"vehicles[].features.windows",
|
|
278
|
-
"vehicles[].features.trunk",
|
|
279
|
-
"vehicles[].features.bonnet",
|
|
280
|
-
"vehicles[].features.sunroof",
|
|
281
|
-
"vehicles[].features.lock"
|
|
357
|
+
{
|
|
358
|
+
"key": "vehicles[].pollingIntervalMinutes",
|
|
359
|
+
"type": "number"
|
|
360
|
+
}
|
|
282
361
|
]
|
|
283
362
|
}
|
|
284
363
|
]
|
|
@@ -18,3 +18,24 @@ export declare class StateOfChargeSensorBinding extends ServiceBinding {
|
|
|
18
18
|
protected get hasStatusFault(): boolean;
|
|
19
19
|
protected render(_service: Service, vehicle: Vehicle): void;
|
|
20
20
|
}
|
|
21
|
+
/**
|
|
22
|
+
* Battery service for combustion vehicles: the level is the fuel level, low below the configured
|
|
23
|
+
* threshold. HomeKit has no fuel service; hybrids show their high-voltage battery instead.
|
|
24
|
+
*/
|
|
25
|
+
export declare class FuelBinding extends ServiceBinding {
|
|
26
|
+
readonly feature = "fuelLevel";
|
|
27
|
+
protected readonly serviceType: ServiceType;
|
|
28
|
+
protected readonly subtype = "fuel";
|
|
29
|
+
protected readonly displayName = "Fuel";
|
|
30
|
+
protected configure(service: Service): void;
|
|
31
|
+
protected render(_service: Service, vehicle: Vehicle): void;
|
|
32
|
+
}
|
|
33
|
+
/** Humidity sensor that mirrors the fuel level, because HomeKit cannot trigger on battery levels. */
|
|
34
|
+
export declare class FuelLevelSensorBinding extends ServiceBinding {
|
|
35
|
+
readonly feature = "fuelLevelSensor";
|
|
36
|
+
protected readonly serviceType: ServiceType;
|
|
37
|
+
protected readonly subtype = "fuel-level";
|
|
38
|
+
protected readonly displayName = "Fuel Level";
|
|
39
|
+
protected get hasStatusFault(): boolean;
|
|
40
|
+
protected render(_service: Service, vehicle: Vehicle): void;
|
|
41
|
+
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { batteryValues, stateOfCharge } from "../../vehicle/mapping.js";
|
|
1
|
+
import { batteryValues, fuelLevel, fuelValues, stateOfCharge, } from "../../vehicle/mapping.js";
|
|
2
2
|
import { ServiceBinding } from "./common.js";
|
|
3
3
|
/** Battery: level, charging state and low battery below the configured threshold. */
|
|
4
4
|
export class BatteryBinding extends ServiceBinding {
|
|
@@ -33,4 +33,41 @@ export class StateOfChargeSensorBinding extends ServiceBinding {
|
|
|
33
33
|
this.set(this.ctx.hap.Characteristic.CurrentRelativeHumidity, stateOfCharge(vehicle));
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Battery service for combustion vehicles: the level is the fuel level, low below the configured
|
|
38
|
+
* threshold. HomeKit has no fuel service; hybrids show their high-voltage battery instead.
|
|
39
|
+
*/
|
|
40
|
+
export class FuelBinding extends ServiceBinding {
|
|
41
|
+
feature = "fuelLevel";
|
|
42
|
+
serviceType = this.ctx.hap.Service.Battery;
|
|
43
|
+
subtype = "fuel";
|
|
44
|
+
displayName = "Fuel";
|
|
45
|
+
configure(service) {
|
|
46
|
+
const { ChargingState } = this.ctx.hap.Characteristic;
|
|
47
|
+
service.updateCharacteristic(ChargingState, ChargingState.NOT_CHARGEABLE);
|
|
48
|
+
}
|
|
49
|
+
render(_service, vehicle) {
|
|
50
|
+
const { BatteryLevel, StatusLowBattery } = this.ctx.hap.Characteristic;
|
|
51
|
+
const values = fuelValues(vehicle, this.ctx.settings.lowBatteryThreshold);
|
|
52
|
+
this.set(BatteryLevel, values.level);
|
|
53
|
+
if (values.low !== undefined) {
|
|
54
|
+
this.set(StatusLowBattery, values.low
|
|
55
|
+
? StatusLowBattery.BATTERY_LEVEL_LOW
|
|
56
|
+
: StatusLowBattery.BATTERY_LEVEL_NORMAL);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
/** Humidity sensor that mirrors the fuel level, because HomeKit cannot trigger on battery levels. */
|
|
61
|
+
export class FuelLevelSensorBinding extends ServiceBinding {
|
|
62
|
+
feature = "fuelLevelSensor";
|
|
63
|
+
serviceType = this.ctx.hap.Service.HumiditySensor;
|
|
64
|
+
subtype = "fuel-level";
|
|
65
|
+
displayName = "Fuel Level";
|
|
66
|
+
get hasStatusFault() {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
render(_service, vehicle) {
|
|
70
|
+
this.set(this.ctx.hap.Characteristic.CurrentRelativeHumidity, fuelLevel(vehicle));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
36
73
|
//# sourceMappingURL=battery.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"battery.js","sourceRoot":"","sources":["../../../src/accessory/services/battery.ts"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"battery.js","sourceRoot":"","sources":["../../../src/accessory/services/battery.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import type { Service } from "homebridge";
|
|
2
2
|
import type { Vehicle } from "../../api/types.js";
|
|
3
3
|
import type { FeatureToggles } from "../../config.js";
|
|
4
|
-
import { type BodyValues } from "../../vehicle/mapping.js";
|
|
5
4
|
import { ServiceBinding, type BindingContext, type ServiceType } from "./common.js";
|
|
6
|
-
type
|
|
5
|
+
type ContactFeature = Extract<keyof FeatureToggles, "doors" | "windows" | "trunk" | "bonnet" | "sunroof" | "lock" | "lights" | "windowHeating" | "plugLock">;
|
|
7
6
|
interface ContactDefinition {
|
|
8
|
-
feature:
|
|
7
|
+
feature: ContactFeature;
|
|
9
8
|
displayName: string;
|
|
10
|
-
/** `true` means "contact not detected"
|
|
11
|
-
isOpen: (
|
|
9
|
+
/** `true` means "contact not detected": open, unlocked for the lock sensors, on otherwise. */
|
|
10
|
+
isOpen: (vehicle: Vehicle) => boolean | undefined;
|
|
12
11
|
}
|
|
13
12
|
export declare class ContactBinding extends ServiceBinding {
|
|
14
13
|
private readonly definition;
|
|
15
|
-
readonly feature:
|
|
14
|
+
readonly feature: ContactFeature;
|
|
16
15
|
protected readonly serviceType: ServiceType;
|
|
17
16
|
protected readonly subtype: string;
|
|
18
17
|
protected readonly displayName: string;
|