homebridge-intratone 0.4.0 → 0.4.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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,23 @@
2
2
 
3
3
  All notable changes to `homebridge-intratone`. Versions follow [semver](https://semver.org/).
4
4
 
5
+ ## [0.4.2] - 2026-11-12
6
+
7
+ ### Fixed
8
+
9
+ - The settings form still did not appear on first-time setup: config-ui-x only renders the schema
10
+ form once a config block exists (`pluginConfig.length`), which is empty before the first save.
11
+ The custom page now creates an empty config block before calling `showSchemaForm()`, so the
12
+ phone-number form shows on a fresh install. (0.4.1 only addressed the render timing.)
13
+
14
+ ## [0.4.1] - 2026-11-12
15
+
16
+ ### Fixed
17
+
18
+ - The custom settings page showed only the Connection and door panels but not the normal form, so
19
+ the phone number could not be entered. The form is now rendered on the UI host's `ready` event
20
+ (with a timeout fallback) instead of synchronously, which dropped the message.
21
+
5
22
  ## [0.4.0] - 2026-11-11
6
23
 
7
24
  ### Added
@@ -128,6 +145,8 @@ two-way audio are out of scope.
128
145
  masked.
129
146
  - MIT license.
130
147
 
148
+ [0.4.2]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.4.2
149
+ [0.4.1]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.4.1
131
150
  [0.4.0]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.4.0
132
151
  [0.3.0]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.3.0
133
152
  [0.2.2]: https://github.com/jtoucas-DIMO/Homebridge-Intratone/releases/tag/v0.2.2
@@ -1,67 +1,95 @@
1
1
  <!-- Custom settings page for homebridge-config-ui-x.
2
2
  Shows the live connection values and the detected doors (with inline rename) above the form.
3
- The standard form is always rendered first, so the page is never blank if a request fails. -->
3
+ The standard form (phone number, etc.) is shown via showSchemaForm() AFTER the UI host signals
4
+ 'ready' — posting it earlier drops the message and the form never appears. -->
4
5
  <div id="intratone-info" class="mb-3"></div>
5
6
  <div id="intratone-doors" class="mb-3"></div>
6
7
 
7
8
  <script>
8
- (async () => {
9
- // Base form first — if anything below throws, the normal settings still render.
10
- try {
11
- homebridge.showSchemaForm();
12
- } catch (error) {
13
- console.error('showSchemaForm failed', error);
9
+ let started = false;
10
+
11
+ async function init() {
12
+ if (started) {
13
+ return;
14
14
  }
15
+ started = true;
15
16
 
16
17
  const info = document.getElementById('intratone-info');
17
18
  const doors = document.getElementById('intratone-doors');
18
19
 
19
20
  let block;
20
21
  try {
21
- const configs = await homebridge.getPluginConfig();
22
+ let configs = await homebridge.getPluginConfig();
23
+ if (!configs.length) {
24
+ // config-ui-x renders the schema form only once a config block exists (it gates on
25
+ // pluginConfig.length). Create an empty one so the phone-number form appears on first setup.
26
+ await homebridge.updatePluginConfig([{ platform: 'Intratone', name: 'Intratone' }]);
27
+ configs = await homebridge.getPluginConfig();
28
+ }
22
29
  block = configs[0] || { platform: 'Intratone', name: 'Intratone' };
23
30
  } catch (error) {
24
- return; // No config access: just leave the standard form.
31
+ try { homebridge.showSchemaForm(); } catch (e) { console.error(e); }
32
+ return;
33
+ }
34
+
35
+ // With a config block present, the standard form (phone number, service, Advanced) renders.
36
+ try {
37
+ homebridge.showSchemaForm();
38
+ } catch (error) {
39
+ console.error('showSchemaForm failed', error);
25
40
  }
26
41
 
27
- homebridge.showSpinner();
28
- const [status, accesses] = await Promise.allSettled([
29
- homebridge.request('/status', { config: block }),
30
- homebridge.request('/accesses', { config: block }),
31
- ]);
32
- homebridge.hideSpinner();
42
+ let status;
43
+ let accesses;
44
+ try {
45
+ homebridge.showSpinner();
46
+ [status, accesses] = await Promise.allSettled([
47
+ homebridge.request('/status', { config: block }),
48
+ homebridge.request('/accesses', { config: block }),
49
+ ]);
50
+ } finally {
51
+ homebridge.hideSpinner();
52
+ }
33
53
 
34
54
  renderInfo(info, status);
35
55
  renderDoors(doors, block, accesses);
36
- })();
56
+ }
57
+
58
+ // The form must be shown after the host is ready; a timeout covers the case where 'ready'
59
+ // already fired before this listener was attached.
60
+ homebridge.addEventListener('ready', init);
61
+ setTimeout(init, 1500);
37
62
 
38
63
  function note(parent, text) {
39
- parent.innerHTML = '<p class="help-block text-muted">' + text + '</p>';
64
+ const p = document.createElement('p');
65
+ p.className = 'help-block text-muted';
66
+ p.textContent = text;
67
+ parent.appendChild(p);
40
68
  }
41
69
 
42
70
  function renderInfo(container, settled) {
71
+ container.innerHTML = '';
43
72
  const title = document.createElement('h5');
44
73
  title.textContent = 'Connection';
45
74
  container.appendChild(title);
46
75
 
47
- if (settled.status !== 'fulfilled') {
48
- const reason = settled.reason && settled.reason.message ? settled.reason.message : 'not connected yet';
49
- const p = document.createElement('p');
50
- p.className = 'help-block text-muted';
51
- p.textContent = 'Not connected (' + reason + '). Fill in the phone number and save, then reopen.';
52
- container.appendChild(p);
76
+ if (!settled || settled.status !== 'fulfilled') {
77
+ const reason = settled && settled.reason && settled.reason.message ? settled.reason.message : 'not connected yet';
78
+ note(container, 'Not connected (' + reason + '). Set the phone number below, press Save, then reopen this screen.');
53
79
  return;
54
80
  }
55
81
  const s = settled.value;
82
+ const session = s.session || {};
83
+ const flags = s.flags || {};
56
84
  const rows = [
57
85
  ['Device ID', s.deviceId + (s.generatedDeviceId ? ' (generated)' : '')],
58
86
  ['App ID', s.appId],
59
87
  ['App version', s.appVersion],
60
88
  ['Client', s.identity],
61
- ['Session valid until', s.session && s.session.validUntil],
62
- ['Smartphone ID', s.session && s.session.smartphoneId],
63
- ['Mobipass key held here', s.flags ? (s.flags.mobipass ? 'yes' : 'no') : '?'],
64
- ['Mobipass account', s.flags ? (s.flags.mobipassCompatible ? 'yes' : 'no') : '?'],
89
+ ['Session valid until', session.validUntil],
90
+ ['Smartphone ID', session.smartphoneId],
91
+ ['Mobipass key held here', s.flags ? (flags.mobipass ? 'yes' : 'no') : '?'],
92
+ ['Mobipass account', s.flags ? (flags.mobipassCompatible ? 'yes' : 'no') : '?'],
65
93
  ['State file', s.stateFile],
66
94
  ];
67
95
  const dl = document.createElement('dl');
@@ -102,28 +130,23 @@
102
130
  }
103
131
 
104
132
  function renderDoors(container, block, settled) {
133
+ container.innerHTML = '';
105
134
  const title = document.createElement('h5');
106
135
  title.textContent = 'Your doors';
107
136
  container.appendChild(title);
108
137
 
109
- if (settled.status !== 'fulfilled') {
110
- const reason = settled.reason && settled.reason.message ? settled.reason.message : 'unavailable';
111
- const p = document.createElement('p');
112
- p.className = 'help-block text-muted';
113
- p.textContent = 'Could not list your doors (' + reason + '). You can still rename them by editing config.json (access_names); unnamed doors keep their detected names in the Home app.';
114
- container.appendChild(p);
138
+ if (!settled || settled.status !== 'fulfilled') {
139
+ const reason = settled && settled.reason && settled.reason.message ? settled.reason.message : 'unavailable';
140
+ note(container, 'Could not list your doors (' + reason + '). Set the phone number below and Save first. You can also rename doors in config.json (access_names); unnamed doors keep their detected names in the Home app.');
115
141
  return;
116
142
  }
117
143
 
118
144
  const list = (settled.value && settled.value.openable) || [];
119
145
  const map = overridesFromConfig(block);
120
146
 
121
- const hint = document.createElement('p');
122
- hint.className = 'help-block text-muted';
123
- hint.textContent = list.length
147
+ note(container, list.length
124
148
  ? 'Type a name to show it in the Home app. Leave blank to keep the detected name. Press Save below to apply.'
125
- : 'No openable doors detected yet. Once they appear, you can rename them here.';
126
- container.appendChild(hint);
149
+ : 'No openable doors detected yet. Once they appear, you can rename them here.');
127
150
 
128
151
  for (const door of list) {
129
152
  const group = document.createElement('div');
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "homebridge-intratone",
3
3
  "displayName": "Intratone",
4
- "version": "0.4.0",
4
+ "version": "0.4.2",
5
5
  "description": "Unofficial Homebridge plugin to open Intratone / Cogelec doors and gates from HomeKit and Matter (remote open, no doorbell).",
6
6
  "license": "MIT",
7
7
  "author": "jtoucas-DIMO",