@rhizomatics/signalk-einklabel-plugin 1.3.0-beta3 → 1.3.0-beta4

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,7 @@
2
2
 
3
3
  First implementation of using new SignalK BLE Manager rather than directly using the `bluez` services. Off by default until longer term stability demonstrated.
4
4
 
5
+
5
6
  # 1.2.3
6
7
 
7
8
  - Improved example tide template for 2.9" Gicisky, and added blank and error templates
@@ -25,6 +25,15 @@ export interface BleBackend {
25
25
  */
26
26
  export declare function withSessionWatchdog(conn: GattConnection, timeoutMs: number, forceClose: () => Promise<void>): GattConnection;
27
27
  export declare function nodeBleBackend(): BleBackend;
28
+ /**
29
+ * Waits for the BLE Manager to know about `address` before a GATT connect is attempted against it -
30
+ * mirrors `getOrDiscoverDevice` in `bleDiscovery.ts`, which gives `nodeBleBackend` the same guarantee
31
+ * against BlueZ directly. Without this, a specifically-addressed device that the manager hasn't seen
32
+ * yet (e.g. this plugin's own `scanOnStart` is off and no other BLE plugin happens to be scanning)
33
+ * would sit on `bleApi.connectGATT()` until that call's own `timeoutMs` gives up, rather than the
34
+ * plugin quietly rediscovering it the way the direct-BlueZ backend already does.
35
+ */
36
+ export declare function ensureDeviceVisible(bleApi: BLEApi, pluginId: string, address: string, timeoutMs: number): Promise<void>;
28
37
  /**
29
38
  * `bleApi.connectGATT()` has no timeout of its own, same story as node-ble's `Device#connect()` (see
30
39
  * `connectWithTimeout` in `bleDiscovery.ts`) - races it against `timeoutMs`.
@@ -2,6 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.withSessionWatchdog = withSessionWatchdog;
4
4
  exports.nodeBleBackend = nodeBleBackend;
5
+ exports.ensureDeviceVisible = ensureDeviceVisible;
5
6
  exports.bleApiBackend = bleApiBackend;
6
7
  const pluginVersion_1 = require("../pluginVersion");
7
8
  const bleDiscovery_1 = require("./bleDiscovery");
@@ -137,6 +138,35 @@ function nodeBleBackend() {
137
138
  },
138
139
  };
139
140
  }
141
+ /**
142
+ * Waits for the BLE Manager to know about `address` before a GATT connect is attempted against it -
143
+ * mirrors `getOrDiscoverDevice` in `bleDiscovery.ts`, which gives `nodeBleBackend` the same guarantee
144
+ * against BlueZ directly. Without this, a specifically-addressed device that the manager hasn't seen
145
+ * yet (e.g. this plugin's own `scanOnStart` is off and no other BLE plugin happens to be scanning)
146
+ * would sit on `bleApi.connectGATT()` until that call's own `timeoutMs` gives up, rather than the
147
+ * plugin quietly rediscovering it the way the direct-BlueZ backend already does.
148
+ */
149
+ async function ensureDeviceVisible(bleApi, pluginId, address, timeoutMs) {
150
+ const known = await bleApi.getDevice(address).catch(() => null);
151
+ if (known)
152
+ return;
153
+ const seen = await new Promise((resolve) => {
154
+ const timer = setTimeout(() => {
155
+ unsubscribe();
156
+ resolve(false);
157
+ }, timeoutMs);
158
+ const unsubscribe = bleApi.onAdvertisement(pluginId, (adv) => {
159
+ if (adv.mac !== address)
160
+ return;
161
+ clearTimeout(timer);
162
+ unsubscribe();
163
+ resolve(true);
164
+ });
165
+ });
166
+ if (!seen) {
167
+ throw new Error(`device ${address} isn't visible to the SignalK BLE Manager yet (out of range, asleep, or never seen) after waiting ${timeoutMs}ms`);
168
+ }
169
+ }
140
170
  /**
141
171
  * `bleApi.connectGATT()` has no timeout of its own, same story as node-ble's `Device#connect()` (see
142
172
  * `connectWithTimeout` in `bleDiscovery.ts`) - races it against `timeoutMs`.
@@ -149,6 +179,7 @@ function bleApiBackend(bleApi, pluginId) {
149
179
  // "already claimed" until the server restarts - see signalk-bluetti-plugin's BleManagerDevice
150
180
  // for the same defensive call. A no-op if we don't currently hold the claim.
151
181
  await bleApi.releaseGATTDevice(address, pluginId).catch(() => { });
182
+ await ensureDeviceVisible(bleApi, pluginId, address, DEVICE_DISCOVERY_TIMEOUT_MS);
152
183
  const connecting = bleApi.connectGATT(address, pluginId);
153
184
  let timedOut = false;
154
185
  const conn = await Promise.race([connecting, (0, bleDiscovery_1.sleep)(timeoutMs).then(() => void (timedOut = true))]);
@@ -179,6 +210,14 @@ function bleApiBackend(bleApi, pluginId) {
179
210
  // `BLEDeviceInfo` (from `getDevices()`/`getDevice()`) carries mac/name/rssi/seenBy but not
180
211
  // manufacturer data (see `BLEDeviceInfoSchema` in `@signalk/server-api`'s `ble-schemas.ts`) -
181
212
  // only the streamed `BLEAdvertisement` does. So this always actively waits on the stream.
213
+ //
214
+ // Same defensive release as `connectGatt`, and just as necessary here: a device the BLE Manager
215
+ // still thinks *we* hold a GATT claim on (e.g. from a crash/reload mid-paint, before this call
216
+ // ever reaches `connectGatt` below) stops advertising while claimed - which would otherwise wedge
217
+ // this wait forever, since nothing else in this path ever calls `connectGatt` (and so never gets a
218
+ // chance to release the stale claim) unless a fresh advertisement shows up first. A no-op if we
219
+ // don't currently hold the claim.
220
+ await bleApi.releaseGATTDevice(address, pluginId).catch(() => { });
182
221
  return new Promise((resolve) => {
183
222
  const timer = setTimeout(() => {
184
223
  unsubscribe();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rhizomatics/signalk-einklabel-plugin",
3
- "version": "1.3.0-beta3",
3
+ "version": "1.3.0-beta4",
4
4
  "description": "Display SignalK data on eInk Electronic Shelf Labels, includes working examples for tide clock and watch schedule.",
5
5
  "keywords": [
6
6
  "ble",