@homebridge-plugins/homebridge-august 3.3.0-beta.0 → 3.3.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -14
- package/CLAUDE.md +48 -0
- package/README.md +39 -27
- package/config.schema.json +47 -3
- package/dist/Platform.HAP.d.ts +139 -20
- package/dist/Platform.HAP.d.ts.map +1 -1
- package/dist/Platform.HAP.js +732 -46
- package/dist/Platform.HAP.js.map +1 -1
- package/dist/connectivity-manager.d.ts +3 -3
- package/dist/connectivity-manager.d.ts.map +1 -1
- package/dist/connectivity-manager.js +14 -57
- package/dist/connectivity-manager.js.map +1 -1
- package/dist/devices/device.d.ts +16 -5
- package/dist/devices/device.d.ts.map +1 -1
- package/dist/devices/device.js +75 -18
- package/dist/devices/device.js.map +1 -1
- package/dist/devices/device.test.d.ts +2 -0
- package/dist/devices/device.test.d.ts.map +1 -0
- package/dist/devices/device.test.js +294 -0
- package/dist/devices/device.test.js.map +1 -0
- package/dist/devices/lock.d.ts +3 -3
- package/dist/devices/lock.d.ts.map +1 -1
- package/dist/devices/lock.js +41 -41
- package/dist/devices/lock.js.map +1 -1
- package/dist/index.js +4 -4
- package/dist/index.js.map +1 -1
- package/dist/platform.matter.d.ts +26 -18
- package/dist/platform.matter.d.ts.map +1 -1
- package/dist/platform.matter.js +95 -76
- package/dist/platform.matter.js.map +1 -1
- package/dist/settings.d.ts +1 -0
- package/dist/settings.d.ts.map +1 -1
- package/package.json +37 -32
- package/test/connectivity-manager.test.ts +592 -0
- package/test/platform.matter.test.ts +660 -0
- package/test/platform.polling.test.ts +5 -5
- package/test/{platform.hap.test.ts → platform.test.ts} +23 -23
- package/.github/FUNDING.yml +0 -4
- package/.github/ISSUE_TEMPLATE/bug-report.yml +0 -97
- package/.github/ISSUE_TEMPLATE/config.yml +0 -8
- package/.github/ISSUE_TEMPLATE/feature-request.yml +0 -38
- package/.github/ISSUE_TEMPLATE/support-request.yml +0 -85
- package/.github/ISSUE_TEMPLATE.md +0 -48
- package/.github/PULL_REQUEST_TEMPLATE/pull_request.md +0 -27
- package/.github/copilot-instructions.md +0 -200
- package/.github/dependabot.yml +0 -17
- package/.github/labeler.yml +0 -38
- package/.github/npm-version-script-esm.js +0 -97
- package/.github/workflows/release.yml +0 -169
- package/.github/workflows/stale.yml +0 -12
- package/SECURITY.md +0 -19
- package/branding/Homebridge_x_August.svg +0 -32
- package/branding/icon.png +0 -0
- package/dist/Platform.Base.d.ts +0 -288
- package/dist/Platform.Base.d.ts.map +0 -1
- package/dist/Platform.Base.js +0 -797
- package/dist/Platform.Base.js.map +0 -1
- package/dist/package.json +0 -85
- package/docs/.nojekyll +0 -1
- package/docs/assets/hierarchy.js +0 -1
- package/docs/assets/highlight.css +0 -22
- package/docs/assets/icons.js +0 -18
- package/docs/assets/icons.svg +0 -1
- package/docs/assets/main.js +0 -60
- package/docs/assets/navigation.js +0 -1
- package/docs/assets/search.js +0 -1
- package/docs/assets/style.css +0 -1633
- package/docs/hierarchy.html +0 -1
- package/docs/index.html +0 -44
- package/docs/modules.html +0 -1
- package/docs/variables/default.html +0 -1
- package/eslint.config.js +0 -47
- package/test/device.test.ts +0 -384
- package/vitest.config.ts +0 -8
package/docs/hierarchy.html
DELETED
|
@@ -1 +0,0 @@
|
|
|
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>@homebridge-plugins/homebridge-august</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-august"/><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-august</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"><h1>@homebridge-plugins/homebridge-august</h1></div><h2>Hierarchy Summary</h2></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-august</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/docs/index.html
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
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>@homebridge-plugins/homebridge-august</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-august"/><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-august</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"><h1>@homebridge-plugins/homebridge-august</h1></div><div class="tsd-panel tsd-typography"><span align="center">
|
|
2
|
-
<p><a href="https://github.com/homebridge/verified/blob/master/verified-plugins.json"><img alt="homebridge-verified" src="https://raw.githubusercontent.com/homebridge-plugins/homebridge-august/latest/branding/Homebridge_x_August.svg?sanitize=true" width="350px"></a></p>
|
|
3
|
-
<h1 id="homebridge-august" class="tsd-anchor-link">Homebridge August<a href="#homebridge-august" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h1>
|
|
4
|
-
<p><a href="https://www.npmjs.com/package/homebridge-august"><img title="npm version" src="https://badgen.net/npm/v/homebridge-august?icon=npm&label" ></a>
|
|
5
|
-
<a href="https://www.npmjs.com/package/homebridge-august"><img title="npm downloads" src="https://badgen.net/npm/dt/homebridge-august?label=downloads" ></a>
|
|
6
|
-
<a href="https://discord.gg/8fpZA4S"><img title="discord-august" src="https://badgen.net/discord/online-members/8fpZA4S?icon=discord&label=discord" ></a>
|
|
7
|
-
<a href="https://paypal.me/donavanbecker"><img title="donate" src="https://badgen.net/badge/donate/paypal/yellow" ></a></p>
|
|
8
|
-
<p>The Homebridge <a href="https://august.com">August</a>
|
|
9
|
-
plugin allows you to access your <a href="https://august.com">August</a> & <a href="https://shopyalehome.com">Yale</a> Lock(s) from HomeKit with
|
|
10
|
-
<a href="https://homebridge.io">Homebridge</a>.
|
|
11
|
-
</p>
|
|
12
|
-
</span>
|
|
13
|
-
<h2 id="installation" class="tsd-anchor-link">Installation<a href="#installation" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
|
|
14
|
-
<ol>
|
|
15
|
-
<li>Search for "August" on the plugin screen of <a href="https://github.com/oznu/homebridge-config-ui-x">Homebridge Config UI X</a>.</li>
|
|
16
|
-
<li>Click <strong>Install</strong>.</li>
|
|
17
|
-
</ol>
|
|
18
|
-
<h2 id="configuration" class="tsd-anchor-link">Configuration<a href="#configuration" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
|
|
19
|
-
<ol>
|
|
20
|
-
<li>
|
|
21
|
-
<p>Input your August E-mail/Phone Number into the August Account Info.</p>
|
|
22
|
-
</li>
|
|
23
|
-
<li>
|
|
24
|
-
<p>August Validate code will be sent after restarting Homebridge.</p>
|
|
25
|
-
</li>
|
|
26
|
-
<li>
|
|
27
|
-
<p>Input your Validate Code into the August Account Info.</p>
|
|
28
|
-
</li>
|
|
29
|
-
<li>
|
|
30
|
-
<p>Finally Restart Homebridge.</p>
|
|
31
|
-
</li>
|
|
32
|
-
</ol>
|
|
33
|
-
<h2 id="supported-august-devices" class="tsd-anchor-link">Supported August Devices<a href="#supported-august-devices" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
|
|
34
|
-
<ul>
|
|
35
|
-
<li>August Smart lock (AUG-SL04-C03-N04)</li>
|
|
36
|
-
<li>August Smart Lock Pro 3rd Gee (AUG-SL03-C02-G03-C)</li>
|
|
37
|
-
<li>August WiFi Smart Lock (Gen 4)</li>
|
|
38
|
-
<li>Yale Assure Lock (AUG-MD01)</li>
|
|
39
|
-
<li>Yale Assure Lock 2 (YDR410)</li>
|
|
40
|
-
<li>Yale Assure Lock SL (YDR256)</li>
|
|
41
|
-
</ul>
|
|
42
|
-
<h2 id="thanks" class="tsd-anchor-link">Thanks<a href="#thanks" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></h2>
|
|
43
|
-
<p>Thank you to <a href="https://github.com/hufftheweevil">hufftheweevil</a> for the <a href="https://github.com/hufftheweevil/august-api">august-api</a> module.</p>
|
|
44
|
-
</div></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><details open class="tsd-accordion tsd-page-navigation"><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>On This Page</h3></summary><div class="tsd-accordion-details"><a href="#homebridge-august"><span>Homebridge <wbr/>August</span></a><ul><li><a href="#installation"><span>Installation</span></a></li><li><a href="#configuration"><span>Configuration</span></a></li><li><a href="#supported-august-devices"><span>Supported <wbr/>August <wbr/>Devices</span></a></li><li><a href="#thanks"><span>Thanks</span></a></li></ul></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html">@homebridge-plugins/homebridge-august</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/docs/modules.html
DELETED
|
@@ -1 +0,0 @@
|
|
|
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>@homebridge-plugins/homebridge-august</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-august"/><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-august</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"></ul><h1>@homebridge-plugins/homebridge-august</h1></div><details class="tsd-panel-group tsd-member-group tsd-accordion" open><summary class="tsd-accordion-summary" data-key="section-Variables"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg><h2>Variables</h2></summary><dl class="tsd-member-summaries"><dt class="tsd-member-summary" id="default"><span class="tsd-member-summary-name"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Variable"><use href="assets/icons.svg#icon-32"></use></svg><a href="variables/default.html">default</a><a href="#default" aria-label="Permalink" class="tsd-anchor-icon"><svg viewBox="0 0 24 24" aria-hidden="true"><use href="assets/icons.svg#icon-anchor"></use></svg></a></span></dt><dd class="tsd-member-summary"></dd></dl></details></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><details open class="tsd-accordion tsd-page-navigation"><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>On This Page</h3></summary><div class="tsd-accordion-details"><details open class="tsd-accordion tsd-page-navigation-section"><summary class="tsd-accordion-summary" data-key="section-Variables"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="assets/icons.svg#icon-chevronDown"></use></svg>Variables</summary><div><a href="#default"><svg class="tsd-kind-icon" viewBox="0 0 24 24" aria-label="Variable"><use href="assets/icons.svg#icon-32"></use></svg><span>default</span></a></div></details></div></details></div><div class="site-menu"><nav class="tsd-navigation"><a href="modules.html" class="current">@homebridge-plugins/homebridge-august</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 +0,0 @@
|
|
|
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-august</title><meta name="description" content="Documentation for @homebridge-plugins/homebridge-august"/><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-august</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">=></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-august/blob/037fd62475c7abe0fc3ed48ecbe23d6f8ccce51d/src/index.ts#L26">index.ts:26</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-august</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/eslint.config.js
DELETED
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import antfu from '@antfu/eslint-config'
|
|
2
|
-
|
|
3
|
-
export default antfu(
|
|
4
|
-
{
|
|
5
|
-
ignores: ['dist', 'docs'],
|
|
6
|
-
jsx: false,
|
|
7
|
-
typescript: true,
|
|
8
|
-
formatters: {
|
|
9
|
-
markdown: true,
|
|
10
|
-
},
|
|
11
|
-
rules: {
|
|
12
|
-
'curly': ['error', 'multi-line'],
|
|
13
|
-
'import/order': 0,
|
|
14
|
-
'jsdoc/check-alignment': 'error',
|
|
15
|
-
'jsdoc/check-line-alignment': 'error',
|
|
16
|
-
'no-new': 0,
|
|
17
|
-
'no-undef': 0,
|
|
18
|
-
'perfectionist/sort-exports': 'error',
|
|
19
|
-
'perfectionist/sort-imports': [
|
|
20
|
-
'error',
|
|
21
|
-
{
|
|
22
|
-
groups: [
|
|
23
|
-
'type-builtin',
|
|
24
|
-
'type-external',
|
|
25
|
-
'type-internal',
|
|
26
|
-
['type-parent', 'type-sibling', 'type-index'],
|
|
27
|
-
'builtin',
|
|
28
|
-
'external',
|
|
29
|
-
'internal',
|
|
30
|
-
['parent', 'sibling', 'index'],
|
|
31
|
-
'unknown',
|
|
32
|
-
],
|
|
33
|
-
order: 'asc',
|
|
34
|
-
type: 'natural',
|
|
35
|
-
},
|
|
36
|
-
],
|
|
37
|
-
'perfectionist/sort-named-exports': 'error',
|
|
38
|
-
'perfectionist/sort-named-imports': 'error',
|
|
39
|
-
'sort-imports': 0,
|
|
40
|
-
'style/brace-style': ['error', '1tbs', { allowSingleLine: true }],
|
|
41
|
-
'style/quote-props': ['error', 'consistent-as-needed'],
|
|
42
|
-
'test/no-only-tests': 'error',
|
|
43
|
-
'unicorn/no-useless-spread': 'error',
|
|
44
|
-
'unused-imports/no-unused-vars': ['error', { caughtErrors: 'none' }],
|
|
45
|
-
},
|
|
46
|
-
},
|
|
47
|
-
)
|
package/test/device.test.ts
DELETED
|
@@ -1,384 +0,0 @@
|
|
|
1
|
-
import type { CharacteristicValue, Service } from 'homebridge'
|
|
2
|
-
|
|
3
|
-
import { beforeEach, describe, expect, it, vi } from 'vitest'
|
|
4
|
-
|
|
5
|
-
// Create a simplified test implementation that mimics the updateCharacteristic behavior
|
|
6
|
-
class MockDeviceWithCharacteristics {
|
|
7
|
-
accessory = { context: {} as Record<string, CharacteristicValue>, displayName: 'Test Lock' }
|
|
8
|
-
debugLog = vi.fn()
|
|
9
|
-
debugWarnLog = vi.fn()
|
|
10
|
-
infoLog = vi.fn()
|
|
11
|
-
|
|
12
|
-
async updateCharacteristic(
|
|
13
|
-
Service: Service,
|
|
14
|
-
ServiceName: string,
|
|
15
|
-
Characteristic: any,
|
|
16
|
-
CharacteristicValue: CharacteristicValue,
|
|
17
|
-
CharacteristicName: string,
|
|
18
|
-
Value?: CharacteristicValue,
|
|
19
|
-
StatusMatch?: string,
|
|
20
|
-
StatusDoesNotMatch?: string,
|
|
21
|
-
): Promise<void> {
|
|
22
|
-
if (CharacteristicValue === undefined) {
|
|
23
|
-
await this.debugLog(`${CharacteristicName}: ${CharacteristicValue}`)
|
|
24
|
-
} else {
|
|
25
|
-
const contextKey = `${ServiceName}${CharacteristicName}`
|
|
26
|
-
await this.debugWarnLog(`context before: ${this.accessory.context[contextKey]}`)
|
|
27
|
-
const contextBefore = this.accessory.context[contextKey]
|
|
28
|
-
this.accessory.context[contextKey] = CharacteristicValue
|
|
29
|
-
await this.debugWarnLog(`context after: ${this.accessory.context[contextKey]}`)
|
|
30
|
-
await this.debugLog(`updateCharacteristic ${CharacteristicName}: ${CharacteristicValue} (${CharacteristicValue === Value ? StatusMatch : StatusDoesNotMatch})`)
|
|
31
|
-
if (contextBefore !== CharacteristicValue) {
|
|
32
|
-
// Value actually changed - push update to HomeKit
|
|
33
|
-
Service.updateCharacteristic(Characteristic, CharacteristicValue)
|
|
34
|
-
// Only log state change messages when we had a prior known value (not initial discovery)
|
|
35
|
-
if (contextBefore !== undefined && StatusMatch && StatusDoesNotMatch) {
|
|
36
|
-
await this.infoLog(`was ${CharacteristicValue === Value ? StatusMatch : StatusDoesNotMatch}`)
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// Create a simplified test implementation that mimics the statusCode behavior
|
|
44
|
-
class MockDevice {
|
|
45
|
-
debugLog = vi.fn()
|
|
46
|
-
debugErrorLog = vi.fn()
|
|
47
|
-
|
|
48
|
-
/**
|
|
49
|
-
* Check if error is a network timeout or session expiration that requires session refresh
|
|
50
|
-
* Handles 502 Bad Gateway, 401 Unauthorized, 503 Service Unavailable, and network timeouts
|
|
51
|
-
*/
|
|
52
|
-
isTimeoutError(error: { message: string, name?: string, statusCode?: number }): boolean {
|
|
53
|
-
// Check for august-yale TimeoutError by name (stable contract — works regardless
|
|
54
|
-
// of message format changes) and Node.js network timeouts by message
|
|
55
|
-
if (error.name === 'TimeoutError' || error.message?.includes('ETIMEDOUT')) {
|
|
56
|
-
return true
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
// Check for status codes that indicate session expiration or temporary server issues
|
|
60
|
-
// 502 Bad Gateway - typically indicates session has expired or server issues
|
|
61
|
-
// 503 Service Unavailable - temporary server issues
|
|
62
|
-
// 401 Unauthorized - session has expired
|
|
63
|
-
if (error.statusCode && (error.statusCode === 502 || error.statusCode === 503 || error.statusCode === 401)) {
|
|
64
|
-
return true
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Check for error messages containing these status codes (from tiny-json-http error format)
|
|
68
|
-
// Format: "POST failed with: 502" or "GET failed with: 401"
|
|
69
|
-
if (error.message) {
|
|
70
|
-
const sessionErrorPatterns = [
|
|
71
|
-
/failed with: 502/i,
|
|
72
|
-
/failed with: 503/i,
|
|
73
|
-
/failed with: 401/i,
|
|
74
|
-
/Bad Gateway/i,
|
|
75
|
-
/Service Unavailable/i,
|
|
76
|
-
/Unauthorized/i,
|
|
77
|
-
]
|
|
78
|
-
return sessionErrorPatterns.some(pattern => pattern.test(error.message))
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
return false
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
async statusCode(action: string, error: { message: string, constructor?: { name: string } }): Promise<void> {
|
|
85
|
-
const statusCodeString = error.message || '' // Convert statusCode to a string, handle undefined/null
|
|
86
|
-
|
|
87
|
-
// Check if the error is an AggregateError or doesn't contain a status code
|
|
88
|
-
if (error.constructor?.name === 'AggregateError' || !/^\d{3}/.test(statusCodeString)) {
|
|
89
|
-
await this.debugErrorLog(`${action} failed with ${error.constructor?.name || 'Error'}: ${statusCodeString}`)
|
|
90
|
-
return
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const statusCode = statusCodeString.slice(0, 3)
|
|
94
|
-
const logMap: Record<string, string> = {
|
|
95
|
-
100: `Command successfully sent, statusCode: ${statusCodeString}`,
|
|
96
|
-
200: `Request successful, statusCode: ${statusCodeString}`,
|
|
97
|
-
400: `Bad Request, statusCode: ${statusCodeString}`,
|
|
98
|
-
429: `Too Many Requests, exceeded the number of requests allowed for a given time window, statusCode: ${statusCodeString}`,
|
|
99
|
-
}
|
|
100
|
-
const logMessage = logMap[statusCode]
|
|
101
|
-
?? `Unknown statusCode: ${statusCodeString}, Submit Bugs Here: https://tinyurl.com/AugustYaleBug`
|
|
102
|
-
await this.debugLog(logMessage)
|
|
103
|
-
if (!logMap[statusCode]) {
|
|
104
|
-
await this.debugErrorLog(`failed ${action}, Error: ${error}`)
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
describe('statusCode error handling', () => {
|
|
110
|
-
let mockDevice: MockDevice
|
|
111
|
-
|
|
112
|
-
beforeEach(() => {
|
|
113
|
-
mockDevice = new MockDevice()
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
describe('isTimeoutError method', () => {
|
|
117
|
-
it('should detect august-yale TimeoutError by error.name', () => {
|
|
118
|
-
const error = { message: 'Request timed out after 30000ms', name: 'TimeoutError' }
|
|
119
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
120
|
-
})
|
|
121
|
-
|
|
122
|
-
it('should detect august-yale TimeoutError regardless of message content', () => {
|
|
123
|
-
const error = { message: 'anything', name: 'TimeoutError' }
|
|
124
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
it('should detect ETIMEDOUT network errors', () => {
|
|
128
|
-
const error = { message: 'ETIMEDOUT connection timed out' }
|
|
129
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
130
|
-
})
|
|
131
|
-
|
|
132
|
-
it('should detect 502 Bad Gateway status code', () => {
|
|
133
|
-
const error = { message: 'POST failed with: 502', statusCode: 502 }
|
|
134
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
it('should detect 502 in error message', () => {
|
|
138
|
-
const error = { message: 'POST failed with: 502' }
|
|
139
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
it('should detect 503 Service Unavailable status code', () => {
|
|
143
|
-
const error = { message: 'GET failed with: 503', statusCode: 503 }
|
|
144
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
145
|
-
})
|
|
146
|
-
|
|
147
|
-
it('should detect 503 in error message', () => {
|
|
148
|
-
const error = { message: 'Service Unavailable' }
|
|
149
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
150
|
-
})
|
|
151
|
-
|
|
152
|
-
it('should detect 401 Unauthorized status code', () => {
|
|
153
|
-
const error = { message: 'POST failed with: 401', statusCode: 401 }
|
|
154
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
155
|
-
})
|
|
156
|
-
|
|
157
|
-
it('should detect 401 in error message', () => {
|
|
158
|
-
const error = { message: 'Unauthorized access' }
|
|
159
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
160
|
-
})
|
|
161
|
-
|
|
162
|
-
it('should detect Bad Gateway in error message', () => {
|
|
163
|
-
const error = { message: 'Bad Gateway' }
|
|
164
|
-
expect(mockDevice.isTimeoutError(error)).toBe(true)
|
|
165
|
-
})
|
|
166
|
-
|
|
167
|
-
it('should return false for non-timeout errors', () => {
|
|
168
|
-
const error = { message: '404 Not Found' }
|
|
169
|
-
expect(mockDevice.isTimeoutError(error)).toBe(false)
|
|
170
|
-
})
|
|
171
|
-
|
|
172
|
-
it('should return false for 400 Bad Request', () => {
|
|
173
|
-
const error = { message: '400 Bad Request', statusCode: 400 }
|
|
174
|
-
expect(mockDevice.isTimeoutError(error)).toBe(false)
|
|
175
|
-
})
|
|
176
|
-
|
|
177
|
-
it('should return false for 429 Too Many Requests', () => {
|
|
178
|
-
const error = { message: '429 Too Many Requests', statusCode: 429 }
|
|
179
|
-
expect(mockDevice.isTimeoutError(error)).toBe(false)
|
|
180
|
-
})
|
|
181
|
-
|
|
182
|
-
it('should return false for empty message', () => {
|
|
183
|
-
const error = { message: '' }
|
|
184
|
-
expect(mockDevice.isTimeoutError(error)).toBe(false)
|
|
185
|
-
})
|
|
186
|
-
|
|
187
|
-
it('should return false for errors with non-timeout name', () => {
|
|
188
|
-
const error = { message: 'something failed', name: 'Error' }
|
|
189
|
-
expect(mockDevice.isTimeoutError(error)).toBe(false)
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
it('should not match 401 in non-HTTP status contexts', () => {
|
|
193
|
-
const error = { message: 'Expected 4012 records but found 401' }
|
|
194
|
-
expect(mockDevice.isTimeoutError(error)).toBe(false)
|
|
195
|
-
})
|
|
196
|
-
|
|
197
|
-
it('should not match 502 in non-HTTP status contexts', () => {
|
|
198
|
-
const error = { message: 'Lock ID 50234 not found' }
|
|
199
|
-
expect(mockDevice.isTimeoutError(error)).toBe(false)
|
|
200
|
-
})
|
|
201
|
-
})
|
|
202
|
-
|
|
203
|
-
describe('statusCode method', () => {
|
|
204
|
-
it('should handle standard HTTP status codes', async () => {
|
|
205
|
-
await mockDevice.statusCode('test action', { message: '400 Bad Request' })
|
|
206
|
-
|
|
207
|
-
expect(mockDevice.debugLog).toHaveBeenCalledWith('Bad Request, statusCode: 400 Bad Request')
|
|
208
|
-
expect(mockDevice.debugErrorLog).not.toHaveBeenCalled()
|
|
209
|
-
})
|
|
210
|
-
|
|
211
|
-
it('should handle AggregateError specifically', async () => {
|
|
212
|
-
await mockDevice.statusCode('refreshStatus', {
|
|
213
|
-
message: 'Multiple errors occurred',
|
|
214
|
-
constructor: { name: 'AggregateError' },
|
|
215
|
-
})
|
|
216
|
-
|
|
217
|
-
expect(mockDevice.debugErrorLog).toHaveBeenCalledWith('refreshStatus failed with AggregateError: Multiple errors occurred')
|
|
218
|
-
expect(mockDevice.debugLog).not.toHaveBeenCalled()
|
|
219
|
-
})
|
|
220
|
-
|
|
221
|
-
it('should handle error with empty message', async () => {
|
|
222
|
-
await mockDevice.statusCode('refreshStatus', { message: '' })
|
|
223
|
-
|
|
224
|
-
expect(mockDevice.debugErrorLog).toHaveBeenCalledWith('refreshStatus failed with Object: ')
|
|
225
|
-
expect(mockDevice.debugLog).not.toHaveBeenCalled()
|
|
226
|
-
})
|
|
227
|
-
|
|
228
|
-
it('should handle error message without numeric status code', async () => {
|
|
229
|
-
await mockDevice.statusCode('refreshStatus', { message: 'Network connection failed' })
|
|
230
|
-
|
|
231
|
-
expect(mockDevice.debugErrorLog).toHaveBeenCalledWith('refreshStatus failed with Object: Network connection failed')
|
|
232
|
-
expect(mockDevice.debugLog).not.toHaveBeenCalled()
|
|
233
|
-
})
|
|
234
|
-
|
|
235
|
-
it('should handle 429 Too Many Requests status code', async () => {
|
|
236
|
-
await mockDevice.statusCode('test action', { message: '429 Too Many Requests' })
|
|
237
|
-
|
|
238
|
-
expect(mockDevice.debugLog).toHaveBeenCalledWith('Too Many Requests, exceeded the number of requests allowed for a given time window, statusCode: 429 Too Many Requests')
|
|
239
|
-
expect(mockDevice.debugErrorLog).not.toHaveBeenCalled()
|
|
240
|
-
})
|
|
241
|
-
|
|
242
|
-
it('should handle unknown numeric status codes', async () => {
|
|
243
|
-
await mockDevice.statusCode('test action', { message: '503 Service Unavailable' })
|
|
244
|
-
|
|
245
|
-
expect(mockDevice.debugLog).toHaveBeenCalledWith('Unknown statusCode: 503 Service Unavailable, Submit Bugs Here: https://tinyurl.com/AugustYaleBug')
|
|
246
|
-
expect(mockDevice.debugErrorLog).toHaveBeenCalledWith('failed test action, Error: [object Object]')
|
|
247
|
-
})
|
|
248
|
-
})
|
|
249
|
-
})
|
|
250
|
-
|
|
251
|
-
describe('updateCharacteristic', () => {
|
|
252
|
-
let device: MockDeviceWithCharacteristics
|
|
253
|
-
let mockService: Service
|
|
254
|
-
const CHARACTERISTIC = 'LockCurrentState'
|
|
255
|
-
|
|
256
|
-
beforeEach(() => {
|
|
257
|
-
device = new MockDeviceWithCharacteristics()
|
|
258
|
-
mockService = {
|
|
259
|
-
updateCharacteristic: vi.fn(),
|
|
260
|
-
} as unknown as Service
|
|
261
|
-
})
|
|
262
|
-
|
|
263
|
-
it('should skip HomeKit update when CharacteristicValue is undefined', async () => {
|
|
264
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, undefined as any, 'LockCurrentState')
|
|
265
|
-
|
|
266
|
-
expect(mockService.updateCharacteristic).not.toHaveBeenCalled()
|
|
267
|
-
expect(device.debugLog).toHaveBeenCalledWith('LockCurrentState: undefined')
|
|
268
|
-
})
|
|
269
|
-
|
|
270
|
-
describe('initial state discovery (no prior context)', () => {
|
|
271
|
-
it('should push value to HomeKit on first update', async () => {
|
|
272
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 0, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
273
|
-
|
|
274
|
-
expect(mockService.updateCharacteristic).toHaveBeenCalledWith(CHARACTERISTIC, 0)
|
|
275
|
-
})
|
|
276
|
-
|
|
277
|
-
it('should NOT log info message on initial discovery', async () => {
|
|
278
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 0, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
279
|
-
|
|
280
|
-
expect(device.infoLog).not.toHaveBeenCalled()
|
|
281
|
-
})
|
|
282
|
-
|
|
283
|
-
it('should store the value in context for future comparisons', async () => {
|
|
284
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 0, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
285
|
-
|
|
286
|
-
expect(device.accessory.context.LockMechanismLockCurrentState).toBe(0)
|
|
287
|
-
})
|
|
288
|
-
})
|
|
289
|
-
|
|
290
|
-
describe('subsequent updates with unchanged value', () => {
|
|
291
|
-
it('should NOT push to HomeKit when value has not changed', async () => {
|
|
292
|
-
// Seed context as if a previous update occurred
|
|
293
|
-
device.accessory.context.LockMechanismLockCurrentState = 1
|
|
294
|
-
|
|
295
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 1, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
296
|
-
|
|
297
|
-
expect(mockService.updateCharacteristic).not.toHaveBeenCalled()
|
|
298
|
-
})
|
|
299
|
-
|
|
300
|
-
it('should NOT log info message when value has not changed', async () => {
|
|
301
|
-
device.accessory.context.LockMechanismLockCurrentState = 1
|
|
302
|
-
|
|
303
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 1, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
304
|
-
|
|
305
|
-
expect(device.infoLog).not.toHaveBeenCalled()
|
|
306
|
-
})
|
|
307
|
-
})
|
|
308
|
-
|
|
309
|
-
describe('genuine state change', () => {
|
|
310
|
-
it('should push to HomeKit when value changes', async () => {
|
|
311
|
-
device.accessory.context.LockMechanismLockCurrentState = 1
|
|
312
|
-
|
|
313
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 0, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
314
|
-
|
|
315
|
-
expect(mockService.updateCharacteristic).toHaveBeenCalledWith(CHARACTERISTIC, 0)
|
|
316
|
-
})
|
|
317
|
-
|
|
318
|
-
it('should log "was Unlocked" when lock changes from secured to unsecured', async () => {
|
|
319
|
-
device.accessory.context.LockMechanismLockCurrentState = 1
|
|
320
|
-
|
|
321
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 0, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
322
|
-
|
|
323
|
-
expect(device.infoLog).toHaveBeenCalledWith('was Unlocked')
|
|
324
|
-
})
|
|
325
|
-
|
|
326
|
-
it('should log "was Locked" when lock changes from unsecured to secured', async () => {
|
|
327
|
-
device.accessory.context.LockMechanismLockCurrentState = 0
|
|
328
|
-
|
|
329
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 1, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
330
|
-
|
|
331
|
-
expect(device.infoLog).toHaveBeenCalledWith('was Locked')
|
|
332
|
-
})
|
|
333
|
-
|
|
334
|
-
it('should update context to new value', async () => {
|
|
335
|
-
device.accessory.context.LockMechanismLockCurrentState = 1
|
|
336
|
-
|
|
337
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 0, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
338
|
-
|
|
339
|
-
expect(device.accessory.context.LockMechanismLockCurrentState).toBe(0)
|
|
340
|
-
})
|
|
341
|
-
})
|
|
342
|
-
|
|
343
|
-
describe('contact sensor state changes', () => {
|
|
344
|
-
it('should log "was Closed" when door changes to closed', async () => {
|
|
345
|
-
device.accessory.context.ContactSensorContactSensorState = 1
|
|
346
|
-
|
|
347
|
-
await device.updateCharacteristic(mockService, 'ContactSensor', 'ContactSensorState', 0, 'ContactSensorState', 1, 'Opened', 'Closed')
|
|
348
|
-
|
|
349
|
-
expect(device.infoLog).toHaveBeenCalledWith('was Closed')
|
|
350
|
-
})
|
|
351
|
-
|
|
352
|
-
it('should log "was Opened" when door changes to open', async () => {
|
|
353
|
-
device.accessory.context.ContactSensorContactSensorState = 0
|
|
354
|
-
|
|
355
|
-
await device.updateCharacteristic(mockService, 'ContactSensor', 'ContactSensorState', 1, 'ContactSensorState', 1, 'Opened', 'Closed')
|
|
356
|
-
|
|
357
|
-
expect(device.infoLog).toHaveBeenCalledWith('was Opened')
|
|
358
|
-
})
|
|
359
|
-
})
|
|
360
|
-
|
|
361
|
-
describe('updates without StatusMatch/StatusDoesNotMatch', () => {
|
|
362
|
-
it('should push to HomeKit but not log info when no status strings provided', async () => {
|
|
363
|
-
device.accessory.context.BatteryBatteryLevel = 90
|
|
364
|
-
|
|
365
|
-
await device.updateCharacteristic(mockService, 'Battery', 'BatteryLevel', 85, 'BatteryLevel')
|
|
366
|
-
|
|
367
|
-
expect(mockService.updateCharacteristic).toHaveBeenCalledWith('BatteryLevel', 85)
|
|
368
|
-
expect(device.infoLog).not.toHaveBeenCalled()
|
|
369
|
-
})
|
|
370
|
-
})
|
|
371
|
-
|
|
372
|
-
describe('startup simulation (seeded context matches API response)', () => {
|
|
373
|
-
it('should not push to HomeKit or log when seeded context matches first API value', async () => {
|
|
374
|
-
// Simulate constructor seeding: accessory.context.LockMechanismLockCurrentState ??= SECURED
|
|
375
|
-
device.accessory.context.LockMechanismLockCurrentState = 1
|
|
376
|
-
|
|
377
|
-
// First API response returns same state (SECURED = 1)
|
|
378
|
-
await device.updateCharacteristic(mockService, 'LockMechanism', CHARACTERISTIC, 1, 'LockCurrentState', 1, 'Locked', 'Unlocked')
|
|
379
|
-
|
|
380
|
-
expect(mockService.updateCharacteristic).not.toHaveBeenCalled()
|
|
381
|
-
expect(device.infoLog).not.toHaveBeenCalled()
|
|
382
|
-
})
|
|
383
|
-
})
|
|
384
|
-
})
|