@homebridge-plugins/homebridge-firstalert 0.0.1-beta.1 → 0.0.1-beta.2

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.
Files changed (63) hide show
  1. package/docs/variables/default.html +1 -1
  2. package/package.json +1 -1
  3. package/dist/homebridge-ui/public/index.html +0 -548
  4. package/dist/src/api/resideoClient.d.ts +0 -32
  5. package/dist/src/api/resideoClient.d.ts.map +0 -1
  6. package/dist/src/api/resideoClient.js +0 -76
  7. package/dist/src/api/resideoClient.js.map +0 -1
  8. package/dist/src/devices/device.d.ts +0 -40
  9. package/dist/src/devices/device.d.ts.map +0 -1
  10. package/dist/src/devices/device.js +0 -207
  11. package/dist/src/devices/device.js.map +0 -1
  12. package/dist/src/devices/leaksensors.d.ts +0 -34
  13. package/dist/src/devices/leaksensors.d.ts.map +0 -1
  14. package/dist/src/devices/leaksensors.js +0 -163
  15. package/dist/src/devices/leaksensors.js.map +0 -1
  16. package/dist/src/devices/smoke.d.ts +0 -35
  17. package/dist/src/devices/smoke.d.ts.map +0 -1
  18. package/dist/src/devices/smoke.js +0 -150
  19. package/dist/src/devices/smoke.js.map +0 -1
  20. package/dist/src/devices/thermostats.d.ts +0 -42
  21. package/dist/src/devices/thermostats.d.ts.map +0 -1
  22. package/dist/src/devices/thermostats.js +0 -192
  23. package/dist/src/devices/thermostats.js.map +0 -1
  24. package/dist/src/devices/valve.d.ts +0 -21
  25. package/dist/src/devices/valve.d.ts.map +0 -1
  26. package/dist/src/devices/valve.js +0 -131
  27. package/dist/src/devices/valve.js.map +0 -1
  28. package/dist/src/homebridge-ui/server.d.ts +0 -5
  29. package/dist/src/homebridge-ui/server.d.ts.map +0 -1
  30. package/dist/src/homebridge-ui/server.js +0 -95
  31. package/dist/src/homebridge-ui/server.js.map +0 -1
  32. package/dist/src/index.d.ts +0 -4
  33. package/dist/src/index.d.ts.map +0 -1
  34. package/dist/src/index.js +0 -7
  35. package/dist/src/index.js.map +0 -1
  36. package/dist/src/platform.d.ts +0 -18
  37. package/dist/src/platform.d.ts.map +0 -1
  38. package/dist/src/platform.js +0 -108
  39. package/dist/src/platform.js.map +0 -1
  40. package/dist/src/settings.d.ts +0 -341
  41. package/dist/src/settings.d.ts.map +0 -1
  42. package/dist/src/settings.js +0 -25
  43. package/dist/src/settings.js.map +0 -1
  44. package/dist/src/utils.d.ts +0 -21
  45. package/dist/src/utils.d.ts.map +0 -1
  46. package/dist/src/utils.js +0 -58
  47. package/dist/src/utils.js.map +0 -1
  48. package/dist/test/index.test.d.ts +0 -2
  49. package/dist/test/index.test.d.ts.map +0 -1
  50. package/dist/test/index.test.js +0 -14
  51. package/dist/test/index.test.js.map +0 -1
  52. package/dist/test/platform.test.d.ts +0 -2
  53. package/dist/test/platform.test.d.ts.map +0 -1
  54. package/dist/test/platform.test.js +0 -56
  55. package/dist/test/platform.test.js.map +0 -1
  56. package/dist/test/settings.test.d.ts +0 -2
  57. package/dist/test/settings.test.d.ts.map +0 -1
  58. package/dist/test/settings.test.js +0 -48
  59. package/dist/test/settings.test.js.map +0 -1
  60. package/dist/test/utils.test.d.ts +0 -2
  61. package/dist/test/utils.test.d.ts.map +0 -1
  62. package/dist/test/utils.test.js +0 -17
  63. package/dist/test/utils.test.js.map +0 -1
@@ -1 +1 @@
1
- <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @homebridge-plugins/homebridge-firstalert</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-firstalert"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@homebridge-plugins/homebridge-firstalert</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=&gt;</span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/homebridge-plugins/homebridge-firstalert/blob/4e9b7a0dafe971e2a3d4653fe9b6c5b65ad9c47d/src/index.ts#L11">index.ts:11</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@homebridge-plugins/homebridge-firstalert</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>default | @homebridge-plugins/homebridge-firstalert</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-firstalert"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">@homebridge-plugins/homebridge-firstalert</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="" aria-current="page">default</a></li></ul><h1>Variable default</h1></div><div class="tsd-signature"><span class="tsd-kind-variable">default</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span> <span class="tsd-signature-symbol">=&gt;</span> <span class="tsd-signature-type">void</span></div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter-signature"><ul class="tsd-signatures"><li class="tsd-signature" id="__type"><span class="tsd-signature-symbol">(</span><span class="tsd-kind-parameter">api</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">API</span><span class="tsd-signature-symbol">)</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">void</span></li><li class="tsd-description"><div class="tsd-parameters"><h4 class="tsd-parameters-title">Parameters</h4><ul class="tsd-parameter-list"><li><span><span class="tsd-kind-parameter">api</span>: <span class="tsd-signature-type">API</span></span></li></ul></div><h4 class="tsd-returns-title">Returns <span class="tsd-signature-type">void</span></h4></li></ul></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/homebridge-plugins/homebridge-firstalert/blob/b438f4ff5c891fed1ac79d592879d0666845d890/src/index.ts#L11">index.ts:11</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">@homebridge-plugins/homebridge-firstalert</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer></footer><div class="overlay"></div></body></html>
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@homebridge-plugins/homebridge-firstalert",
3
3
  "displayName": "FirstAlert",
4
4
  "type": "module",
5
- "version": "0.0.1-beta.1",
5
+ "version": "0.0.1-beta.2",
6
6
  "description": "The FirstAlert plugin allows you to access your FirstAlert device(s) from HomeKit.",
7
7
  "author": {
8
8
  "name": "donavanbecker",
@@ -1,548 +0,0 @@
1
- <p class="text-center">
2
- <img
3
- src="https://raw.githubusercontent.com/homebridge-plugins/homebridge-firstalert/latest/branding/Homebridge_x_Resideo.svg"
4
- alt="homebridge-firstalert logo" style="width: 40%;" />
5
- </p>
6
- <div id="pageIntro" style="display: none;">
7
- <p class="lead text-center">Thank you for installing <strong>homebridge-firstalert</strong></p>
8
- <p class="lead text-center">Before continuing:</p>
9
- <ol>
10
- <li class="mb-3">Login / create an account at <a href="https://developer.honeywellhome.com/user" target="_blank"
11
- rel="noreferrer noopener">https://developer.honeywellhome.com/user</a>.</li>
12
- <li class="mb-3">Click <strong>Create New App</strong>.</li>
13
- <li class="mb-3">
14
- Give your application a name, and enter the 'Callback URL' exactly as it is displayed below.
15
- <br>
16
- <div class="input-group mt-3">
17
- <input type="text" class="form-control" disabled id="copyMe">
18
- <div class="input-group-append">
19
- <button class="btn btn-primary m-0 py-0 px-3" onclick="copyMyText()" type="button">
20
- <svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" fill="currentColor"
21
- class="mb-1 bi bi-clipboard" viewBox="0 0 16 16">
22
- <path
23
- d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z" />
24
- <path
25
- d="M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z" />
26
- </svg>
27
- </button>
28
- </div>
29
- </div>
30
- </li>
31
- <li>Enter the generated 'Consumer Key' and 'Consumer Secret' on the next page.</li>
32
- </ol>
33
- <div class="text-center">
34
- <button type="button" class="btn btn-primary" id="introLink">Continue &rarr;</button>
35
- </div>
36
- </div>
37
- <div id="menuWrapper" class="btn-group w-100 mb-0" role="group" aria-label="UI Menu" style="display: none;">
38
- <button type="button" class="btn btn-primary ml-0" id="menuAccount">
39
- Account
40
- </button>
41
- <button type="button" class="btn btn-primary" id="menuSettings">
42
- Settings
43
- </button>
44
- <button type="button" class="btn btn-primary" id="menuDevices">
45
- Devices
46
- </button>
47
- <button type="button" class="btn btn-primary mr-0" id="menuHome">
48
- Support
49
- </button>
50
- </div>
51
- <div id="pageAccount" class="mt-4" style="display: none;">
52
- <div class="alert alert-warning" style="display: none;" id="validateForm">
53
- Please enter both values
54
- </div>
55
- <div class="alert alert-success" style="display: none;" id="linkSuccess">
56
- Config saved, please close this window and restart Homebridge
57
- </div>
58
- <div class="form-group">
59
- <label for="inputConsumerKey">Consumer Key <span class="text-danger">*</span></label>
60
- <input type="text" class="form-control" id="inputConsumerKey">
61
- </div>
62
- <div class="form-group">
63
- <label for="inputConsumerSecret">Consumer Secret <span class="text-danger">*</span></label>
64
- <input type="text" class="form-control" id="inputConsumerSecret">
65
- </div>
66
- <div class="form-group text-center">
67
- <button type="button" class="btn btn-primary" id="backToIntro">&larr;</button>
68
- <button type="button" class="btn btn-primary" id="linkButton">Continue &rarr;</button>
69
- <button type="button" class="btn btn-danger" id="unLinkButton">Unlink Account &rarr;</button>
70
- </div>
71
- </div>
72
- <div id="pageDevices" class="mt-4" style="display: none;">
73
- <div id="deviceInfo">
74
- <form>
75
- <div class="form-group">
76
- <select class="form-control" id="deviceSelect"></select>
77
- </div>
78
- </form>
79
- <table class="table w-100" id="deviceTable" style="display: none;">
80
- <thead>
81
- <tr class="table-active">
82
- <th scope="col" style="width: 40%;">Device Name</th>
83
- <th scope="col" style="width: 60%;" id="displayName"></th>
84
- </tr>
85
- </thead>
86
- <tbody>
87
- <tr>
88
- <th scope="row">Device ID</th>
89
- <td id="deviceID"></td>
90
- </tr>
91
- <tr>
92
- <th scope="row">Model</th>
93
- <td id="model"></td>
94
- </tr>
95
- <tr>
96
- <th scope="row">Firmware Version</th>
97
- <td id="firmwareRevision"></td>
98
- </tr>
99
- </tbody>
100
- </table>
101
- </div>
102
- </div>
103
- <div id="pageSupport" class="mt-4" style="display: none;">
104
- <p class="text-center lead">Thank you for using <strong>homebridge-firstalert</strong></p>
105
- <p class="text-center">The links below will take you to our GitHub wiki</p>
106
- <h5>Setup</h5>
107
- <ul>
108
- <li>
109
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki" target="_blank">Wiki Home</a>
110
- </li>
111
- <li>
112
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Configuration"
113
- target="_blank">Configuration</a>
114
- </li>
115
- <li>
116
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Beta-Version" target="_blank">Beta
117
- Version</a>
118
- </li>
119
- <li>
120
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Node-Version" target="_blank">Node
121
- Version</a>
122
- </li>
123
- <li>
124
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Uninstallation"
125
- target="_blank">Uninstallation</a>
126
- </li>
127
- </ul>
128
- <h5>Features</h5>
129
- <ul>
130
- <li>
131
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Supported-Devices"
132
- target="_blank">Supported
133
- Devices</a>
134
- </li>
135
- <li>
136
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Fan-Modes" target="_blank">Fan
137
- Modes</a>
138
- </li>
139
- </ul>
140
- <h5>Help/About</h5>
141
- <ul>
142
- <li>
143
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/issues/new/choose" target="_blank">Support
144
- Request</a>
145
- </li>
146
- <li>
147
- <a href="https://github.com/homebridge-plugins/homebridge-firstalert/blob/latest/CHANGELOG.md"
148
- target="_blank">Changelog</a>
149
- </li>
150
- <li>
151
- <a href="https://github.com/sponsors/donavanbecker" target="_blank">About Me</a>
152
- </li>
153
- </ul>
154
- <h5>Disclaimer</h5>
155
- <ul>
156
- <li>
157
- I am in no way affiliated with FirstAlert and this plugin is a personal project that I maintain in
158
- my free time.
159
- </li>
160
- <li>
161
- Use this plugin entirely at your own risk - please see licence for more information.
162
- </li>
163
- </ul>
164
- </div>
165
- <script>
166
- ; (async () => {
167
- try {
168
- const currentConfig = await homebridge.getPluginConfig()
169
- const hostname = window.location.hostname
170
- try {
171
- await homebridge.request('Start FirstAlert Login Server')
172
- } catch (err) {
173
- const msg = err.message
174
- homebridge.toast.error(msg, 'HTTP Server Not Started')
175
- }
176
- homebridge.addEventListener('creds-received', async event => {
177
- try {
178
- if (event.data.access && event.data.refresh) {
179
- this.popup.close()
180
- currentConfig[0].credentials = {
181
- consumerKey: event.data.key,
182
- consumerSecret: event.data.secret,
183
- accessToken: event.data.access,
184
- refreshToken: event.data.refresh
185
- }
186
- await homebridge.updatePluginConfig(currentConfig)
187
- await homebridge.savePluginConfig()
188
- homebridge.toast.success("Successfully Linked FirstAlert Account", "homebridge-firstalert")
189
- document.getElementById('backToIntro').style.display = 'none'
190
- document.getElementById('linkButton').style.display = 'none'
191
- document.getElementById('unLinkButton').style.display = 'none'
192
- document.getElementById('linkSuccess').style.display = 'block'
193
- // Show discover devices button after successful login
194
- if (!document.getElementById('discoverDevicesBtn')) {
195
- const discoverBtn = document.createElement('button')
196
- discoverBtn.id = 'discoverDevicesBtn'
197
- discoverBtn.className = 'btn btn-success mt-3'
198
- discoverBtn.innerText = 'Discover Devices'
199
- discoverBtn.onclick = async () => {
200
- homebridge.showSpinner()
201
- try {
202
- const result = await homebridge.request('discoverDevices', { accessToken: result.data.accessToken })
203
- if (result.status === 'ok' && result.data) {
204
- // Show device list and allow adding to config
205
- let deviceList = result.data.devices || result.data;
206
- if (!Array.isArray(deviceList)) deviceList = Object.values(deviceList).flat();
207
- const deviceDiv = document.createElement('div')
208
- deviceDiv.id = 'discoveredDevices'
209
- deviceDiv.innerHTML = '<h5>Discovered Devices</h5>'
210
- deviceList.forEach(device => {
211
- const d = document.createElement('div')
212
- d.className = 'alert alert-info mb-2'
213
- d.innerHTML = `<b>${device.name || device.deviceID}</b> (${device.type || device.deviceType || ''}) <button class='btn btn-sm btn-primary ml-2 addDeviceBtn'>Add</button>`
214
- d.querySelector('.addDeviceBtn').onclick = async () => {
215
- // Add device to config
216
- if (!currentConfig[0].devices) currentConfig[0].devices = []
217
- currentConfig[0].devices.push({ id: device.deviceID, name: device.name, type: device.type || device.deviceType })
218
- await homebridge.updatePluginConfig(currentConfig)
219
- await homebridge.savePluginConfig()
220
- homebridge.toast.success('Device added to config', 'homebridge-firstalert')
221
- }
222
- deviceDiv.appendChild(d)
223
- })
224
- document.getElementById('pageAccount').appendChild(deviceDiv)
225
- } else {
226
- homebridge.toast.error('Device discovery failed: ' + (result.data || 'Unknown error'), 'Error')
227
- }
228
- } catch (err) {
229
- homebridge.toast.error('Device discovery failed: ' + (err?.message || err), 'Error')
230
- } finally {
231
- homebridge.hideSpinner()
232
- }
233
- }
234
- document.getElementById('pageAccount').appendChild(discoverBtn)
235
- }
236
- } else {
237
- throw new Error('no access/token received from server')
238
- }
239
- } catch (err) {
240
- console.log(err)
241
- homebridge.toast.error('Try again, or see the console message for info.', 'Error')
242
- }
243
- })
244
- copyMyText = () => {
245
- var textToCopy = document.getElementById("copyMe");
246
- textToCopy.select();
247
- document.execCommand("copy");
248
- }
249
- linkAccount = async () => {
250
- document.getElementById('validateForm').style.display = 'none'
251
- const consumerKey = document.getElementById('inputConsumerKey').value
252
- const consumerSecret = document.getElementById('inputConsumerSecret').value
253
- if (!consumerKey || !consumerSecret) {
254
- document.getElementById('validateForm').style.display = 'block'
255
- return
256
- }
257
- homebridge.showSpinner()
258
- try {
259
- // Step 1: Start OAuth flow, get authUrl and codeVerifier
260
- const startResult = await homebridge.request('startOAuthFlow', { consumerKey, consumerSecret })
261
- if (startResult.status === 'need_code' && startResult.data && startResult.data.authUrl && startResult.data.codeVerifier) {
262
- // Show modal for code entry
263
- let modal = document.getElementById('oauthModal')
264
- if (!modal) {
265
- modal = document.createElement('div')
266
- modal.id = 'oauthModal'
267
- modal.style.position = 'fixed'
268
- modal.style.top = '0'
269
- modal.style.left = '0'
270
- modal.style.width = '100vw'
271
- modal.style.height = '100vh'
272
- modal.style.background = 'rgba(0,0,0,0.5)'
273
- modal.style.display = 'flex'
274
- modal.style.alignItems = 'center'
275
- modal.style.justifyContent = 'center'
276
- modal.innerHTML = `<div style="background:#fff;padding:2em;border-radius:8px;max-width:400px;width:100%;text-align:center;">
277
- <h5>FirstAlert Login</h5>
278
- <p>Click <a href='${startResult.data.authUrl}' target='_blank'>here</a> to log in and authorize, then paste the code below:</p>
279
- <input id='oauthCodeInput' class='form-control mb-2' placeholder='Paste code here'>
280
- <div class='text-danger mb-2' id='oauthCodeError' style='display:none'></div>
281
- <button class='btn btn-primary' id='oauthCodeSubmit'>Submit</button>
282
- <button class='btn btn-link' id='oauthCodeCancel'>Cancel</button>
283
- </div>`
284
- document.body.appendChild(modal)
285
- } else {
286
- modal.style.display = 'flex'
287
- }
288
- document.getElementById('oauthCodeInput').value = ''
289
- document.getElementById('oauthCodeError').style.display = 'none'
290
- document.getElementById('oauthCodeSubmit').onclick = async () => {
291
- const code = document.getElementById('oauthCodeInput').value
292
- if (!code) {
293
- document.getElementById('oauthCodeError').innerText = 'Please enter the code.'
294
- document.getElementById('oauthCodeError').style.display = 'block'
295
- return
296
- }
297
- modal.style.display = 'none'
298
- homebridge.showSpinner()
299
- try {
300
- const finishResult = await homebridge.request('startOAuthFlow', { consumerKey, consumerSecret, code, codeVerifier: startResult.data.codeVerifier })
301
- if (finishResult.status === 'ok' && finishResult.data && finishResult.data.refreshToken) {
302
- currentConfig[0].credentials = {
303
- consumerKey,
304
- consumerSecret,
305
- accessToken: finishResult.data.accessToken,
306
- refreshToken: finishResult.data.refreshToken
307
- }
308
- await homebridge.updatePluginConfig(currentConfig)
309
- await homebridge.savePluginConfig()
310
- homebridge.toast.success('Successfully Linked FirstAlert Account', 'homebridge-firstalert')
311
- document.getElementById('backToIntro').style.display = 'none'
312
- document.getElementById('linkButton').style.display = 'none'
313
- document.getElementById('unLinkButton').style.display = 'none'
314
- document.getElementById('linkSuccess').style.display = 'block'
315
- } else {
316
- homebridge.toast.error('Login failed: ' + (finishResult.data?.error_description || finishResult.data || 'Unknown error'), 'Error')
317
- }
318
- } catch (err) {
319
- homebridge.toast.error('Login failed: ' + (err?.message || err), 'Error')
320
- } finally {
321
- homebridge.hideSpinner()
322
- }
323
- }
324
- document.getElementById('oauthCodeCancel').onclick = () => {
325
- modal.style.display = 'none'
326
- }
327
- return
328
- }
329
- // If we get here, try the legacy direct token flow
330
- if (startResult.status === 'ok' && startResult.data && startResult.data.refreshToken) {
331
- currentConfig[0].credentials = {
332
- consumerKey,
333
- consumerSecret,
334
- accessToken: startResult.data.accessToken,
335
- refreshToken: startResult.data.refreshToken
336
- }
337
- await homebridge.updatePluginConfig(currentConfig)
338
- await homebridge.savePluginConfig()
339
- homebridge.toast.success('Successfully Linked FirstAlert Account', 'homebridge-firstalert')
340
- document.getElementById('backToIntro').style.display = 'none'
341
- document.getElementById('linkButton').style.display = 'none'
342
- document.getElementById('unLinkButton').style.display = 'none'
343
- document.getElementById('linkSuccess').style.display = 'block'
344
- } else {
345
- homebridge.toast.error('Login failed: ' + (startResult.data?.error_description || startResult.data || 'Unknown error'), 'Error')
346
- }
347
- } catch (err) {
348
- homebridge.toast.error('Login failed: ' + (err?.message || err), 'Error')
349
- } finally {
350
- homebridge.hideSpinner()
351
- }
352
- }
353
- unLinkAccount = async () => {
354
- try {
355
- document.getElementById('validateForm').style.display = 'none'
356
- if (
357
- !document.getElementById('inputConsumerKey').value ||
358
- !document.getElementById('inputConsumerSecret').value
359
- ) {
360
- document.getElementById('validateForm').style.display = 'block'
361
- return
362
- }
363
- delete currentConfig[0].credentials
364
- await homebridge.updatePluginConfig(currentConfig)
365
- await homebridge.savePluginConfig()
366
- document.getElementById('inputConsumerKey').value = ''
367
- document.getElementById('inputConsumerSecret').value = ''
368
- document.getElementById('unLinkButton').style.display = 'none'
369
- } catch (err) {
370
- console.error(err)
371
- homebridge.toast.error('Try again, or see the console message for info.', 'Error')
372
- }
373
- }
374
- showIntro = () => {
375
- const introLink = document.getElementById('introLink')
376
- document.getElementById('copyMe').value = 'http://' + hostname + ':8585/auth'
377
- introLink.addEventListener('click', () => {
378
- homebridge.showSpinner()
379
- document.getElementById('pageIntro').style.display = 'none'
380
- document.getElementById('menuWrapper').style.display = 'inline-flex'
381
- showAccount()
382
- homebridge.hideSpinner()
383
- })
384
- document.getElementById('pageAccount').style.display = 'none'
385
- document.getElementById('menuWrapper').style.display = 'none'
386
- document.getElementById('pageIntro').style.display = 'block'
387
- }
388
- showDevices = async () => {
389
- homebridge.showSpinner()
390
- homebridge.hideSchemaForm()
391
- document.getElementById('menuHome').classList.remove('btn-elegant')
392
- document.getElementById('menuHome').classList.add('btn-primary')
393
- document.getElementById('menuDevices').classList.add('btn-elegant')
394
- document.getElementById('menuDevices').classList.remove('btn-primary')
395
- document.getElementById('menuAccount').classList.remove('btn-elegant')
396
- document.getElementById('menuAccount').classList.add('btn-primary')
397
- document.getElementById('menuSettings').classList.remove('btn-elegant')
398
- document.getElementById('menuSettings').classList.add('btn-primary')
399
- document.getElementById('pageSupport').style.display = 'none'
400
- document.getElementById('pageAccount').style.display = 'none'
401
- document.getElementById('pageDevices').style.display = 'block'
402
- const cachedAccessories =
403
- typeof homebridge.getCachedAccessories === 'function'
404
- ? await homebridge.getCachedAccessories()
405
- : await homebridge.request('/getCachedAccessories')
406
- if (cachedAccessories.length > 0) {
407
- cachedAccessories.sort((a, b) => {
408
- return a.displayName.toLowerCase() > b.displayName.toLowerCase()
409
- ? 1
410
- : b.displayName.toLowerCase() > a.displayName.toLowerCase()
411
- ? -1
412
- : 0
413
- })
414
- }
415
- const deviceSelect = document.getElementById('deviceSelect')
416
- deviceSelect.innerHTML = ''
417
- cachedAccessories.forEach(a => {
418
- const option = document.createElement('option')
419
- option.text = a.displayName
420
- option.value = a.UUID
421
- deviceSelect.add(option)
422
- })
423
- showDeviceInfo = async UUID => {
424
- homebridge.showSpinner()
425
- const thisAcc = cachedAccessories.find(x => x.UUID === UUID)
426
- const context = thisAcc.context
427
- document.getElementById('displayName').innerHTML = thisAcc.displayName
428
- document.getElementById('deviceID').innerHTML = context.deviceID
429
- document.getElementById('model').innerHTML = context.model
430
- document.getElementById('firmwareRevision').innerHTML = context.firmwareRevision || 'N/A'
431
- document.getElementById('deviceTable').style.display = 'inline-table'
432
- homebridge.hideSpinner()
433
- }
434
- deviceSelect.addEventListener('change', event => showDeviceInfo(event.target.value))
435
- if (cachedAccessories.length > 0) {
436
- showDeviceInfo(cachedAccessories[0].UUID)
437
- } else {
438
- const option = document.createElement('option')
439
- option.text = 'No Devices'
440
- deviceSelect.add(option)
441
- deviceSelect.disabled = true
442
- }
443
- homebridge.hideSpinner()
444
- }
445
- showSupport = () => {
446
- homebridge.showSpinner()
447
- homebridge.hideSchemaForm()
448
- document.getElementById('menuHome').classList.add('btn-elegant')
449
- document.getElementById('menuHome').classList.remove('btn-primary')
450
- document.getElementById('menuDevices').classList.remove('btn-elegant')
451
- document.getElementById('menuDevices').classList.add('btn-primary')
452
- document.getElementById('menuSettings').classList.remove('btn-elegant')
453
- document.getElementById('menuSettings').classList.add('btn-primary')
454
- document.getElementById('menuAccount').classList.remove('btn-elegant')
455
- document.getElementById('menuAccount').classList.add('btn-primary')
456
- document.getElementById('pageSupport').style.display = 'block'
457
- document.getElementById('pageDevices').style.display = 'none'
458
- document.getElementById('pageAccount').style.display = 'none'
459
- homebridge.hideSpinner()
460
- }
461
- showSettings = () => {
462
- homebridge.showSpinner()
463
- document.getElementById('menuHome').classList.remove('btn-elegant')
464
- document.getElementById('menuHome').classList.add('btn-primary')
465
- document.getElementById('menuDevices').classList.remove('btn-elegant')
466
- document.getElementById('menuDevices').classList.add('btn-primary')
467
- document.getElementById('menuSettings').classList.add('btn-elegant')
468
- document.getElementById('menuSettings').classList.remove('btn-primary')
469
- document.getElementById('menuAccount').classList.remove('btn-elegant')
470
- document.getElementById('menuAccount').classList.add('btn-primary')
471
- document.getElementById('pageSupport').style.display = 'none'
472
- document.getElementById('pageDevices').style.display = 'none'
473
- document.getElementById('pageAccount').style.display = 'none'
474
- homebridge.showSchemaForm()
475
- homebridge.hideSpinner()
476
- }
477
- showAccount = () => {
478
- homebridge.showSpinner()
479
- const backToIntro = document.getElementById('backToIntro')
480
- backToIntro.addEventListener('click', () => {
481
- showIntro()
482
- })
483
- backToIntro.style.display = 'none'
484
- const linkButton = document.getElementById('linkButton')
485
- linkButton.addEventListener('click', () => {
486
- linkAccount()
487
- })
488
- const unLinkButton = document.getElementById('unLinkButton')
489
- unLinkButton.style.display = 'none'
490
- unLinkButton.addEventListener('click', () => {
491
- unLinkAccount()
492
- })
493
- document.getElementById('linkSuccess').style.display = 'none'
494
- homebridge.hideSchemaForm()
495
- document.getElementById('menuHome').classList.remove('btn-elegant')
496
- document.getElementById('menuHome').classList.add('btn-primary')
497
- document.getElementById('menuDevices').classList.remove('btn-elegant')
498
- document.getElementById('menuDevices').classList.add('btn-primary')
499
- document.getElementById('menuAccount').classList.add('btn-elegant')
500
- document.getElementById('menuAccount').classList.remove('btn-primary')
501
- document.getElementById('menuSettings').classList.remove('btn-elegant')
502
- document.getElementById('menuSettings').classList.add('btn-primary')
503
- document.getElementById('pageSupport').style.display = 'none'
504
- document.getElementById('pageDevices').style.display = 'none'
505
- document.getElementById('pageAccount').style.display = 'block'
506
- document.getElementById('linkButton').style.display = 'inline-block'
507
- let isRelink = false
508
- if (currentConfig[0] && currentConfig[0].credentials) {
509
- const key = currentConfig[0].credentials.consumerKey || ''
510
- const secret = currentConfig[0].credentials.consumerSecret || ''
511
- document.getElementById('inputConsumerKey').value = key
512
- document.getElementById('inputConsumerSecret').value = secret
513
- if (key && secret) {
514
- isRelink = true
515
- document.getElementById('unLinkButton').style.display = 'inline-block'
516
- } else {
517
- document.getElementById('unLinkButton').style.display = 'none'
518
- }
519
- }
520
- document.getElementById('linkButton').innerHTML = isRelink
521
- ? 'Relink Account &rarr;'
522
- : 'Link Account &rarr;'
523
- if (!isRelink) {
524
- document.getElementById('backToIntro').style.display = 'inline-block'
525
- } else {
526
- document.getElementById('backToIntro').style.display = 'none'
527
- }
528
- homebridge.hideSpinner()
529
- }
530
- menuHome.addEventListener('click', () => showSupport())
531
- menuAccount.addEventListener('click', () => showAccount())
532
- menuDevices.addEventListener('click', () => showDevices())
533
- menuSettings.addEventListener('click', () => showSettings())
534
- if (currentConfig.length) {
535
- document.getElementById('menuWrapper').style.display = 'inline-flex'
536
- showAccount()
537
- } else {
538
- currentConfig.push({ name: 'FirstAlert' })
539
- await homebridge.updatePluginConfig(currentConfig)
540
- showIntro()
541
- }
542
- } catch (err) {
543
- homebridge.toast.error(err.message, 'Error')
544
- } finally {
545
- homebridge.hideSpinner()
546
- }
547
- })()
548
- </script>
@@ -1,32 +0,0 @@
1
- export interface ResideoDevice {
2
- id: string;
3
- name: string;
4
- deviceId: string;
5
- globalDeviceType: string;
6
- }
7
- export interface ResideoAccount {
8
- id: string;
9
- firstName: string;
10
- lastName: string;
11
- contactEmail: string;
12
- countryCode: string;
13
- locale: string;
14
- devices: ResideoDevice[];
15
- }
16
- export interface ResideoDeviceState {
17
- name: string;
18
- deviceType: string;
19
- isOnline: boolean;
20
- deviceState: any;
21
- }
22
- export declare class ResideoClient {
23
- private clientId;
24
- private refreshToken;
25
- private accessToken;
26
- constructor(refreshToken: string);
27
- refreshAccessToken(): Promise<string>;
28
- getAccessToken(): Promise<string>;
29
- getAccount(): Promise<ResideoAccount>;
30
- getDeviceState(deviceId: string): Promise<ResideoDeviceState>;
31
- }
32
- //# sourceMappingURL=resideoClient.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"resideoClient.d.ts","sourceRoot":"","sources":["../../../src/api/resideoClient.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,EAAE,MAAM,CAAA;IAChB,gBAAgB,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,YAAY,EAAE,MAAM,CAAA;IACpB,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,aAAa,EAAE,CAAA;CACzB;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,GAAG,CAAA;CACjB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAqC;IACrD,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,WAAW,CAAsB;gBAE7B,YAAY,EAAE,MAAM;IAI1B,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC;IAmBrC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAOjC,UAAU,IAAI,OAAO,CAAC,cAAc,CAAC;IAiCrC,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAC;CAQpE"}