1
1
// SPDX-License-Identifier: MIT
2
- // Copyright (c) 2020-2023 The Pybricks Authors
2
+ // Copyright (c) 2020-2024 The Pybricks Authors
3
3
//
4
4
// Definitions related to the Pybricks Bluetooth low energy GATT service.
5
5
@@ -25,13 +25,13 @@ export enum CommandType {
25
25
/**
26
26
* Request to start the user program.
27
27
*
28
- * @since Pybricks Profile v1.2.0
28
+ * @since Pybricks Profile v1.2.0 - changed in v1.4.0
29
29
*/
30
30
StartUserProgram = 1 ,
31
31
/**
32
32
* Request to start the interactive REPL.
33
33
*
34
- * @since Pybricks Profile v1.2.0
34
+ * @since Pybricks Profile v1.2.0 - removed in v1.4.0
35
35
*/
36
36
StartRepl = 2 ,
37
37
/**
@@ -58,6 +58,43 @@ export enum CommandType {
58
58
* @since Pybricks Profile v1.3.0
59
59
*/
60
60
WriteStdin = 6 ,
61
+ /**
62
+ * Requests to write to a buffer that is pre-allocated by a user program.
63
+ *
64
+ * Parameters:
65
+ * - offset: The offset from the buffer base address (16-bit little-endian
66
+ * unsigned integer).
67
+ * - payload: The data to write.
68
+ *
69
+ * @since Pybricks Profile v1.4.0
70
+ */
71
+ WriteAppData = 7 ,
72
+ }
73
+
74
+ /**
75
+ * Built-in program ID's for use with {@link CommandType.StartUserProgram}.
76
+ *
77
+ * @since Pybricks Profile v1.4.0
78
+ */
79
+ export enum BuiltinProgramId {
80
+ /**
81
+ * Requests to start the built-in REPL on stdio.
82
+ *
83
+ * @since Pybricks Profile v1.4.0
84
+ */
85
+ REPL = 0x80 ,
86
+ /**
87
+ * Requests to start the built-in sensor port view monitoring program.
88
+ *
89
+ * @since Pybricks Profile v1.4.0
90
+ */
91
+ PortView = 0x81 ,
92
+ /**
93
+ * Requests to start the built-in IMU calibration program.
94
+ *
95
+ * @since Pybricks Profile v1.4.0
96
+ */
97
+ IMUCalibration = 0x82 ,
61
98
}
62
99
63
100
/**
@@ -74,20 +111,38 @@ export function createStopUserProgramCommand(): Uint8Array {
74
111
/**
75
112
* Creates a {@link CommandType.StartUserProgram} message.
76
113
*
77
- * @since Pybricks Profile v1.2.0
114
+ * Parameters:
115
+ * - slot: Program identifier (one byte). Slots 0--127 are reserved for
116
+ * downloaded user programs. Slots 128--255 are for builtin user programs.
117
+ *
118
+ * @since Pybricks Profile v1.4.0
78
119
*/
79
- export function createStartUserProgramCommand ( ) : Uint8Array {
120
+ export function createStartUserProgramCommand (
121
+ slot : number | BuiltinProgramId ,
122
+ ) : Uint8Array {
123
+ const msg = new Uint8Array ( 2 ) ;
124
+ msg [ 0 ] = CommandType . StartUserProgram ;
125
+ msg [ 1 ] = slot ;
126
+ return msg ;
127
+ }
128
+
129
+ /**
130
+ * Creates a legacy {@link CommandType.StartUserProgram} message.
131
+ *
132
+ * @since Pybricks Profile v1.2.0 - removed in v1.4.0
133
+ */
134
+ export function createLegacyStartUserProgramCommand ( ) : Uint8Array {
80
135
const msg = new Uint8Array ( 1 ) ;
81
136
msg [ 0 ] = CommandType . StartUserProgram ;
82
137
return msg ;
83
138
}
84
139
85
140
/**
86
- * Creates a {@link CommandType.StartRepl} message.
141
+ * Creates a legacy {@link CommandType.StartRepl} message.
87
142
*
88
- * @since Pybricks Profile v1.2.0
143
+ * @since Pybricks Profile v1.2.0 - removed in v1.4.0
89
144
*/
90
- export function createStartReplCommand ( ) : Uint8Array {
145
+ export function createLegacyStartReplCommand ( ) : Uint8Array {
91
146
const msg = new Uint8Array ( 1 ) ;
92
147
msg [ 0 ] = CommandType . StartRepl ;
93
148
return msg ;
@@ -140,6 +195,25 @@ export function createWriteStdinCommand(payload: ArrayBuffer): Uint8Array {
140
195
return msg ;
141
196
}
142
197
198
+ /**
199
+ * Creates a {@link CommandType.WriteAppData} message.
200
+ * @param offset The offset from the buffer base address
201
+ * @param payload The bytes to write.
202
+ *
203
+ * @since Pybricks Profile v1.4.0.
204
+ */
205
+ export function createWriteAppDataCommand (
206
+ offset : number ,
207
+ payload : ArrayBuffer ,
208
+ ) : Uint8Array {
209
+ const msg = new Uint8Array ( 1 + 2 + payload . byteLength ) ;
210
+ const view = new DataView ( msg . buffer ) ;
211
+ view . setUint8 ( 0 , CommandType . WriteAppData ) ;
212
+ view . setUint16 ( 1 , offset & 0xffff , true ) ;
213
+ msg . set ( new Uint8Array ( payload ) , 3 ) ;
214
+ return msg ;
215
+ }
216
+
143
217
/** Events are notifications received from the hub. */
144
218
export enum EventType {
145
219
/**
@@ -156,6 +230,12 @@ export enum EventType {
156
230
* @since Pybricks Profile v1.3.0
157
231
*/
158
232
WriteStdout = 1 ,
233
+ /**
234
+ * Hub wrote to AppData event.
235
+ *
236
+ * @since Pybricks Profile v1.4.0
237
+ */
238
+ WriteAppData = 2 ,
159
239
}
160
240
161
241
/** Status indications received by Event.StatusReport */
@@ -223,13 +303,16 @@ export function getEventType(msg: DataView): EventType {
223
303
/**
224
304
* Parses the payload of a status report message.
225
305
* @param msg The raw message data.
226
- * @returns The status as bit flags.
306
+ * @returns The status as bit flags and the slot number of the running program .
227
307
*
228
- * @since Pybricks Profile v1.0.0
308
+ * @since Pybricks Profile v1.0.0 - changed in v1.4.0
229
309
*/
230
- export function parseStatusReport ( msg : DataView ) : number {
310
+ export function parseStatusReport ( msg : DataView ) : { flags : number ; slot : number } {
231
311
assert ( msg . getUint8 ( 0 ) === EventType . StatusReport , 'expecting status report event' ) ;
232
- return msg . getUint32 ( 1 , true ) ;
312
+ return {
313
+ flags : msg . getUint32 ( 1 , true ) ,
314
+ slot : msg . byteLength > 5 ? msg . getUint8 ( 5 ) : 0 ,
315
+ } ;
233
316
}
234
317
235
318
/**
@@ -244,6 +327,18 @@ export function parseWriteStdout(msg: DataView): ArrayBuffer {
244
327
return msg . buffer . slice ( 1 ) ;
245
328
}
246
329
330
+ /**
331
+ * Parses the payload of a app data message.
332
+ * @param msg The raw message data.
333
+ * @returns The bytes that were written.
334
+ *
335
+ * @since Pybricks Profile v1.4.0
336
+ */
337
+ export function parseWriteAppData ( msg : DataView ) : ArrayBuffer {
338
+ assert ( msg . getUint8 ( 0 ) === EventType . WriteAppData , 'expecting write appdata event' ) ;
339
+ return msg . buffer . slice ( 1 ) ;
340
+ }
341
+
247
342
/**
248
343
* Protocol error. Thrown e.g. when there is a malformed message.
249
344
*/
@@ -266,7 +361,9 @@ export class ProtocolError extends Error {
266
361
*/
267
362
export enum HubCapabilityFlag {
268
363
/**
269
- * Hub has an interactive REPL.
364
+ * Hub supports {@link CommandType.StartUserProgram} command with
365
+ * {@link BuiltinProgramId.REPL} for protocol v1.4.0 and later or hub
366
+ * supports {@link CommandType.StartRepl}
270
367
*
271
368
* @since Pybricks Profile v1.2.0
272
369
*/
@@ -285,6 +382,22 @@ export enum HubCapabilityFlag {
285
382
* @since Pybricks Profile v1.3.0
286
383
*/
287
384
UserProgramMultiMpy6Native6p1 = 1 << 2 ,
385
+
386
+ /**
387
+ * Hub supports {@link CommandType.StartUserProgram} command with
388
+ * {@link BuiltinProgramId.PortView}.
389
+ *
390
+ * @since Pybricks Profile v1.4.0.
391
+ */
392
+ HasPortView = 1 << 3 ,
393
+
394
+ /**
395
+ * Hub supports {@link CommandType.StartUserProgram} command with
396
+ * {@link BuiltinProgramId.IMUCalibration}.
397
+ *
398
+ * @since Pybricks Profile v1.4.0.
399
+ */
400
+ HasIMUCalibration = 1 << 4 ,
288
401
}
289
402
290
403
/** Supported user program file formats. */
0 commit comments