homebridge-config-ui-x 5.0.0-beta.26 → 5.0.0-beta.28

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 (180) hide show
  1. package/CHANGELOG.md +62 -17
  2. package/LICENSE +1 -1
  3. package/config.schema.json +38 -18
  4. package/dist/bin/hb-service.js +48 -47
  5. package/dist/bin/hb-service.js.map +1 -1
  6. package/dist/bin/platforms/win32.js +4 -2
  7. package/dist/bin/platforms/win32.js.map +1 -1
  8. package/dist/bin/standalone.js +1 -0
  9. package/dist/bin/standalone.js.map +1 -1
  10. package/dist/core/auth/auth.controller.d.ts +2 -0
  11. package/dist/core/auth/auth.service.js +10 -10
  12. package/dist/core/auth/auth.service.js.map +1 -1
  13. package/dist/core/config/config.service.d.ts +3 -0
  14. package/dist/core/config/config.service.js +1 -0
  15. package/dist/core/config/config.service.js.map +1 -1
  16. package/dist/core/config/config.startup.js +2 -2
  17. package/dist/core/config/config.startup.js.map +1 -1
  18. package/dist/core/homebridge-ipc/homebridge-ipc.service.js +3 -3
  19. package/dist/core/homebridge-ipc/homebridge-ipc.service.js.map +1 -1
  20. package/dist/index.js +8 -7
  21. package/dist/index.js.map +1 -1
  22. package/dist/main.js +1 -1
  23. package/dist/main.js.map +1 -1
  24. package/dist/modules/accessories/accessories.controller.js +4 -4
  25. package/dist/modules/accessories/accessories.controller.js.map +1 -1
  26. package/dist/modules/accessories/accessories.service.js +7 -6
  27. package/dist/modules/accessories/accessories.service.js.map +1 -1
  28. package/dist/modules/backup/backup.controller.js +7 -7
  29. package/dist/modules/backup/backup.controller.js.map +1 -1
  30. package/dist/modules/backup/backup.service.js +14 -14
  31. package/dist/modules/backup/backup.service.js.map +1 -1
  32. package/dist/modules/child-bridges/child-bridges.service.js +3 -3
  33. package/dist/modules/child-bridges/child-bridges.service.js.map +1 -1
  34. package/dist/modules/config-editor/config-editor.controller.js +7 -7
  35. package/dist/modules/config-editor/config-editor.controller.js.map +1 -1
  36. package/dist/modules/config-editor/config-editor.service.js +6 -6
  37. package/dist/modules/config-editor/config-editor.service.js.map +1 -1
  38. package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.js +11 -9
  39. package/dist/modules/custom-plugins/plugins-settings-ui/plugins-settings-ui.service.js.map +1 -1
  40. package/dist/modules/log/log.service.js +3 -3
  41. package/dist/modules/log/log.service.js.map +1 -1
  42. package/dist/modules/platform-tools/docker/docker.controller.js +3 -3
  43. package/dist/modules/platform-tools/docker/docker.controller.js.map +1 -1
  44. package/dist/modules/platform-tools/docker/docker.service.js +1 -1
  45. package/dist/modules/platform-tools/docker/docker.service.js.map +1 -1
  46. package/dist/modules/platform-tools/hb-service/hb-service.controller.js +1 -1
  47. package/dist/modules/platform-tools/hb-service/hb-service.controller.js.map +1 -1
  48. package/dist/modules/platform-tools/hb-service/hb-service.service.js +6 -6
  49. package/dist/modules/platform-tools/hb-service/hb-service.service.js.map +1 -1
  50. package/dist/modules/platform-tools/linux/linux.controller.js +2 -2
  51. package/dist/modules/platform-tools/linux/linux.controller.js.map +1 -1
  52. package/dist/modules/platform-tools/linux/linux.service.js +2 -2
  53. package/dist/modules/platform-tools/linux/linux.service.js.map +1 -1
  54. package/dist/modules/platform-tools/terminal/terminal.service.js +2 -2
  55. package/dist/modules/platform-tools/terminal/terminal.service.js.map +1 -1
  56. package/dist/modules/plugins/plugins.controller.js +4 -4
  57. package/dist/modules/plugins/plugins.controller.js.map +1 -1
  58. package/dist/modules/plugins/plugins.service.d.ts +1 -0
  59. package/dist/modules/plugins/plugins.service.js +61 -35
  60. package/dist/modules/plugins/plugins.service.js.map +1 -1
  61. package/dist/modules/server/server.controller.d.ts +19 -2
  62. package/dist/modules/server/server.controller.js +84 -18
  63. package/dist/modules/server/server.controller.js.map +1 -1
  64. package/dist/modules/server/server.service.d.ts +23 -6
  65. package/dist/modules/server/server.service.js +171 -56
  66. package/dist/modules/server/server.service.js.map +1 -1
  67. package/dist/modules/status/status.controller.js +3 -3
  68. package/dist/modules/status/status.controller.js.map +1 -1
  69. package/dist/modules/status/status.service.js +4 -4
  70. package/dist/modules/status/status.service.js.map +1 -1
  71. package/dist/modules/users/users.controller.js +1 -1
  72. package/dist/modules/users/users.controller.js.map +1 -1
  73. package/dist/self-check.js +6 -6
  74. package/dist/self-check.js.map +1 -1
  75. package/package.json +6 -6
  76. package/public/3rdpartylicenses.txt +25 -25
  77. package/public/chunk-2NFCPXAU.js +1 -0
  78. package/public/chunk-2NVHMNG5.js +1 -0
  79. package/public/{chunk-IPIDD3HC.js → chunk-2TOAVTFL.js} +1 -1
  80. package/public/chunk-3RXSS7UO.js +1 -0
  81. package/public/chunk-3Y2DGAWS.js +1 -0
  82. package/public/chunk-4JBDAK6H.js +1 -0
  83. package/public/{chunk-B753ANRE.js → chunk-4KPISZW4.js} +1 -1
  84. package/public/chunk-56KXI7R5.js +1 -0
  85. package/public/{chunk-U7623GKH.js → chunk-6EVHGB4P.js} +1 -1
  86. package/public/chunk-6YUXY73A.js +1 -0
  87. package/public/chunk-77AXHBP3.js +32 -0
  88. package/public/chunk-7EH23OME.js +1 -0
  89. package/public/{chunk-2OJNON6V.js → chunk-7EKKX4HT.js} +1 -1
  90. package/public/{chunk-KFOQEXZZ.js → chunk-7JAZ6D7D.js} +1 -1
  91. package/public/chunk-7O7AR4AM.js +6 -0
  92. package/public/{chunk-35ZEUC3N.js → chunk-A7RV5JVQ.js} +1 -1
  93. package/public/chunk-CKS4OOJF.js +1 -0
  94. package/public/{chunk-E4B7DNVE.js → chunk-DKV2C6JN.js} +4 -4
  95. package/public/chunk-DTBDAENF.js +1 -0
  96. package/public/{chunk-2VNUUJGQ.js → chunk-DY4CFYGO.js} +1 -1
  97. package/public/chunk-EEDUUZ6J.js +1 -0
  98. package/public/{chunk-T7Y7UGKU.js → chunk-EQHMVJZQ.js} +1 -1
  99. package/public/chunk-FCNYMCDH.js +1 -0
  100. package/public/{chunk-UIOHAIYB.js → chunk-FSQPG6HA.js} +1 -1
  101. package/public/chunk-GHT3N6F5.js +1 -0
  102. package/public/{chunk-P6NTJCU3.js → chunk-IAME6HRQ.js} +1 -1
  103. package/public/chunk-IQOW7DIL.js +1 -0
  104. package/public/{chunk-OC7KX4QS.js → chunk-IW6SKATB.js} +1 -1
  105. package/public/chunk-J3RKUN7D.js +1 -0
  106. package/public/chunk-JFJTXO7W.js +1 -0
  107. package/public/{chunk-V7MSRFYG.js → chunk-JH3TEYUN.js} +1 -1
  108. package/public/chunk-LEFLOPGL.js +1 -0
  109. package/public/chunk-LRA5QZUF.js +1 -0
  110. package/public/chunk-MOYAUTWQ.js +1 -0
  111. package/public/{chunk-NF2LWORY.js → chunk-NMDGMKTC.js} +1 -1
  112. package/public/chunk-NSSJTB6U.js +1 -0
  113. package/public/chunk-O2T3H55F.js +20 -0
  114. package/public/chunk-OBQHFSUL.js +1 -0
  115. package/public/{chunk-EMNTAE5G.js → chunk-OGMGPP6F.js} +1 -1
  116. package/public/{chunk-BBIB7OOE.js → chunk-OQ6Q5ACW.js} +1 -1
  117. package/public/chunk-P6QZTG6X.js +1 -0
  118. package/public/{chunk-4HJ4QRHU.js → chunk-PALAGBX5.js} +1 -1
  119. package/public/chunk-Q23I6M54.js +1 -0
  120. package/public/{chunk-B46KABOE.js → chunk-QOCGTZFM.js} +1 -1
  121. package/public/chunk-SHOUY6NT.js +1 -0
  122. package/public/chunk-SJK6QB4P.js +1 -0
  123. package/public/{chunk-TQEO2WY5.js → chunk-SK6P7SRA.js} +1 -1
  124. package/public/chunk-SPZTKLLI.js +1 -0
  125. package/public/chunk-T7V32PLS.js +1 -0
  126. package/public/chunk-UAYX5MW3.js +1 -0
  127. package/public/{chunk-OJ45QGCH.js → chunk-VRKZRZ3K.js} +1 -1
  128. package/public/chunk-WB62D2DL.js +1 -0
  129. package/public/chunk-WQOH45IS.js +1 -0
  130. package/public/{chunk-JXNMTC4S.js → chunk-WZBWQOWX.js} +1 -1
  131. package/public/chunk-X5YRTZFZ.js +1 -0
  132. package/public/chunk-Y3G4O36G.js +1 -0
  133. package/public/{chunk-N4GLNFOT.js → chunk-Y3M46CD2.js} +1 -1
  134. package/public/{chunk-H3RI2X3J.js → chunk-Y7ZULLZS.js} +2 -2
  135. package/public/{chunk-OQEKVBVC.js → chunk-YSFKEXNC.js} +1 -1
  136. package/public/chunk-YUK7YC5O.js +1 -0
  137. package/public/{chunk-L2733SOJ.js → chunk-YWEEDHFM.js} +1 -1
  138. package/public/chunk-ZNWGO4JM.js +1 -0
  139. package/public/chunk-ZYVX5TJ4.js +1 -0
  140. package/public/index.html +2 -2
  141. package/public/main-ZKH4BRWO.js +1 -0
  142. package/public/{styles-LM2DJG4C.css → styles-LO2KB5IY.css} +1 -1
  143. package/public/chunk-2N2FIQZE.js +0 -1
  144. package/public/chunk-35GQ3F7V.js +0 -1
  145. package/public/chunk-36GSB6KM.js +0 -1
  146. package/public/chunk-3G2INPN4.js +0 -6
  147. package/public/chunk-3VNR3PA7.js +0 -1
  148. package/public/chunk-56Z7AYJ5.js +0 -1
  149. package/public/chunk-6J7CM2LU.js +0 -1
  150. package/public/chunk-7ZMNAUG3.js +0 -1
  151. package/public/chunk-AHQEC5XD.js +0 -1
  152. package/public/chunk-BO2Q6JEC.js +0 -1
  153. package/public/chunk-BVU3XBKZ.js +0 -1
  154. package/public/chunk-D73G6FHU.js +0 -1
  155. package/public/chunk-EFJQDZWX.js +0 -1
  156. package/public/chunk-F6IIUWOY.js +0 -1
  157. package/public/chunk-FAWZXXFU.js +0 -1
  158. package/public/chunk-H4TSN4GX.js +0 -20
  159. package/public/chunk-J5YJPEOP.js +0 -1
  160. package/public/chunk-MA2NAED5.js +0 -1
  161. package/public/chunk-NEHFSTZG.js +0 -1
  162. package/public/chunk-OD3LAPR5.js +0 -1
  163. package/public/chunk-ONUDLIEE.js +0 -1
  164. package/public/chunk-QXIVYED3.js +0 -1
  165. package/public/chunk-SNISLJD4.js +0 -1
  166. package/public/chunk-SRN6APE2.js +0 -1
  167. package/public/chunk-SWSVESSY.js +0 -1
  168. package/public/chunk-T5M25JEJ.js +0 -1
  169. package/public/chunk-TILEZFVJ.js +0 -1
  170. package/public/chunk-TLJ5IZVT.js +0 -32
  171. package/public/chunk-UPOTR3TI.js +0 -1
  172. package/public/chunk-VM7WUBIT.js +0 -1
  173. package/public/chunk-W5T6GB3H.js +0 -1
  174. package/public/chunk-WRDAYUQ7.js +0 -1
  175. package/public/chunk-XLT7LNOY.js +0 -1
  176. package/public/chunk-XROHACBE.js +0 -1
  177. package/public/chunk-XSAIQ7YY.js +0 -1
  178. package/public/chunk-YIXOCUUM.js +0 -1
  179. package/public/chunk-YMEQWVLZ.js +0 -1
  180. package/public/main-HHNIKZ37.js +0 -1
package/CHANGELOG.md CHANGED
@@ -6,7 +6,7 @@ All notable changes to `homebridge-config-ui-x` will be documented in this file.
6
6
 
7
7
  ### ⚠️ Breaking Changes
8
8
 
9
- - This version of the Homebridge UI will drop support for:
9
+ - This version of the Homebridge UI drops support for:
10
10
  - Node.js `v16` and earlier, so please update to `v18` or `v20` or `v22` - [more info on updating](https://github.com/homebridge/homebridge/wiki/How-To-Update-Node.js)
11
11
  - Raspberry Pi devices running on the `armv6` architecture (like the Pi 1 and Pi Zero) - please update your hardware
12
12
  - Instances using `pnpm` as the package manager - consider updating your Homebridge instance to use npm instead - [more info on updating](https://github.com/homebridge/homebridge-apt-pkg/blob/latest/README.md#using-apt)
@@ -23,18 +23,6 @@ This version of Homebridge UI adds validation to plugin config screens. This doe
23
23
 
24
24
  If you have a plugin which can be configured multiple times, then an icon will be shown on each configuration block.
25
25
 
26
- For custom UIs developed using the `@homebridge/plugin-ui-utils` package, the `Save` button will be enabled at all times by default.
27
- In `@homebridge/plugin-ui-utils@v2.0.0`, two new methods have been added which allow you to disable and enable the `Save` button:
28
-
29
- - `homebridge.disableSaveButton()`
30
- - `homebridge.enableSaveButton()`
31
-
32
- When the button is enabled, the validation icon will be visible showing the status of the configuration. When the button is disabled, the validation icon will be hidden.
33
- To maintain compatibility with older versions of the Homebridge UI, it is recommended to check if the method exists before calling it:
34
-
35
- - `homebridge.disableSaveButton?.()`
36
- - `homebridge.enableSaveButton?.()`
37
-
38
26
  Plugin developers:
39
27
 
40
28
  - Please do not rely on this validation and assume that a user's configuration will be valid
@@ -45,7 +33,6 @@ Plugin developers:
45
33
  ### UI Changes
46
34
 
47
35
  - updates to the `fi.json` language file (#2253) (@l1500s)
48
- - implement and allow switching to scoped plugins
49
36
  - add plugin config validation functionality
50
37
  - refactor status and child bridge widgets
51
38
  - update default dashboard layout
@@ -55,7 +42,6 @@ Plugin developers:
55
42
  - retire use of `pnpm` and code references
56
43
  - bump the default node version from 20 to 22
57
44
  - make terminal enabled by default on new macOS hb-service installs
58
- - update node pty beta `v0.12.0-beta`
59
45
  - improvements to GH actions and build processes (@NorthernMan54)
60
46
 
61
47
  ### Homebridge Dependencies
@@ -64,9 +50,68 @@ Plugin developers:
64
50
  - `@homebridge/node-pty-prebuilt-multiarch` @ `v0.12.0-beta`
65
51
  - `@homebridge/plugin-ui-utils` @ `v2.0.0`
66
52
 
53
+ ## v4.68.0 (2025-01-06)
54
+
55
+ Happy 2025 to all our users! 🎉
56
+
57
+ ### UI Changes
58
+
59
+ - improved messaging on plugin child bridge modal
60
+ - further improvements to plugin search
61
+ - implement and allow switching to scoped plugins
62
+ - merge plugin info and verified modals
63
+ - condensing plugin card into title + three lines of description
64
+ - consistent formatting of child bridge names across the ui
65
+ - general improvements across the ui
66
+ - status page:
67
+ - individual widget setting form design made consistent with other forms
68
+ - added pairing status to qr code widget
69
+ - plugins page:
70
+ - visual improvements to plugin child bridge settings modal
71
+ - allow plugins to disable/enable the save button in custom uis (see below section)
72
+ - accessories page:
73
+ - changed accessory spanner icon to info icon (more descriptive)
74
+ - accessory info modal redesigned and provides more info where possible like the accessory UUID (including a link to remove from the cache)
75
+ - added support modal with some info about rooms and accessories (visible on desktop)
76
+ - json config page:
77
+ - redesigned restore modal to be more consistent with other modals
78
+ - settings page:
79
+ - chevron icons replaced with arrow-right icons
80
+ - removed restore modal from settings page and is accessible from the backup modal
81
+ - backup modal redesigned to be more consistent with other modals
82
+ - added new display -> menu mode setting which allows keeping the side menu from expanding out on desktop
83
+ - redesigned and improved accessories and bridges sections and modals
84
+ - users page:
85
+ - add user and edit user modals redesigned to be more consistent with other modals
86
+ - user card updated with icon buttons for edit/delete rather than text buttons
87
+
88
+ ### Plugin Custom UI Changes
89
+
90
+ The UI has recently been updated with `@homebridge/plugin-ui-utils` @ `v2.0.0`, which includes a new feature to allow plugin developers to dynamically enable and disable the `Save` button in the custom UI modal.
91
+ Two new methods have been added for this purpose:
92
+
93
+ - `homebridge.disableSaveButton()`
94
+ - `homebridge.enableSaveButton()`
95
+
96
+ Developers: to maintain compatibility with older versions of the Homebridge UI, it is recommended to check if the methods exist before calling them in your custom UIs:
97
+
98
+ - `homebridge.disableSaveButton?.()`
99
+ - `homebridge.enableSaveButton?.()`
100
+
101
+ ### Other Changes
102
+
103
+ - auto-fix ui theme setting property if existing value is not valid
104
+ - do not allow `armv6l` users to update to UI `v5`
105
+
106
+ ### Homebridge Dependencies
107
+
108
+ - `@homebridge/hap-client` @ `v2.0.5`
109
+ - `@homebridge/node-pty-prebuilt-multiarch` @ `v0.11.14`
110
+ - `@homebridge/plugin-ui-utils` @ `v2.0.0`
111
+
67
112
  ## v4.67.0 (2024-12-28)
68
113
 
69
- ## UI Changes
114
+ ### UI Changes
70
115
 
71
116
  - add explanation of deleting child bridges when un-toggling
72
117
  - add filtering to search to improve results (#2286) (@justjam2013) (fixes [#2266](https://github.com/homebridge/homebridge-config-ui-x/issues/2266))
@@ -80,7 +125,7 @@ Plugin developers:
80
125
  - improve and finish up previous angular migration
81
126
  - update `hap-client` + `plugin-ui-utils` hb dependencies
82
127
  - update dependencies
83
- - import lint sorting of imports
128
+ - improve lint sorting of imports
84
129
 
85
130
  ### Homebridge Dependencies
86
131
 
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023-2024 Homebridge
3
+ Copyright (c) 2023-2025 Homebridge
4
4
  Copyright (c) 2017-2023 oznu <dev@oz.nu>
5
5
  Copyright (c) 2017 Michael Kellsy
6
6
 
@@ -156,6 +156,26 @@
156
156
  }
157
157
  ]
158
158
  },
159
+ "menuMode": {
160
+ "title": "Menu Mode",
161
+ "description": "Modes for the UI side menu.",
162
+ "type": "string",
163
+ "default": "default",
164
+ "oneOf": [
165
+ {
166
+ "title": "Default",
167
+ "enum": [
168
+ "default"
169
+ ]
170
+ },
171
+ {
172
+ "title": "Freeze",
173
+ "enum": [
174
+ "freeze"
175
+ ]
176
+ }
177
+ ]
178
+ },
159
179
  "restart": {
160
180
  "title": "Custom Restart Command",
161
181
  "type": "string",
@@ -163,7 +183,7 @@
163
183
  "placeholder": "eg. sudo systemctl restart homebridge"
164
184
  },
165
185
  "temp": {
166
- "title": "Path to OS Temp File",
186
+ "title": "OS Temp File Path",
167
187
  "type": "string",
168
188
  "placeholder": "eg. /sys/class/thermal/thermal_zone0/temp",
169
189
  "description": "If you are running Homebridge on a Raspberry Pi, you can enter the path to the OS temp file here. This will display the current temperature on the Homebridge status page."
@@ -373,7 +393,7 @@
373
393
  ]
374
394
  },
375
395
  "loginWallpaper": {
376
- "title": "Path to Login Wallpaper Image File",
396
+ "title": "Login Wallpaper Path",
377
397
  "description": "The full path to the .jpg file.",
378
398
  "type": "string",
379
399
  "placeholder": "eg. /home/pi/mywallpaper.jpg"
@@ -390,7 +410,7 @@
390
410
  "placeholder": "eg. /usr/local/lib/node_modules/homebridge"
391
411
  },
392
412
  "noFork": {
393
- "title": "Do not run the Config UI web server in a separate process/thread",
413
+ "title": "Do not run the UI server in a separate process/thread",
394
414
  "type": "boolean",
395
415
  "description": "If you are running Homebridge in a container, you may need to enable this option."
396
416
  },
@@ -398,11 +418,11 @@
398
418
  "title": "Host IP Address",
399
419
  "type": "string",
400
420
  "pattern": "^[^{}/ :\\\\]+(?::\\d+)?$",
401
- "description": "The host ip address to listen on. In most cases this will be '::' or '0.0.0.0'",
421
+ "description": "The host IP address to listen on. In most cases this will be '::' or '0.0.0.0'.",
402
422
  "placeholder": "eg. 0.0.0.0"
403
423
  },
404
424
  "debug": {
405
- "title": " Enable / disable debug level logging",
425
+ "title": "Enable Debug Logging",
406
426
  "type": "boolean",
407
427
  "description": "If enabled, the Homebridge UI will log debug level messages to the console."
408
428
  },
@@ -412,7 +432,7 @@
412
432
  "description": "If you are running Homebridge in a container, you may need to enable this option."
413
433
  },
414
434
  "sessionTimeout": {
415
- "title": "Session Timeout (in seconds)",
435
+ "title": "Session Timeout (Seconds)",
416
436
  "type": "integer",
417
437
  "placeholder": 28800,
418
438
  "minimum": 600,
@@ -492,14 +512,14 @@
492
512
  },
493
513
  "tail": {
494
514
  "type": "string",
495
- "description": "Depreciated",
515
+ "description": "Depreciated.",
496
516
  "condition": {
497
517
  "functionBody": "return (model.log && (model.log.method==='custom' || model.log.method==='systemd' || model.log.method==='file'))"
498
518
  }
499
519
  },
500
520
  "systemd": {
501
521
  "type": "string",
502
- "description": "Depreciated",
522
+ "description": "Depreciated.",
503
523
  "condition": {
504
524
  "functionBody": "return (model.log && (model.log.method==='custom' || model.log.method==='systemd' || model.log.method==='file'))"
505
525
  }
@@ -525,19 +545,19 @@
525
545
  "description": "The SSL settings for the Homebridge UI.",
526
546
  "properties": {
527
547
  "key": {
528
- "title": "Path To Private Key",
548
+ "title": "Private Key Path",
529
549
  "type": "string",
530
550
  "description": "The full path to the private key file.",
531
551
  "placeholder": "eg. /Users/homebridge/.homebridge/certs/server.key"
532
552
  },
533
553
  "cert": {
534
- "title": "Path To Certificate",
554
+ "title": "Certificate Path",
535
555
  "type": "string",
536
556
  "description": "The full path to the certificate file.",
537
557
  "placeholder": "eg. /Users/homebridge/.homebridge/certs/server.crt"
538
558
  },
539
559
  "pfx": {
540
- "title": "Path To PKCS#12 Certificate",
560
+ "title": "PKCS#12 Certificate Path",
541
561
  "type": "string",
542
562
  "description": "The full path to the PKCS#12 certificate file.",
543
563
  "placeholder": "eg. /Users/homebridge/.homebridge/certs/server.pfx"
@@ -556,14 +576,14 @@
556
576
  "description": "The accessory control settings for the Homebridge UI.",
557
577
  "properties": {
558
578
  "debug": {
559
- "title": " Enable / disable debug level logging for accessory control via the web UI",
579
+ "title": "Enable Accessory Control Debug Logging",
560
580
  "type": "boolean",
561
581
  "description": "If enabled, the Homebridge UI will log debug level messages to the console."
562
582
  },
563
583
  "instanceBlacklist": {
564
- "title": "Blacklisted Instances",
584
+ "title": "Blacklisted Bridges/Instances",
565
585
  "type": "array",
566
- "description": "A list of instances that should not be controlled via the web UI.",
586
+ "description": "A list of instances (or bridge usernames) that should not be controlled via the web UI.",
567
587
  "placeholder": "eg. 00:00:00:00:00:00",
568
588
  "items": {
569
589
  "title": "Instance Username",
@@ -600,8 +620,8 @@
600
620
  "description": "When running behind a reverse proxy you may need to enter the hostname you use to access the UI."
601
621
  },
602
622
  "scheduledBackupPath": {
603
- "title": "Scheduled backup destination path",
604
- "description": "The full path to where the service should save daily scheduled backups archives",
623
+ "title": "Scheduled Backup Destination",
624
+ "description": "The full path to where the service should save daily scheduled backups archives.",
605
625
  "type": "string",
606
626
  "placeholder": "eg. /home/pi/homebridge-backups",
607
627
  "condition": {
@@ -611,12 +631,12 @@
611
631
  "scheduledBackupDisable": {
612
632
  "title": "Disable Scheduled Backups",
613
633
  "type": "boolean",
614
- "description": "When enabled, the Homebridge UI will not create daily scheduled backups"
634
+ "description": "When enabled, the Homebridge UI will not create daily scheduled backups."
615
635
  },
616
636
  "disableServerMetricsMonitoring": {
617
637
  "title": "Disable Server Metrics Monitoring",
618
638
  "type": "boolean",
619
- "description": "When enabled, the Homebridge UI will not collect or report cpu / memory stats"
639
+ "description": "When enabled, the Homebridge UI will not collect or report CPU or memory stats."
620
640
  }
621
641
  }
622
642
  },
@@ -90,6 +90,7 @@ class HomebridgeServiceHelper {
90
90
  }
91
91
  commander_1.program
92
92
  .allowUnknownOption()
93
+ .allowExcessArguments()
93
94
  .storeOptionsAsProperties(true)
94
95
  .arguments('[install|uninstall|start|stop|restart|rebuild|run|logs|view|add|remove]')
95
96
  .option('-P, --plugin-path <path>', '', (p) => {
@@ -122,12 +123,12 @@ class HomebridgeServiceHelper {
122
123
  switch (this.action) {
123
124
  case 'install': {
124
125
  this.nvmCheck();
125
- this.logger(`Installing ${this.serviceName} Service`);
126
+ this.logger(`Installing ${this.serviceName} service...`);
126
127
  this.installer.install();
127
128
  break;
128
129
  }
129
130
  case 'uninstall': {
130
- this.logger(`Removing ${this.serviceName} Service`);
131
+ this.logger(`Removing ${this.serviceName} service...`);
131
132
  this.installer.uninstall();
132
133
  break;
133
134
  }
@@ -140,7 +141,7 @@ class HomebridgeServiceHelper {
140
141
  break;
141
142
  }
142
143
  case 'restart': {
143
- this.logger(`Restarting ${this.serviceName} Service`);
144
+ this.logger(`Restarting ${this.serviceName} service...`);
144
145
  this.installer.restart();
145
146
  break;
146
147
  }
@@ -222,7 +223,7 @@ class HomebridgeServiceHelper {
222
223
  }
223
224
  setEnv() {
224
225
  if (!this.serviceName.match(/^[a-z0-9-]+$/i)) {
225
- this.logger('ERROR: Service name must not contain spaces or special characters', 'fail');
226
+ this.logger('Service name must not contain spaces or special characters.', 'fail');
226
227
  node_process_1.default.exit(1);
227
228
  }
228
229
  if (!this.storagePath) {
@@ -257,7 +258,7 @@ class HomebridgeServiceHelper {
257
258
  this.log = node_process_1.default.stdout;
258
259
  return;
259
260
  }
260
- this.logger(`Logging to ${this.logPath}`);
261
+ this.logger(`Logging to ${this.logPath}.`);
261
262
  this.log = (0, fs_extra_1.createWriteStream)(this.logPath, { flags: 'a' });
262
263
  node_process_1.default.stdout.write = node_process_1.default.stderr.write = this.log.write.bind(this.log);
263
264
  }
@@ -289,7 +290,7 @@ class HomebridgeServiceHelper {
289
290
  await (0, fs_extra_1.close)(logFileHandle);
290
291
  }
291
292
  catch (e) {
292
- this.logger(`Failed to truncate log file: ${e.message}`, 'fail');
293
+ this.logger(`Failed to truncate log file: ${e.message}.`, 'fail');
293
294
  }
294
295
  }
295
296
  async launch() {
@@ -298,8 +299,8 @@ class HomebridgeServiceHelper {
298
299
  this.logger('Use the --allow-root flag to force the service to run as the root user.');
299
300
  node_process_1.default.exit(0);
300
301
  }
301
- this.logger(`Homebridge Storage Path: ${this.storagePath}`);
302
- this.logger(`Homebridge Config Path: ${node_process_1.default.env.UIX_CONFIG_PATH}`);
302
+ this.logger(`Homebridge storage path: ${this.storagePath}.`);
303
+ this.logger(`Homebridge config path: ${node_process_1.default.env.UIX_CONFIG_PATH}.`);
303
304
  setInterval(() => {
304
305
  this.truncateLog();
305
306
  }, (1000 * 60 * 60) * 2);
@@ -307,13 +308,13 @@ class HomebridgeServiceHelper {
307
308
  await this.storagePathCheck();
308
309
  await this.startLog();
309
310
  await this.configCheck();
310
- this.logger(`OS: ${(0, node_os_1.type)()} ${(0, node_os_1.release)()} ${(0, node_os_1.arch)()}`);
311
- this.logger(`Node.js ${node_process_1.default.version} ${node_process_1.default.execPath}`);
311
+ this.logger(`OS: ${(0, node_os_1.type)()} ${(0, node_os_1.release)()} ${(0, node_os_1.arch)()}.`);
312
+ this.logger(`Node.js ${node_process_1.default.version} ${node_process_1.default.execPath}.`);
312
313
  this.homebridgeBinary = await this.findHomebridgePath();
313
- this.logger(`Homebridge Path: ${this.homebridgeBinary}`);
314
+ this.logger(`Homebridge path: ${this.homebridgeBinary}.`);
314
315
  await this.loadHomebridgeStartupOptions();
315
316
  this.uiBinary = (0, node_path_1.resolve)(node_process_1.default.env.UIX_BASE_PATH, 'dist', 'bin', 'standalone.js');
316
- this.logger(`UI Path: ${this.uiBinary}`);
317
+ this.logger(`UI path: ${this.uiBinary}.`);
317
318
  }
318
319
  catch (e) {
319
320
  this.logger(e.message);
@@ -325,7 +326,7 @@ class HomebridgeServiceHelper {
325
326
  this.ipcService.setHomebridgeVersion(this.homebridgePackage.version);
326
327
  }
327
328
  if ((0, node_os_1.cpus)().length === 1 && (0, node_os_1.arch)() === 'arm') {
328
- this.logger('Delaying Homebridge startup by 20 seconds on low powered server');
329
+ this.logger('Delaying Homebridge startup by 20 seconds on low powered server.');
329
330
  setTimeout(() => {
330
331
  this.runHomebridge();
331
332
  }, 20000);
@@ -354,7 +355,7 @@ class HomebridgeServiceHelper {
354
355
  }
355
356
  runHomebridge() {
356
357
  if (!this.homebridgeBinary || !(0, fs_extra_1.pathExistsSync)(this.homebridgeBinary)) {
357
- this.logger('Could not find Homebridge. Make sure you have installed homebridge using the -g flag then restart.', 'fail');
358
+ this.logger('Could not find Homebridge. Make sure you have installed Homebridge using the -g flag then restart.', 'fail');
358
359
  this.logger('npm install -g --unsafe-perm homebridge', 'fail');
359
360
  return;
360
361
  }
@@ -364,10 +365,10 @@ class HomebridgeServiceHelper {
364
365
  }
365
366
  }
366
367
  if (this.homebridgeOpts.length) {
367
- this.logger(`Starting Homebridge with extra flags: ${this.homebridgeOpts.join(' ')}`);
368
+ this.logger(`Starting Homebridge with extra flags: ${this.homebridgeOpts.join(' ')}.`);
368
369
  }
369
370
  if (Object.keys(this.homebridgeCustomEnv).length) {
370
- this.logger(`Starting Homebridge with custom env: ${JSON.stringify(this.homebridgeCustomEnv)}`);
371
+ this.logger(`Starting Homebridge with custom env: ${JSON.stringify(this.homebridgeCustomEnv)}.`);
371
372
  }
372
373
  const env = {};
373
374
  Object.assign(env, node_process_1.default.env);
@@ -394,7 +395,7 @@ class HomebridgeServiceHelper {
394
395
  this.ipcService.setHomebridgeProcess(this.homebridge);
395
396
  this.ipcService.setHomebridgeVersion(this.homebridgePackage.version);
396
397
  }
397
- this.logger(`Started Homebridge v${this.homebridgePackage.version} with PID: ${this.homebridge.pid}`);
398
+ this.logger(`Started Homebridge v${this.homebridgePackage.version} with PID: ${this.homebridge.pid}.`);
398
399
  this.homebridge.stdout.on('data', (data) => {
399
400
  this.log.write(data);
400
401
  });
@@ -406,7 +407,7 @@ class HomebridgeServiceHelper {
406
407
  });
407
408
  }
408
409
  handleHomebridgeClose(code, signal) {
409
- this.logger(`Homebridge Process Ended. Code: ${code}, Signal: ${signal}`);
410
+ this.logger(`Homebridge process ended. Code: ${code}, signal: ${signal}.`);
410
411
  this.checkForStaleHomebridgeProcess();
411
412
  this.refreshHomebridgePackage();
412
413
  setTimeout(() => {
@@ -421,7 +422,7 @@ class HomebridgeServiceHelper {
421
422
  this.ipcService = ui.get(main.HomebridgeIpcService);
422
423
  }
423
424
  catch (e) {
424
- this.logger('ERROR: The user interface threw an unhandled error');
425
+ this.logger('The user interface threw an unhandled error.');
425
426
  console.error(e);
426
427
  setTimeout(() => {
427
428
  node_process_1.default.exit(1);
@@ -478,10 +479,10 @@ class HomebridgeServiceHelper {
478
479
  this.homebridgePackage = await (0, fs_extra_1.readJson)((0, node_path_1.join)(this.homebridgeModulePath, 'package.json'));
479
480
  }
480
481
  else {
481
- this.logger(`Homebridge not longer found at ${this.homebridgeModulePath}`, 'fail');
482
+ this.logger(`Homebridge not longer found at ${this.homebridgeModulePath}.`, 'fail');
482
483
  this.homebridgeModulePath = undefined;
483
484
  this.homebridgeBinary = await this.findHomebridgePath();
484
- this.logger(`Found New Homebridge Path: ${this.homebridgeBinary}`);
485
+ this.logger(`Found new Homebridge path: ${this.homebridgeBinary}.`);
485
486
  }
486
487
  }
487
488
  catch (e) {
@@ -490,7 +491,7 @@ class HomebridgeServiceHelper {
490
491
  }
491
492
  nodeVersionCheck() {
492
493
  if (Number.parseInt(node_process_1.default.versions.modules, 10) < 64) {
493
- this.logger(`ERROR: Node.js v10.13.0 or greater is required. Current: ${node_process_1.default.version}.`, 'fail');
494
+ this.logger(`Node.js v10.13.0 or greater is required, current: ${node_process_1.default.version}.`, 'fail');
494
495
  node_process_1.default.exit(1);
495
496
  }
496
497
  }
@@ -514,24 +515,24 @@ class HomebridgeServiceHelper {
514
515
  console.log(`* http://[${defaultInterface.ip6}]:${this.uiPort}`);
515
516
  }
516
517
  console.log('');
517
- this.logger('Homebridge Setup Complete', 'succeed');
518
+ this.logger('Homebridge setup complete.', 'succeed');
518
519
  }
519
520
  async portCheck() {
520
521
  const inUse = await (0, tcp_port_used_1.check)(this.uiPort);
521
522
  if (inUse) {
522
- this.logger(`ERROR: Port ${this.uiPort} is already in use by another process on this host.`, 'fail');
523
- this.logger('You can specify another port using the --port flag, eg.', 'fail');
524
- this.logger(`EXAMPLE: hb-service ${this.action} --port 8581`, 'fail');
523
+ this.logger(`Port ${this.uiPort} is already in use by another process on this host.`, 'fail');
524
+ this.logger('You can specify another port using the --port flag, e.g.:', 'fail');
525
+ this.logger(`hb-service ${this.action} --port 8581`, 'fail');
525
526
  node_process_1.default.exit(1);
526
527
  }
527
528
  }
528
529
  async storagePathCheck() {
529
530
  if ((0, node_os_1.platform)() === 'darwin' && !await (0, fs_extra_1.pathExists)((0, node_path_1.dirname)(this.storagePath))) {
530
- this.logger(`Cannot create Homebridge storage directory, base path does not exist: ${(0, node_path_1.dirname)(this.storagePath)}`, 'fail');
531
+ this.logger(`Cannot create Homebridge storage directory, base path does not exist: ${(0, node_path_1.dirname)(this.storagePath)}.`, 'fail');
531
532
  node_process_1.default.exit(1);
532
533
  }
533
534
  if (!await (0, fs_extra_1.pathExists)(this.storagePath)) {
534
- this.logger(`Creating Homebridge directory: ${this.storagePath}`);
535
+ this.logger(`Creating Homebridge directory: ${this.storagePath}.`);
535
536
  await (0, fs_extra_1.mkdirp)(this.storagePath);
536
537
  await this.chownPath(this.storagePath);
537
538
  }
@@ -540,7 +541,7 @@ class HomebridgeServiceHelper {
540
541
  let saveRequired = false;
541
542
  let restartRequired = false;
542
543
  if (!await (0, fs_extra_1.pathExists)(node_process_1.default.env.UIX_CONFIG_PATH)) {
543
- this.logger(`Creating default config.json: ${node_process_1.default.env.UIX_CONFIG_PATH}`);
544
+ this.logger(`Creating default config.json: ${node_process_1.default.env.UIX_CONFIG_PATH}.`);
544
545
  await this.createDefaultConfig();
545
546
  restartRequired = true;
546
547
  }
@@ -551,7 +552,7 @@ class HomebridgeServiceHelper {
551
552
  }
552
553
  let uiConfigBlock = currentConfig.platforms.find((x) => x.platform === 'config');
553
554
  if (!uiConfigBlock) {
554
- this.logger(`Adding missing UI platform block to ${node_process_1.default.env.UIX_CONFIG_PATH}`, 'info');
555
+ this.logger(`Adding missing UI platform block to ${node_process_1.default.env.UIX_CONFIG_PATH}.`, 'info');
555
556
  uiConfigBlock = await this.createDefaultUiConfig();
556
557
  currentConfig.platforms.push(uiConfigBlock);
557
558
  saveRequired = true;
@@ -559,14 +560,14 @@ class HomebridgeServiceHelper {
559
560
  }
560
561
  if (this.action !== 'install' && typeof uiConfigBlock.port !== 'number') {
561
562
  uiConfigBlock.port = await this.getLastKnownUiPort();
562
- this.logger(`Added missing port number to UI config - ${uiConfigBlock.port}`, 'info');
563
+ this.logger(`Added missing port number to UI config: ${uiConfigBlock.port}.`, 'info');
563
564
  saveRequired = true;
564
565
  restartRequired = true;
565
566
  }
566
567
  if (this.action === 'install') {
567
568
  if (uiConfigBlock.port !== this.uiPort) {
568
569
  uiConfigBlock.port = this.uiPort;
569
- this.logger(`WARNING: HOMEBRIDGE UI PORT IN ${node_process_1.default.env.UIX_CONFIG_PATH} CHANGED TO ${this.uiPort}`, 'warn');
570
+ this.logger(`Homebridge UI port in ${node_process_1.default.env.UIX_CONFIG_PATH} changed to: ${this.uiPort}.`, 'warn');
570
571
  }
571
572
  delete uiConfigBlock.restart;
572
573
  delete uiConfigBlock.sudo;
@@ -575,29 +576,29 @@ class HomebridgeServiceHelper {
575
576
  }
576
577
  if (typeof uiConfigBlock.port !== 'number') {
577
578
  uiConfigBlock.port = await this.getLastKnownUiPort();
578
- this.logger(`Added missing port number to UI config - ${uiConfigBlock.port}`, 'info');
579
+ this.logger(`Added missing port number to UI config: ${uiConfigBlock.port}.`, 'info');
579
580
  saveRequired = true;
580
581
  restartRequired = true;
581
582
  }
582
583
  if (!currentConfig.bridge) {
583
584
  currentConfig.bridge = await this.generateBridgeConfig();
584
- this.logger('Added missing Homebridge bridge section to the config.json', 'info');
585
+ this.logger('Added missing Homebridge bridge section to the config.json.', 'info');
585
586
  saveRequired = true;
586
587
  }
587
588
  if (!currentConfig.bridge.port) {
588
589
  currentConfig.bridge.port = await this.generatePort();
589
- this.logger(`Added port to the Homebridge bridge section of the config.json: ${currentConfig.bridge.port}`, 'info');
590
+ this.logger(`Added port to the Homebridge bridge section of the config.json: ${currentConfig.bridge.port}.`, 'info');
590
591
  saveRequired = true;
591
592
  }
592
593
  if ((uiConfigBlock && currentConfig.bridge.port === uiConfigBlock.port) || currentConfig.bridge.port === 8080) {
593
594
  currentConfig.bridge.port = await this.generatePort();
594
- this.logger(`Bridge port must not be the same as the UI port. Changing bridge port to ${currentConfig.bridge.port}.`, 'info');
595
+ this.logger(`Bridge port must not be the same as the UI port. Changing bridge port to: ${currentConfig.bridge.port}.`, 'info');
595
596
  saveRequired = true;
596
597
  }
597
598
  if (currentConfig.plugins && Array.isArray(currentConfig.plugins)) {
598
599
  if (!currentConfig.plugins.includes('homebridge-config-ui-x')) {
599
600
  currentConfig.plugins.push('homebridge-config-ui-x');
600
- this.logger('Added homebridge-config-ui-x to the plugins array in the config.json', 'info');
601
+ this.logger('Added Homebridge UI to the plugins array in the config.json.', 'info');
601
602
  saveRequired = true;
602
603
  }
603
604
  }
@@ -739,7 +740,7 @@ class HomebridgeServiceHelper {
739
740
  if (!pid) {
740
741
  return;
741
742
  }
742
- this.logger(`Found stale Homebridge process running on port ${currentConfig.bridge.port} with PID ${pid}, killing...`);
743
+ this.logger(`Found stale Homebridge process running on port: ${currentConfig.bridge.port}, with PID: ${pid}, killing...`);
743
744
  node_process_1.default.kill(pid, 'SIGKILL');
744
745
  }
745
746
  catch (e) {
@@ -747,7 +748,7 @@ class HomebridgeServiceHelper {
747
748
  }
748
749
  async tailLogs() {
749
750
  if (!(0, fs_extra_1.existsSync)(this.logPath)) {
750
- this.logger(`ERROR: Log file does not exist at expected location: ${this.logPath}`, 'fail');
751
+ this.logger(`Log file does not exist at expected location: ${this.logPath}.`, 'fail');
751
752
  node_process_1.default.exit(1);
752
753
  }
753
754
  const logStats = await (0, fs_extra_1.stat)(this.logPath);
@@ -771,7 +772,7 @@ class HomebridgeServiceHelper {
771
772
  async viewLogs() {
772
773
  this.installer.viewLogs();
773
774
  if (!(0, fs_extra_1.existsSync)(this.logPath)) {
774
- this.logger(`ERROR: Log file does not exist at expected location: ${this.logPath}`, 'fail');
775
+ this.logger(`Log file does not exist at expected location: ${this.logPath}.`, 'fail');
775
776
  node_process_1.default.exit(1);
776
777
  }
777
778
  const logStats = await (0, fs_extra_1.stat)(this.logPath);
@@ -825,7 +826,7 @@ class HomebridgeServiceHelper {
825
826
  }
826
827
  }
827
828
  catch (e) {
828
- this.logger(`Failed to load startup options ${e.message}`);
829
+ this.logger(`Failed to load startup options as ${e.message}.`);
829
830
  }
830
831
  }
831
832
  fixDockerPermissions() {
@@ -932,15 +933,15 @@ class HomebridgeServiceHelper {
932
933
  try {
933
934
  const res = await axios_1.default.get(`http://localhost:${this.uiPort}/api`);
934
935
  if (res.data === 'Hello World!') {
935
- this.logger('Homebridge UI Running', 'succeed');
936
+ this.logger('Homebridge UI running.', 'succeed');
936
937
  }
937
938
  else {
938
- this.logger('Unexpected Response', 'fail');
939
+ this.logger('Unexpected response.', 'fail');
939
940
  node_process_1.default.exit(1);
940
941
  }
941
942
  }
942
943
  catch (e) {
943
- this.logger('Homebridge UI Not Running', 'fail');
944
+ this.logger('Homebridge UI not running.', 'fail');
944
945
  node_process_1.default.exit(1);
945
946
  }
946
947
  }
@@ -979,7 +980,7 @@ class HomebridgeServiceHelper {
979
980
  }
980
981
  const cwd = (0, node_path_1.dirname)(node_process_1.default.env.UIX_CUSTOM_PLUGIN_PATH);
981
982
  if (!await (0, fs_extra_1.pathExists)(cwd)) {
982
- this.logger(`Path does not exist: "${cwd}"`, 'fail');
983
+ this.logger(`Path does not exist: ${cwd}.`, 'fail');
983
984
  }
984
985
  let cmd = `npm --prefix "${cwd}" ${action} ${target.name}`;
985
986
  if (action === 'add') {
@@ -991,10 +992,10 @@ class HomebridgeServiceHelper {
991
992
  cwd,
992
993
  stdio: 'inherit',
993
994
  });
994
- this.logger(`Installed ${target.name}@${target.version}`, 'succeed');
995
+ this.logger(`Installed ${target.name}@${target.version}.`, 'succeed');
995
996
  }
996
997
  catch (e) {
997
- this.logger('Plugin installation failed.', 'fail');
998
+ this.logger(`Plugin installation failed as ${e.message}.`, 'fail');
998
999
  }
999
1000
  }
1000
1001
  }