incyclist-devices 3.0.24 → 3.0.25
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.
|
@@ -55,7 +55,7 @@ class BleAdapter extends adpater_js_1.default {
|
|
|
55
55
|
const info = peripheral.getInfo();
|
|
56
56
|
const settings = { ...this.settings };
|
|
57
57
|
settings.id = settings.id ?? info.id;
|
|
58
|
-
settings.address =
|
|
58
|
+
settings.address = info.address ?? settings.address;
|
|
59
59
|
settings.name = settings.name ?? info.name;
|
|
60
60
|
this.settings = settings;
|
|
61
61
|
}
|
|
@@ -77,11 +77,13 @@ class BleAdapter extends adpater_js_1.default {
|
|
|
77
77
|
if (as.profile || settings.profile) {
|
|
78
78
|
return (as.protocol === settings.protocol && as.profile === settings.profile && as.name === settings.name);
|
|
79
79
|
}
|
|
80
|
-
|
|
81
|
-
return
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
80
|
+
if (as.protocol !== settings.protocol)
|
|
81
|
+
return false;
|
|
82
|
+
if (as.id && settings.id)
|
|
83
|
+
return as.id === settings.id;
|
|
84
|
+
if (as.address && settings.address)
|
|
85
|
+
return as.address === settings.address;
|
|
86
|
+
return !!(as.name && settings.name && as.name === settings.name);
|
|
85
87
|
}
|
|
86
88
|
isSame(adapter) {
|
|
87
89
|
return this.isEqual(adapter.getSettings());
|
|
@@ -72,14 +72,18 @@ class DirectConnectInterface extends node_events_1.EventEmitter {
|
|
|
72
72
|
const protocol = this.getProtocol(service);
|
|
73
73
|
const address = service.address;
|
|
74
74
|
const services = service.serviceUUIDs?.map(uuid => (0, index_js_1.beautifyUUID)(uuid, false))?.join(',');
|
|
75
|
-
|
|
75
|
+
const id = service.serialNo || undefined;
|
|
76
|
+
return { interface: DirectConnectInterface.INTERFACE_NAME, name, protocol, address, services, ...(id ? { id } : {}) };
|
|
76
77
|
}
|
|
77
78
|
catch {
|
|
78
79
|
return null;
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
createPeripheralFromSettings(settings) {
|
|
82
|
-
const
|
|
83
|
+
const bleSettings = settings;
|
|
84
|
+
const all = this.getAll();
|
|
85
|
+
const info = (bleSettings.address && all.find(a => a.service.name === settings.name && a.service.address === bleSettings.address))
|
|
86
|
+
?? all.find(a => a.service.name === settings.name);
|
|
83
87
|
if (!info?.service)
|
|
84
88
|
return null;
|
|
85
89
|
return this.createPeripheral(info.service);
|
|
@@ -247,35 +251,68 @@ class DirectConnectInterface extends node_events_1.EventEmitter {
|
|
|
247
251
|
const src = source === 'known-device' ? 'known-device' : 'mdns';
|
|
248
252
|
try {
|
|
249
253
|
service.transport = this.getName();
|
|
250
|
-
const
|
|
251
|
-
if (
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
254
|
+
const sameAddress = this.findByNameAndAddress(service.name, service.address);
|
|
255
|
+
if (sameAddress) {
|
|
256
|
+
this.refreshSameAddressEntry(sameAddress, service, src, source);
|
|
257
|
+
return;
|
|
258
|
+
}
|
|
259
|
+
const sameName = this.findAllByName(service.name);
|
|
260
|
+
if (src === 'known-device' && sameName.some(a => a.source !== 'known-device')) {
|
|
261
|
+
return;
|
|
262
|
+
}
|
|
263
|
+
if (sameName.length === 0) {
|
|
264
|
+
this.announceNewEntry(service, src, source, 'device announced');
|
|
265
|
+
return;
|
|
259
266
|
}
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
this.logEvent({ message: 'device announced', device: service.name, announcement: service, source });
|
|
265
|
-
this.emitDevice(service);
|
|
266
|
-
this.matching?.push(service.name);
|
|
267
|
+
const realEntries = sameName.filter(a => a.source !== 'known-device');
|
|
268
|
+
if (src !== 'known-device' && realEntries.length >= 1) {
|
|
269
|
+
this.announceNewEntry(service, src, source, 'device announced (name collision, distinct address)');
|
|
270
|
+
return;
|
|
267
271
|
}
|
|
272
|
+
this.reannounceExistingEntry(sameName[0], service, src, source);
|
|
268
273
|
}
|
|
269
274
|
catch (err) {
|
|
270
275
|
this.logError(err, 'addService');
|
|
271
276
|
}
|
|
272
277
|
}
|
|
273
|
-
|
|
274
|
-
|
|
278
|
+
refreshSameAddressEntry(sameAddress, service, src, source) {
|
|
279
|
+
const idx = this.services.indexOf(sameAddress);
|
|
280
|
+
const wasKnownDevicePlaceholder = sameAddress.source === 'known-device';
|
|
281
|
+
const nextSource = (wasKnownDevicePlaceholder && src !== 'known-device') ? src : sameAddress.source;
|
|
282
|
+
this.services[idx] = { ts: Date.now(), service, source: nextSource };
|
|
283
|
+
if (src !== 'known-device' && wasKnownDevicePlaceholder) {
|
|
284
|
+
this.logEvent({ message: 'device re-announced', device: service.name, announcement: service, source });
|
|
285
|
+
this.emitDevice(service);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
announceNewEntry(service, src, source, message) {
|
|
289
|
+
this.services.push({ ts: Date.now(), service, source: src });
|
|
290
|
+
if (!service.serviceUUIDs?.length)
|
|
291
|
+
return;
|
|
292
|
+
this.logEvent({ message, device: service.name, announcement: service, source });
|
|
293
|
+
this.emitDevice(service);
|
|
294
|
+
this.matching?.push(service.name);
|
|
295
|
+
}
|
|
296
|
+
reannounceExistingEntry(existing, service, src, source) {
|
|
297
|
+
const idx = this.services.indexOf(existing);
|
|
298
|
+
this.services[idx] = { ts: Date.now(), service, source: src };
|
|
299
|
+
if (src !== 'known-device') {
|
|
300
|
+
this.logEvent({ message: 'device re-announced', device: service.name, announcement: service, source });
|
|
301
|
+
this.emitDevice(service);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
findByNameAndAddress(name, address) {
|
|
305
|
+
return this.services.find(a => a.service.name === name && a.service.address === address && a.ts > Date.now() - DC_EXPIRATION_TIMEOUT);
|
|
306
|
+
}
|
|
307
|
+
findAllByName(name) {
|
|
308
|
+
return this.services.filter(a => a.service.name === name && a.ts > Date.now() - DC_EXPIRATION_TIMEOUT);
|
|
275
309
|
}
|
|
276
310
|
getAll() {
|
|
277
311
|
return this.services.filter(a => a.ts > Date.now() - DC_EXPIRATION_TIMEOUT);
|
|
278
312
|
}
|
|
313
|
+
hasNameCollision(name) {
|
|
314
|
+
return this.findAllByName(name).length > 1;
|
|
315
|
+
}
|
|
279
316
|
setDebug(enabled) {
|
|
280
317
|
this.debug = enabled;
|
|
281
318
|
}
|
|
@@ -50,7 +50,7 @@ export default class BleAdapter extends IncyclistDevice {
|
|
|
50
50
|
const info = peripheral.getInfo();
|
|
51
51
|
const settings = { ...this.settings };
|
|
52
52
|
settings.id = settings.id ?? info.id;
|
|
53
|
-
settings.address =
|
|
53
|
+
settings.address = info.address ?? settings.address;
|
|
54
54
|
settings.name = settings.name ?? info.name;
|
|
55
55
|
this.settings = settings;
|
|
56
56
|
}
|
|
@@ -72,11 +72,13 @@ export default class BleAdapter extends IncyclistDevice {
|
|
|
72
72
|
if (as.profile || settings.profile) {
|
|
73
73
|
return (as.protocol === settings.protocol && as.profile === settings.profile && as.name === settings.name);
|
|
74
74
|
}
|
|
75
|
-
|
|
76
|
-
return
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
75
|
+
if (as.protocol !== settings.protocol)
|
|
76
|
+
return false;
|
|
77
|
+
if (as.id && settings.id)
|
|
78
|
+
return as.id === settings.id;
|
|
79
|
+
if (as.address && settings.address)
|
|
80
|
+
return as.address === settings.address;
|
|
81
|
+
return !!(as.name && settings.name && as.name === settings.name);
|
|
80
82
|
}
|
|
81
83
|
isSame(adapter) {
|
|
82
84
|
return this.isEqual(adapter.getSettings());
|
|
@@ -69,14 +69,18 @@ export default class DirectConnectInterface extends EventEmitter {
|
|
|
69
69
|
const protocol = this.getProtocol(service);
|
|
70
70
|
const address = service.address;
|
|
71
71
|
const services = service.serviceUUIDs?.map(uuid => beautifyUUID(uuid, false))?.join(',');
|
|
72
|
-
|
|
72
|
+
const id = service.serialNo || undefined;
|
|
73
|
+
return { interface: DirectConnectInterface.INTERFACE_NAME, name, protocol, address, services, ...(id ? { id } : {}) };
|
|
73
74
|
}
|
|
74
75
|
catch {
|
|
75
76
|
return null;
|
|
76
77
|
}
|
|
77
78
|
}
|
|
78
79
|
createPeripheralFromSettings(settings) {
|
|
79
|
-
const
|
|
80
|
+
const bleSettings = settings;
|
|
81
|
+
const all = this.getAll();
|
|
82
|
+
const info = (bleSettings.address && all.find(a => a.service.name === settings.name && a.service.address === bleSettings.address))
|
|
83
|
+
?? all.find(a => a.service.name === settings.name);
|
|
80
84
|
if (!info?.service)
|
|
81
85
|
return null;
|
|
82
86
|
return this.createPeripheral(info.service);
|
|
@@ -244,35 +248,68 @@ export default class DirectConnectInterface extends EventEmitter {
|
|
|
244
248
|
const src = source === 'known-device' ? 'known-device' : 'mdns';
|
|
245
249
|
try {
|
|
246
250
|
service.transport = this.getName();
|
|
247
|
-
const
|
|
248
|
-
if (
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
251
|
+
const sameAddress = this.findByNameAndAddress(service.name, service.address);
|
|
252
|
+
if (sameAddress) {
|
|
253
|
+
this.refreshSameAddressEntry(sameAddress, service, src, source);
|
|
254
|
+
return;
|
|
255
|
+
}
|
|
256
|
+
const sameName = this.findAllByName(service.name);
|
|
257
|
+
if (src === 'known-device' && sameName.some(a => a.source !== 'known-device')) {
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
if (sameName.length === 0) {
|
|
261
|
+
this.announceNewEntry(service, src, source, 'device announced');
|
|
262
|
+
return;
|
|
256
263
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
this.logEvent({ message: 'device announced', device: service.name, announcement: service, source });
|
|
262
|
-
this.emitDevice(service);
|
|
263
|
-
this.matching?.push(service.name);
|
|
264
|
+
const realEntries = sameName.filter(a => a.source !== 'known-device');
|
|
265
|
+
if (src !== 'known-device' && realEntries.length >= 1) {
|
|
266
|
+
this.announceNewEntry(service, src, source, 'device announced (name collision, distinct address)');
|
|
267
|
+
return;
|
|
264
268
|
}
|
|
269
|
+
this.reannounceExistingEntry(sameName[0], service, src, source);
|
|
265
270
|
}
|
|
266
271
|
catch (err) {
|
|
267
272
|
this.logError(err, 'addService');
|
|
268
273
|
}
|
|
269
274
|
}
|
|
270
|
-
|
|
271
|
-
|
|
275
|
+
refreshSameAddressEntry(sameAddress, service, src, source) {
|
|
276
|
+
const idx = this.services.indexOf(sameAddress);
|
|
277
|
+
const wasKnownDevicePlaceholder = sameAddress.source === 'known-device';
|
|
278
|
+
const nextSource = (wasKnownDevicePlaceholder && src !== 'known-device') ? src : sameAddress.source;
|
|
279
|
+
this.services[idx] = { ts: Date.now(), service, source: nextSource };
|
|
280
|
+
if (src !== 'known-device' && wasKnownDevicePlaceholder) {
|
|
281
|
+
this.logEvent({ message: 'device re-announced', device: service.name, announcement: service, source });
|
|
282
|
+
this.emitDevice(service);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
announceNewEntry(service, src, source, message) {
|
|
286
|
+
this.services.push({ ts: Date.now(), service, source: src });
|
|
287
|
+
if (!service.serviceUUIDs?.length)
|
|
288
|
+
return;
|
|
289
|
+
this.logEvent({ message, device: service.name, announcement: service, source });
|
|
290
|
+
this.emitDevice(service);
|
|
291
|
+
this.matching?.push(service.name);
|
|
292
|
+
}
|
|
293
|
+
reannounceExistingEntry(existing, service, src, source) {
|
|
294
|
+
const idx = this.services.indexOf(existing);
|
|
295
|
+
this.services[idx] = { ts: Date.now(), service, source: src };
|
|
296
|
+
if (src !== 'known-device') {
|
|
297
|
+
this.logEvent({ message: 'device re-announced', device: service.name, announcement: service, source });
|
|
298
|
+
this.emitDevice(service);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
findByNameAndAddress(name, address) {
|
|
302
|
+
return this.services.find(a => a.service.name === name && a.service.address === address && a.ts > Date.now() - DC_EXPIRATION_TIMEOUT);
|
|
303
|
+
}
|
|
304
|
+
findAllByName(name) {
|
|
305
|
+
return this.services.filter(a => a.service.name === name && a.ts > Date.now() - DC_EXPIRATION_TIMEOUT);
|
|
272
306
|
}
|
|
273
307
|
getAll() {
|
|
274
308
|
return this.services.filter(a => a.ts > Date.now() - DC_EXPIRATION_TIMEOUT);
|
|
275
309
|
}
|
|
310
|
+
hasNameCollision(name) {
|
|
311
|
+
return this.findAllByName(name).length > 1;
|
|
312
|
+
}
|
|
276
313
|
setDebug(enabled) {
|
|
277
314
|
this.debug = enabled;
|
|
278
315
|
}
|
|
@@ -62,8 +62,13 @@ export default class DirectConnectInterface extends EventEmitter implements IBle
|
|
|
62
62
|
name: string;
|
|
63
63
|
}[];
|
|
64
64
|
protected addService(service: MulticastDnsAnnouncement, source?: string): void;
|
|
65
|
-
|
|
65
|
+
private refreshSameAddressEntry;
|
|
66
|
+
private announceNewEntry;
|
|
67
|
+
private reannounceExistingEntry;
|
|
68
|
+
protected findByNameAndAddress(name: string, address: string): Announcement;
|
|
69
|
+
protected findAllByName(name: string): Announcement[];
|
|
66
70
|
protected getAll(): Announcement[];
|
|
71
|
+
hasNameCollision(name: string): boolean;
|
|
67
72
|
setDebug(enabled: boolean): void;
|
|
68
73
|
logEvent(event: any): void;
|
|
69
74
|
logError(err: Error, fn: string, args?: any): void;
|