homebridge-generac 0.1.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.
Files changed (71) hide show
  1. package/CHANGELOG.md +32 -0
  2. package/LICENSE +200 -0
  3. package/NOTICE +20 -0
  4. package/README.md +179 -0
  5. package/SECURITY.md +17 -0
  6. package/config.schema.json +133 -0
  7. package/dist/accessory.d.ts +54 -0
  8. package/dist/accessory.js +191 -0
  9. package/dist/accessory.js.map +1 -0
  10. package/dist/api.d.ts +43 -0
  11. package/dist/api.js +124 -0
  12. package/dist/api.js.map +1 -0
  13. package/dist/attention.d.ts +18 -0
  14. package/dist/attention.js +40 -0
  15. package/dist/attention.js.map +1 -0
  16. package/dist/auth.d.ts +56 -0
  17. package/dist/auth.js +412 -0
  18. package/dist/auth.js.map +1 -0
  19. package/dist/captures.d.ts +9 -0
  20. package/dist/captures.js +42 -0
  21. package/dist/captures.js.map +1 -0
  22. package/dist/cli.d.ts +2 -0
  23. package/dist/cli.js +116 -0
  24. package/dist/cli.js.map +1 -0
  25. package/dist/exercise.d.ts +42 -0
  26. package/dist/exercise.js +115 -0
  27. package/dist/exercise.js.map +1 -0
  28. package/dist/files.d.ts +5 -0
  29. package/dist/files.js +28 -0
  30. package/dist/files.js.map +1 -0
  31. package/dist/index.d.ts +3 -0
  32. package/dist/index.js +6 -0
  33. package/dist/index.js.map +1 -0
  34. package/dist/model.d.ts +74 -0
  35. package/dist/model.js +167 -0
  36. package/dist/model.js.map +1 -0
  37. package/dist/platform.d.ts +117 -0
  38. package/dist/platform.js +596 -0
  39. package/dist/platform.js.map +1 -0
  40. package/dist/settings.d.ts +75 -0
  41. package/dist/settings.js +115 -0
  42. package/dist/settings.js.map +1 -0
  43. package/dist/state.d.ts +28 -0
  44. package/dist/state.js +43 -0
  45. package/dist/state.js.map +1 -0
  46. package/dist/types.d.ts +98 -0
  47. package/dist/types.js +48 -0
  48. package/dist/types.js.map +1 -0
  49. package/dist/ui/server.d.ts +96 -0
  50. package/dist/ui/server.js +328 -0
  51. package/dist/ui/server.js.map +1 -0
  52. package/homebridge-ui/public/generac-banner.png +0 -0
  53. package/homebridge-ui/public/generac.css +255 -0
  54. package/homebridge-ui/public/index.css +510 -0
  55. package/homebridge-ui/public/index.html +14 -0
  56. package/homebridge-ui/public/js/api.js +31 -0
  57. package/homebridge-ui/public/js/app.js +1 -0
  58. package/homebridge-ui/public/js/card.js +27 -0
  59. package/homebridge-ui/public/js/copy.js +167 -0
  60. package/homebridge-ui/public/js/dom.js +247 -0
  61. package/homebridge-ui/public/js/footer.js +26 -0
  62. package/homebridge-ui/public/js/format.js +62 -0
  63. package/homebridge-ui/public/js/main.js +288 -0
  64. package/homebridge-ui/public/js/mark.js +34 -0
  65. package/homebridge-ui/public/js/model.js +120 -0
  66. package/homebridge-ui/public/js/sections/account.js +272 -0
  67. package/homebridge-ui/public/js/sections/generators.js +165 -0
  68. package/homebridge-ui/public/js/sections/settings.js +114 -0
  69. package/homebridge-ui/public/js/validate.js +45 -0
  70. package/homebridge-ui/server.js +8 -0
  71. package/package.json +70 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,32 @@
1
+ # Changelog
2
+
3
+ All notable changes to homebridge-generac are listed here. The format follows Keep a Changelog, and the project follows semantic versioning from 0.1.0-beta.1. The release notes of a version are its section here and nothing else. Dates are written US style.
4
+
5
+ ## Unreleased
6
+
7
+ ## 0.1.0-beta.1 (September 15, 2026)
8
+
9
+ First beta of Generac for Homebridge, a ground-up successor to homebridge-mobilelink.
10
+
11
+ ### Added
12
+
13
+ - One accessory per generator on the Mobile Link account with a Running contact sensor, a Fault contact sensor, a Maintenance Due contact sensor, an Exercising contact sensor and a Battery service showing the starting battery level and the low battery flag. Every sensor reports Status Active from the generator's connection and Status Fault from the fault state.
14
+ - Fault opens on a Warning status, active alarms or warnings, an alarm code, the control switch in OFF (Treat Stopped as a fault, on by default) or a lost connection (Treat a lost connection as a fault, off by default). The reasons appear on the settings page and in the log.
15
+ - The Exercising sensor opens while the weekly exercise runs, or when Mobile Link reports one finished since the last check, so an exercise the plugin slept through is still detected. It stays open for the exercise hold time (default 5 minutes). Around the exercise time, from 2 minutes before until 20 minutes after, every day, the plugin checks at the faster interval.
16
+ - Optional Attention needed occupancy sensor that turns on while the plugin needs you to reconnect.
17
+ - A settings page in the Homebridge UI: connect the Mobile Link account (email, password, then the text message, authenticator or email code), see every generator with its status, fault reasons, battery, engine hours, exercise time, last exercise and last seen, rename generators, disconnect, change every setting, and reset the plugin to a fresh install. The page works in both Homebridge UI themes and at phone width.
18
+ - Sign-in from the settings page takes effect within a minute, with no restart.
19
+ - The `homebridge-generac status` and `homebridge-generac login` commands for terminal use.
20
+ - Polling every 10 minutes while idle and every 90 seconds while a generator is running, exercising or in fault, with backoff up to 30 minutes on failures. Sensors show Not responding after three failures in a row.
21
+ - Per-generator display names, kept together with renames made in the Home app.
22
+ - Propane tank monitors and linked ecobee thermostats on the account are listed on the settings page and skipped: tank level support is planned for 0.2.0, and ecobee thermostats are already in HomeKit.
23
+ - With Debug logging on, every status change writes the raw Mobile Link payload to `homebridge-generac/captures/` in the Homebridge storage folder, keeping the newest 10.
24
+
25
+ ### Notes
26
+
27
+ - The plugin is read only. It cannot start, stop or exercise a generator.
28
+ - The Mobile Link password is never stored or logged. The plugin keeps a refresh token in `homebridge-generac/credentials.json` (mode 600) inside the Homebridge storage folder, outside config.json.
29
+ - Accounts created before April 21, 2026 need a password reset since then: Generac moved Mobile Link sign-in to a new system on that date and did not carry older passwords across.
30
+ - Changing the Mobile Link password signs the plugin out. The settings page then shows Reconnect needed; sign in again to resume updates.
31
+ - Accounts set up for push, voice or security-key sign-in cannot be completed by the plugin. Switch the account to text message or an authenticator app in the Mobile Link app first.
32
+ - The settings page shows the low battery threshold with one decimal place, and the Reset dialog opens directly below the Reset link.
package/LICENSE ADDED
@@ -0,0 +1,200 @@
1
+ Apache License
2
+ Version 2.0, January 2004
3
+ http://www.apache.org/licenses/
4
+
5
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
6
+
7
+ 1. Definitions.
8
+
9
+ "License" shall mean the terms and conditions for use, reproduction,
10
+ and distribution as defined by Sections 1 through 9 of this document.
11
+
12
+ "Licensor" shall mean the copyright owner or entity authorized by
13
+ the copyright owner that is granting the License.
14
+
15
+ "Legal Entity" shall mean the union of the acting entity and all
16
+ other entities that control, are controlled by, or are under common
17
+ control with that entity. For the purposes of this definition,
18
+ "control" means (i) the power, direct or indirect, to cause the
19
+ direction or management of such entity, whether by contract or
20
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
21
+ outstanding shares, or (iii) beneficial ownership of such entity.
22
+
23
+ "You" (or "Your") shall mean an individual or Legal Entity
24
+ exercising permissions granted by this License.
25
+
26
+ "Source" form shall mean the preferred form for making modifications,
27
+ including but not limited to software source code, documentation
28
+ source, and configuration files.
29
+
30
+ "Object" form shall mean any form resulting from mechanical
31
+ transformation or translation of a Source form, including but
32
+ not limited to compiled object code, generated documentation,
33
+ and conversions to other media types.
34
+
35
+ "Work" shall mean the work of authorship, whether in Source or
36
+ Object form, made available under the License, as indicated by a
37
+ copyright notice that is included in or attached to the work
38
+ (an example is provided in the Appendix below).
39
+
40
+ "Derivative Works" shall mean any work, whether in Source or Object
41
+ form, that is based on (or derived from) the Work and for which the
42
+ editorial revisions, annotations, elaborations, or other modifications
43
+ represent, as a whole, an original work of authorship. For the purposes
44
+ of this License, Derivative Works shall not include works that remain
45
+ separable from, or merely link (or bind by name) to the interfaces of,
46
+ the Work and Derivative Works thereof.
47
+
48
+ "Contribution" shall mean any work of authorship, including
49
+ the original version of the Work and any modifications or additions
50
+ to that Work or Derivative Works thereof, that is intentionally
51
+ submitted to Licensor for inclusion in the Work by the copyright owner
52
+ or by an individual or Legal Entity authorized to submit on behalf of
53
+ the copyright owner. For the purposes of this definition, "submitted"
54
+ means any form of electronic, verbal, or written communication sent
55
+ to the Licensor or its representatives, including but not limited to
56
+ communication on electronic mailing lists, source code control systems,
57
+ and issue tracking systems that are managed by, or on behalf of, the
58
+ Licensor for the purpose of discussing and improving the Work, but
59
+ excluding communication that is conspicuously marked or otherwise
60
+ designated in writing by the copyright owner as "Not a Contribution."
61
+
62
+ "Contributor" shall mean Licensor and any individual or Legal Entity
63
+ on behalf of whom a Contribution has been received by Licensor and
64
+ subsequently incorporated within the Work.
65
+
66
+ 2. Grant of Copyright License. Subject to the terms and conditions of
67
+ this License, each Contributor hereby grants to You a perpetual,
68
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
69
+ copyright license to reproduce, prepare Derivative Works of,
70
+ publicly display, publicly perform, sublicense, and distribute the
71
+ Work and such Derivative Works in Source or Object form.
72
+
73
+ 3. Grant of Patent License. Subject to the terms and conditions of
74
+ this License, each Contributor hereby grants to You a perpetual,
75
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
76
+ (except as stated in this section) patent license to make, have made,
77
+ use, offer to sell, sell, import, and otherwise transfer the Work,
78
+ where such license applies only to those patent claims licensable
79
+ by such Contributor that are necessarily infringed by their
80
+ Contribution(s) alone or by combination of their Contribution(s)
81
+ with the Work to which such Contribution(s) was submitted. If You
82
+ institute patent litigation against any entity (including a
83
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
84
+ or a Contribution incorporated within the Work constitutes direct
85
+ or contributory patent infringement, then any patent licenses
86
+ granted to You under this License for that Work shall terminate
87
+ as of the date such litigation is filed.
88
+
89
+ 4. Redistribution. You may reproduce and distribute copies of the
90
+ Work or Derivative Works thereof in any medium, with or without
91
+ modifications, and in Source or Object form, provided that You
92
+ meet the following conditions:
93
+
94
+ (a) You must give any other recipients of the Work or
95
+ Derivative Works a copy of this License; and
96
+
97
+ (b) You must cause any modified files to carry prominent notices
98
+ stating that You changed the files; and
99
+
100
+ (c) You must retain, in the Source form of any Derivative Works
101
+ that You distribute, all copyright, patent, trademark, and
102
+ attribution notices from the Source form of the Work,
103
+ excluding those notices that do not pertain to any part of
104
+ the Derivative Works; and
105
+
106
+ (d) If the Work includes a "NOTICE" text file as part of its
107
+ distribution, then any Derivative Works that You distribute must
108
+ include a readable copy of the attribution notices contained
109
+ within such NOTICE file, excluding those notices that do not
110
+ pertain to any part of the Derivative Works, in at least one
111
+ of the following places: within a NOTICE text file distributed
112
+ as part of the Derivative Works; within the Source form or
113
+ documentation, if provided along with the Derivative Works; or,
114
+ within a display generated by the Derivative Works, if and
115
+ wherever such third-party notices normally appear. The contents
116
+ of the NOTICE file are for informational purposes only and
117
+ do not modify the License. You may add Your own attribution
118
+ notices within Derivative Works that You distribute, alongside
119
+ or as an addendum to the NOTICE text from the Work, provided
120
+ that such additional attribution notices cannot be construed
121
+ as modifying the License.
122
+
123
+ You may add Your own copyright statement to Your modifications and
124
+ may provide additional or different license terms and conditions
125
+ for use, reproduction, or distribution of Your modifications, or
126
+ for any such Derivative Works as a whole, provided Your use,
127
+ reproduction, and distribution of the Work otherwise complies with
128
+ the conditions stated in this License.
129
+
130
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
131
+ any Contribution intentionally submitted for inclusion in the Work
132
+ by You to the Licensor shall be under the terms and conditions of
133
+ this License, without any additional terms or conditions.
134
+ Notwithstanding the above, nothing herein shall supersede or modify
135
+ the terms of any separate license agreement you may have executed
136
+ with Licensor regarding such Contributions.
137
+
138
+ 6. Trademarks. This License does not grant permission to use the trade
139
+ names, trademarks, service marks, or product names of the Licensor,
140
+ except as required for reasonable and customary use in describing the
141
+ origin of the Work and reproducing the content of the NOTICE file.
142
+
143
+ 7. Disclaimer of Warranty. Unless required by applicable law or
144
+ agreed to in writing, Licensor provides the Work (and each
145
+ Contributor provides its Contributions) on an "AS IS" BASIS,
146
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
147
+ implied, including, without limitation, any warranties or conditions
148
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
149
+ PARTICULAR PURPOSE. You are solely responsible for determining the
150
+ appropriateness of using or redistributing the Work and assume any
151
+ risks associated with Your exercise of permissions under this License.
152
+
153
+ 8. Limitation of Liability. In no event and under no legal theory,
154
+ whether in tort (including negligence), contract, or otherwise,
155
+ unless required by applicable law (such as deliberate and grossly
156
+ negligent acts) or agreed to in writing, shall any Contributor be
157
+ liable to You for damages, including any direct, indirect, special,
158
+ incidental, or consequential damages of any character arising as a
159
+ result of this License or out of the use or inability to use the
160
+ Work (including but not limited to damages for loss of goodwill,
161
+ work stoppage, computer failure or malfunction, or any and all
162
+ other commercial damages or losses), even if such Contributor
163
+ has been advised of the possibility of such damages.
164
+
165
+ 9. Accepting Warranty or Additional Liability. While redistributing
166
+ the Work or Derivative Works thereof, You may choose to offer,
167
+ and charge a fee for, acceptance of support, warranty, indemnity,
168
+ or other liability obligations and/or rights consistent with this
169
+ License. However, in accepting such obligations, You may act only
170
+ on Your own behalf and on Your sole responsibility, not on behalf
171
+ of any other Contributor, and only if You agree to indemnify,
172
+ defend, and hold each Contributor harmless for any liability
173
+ incurred by, or claims asserted against, such Contributor by reason
174
+ of your accepting any such warranty or additional liability.
175
+
176
+ END OF TERMS AND CONDITIONS
177
+ APPENDIX: How to apply the Apache License to your work.
178
+
179
+ To apply the Apache License to your work, attach the following
180
+ boilerplate notice, with the fields enclosed by brackets "[]"
181
+ replaced with your own identifying information. (Don't include
182
+ the brackets!) The text should be enclosed in the appropriate
183
+ comment syntax for the file format. We also recommend that a
184
+ file or class name and description of purpose be included on the
185
+ same "printed page" as the copyright notice for easier
186
+ identification within third-party archives.
187
+
188
+ Copyright 2026 Alex Rodriguez (arodbuilds) https://alex-rodriguez.com
189
+
190
+ Licensed under the Apache License, Version 2.0 (the "License");
191
+ you may not use this file except in compliance with the License.
192
+ You may obtain a copy of the License at
193
+
194
+ http://www.apache.org/licenses/LICENSE-2.0
195
+
196
+ Unless required by applicable law or agreed to in writing, software
197
+ distributed under the License is distributed on an "AS IS" BASIS,
198
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
199
+ See the License for the specific language governing permissions and
200
+ limitations under the License.
package/NOTICE ADDED
@@ -0,0 +1,20 @@
1
+ homebridge-generac (Generac for Homebridge)
2
+ Copyright 2026 Alex Rodriguez (arodbuilds) https://alex-rodriguez.com
3
+
4
+ Licensed under the Apache License, Version 2.0. See LICENSE.
5
+
6
+ This product includes work from the following projects, in this order:
7
+
8
+ 1. ha-generac (https://github.com/binarydev/ha-generac)
9
+ The Auth0 and DPoP login flow in src/auth.ts is ported from the auth
10
+ module of ha-generac: the Auth0 flow by sslivins and the MFA handling by
11
+ pjordanandrsn. Licensed under the Apache License, Version 2.0.
12
+
13
+ 2. homebridge-mobilelink by Nicholas Penree
14
+ (https://www.npmjs.com/package/homebridge-mobilelink)
15
+ The original HomeKit bridge for Generac Mobile Link, of which this plugin
16
+ is the successor. Licensed under the Apache License, Version 2.0. No code
17
+ from homebridge-mobilelink is used in this project.
18
+
19
+ Generac and Mobile Link are trademarks of Generac Power Systems, Inc. This
20
+ project is not affiliated with Generac.
package/README.md ADDED
@@ -0,0 +1,179 @@
1
+ <img src="assets/generac-banner.png" alt="Generac for Homebridge: Your standby generator in HomeKit. Status, battery, run hours and alerts from Mobile Link." width="100%">
2
+
3
+ <!--
4
+ verified-by-homebridge: this plugin has not been through Homebridge verification yet.
5
+ Do not claim it. Once the plugin is verified, replace this comment with the badge:
6
+ [![verified-by-homebridge](https://badgen.net/badge/homebridge/verified/purple)](https://github.com/homebridge/homebridge/wiki/Verified-Plugins)
7
+ -->
8
+
9
+ [![npm version](https://img.shields.io/npm/v/homebridge-generac/beta)](https://www.npmjs.com/package/homebridge-generac)
10
+ [![npm downloads](https://img.shields.io/npm/dt/homebridge-generac)](https://www.npmjs.com/package/homebridge-generac)
11
+ [![License](https://img.shields.io/github/license/arodbuilds/homebridge-generac)](LICENSE)
12
+ [![Build and Lint](https://github.com/arodbuilds/homebridge-generac/actions/workflows/build.yml/badge.svg)](https://github.com/arodbuilds/homebridge-generac/actions/workflows/build.yml)
13
+
14
+ A [Homebridge](https://homebridge.io) plugin that shows the standby generators on your Generac Mobile Link account in the Home app. Each generator appears as a Running sensor, a Fault sensor, a Maintenance Due sensor, an Exercising sensor and a starting battery reading, so you can see at a glance whether the unit is ready, get a notification when it starts or reports a problem, and build automations around it. It is read only and never stores your Mobile Link password.
15
+
16
+ Not affiliated with or endorsed by Generac Power Systems, Inc. Generac and Mobile Link are its trademarks. Uses Generac's undocumented Mobile Link API, which can change without notice.
17
+
18
+ > **Status:** Beta. Please report what works and what does not in the [issue tracker](https://github.com/arodbuilds/homebridge-generac/issues).
19
+
20
+ ## Contents
21
+
22
+ - [Requirements](#requirements)
23
+ - [Install](#install)
24
+ - [Setup](#setup)
25
+ - [1. Connect your Mobile Link account](#1-connect-your-mobile-link-account)
26
+ - [2. Enter the code](#2-enter-the-code)
27
+ - [3. Your generators](#3-your-generators)
28
+ - [4. Settings](#4-settings)
29
+ - [What you get in HomeKit](#what-you-get-in-homekit)
30
+ - [How it works](#how-it-works)
31
+ - [Privacy and what is stored where](#privacy-and-what-is-stored-where)
32
+ - [Troubleshooting](#troubleshooting)
33
+ - [Development](#development)
34
+ - [Credits](#credits)
35
+ - [License](#license)
36
+
37
+ ## Requirements
38
+
39
+ - Homebridge 1.8 or 2.x, with the Homebridge UI for the settings page.
40
+ - Node 20 or later.
41
+ - A Generac Mobile Link account with at least one generator on it.
42
+ - If the account predates April 21, 2026, a password reset since then. Generac moved Mobile Link sign-in to a new system on that date and did not carry older passwords across, so an older password is rejected until it is reset in the Mobile Link app.
43
+
44
+ ## Install
45
+
46
+ Search for "Generac" under Plugins in the Homebridge UI and install the beta, or from a shell on the Homebridge host:
47
+
48
+ ```shell
49
+ npm i -g homebridge-generac@beta
50
+ ```
51
+
52
+ Then open the plugin's settings from the Plugins page. Everything in the setup below happens on that page. The host's Save button writes config.json and Homebridge restarts the plugin.
53
+
54
+ ## Setup
55
+
56
+ ### 1. Connect your Mobile Link account
57
+
58
+ Under Mobile Link account, click Connect and enter the email and password you use in the Mobile Link app, then click Sign in. The password is used once for that sign-in and is not stored anywhere.
59
+
60
+ ![The Mobile Link account card: Connected, the account email and when it was last checked](assets/screenshots/account-connected.png)
61
+
62
+ Once signed in, the card reads Checking until Homebridge picks up the new sign-in, which takes up to a minute and needs no restart, then Connected with the email and when the plugin last checked the account. Disconnect signs the plugin out again.
63
+
64
+ ### 2. Enter the code
65
+
66
+ ![The code step: Mobile Link texted a code to the phone on your account](assets/screenshots/connect-code.png)
67
+
68
+ Mobile Link sends a code by text message, authenticator app or email, depending on how your account is set up. Type it in and click Continue. A wrong code can be tried three times; after that, or after five minutes, cancel and sign in again. Accounts set up for push, voice or security-key sign-in cannot be completed by the plugin; switch the account to text message or an authenticator app in the Mobile Link app first.
69
+
70
+ ### 3. Your generators
71
+
72
+ ![A generator card: Ready to run, battery, engine hours, exercise time, last exercise and last seen](assets/screenshots/generator-ready.png)
73
+
74
+ Every generator on the account gets a card within a minute of connecting, with its Mobile Link status, the starting battery voltage, engine hours, the weekly exercise time, the last exercise Mobile Link recorded, and when the unit last reported in. Rename changes the name shown in the Home app; Save keeps it.
75
+
76
+ ![A generator card in Fault: Switch in OFF](assets/screenshots/generator-fault.png)
77
+
78
+ When something is wrong the card shows a Fault badge with the reasons Mobile Link gives: the control switch in OFF, active alarms or warnings, an alarm code, a warning status or a lost connection. A unit that has stopped reporting shows Not responding with the time it was last heard from.
79
+
80
+ ### 4. Settings
81
+
82
+ ![The Settings section with Advanced open](assets/screenshots/settings-advanced.png)
83
+
84
+ Settings holds one Advanced disclosure:
85
+
86
+ - Name: the plugin name in Homebridge logs.
87
+ - Poll interval while idle (minutes) and Poll interval while running or in fault (seconds): how often the plugin checks Mobile Link, see [How it works](#how-it-works).
88
+ - Low battery threshold (volts): the voltage at or below which the Battery service reports low. The default is 12.0 V; a healthy starting battery on charge reads 13.4 to 13.8 V.
89
+ - Treat Stopped as a fault: on by default. Stopped means the control switch is in OFF and the generator will not start during an outage.
90
+ - Treat a lost connection as a fault: off by default. Wi-Fi drops are common and the sensors already show Not responding.
91
+ - Attention needed sensor: an occupancy sensor that turns on while the plugin needs you to reconnect, for an automation that sends you a notification.
92
+ - Exercising sensor: on by default, see [What you get in HomeKit](#what-you-get-in-homekit).
93
+ - Exercise time: when the weekly exercise starts, prefilled from Mobile Link. Correct it if your unit starts at a different time.
94
+ - Exercise hold (minutes): how long the Exercising sensor stays open after an exercise is detected.
95
+ - Debug logging: verbose logging. The password is never logged, even with this on.
96
+ - Reset plugin to fresh install: signs out, removes every generator from the Home app on the next restart, and clears the settings.
97
+
98
+ ## What you get in HomeKit
99
+
100
+ One accessory per generator, named after the generator, with these services:
101
+
102
+ | Service | Kind | Open (or on) when |
103
+ | --- | --- | --- |
104
+ | Running | Contact sensor | The engine is running. |
105
+ | Fault | Contact sensor | Mobile Link reports a Warning status, an active alarm or warning, or an alarm code; the control switch is in OFF (Treat Stopped as a fault); or the unit lost its connection (Treat a lost connection as a fault, off by default). |
106
+ | Maintenance Due | Contact sensor | Generac flags service as due. |
107
+ | Exercising | Contact sensor | The weekly exercise is running, or Mobile Link reports one finished since the last check. |
108
+ | Battery | Battery service | Always present: the starting battery voltage as a level (11.8 V is 0 percent, 12.8 V is 100 percent) and the low battery flag at or below the threshold. |
109
+
110
+ Optionally, one Attention needed occupancy sensor for the plugin, on while the plugin cannot sign in.
111
+
112
+ **Why contact sensors and not a switch.** A switch in the Home app invites you to flip it, and this plugin cannot start, stop or exercise a generator; no command endpoint has been validated and the plugin stays read only. Contact sensors say exactly what they mean, show open and closed in the Home app, and are what HomeKit automations trigger on. In Automations, choose a sensor and pick what should happen when it opens and when it closes: turn on a light when Running opens, send a notification when Fault opens.
113
+
114
+ **The Exercising sensor.** Standby generators run themselves for a few minutes every week. The sensor opens when a check sees the unit exercising, and also retroactively: Mobile Link records the finished exercise with a timestamp, so an exercise the plugin slept through is still detected on the next check and opens the sensor then. The sensor stays open for the exercise hold time after the last detection. Use it to confirm the generator exercised this week, for example with an automation that notifies you if it has not opened by Saturday evening.
115
+
116
+ **Notifications.** For the Fault sensor, turn on notifications in the Home app and allow them as Critical Alerts, so a fault gets through Do Not Disturb and a Focus. That is the one notification worth having from this plugin.
117
+
118
+ Every sensor also reports Status Active, which is off while the unit is not responding or the plugin cannot reach Mobile Link, and Status Fault, which follows the Fault sensor. Names you give the sensors in the Home app are kept.
119
+
120
+ ## How it works
121
+
122
+ - **Polling.** While every generator is ready and quiet the plugin checks Mobile Link every 10 minutes (Poll interval while idle, minimum 2). While any generator is running, exercising or in fault it checks every 90 seconds (Poll interval while running or in fault, minimum 60). Mobile Link itself updates every few minutes and limits how often an account can be checked, so faster settings rarely help.
123
+ - **The exercise watch window.** Around the exercise time, from 2 minutes before it until 20 minutes after it, every day, the plugin checks at the faster interval so a live exercise is likely to be seen rather than only detected afterwards.
124
+ - **Backoff.** When a check fails, the plugin waits longer between tries, doubling from the fast interval up to 30 minutes with some jitter. After three failures in a row the sensors show Not responding until a check succeeds.
125
+ - **Sign-in.** The plugin signs in once, from the settings page, and keeps only a refresh token. Access tokens are refreshed shortly before they expire; the plugin never signs in again on its own and never needs the password after the first time.
126
+ - **After a password change.** Changing the Mobile Link password revokes the refresh token. The plugin then enters Reconnect needed: it logs once, marks the sensors as not responding, turns the Attention needed sensor on if enabled, and retries hourly in case access comes back. Click Reconnect on the settings page and sign in again; nothing else changes.
127
+ - **Configuration.** The settings page writes the platform block in config.json; the shape and every default are in [SPEC.md](SPEC.md) section 9 and in `config.schema.json`, for anyone who edits by hand.
128
+
129
+ ## Privacy and what is stored where
130
+
131
+ - The sign-in lives in `homebridge-generac/credentials.json` inside the Homebridge storage folder, with mode 600, readable only by the Homebridge user. It holds the account email, the refresh token and the key the token is bound to. It is never written to config.json, the log or the settings page.
132
+ - The password is never stored. It is used once to sign in from the settings page (or the `homebridge-generac login` command) and then forgotten.
133
+ - `homebridge-generac/state.json` holds what the settings page shows: the account state, each generator's last status, and when the plugin last checked. No tokens.
134
+ - With Debug logging on, every status change writes the raw Mobile Link payload for the generator to `homebridge-generac/captures/`, keeping the newest 10, so a real payload can be shared as a test fixture. Captures never contain tokens.
135
+ - The log never contains passwords, tokens, keys or one-time codes, at any log level.
136
+ - Nothing is sent anywhere but Generac. The plugin talks to Generac's sign-in service and the Mobile Link API and to nothing else.
137
+ - To remove everything, use Reset plugin to fresh install on the settings page, or delete the `homebridge-generac` folder in the Homebridge storage folder.
138
+
139
+ ## Troubleshooting
140
+
141
+ - **"Mobile Link rejected that password."** If you have not reset the password since April 21, 2026, reset it in the Mobile Link app, then try again. Older passwords were not carried across Generac's security update.
142
+ - **"Mobile Link doesn't recognize that email."** Use the email you sign in with in the Mobile Link app.
143
+ - **"Your account uses a sign-in method this plugin can't complete."** The account is set up for push, voice or security-key sign-in. In the Mobile Link app, switch to text message or an authenticator app, then try again.
144
+ - **"Couldn't reach Mobile Link."** The Homebridge host could not reach Generac's sign-in service. Try again in a minute.
145
+ - **The card stays on Checking.** Homebridge picks up a new sign-in within a minute without a restart. If the card has not changed after two minutes, restart Homebridge from Power Options.
146
+ - **Reconnect needed.** Mobile Link signed the plugin out. This happens after a password change or if Generac revokes access. Click Reconnect and sign in again; the generators and their sensors stay as they were. The Attention needed sensor, if enabled, is on until you do.
147
+ - **Not responding.** The generator has not reported to Mobile Link recently (a Wi-Fi drop is the usual cause), or the plugin has not been able to reach Mobile Link for three checks in a row. The card shows when the unit was last heard from; the sensors report Status Active off and keep their last values. It is not a fault unless Treat a lost connection as a fault is on.
148
+ - **No generators yet.** They appear within a minute of connecting. If the account holds only a propane tank monitor or a linked ecobee thermostat, the settings page says so under Generators: tank monitors are planned for a later release, and ecobee thermostats are already native HomeKit devices and are skipped.
149
+ - **The generator exercised but the sensor did not open.** The sensor also opens retroactively when Mobile Link records the finished exercise, usually within the next idle poll. Check Exercise time under Advanced; the plugin checks more often around that time every day.
150
+
151
+ ## Development
152
+
153
+ Node 20 or later. Clone the repository, then:
154
+
155
+ ```shell
156
+ npm ci
157
+ npm test
158
+ ```
159
+
160
+ `npm test` lints, builds and runs the node:test suites in `test/`. Tests never touch the network: `fetch` is mocked and the Mobile Link answers come from the fixtures under `test/fixtures/`. `npm run lint` and `npm run build` run the parts on their own.
161
+
162
+ To try a build on a Homebridge host, symlink the clone into the global plugin path, for example `ln -s ~/homebridge-generac "$(npm root -g)/homebridge-generac"`, then restart Homebridge. The settings page is TypeScript under `homebridge-ui/src/`, compiled to `homebridge-ui/public/js/` by the build; its server side is compiled from `src/ui/` and started by `homebridge-ui/server.js`. [SPEC.md](SPEC.md) is the source of truth for behaviour, naming, configuration and the page's copy.
163
+
164
+ The `homebridge-generac status` command prints the account and generator state from a terminal, and `homebridge-generac login` signs in without the settings page.
165
+
166
+ ## Credits
167
+
168
+ Generac's Mobile Link API is undocumented, and this plugin stands on work that mapped it before:
169
+
170
+ - [ha-generac](https://github.com/binarydev/ha-generac) (Apache-2.0): the Auth0 and DPoP sign-in sequence in `src/auth.ts` is ported from its auth module, the Auth0 flow by sslivins and the code-challenge handling by pjordanandrsn, as recorded in [NOTICE](NOTICE).
171
+ - [homebridge-mobilelink](https://www.npmjs.com/package/homebridge-mobilelink) by Nicholas Penree (Apache-2.0): the original HomeKit bridge for Mobile Link, of which this plugin is the successor.
172
+
173
+ Beyond the ported sign-in sequence, no code is shared with either project.
174
+
175
+ Built by Alex Rodriguez. If this plugin is useful to you, say hello at [alex-rodriguez.com](https://alex-rodriguez.com/?ref=generac#building).
176
+
177
+ ## License
178
+
179
+ Apache-2.0. Copyright 2026 Alex Rodriguez (arodbuilds).
package/SECURITY.md ADDED
@@ -0,0 +1,17 @@
1
+ # Security policy
2
+
3
+ ## Supported versions
4
+
5
+ Only the newest release receives security fixes. Older versions do not.
6
+
7
+ ## Reporting a vulnerability
8
+
9
+ Please report vulnerabilities privately through GitHub: open the Security tab of this repository and choose Report a vulnerability. Do not open a public issue for security problems.
10
+
11
+ You will get an acknowledgement within a few days, a fix or mitigation as soon as one is ready, and credit in the release notes if you want it.
12
+
13
+ ## Scope
14
+
15
+ In scope: anything that could expose the Mobile Link refresh token, the DPoP key or a password, or weaken the sign-in flow.
16
+
17
+ Out of scope: Generac changing its undocumented API or login page. Those break the plugin but are not vulnerabilities; report them as ordinary issues.
@@ -0,0 +1,133 @@
1
+ {
2
+ "pluginAlias": "Generac",
3
+ "pluginType": "platform",
4
+ "singular": true,
5
+ "headerDisplay": "Generac for Homebridge shows the standby generators on your Mobile Link account in the Home app. Each generator appears as a Running sensor, a Fault sensor, a Maintenance Due sensor and a starting battery reading. Propane models will also get a tank level later. Not affiliated with or endorsed by Generac Power Systems, Inc. Generac and Mobile Link are its trademarks. Uses Generac's undocumented Mobile Link API, which can change without notice.",
6
+ "schema": {
7
+ "type": "object",
8
+ "required": [
9
+ "name"
10
+ ],
11
+ "properties": {
12
+ "name": {
13
+ "title": "Name",
14
+ "type": "string",
15
+ "default": "Generac"
16
+ },
17
+ "pollIdleMinutes": {
18
+ "title": "Poll interval while idle (minutes)",
19
+ "type": "integer",
20
+ "default": 10,
21
+ "minimum": 2,
22
+ "description": "Mobile Link updates every few minutes and limits how often you can check. Faster than this rarely helps."
23
+ },
24
+ "pollActiveSeconds": {
25
+ "title": "Poll interval while running or in fault (seconds)",
26
+ "type": "integer",
27
+ "default": 90,
28
+ "minimum": 60,
29
+ "description": "Used while a generator is running, exercising, or reporting a problem."
30
+ },
31
+ "batteryLowVoltage": {
32
+ "title": "Low battery threshold (volts)",
33
+ "type": "number",
34
+ "default": 12.0,
35
+ "description": "A healthy starting battery on charge reads 13.4 to 13.8 V."
36
+ },
37
+ "faultOnStopped": {
38
+ "title": "Treat Stopped as a fault",
39
+ "type": "boolean",
40
+ "default": true,
41
+ "description": "Stopped means the control switch is in OFF and the generator won't start during an outage."
42
+ },
43
+ "faultOnDisconnected": {
44
+ "title": "Treat a lost connection as a fault",
45
+ "type": "boolean",
46
+ "default": false,
47
+ "description": "Off by default. Wi-Fi drops are common and the sensors already show Not responding."
48
+ },
49
+ "attentionSensor": {
50
+ "title": "Attention needed sensor",
51
+ "type": "boolean",
52
+ "default": false,
53
+ "description": "Adds an occupancy sensor to HomeKit that turns on when the plugin needs you to reconnect."
54
+ },
55
+ "exerciseSensor": {
56
+ "title": "Exercising sensor",
57
+ "type": "boolean",
58
+ "default": true,
59
+ "description": "Adds a sensor that opens while the weekly exercise runs, or when Mobile Link reports one finished. Use it to confirm the generator exercised this week."
60
+ },
61
+ "exerciseTime": {
62
+ "title": "Exercise time",
63
+ "type": "string",
64
+ "pattern": "^([01][0-9]|2[0-3]):[0-5][0-9]$",
65
+ "description": "When your generator's weekly exercise starts. Prefilled from Mobile Link; correct it if your unit starts at a different time. The plugin checks more often around this time every day."
66
+ },
67
+ "exerciseHoldMinutes": {
68
+ "title": "Exercise hold (minutes)",
69
+ "type": "integer",
70
+ "default": 5,
71
+ "minimum": 1,
72
+ "description": "How long the Exercising sensor stays open after an exercise is detected."
73
+ },
74
+ "debug": {
75
+ "title": "Debug logging",
76
+ "type": "boolean",
77
+ "default": false,
78
+ "description": "Verbose logging. Your password is never logged, even with this on."
79
+ },
80
+ "credentialsPath": {
81
+ "type": "string"
82
+ },
83
+ "generators": {
84
+ "type": "array",
85
+ "items": {
86
+ "type": "object",
87
+ "properties": {
88
+ "apparatusId": {
89
+ "type": "integer"
90
+ },
91
+ "name": {
92
+ "type": "string"
93
+ }
94
+ }
95
+ }
96
+ }
97
+ }
98
+ },
99
+ "layout": [
100
+ "name",
101
+ {
102
+ "key": "pollIdleMinutes",
103
+ "validationMessages": {
104
+ "minimum": "Minimum is 2 minutes."
105
+ }
106
+ },
107
+ {
108
+ "key": "pollActiveSeconds",
109
+ "validationMessages": {
110
+ "minimum": "Minimum is 60 seconds."
111
+ }
112
+ },
113
+ "batteryLowVoltage",
114
+ "faultOnStopped",
115
+ "faultOnDisconnected",
116
+ "attentionSensor",
117
+ "exerciseSensor",
118
+ {
119
+ "key": "exerciseTime",
120
+ "validationMessages": {
121
+ "pattern": "Enter a time as HH:MM, for example 10:00."
122
+ }
123
+ },
124
+ {
125
+ "key": "exerciseHoldMinutes",
126
+ "validationMessages": {
127
+ "minimum": "Minimum is 1 minute."
128
+ }
129
+ },
130
+ "debug"
131
+ ],
132
+ "customUi": true
133
+ }
@@ -0,0 +1,54 @@
1
+ import type { PlatformAccessory } from 'homebridge';
2
+ import { type GeneratorState } from './model.js';
3
+ import type { GeneracPlatform } from './platform.js';
4
+ /**
5
+ * One Generac generator as a HomeKit accessory.
6
+ *
7
+ * Deliberately not an Outlet or Switch: HomeKit would then read "off" while the
8
+ * unit sits healthy in Ready, and a fault would have nowhere to go but a thrown
9
+ * error (which the Home app renders as "No Response"). Contact sensors give
10
+ * three independently automatable, notifiable booleans, and StatusFault /
11
+ * StatusActive carry the health signals HomeKit already understands.
12
+ *
13
+ * Running contact OPEN while the engine is running
14
+ * Fault contact OPEN on warning / alarm / stopped (see FaultOptions)
15
+ * Maintenance Due contact OPEN when Generac flags service
16
+ * Exercising contact OPEN while an exercise is detected, live or retroactively (optional, SPEC section 7)
17
+ * Battery starting-battery voltage mapped to level + low-battery flag
18
+ */
19
+ export declare class GeneratorAccessory {
20
+ private readonly platform;
21
+ readonly accessory: PlatformAccessory;
22
+ private readonly running;
23
+ private readonly fault;
24
+ private readonly maintenance;
25
+ /** Present only while `exerciseSensor` is on; the platform drives it through `setExercising`. */
26
+ private readonly exercising;
27
+ private readonly battery;
28
+ private state;
29
+ private exerciseOpen;
30
+ private displayName;
31
+ constructor(platform: GeneracPlatform, accessory: PlatformAccessory, initial: GeneratorState, displayName: string);
32
+ private contact;
33
+ /**
34
+ * Apply a display name (the `generators[]` override or the Mobile Link name).
35
+ * Service names follow. ConfiguredName follows only while it still holds the
36
+ * name this plugin gave it, so a rename made in the Home app sticks.
37
+ * Returns true when anything changed, so the platform can persist the cache.
38
+ */
39
+ setDisplayName(name: string): boolean;
40
+ /** Every contact sensor with its label, the optional Exercising one included. */
41
+ private contacts;
42
+ private contactState;
43
+ private lowBattery;
44
+ /** Push a fresh state into HomeKit. Always updates; never gated on identity fields. */
45
+ update(next: GeneratorState): void;
46
+ /** The last state pushed to HomeKit. */
47
+ get current(): GeneratorState | null;
48
+ /** Opens or closes the Exercising sensor (SPEC section 7, service 6). A no-op without the sensor. */
49
+ setExercising(open: boolean): void;
50
+ /** Whether the Exercising sensor is open. */
51
+ get isExercising(): boolean;
52
+ /** Mark the accessory unreachable after repeated poll failures without changing its last state. */
53
+ markUnreachable(): void;
54
+ }