homebridge-ecobee-security 0.9.0 → 0.9.1
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 +26 -0
- package/README.md +101 -3
- package/config.schema.json +123 -1
- package/homebridge-ui/public/index.html +152 -0
- package/homebridge-ui/server.js +13 -0
- package/lib/camera/camera.js +57 -7
- package/lib/camera/session.js +119 -6
- package/lib/camera/talk.js +311 -0
- package/lib/comfort.js +280 -0
- package/lib/ecobee.js +70 -2
- package/lib/platform.js +260 -9
- package/lib/presence.js +156 -0
- package/lib/security.js +7 -3
- package/lib/vacation.js +11 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.1
|
|
4
|
+
|
|
5
|
+
- New setting **Add Comfort Setting switches** (`comfortSetting`, `comfortHoldType`): a Comfort Setting
|
|
6
|
+
accessory with a switch for each ecobee comfort setting (Home, Away, Sleep and your own). Turning one on
|
|
7
|
+
holds it, turning it off goes back to the schedule, and holds set in the ecobee app show up too.
|
|
8
|
+
- New setting **Two-way talk (beta)** (`twoWayAudio`, off by default): talk through the doorbell from the Home
|
|
9
|
+
app's live view. Needs the doorbell to accept audio from the plugin; the log says what it answered. With it
|
|
10
|
+
on, `twoWayAudioTest` (config only) plays a 3-second tone on the doorbell when a live view starts.
|
|
11
|
+
- New setting **Enable presence sensors for household members** (`memberPresence`, `presenceMembers`):
|
|
12
|
+
an occupancy sensor per person, Occupied while the ecobee app's location says they are home, for Home
|
|
13
|
+
app conditions like "only if Alex is home". Needs location set to Always in the ecobee app on that
|
|
14
|
+
person's phone; shows No Response while unknown.
|
|
15
|
+
- New setting **Home Occupied source** (`occupancySource`): besides your own Home app automations
|
|
16
|
+
(the default), Home Occupied can follow **ecobee Autopilot**, the ecobee app's location on household
|
|
17
|
+
members' phones, which arms and disarms like the switch does. ecobee's Smart Home & Away stays as the
|
|
18
|
+
third choice, now labelled beta.
|
|
19
|
+
- Two new settings with the Vacation Mode switch (off by default; they need the Home Occupied switch and
|
|
20
|
+
a source other than ecobee Smart Home & Away): **Start a vacation when the home has been empty for**
|
|
21
|
+
(`vacationWhenEmpty`, `vacationEmptyHours`), a safety net that starts a vacation once, and **End the
|
|
22
|
+
vacation when someone comes home** (`vacationEndOnArrival`), which also ends dated vacations.
|
|
23
|
+
- When the last hold is released (a robot back on its base, say) and it had switched Away to Home, Away is
|
|
24
|
+
armed again after a 3-second countdown instead of the full exit delay. The house was already empty, so
|
|
25
|
+
the delay only left it unarmed longer. Away you asked for during the hold still gets the normal exit delay.
|
|
26
|
+
- Fixed: turning Vacation Mode on in the Home app didn't start a vacation (ecobee rejected the vacation's
|
|
27
|
+
name).
|
|
28
|
+
|
|
3
29
|
## 0.9.0
|
|
4
30
|
|
|
5
31
|
### Doorbell camera (beta)
|
package/README.md
CHANGED
|
@@ -150,6 +150,8 @@ Sign-in: see [Sign-in](#sign-in).
|
|
|
150
150
|
| `doorbellCamera` | `false` | Adds the doorbell camera (beta). Restart the bridge after changing it. |
|
|
151
151
|
| `motionGrace` | `15` | Seconds the motion sensor stays on after the doorbell's motion ends (6 to 120). |
|
|
152
152
|
| `ffmpegPath` | `/usr/local/bin/ffmpeg` if it exists, else `ffmpeg` | The ffmpeg to use. |
|
|
153
|
+
| `twoWayAudio` | `false` | Talk through the doorbell from the Home app's live view (beta; see [Two-way talk](#two-way-talk-beta)). |
|
|
154
|
+
| `twoWayAudioTest` | `false` | With `twoWayAudio`: plays a 3-second tone on the doorbell when a live view starts (config file only). |
|
|
153
155
|
| `debugRecordings` | `false` | Keeps the last five recordings for troubleshooting (config file only; see [Troubleshooting](#troubleshooting)). |
|
|
154
156
|
|
|
155
157
|
### Switches and sensors settings
|
|
@@ -157,7 +159,14 @@ Sign-in: see [Sign-in](#sign-in).
|
|
|
157
159
|
| Setting | Default | |
|
|
158
160
|
|---|---|---|
|
|
159
161
|
| `occupancySwitch` | `false` | Adds a **Home Occupied** switch for your presence automations (see [Home Occupied switch](#home-occupied-switch)). |
|
|
162
|
+
| `occupancySource` | `"home"` | Who sets Home Occupied: `"home"` (your automations), `"autopilot"` or `"ecobee"` (see [Home Occupied source](#home-occupied-source)). |
|
|
163
|
+
| `memberPresence` | `false` | Adds a presence sensor for each household member in `presenceMembers` (see [Member presence sensors](#member-presence-sensors)). |
|
|
164
|
+
| `presenceMembers` | none | The ecobee account ids of the people to add; the settings page lists them. |
|
|
160
165
|
| `vacationSwitch` | `false` | Adds a **Vacation Mode** switch that is on while an ecobee vacation is running (see [Vacation Mode switch](#vacation-mode-switch)). |
|
|
166
|
+
| `vacationWhenEmpty` | `false` | Starts a vacation when Home Occupied has been off for `vacationEmptyHours` (default 24; see [Vacations that follow Home Occupied](#vacations-that-follow-home-occupied)). |
|
|
167
|
+
| `vacationEndOnArrival` | `false` | Ends running vacations when Home Occupied turns on. |
|
|
168
|
+
| `comfortSetting` | `false` | Adds a **Comfort Setting** accessory with a switch per ecobee comfort setting (see [Comfort Setting](#comfort-setting)). |
|
|
169
|
+
| `comfortHoldType` | `"nextTransition"` | How long a comfort setting turned on is held: `"nextTransition"` or `"indefinite"`. |
|
|
161
170
|
| `smokeSensor` | `true` | Adds a separate **Smoke Alarm** accessory (a Smoke Sensor) that detects smoke while ecobee has a smoke-alarm incident open, for automations and Home app smoke notifications. Set to `false` to remove it. |
|
|
162
171
|
| `airQuality` | `true` | For each thermostat with an air quality sensor: an accessory "<thermostat> Air Quality" with an **Air Quality Sensor** (overall level; VOC as ecobee reports it, in ppb, which the Home app labels µg/m³) and a **Carbon Dioxide Sensor** (ppm). Read every 5 minutes. The level follows the ecobee app's Clean–Poor bar: its first two segments are Excellent, then Good, Fair, Inferior, Poor; Unknown while the sensor calibrates. |
|
|
163
172
|
| `co2Alert` | `1000` | CO2 (ppm) at or above which the Carbon Dioxide Sensor reports abnormal levels. |
|
|
@@ -231,9 +240,9 @@ Using a robot vacuum as the example:
|
|
|
231
240
|
|
|
232
241
|
| Situation | What the security system does |
|
|
233
242
|
|---|---|
|
|
234
|
-
| The robot starts cleaning while the system is armed **Away** | Switches to Home, and goes back to Away when the robot is done. |
|
|
243
|
+
| The robot starts cleaning while the system is armed **Away** | Switches to Home, and goes back to Away when the robot is done, after a 3-second countdown. |
|
|
235
244
|
| The robot starts while the system is set to **Home**, **Night** or **Off** | Nothing changes. |
|
|
236
|
-
| You arm **Away in the Home app** while the robot is cleaning (the tile, a scene, an automation or Siri) | Stays in Home until the robot is done, then arms Away. The tile shows "Arming…" meanwhile. |
|
|
245
|
+
| You arm **Away in the Home app** while the robot is cleaning (the tile, a scene, an automation or Siri) | Stays in Home until the robot is done, then arms Away with the normal exit delay. The tile shows "Arming…" meanwhile. |
|
|
237
246
|
| You want Away **now** | Turn on the **Arm Away Now** switch (see [Hold options](#hold-options)). It arms Away right away and sends the robot home. |
|
|
238
247
|
| You arm **Away in the ecobee app** while the robot is cleaning | Sends the robot home, and gives it up to 2 extra minutes on the countdown. It arms as soon as the robot is docked, but never earlier than your normal countdown. If the robot won't make it in time, it stops where it is before the sensors arm. |
|
|
239
248
|
| You arm **Away at the keypad** while the robot is cleaning | Stops the robot where it is. ecobee doesn't report keypad countdowns, so this happens once Away is already armed: there's a window of up to 10 seconds in which a motion sensor could still catch the robot. |
|
|
@@ -313,7 +322,7 @@ camera isn't published and the log says why.
|
|
|
313
322
|
|
|
314
323
|
Skip steps 2 to 4 to run the camera without the link: it is then a second tile, a plain camera named
|
|
315
324
|
"<name> Camera", next to ecobee's own doorbell tile, which keeps the ring, motion and recordings. With the
|
|
316
|
-
link the camera replaces ecobee's doorbell.
|
|
325
|
+
link the camera replaces ecobee's doorbell.
|
|
317
326
|
|
|
318
327
|
Notes:
|
|
319
328
|
|
|
@@ -369,6 +378,18 @@ person, animal and package detection, are then made by HomeKit.
|
|
|
369
378
|
|
|
370
379
|
To inspect recordings, see [Troubleshooting](#troubleshooting).
|
|
371
380
|
|
|
381
|
+
### Two-way talk (beta)
|
|
382
|
+
|
|
383
|
+
Turn on **Two-way talk** (`twoWayAudio`) and restart the bridge to talk through the doorbell from the Home app's
|
|
384
|
+
live view (the microphone button). It is a beta: whether the doorbell accepts audio from the plugin isn't known for
|
|
385
|
+
every firmware, and talking adds a little delay. The log says at start-up what the doorbell answered ("two-way
|
|
386
|
+
talk: the camera answered audio sendrecv" is good; anything else means it can't take audio and the plugin carries
|
|
387
|
+
on receive-only, as before). The live view's picture and sound are not affected.
|
|
388
|
+
|
|
389
|
+
To check that audio reaches the doorbell, set `"twoWayAudioTest": true` in the config (there is no settings-page
|
|
390
|
+
switch), open the live view while standing at the door, and listen for a 3-second tone; the log says "test tone
|
|
391
|
+
sent". Turn it off afterwards.
|
|
392
|
+
|
|
372
393
|
## Home Occupied switch
|
|
373
394
|
|
|
374
395
|
Apple Home asks you to confirm (a notification you have to tap) whenever a people-arrive or
|
|
@@ -404,6 +425,42 @@ What each direction does:
|
|
|
404
425
|
> or from a shared home member's phone, turns off an Away system, so treat it as as sensitive as the
|
|
405
426
|
> security tile itself.
|
|
406
427
|
|
|
428
|
+
### Home Occupied source
|
|
429
|
+
|
|
430
|
+
Who sets the switch is the **Home Occupied source** (`occupancySource`), shown once the switch is on.
|
|
431
|
+
Restart the bridge after changing it.
|
|
432
|
+
|
|
433
|
+
| Source | `occupancySource` | What decides |
|
|
434
|
+
|---|---|---|
|
|
435
|
+
| **Set via Home App Automations** | `"home"` (default) | You do, with Home app arrive/leave automations, which use Apple's location of each person in your Home. Fastest, and you keep the most control. Nothing to set up in ecobee. |
|
|
436
|
+
| **ecobee Autopilot** | `"autopilot"` | The ecobee app's location on each household member's phone, read every 30 seconds. Location must be set to **Always** in the ecobee app on every phone that counts. Reacts quickly, but doesn't see guests or people without the ecobee app. |
|
|
437
|
+
| **ecobee Smart Home & Away (beta)** | `"ecobee"` | The thermostat, part of ecobee's eco+: it decides from motion on ecobee sensors, plus phones when Autopilot is on. It notices anyone in the house, but can take a long time to decide the home is empty. Paused during an ecobee vacation. Doesn't arm or disarm anything. |
|
|
438
|
+
|
|
439
|
+
With Autopilot, someone home is any member whose phone is tracked and reads home; nobody home is all of
|
|
440
|
+
those reading away. If some are unknown and none is home, the switch keeps its last state, and so it
|
|
441
|
+
does if no member is tracked or ecobee can't be reached (the log says which). After a restart, Autopilot's first reading only brings the switch up to date, without arming or disarming
|
|
442
|
+
anything; later changes arm and disarm exactly as the switch does. With either ecobee source the switch follows ecobee, so changing it
|
|
443
|
+
in the Home app is undone.
|
|
444
|
+
|
|
445
|
+
> [!NOTE]
|
|
446
|
+
> If ecobee's own Autopilot is set to arm and disarm by itself in the ecobee app, ecobee and the plugin
|
|
447
|
+
> both act on the same arrivals and departures. Pick one.
|
|
448
|
+
|
|
449
|
+
## Member presence sensors
|
|
450
|
+
|
|
451
|
+
Turn on **Enable presence sensors for household members** (`memberPresence`) and tick the people in the
|
|
452
|
+
settings (`presenceMembers`, their ecobee account ids). Each gets an occupancy sensor named after them,
|
|
453
|
+
**Occupied** while the ecobee app's location says they are home, for Home app conditions like "only if
|
|
454
|
+
Alex is home" or "only when nobody else is home". The plugin reads ecobee every 30 seconds and logs
|
|
455
|
+
when someone comes or goes. Restart the bridge after changing the setting.
|
|
456
|
+
|
|
457
|
+
- The person's phone must report to ecobee with location set to **Always** in the ecobee app. A person
|
|
458
|
+
for whom that isn't so isn't listed as available in the settings, and gets no sensor until it is.
|
|
459
|
+
- Only household members count. Guests, and people without the ecobee app, aren't seen.
|
|
460
|
+
- **No Response** means unknown: ecobee doesn't know where the phone is, the person is no longer tracked,
|
|
461
|
+
or ecobee couldn't be reached for a while.
|
|
462
|
+
- Anyone you share your Home with can see these sensors, and so where the people are.
|
|
463
|
+
|
|
407
464
|
## Vacation Mode switch
|
|
408
465
|
|
|
409
466
|
Turn on **Vacation Mode switch** (`vacationSwitch`) and the plugin adds a switch named **Vacation Mode**
|
|
@@ -421,6 +478,47 @@ ends.
|
|
|
421
478
|
- Like the other sensors, the switch shows No Response while ecobee can't be reached or you're
|
|
422
479
|
signed out. Restart the bridge after changing the setting.
|
|
423
480
|
|
|
481
|
+
### Vacations that follow Home Occupied
|
|
482
|
+
|
|
483
|
+
Two optional settings in the Vacation Mode section (off by default). They need both the Home Occupied
|
|
484
|
+
and the Vacation Mode switches, and a [Home Occupied source](#home-occupied-source) other than ecobee
|
|
485
|
+
Smart Home & Away, which ecobee pauses during a vacation.
|
|
486
|
+
|
|
487
|
+
- **Start a vacation when the home has been empty for** (`vacationWhenEmpty`, `vacationEmptyHours`,
|
|
488
|
+
24 by default, 1 to 720): once Home Occupied has been off that long and no vacation is running, the
|
|
489
|
+
plugin starts one as the switch does. It does this at most once per empty period, so a vacation you
|
|
490
|
+
end by hand while still away stays ended. Treat it as a safety net and start vacations deliberately,
|
|
491
|
+
with the switch or dated in the ecobee app: a wrongly "empty" home (say, a phone without location
|
|
492
|
+
set to Always under ecobee Autopilot) would start one, which is why the default is long.
|
|
493
|
+
- **End the vacation when someone comes home** (`vacationEndOnArrival`): when Home Occupied turns on,
|
|
494
|
+
every running ecobee vacation ends, including dated ones from the ecobee app. The reading right
|
|
495
|
+
after a restart doesn't count.
|
|
496
|
+
|
|
497
|
+
Visitors while you're away aren't household members, so Home Occupied stays off and the vacation keeps
|
|
498
|
+
running. They disarm with their keypad code and arm Away from the ecobee keypad when they leave. If
|
|
499
|
+
they forget, the Home app's security notification shows the disarm, and you can arm from your phone.
|
|
500
|
+
|
|
501
|
+
## Comfort Setting
|
|
502
|
+
|
|
503
|
+
Turn on **Add Comfort Setting switches** (`comfortSetting`) and the plugin adds one accessory,
|
|
504
|
+
**Comfort Setting**, with a switch for each of your ecobee comfort settings (Home, Away, Sleep and your own,
|
|
505
|
+
read from the thermostats' program; with several thermostats, a setting any of them has). It is for
|
|
506
|
+
automations such as "Home Occupied off → Away on".
|
|
507
|
+
|
|
508
|
+
- Turning a switch **on** holds that comfort setting on the thermostats that have it, and the others
|
|
509
|
+
turn off. How long: `comfortHoldType`, `"nextTransition"` (default, until the next scheduled change)
|
|
510
|
+
or `"indefinite"` (until you change it).
|
|
511
|
+
- Turning the active switch **off** goes back to your schedule, so all off means following the schedule.
|
|
512
|
+
- A hold set in the ecobee app or on the thermostat lights the matching switch (read every minute). A
|
|
513
|
+
temperature-only hold lights none.
|
|
514
|
+
- During an ecobee vacation all switches are off and changes are refused (the log says so).
|
|
515
|
+
- Like the other sensors, the switches show No Response while ecobee can't be reached. Restart the
|
|
516
|
+
bridge after changing the setting.
|
|
517
|
+
|
|
518
|
+
> [!NOTE]
|
|
519
|
+
> The Home app shows the switches as one tile, and tapping the tile toggles all of them. Open the tile
|
|
520
|
+
> and pick one, or use **Show as Separate Tiles** in the accessory's settings.
|
|
521
|
+
|
|
424
522
|
## Smoke alarm and air quality
|
|
425
523
|
|
|
426
524
|
- **Smoke Alarm** (`smokeSensor`, on by default) is its own accessory, a Smoke Sensor that detects smoke while ecobee has a smoke-alarm incident open. It is separate from the security tile (the Home app would otherwise merge it into the tile with a cloud icon).
|
package/config.schema.json
CHANGED
|
@@ -106,17 +106,121 @@
|
|
|
106
106
|
"default": false,
|
|
107
107
|
"description": "Adds a Home Occupied switch to the Home app, with an occupancy sensor. By default your own people-arrive and people-leave automations set it, and it does the rest: off (nobody home) arms Away, on (someone home) turns Away off. Switches don't ask for confirmation the way automations that change the security system do. See \"Home Occupied switch\" in the README."
|
|
108
108
|
},
|
|
109
|
+
"occupancySource": {
|
|
110
|
+
"title": "Home Occupied source",
|
|
111
|
+
"type": "string",
|
|
112
|
+
"default": "home",
|
|
113
|
+
"oneOf": [
|
|
114
|
+
{
|
|
115
|
+
"title": "Set via Home App Automations",
|
|
116
|
+
"enum": [
|
|
117
|
+
"home"
|
|
118
|
+
]
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
"title": "ecobee Autopilot",
|
|
122
|
+
"enum": [
|
|
123
|
+
"autopilot"
|
|
124
|
+
]
|
|
125
|
+
},
|
|
126
|
+
{
|
|
127
|
+
"title": "ecobee Smart Home & Away (beta)",
|
|
128
|
+
"enum": [
|
|
129
|
+
"ecobee"
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
],
|
|
133
|
+
"description": "Who sets Home Occupied. Home App Automations: your arrive/leave automations. ecobee Autopilot: the ecobee app's location on household members' phones, which need location set to Always in the ecobee app. ecobee Smart Home & Away: the thermostat decides from motion on ecobee sensors (plus phones when Autopilot is on); it can be slow to notice an empty home, and it doesn't arm or disarm. See \"Home Occupied source\" in the README.",
|
|
134
|
+
"condition": {
|
|
135
|
+
"functionBody": "return model.occupancySwitch === true;"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"memberPresence": {
|
|
139
|
+
"title": "Presence sensors for household members",
|
|
140
|
+
"type": "boolean",
|
|
141
|
+
"default": false,
|
|
142
|
+
"description": "Adds an occupancy sensor for each person in presenceMembers, for Home app conditions like \"only if Alex is home\". Anyone you share your Home with can see them. Each person's phone needs location set to Always in the ecobee app. See \"Member presence sensors\" in the README."
|
|
143
|
+
},
|
|
144
|
+
"presenceMembers": {
|
|
145
|
+
"title": "People with a presence sensor",
|
|
146
|
+
"type": "array",
|
|
147
|
+
"items": {
|
|
148
|
+
"type": "string"
|
|
149
|
+
},
|
|
150
|
+
"description": "ecobee account ids of the people to add (the settings page lists them). With no list, none.",
|
|
151
|
+
"condition": {
|
|
152
|
+
"functionBody": "return model.memberPresence === true;"
|
|
153
|
+
}
|
|
154
|
+
},
|
|
109
155
|
"vacationSwitch": {
|
|
110
156
|
"title": "Vacation Mode switch",
|
|
111
157
|
"type": "boolean",
|
|
112
158
|
"default": false,
|
|
113
159
|
"description": "Shows when an ecobee vacation is on, for other accessories to follow. Turn it on to start a vacation now, until you turn it off; set dated vacations in the ecobee app."
|
|
114
160
|
},
|
|
161
|
+
"vacationWhenEmpty": {
|
|
162
|
+
"title": "Start a vacation when the home has been empty for",
|
|
163
|
+
"type": "boolean",
|
|
164
|
+
"default": false,
|
|
165
|
+
"description": "A safety net if you forget to turn Vacation Mode on: starts an ecobee vacation once Home Occupied has been off for vacationEmptyHours. Needs the Home Occupied and Vacation Mode switches, and a Home Occupied source other than ecobee Smart Home & Away.",
|
|
166
|
+
"condition": {
|
|
167
|
+
"functionBody": "return model.vacationSwitch === true && model.occupancySwitch === true && model.occupancySource !== 'ecobee';"
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
"vacationEmptyHours": {
|
|
171
|
+
"title": "Hours empty before the vacation starts",
|
|
172
|
+
"type": "integer",
|
|
173
|
+
"default": 24,
|
|
174
|
+
"minimum": 1,
|
|
175
|
+
"maximum": 720,
|
|
176
|
+
"description": "How long the home has to be empty first.",
|
|
177
|
+
"condition": {
|
|
178
|
+
"functionBody": "return model.vacationWhenEmpty === true && model.vacationSwitch === true && model.occupancySwitch === true && model.occupancySource !== 'ecobee';"
|
|
179
|
+
}
|
|
180
|
+
},
|
|
181
|
+
"vacationEndOnArrival": {
|
|
182
|
+
"title": "End the vacation when someone comes home",
|
|
183
|
+
"type": "boolean",
|
|
184
|
+
"default": false,
|
|
185
|
+
"description": "Ends any running ecobee vacation, including dated ones from the ecobee app, when Home Occupied turns on. Needs the Home Occupied and Vacation Mode switches, and a Home Occupied source other than ecobee Smart Home & Away.",
|
|
186
|
+
"condition": {
|
|
187
|
+
"functionBody": "return model.vacationSwitch === true && model.occupancySwitch === true && model.occupancySource !== 'ecobee';"
|
|
188
|
+
}
|
|
189
|
+
},
|
|
190
|
+
"comfortSetting": {
|
|
191
|
+
"title": "Add Comfort Setting switches",
|
|
192
|
+
"type": "boolean",
|
|
193
|
+
"default": false,
|
|
194
|
+
"description": "One switch per ecobee comfort setting (Home, Away, Sleep and your own). Turning one on holds it; turning it off goes back to your schedule. Restart the bridge after changing this."
|
|
195
|
+
},
|
|
196
|
+
"comfortHoldType": {
|
|
197
|
+
"title": "Comfort setting hold",
|
|
198
|
+
"type": "string",
|
|
199
|
+
"default": "nextTransition",
|
|
200
|
+
"oneOf": [
|
|
201
|
+
{
|
|
202
|
+
"title": "Until the next scheduled change",
|
|
203
|
+
"enum": [
|
|
204
|
+
"nextTransition"
|
|
205
|
+
]
|
|
206
|
+
},
|
|
207
|
+
{
|
|
208
|
+
"title": "Until I change it",
|
|
209
|
+
"enum": [
|
|
210
|
+
"indefinite"
|
|
211
|
+
]
|
|
212
|
+
}
|
|
213
|
+
],
|
|
214
|
+
"description": "How long a comfort setting you turn on in the Home app is held.",
|
|
215
|
+
"condition": {
|
|
216
|
+
"functionBody": "return model.comfortSetting === true;"
|
|
217
|
+
}
|
|
218
|
+
},
|
|
115
219
|
"doorbellCamera": {
|
|
116
220
|
"title": "Doorbell camera",
|
|
117
221
|
"type": "boolean",
|
|
118
222
|
"default": false,
|
|
119
|
-
"description": "Brings the ecobee doorbell into HomeKit Secure Video: recordings, activity zones and Apple's person and package detection in the Home app, plus live view. With the doorbell link it replaces ecobee's doorbell (instant ring and motion).
|
|
223
|
+
"description": "Brings the ecobee doorbell into HomeKit Secure Video: recordings, activity zones and Apple's person and package detection in the Home app, plus live view. With the doorbell link it replaces ecobee's doorbell (instant ring and motion). Restart the bridge after changing this. Add it in the Home app with the setup code shown in the Homebridge log. Needs an ffmpeg with libfdk_aac and libx264. See \"Doorbell camera\" in the README."
|
|
120
224
|
},
|
|
121
225
|
"motionGrace": {
|
|
122
226
|
"title": "Motion grace period (seconds)",
|
|
@@ -129,6 +233,24 @@
|
|
|
129
233
|
"functionBody": "return model.doorbellCamera === true;"
|
|
130
234
|
}
|
|
131
235
|
},
|
|
236
|
+
"twoWayAudio": {
|
|
237
|
+
"title": "Two-way talk",
|
|
238
|
+
"type": "boolean",
|
|
239
|
+
"default": false,
|
|
240
|
+
"description": "Talk through the doorbell from the Home app's live view.",
|
|
241
|
+
"condition": {
|
|
242
|
+
"functionBody": "return model.doorbellCamera === true;"
|
|
243
|
+
}
|
|
244
|
+
},
|
|
245
|
+
"twoWayAudioTest": {
|
|
246
|
+
"title": "Two-way talk test tone",
|
|
247
|
+
"type": "boolean",
|
|
248
|
+
"default": false,
|
|
249
|
+
"description": "Plays a 3-second tone on the doorbell when live view starts, to check that audio reaches it. Turn it off afterwards.",
|
|
250
|
+
"condition": {
|
|
251
|
+
"functionBody": "return model.doorbellCamera === true && model.twoWayAudio === true;"
|
|
252
|
+
}
|
|
253
|
+
},
|
|
132
254
|
"ffmpegPath": {
|
|
133
255
|
"title": "ffmpeg path",
|
|
134
256
|
"type": "string",
|
|
@@ -152,6 +152,12 @@
|
|
|
152
152
|
</div>
|
|
153
153
|
<div id="link-error" class="alert alert-danger mt-2 mb-0" role="alert" hidden></div>
|
|
154
154
|
</div>
|
|
155
|
+
<div class="form-check form-switch mb-1">
|
|
156
|
+
<input class="form-check-input" type="checkbox" role="switch" id="s-twoWayAudio" data-key="twoWayAudio" data-type="bool" data-default="false">
|
|
157
|
+
<label class="form-check-label" for="s-twoWayAudio">Two-way talk (beta)</label>
|
|
158
|
+
</div>
|
|
159
|
+
<p class="hint mb-2">Talk through the doorbell from the Home app's live view. Restart the bridge after changing this.
|
|
160
|
+
<a href="https://github.com/seanfletchr/homebridge-ecobee-security#two-way-talk-beta" target="_blank" rel="noopener">Learn more…</a></p>
|
|
155
161
|
<details>
|
|
156
162
|
<summary>Advanced</summary>
|
|
157
163
|
<div class="mt-2">
|
|
@@ -179,6 +185,27 @@
|
|
|
179
185
|
off (nobody home) arms Away, on (someone home) turns Away off. Switches don't ask for confirmation the way
|
|
180
186
|
automations that change the security system do. Restart the bridge after changing this.
|
|
181
187
|
<a href="https://github.com/seanfletchr/homebridge-ecobee-security#home-occupied-switch" target="_blank" rel="noopener">Learn more…</a></p>
|
|
188
|
+
<div id="occupancy-source-box" hidden>
|
|
189
|
+
<label for="s-occupancySource" class="form-label mb-1">Home Occupied source</label>
|
|
190
|
+
<select class="form-select" id="s-occupancySource" data-key="occupancySource" data-type="select" data-default="home"><option value="home">Set via Home App Automations</option><option value="autopilot">ecobee Autopilot</option><option value="ecobee">ecobee Smart Home & Away (beta)</option></select>
|
|
191
|
+
<p class="hint mt-1 mb-0"><span id="occupancy-source-hint"></span>
|
|
192
|
+
Restart the bridge after changing this.
|
|
193
|
+
<a href="https://github.com/seanfletchr/homebridge-ecobee-security#home-occupied-source" target="_blank" rel="noopener">Learn more…</a></p>
|
|
194
|
+
</div>
|
|
195
|
+
</div>
|
|
196
|
+
|
|
197
|
+
<div class="mt-3">
|
|
198
|
+
<h6 class="mb-1">Household members</h6>
|
|
199
|
+
<div class="form-check form-switch mb-1">
|
|
200
|
+
<input class="form-check-input" type="checkbox" role="switch" id="s-memberPresence" data-key="memberPresence" data-type="bool" data-default="false">
|
|
201
|
+
<label class="form-check-label" for="s-memberPresence">Enable presence sensors for household members</label>
|
|
202
|
+
</div>
|
|
203
|
+
<p class="hint mb-2">Adds a sensor for each person you tick, for Home app conditions like "only if Alex is home". Anyone you share your Home with can see them. Restart the bridge after changing this.
|
|
204
|
+
<a href="https://github.com/seanfletchr/homebridge-ecobee-security#member-presence-sensors" target="_blank" rel="noopener">Learn more…</a></p>
|
|
205
|
+
<div id="members-box" hidden>
|
|
206
|
+
<div class="mb-1">People with a sensor</div>
|
|
207
|
+
<div id="members"></div>
|
|
208
|
+
</div>
|
|
182
209
|
</div>
|
|
183
210
|
|
|
184
211
|
<div class="mt-3">
|
|
@@ -188,6 +215,37 @@
|
|
|
188
215
|
<label class="form-check-label" for="s-vacationSwitch">Add a Vacation Mode switch</label>
|
|
189
216
|
</div>
|
|
190
217
|
<p class="hint mb-2">Shows when an ecobee vacation is on, for other accessories to follow. Turn it on to start a vacation now, until you turn it off; set dated vacations in the ecobee app. Restart the bridge after changing this.</p>
|
|
218
|
+
<div id="vacation-options" hidden>
|
|
219
|
+
<div class="form-check mb-1">
|
|
220
|
+
<input class="form-check-input" type="checkbox" id="s-vacationWhenEmpty" data-key="vacationWhenEmpty" data-type="bool" data-default="false">
|
|
221
|
+
<label class="form-check-label" for="s-vacationWhenEmpty">Start a vacation when the home has been empty for</label>
|
|
222
|
+
</div>
|
|
223
|
+
<div class="d-flex align-items-center gap-2 mb-1 ms-4">
|
|
224
|
+
<input class="form-control" style="width: 6rem" type="number" step="1" min="1" max="720" id="s-vacationEmptyHours" data-key="vacationEmptyHours" data-type="int" data-default="24" aria-label="Hours empty before the vacation starts">
|
|
225
|
+
<span>hours</span>
|
|
226
|
+
</div>
|
|
227
|
+
<div class="hint mb-2 ms-4">A safety net if you forget to turn Vacation Mode on.</div>
|
|
228
|
+
<div class="form-check mb-1">
|
|
229
|
+
<input class="form-check-input" type="checkbox" id="s-vacationEndOnArrival" data-key="vacationEndOnArrival" data-type="bool" data-default="false">
|
|
230
|
+
<label class="form-check-label" for="s-vacationEndOnArrival">End the vacation when someone comes home</label>
|
|
231
|
+
</div>
|
|
232
|
+
<div class="hint ms-4">Also ends vacations you set in the ecobee app.</div>
|
|
233
|
+
<p class="hint mt-2 mb-0" id="vacation-options-hint" hidden></p>
|
|
234
|
+
</div>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<div class="mt-3">
|
|
238
|
+
<h6 class="mb-1">Comfort Setting</h6>
|
|
239
|
+
<div class="form-check form-switch mb-1">
|
|
240
|
+
<input class="form-check-input" type="checkbox" role="switch" id="s-comfortSetting" data-key="comfortSetting" data-type="bool" data-default="false">
|
|
241
|
+
<label class="form-check-label" for="s-comfortSetting">Add Comfort Setting switches</label>
|
|
242
|
+
</div>
|
|
243
|
+
<p class="hint mb-2">One switch per ecobee comfort setting (Home, Away, Sleep and your own). Turning one on holds it; turning it off goes back to your schedule. Restart the bridge after changing this.
|
|
244
|
+
<a href="https://github.com/seanfletchr/homebridge-ecobee-security#comfort-setting" target="_blank" rel="noopener">Learn more…</a></p>
|
|
245
|
+
<div id="comfort-box" hidden>
|
|
246
|
+
<label for="s-comfortHoldType" class="form-label mb-1">Hold</label>
|
|
247
|
+
<select class="form-select" id="s-comfortHoldType" data-key="comfortHoldType" data-type="select" data-default="nextTransition"><option value="nextTransition">Until the next scheduled change</option><option value="indefinite">Until I change it</option></select>
|
|
248
|
+
</div>
|
|
191
249
|
</div>
|
|
192
250
|
|
|
193
251
|
<div class="mt-3">
|
|
@@ -357,6 +415,10 @@
|
|
|
357
415
|
}
|
|
358
416
|
}
|
|
359
417
|
$('co2-box').hidden = block?.airQuality === false;
|
|
418
|
+
showOccupancySource();
|
|
419
|
+
showVacationOptions();
|
|
420
|
+
$('comfort-box').hidden = block?.comfortSetting !== true;
|
|
421
|
+
await showMembers(block);
|
|
360
422
|
$('camera-box').hidden = block?.doorbellCamera !== true;
|
|
361
423
|
if (block?.doorbellCamera === true) {
|
|
362
424
|
await showLink();
|
|
@@ -383,6 +445,83 @@
|
|
|
383
445
|
$('home-box').hidden = homes.length < 2 && !set;
|
|
384
446
|
}
|
|
385
447
|
|
|
448
|
+
const SOURCE_HINTS = {
|
|
449
|
+
home: 'Your arrive/leave automations in the Home app set it.',
|
|
450
|
+
autopilot: 'Follows the ecobee app\'s location on household members\' phones. Each phone needs location set to Always in the ecobee app.',
|
|
451
|
+
ecobee: 'The thermostat decides from motion on ecobee sensors (plus phones when Autopilot is on). It can be slow to notice an empty home.',
|
|
452
|
+
};
|
|
453
|
+
|
|
454
|
+
/** The Home Occupied source choice, shown only while the switch is on, with the hint for the chosen source. */
|
|
455
|
+
function showOccupancySource() {
|
|
456
|
+
$('occupancy-source-box').hidden = !$('s-occupancySwitch').checked;
|
|
457
|
+
$('occupancy-source-hint').textContent = SOURCE_HINTS[$('s-occupancySource').value] ?? SOURCE_HINTS.home;
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/** The vacation options: shown with the Vacation Mode switch, usable only with Home Occupied and a source other than ecobee's. */
|
|
461
|
+
function showVacationOptions() {
|
|
462
|
+
$('vacation-options').hidden = !$('s-vacationSwitch').checked;
|
|
463
|
+
const occupied = $('s-occupancySwitch').checked;
|
|
464
|
+
const ecobee = $('s-occupancySource').value === 'ecobee';
|
|
465
|
+
for (const id of ['s-vacationWhenEmpty', 's-vacationEmptyHours', 's-vacationEndOnArrival']) {
|
|
466
|
+
$(id).disabled = !occupied || ecobee;
|
|
467
|
+
}
|
|
468
|
+
const hint = $('vacation-options-hint');
|
|
469
|
+
hint.hidden = occupied && !ecobee;
|
|
470
|
+
hint.textContent = !occupied
|
|
471
|
+
? 'These need the Home Occupied switch above.'
|
|
472
|
+
: 'Not available with ecobee Smart Home & Away as the Home Occupied source: ecobee pauses it during a vacation, so it couldn\'t tell when someone comes home.';
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
/** The household members to tick, from what the plugin last saw (untracked ones greyed out with the reason). */
|
|
476
|
+
async function showMembers(blockIn) {
|
|
477
|
+
const block = blockIn ?? (await homebridge.getPluginConfig())[0] ?? {};
|
|
478
|
+
$('members-box').hidden = block.memberPresence !== true;
|
|
479
|
+
if (block.memberPresence !== true) {
|
|
480
|
+
return;
|
|
481
|
+
}
|
|
482
|
+
const members = await homebridge.request('/members').catch(() => []);
|
|
483
|
+
const box = $('members');
|
|
484
|
+
box.textContent = '';
|
|
485
|
+
if (!members.length) {
|
|
486
|
+
const p = document.createElement('p');
|
|
487
|
+
p.className = 'hint mb-0';
|
|
488
|
+
p.textContent = block.refreshToken
|
|
489
|
+
? 'No household members found yet. They show up here a minute after the bridge starts.'
|
|
490
|
+
: 'Sign in to ecobee first.';
|
|
491
|
+
box.append(p);
|
|
492
|
+
return;
|
|
493
|
+
}
|
|
494
|
+
const chosen = Array.isArray(block.presenceMembers) ? block.presenceMembers : [];
|
|
495
|
+
for (const member of members) {
|
|
496
|
+
const id = `member-${member.accountId.replace(/[^a-z0-9]/gi, '-')}`;
|
|
497
|
+
const input = Object.assign(document.createElement('input'), {
|
|
498
|
+
className: 'form-check-input', type: 'checkbox', id, checked: chosen.includes(member.accountId),
|
|
499
|
+
});
|
|
500
|
+
input.addEventListener('change', () => setMember(member.accountId, input.checked));
|
|
501
|
+
const label = Object.assign(document.createElement('label'), { className: 'form-check-label', htmlFor: id });
|
|
502
|
+
label.textContent = member.name;
|
|
503
|
+
const row = Object.assign(document.createElement('div'), { className: 'form-check mb-1' });
|
|
504
|
+
row.append(input, label);
|
|
505
|
+
if (!member.tracked) {
|
|
506
|
+
// Ticked but untracked stays enabled so it can be unticked; the plugin doesn't publish it meanwhile.
|
|
507
|
+
input.disabled = !input.checked;
|
|
508
|
+
label.style.opacity = '0.6';
|
|
509
|
+
const hint = Object.assign(document.createElement('div'), { className: 'hint' });
|
|
510
|
+
hint.textContent = `Not available: ${member.reason}.`;
|
|
511
|
+
row.append(hint);
|
|
512
|
+
}
|
|
513
|
+
box.append(row);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
async function setMember(accountId, on) {
|
|
518
|
+
const blocks = await homebridge.getPluginConfig();
|
|
519
|
+
const block = blocks[0];
|
|
520
|
+
const current = Array.isArray(block.presenceMembers) ? block.presenceMembers : [];
|
|
521
|
+
block.presenceMembers = on ? [...new Set([...current, accountId])] : current.filter(k => k !== accountId);
|
|
522
|
+
await homebridge.updatePluginConfig([block, ...blocks.slice(1)]);
|
|
523
|
+
}
|
|
524
|
+
|
|
386
525
|
/** Write one setting. Top-level keys are cleared with undefined, never deleted (the UI merges shallowly). */
|
|
387
526
|
async function setSetting(key, value) {
|
|
388
527
|
const blocks = await homebridge.getPluginConfig();
|
|
@@ -398,6 +537,15 @@
|
|
|
398
537
|
await setSetting(key, input.checked);
|
|
399
538
|
if (key === 'airQuality') {
|
|
400
539
|
$('co2-box').hidden = !input.checked;
|
|
540
|
+
} else if (key === 'occupancySwitch') {
|
|
541
|
+
showOccupancySource();
|
|
542
|
+
showVacationOptions();
|
|
543
|
+
} else if (key === 'comfortSetting') {
|
|
544
|
+
$('comfort-box').hidden = !input.checked;
|
|
545
|
+
} else if (key === 'vacationSwitch') {
|
|
546
|
+
showVacationOptions();
|
|
547
|
+
} else if (key === 'memberPresence') {
|
|
548
|
+
await showMembers();
|
|
401
549
|
} else if (key === 'doorbellCamera') {
|
|
402
550
|
$('camera-box').hidden = !input.checked;
|
|
403
551
|
if (input.checked) {
|
|
@@ -413,6 +561,10 @@
|
|
|
413
561
|
}
|
|
414
562
|
} else if (type === 'select') {
|
|
415
563
|
await setSetting(key, input.value === '' ? undefined : input.value);
|
|
564
|
+
if (key === 'occupancySource') {
|
|
565
|
+
showOccupancySource();
|
|
566
|
+
showVacationOptions();
|
|
567
|
+
}
|
|
416
568
|
} else {
|
|
417
569
|
await setSetting(key, input.value.trim() === '' ? undefined : input.value.trim());
|
|
418
570
|
}
|
package/homebridge-ui/server.js
CHANGED
|
@@ -8,6 +8,7 @@ import { fileURLToPath } from 'node:url';
|
|
|
8
8
|
|
|
9
9
|
import { HomebridgePluginUiServer, RequestError } from '@homebridge/plugin-ui-utils';
|
|
10
10
|
|
|
11
|
+
import { memberTracking } from '../lib/ecobee.js';
|
|
11
12
|
import { findDoorbells, pairDoorbell, readPairing, unpairDoorbell } from '../lib/camera/hap-pairing.js';
|
|
12
13
|
import { browserSignInLink, finishBrowserSignIn, finishMfa, passwordSignIn, SignInError } from '../lib/auth.js';
|
|
13
14
|
|
|
@@ -93,6 +94,18 @@ class UiServer extends HomebridgePluginUiServer {
|
|
|
93
94
|
}
|
|
94
95
|
});
|
|
95
96
|
|
|
97
|
+
// The household members the plugin last saw (only that list leaves state.json), with whether the
|
|
98
|
+
// ecobee app can tell where they are. The plugin reads them from ecobee with its own sign-in, so
|
|
99
|
+
// the page doesn't use the refresh token (a second user of it could invalidate the plugin's).
|
|
100
|
+
this.onRequest('/members', async () => {
|
|
101
|
+
try {
|
|
102
|
+
const store = JSON.parse(await readFile(join(this.homebridgeStoragePath, 'ecobee-security', 'state.json'), 'utf8'));
|
|
103
|
+
return (store.members ?? []).map(m => ({ accountId: m.accountId, name: m.name, ...memberTracking(m) }));
|
|
104
|
+
} catch {
|
|
105
|
+
return [];
|
|
106
|
+
}
|
|
107
|
+
});
|
|
108
|
+
|
|
96
109
|
// The doorbell link: pairing with the doorbell's own HomeKit server. The setup code is used once
|
|
97
110
|
// and neither logged nor kept.
|
|
98
111
|
const pairingPath = () => join(this.homebridgeStoragePath, 'ecobee-security', 'doorbell-pairing.json');
|