@microbit/microbit-connection 0.9.0-apps.alpha.17 → 0.9.0-apps.alpha.19
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/build/cjs/async-util.d.ts +3 -1
- package/build/cjs/async-util.js +5 -1
- package/build/cjs/async-util.js.map +1 -1
- package/build/cjs/bluetooth/ble-error.d.ts +10 -0
- package/build/cjs/bluetooth/ble-error.js +47 -0
- package/build/cjs/bluetooth/ble-error.js.map +1 -0
- package/build/cjs/bluetooth/connection.d.ts +263 -3
- package/build/cjs/bluetooth/connection.js +78 -21
- package/build/cjs/bluetooth/connection.js.map +1 -1
- package/build/cjs/bluetooth/device-wrapper.d.ts +6 -0
- package/build/cjs/bluetooth/device-wrapper.js +30 -7
- package/build/cjs/bluetooth/device-wrapper.js.map +1 -1
- package/build/cjs/bluetooth/flashing/flashing-full.js +2 -1
- package/build/cjs/bluetooth/flashing/flashing-full.js.map +1 -1
- package/build/cjs/bluetooth/flashing/flashing-partial.js +2 -1
- package/build/cjs/bluetooth/flashing/flashing-partial.js.map +1 -1
- package/build/cjs/bluetooth/flashing/nordic-dfu.js +18 -6
- package/build/cjs/bluetooth/flashing/nordic-dfu.js.map +1 -1
- package/build/cjs/bluetooth/services/accelerometer-service.js +5 -4
- package/build/cjs/bluetooth/services/accelerometer-service.js.map +1 -1
- package/build/cjs/bluetooth/services/button-service.js +12 -3
- package/build/cjs/bluetooth/services/button-service.js.map +1 -1
- package/build/cjs/bluetooth/services/device-information-service.js +7 -12
- package/build/cjs/bluetooth/services/device-information-service.js.map +1 -1
- package/build/cjs/bluetooth/services/event-service.d.ts +48 -0
- package/build/cjs/bluetooth/services/event-service.js +273 -0
- package/build/cjs/bluetooth/services/event-service.js.map +1 -0
- package/build/cjs/bluetooth/services/event-service.test.d.ts +1 -0
- package/build/cjs/bluetooth/services/event-service.test.js +252 -0
- package/build/cjs/bluetooth/services/event-service.test.js.map +1 -0
- package/build/cjs/bluetooth/services/io-pin-service.d.ts +65 -0
- package/build/cjs/bluetooth/services/io-pin-service.js +173 -0
- package/build/cjs/bluetooth/services/io-pin-service.js.map +1 -0
- package/build/cjs/bluetooth/services/led-service.js +3 -0
- package/build/cjs/bluetooth/services/led-service.js.map +1 -1
- package/build/cjs/bluetooth/services/magnetometer-service.js +5 -4
- package/build/cjs/bluetooth/services/magnetometer-service.js.map +1 -1
- package/build/cjs/bluetooth/services/temperature-service.d.ts +14 -0
- package/build/cjs/bluetooth/services/temperature-service.js +80 -0
- package/build/cjs/bluetooth/services/temperature-service.js.map +1 -0
- package/build/cjs/bluetooth/services/uart-service.js +12 -3
- package/build/cjs/bluetooth/services/uart-service.js.map +1 -1
- package/build/cjs/device.d.ts +73 -58
- package/build/cjs/device.js +7 -2
- package/build/cjs/device.js.map +1 -1
- package/build/cjs/events.d.ts +1 -2
- package/build/cjs/events.js.map +1 -1
- package/build/cjs/index.d.ts +5 -5
- package/build/cjs/index.js +4 -3
- package/build/cjs/index.js.map +1 -1
- package/build/cjs/microbit-events.d.ts +67 -0
- package/build/cjs/microbit-events.js +55 -0
- package/build/cjs/microbit-events.js.map +1 -0
- package/build/cjs/radio-bridge/connection.d.ts +18 -5
- package/build/cjs/radio-bridge/connection.js +30 -12
- package/build/cjs/radio-bridge/connection.js.map +1 -1
- package/build/cjs/service-events.d.ts +55 -6
- package/build/cjs/service-events.js.map +1 -1
- package/build/cjs/usb/arm-debug.d.ts +1 -1
- package/build/cjs/usb/arm-debug.js +3 -3
- package/build/cjs/usb/arm-debug.js.map +1 -1
- package/build/cjs/usb/cmsis-dap.js +1 -1
- package/build/cjs/usb/cmsis-dap.js.map +1 -1
- package/build/cjs/usb/connection.d.ts +18 -3
- package/build/cjs/usb/connection.js +17 -10
- package/build/cjs/usb/connection.js.map +1 -1
- package/build/cjs/usb/index.d.ts +1 -1
- package/build/cjs/usb/partial-flashing.d.ts +22 -4
- package/build/cjs/usb/partial-flashing.js +108 -18
- package/build/cjs/usb/partial-flashing.js.map +1 -1
- package/build/cjs/usb/serial-events.d.ts +0 -5
- package/build/cjs/usb/transport.js +4 -4
- package/build/cjs/usb/transport.js.map +1 -1
- package/build/esm/async-util.d.ts +3 -1
- package/build/esm/async-util.js +5 -1
- package/build/esm/async-util.js.map +1 -1
- package/build/esm/bluetooth/ble-error.d.ts +10 -0
- package/build/esm/bluetooth/ble-error.js +42 -0
- package/build/esm/bluetooth/ble-error.js.map +1 -0
- package/build/esm/bluetooth/connection.d.ts +263 -3
- package/build/esm/bluetooth/connection.js +79 -22
- package/build/esm/bluetooth/connection.js.map +1 -1
- package/build/esm/bluetooth/device-wrapper.d.ts +6 -0
- package/build/esm/bluetooth/device-wrapper.js +30 -7
- package/build/esm/bluetooth/device-wrapper.js.map +1 -1
- package/build/esm/bluetooth/flashing/flashing-full.js +2 -1
- package/build/esm/bluetooth/flashing/flashing-full.js.map +1 -1
- package/build/esm/bluetooth/flashing/flashing-partial.js +2 -1
- package/build/esm/bluetooth/flashing/flashing-partial.js.map +1 -1
- package/build/esm/bluetooth/flashing/nordic-dfu.js +18 -6
- package/build/esm/bluetooth/flashing/nordic-dfu.js.map +1 -1
- package/build/esm/bluetooth/services/accelerometer-service.js +5 -4
- package/build/esm/bluetooth/services/accelerometer-service.js.map +1 -1
- package/build/esm/bluetooth/services/button-service.js +12 -3
- package/build/esm/bluetooth/services/button-service.js.map +1 -1
- package/build/esm/bluetooth/services/device-information-service.js +7 -12
- package/build/esm/bluetooth/services/device-information-service.js.map +1 -1
- package/build/esm/bluetooth/services/event-service.d.ts +48 -0
- package/build/esm/bluetooth/services/event-service.js +269 -0
- package/build/esm/bluetooth/services/event-service.js.map +1 -0
- package/build/esm/bluetooth/services/event-service.test.d.ts +1 -0
- package/build/esm/bluetooth/services/event-service.test.js +250 -0
- package/build/esm/bluetooth/services/event-service.test.js.map +1 -0
- package/build/esm/bluetooth/services/io-pin-service.d.ts +65 -0
- package/build/esm/bluetooth/services/io-pin-service.js +169 -0
- package/build/esm/bluetooth/services/io-pin-service.js.map +1 -0
- package/build/esm/bluetooth/services/led-service.js +3 -0
- package/build/esm/bluetooth/services/led-service.js.map +1 -1
- package/build/esm/bluetooth/services/magnetometer-service.js +5 -4
- package/build/esm/bluetooth/services/magnetometer-service.js.map +1 -1
- package/build/esm/bluetooth/services/temperature-service.d.ts +14 -0
- package/build/esm/bluetooth/services/temperature-service.js +76 -0
- package/build/esm/bluetooth/services/temperature-service.js.map +1 -0
- package/build/esm/bluetooth/services/uart-service.js +12 -3
- package/build/esm/bluetooth/services/uart-service.js.map +1 -1
- package/build/esm/device.d.ts +73 -58
- package/build/esm/device.js +7 -2
- package/build/esm/device.js.map +1 -1
- package/build/esm/events.d.ts +1 -2
- package/build/esm/events.js.map +1 -1
- package/build/esm/index.d.ts +5 -5
- package/build/esm/index.js +2 -2
- package/build/esm/index.js.map +1 -1
- package/build/esm/microbit-events.d.ts +67 -0
- package/build/esm/microbit-events.js +52 -0
- package/build/esm/microbit-events.js.map +1 -0
- package/build/esm/radio-bridge/connection.d.ts +18 -5
- package/build/esm/radio-bridge/connection.js +31 -13
- package/build/esm/radio-bridge/connection.js.map +1 -1
- package/build/esm/service-events.d.ts +55 -6
- package/build/esm/service-events.js.map +1 -1
- package/build/esm/usb/arm-debug.d.ts +1 -1
- package/build/esm/usb/arm-debug.js +3 -3
- package/build/esm/usb/arm-debug.js.map +1 -1
- package/build/esm/usb/cmsis-dap.js +1 -1
- package/build/esm/usb/cmsis-dap.js.map +1 -1
- package/build/esm/usb/connection.d.ts +18 -3
- package/build/esm/usb/connection.js +18 -11
- package/build/esm/usb/connection.js.map +1 -1
- package/build/esm/usb/index.d.ts +1 -1
- package/build/esm/usb/partial-flashing.d.ts +22 -4
- package/build/esm/usb/partial-flashing.js +108 -18
- package/build/esm/usb/partial-flashing.js.map +1 -1
- package/build/esm/usb/serial-events.d.ts +0 -5
- package/build/esm/usb/transport.js +4 -4
- package/build/esm/usb/transport.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,269 @@
|
|
|
1
|
+
import { BleClient } from "@capacitor-community/bluetooth-le";
|
|
2
|
+
import { profile } from "../profile.js";
|
|
3
|
+
import { mapBleError } from "../ble-error.js";
|
|
4
|
+
import { EventSource, V2Source, } from "../../microbit-events.js";
|
|
5
|
+
const NAMED_EVENTS = [
|
|
6
|
+
"gesturechanged",
|
|
7
|
+
"buttonaaction",
|
|
8
|
+
"buttonbaction",
|
|
9
|
+
"buttonabaction",
|
|
10
|
+
"logoaction",
|
|
11
|
+
];
|
|
12
|
+
function isNamedEvent(type) {
|
|
13
|
+
return NAMED_EVENTS.includes(type);
|
|
14
|
+
}
|
|
15
|
+
export class EventService {
|
|
16
|
+
constructor(deviceId, dispatchTypedEvent, getBoardVersion) {
|
|
17
|
+
Object.defineProperty(this, "deviceId", {
|
|
18
|
+
enumerable: true,
|
|
19
|
+
configurable: true,
|
|
20
|
+
writable: true,
|
|
21
|
+
value: deviceId
|
|
22
|
+
});
|
|
23
|
+
Object.defineProperty(this, "dispatchTypedEvent", {
|
|
24
|
+
enumerable: true,
|
|
25
|
+
configurable: true,
|
|
26
|
+
writable: true,
|
|
27
|
+
value: dispatchTypedEvent
|
|
28
|
+
});
|
|
29
|
+
Object.defineProperty(this, "getBoardVersion", {
|
|
30
|
+
enumerable: true,
|
|
31
|
+
configurable: true,
|
|
32
|
+
writable: true,
|
|
33
|
+
value: getBoardVersion
|
|
34
|
+
});
|
|
35
|
+
Object.defineProperty(this, "uuid", {
|
|
36
|
+
enumerable: true,
|
|
37
|
+
configurable: true,
|
|
38
|
+
writable: true,
|
|
39
|
+
value: profile.event.id
|
|
40
|
+
});
|
|
41
|
+
Object.defineProperty(this, "activeEventTypes", {
|
|
42
|
+
enumerable: true,
|
|
43
|
+
configurable: true,
|
|
44
|
+
writable: true,
|
|
45
|
+
value: new Set()
|
|
46
|
+
});
|
|
47
|
+
/**
|
|
48
|
+
* Filters registered via named events (gestures, buttons), keyed as "source:value".
|
|
49
|
+
* Persists across reconnects so we can replay them.
|
|
50
|
+
*/
|
|
51
|
+
Object.defineProperty(this, "namedRequirements", {
|
|
52
|
+
enumerable: true,
|
|
53
|
+
configurable: true,
|
|
54
|
+
writable: true,
|
|
55
|
+
value: new Set()
|
|
56
|
+
});
|
|
57
|
+
/**
|
|
58
|
+
* Filters registered via explicit {@link subscribeToEvent} calls, keyed as "source:value".
|
|
59
|
+
* Only events matching these are dispatched as `microbitevent`.
|
|
60
|
+
* Persists across reconnects so we can replay them.
|
|
61
|
+
*/
|
|
62
|
+
Object.defineProperty(this, "explicitSubscriptions", {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
configurable: true,
|
|
65
|
+
writable: true,
|
|
66
|
+
value: new Set()
|
|
67
|
+
});
|
|
68
|
+
/**
|
|
69
|
+
* Tracks which named event types contributed which filter keys,
|
|
70
|
+
* so we can clean up when a named event is stopped.
|
|
71
|
+
*/
|
|
72
|
+
Object.defineProperty(this, "namedEventFilters", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
configurable: true,
|
|
75
|
+
writable: true,
|
|
76
|
+
value: new Map()
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
getRelevantEvents() {
|
|
80
|
+
return [
|
|
81
|
+
"gesturechanged",
|
|
82
|
+
"buttonaaction",
|
|
83
|
+
"buttonbaction",
|
|
84
|
+
"buttonabaction",
|
|
85
|
+
"logoaction",
|
|
86
|
+
"microbitevent",
|
|
87
|
+
];
|
|
88
|
+
}
|
|
89
|
+
async startNotifications(type) {
|
|
90
|
+
if (!this.getRelevantEvents().includes(type)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
this.activeEventTypes.add(type);
|
|
94
|
+
try {
|
|
95
|
+
// Always (re-)register the BLE notification. After a reconnect the
|
|
96
|
+
// previous subscription is gone even though the service instance is
|
|
97
|
+
// reused, so we cannot skip this.
|
|
98
|
+
await BleClient.startNotifications(this.deviceId, profile.event.id, profile.event.characteristics.microBitEvent.id, (value) => this.handleNotification(value));
|
|
99
|
+
if (isNamedEvent(type)) {
|
|
100
|
+
this.writeRequirementsForNamedEvent(type);
|
|
101
|
+
}
|
|
102
|
+
// Replay all filters (handles reconnect case where the micro:bit
|
|
103
|
+
// has lost its listener registrations).
|
|
104
|
+
await this.replayAllRequirements();
|
|
105
|
+
}
|
|
106
|
+
catch (e) {
|
|
107
|
+
this.dispatchTypedEvent("backgrounderror", {
|
|
108
|
+
error: mapBleError(e),
|
|
109
|
+
event: type,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
async stopNotifications(type) {
|
|
114
|
+
if (!this.getRelevantEvents().includes(type)) {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
this.activeEventTypes.delete(type);
|
|
118
|
+
// Remove filters contributed by this named event type
|
|
119
|
+
if (isNamedEvent(type)) {
|
|
120
|
+
const keys = this.namedEventFilters.get(type) ?? [];
|
|
121
|
+
for (const key of keys) {
|
|
122
|
+
this.namedRequirements.delete(key);
|
|
123
|
+
}
|
|
124
|
+
this.namedEventFilters.delete(type);
|
|
125
|
+
}
|
|
126
|
+
if (this.activeEventTypes.size === 0) {
|
|
127
|
+
try {
|
|
128
|
+
await BleClient.stopNotifications(this.deviceId, profile.event.id, profile.event.characteristics.microBitEvent.id);
|
|
129
|
+
}
|
|
130
|
+
catch (e) {
|
|
131
|
+
this.dispatchTypedEvent("backgrounderror", {
|
|
132
|
+
error: mapBleError(e),
|
|
133
|
+
event: type,
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Register interest in a specific micro:bit message bus event.
|
|
140
|
+
* Tells the micro:bit to forward matching message bus traffic over BLE.
|
|
141
|
+
* Matching events are dispatched as `microbitevent`.
|
|
142
|
+
* Use 0 as the value to match all events from a source.
|
|
143
|
+
*/
|
|
144
|
+
async subscribeToEvent(source, value) {
|
|
145
|
+
const key = filterKey(source, value);
|
|
146
|
+
if (!this.explicitSubscriptions.has(key)) {
|
|
147
|
+
this.explicitSubscriptions.add(key);
|
|
148
|
+
await this.writeClientRequirement(source, value);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* Send an event to the micro:bit's message bus.
|
|
153
|
+
*/
|
|
154
|
+
async sendEvent(source, value) {
|
|
155
|
+
const data = new DataView(new ArrayBuffer(4));
|
|
156
|
+
data.setUint16(0, source, true);
|
|
157
|
+
data.setUint16(2, value, true);
|
|
158
|
+
await BleClient.writeWithoutResponse(this.deviceId, profile.event.id, profile.event.characteristics.clientEvent.id, data);
|
|
159
|
+
}
|
|
160
|
+
handleNotification(dataView) {
|
|
161
|
+
for (let offset = 0; offset + 4 <= dataView.byteLength; offset += 4) {
|
|
162
|
+
const source = dataView.getUint16(offset, true);
|
|
163
|
+
const value = dataView.getUint16(offset + 2, true);
|
|
164
|
+
if (this.activeEventTypes.has("microbitevent") &&
|
|
165
|
+
this.matchesExplicitSubscription(source, value)) {
|
|
166
|
+
this.dispatchTypedEvent("microbitevent", { source, value });
|
|
167
|
+
}
|
|
168
|
+
this.demuxToNamedEvents(source, value);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
demuxToNamedEvents(source, value) {
|
|
172
|
+
const src = this.getSourceIds();
|
|
173
|
+
if (!src)
|
|
174
|
+
return;
|
|
175
|
+
if (source === src.Gesture && this.activeEventTypes.has("gesturechanged")) {
|
|
176
|
+
this.dispatchTypedEvent("gesturechanged", {
|
|
177
|
+
gesture: value,
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
if (source === src.ButtonA && this.activeEventTypes.has("buttonaaction")) {
|
|
181
|
+
this.dispatchTypedEvent("buttonaaction", {
|
|
182
|
+
button: "A",
|
|
183
|
+
action: value,
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
if (source === src.ButtonB && this.activeEventTypes.has("buttonbaction")) {
|
|
187
|
+
this.dispatchTypedEvent("buttonbaction", {
|
|
188
|
+
button: "B",
|
|
189
|
+
action: value,
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
if (source === src.ButtonAB &&
|
|
193
|
+
this.activeEventTypes.has("buttonabaction")) {
|
|
194
|
+
this.dispatchTypedEvent("buttonabaction", {
|
|
195
|
+
button: "AB",
|
|
196
|
+
action: value,
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
if (source === V2Source.Logo && this.activeEventTypes.has("logoaction")) {
|
|
200
|
+
this.dispatchTypedEvent("logoaction", {
|
|
201
|
+
button: "Logo",
|
|
202
|
+
action: value,
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
writeRequirementsForNamedEvent(type) {
|
|
207
|
+
const src = this.getSourceIds();
|
|
208
|
+
if (!src)
|
|
209
|
+
return;
|
|
210
|
+
const filters = [];
|
|
211
|
+
switch (type) {
|
|
212
|
+
case "gesturechanged":
|
|
213
|
+
filters.push([src.Gesture, 0]);
|
|
214
|
+
break;
|
|
215
|
+
case "buttonaaction":
|
|
216
|
+
filters.push([src.ButtonA, 0]);
|
|
217
|
+
break;
|
|
218
|
+
case "buttonbaction":
|
|
219
|
+
filters.push([src.ButtonB, 0]);
|
|
220
|
+
break;
|
|
221
|
+
case "buttonabaction":
|
|
222
|
+
filters.push([src.ButtonAB, 0]);
|
|
223
|
+
break;
|
|
224
|
+
case "logoaction":
|
|
225
|
+
filters.push([V2Source.Logo, 0]);
|
|
226
|
+
break;
|
|
227
|
+
}
|
|
228
|
+
const keys = [];
|
|
229
|
+
for (const [source, value] of filters) {
|
|
230
|
+
const key = filterKey(source, value);
|
|
231
|
+
keys.push(key);
|
|
232
|
+
this.namedRequirements.add(key);
|
|
233
|
+
}
|
|
234
|
+
this.namedEventFilters.set(type, keys);
|
|
235
|
+
}
|
|
236
|
+
matchesExplicitSubscription(source, value) {
|
|
237
|
+
if (this.explicitSubscriptions.has(filterKey(source, value)))
|
|
238
|
+
return true;
|
|
239
|
+
if (this.explicitSubscriptions.has(filterKey(source, 0)))
|
|
240
|
+
return true;
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
async replayAllRequirements() {
|
|
244
|
+
for (const key of this.namedRequirements) {
|
|
245
|
+
const [source, value] = key.split(":").map(Number);
|
|
246
|
+
await this.writeClientRequirement(source, value);
|
|
247
|
+
}
|
|
248
|
+
for (const key of this.explicitSubscriptions) {
|
|
249
|
+
const [source, value] = key.split(":").map(Number);
|
|
250
|
+
await this.writeClientRequirement(source, value);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
async writeClientRequirement(source, value) {
|
|
254
|
+
const data = new DataView(new ArrayBuffer(4));
|
|
255
|
+
data.setUint16(0, source, true);
|
|
256
|
+
data.setUint16(2, value, true);
|
|
257
|
+
await BleClient.write(this.deviceId, profile.event.id, profile.event.characteristics.clientRequirements.id, data);
|
|
258
|
+
}
|
|
259
|
+
getSourceIds() {
|
|
260
|
+
const version = this.getBoardVersion();
|
|
261
|
+
if (!version)
|
|
262
|
+
return undefined;
|
|
263
|
+
return version === "V1" ? EventSource.v1 : EventSource.v2;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
function filterKey(source, value) {
|
|
267
|
+
return `${source}:${value}`;
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=event-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-service.js","sourceRoot":"","sources":["../../../../src/bluetooth/services/event-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach } from "vitest";
|
|
2
|
+
import { BleClient } from "@capacitor-community/bluetooth-le";
|
|
3
|
+
import { EventService } from "./event-service.js";
|
|
4
|
+
import { V2Source, GestureEvent, ButtonAction } from "../../microbit-events.js";
|
|
5
|
+
vi.mock("@capacitor-community/bluetooth-le", () => ({
|
|
6
|
+
BleClient: {
|
|
7
|
+
startNotifications: vi.fn().mockResolvedValue(undefined),
|
|
8
|
+
stopNotifications: vi.fn().mockResolvedValue(undefined),
|
|
9
|
+
write: vi.fn().mockResolvedValue(undefined),
|
|
10
|
+
writeWithoutResponse: vi.fn().mockResolvedValue(undefined),
|
|
11
|
+
},
|
|
12
|
+
}));
|
|
13
|
+
vi.mock("../ble-error.js", () => ({
|
|
14
|
+
mapBleError: (e) => e,
|
|
15
|
+
}));
|
|
16
|
+
function makeEvent(source, value) {
|
|
17
|
+
const data = new DataView(new ArrayBuffer(4));
|
|
18
|
+
data.setUint16(0, source, true);
|
|
19
|
+
data.setUint16(2, value, true);
|
|
20
|
+
return data;
|
|
21
|
+
}
|
|
22
|
+
function makeMultiEvent(...pairs) {
|
|
23
|
+
const data = new DataView(new ArrayBuffer(pairs.length * 4));
|
|
24
|
+
pairs.forEach(([source, value], i) => {
|
|
25
|
+
data.setUint16(i * 4, source, true);
|
|
26
|
+
data.setUint16(i * 4 + 2, value, true);
|
|
27
|
+
});
|
|
28
|
+
return data;
|
|
29
|
+
}
|
|
30
|
+
/** Captures the notification callback passed to BleClient.startNotifications */
|
|
31
|
+
function captureNotificationCallback() {
|
|
32
|
+
const calls = BleClient.startNotifications.mock.calls;
|
|
33
|
+
const lastCall = calls[calls.length - 1];
|
|
34
|
+
return lastCall[3];
|
|
35
|
+
}
|
|
36
|
+
describe("EventService", () => {
|
|
37
|
+
let service;
|
|
38
|
+
let dispatch;
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
vi.clearAllMocks();
|
|
41
|
+
dispatch = vi.fn();
|
|
42
|
+
service = new EventService("test-device", dispatch, () => "V2");
|
|
43
|
+
});
|
|
44
|
+
describe("named events", () => {
|
|
45
|
+
it("dispatches gesturechanged when listening", async () => {
|
|
46
|
+
await service.startNotifications("gesturechanged");
|
|
47
|
+
const notify = captureNotificationCallback();
|
|
48
|
+
notify(makeEvent(V2Source.Gesture, GestureEvent.Shake));
|
|
49
|
+
expect(dispatch).toHaveBeenCalledWith("gesturechanged", {
|
|
50
|
+
gesture: GestureEvent.Shake,
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
it("dispatches button actions for A, B, AB", async () => {
|
|
54
|
+
await service.startNotifications("buttonaaction");
|
|
55
|
+
await service.startNotifications("buttonbaction");
|
|
56
|
+
await service.startNotifications("buttonabaction");
|
|
57
|
+
const notify = captureNotificationCallback();
|
|
58
|
+
notify(makeEvent(V2Source.ButtonA, ButtonAction.Click));
|
|
59
|
+
notify(makeEvent(V2Source.ButtonB, ButtonAction.LongClick));
|
|
60
|
+
notify(makeEvent(V2Source.ButtonAB, ButtonAction.DoubleClick));
|
|
61
|
+
expect(dispatch).toHaveBeenCalledWith("buttonaaction", {
|
|
62
|
+
button: "A",
|
|
63
|
+
action: ButtonAction.Click,
|
|
64
|
+
});
|
|
65
|
+
expect(dispatch).toHaveBeenCalledWith("buttonbaction", {
|
|
66
|
+
button: "B",
|
|
67
|
+
action: ButtonAction.LongClick,
|
|
68
|
+
});
|
|
69
|
+
expect(dispatch).toHaveBeenCalledWith("buttonabaction", {
|
|
70
|
+
button: "AB",
|
|
71
|
+
action: ButtonAction.DoubleClick,
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
it("dispatches logoaction (V2 only)", async () => {
|
|
75
|
+
await service.startNotifications("logoaction");
|
|
76
|
+
const notify = captureNotificationCallback();
|
|
77
|
+
notify(makeEvent(V2Source.Logo, ButtonAction.Click));
|
|
78
|
+
expect(dispatch).toHaveBeenCalledWith("logoaction", {
|
|
79
|
+
button: "Logo",
|
|
80
|
+
action: ButtonAction.Click,
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
it("does not dispatch after stopping a named event", async () => {
|
|
84
|
+
await service.startNotifications("gesturechanged");
|
|
85
|
+
const notify = captureNotificationCallback();
|
|
86
|
+
await service.stopNotifications("gesturechanged");
|
|
87
|
+
notify(makeEvent(V2Source.Gesture, GestureEvent.Shake));
|
|
88
|
+
expect(dispatch).not.toHaveBeenCalledWith("gesturechanged", expect.anything());
|
|
89
|
+
});
|
|
90
|
+
it("handles multiple events packed in one notification", async () => {
|
|
91
|
+
await service.startNotifications("gesturechanged");
|
|
92
|
+
await service.startNotifications("buttonaaction");
|
|
93
|
+
const notify = captureNotificationCallback();
|
|
94
|
+
notify(makeMultiEvent([V2Source.Gesture, GestureEvent.FaceUp], [V2Source.ButtonA, ButtonAction.Click]));
|
|
95
|
+
expect(dispatch).toHaveBeenCalledWith("gesturechanged", {
|
|
96
|
+
gesture: GestureEvent.FaceUp,
|
|
97
|
+
});
|
|
98
|
+
expect(dispatch).toHaveBeenCalledWith("buttonaaction", {
|
|
99
|
+
button: "A",
|
|
100
|
+
action: ButtonAction.Click,
|
|
101
|
+
});
|
|
102
|
+
});
|
|
103
|
+
});
|
|
104
|
+
describe("microbitevent isolation", () => {
|
|
105
|
+
it("does not dispatch microbitevent for named event traffic", async () => {
|
|
106
|
+
await service.startNotifications("gesturechanged");
|
|
107
|
+
await service.startNotifications("microbitevent");
|
|
108
|
+
const notify = captureNotificationCallback();
|
|
109
|
+
notify(makeEvent(V2Source.Gesture, GestureEvent.Shake));
|
|
110
|
+
expect(dispatch).toHaveBeenCalledWith("gesturechanged", {
|
|
111
|
+
gesture: GestureEvent.Shake,
|
|
112
|
+
});
|
|
113
|
+
expect(dispatch).not.toHaveBeenCalledWith("microbitevent", expect.anything());
|
|
114
|
+
});
|
|
115
|
+
it("dispatches microbitevent only for explicit subscriptions", async () => {
|
|
116
|
+
await service.startNotifications("microbitevent");
|
|
117
|
+
await service.subscribeToEvent(999, 0);
|
|
118
|
+
const notify = captureNotificationCallback();
|
|
119
|
+
notify(makeEvent(999, 42));
|
|
120
|
+
expect(dispatch).toHaveBeenCalledWith("microbitevent", {
|
|
121
|
+
source: 999,
|
|
122
|
+
value: 42,
|
|
123
|
+
});
|
|
124
|
+
});
|
|
125
|
+
it("wildcard subscription (value=0) matches all values from that source", async () => {
|
|
126
|
+
await service.startNotifications("microbitevent");
|
|
127
|
+
await service.subscribeToEvent(999, 0);
|
|
128
|
+
const notify = captureNotificationCallback();
|
|
129
|
+
notify(makeEvent(999, 1));
|
|
130
|
+
notify(makeEvent(999, 2));
|
|
131
|
+
notify(makeEvent(888, 1));
|
|
132
|
+
expect(dispatch).toHaveBeenCalledWith("microbitevent", {
|
|
133
|
+
source: 999,
|
|
134
|
+
value: 1,
|
|
135
|
+
});
|
|
136
|
+
expect(dispatch).toHaveBeenCalledWith("microbitevent", {
|
|
137
|
+
source: 999,
|
|
138
|
+
value: 2,
|
|
139
|
+
});
|
|
140
|
+
expect(dispatch).not.toHaveBeenCalledWith("microbitevent", expect.objectContaining({ source: 888 }));
|
|
141
|
+
});
|
|
142
|
+
it("exact subscription only matches that specific value", async () => {
|
|
143
|
+
await service.startNotifications("microbitevent");
|
|
144
|
+
await service.subscribeToEvent(999, 5);
|
|
145
|
+
const notify = captureNotificationCallback();
|
|
146
|
+
notify(makeEvent(999, 5));
|
|
147
|
+
notify(makeEvent(999, 6));
|
|
148
|
+
expect(dispatch).toHaveBeenCalledWith("microbitevent", {
|
|
149
|
+
source: 999,
|
|
150
|
+
value: 5,
|
|
151
|
+
});
|
|
152
|
+
expect(dispatch).not.toHaveBeenCalledWith("microbitevent", expect.objectContaining({ value: 6 }));
|
|
153
|
+
});
|
|
154
|
+
it("named events and explicit subscriptions work independently", async () => {
|
|
155
|
+
await service.startNotifications("gesturechanged");
|
|
156
|
+
await service.startNotifications("microbitevent");
|
|
157
|
+
await service.subscribeToEvent(999, 0);
|
|
158
|
+
const notify = captureNotificationCallback();
|
|
159
|
+
// Gesture events go to gesturechanged only
|
|
160
|
+
notify(makeEvent(V2Source.Gesture, GestureEvent.Shake));
|
|
161
|
+
// Custom events go to microbitevent only
|
|
162
|
+
notify(makeEvent(999, 42));
|
|
163
|
+
expect(dispatch).toHaveBeenCalledWith("gesturechanged", {
|
|
164
|
+
gesture: GestureEvent.Shake,
|
|
165
|
+
});
|
|
166
|
+
expect(dispatch).toHaveBeenCalledWith("microbitevent", {
|
|
167
|
+
source: 999,
|
|
168
|
+
value: 42,
|
|
169
|
+
});
|
|
170
|
+
// Gesture should NOT leak into microbitevent
|
|
171
|
+
expect(dispatch).not.toHaveBeenCalledWith("microbitevent", expect.objectContaining({ source: V2Source.Gesture }));
|
|
172
|
+
});
|
|
173
|
+
it("overlapping named + explicit subscription dispatches both", async () => {
|
|
174
|
+
await service.startNotifications("gesturechanged");
|
|
175
|
+
await service.startNotifications("microbitevent");
|
|
176
|
+
// Explicitly subscribe to the same source as the named event
|
|
177
|
+
await service.subscribeToEvent(V2Source.Gesture, 0);
|
|
178
|
+
const notify = captureNotificationCallback();
|
|
179
|
+
notify(makeEvent(V2Source.Gesture, GestureEvent.Shake));
|
|
180
|
+
// Both fire — you asked for both
|
|
181
|
+
expect(dispatch).toHaveBeenCalledWith("gesturechanged", {
|
|
182
|
+
gesture: GestureEvent.Shake,
|
|
183
|
+
});
|
|
184
|
+
expect(dispatch).toHaveBeenCalledWith("microbitevent", {
|
|
185
|
+
source: V2Source.Gesture,
|
|
186
|
+
value: GestureEvent.Shake,
|
|
187
|
+
});
|
|
188
|
+
});
|
|
189
|
+
it("stopping named event leaves explicit subscription working", async () => {
|
|
190
|
+
await service.startNotifications("gesturechanged");
|
|
191
|
+
await service.startNotifications("microbitevent");
|
|
192
|
+
await service.subscribeToEvent(V2Source.Gesture, 0);
|
|
193
|
+
const notify = captureNotificationCallback();
|
|
194
|
+
await service.stopNotifications("gesturechanged");
|
|
195
|
+
dispatch.mockClear();
|
|
196
|
+
notify(makeEvent(V2Source.Gesture, GestureEvent.Shake));
|
|
197
|
+
// Named event stopped
|
|
198
|
+
expect(dispatch).not.toHaveBeenCalledWith("gesturechanged", expect.anything());
|
|
199
|
+
// Explicit subscription still works
|
|
200
|
+
expect(dispatch).toHaveBeenCalledWith("microbitevent", {
|
|
201
|
+
source: V2Source.Gesture,
|
|
202
|
+
value: GestureEvent.Shake,
|
|
203
|
+
});
|
|
204
|
+
});
|
|
205
|
+
});
|
|
206
|
+
describe("BLE notification lifecycle", () => {
|
|
207
|
+
it("re-registers BLE notifications on each startNotifications call to handle reconnect", async () => {
|
|
208
|
+
await service.startNotifications("gesturechanged");
|
|
209
|
+
await service.startNotifications("buttonaaction");
|
|
210
|
+
await service.startNotifications("microbitevent");
|
|
211
|
+
expect(BleClient.startNotifications).toHaveBeenCalledTimes(3);
|
|
212
|
+
});
|
|
213
|
+
it("stops BLE notifications only when all event types are stopped", async () => {
|
|
214
|
+
await service.startNotifications("gesturechanged");
|
|
215
|
+
await service.startNotifications("buttonaaction");
|
|
216
|
+
await service.stopNotifications("gesturechanged");
|
|
217
|
+
expect(BleClient.stopNotifications).not.toHaveBeenCalled();
|
|
218
|
+
await service.stopNotifications("buttonaaction");
|
|
219
|
+
expect(BleClient.stopNotifications).toHaveBeenCalledTimes(1);
|
|
220
|
+
});
|
|
221
|
+
it("ignores irrelevant event types", async () => {
|
|
222
|
+
await service.startNotifications("accelerometerdatachanged");
|
|
223
|
+
expect(BleClient.startNotifications).not.toHaveBeenCalled();
|
|
224
|
+
});
|
|
225
|
+
});
|
|
226
|
+
describe("client requirements", () => {
|
|
227
|
+
it("writes client requirements for named events", async () => {
|
|
228
|
+
await service.startNotifications("gesturechanged");
|
|
229
|
+
expect(BleClient.write).toHaveBeenCalled();
|
|
230
|
+
const calls = BleClient.write.mock.calls;
|
|
231
|
+
const data = calls[calls.length - 1][3];
|
|
232
|
+
expect(data.getUint16(0, true)).toBe(V2Source.Gesture);
|
|
233
|
+
expect(data.getUint16(2, true)).toBe(0);
|
|
234
|
+
});
|
|
235
|
+
it("writes client requirements for explicit subscriptions", async () => {
|
|
236
|
+
await service.subscribeToEvent(999, 42);
|
|
237
|
+
expect(BleClient.write).toHaveBeenCalled();
|
|
238
|
+
const calls = BleClient.write.mock.calls;
|
|
239
|
+
const data = calls[calls.length - 1][3];
|
|
240
|
+
expect(data.getUint16(0, true)).toBe(999);
|
|
241
|
+
expect(data.getUint16(2, true)).toBe(42);
|
|
242
|
+
});
|
|
243
|
+
it("does not duplicate explicit subscription writes", async () => {
|
|
244
|
+
await service.subscribeToEvent(999, 42);
|
|
245
|
+
await service.subscribeToEvent(999, 42);
|
|
246
|
+
expect(BleClient.write).toHaveBeenCalledTimes(1);
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
//# sourceMappingURL=event-service.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-service.test.js","sourceRoot":"","sources":["../../../../src/bluetooth/services/event-service.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { Service } from "../device-wrapper.js";
|
|
2
|
+
import { PinValue, TypedServiceEvent, TypedServiceEventDispatcher } from "../../service-events.js";
|
|
3
|
+
export declare class IoPinService implements Service {
|
|
4
|
+
private deviceId;
|
|
5
|
+
private dispatchTypedEvent;
|
|
6
|
+
uuid: string;
|
|
7
|
+
constructor(deviceId: string, dispatchTypedEvent: TypedServiceEventDispatcher);
|
|
8
|
+
getRelevantEvents(): TypedServiceEvent[];
|
|
9
|
+
/**
|
|
10
|
+
* Gets which pins are configured as analog.
|
|
11
|
+
* All other pins are digital (the default).
|
|
12
|
+
*
|
|
13
|
+
* @returns array of pin numbers (0-18) configured as analog.
|
|
14
|
+
*/
|
|
15
|
+
getAnalogPins(): Promise<number[]>;
|
|
16
|
+
/**
|
|
17
|
+
* Sets which pins are configured as analog.
|
|
18
|
+
* All other pins become digital (the default).
|
|
19
|
+
*
|
|
20
|
+
* @param pins array of pin numbers (0-18) to configure as analog.
|
|
21
|
+
*/
|
|
22
|
+
setAnalogPins(pins: number[]): Promise<void>;
|
|
23
|
+
/**
|
|
24
|
+
* Gets which pins are configured as inputs.
|
|
25
|
+
* Input pins are monitored by the service and their values reported
|
|
26
|
+
* via notifications and reads of the pin data characteristic.
|
|
27
|
+
* All other pins are outputs (the default).
|
|
28
|
+
*
|
|
29
|
+
* @returns array of pin numbers (0-18) configured as inputs.
|
|
30
|
+
*/
|
|
31
|
+
getInputPins(): Promise<number[]>;
|
|
32
|
+
/**
|
|
33
|
+
* Sets which pins are configured as inputs.
|
|
34
|
+
* Input pins are monitored by the service and their values reported
|
|
35
|
+
* via notifications and reads of the pin data characteristic.
|
|
36
|
+
* All other pins become outputs (the default).
|
|
37
|
+
*
|
|
38
|
+
* @param pins array of pin numbers (0-18) to configure as inputs.
|
|
39
|
+
*/
|
|
40
|
+
setInputPins(pins: number[]): Promise<void>;
|
|
41
|
+
/**
|
|
42
|
+
* Reads pin data for all active input pins.
|
|
43
|
+
* For digital pins, value is 0 or 1.
|
|
44
|
+
* For analog pins, value is 0-255 (10-bit analog value >> 2).
|
|
45
|
+
*/
|
|
46
|
+
readPins(): Promise<PinValue[]>;
|
|
47
|
+
/**
|
|
48
|
+
* Writes pin data for output pins.
|
|
49
|
+
* Only pins configured as outputs (not active inputs) will be affected.
|
|
50
|
+
* For digital pins, value is 0 or 1.
|
|
51
|
+
* For analog pins, value 0-255 is scaled to 0-1023 on the device.
|
|
52
|
+
*/
|
|
53
|
+
writePins(data: PinValue[]): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* Sets PWM output on a pin.
|
|
56
|
+
*
|
|
57
|
+
* @param pin Pin number (0-18).
|
|
58
|
+
* @param value Analog value (0-1024).
|
|
59
|
+
* @param period Period in microseconds.
|
|
60
|
+
*/
|
|
61
|
+
setPwm(pin: number, value: number, period: number): Promise<void>;
|
|
62
|
+
startNotifications(type: TypedServiceEvent): Promise<void>;
|
|
63
|
+
stopNotifications(type: TypedServiceEvent): Promise<void>;
|
|
64
|
+
private dataViewToPinData;
|
|
65
|
+
}
|