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

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 (118) hide show
  1. package/branding/icon.png +0 -0
  2. package/dist/homebridge-ui/public/index.html +230 -0
  3. package/dist/src/api/resideoClient.d.ts +32 -0
  4. package/dist/src/api/resideoClient.d.ts.map +1 -0
  5. package/dist/src/api/resideoClient.js +76 -0
  6. package/dist/src/api/resideoClient.js.map +1 -0
  7. package/dist/src/devices/device.d.ts +40 -0
  8. package/dist/src/devices/device.d.ts.map +1 -0
  9. package/dist/src/devices/device.js +207 -0
  10. package/dist/src/devices/device.js.map +1 -0
  11. package/dist/src/devices/leaksensors.d.ts +34 -0
  12. package/dist/src/devices/leaksensors.d.ts.map +1 -0
  13. package/dist/src/devices/leaksensors.js +163 -0
  14. package/dist/src/devices/leaksensors.js.map +1 -0
  15. package/dist/src/devices/smoke.d.ts +35 -0
  16. package/dist/src/devices/smoke.d.ts.map +1 -0
  17. package/dist/src/devices/smoke.js +150 -0
  18. package/dist/src/devices/smoke.js.map +1 -0
  19. package/dist/src/devices/thermostats.d.ts +42 -0
  20. package/dist/src/devices/thermostats.d.ts.map +1 -0
  21. package/dist/src/devices/thermostats.js +192 -0
  22. package/dist/src/devices/thermostats.js.map +1 -0
  23. package/dist/src/devices/valve.d.ts +21 -0
  24. package/dist/src/devices/valve.d.ts.map +1 -0
  25. package/dist/src/devices/valve.js +131 -0
  26. package/dist/src/devices/valve.js.map +1 -0
  27. package/dist/src/homebridge-ui/server.d.ts +2 -0
  28. package/dist/src/homebridge-ui/server.d.ts.map +1 -0
  29. package/dist/src/homebridge-ui/server.js +411 -0
  30. package/dist/src/homebridge-ui/server.js.map +1 -0
  31. package/dist/src/index.d.ts +4 -0
  32. package/dist/src/index.d.ts.map +1 -0
  33. package/dist/src/index.js +7 -0
  34. package/dist/src/index.js.map +1 -0
  35. package/dist/src/platform.d.ts +18 -0
  36. package/dist/src/platform.d.ts.map +1 -0
  37. package/dist/src/platform.js +108 -0
  38. package/dist/src/platform.js.map +1 -0
  39. package/dist/src/settings.d.ts +341 -0
  40. package/dist/src/settings.d.ts.map +1 -0
  41. package/dist/src/settings.js +25 -0
  42. package/dist/src/settings.js.map +1 -0
  43. package/dist/src/utils.d.ts +21 -0
  44. package/dist/src/utils.d.ts.map +1 -0
  45. package/{src/utils.ts → dist/src/utils.js} +27 -30
  46. package/dist/src/utils.js.map +1 -0
  47. package/dist/test/index.test.d.ts +2 -0
  48. package/dist/test/index.test.d.ts.map +1 -0
  49. package/dist/test/index.test.js +14 -0
  50. package/dist/test/index.test.js.map +1 -0
  51. package/dist/test/platform.test.d.ts +2 -0
  52. package/dist/test/platform.test.d.ts.map +1 -0
  53. package/dist/test/platform.test.js +56 -0
  54. package/dist/test/platform.test.js.map +1 -0
  55. package/dist/test/settings.test.d.ts +2 -0
  56. package/dist/test/settings.test.d.ts.map +1 -0
  57. package/dist/test/settings.test.js +48 -0
  58. package/dist/test/settings.test.js.map +1 -0
  59. package/dist/test/utils.test.d.ts +2 -0
  60. package/dist/test/utils.test.d.ts.map +1 -0
  61. package/dist/test/utils.test.js +17 -0
  62. package/dist/test/utils.test.js.map +1 -0
  63. package/package.json +8 -4
  64. package/.gitattributes +0 -2
  65. package/.github/FUNDING.yml +0 -4
  66. package/.github/ISSUE_TEMPLATE/bug-report.yml +0 -97
  67. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  68. package/.github/ISSUE_TEMPLATE/feature-request.yml +0 -38
  69. package/.github/ISSUE_TEMPLATE/support-request.yml +0 -85
  70. package/.github/ISSUE_TEMPLATE.md +0 -52
  71. package/.github/PULL_REQUEST_TEMPLATE/pull_request.md +0 -27
  72. package/.github/dependabot.yml +0 -17
  73. package/.github/labeler.yml +0 -38
  74. package/.github/npm-version-script-esm.js +0 -97
  75. package/.github/release-drafter.yml +0 -33
  76. package/.github/workflows/beta-release.yml +0 -55
  77. package/.github/workflows/build.yml +0 -18
  78. package/.github/workflows/changerelease.yml +0 -11
  79. package/.github/workflows/labeler.yml +0 -9
  80. package/.github/workflows/release-drafter.yml +0 -14
  81. package/.github/workflows/release.yml +0 -35
  82. package/.github/workflows/stale.yml +0 -12
  83. package/CHANGELOG.md +0 -10
  84. package/SECURITY.md +0 -19
  85. package/config.schema.json +0 -58
  86. package/docs/.nojekyll +0 -1
  87. package/docs/assets/hierarchy.js +0 -1
  88. package/docs/assets/highlight.css +0 -22
  89. package/docs/assets/icons.js +0 -18
  90. package/docs/assets/icons.svg +0 -1
  91. package/docs/assets/main.js +0 -60
  92. package/docs/assets/navigation.js +0 -1
  93. package/docs/assets/search.js +0 -1
  94. package/docs/assets/style.css +0 -1633
  95. package/docs/hierarchy.html +0 -1
  96. package/docs/index.html +0 -77
  97. package/docs/modules.html +0 -1
  98. package/docs/variables/default.html +0 -1
  99. package/eslint.config.js +0 -44
  100. package/nodemon.json +0 -10
  101. package/scripts/free-dev-ports.mjs +0 -105
  102. package/src/api/resideoClient.ts +0 -106
  103. package/src/devices/device.ts +0 -226
  104. package/src/devices/leaksensors.ts +0 -206
  105. package/src/devices/smoke.ts +0 -173
  106. package/src/devices/thermostats.ts +0 -243
  107. package/src/devices/valve.ts +0 -162
  108. package/src/homebridge-ui/public/index.html +0 -548
  109. package/src/homebridge-ui/server.ts +0 -102
  110. package/src/index.ts +0 -13
  111. package/src/platform.ts +0 -112
  112. package/src/settings.ts +0 -402
  113. package/test/index.test.ts +0 -18
  114. package/test/platform.test.ts +0 -65
  115. package/test/settings.test.ts +0 -56
  116. package/test/utils.test.ts +0 -20
  117. package/tsconfig.json +0 -27
  118. package/typedoc.json +0 -22
package/branding/icon.png CHANGED
Binary file
@@ -0,0 +1,230 @@
1
+ <div class="text-center mt-5">
2
+ <img id="firstalert-logo" src="/branding/Homebridge_x_FirstAlert.svg" alt="homebridge-firstalert logo"
3
+ style="width: 120px;" onerror="this.onerror=null;this.src='/branding/icon.png';" />
4
+ <h2 class="mt-3">First Alert by Resideo</h2>
5
+ <div id="auth-section" class="mt-4" style="max-width: 400px; margin: 0 auto;">
6
+ <div id="login-form" style="display: none;">
7
+ <div class="alert alert-warning" style="display: none;" id="validateForm">Please enter both email and password.
8
+ </div>
9
+ <div class="form-group text-left">
10
+ <label for="inputEmail">Email</label>
11
+ <input type="email" class="form-control" id="inputEmail" autocomplete="username"
12
+ placeholder="Enter your Resideo email">
13
+ </div>
14
+ <div class="form-group text-left">
15
+ <label for="inputPassword">Password</label>
16
+ <input type="password" class="form-control" id="inputPassword" autocomplete="current-password"
17
+ placeholder="Enter your password">
18
+ </div>
19
+ <button type="button" class="btn btn-primary w-100 mt-3" id="loginButton">Login</button>
20
+ <pre id="loginLogs"
21
+ style="background:#222;color:#eee;padding:1em;margin-top:1em;max-height:180px;overflow:auto;display:none;font-size:0.95em;"></pre>
22
+ </div>
23
+ <div id="unlink-section" style="display: none;">
24
+ <div class="alert alert-success" style="display: none;" id="linkSuccess">Account linked. You may now close this
25
+ window.</div>
26
+ <button type="button" class="btn btn-danger w-100" id="unlinkButton">Unlink Account</button>
27
+ </div>
28
+ </div>
29
+ <div class="mt-4">
30
+ <small class="text-muted">Your credentials are only used to obtain a refresh token and are never stored.</small>
31
+ </div>
32
+ </div>
33
+ <div id="pageDevices" class="mt-4" style="display: none;">
34
+ <div id="deviceInfo">
35
+ <form>
36
+ <div class="form-group">
37
+ <select class="form-control" id="deviceSelect"></select>
38
+ </div>
39
+ </form>
40
+ <table class="table w-100" id="deviceTable" style="display: none;">
41
+ <thead>
42
+ <tr class="table-active">
43
+ <th scope="col" style="width: 40%;">Device Name</th>
44
+ <th scope="col" style="width: 60%;" id="displayName"></th>
45
+ </tr>
46
+ </thead>
47
+ <tbody>
48
+ <tr>
49
+ <th scope="row">Device ID</th>
50
+ <td id="deviceID"></td>
51
+ </tr>
52
+ <tr>
53
+ <th scope="row">Model</th>
54
+ <td id="model"></td>
55
+ </tr>
56
+ <tr>
57
+ <th scope="row">Firmware Version</th>
58
+ <td id="firmwareRevision"></td>
59
+ </tr>
60
+ </tbody>
61
+ </table>
62
+ </div>
63
+ </div>
64
+ <div id="pageSupport" class="mt-4" style="display: none;">
65
+ <p class="text-center lead">Thank you for using <strong>homebridge-firstalert</strong></p>
66
+ <p class="text-center">The links below will take you to our GitHub wiki</p>
67
+ <h5>Setup</h5>
68
+ <ul>
69
+ <li>
70
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki" target="_blank">Wiki Home</a>
71
+ </li>
72
+ <li>
73
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Configuration"
74
+ target="_blank">Configuration</a>
75
+ </li>
76
+ <li>
77
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Beta-Version" target="_blank">Beta
78
+ Version</a>
79
+ </li>
80
+ <li>
81
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Node-Version" target="_blank">Node
82
+ Version</a>
83
+ </li>
84
+ <li>
85
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Uninstallation"
86
+ target="_blank">Uninstallation</a>
87
+ </li>
88
+ </ul>
89
+ <h5>Features</h5>
90
+ <ul>
91
+ <li>
92
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Supported-Devices"
93
+ target="_blank">Supported
94
+ Devices</a>
95
+ </li>
96
+ <li>
97
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/wiki/Fan-Modes" target="_blank">Fan
98
+ Modes</a>
99
+ </li>
100
+ </ul>
101
+ <h5>Help/About</h5>
102
+ <ul>
103
+ <li>
104
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/issues/new/choose" target="_blank">Support
105
+ Request</a>
106
+ </li>
107
+ <li>
108
+ <a href="https://github.com/homebridge-plugins/homebridge-firstalert/blob/latest/CHANGELOG.md"
109
+ target="_blank">Changelog</a>
110
+ </li>
111
+ <li>
112
+ <a href="https://github.com/sponsors/donavanbecker" target="_blank">About Me</a>
113
+ </li>
114
+ </ul>
115
+ <h5>Disclaimer</h5>
116
+ <ul>
117
+ <li>
118
+ I am in no way affiliated with FirstAlert and this plugin is a personal project that I maintain in
119
+ my free time.
120
+ </li>
121
+ <li>
122
+ Use this plugin entirely at your own risk - please see licence for more information.
123
+ </li>
124
+ </ul>
125
+ </div>
126
+ <script>
127
+ ; (async () => {
128
+ try {
129
+ const config = await homebridge.getPluginConfig();
130
+ const credentials = config[0]?.credentials;
131
+ const hasRefresh = !!(credentials && credentials.refreshToken);
132
+
133
+ // UI elements
134
+ const loginForm = document.getElementById('login-form');
135
+ const unlinkSection = document.getElementById('unlink-section');
136
+ const validateForm = document.getElementById('validateForm');
137
+ const linkSuccess = document.getElementById('linkSuccess');
138
+ const loginButton = document.getElementById('loginButton');
139
+ const unlinkButton = document.getElementById('unlinkButton');
140
+ const inputEmail = document.getElementById('inputEmail');
141
+ const inputPassword = document.getElementById('inputPassword');
142
+
143
+ // Show correct section
144
+ if (hasRefresh) {
145
+ loginForm.style.display = 'none';
146
+ unlinkSection.style.display = 'block';
147
+ } else {
148
+ loginForm.style.display = 'block';
149
+ unlinkSection.style.display = 'none';
150
+ }
151
+
152
+ // Login handler
153
+ if (loginButton) {
154
+ loginButton.onclick = async () => {
155
+ validateForm.style.display = 'none';
156
+ const email = inputEmail.value.trim();
157
+ const password = inputPassword.value.trim();
158
+ const logs = document.getElementById('loginLogs');
159
+ logs.style.display = 'block';
160
+ logs.textContent = '';
161
+ if (!email || !password) {
162
+ validateForm.style.display = 'block';
163
+ logs.textContent = 'Email and password are required.';
164
+ return;
165
+ }
166
+ homebridge.showSpinner();
167
+ logs.textContent = 'Attempting to authenticate...\n';
168
+ try {
169
+ logs.textContent += 'Sending credentials to server...\n';
170
+ const result = await homebridge.request('startResideoAuth', { email, password });
171
+ if (Array.isArray(result.logs)) {
172
+ logs.textContent += result.logs.join('\n') + '\n';
173
+ } else if (result.logs) {
174
+ logs.textContent += result.logs + '\n';
175
+ }
176
+ if (result.status === 'ok' && result.data && result.data.refreshToken) {
177
+ config[0].credentials = {
178
+ email,
179
+ refreshToken: result.data.refreshToken,
180
+ accessToken: result.data.accessToken
181
+ };
182
+ await homebridge.updatePluginConfig(config);
183
+ await homebridge.savePluginConfig();
184
+ loginForm.style.display = 'none';
185
+ unlinkSection.style.display = 'block';
186
+ linkSuccess.style.display = 'block';
187
+ homebridge.toast.success('Successfully linked account', 'homebridge-firstalert');
188
+ logs.textContent += 'Successfully linked account.\n';
189
+ } else {
190
+ const errMsg = 'Login failed: ' + (result.data?.error_description || result.data || 'Unknown error');
191
+ homebridge.toast.error(errMsg, 'Error');
192
+ logs.textContent += errMsg + '\n';
193
+ }
194
+ } catch (err) {
195
+ const errMsg = 'Login failed: ' + (err?.message || err);
196
+ homebridge.toast.error(errMsg, 'Error');
197
+ logs.textContent += errMsg + '\n';
198
+ } finally {
199
+ homebridge.hideSpinner();
200
+ }
201
+ };
202
+ }
203
+
204
+ // Unlink handler
205
+ if (unlinkButton) {
206
+ unlinkButton.onclick = async () => {
207
+ homebridge.showSpinner();
208
+ try {
209
+ delete config[0].credentials;
210
+ await homebridge.updatePluginConfig(config);
211
+ await homebridge.savePluginConfig();
212
+ unlinkSection.style.display = 'none';
213
+ loginForm.style.display = 'block';
214
+ inputEmail.value = '';
215
+ inputPassword.value = '';
216
+ homebridge.toast.success('Account unlinked', 'homebridge-firstalert');
217
+ } catch (err) {
218
+ homebridge.toast.error('Unlink failed: ' + (err?.message || err), 'Error');
219
+ } finally {
220
+ homebridge.hideSpinner();
221
+ }
222
+ };
223
+ }
224
+ } catch (err) {
225
+ homebridge.toast.error(err.message, 'Error');
226
+ } finally {
227
+ homebridge.hideSpinner();
228
+ }
229
+ })();
230
+ </script>
@@ -0,0 +1,32 @@
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
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,76 @@
1
+ // FirstAlert API client for OAuth and device polling
2
+ // Implements token refresh, account/device fetch, and strong typing
3
+ import { request } from 'undici';
4
+ export class ResideoClient {
5
+ clientId = 'SRmiA7CaYi1JgivDZdzzoZu4X5VBogGt';
6
+ refreshToken;
7
+ accessToken = null;
8
+ constructor(refreshToken) {
9
+ this.refreshToken = refreshToken;
10
+ }
11
+ async refreshAccessToken() {
12
+ const body = JSON.stringify({
13
+ grant_type: 'refresh_token',
14
+ refresh_token: this.refreshToken,
15
+ client_id: this.clientId,
16
+ });
17
+ const { body: resBody } = await request('https://login.firstalert.com/oauth/token', {
18
+ method: 'POST',
19
+ headers: { 'Content-Type': 'application/json' },
20
+ body,
21
+ });
22
+ const data = await resBody.json();
23
+ this.accessToken = data.access_token ?? '';
24
+ if (!this.accessToken) {
25
+ throw new Error('Failed to obtain access token from FirstAlert API');
26
+ }
27
+ return this.accessToken;
28
+ }
29
+ async getAccessToken() {
30
+ if (!this.accessToken) {
31
+ await this.refreshAccessToken();
32
+ }
33
+ return this.accessToken;
34
+ }
35
+ async getAccount() {
36
+ const token = await this.getAccessToken();
37
+ const { body: resBody } = await request('https://api.firstalert.com/ris-public-api/api/v1/accounts', {
38
+ method: 'GET',
39
+ headers: { Authorization: `Bearer ${token}` },
40
+ });
41
+ const resp = await resBody.json();
42
+ // Parse and flatten devices
43
+ const data = resp.data;
44
+ const devices = [];
45
+ for (const user of data.consumerUsers) {
46
+ for (const loc of user.consumerAccount.locations) {
47
+ for (const dev of loc.consumerDevices) {
48
+ devices.push({
49
+ id: dev.id,
50
+ name: dev.name,
51
+ deviceId: dev.device.deviceId,
52
+ globalDeviceType: dev.device.globalDeviceType,
53
+ });
54
+ }
55
+ }
56
+ }
57
+ return {
58
+ id: data.id,
59
+ firstName: data.firstName,
60
+ lastName: data.lastName,
61
+ contactEmail: data.contactEmail,
62
+ countryCode: data.countryCode,
63
+ locale: data.locale,
64
+ devices,
65
+ };
66
+ }
67
+ async getDeviceState(deviceId) {
68
+ const token = await this.getAccessToken();
69
+ const { body: resBody } = await request(`https://api.firstalert.com/ris-public-api/api/v2/devices/smokeDetectors/${deviceId}/state`, {
70
+ method: 'GET',
71
+ headers: { Authorization: `Bearer ${token}` },
72
+ });
73
+ return await resBody.json();
74
+ }
75
+ }
76
+ //# sourceMappingURL=resideoClient.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resideoClient.js","sourceRoot":"","sources":["../../../src/api/resideoClient.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { API, HAP, Logging, PlatformAccessory } from 'homebridge';
2
+ import type { ResideoDevice } from '../api/resideoClient.js';
3
+ import type { ResideoPlatform } from '../platform.js';
4
+ import type { ResideoPlatformConfig } from '../settings.js';
5
+ export declare abstract class deviceBase {
6
+ protected readonly platform: ResideoPlatform;
7
+ protected accessory: PlatformAccessory;
8
+ protected device: ResideoDevice;
9
+ readonly api: API;
10
+ readonly log: Logging;
11
+ readonly config: ResideoPlatformConfig;
12
+ protected readonly hap: HAP;
13
+ protected deviceLogging: string;
14
+ protected deviceRefreshRate: number;
15
+ protected deviceUpdateRate: number;
16
+ protected devicePushRate: number;
17
+ protected deviceFirmwareVersion: string;
18
+ protected deviceMaxRetries: number;
19
+ protected deviceDelayBetweenRetries: number;
20
+ constructor(platform: ResideoPlatform, accessory: PlatformAccessory, device: ResideoDevice);
21
+ getDeviceLogSettings(): Promise<void>;
22
+ getDeviceRateSettings(): Promise<void>;
23
+ getDeviceConfigSettings(device: ResideoDevice): Promise<void>;
24
+ getDeviceContext(accessory: PlatformAccessory, device: ResideoDevice): Promise<void>;
25
+ statusCode(statusCode: number, action: string): Promise<void>;
26
+ resideoAPIError(e: any, action: string): Promise<void>;
27
+ /**
28
+ * Logging for Device
29
+ */
30
+ infoLog(...log: any[]): Promise<void>;
31
+ successLog(...log: any[]): Promise<void>;
32
+ debugSuccessLog(...log: any[]): Promise<void>;
33
+ warnLog(...log: any[]): Promise<void>;
34
+ debugWarnLog(...log: any[]): Promise<void>;
35
+ errorLog(...log: any[]): Promise<void>;
36
+ debugErrorLog(...log: any[]): Promise<void>;
37
+ debugLog(...log: any[]): Promise<void>;
38
+ enablingDeviceLogging(): Promise<boolean>;
39
+ }
40
+ //# sourceMappingURL=device.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.d.ts","sourceRoot":"","sources":["../../../src/devices/device.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAEtE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,gBAAgB,CAAA;AAE3D,8BAAsB,UAAU;IAgB5B,SAAS,CAAC,QAAQ,CAAC,QAAQ,EAAE,eAAe;IAC5C,SAAS,CAAC,SAAS,EAAE,iBAAiB;IACtC,SAAS,CAAC,MAAM,EAAE,aAAa;IAjBjC,SAAgB,GAAG,EAAE,GAAG,CAAA;IACxB,SAAgB,GAAG,EAAE,OAAO,CAAA;IAC5B,SAAgB,MAAM,EAAG,qBAAqB,CAAA;IAC9C,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAA;IAG3B,SAAS,CAAC,aAAa,EAAG,MAAM,CAAA;IAChC,SAAS,CAAC,iBAAiB,EAAG,MAAM,CAAA;IACpC,SAAS,CAAC,gBAAgB,EAAG,MAAM,CAAA;IACnC,SAAS,CAAC,cAAc,EAAG,MAAM,CAAA;IACjC,SAAS,CAAC,qBAAqB,EAAG,MAAM,CAAA;IACxC,SAAS,CAAC,gBAAgB,EAAG,MAAM,CAAA;IACnC,SAAS,CAAC,yBAAyB,EAAG,MAAM,CAAA;gBAGvB,QAAQ,EAAE,eAAe,EAClC,SAAS,EAAE,iBAAiB,EAC5B,MAAM,EAAE,aAAa;IAyB3B,oBAAoB,IAAI,OAAO,CAAC,IAAI,CAAC;IAKrC,qBAAqB,IAAI,OAAO,CAAC,IAAI,CAAC;IAYtC,uBAAuB,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAK7D,gBAAgB,CAAC,SAAS,EAAE,iBAAiB,EAAE,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAkBpF,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA4B7D,eAAe,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC5D;;OAEG;IACG,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrC,UAAU,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMxC,eAAe,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ7C,OAAO,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMrC,YAAY,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ1C,QAAQ,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAMtC,aAAa,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ3C,QAAQ,CAAC,GAAG,GAAG,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtC,qBAAqB,IAAI,OAAO,CAAC,OAAO,CAAC;CAGhD"}
@@ -0,0 +1,207 @@
1
+ export class deviceBase {
2
+ platform;
3
+ accessory;
4
+ device;
5
+ api;
6
+ log;
7
+ config;
8
+ hap;
9
+ // Config
10
+ deviceLogging;
11
+ deviceRefreshRate;
12
+ deviceUpdateRate;
13
+ devicePushRate;
14
+ deviceFirmwareVersion;
15
+ deviceMaxRetries;
16
+ deviceDelayBetweenRetries;
17
+ constructor(platform, accessory, device) {
18
+ this.platform = platform;
19
+ this.accessory = accessory;
20
+ this.device = device;
21
+ this.api = platform.api;
22
+ this.log = platform.log;
23
+ this.config = platform.config;
24
+ this.hap = platform.api.hap;
25
+ this.getDeviceLogSettings();
26
+ this.getDeviceRateSettings();
27
+ this.getDeviceConfigSettings(device);
28
+ this.getDeviceContext(accessory, device);
29
+ // Set accessory information
30
+ accessory
31
+ .getService(this.hap.Service.AccessoryInformation)
32
+ .setCharacteristic(this.hap.Characteristic.Manufacturer, 'FirstAlert')
33
+ .setCharacteristic(this.hap.Characteristic.Name, accessory.displayName)
34
+ .setCharacteristic(this.hap.Characteristic.ConfiguredName, accessory.displayName)
35
+ .setCharacteristic(this.hap.Characteristic.Model, accessory.context.model)
36
+ .setCharacteristic(this.hap.Characteristic.SerialNumber, accessory.context.deviceID)
37
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.deviceFirmwareVersion)
38
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
39
+ .updateValue(this.deviceFirmwareVersion);
40
+ }
41
+ async getDeviceLogSettings() {
42
+ this.deviceLogging = 'standard';
43
+ await this.debugLog(`Using Device Logging: ${this.deviceLogging}`);
44
+ }
45
+ async getDeviceRateSettings() {
46
+ // Use default values; ResideoDevice does not have these properties
47
+ this.deviceRefreshRate = 120;
48
+ this.deviceUpdateRate = 5;
49
+ this.devicePushRate = 0.1;
50
+ await this.debugLog(`Using refreshRate: ${this.deviceRefreshRate}, updateRate: ${this.deviceUpdateRate}, pushRate: ${this.devicePushRate}`);
51
+ this.deviceMaxRetries = 5;
52
+ await this.debugLog(`Using maxRetries: ${this.deviceMaxRetries}`);
53
+ this.deviceDelayBetweenRetries = 3 * 1000;
54
+ await this.debugLog(`Using delayBetweenRetries: ${this.deviceDelayBetweenRetries}`);
55
+ }
56
+ async getDeviceConfigSettings(device) {
57
+ // No config merging; ResideoDevice does not have these properties
58
+ this.debugSuccessLog(`Config: ${JSON.stringify(device)}`);
59
+ }
60
+ async getDeviceContext(accessory, device) {
61
+ // Context Information
62
+ accessory.context.model = device.globalDeviceType;
63
+ accessory.context.deviceID = device.deviceId;
64
+ accessory.context.deviceType = device.globalDeviceType;
65
+ // FirmwareRevision
66
+ const version = '0.0.0';
67
+ this.deviceFirmwareVersion = version;
68
+ accessory
69
+ .getService(this.hap.Service.AccessoryInformation)
70
+ .setCharacteristic(this.hap.Characteristic.HardwareRevision, this.deviceFirmwareVersion)
71
+ .setCharacteristic(this.hap.Characteristic.SoftwareRevision, this.deviceFirmwareVersion)
72
+ .setCharacteristic(this.hap.Characteristic.FirmwareRevision, this.deviceFirmwareVersion)
73
+ .getCharacteristic(this.hap.Characteristic.FirmwareRevision)
74
+ .updateValue(this.deviceFirmwareVersion);
75
+ this.debugSuccessLog(`deviceFirmwareVersion: ${this.deviceFirmwareVersion}`);
76
+ }
77
+ async statusCode(statusCode, action) {
78
+ switch (statusCode) {
79
+ case 200:
80
+ this.debugLog(`${this.device.name}: ${this.accessory.displayName} Standard Response, statusCode: ${statusCode}, Action: ${action}`);
81
+ break;
82
+ case 400:
83
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} Bad Request, statusCode: ${statusCode}, Action: ${action}`);
84
+ break;
85
+ case 401:
86
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} Unauthorized, statusCode: ${statusCode}, Action: ${action}`);
87
+ break;
88
+ case 403:
89
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} Forbidden, The request has been authenticated but does not have appropriate permissions, or a requested resource is not found, statusCode: ${statusCode}`);
90
+ break;
91
+ case 404:
92
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} Not Found, statusCode: ${statusCode}, Action: ${action}`);
93
+ break;
94
+ case 429:
95
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} Too Many Requests, statusCode: ${statusCode}, Action: ${action}`);
96
+ break;
97
+ case 500:
98
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} Internal Server Error (Meater Server), statusCode: ${statusCode}, Action: ${action}`);
99
+ break;
100
+ default:
101
+ this.infoLog(`${this.device.name}: ${this.accessory.displayName} Unknown statusCode: ${statusCode}, Action: ${action}, Report Bugs Here: https://bit.ly/homebridge-firstalert-bug-report`);
102
+ }
103
+ }
104
+ async resideoAPIError(e, action) {
105
+ if (e.message.includes('400')) {
106
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Bad Request`);
107
+ this.debugLog('The client has issued an invalid request. This is commonly used to specify validation errors in a request payload.');
108
+ }
109
+ else if (e.message.includes('401')) {
110
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Unauthorized Request`);
111
+ this.debugLog('Authorization for the API is required, but the request has not been authenticated.');
112
+ }
113
+ else if (e.message.includes('403')) {
114
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Forbidden Request`);
115
+ this.debugLog('The request has been authenticated but does not have appropriate permissions, or a requested resource is not found.');
116
+ }
117
+ else if (e.message.includes('404')) {
118
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Requst Not Found`);
119
+ this.debugLog('Specifies the requested path does not exist.');
120
+ }
121
+ else if (e.message.includes('406')) {
122
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Request Not Acceptable`);
123
+ this.debugLog('The client has requested a MIME type via the Accept header for a value not supported by the server.');
124
+ }
125
+ else if (e.message.includes('415')) {
126
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Unsupported Requst Header`);
127
+ this.debugLog('The client has defined a contentType header that is not supported by the server.');
128
+ }
129
+ else if (e.message.includes('422')) {
130
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Unprocessable Entity`);
131
+ this.debugLog('The client has made a valid request, but the server cannot process it.'
132
+ + ' This is often used for APIs for which certain limits have been exceeded.');
133
+ }
134
+ else if (e.message.includes('429')) {
135
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Too Many Requests`);
136
+ this.debugLog('The client has exceeded the number of requests allowed for a given time window.');
137
+ }
138
+ else if (e.message.includes('500')) {
139
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action}, Internal Server Error`);
140
+ this.debugLog('An unexpected error on the SmartThings servers has occurred. These errors should be rare.');
141
+ }
142
+ else {
143
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to ${action},`);
144
+ }
145
+ if (this.deviceLogging.includes('debug')) {
146
+ this.errorLog(`${this.device.name}: ${this.accessory.displayName} failed to pushChanges, Error Message: ${JSON.stringify(e.message)}`);
147
+ }
148
+ }
149
+ /**
150
+ * Logging for Device
151
+ */
152
+ async infoLog(...log) {
153
+ if (await this.enablingDeviceLogging()) {
154
+ this.log.info(`${this.device.name}: ${this.accessory.displayName}`, String(...log));
155
+ }
156
+ }
157
+ async successLog(...log) {
158
+ if (await this.enablingDeviceLogging()) {
159
+ this.log.success(`${this.device.name}: ${this.accessory.displayName}`, String(...log));
160
+ }
161
+ }
162
+ async debugSuccessLog(...log) {
163
+ if (await this.enablingDeviceLogging()) {
164
+ if (this.deviceLogging?.includes('debug')) {
165
+ this.log.success(`[DEBUG] ${this.device.name}: ${this.accessory.displayName}`, String(...log));
166
+ }
167
+ }
168
+ }
169
+ async warnLog(...log) {
170
+ if (await this.enablingDeviceLogging()) {
171
+ this.log.warn(`${this.device.name}: ${this.accessory.displayName}`, String(...log));
172
+ }
173
+ }
174
+ async debugWarnLog(...log) {
175
+ if (await this.enablingDeviceLogging()) {
176
+ if (this.deviceLogging?.includes('debug')) {
177
+ this.log.warn(`[DEBUG] ${this.device.name}: ${this.accessory.displayName}`, String(...log));
178
+ }
179
+ }
180
+ }
181
+ async errorLog(...log) {
182
+ if (await this.enablingDeviceLogging()) {
183
+ this.log.error(`${this.device.name}: ${this.accessory.displayName}`, String(...log));
184
+ }
185
+ }
186
+ async debugErrorLog(...log) {
187
+ if (await this.enablingDeviceLogging()) {
188
+ if (this.deviceLogging?.includes('debug')) {
189
+ this.log.error(`[DEBUG] ${this.device.name}: ${this.accessory.displayName}`, String(...log));
190
+ }
191
+ }
192
+ }
193
+ async debugLog(...log) {
194
+ if (await this.enablingDeviceLogging()) {
195
+ if (this.deviceLogging === 'debug') {
196
+ this.log.info(`[DEBUG] ${this.device.name}: ${this.accessory.displayName}`, String(...log));
197
+ }
198
+ else {
199
+ this.log.debug(`${this.device.name}: ${this.accessory.displayName}`, String(...log));
200
+ }
201
+ }
202
+ }
203
+ async enablingDeviceLogging() {
204
+ return this.deviceLogging.includes('debug') ?? this.deviceLogging === 'standard';
205
+ }
206
+ }
207
+ //# sourceMappingURL=device.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device.js","sourceRoot":"","sources":["../../../src/devices/device.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,34 @@
1
+ import type { PlatformAccessory } from 'homebridge';
2
+ import { Subject } from 'rxjs';
3
+ import type { ResideoDevice } from '../api/resideoClient.js';
4
+ import type { ResideoPlatform } from '../platform.js';
5
+ import { deviceBase } from './device.js';
6
+ /**
7
+ * Platform Accessory
8
+ * An instance of this class is created for each accessory your platform registers
9
+ * Each accessory may expose multiple services of different service types.
10
+ */
11
+ export declare class LeakSensor extends deviceBase {
12
+ readonly platform: ResideoPlatform;
13
+ private Battery;
14
+ private LeakSensor?;
15
+ private HumiditySensor?;
16
+ private TemperatureSensor?;
17
+ SensorUpdateInProgress: boolean;
18
+ doSensorUpdate: Subject<void>;
19
+ constructor(platform: ResideoPlatform, accessory: PlatformAccessory, device: ResideoDevice);
20
+ /**
21
+ * Parse the device status from the FirstAlert api
22
+ */
23
+ parseStatus(): Promise<void>;
24
+ /**
25
+ * Asks the FirstAlert Home API for the latest device information
26
+ */
27
+ refreshStatus(): Promise<void>;
28
+ /**
29
+ * Updates the status for each of the HomeKit Characteristics
30
+ */
31
+ updateHomeKitCharacteristics(): Promise<void>;
32
+ apiError(e: any): Promise<void>;
33
+ }
34
+ //# sourceMappingURL=leaksensors.d.ts.map