@homebridge-plugins/homebridge-august 3.3.0-beta.0 → 3.3.0-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 (74) hide show
  1. package/CHANGELOG.md +19 -14
  2. package/CLAUDE.md +48 -0
  3. package/README.md +39 -27
  4. package/config.schema.json +48 -3
  5. package/dist/Platform.HAP.d.ts +139 -20
  6. package/dist/Platform.HAP.d.ts.map +1 -1
  7. package/dist/Platform.HAP.js +732 -46
  8. package/dist/Platform.HAP.js.map +1 -1
  9. package/dist/connectivity-manager.d.ts +3 -3
  10. package/dist/connectivity-manager.d.ts.map +1 -1
  11. package/dist/connectivity-manager.js +14 -57
  12. package/dist/connectivity-manager.js.map +1 -1
  13. package/dist/devices/device.d.ts +16 -5
  14. package/dist/devices/device.d.ts.map +1 -1
  15. package/dist/devices/device.js +75 -18
  16. package/dist/devices/device.js.map +1 -1
  17. package/dist/devices/device.test.d.ts +2 -0
  18. package/dist/devices/device.test.d.ts.map +1 -0
  19. package/dist/devices/device.test.js +294 -0
  20. package/dist/devices/device.test.js.map +1 -0
  21. package/dist/devices/lock.d.ts +3 -3
  22. package/dist/devices/lock.d.ts.map +1 -1
  23. package/dist/devices/lock.js +41 -41
  24. package/dist/devices/lock.js.map +1 -1
  25. package/dist/index.js +4 -4
  26. package/dist/index.js.map +1 -1
  27. package/dist/platform.matter.d.ts +26 -18
  28. package/dist/platform.matter.d.ts.map +1 -1
  29. package/dist/platform.matter.js +95 -76
  30. package/dist/platform.matter.js.map +1 -1
  31. package/dist/settings.d.ts +1 -0
  32. package/dist/settings.d.ts.map +1 -1
  33. package/package.json +37 -32
  34. package/test/connectivity-manager.test.ts +592 -0
  35. package/test/platform.matter.test.ts +660 -0
  36. package/test/platform.polling.test.ts +5 -5
  37. package/test/{platform.hap.test.ts → platform.test.ts} +23 -23
  38. package/.github/FUNDING.yml +0 -4
  39. package/.github/ISSUE_TEMPLATE/bug-report.yml +0 -97
  40. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  41. package/.github/ISSUE_TEMPLATE/feature-request.yml +0 -38
  42. package/.github/ISSUE_TEMPLATE/support-request.yml +0 -85
  43. package/.github/ISSUE_TEMPLATE.md +0 -48
  44. package/.github/PULL_REQUEST_TEMPLATE/pull_request.md +0 -27
  45. package/.github/copilot-instructions.md +0 -200
  46. package/.github/dependabot.yml +0 -17
  47. package/.github/labeler.yml +0 -38
  48. package/.github/npm-version-script-esm.js +0 -97
  49. package/.github/workflows/release.yml +0 -169
  50. package/.github/workflows/stale.yml +0 -12
  51. package/SECURITY.md +0 -19
  52. package/branding/Homebridge_x_August.svg +0 -32
  53. package/branding/icon.png +0 -0
  54. package/dist/Platform.Base.d.ts +0 -288
  55. package/dist/Platform.Base.d.ts.map +0 -1
  56. package/dist/Platform.Base.js +0 -797
  57. package/dist/Platform.Base.js.map +0 -1
  58. package/dist/package.json +0 -85
  59. package/docs/.nojekyll +0 -1
  60. package/docs/assets/hierarchy.js +0 -1
  61. package/docs/assets/highlight.css +0 -22
  62. package/docs/assets/icons.js +0 -18
  63. package/docs/assets/icons.svg +0 -1
  64. package/docs/assets/main.js +0 -60
  65. package/docs/assets/navigation.js +0 -1
  66. package/docs/assets/search.js +0 -1
  67. package/docs/assets/style.css +0 -1633
  68. package/docs/hierarchy.html +0 -1
  69. package/docs/index.html +0 -44
  70. package/docs/modules.html +0 -1
  71. package/docs/variables/default.html +0 -1
  72. package/eslint.config.js +0 -47
  73. package/test/device.test.ts +0 -384
  74. package/vitest.config.ts +0 -8
@@ -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 &quot;August&quot; 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">=&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-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
- )
@@ -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
- })
package/vitest.config.ts DELETED
@@ -1,8 +0,0 @@
1
- import { defineConfig } from 'vitest/config'
2
-
3
- export default defineConfig({
4
- test: {
5
- include: ['test/**/*.test.ts'],
6
- environment: 'node',
7
- },
8
- })