homebridge-ecobee-security 0.5.0 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.7.0
4
+
5
+ - New setting **Disarm when a door is unlocked with its keypad** (`keypadDisarm`, off by default,
6
+ in a new **Door keypads** card): entering a code on a smart lock's keypad turns the security system
7
+ off, like Nest Guard with a Nest × Yale lock. Works with locks from the same Homebridge that report
8
+ keypad unlocks (HomeKit's Lock Last Known Action, read over HAP on 127.0.0.1; needs insecure mode).
9
+ The settings page lists the locks found (`keypadLocks`; no list = all).
10
+
11
+ ## 0.6.0
12
+
13
+ - Security holds now keep Away off while a plugin (a robot vacuum) works, instead of just switching
14
+ Away to Home (ecobee's Stay). A plugin counts as out from its first hold until it releases, even if nothing was held.
15
+ - Away from the Home app (a scene, automation, Siri or the tile) while a robot is out waits for it:
16
+ the hold is kept (or started), Home meanwhile, and the release arms Away; the tile shows Arming
17
+ Away while it waits. Home, Night and Off in the Home app, and an alarm, still cancel the hold
18
+ and the waiting Away.
19
+ - New setting **Arm Away Now switch** (`armAwayNowSwitch`, in Security holds, off by default): adds
20
+ an Arm Away Now switch to the Home app that arms Away now and sends any robots that are out back to
21
+ their base.
22
+ - Away armed in the ecobee app or at the keypad while a robot is out asks the robot to head back to
23
+ its base before the exit delay ends, or to stop where it is if it can't make it. Plugins give a halt
24
+ endpoint with their hold request (`&halt=`), and the request says when the exit delay ends
25
+ (`&armAt=`; left out for a keypad Away, which is only seen once armed: the robot stops at once). A
26
+ robot that moves again asks for a new hold.
27
+ - New setting **Extra time for tasks to finish** (`taskWaitSeconds`, default 120, 0 = off):
28
+ when Away is armed from the ecobee app or the Arm Away Now switch while a task is running (like a
29
+ robot heading back to its base), the exit delay is extended by this much, and brought forward again
30
+ once the task is done (never earlier than it would have ended). A robot says it's docked, or stopped, with
31
+ `/release`; robots answer the halt with `returning: true` when they head back.
32
+
3
33
  ## 0.5.0
4
34
 
5
35
  - The `pollInterval` setting is gone: the security state is read every 10 s, as often as the ecobee
@@ -28,35 +58,7 @@
28
58
 
29
59
  ## 0.4.1
30
60
 
61
+ First public release.
62
+
31
63
  - Plugin icon in the README.
32
64
  - Catch and log errors creating the storage folder or control socket instead of stopping the bridge.
33
-
34
- ## 0.4.0
35
-
36
- - `offerNight`: adds Night to the Home app; it arms ecobee's Stay and keeps showing Night. Changing
37
- the setting recreates the security system in HomeKit (the Home app doesn't pick up new modes on an
38
- existing control).
39
- - `alarmTrigger: "entryDelay"`: show Alarm triggered only once an intrusion has outlasted the entry
40
- delay without a disarm, instead of as soon as ecobee opens the incident. Smoke still shows at once.
41
- - `smokeSensor` (on by default): a separate Smoke Alarm accessory that detects smoke while ecobee has a smoke-alarm
42
- incident open.
43
- - Air quality (`airQuality`, on by default): for ecobee thermostats with an air quality sensor, an
44
- Air Quality Sensor (level, VOC) and a Carbon Dioxide Sensor (ppm, alert at `co2Alert`, 1000 ppm).
45
- - The accessory reports the plugin version as its firmware version.
46
- - The hold API refuses a hold while any alarm incident is open, whichever `alarmTrigger` is set.
47
-
48
- ## 0.3.0
49
-
50
- - Sign in from the plugin's settings page in the Homebridge UI with your ecobee email, password
51
- and MFA code. No terminal or browser developer tools needed; the website sign-in is still there
52
- as a fallback.
53
- - `bin/ecobee-login.js` signs in with email and password by default; `--browser` for the old way.
54
-
55
- ## 0.2.0
56
-
57
- - Control socket (`control.sock`) so other plugins can hold the system at Stay and release it to
58
- Away afterwards (used by homebridge-narwal while the robot vacuum cleans).
59
-
60
- ## 0.1.0
61
-
62
- - First release: arm Stay / Away, disarm and alarm state in Apple Home, browser sign-in script.
package/README.md CHANGED
@@ -2,8 +2,9 @@
2
2
 
3
3
  # homebridge-ecobee-security
4
4
 
5
- Shows **ecobee Smart Security** in Apple Home as a security system: arm **Stay**, arm **Away**,
6
- **disarm**, and **Alarm triggered** when ecobee has an open intrusion or smoke incident. It also adds
5
+ Shows **ecobee Smart Security** in Apple Home as a security system: set it to **Home**, **Away** or
6
+ **Off** (ecobee's Stay, Away and disarmed), and see **Alarm triggered** when ecobee has an open
7
+ intrusion or smoke incident. It also adds
7
8
  **air quality** sensors for ecobee thermostats that have one (ecobee Premium), which ecobee's own
8
9
  HomeKit integration leaves out. Works with
9
10
  Siri ("set the security system to away") and Home automations. ecobee removed Smart Security from
@@ -72,76 +73,127 @@ node <plugin folder>/bin/ecobee-login.js --browser # website sign-in
72
73
 
73
74
  | Setting | Default | |
74
75
  |---|---|---|
75
- | `offerNight` | `false` | Adds Night to the Home app. ecobee has no Night mode, so Night arms Stay and the tile keeps showing Night until the state changes (a Stay armed elsewhere shows as Stay). HomeKit only picks up a changed list of modes on a new control, so changing this setting recreates the security system in the Home app: set up scenes and automations that use it again. |
76
+ | `offerNight` | `false` | Adds Night to the Home app. ecobee has no Night mode, so Night arms ecobee's Stay, and the tile keeps showing Night until the state changes (Stay armed in the ecobee app or at the keypad shows as Home). HomeKit only picks up a changed list of modes on a new control, so changing this setting recreates the security system in the Home app: set up scenes and automations that use it again. |
76
77
  | `alarmTrigger` | `"incident"` | When the tile enters **Triggered**: `"incident"` immediately, when ecobee opens an incident as a door or sensor trips while armed (mirrors the ecobee app); `"entryDelay"` only after the entry (disarm) delay runs out without a disarm. Smoke alarms always trigger immediately. |
77
78
  | `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. |
78
- | `allowHolds` | `false` | Lets other Homebridge plugins ask for a **security hold** (see below), e.g. so a robot vacuum can clean while you're away without setting off the motion sensors. Off: hold requests are refused, and a hold left over from before is dropped without re-arming Away. |
79
+ | `allowHolds` | `false` | Lets other plugins, like a robot vacuum, keep the system from arming Away while their task runs (see [Security holds](#security-holds)). |
80
+ | `holdPlugins` | all | The plugins allowed to do that; the settings page lists them. |
81
+ | `armAwayNowSwitch` | `false` | Adds an **Arm Away Now** switch: arms Away immediately and asks any task in progress to stop (a robot goes home). |
82
+ | `taskWaitSeconds` | `120` | How much longer the Away countdown may wait for a task to finish, e.g. a robot getting home (0: don't wait). |
83
+ | `keypadDisarm` | `false` | Turns the security system off when a door is unlocked with a code on its keypad (see [Keypad unlock](#keypad-unlock)). |
84
+ | `keypadLocks` | all | The locks that do that, by serial number; the settings page lists the ones found. |
79
85
  | `airQuality` | `true` | For each thermostat with an air quality sensor: an accessory "&lt;thermostat&gt; 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. |
80
86
  | `co2Alert` | `1000` | CO2 (ppm) at or above which the Carbon Dioxide Sensor reports abnormal levels. |
81
87
 
82
88
  ## How it behaves
83
89
 
84
90
  - **Arm Away** uses ecobee's Away exit delay (60 s by default), just like the app. During the
85
- delay the Home app shows "Arming…" (current Disarmed, target Away). Stay uses the Stay exit delay
86
- (0 by default). Disarm needs no PIN.
91
+ delay the Home app shows "Arming…" (current Off, target Away). Home and Night use ecobee's Stay
92
+ exit delay (0 by default). Off needs no PIN.
87
93
  - **Changes from elsewhere** (ecobee app, keypad, ecobee automations) show up within 10 s, about
88
94
  as fast as in the ecobee app (it polls too), and quickly after an exit delay ends.
89
95
  - **Alarm triggered** while ecobee lists an open incident (see `alarmTrigger` above for when it
90
96
  starts showing). Disarming clears it. Every change in the incident list is logged.
91
- - **Siri:** the Home app calls Stay "Home". Asking Siri for Home or for Stay mode both arm Stay.
97
+ - **Siri:** asking for Home or for Stay mode both set Home (ecobee's Stay).
92
98
  - **Night** is only offered with `offerNight`; ecobee has no Night mode of its own.
93
99
  - After three failed reads in a row the accessory shows a fault; reads back off up to 5 minutes.
94
- - **Security holds** for other plugins, with `allowHolds`: see below.
100
+ - **Keypad unlock:** unlocking a door with its keypad can turn the system off: see below.
101
+ - **Security holds** let other plugins, like a robot vacuum, keep the system from arming Away while they work: see below.
102
+
103
+ ## Keypad unlock
104
+
105
+ Turn on **Disarm when a door is unlocked with its keypad** (`keypadDisarm`) and entering a code on a
106
+ smart lock's keypad turns the security system off, like Nest Guard did with a Nest × Yale lock.
107
+ Family and guests use their lock codes; the lock's own app decides whose code works when (guest
108
+ schedules, expiry), so the plugin needs no codes of its own.
109
+
110
+ - **Which locks:** any lock in Apple Home from the same Homebridge whose plugin reports *how* it was
111
+ unlocked (HomeKit's Lock Last Known Action), for example homebridge-nest-accfactory's Nest × Yale
112
+ locks. The settings page lists the locks found; untick the ones that shouldn't disarm. Locks
113
+ paired to Apple Home directly (not through Homebridge) can't be seen.
114
+ - **Only keypad unlocks** count: not the app, Siri, automations, a key or the thumb turn. Any code
115
+ that opens the lock disarms, yours included.
116
+ - **Speed:** the plugin checks the locks every second; the disarm reaches ecobee about as fast as
117
+ one from the Home app. How quickly the lock reports the unlock depends on the lock and its plugin. Unlock before you open the door: ecobee opens an incident
118
+ as soon as a door opens while armed, and the disarm clears it, as with the ecobee keypad.
119
+ - **Locking** from the outside doesn't arm: most locks can't tell that from the thumb turn inside.
120
+ - A disarm ends any [security hold](#security-holds), as a change from the Home app does.
121
+ - Needs Homebridge's **insecure mode** (Homebridge Settings > Homebridge Insecure Mode / Accessory
122
+ Control; the Homebridge UI's accessory control uses it too): the plugin reads the locks over HAP on
123
+ 127.0.0.1 with the bridge PIN, since each child bridge runs in its own process. The log says if
124
+ it isn't on.
95
125
 
96
126
  ## Security holds
97
127
 
98
- A security hold lets another Homebridge plugin, such as a robot vacuum, keep the motion sensors from
99
- going off while it moves around the house when you're away. The plugin can only *ask*; this plugin
100
- decides, by four rules:
101
-
102
- 1. **Hold:** if the system is armed Away (or arming Away), it's switched to Stay. If an alarm is in
103
- progress, or ecobee can't be read, the hold is refused. Otherwise nothing changes.
104
- 2. **Release:** once **every** plugin that asked is done, and the system is still in Stay, it's
105
- armed Away again (with the normal exit delay).
106
- 3. **Your change wins:** anything someone else does during a hold — disarm, arm Away, a change in
107
- the Home app, an alarm — cancels it, and the system is left as it is.
108
- 4. **No timers:** nothing changes unless a plugin asks or you act.
109
-
110
- Every decision uses ecobee's state read at that moment, not the last poll. Holds are off until you
111
- turn on **Allow security holds** in the settings' **Security holds** section and tick each plugin that
112
- may ask (`holdPlugins`): it lists installed plugins that declare they use holds, and any plugin that
113
- has asked. A plugin that isn't ticked is refused (it can still release a hold it already has).
114
- Turning holds off drops a hold left over from before (without arming Away).
115
-
116
- **Limits** that follow from these rules:
117
-
118
- - **Your own Stay looks like the hold's Stay.** If you disarm and re-arm Stay in the ecobee app or at
119
- the keypad within a few seconds (between two reads), or while the bridge is restarting, the
120
- release still arms Away: ecobee doesn't say who last changed the state. Changes in the Home app are
121
- always seen.
122
- - **Your change wins even with a robot still out.** After you cancel a hold (say, disarm), arming
123
- Away while the robot is still cleaning can set off the motion sensors: a plugin only asks for a
124
- hold when it starts.
125
- - **Plugins identify themselves.** Any plugin running as the homebridge user can reach the socket,
126
- and the plugin name it gives is its own claim: the list keeps honest plugins apart, it isn't a
127
- lock. Two requests with the same name share one hold.
128
- - **A plugin that never releases leaves the system in Stay** until you change it.
129
-
130
- **API** (for plugin authors): a Unix socket at `<homebridge storage>/ecobee-security/control.sock`
131
- (mode 600, homebridge user only), declared in `package.json` as
132
- `"homebridge-security-hold": { "socket": "ecobee-security/control.sock" }` so plugins that support
133
- holds, like homebridge-narwal-freo, can list it. Plugins that ask for holds can declare
134
- `"homebridge-security-hold": { "client": true }` to show up in the list before their first request.
135
- The full API: [Security hold](https://github.com/seanfletchr/homebridge-narwal-freo/blob/main/docs/security-hold.md).
136
-
137
- - `POST /hold?by=<name>&plugin=<package>` → `{ "ok": true, "held": true|false, "state": "…" }`,
138
- or `"ok": false` with a `"reason"`: don't start. `plugin` is optional; without it the plugin is
139
- listed (and allowed) under its `by` name.
140
- - `POST /release?by=<name>&plugin=<package>` → `{ "released": true|false, "state": "…", "waiting": [names] }`;
141
- `waiting` lists holders still out.
142
- - With `allowHolds` off or the plugin not ticked, both answer 403 (a release from a current holder
143
- is always accepted); if ecobee can't be read (release) or isn't connected
144
- yet, a 5xx with `"error"` — try again later. Holds survive restarts (in `state.json`).
128
+ Things that move while you're out set off ecobee's motion sensors: a robot vacuum cleaning, or an AC
129
+ blowing plants around in front of a sensor. **Security holds** let other Homebridge plugins keep the
130
+ system from arming **Away** while their task runs. Instead the system is set to **Home** (Stay in the
131
+ ecobee app): doors and windows stay armed, motion sensors don't.
132
+
133
+ Plugins that support holds include
134
+ [homebridge-narwal-freo](https://github.com/seanfletchr/homebridge-narwal-freo) (robot vacuum). Any
135
+ plugin can add support; see [For plugin authors](#for-plugin-authors).
136
+
137
+ ### Turning it on
138
+
139
+ 1. In this plugin's settings, open **Security holds**, turn on **Allow security holds**, and tick the
140
+ plugins that may use them. (Plugins appear in the list once installed, or after they first ask.)
141
+ 2. Turn on the matching option in the other plugin's settings.
142
+
143
+ ### What happens
144
+
145
+ Using a robot vacuum as the example:
146
+
147
+ | Situation | What the security system does |
148
+ |---|---|
149
+ | The robot starts cleaning while the system is armed **Away** | Switches to Home, and goes back to Away when the robot is done. |
150
+ | The robot starts while the system is set to **Home**, **Night** or **Off** | Nothing changes. |
151
+ | 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. |
152
+ | You want Away **now** | Turn on the **Arm Away Now** switch (see below). It arms Away right away and sends the robot home. |
153
+ | 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. |
154
+ | 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. |
155
+ | You change the mode yourself while the robot is cleaning (in any app or at the keypad) | Your choice wins: when the robot is done, the system is left as you set it. |
156
+ | An alarm is going off, or ecobee can't be reached | The robot isn't allowed to start. |
157
+
158
+ Other plugins work the same way; what "stop" means is up to each one (a robot pauses or goes home,
159
+ an AC turns off). Several at once are fine: Away comes back once all of them are done.
160
+
161
+ ### Settings
162
+
163
+ In the **Security holds** section of the settings:
164
+
165
+ - **Allow security holds** (`allowHolds`) and the list of plugins allowed to ask (`holdPlugins`).
166
+ Turning holds off cancels any hold in progress without re-arming Away.
167
+ - **Arm Away Now switch** (`armAwayNowSwitch`): adds a switch to the Home app that arms Away
168
+ immediately, as from the ecobee app, asking any task in progress to stop (a robot goes home). Use it
169
+ from the Home app, a scene, or Siri ("turn on Arm Away Now").
170
+ - **Extra time for tasks to finish** (`taskWaitSeconds`, default 120 seconds, 0 to turn it off): how
171
+ much longer the Away countdown may wait for a task to wrap up, e.g. a robot getting back to its
172
+ base. It arms as soon as the task is done.
173
+
174
+ ### Good to know
175
+
176
+ - **Only Away is affected.** If your ecobee Stay mode also watches the motion sensors in question,
177
+ holds won't help there.
178
+ - **A quick re-arm in the ecobee app can be missed.** If you disarm and re-arm Stay within a few
179
+ seconds in the ecobee app or at the keypad (or while Homebridge restarts), the plugin may not
180
+ notice, and will arm Away when the task is done. Changes in the Home app are always noticed.
181
+ - **A plugin that can't be told to stop** keeps going when Away is armed at the keypad or in the
182
+ ecobee app. The log says so.
183
+ - **A plugin that never reports it's done** leaves the system in Home until you change it.
184
+ (homebridge-narwal-freo also lets go if its robot hasn't moved for 10 minutes, e.g. when it's
185
+ stuck.)
186
+ - **The allowed-plugins list is a courtesy, not a lock.** Any plugin running in your Homebridge can
187
+ reach the hold API and give any name.
188
+
189
+ ### For plugin authors
190
+
191
+ Holds suit any plugin whose task could trip a motion sensor. Plugins ask over a Unix socket at `<homebridge storage>/ecobee-security/control.sock` (homebridge user
192
+ only). This plugin declares it in `package.json` as
193
+ `"homebridge-security-hold": { "socket": "ecobee-security/control.sock" }`; plugins that ask for holds
194
+ can declare `"homebridge-security-hold": { "client": true }` to appear in the settings list. The API
195
+ (hold, release, and being asked to stop or finish before Away arms) is documented in
196
+ [Security hold](https://github.com/seanfletchr/homebridge-narwal-freo/blob/main/docs/security-hold.md).
145
197
 
146
198
  ## API notes
147
199
 
@@ -3,7 +3,7 @@
3
3
  "pluginType": "platform",
4
4
  "singular": true,
5
5
  "customUi": true,
6
- "headerDisplay": "Shows ecobee Smart Security as a security system in Apple Home (arm Stay / Away, disarm, alarm state). Unofficial: uses the same ecobee cloud as the app.",
6
+ "headerDisplay": "Adds ecobee Smart Security to Apple Home: set it to Home, Away or Off, and see alarms. Unofficial. It uses the same ecobee cloud as the ecobee app.",
7
7
  "schema": {
8
8
  "type": "object",
9
9
  "properties": {
@@ -19,18 +19,18 @@
19
19
  "x-schema-form": {
20
20
  "type": "password"
21
21
  },
22
- "description": "Filled in when you sign in above. Only needed again if ecobee signs the plugin out (password change, 'sign out everywhere')."
22
+ "description": "Filled in when you sign in. You only need a new one if ecobee signs the plugin out, for example after a password change."
23
23
  },
24
24
  "homeId": {
25
25
  "title": "Home ID",
26
26
  "type": "string",
27
- "description": "Only needed if the account has more than one home; the log lists them."
27
+ "description": "Only needed if your account has more than one home. The log lists your homes."
28
28
  },
29
29
  "offerNight": {
30
30
  "title": "Offer Night",
31
31
  "type": "boolean",
32
32
  "default": false,
33
- "description": "Adds the Night setting for more specific automations. ecobee has no \"Night\" mode, so Night arms Stay. Changing this recreates the security system in the Home app; scenes and automations using it must be set up again."
33
+ "description": "Adds a Night mode to use in automations. ecobee has no Night mode, so Night arms ecobee's Stay. Changing this recreates the security system in the Home app, so you need to set up its scenes and automations again."
34
34
  },
35
35
  "alarmTrigger": {
36
36
  "title": "Enter Triggered State",
@@ -44,25 +44,25 @@
44
44
  ]
45
45
  },
46
46
  {
47
- "title": "After the Entry/Disarm delay",
47
+ "title": "After the entry delay",
48
48
  "enum": [
49
49
  "entryDelay"
50
50
  ]
51
51
  }
52
52
  ],
53
- "description": "ecobee opens an incident as soon as a door or sensor trips while armed. \"After the Entry/Disarm delay\" waits until that delay runs out without a disarm, so automations on Triggered don't fire while you're walking in to disarm. Smoke alarms always trigger immediately."
53
+ "description": "Immediately: as soon as a door or sensor trips while armed, like the ecobee app. After the entry delay: only if no one disarms in time, so automations don't run while you walk in. Smoke alarms always trigger immediately."
54
54
  },
55
55
  "smokeSensor": {
56
56
  "title": "Smoke sensor",
57
57
  "type": "boolean",
58
58
  "default": true,
59
- "description": "Adds a separate \"Smoke Alarm\" accessory to the Home app that detects smoke whenever ecobee reports a smoke-alarm incident, so you can use it in automations and get Home app smoke notifications."
59
+ "description": "Adds a Smoke Alarm accessory that detects smoke when ecobee reports a smoke alarm. Use it for Home app notifications and automations."
60
60
  },
61
61
  "allowHolds": {
62
62
  "title": "Allow security holds",
63
63
  "type": "boolean",
64
64
  "default": false,
65
- "description": "Lets other Homebridge plugins (for example a robot vacuum, so it can clean while you're away) switch Away to Stay for a while and back to Away when they're done. Each plugin also has to be allowed in holdPlugins (the settings page lists the ones that asked). See \"Security holds\" in the README."
65
+ "description": "Lets other Homebridge plugins, like a robot vacuum, keep the system from arming Away while they work: if it's armed Away it's switched to Home (ecobee's Stay), and Away comes back when they're done. Away asked for in the Home app meanwhile waits until they're done. Each plugin also has to be allowed in holdPlugins (the settings page lists the ones that asked). See \"Security holds\" in the README."
66
66
  },
67
67
  "holdPlugins": {
68
68
  "title": "Plugins allowed to ask for holds",
@@ -70,20 +70,48 @@
70
70
  "items": {
71
71
  "type": "string"
72
72
  },
73
- "description": "Package names (or, for a plugin that doesn't say, the name it asks with). Without this list, every plugin may ask once Allow security holds is on."
73
+ "description": "Package names of the plugins that may ask, or the name a plugin asks with if it gives no package. With no list, all plugins may ask while Allow security holds is on."
74
+ },
75
+ "armAwayNowSwitch": {
76
+ "title": "Arm Away Now switch",
77
+ "type": "boolean",
78
+ "default": false,
79
+ "description": "Adds an Arm Away Now switch to the Home app (with Allow security holds on). Turning it on arms Away now, with the normal exit delay, and asks any task that's running to stop (a robot goes back to its base, or stops where it is if it can't make it in time). Away from the security tile, scenes, automations and Siri waits until robots are done instead."
80
+ },
81
+ "taskWaitSeconds": {
82
+ "title": "Extra time for tasks to finish (seconds)",
83
+ "type": "integer",
84
+ "default": 120,
85
+ "minimum": 0,
86
+ "maximum": 300,
87
+ "description": "If Away is armed while a task is running, like a robot heading back to its base, the countdown waits up to this much longer, and arms as soon as it's done. 0: no waiting."
88
+ },
89
+ "keypadDisarm": {
90
+ "title": "Disarm when a door is unlocked with its keypad",
91
+ "type": "boolean",
92
+ "default": false,
93
+ "description": "Entering a code on a smart lock's keypad turns the security system off, so family and guests can use their lock codes. Works with locks in Apple Home from this Homebridge that report keypad unlocks. Needs Homebridge's insecure mode. See \"Keypad unlock\" in the README."
94
+ },
95
+ "keypadLocks": {
96
+ "title": "Locks that disarm",
97
+ "type": "array",
98
+ "items": {
99
+ "type": "string"
100
+ },
101
+ "description": "Serial numbers of the locks that disarm (the settings page lists the ones found). With no list, every lock does."
74
102
  },
75
103
  "airQuality": {
76
104
  "title": "Air quality sensors",
77
105
  "type": "boolean",
78
106
  "default": true,
79
- "description": "For ecobee thermostats with an air quality sensor (ecobee Premium): adds an Air Quality Sensor (overall level and VOC) and a Carbon Dioxide Sensor (CO2 in ppm) per thermostat. ecobee's own HomeKit integration doesn't show these. Updated every 5 minutes."
107
+ "description": "Adds 2 sensors for each ecobee Premium thermostat: air quality (with VOC) and CO2. ecobee's own HomeKit integration doesn't include them. Updates every 5 minutes."
80
108
  },
81
109
  "co2Alert": {
82
110
  "title": "CO2 alert level (ppm)",
83
111
  "type": "integer",
84
112
  "default": 1000,
85
113
  "minimum": 400,
86
- "description": "The Carbon Dioxide Sensor reports abnormal CO2 at or above this level, for Home app notifications and automations (for example, turning on ventilation).",
114
+ "description": "At or above this level, the CO2 sensor reports abnormal CO2. Use it for notifications and automations, like turning on ventilation.",
87
115
  "condition": {
88
116
  "functionBody": "return model.airQuality !== false;"
89
117
  }
@@ -8,7 +8,7 @@
8
8
 
9
9
  <div id="signed-in" hidden>
10
10
  <div class="alert alert-success mb-2" role="status" id="signed-in-text">Signed in to ecobee.</div>
11
- <p class="hint mb-2" id="signed-in-hint">You only need to sign in again if the log says ecobee signed the plugin out (for example after a password change).</p>
11
+ <p class="hint mb-2" id="signed-in-hint">Sign in again only if the log says ecobee signed the plugin out, for example after a password change.</p>
12
12
  <button type="button" class="btn btn-secondary" id="sign-in-again">Sign in again</button>
13
13
  </div>
14
14
 
@@ -22,7 +22,7 @@
22
22
  <div class="mb-2">
23
23
  <label for="password" class="form-label">Password</label>
24
24
  <input type="password" class="form-control" id="password" autocomplete="current-password" required>
25
- <div class="hint mt-1">Sent only to ecobee to sign in. The plugin keeps a sign-in token, never your password.</div>
25
+ <div class="hint mt-1">Sent only to ecobee. The plugin saves a sign-in token, not your password.</div>
26
26
  </div>
27
27
  <button type="submit" class="btn btn-primary">Sign in</button>
28
28
  <button type="button" class="btn btn-link" id="sign-in-cancel" hidden>Cancel</button>
@@ -41,12 +41,12 @@
41
41
 
42
42
  <details class="mt-3" id="browser">
43
43
  <summary>Sign in on ecobee's website instead</summary>
44
- <p class="hint mt-2 mb-2">Use this if signing in above keeps failing (for example if ecobee asks for a CAPTCHA). You'll need a desktop browser with developer tools.</p>
44
+ <p class="hint mt-2 mb-2">Use this if signing in above keeps failing, for example if ecobee asks for a CAPTCHA. You need a desktop browser with developer tools.</p>
45
45
  <ol class="small ps-3">
46
46
  <li>In Chrome, open a new tab, open DevTools (Option-Command-I or F12), go to <b>Network</b> and tick <b>Preserve log</b>.</li>
47
47
  <li>In that tab, open <a id="browser-link" href="#" target="_blank" rel="noopener">this sign-in link</a> and sign in.</li>
48
48
  <li>When the page goes blank, type <code>code=</code> in the Network filter, right-click the entry and choose <b>Copy &gt; Copy URL</b>. It starts with <code>com.ecobee.athenamobile://</code></li>
49
- <li>Paste it here straight away (the code expires within a minute):</li>
49
+ <li>Paste it here within a minute, before it expires:</li>
50
50
  </ol>
51
51
  <form id="browser-form" class="d-flex gap-2">
52
52
  <input type="text" class="form-control" id="callback" placeholder="com.ecobee.athenamobile://…" required>
@@ -67,20 +67,20 @@
67
67
  <div class="mb-3">
68
68
  <label for="s-homeId" class="form-label">Home ID</label>
69
69
  <input class="form-control" type="text" id="s-homeId" data-key="homeId" data-type="text" data-default="">
70
- <div class="hint mt-1">Only needed if the account has more than one home; the log lists them.</div>
70
+ <div class="hint mt-1">Only needed if your account has more than one home. The log lists your homes.</div>
71
71
  </div>
72
72
  <div class="mb-3">
73
73
  <div class="form-check form-switch">
74
74
  <input class="form-check-input" type="checkbox" role="switch" id="s-offerNight" data-key="offerNight" data-type="bool" data-default="false">
75
75
  <label class="form-check-label" for="s-offerNight">Offer Night</label>
76
76
  </div>
77
- <div class="hint">Adds the Night setting for more specific automations. ecobee has no "Night" mode, so Night arms Stay.</div>
78
- <div class="hint mt-1">Changing this recreates the security system in the Home app; scenes and automations using it must be set up again.</div>
77
+ <div class="hint">Adds a Night mode to use in automations. ecobee has no Night mode, so Night arms ecobee's Stay.</div>
78
+ <div class="hint mt-1">Changing this recreates the security system in the Home app, so you need to set up its scenes and automations again.</div>
79
79
  </div>
80
80
  <div class="mb-0">
81
81
  <label for="s-alarmTrigger" class="form-label">Enter Triggered State</label>
82
- <select class="form-select" id="s-alarmTrigger" data-key="alarmTrigger" data-type="select" data-default="incident"><option value="incident">Immediately (mirror ecobee app)</option><option value="entryDelay">After the Entry/Disarm delay</option></select>
83
- <div class="hint mt-1">ecobee opens an incident as soon as a door or sensor trips while armed. "After the Entry/Disarm delay" waits until that delay runs out without a disarm, so automations on Triggered don't fire while you're walking in to disarm. Smoke alarms always trigger immediately.</div>
82
+ <select class="form-select" id="s-alarmTrigger" data-key="alarmTrigger" data-type="select" data-default="incident"><option value="incident">Immediately (mirror ecobee app)</option><option value="entryDelay">After the entry delay</option></select>
83
+ <div class="hint mt-1">Immediately: as soon as a door or sensor trips while armed, like the ecobee app. After the entry delay: only if no one disarms in time, so automations don't run while you walk in. Smoke alarms always trigger immediately.</div>
84
84
  </div>
85
85
  </div>
86
86
 
@@ -91,19 +91,34 @@
91
91
  <input class="form-check-input" type="checkbox" role="switch" id="s-smokeSensor" data-key="smokeSensor" data-type="bool" data-default="true">
92
92
  <label class="form-check-label" for="s-smokeSensor">Smoke sensor</label>
93
93
  </div>
94
- <div class="hint">Adds a separate "Smoke Alarm" accessory to the Home app that detects smoke whenever ecobee reports a smoke-alarm incident, so you can use it in automations and get Home app smoke notifications.</div>
94
+ <div class="hint">Adds a Smoke Alarm accessory that detects smoke when ecobee reports a smoke alarm. Use it for Home app notifications and automations.</div>
95
95
  </div>
96
96
  <div class="mb-3">
97
97
  <div class="form-check form-switch">
98
98
  <input class="form-check-input" type="checkbox" role="switch" id="s-airQuality" data-key="airQuality" data-type="bool" data-default="true">
99
99
  <label class="form-check-label" for="s-airQuality">Air quality sensors</label>
100
100
  </div>
101
- <div class="hint">For ecobee thermostats with an air quality sensor (ecobee Premium): adds an Air Quality Sensor (overall level and VOC) and a Carbon Dioxide Sensor (CO2 in ppm) per thermostat. ecobee's own HomeKit integration doesn't show these. Updated every 5 minutes.</div>
101
+ <div class="hint">Adds 2 sensors for each ecobee Premium thermostat: air quality (with VOC) and CO2. ecobee's own HomeKit integration doesn't include them. Updates every 5 minutes.</div>
102
102
  </div>
103
103
  <div class="mb-0" id="co2-box">
104
104
  <label for="s-co2Alert" class="form-label">CO2 alert level (ppm)</label>
105
105
  <input class="form-control" type="number" step="1" min="400" id="s-co2Alert" data-key="co2Alert" data-type="int" data-default="1000">
106
- <div class="hint mt-1">The Carbon Dioxide Sensor reports abnormal CO2 at or above this level, for Home app notifications and automations (for example, turning on ventilation).</div>
106
+ <div class="hint mt-1">At or above this level, the CO2 sensor reports abnormal CO2. Use it for notifications and automations, like turning on ventilation.</div>
107
+ </div>
108
+ </div>
109
+
110
+ <div class="card card-body mb-3" id="keypad-card" hidden>
111
+ <h5 class="mb-2">Door keypads</h5>
112
+ <div class="form-check form-switch mb-1">
113
+ <input class="form-check-input" type="checkbox" role="switch" id="keypad-disarm">
114
+ <label class="form-check-label" for="keypad-disarm">Disarm when a door is unlocked with its keypad</label>
115
+ </div>
116
+ <p class="hint mb-2">Entering a code on a smart lock's keypad turns the security system off, so family and guests
117
+ can use their lock codes. Restart the bridge after changing this.
118
+ <a href="https://github.com/seanfletchr/homebridge-ecobee-security#keypad-unlock" target="_blank" rel="noopener">Learn more…</a></p>
119
+ <div id="keypad-locks-box" hidden>
120
+ <div class="mb-1">Locks that disarm</div>
121
+ <div id="keypad-locks"></div>
107
122
  </div>
108
123
  </div>
109
124
 
@@ -113,12 +128,23 @@
113
128
  <input class="form-check-input" type="checkbox" role="switch" id="allow-holds">
114
129
  <label class="form-check-label" for="allow-holds">Allow security holds</label>
115
130
  </div>
116
- <p class="hint mb-2">Lets supported plugins, like a robot vacuum, switch Away to Home while they work and back to
117
- Away when they're done.
131
+ <p class="hint mb-2">Lets supported plugins, like a robot vacuum, keep the system from arming Away while they work:
132
+ Away is switched to Home, and comes back when they're done. Away asked for in the Home app meanwhile
133
+ waits until they're done.
118
134
  <a href="https://github.com/seanfletchr/homebridge-ecobee-security#security-holds" target="_blank" rel="noopener">Learn more…</a></p>
119
135
  <div id="hold-plugins-box" hidden>
120
136
  <div class="mb-1">Allowed plugins</div>
121
137
  <div id="hold-plugins"></div>
138
+ <div class="form-check form-switch mt-3 mb-1">
139
+ <input class="form-check-input" type="checkbox" role="switch" id="arm-away-now">
140
+ <label class="form-check-label" for="arm-away-now">Arm Away Now switch</label>
141
+ </div>
142
+ <div class="hint">Adds a switch to the Home app that arms Away now and asks any task that's running to stop (a robot goes back to its base). Restart the
143
+ bridge after changing this.</div>
144
+ <label for="s-taskWaitSeconds" class="form-label mt-3 mb-1">Extra time for tasks to finish (seconds)</label>
145
+ <input class="form-control" type="number" step="10" min="0" max="300" id="s-taskWaitSeconds" data-key="taskWaitSeconds" data-type="int" data-default="120">
146
+ <div class="hint mt-1">If Away is armed while a task is running, like a robot heading back to its base, the countdown
147
+ waits up to this much longer, and arms as soon as it's done. 0: no waiting.</div>
122
148
  </div>
123
149
  </div>
124
150
 
@@ -141,7 +167,7 @@
141
167
  $('signed-in').hidden = !signedIn;
142
168
  $('signin').hidden = signedIn;
143
169
  $('signed-in-text').textContent = justSignedIn
144
- ? 'Signed in and saved. Restart the bridge this plugin runs on (or Homebridge) to use the new sign-in.'
170
+ ? 'Signed in and saved. Restart this plugin\'s bridge, or Homebridge, to use the new sign-in.'
145
171
  : 'Signed in to ecobee.';
146
172
  $('sign-in-cancel').hidden = !block?.refreshToken;
147
173
  $('signin-hint').textContent = block?.refreshToken
@@ -177,6 +203,7 @@
177
203
  homebridge.toast.success('Signed in to ecobee.');
178
204
  await showStatus({ justSignedIn: true });
179
205
  await showSettings();
206
+ await showKeypad();
180
207
  await showHolds();
181
208
  }
182
209
 
@@ -302,6 +329,7 @@
302
329
  $('holds-card').hidden = !block.refreshToken;
303
330
  $('allow-holds').checked = block.allowHolds === true;
304
331
  $('hold-plugins-box').hidden = block.allowHolds !== true;
332
+ $('arm-away-now').checked = block.armAwayNowSwitch === true;
305
333
  const plugins = await homebridge.request('/hold-plugins').catch(() => []);
306
334
  const box = $('hold-plugins');
307
335
  box.textContent = '';
@@ -350,8 +378,70 @@
350
378
  await homebridge.updatePluginConfig([block, ...blocks.slice(1)]);
351
379
  });
352
380
 
381
+ $('arm-away-now').addEventListener('change', async () => {
382
+ const blocks = await homebridge.getPluginConfig();
383
+ const block = blocks[0];
384
+ block.armAwayNowSwitch = $('arm-away-now').checked;
385
+ await homebridge.updatePluginConfig([block, ...blocks.slice(1)]);
386
+ });
387
+
388
+ // ── Door keypads ──
389
+
390
+ async function showKeypad() {
391
+ const [block = {}] = await homebridge.getPluginConfig();
392
+ $('keypad-card').hidden = !block.refreshToken;
393
+ $('keypad-disarm').checked = block.keypadDisarm === true;
394
+ $('keypad-locks-box').hidden = block.keypadDisarm !== true;
395
+ const locks = await homebridge.request('/keypad-locks').catch(() => []);
396
+ const box = $('keypad-locks');
397
+ box.textContent = '';
398
+ if (!locks.length) {
399
+ const p = document.createElement('p');
400
+ p.className = 'hint mb-0';
401
+ p.textContent = block.keypadDisarm === true
402
+ ? 'No lock found yet. Locks show up here a minute after the bridge restarts; the log says if none report keypad unlocks.'
403
+ : 'Turn this on and restart the bridge to find your locks.';
404
+ box.append(p);
405
+ return;
406
+ }
407
+ // Without a list, every lock disarms.
408
+ const allowed = Array.isArray(block.keypadLocks) ? block.keypadLocks : locks.map(l => l.key);
409
+ for (const lock of locks) {
410
+ const id = `lock-${lock.key.replace(/[^a-z0-9]/gi, '-')}`;
411
+ const input = Object.assign(document.createElement('input'), {
412
+ className: 'form-check-input', type: 'checkbox', id, checked: allowed.includes(lock.key),
413
+ });
414
+ input.addEventListener('change', () => setLock(locks, lock.key, input.checked));
415
+ const label = Object.assign(document.createElement('label'), { className: 'form-check-label', htmlFor: id });
416
+ label.textContent = lock.name;
417
+ const hint = Object.assign(document.createElement('div'), { className: 'hint' });
418
+ hint.textContent = lock.bridge;
419
+ const row = Object.assign(document.createElement('div'), { className: 'form-check mb-1' });
420
+ row.append(input, label, hint);
421
+ box.append(row);
422
+ }
423
+ }
424
+
425
+ async function setLock(locks, key, on) {
426
+ const blocks = await homebridge.getPluginConfig();
427
+ const block = blocks[0];
428
+ const current = Array.isArray(block.keypadLocks) ? block.keypadLocks : locks.map(l => l.key);
429
+ block.keypadLocks = on ? [...new Set([...current, key])] : current.filter(k => k !== key);
430
+ await homebridge.updatePluginConfig([block, ...blocks.slice(1)]);
431
+ }
432
+
433
+ $('keypad-disarm').addEventListener('change', async () => {
434
+ const blocks = await homebridge.getPluginConfig();
435
+ const block = blocks[0];
436
+ block.keypadDisarm = $('keypad-disarm').checked;
437
+ $('keypad-locks-box').hidden = !block.keypadDisarm;
438
+ await homebridge.updatePluginConfig([block, ...blocks.slice(1)]);
439
+ await showKeypad();
440
+ });
441
+
353
442
  await showStatus();
354
443
  await showSettings();
444
+ await showKeypad();
355
445
  await showHolds();
356
446
  })();
357
447
  </script>