11// SPDX-License-Identifier: MIT
2- // Copyright (c) 2020-2023 The Pybricks Authors
2+ // Copyright (c) 2020-2024 The Pybricks Authors
33//
44// Definitions related to the Pybricks Bluetooth low energy GATT service.
55
@@ -25,13 +25,13 @@ export enum CommandType {
2525 /**
2626 * Request to start the user program.
2727 *
28- * @since Pybricks Profile v1.2.0
28+ * @since Pybricks Profile v1.2.0 - changed in v1.4.0
2929 */
3030 StartUserProgram = 1 ,
3131 /**
3232 * Request to start the interactive REPL.
3333 *
34- * @since Pybricks Profile v1.2.0
34+ * @since Pybricks Profile v1.2.0 - removed in v1.4.0
3535 */
3636 StartRepl = 2 ,
3737 /**
@@ -58,6 +58,43 @@ export enum CommandType {
5858 * @since Pybricks Profile v1.3.0
5959 */
6060 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 ,
6198}
6299
63100/**
@@ -74,20 +111,38 @@ export function createStopUserProgramCommand(): Uint8Array {
74111/**
75112 * Creates a {@link CommandType.StartUserProgram} message.
76113 *
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
78119 */
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 {
80135 const msg = new Uint8Array ( 1 ) ;
81136 msg [ 0 ] = CommandType . StartUserProgram ;
82137 return msg ;
83138}
84139
85140/**
86- * Creates a {@link CommandType.StartRepl} message.
141+ * Creates a legacy {@link CommandType.StartRepl} message.
87142 *
88- * @since Pybricks Profile v1.2.0
143+ * @since Pybricks Profile v1.2.0 - removed in v1.4.0
89144 */
90- export function createStartReplCommand ( ) : Uint8Array {
145+ export function createLegacyStartReplCommand ( ) : Uint8Array {
91146 const msg = new Uint8Array ( 1 ) ;
92147 msg [ 0 ] = CommandType . StartRepl ;
93148 return msg ;
@@ -140,6 +195,25 @@ export function createWriteStdinCommand(payload: ArrayBuffer): Uint8Array {
140195 return msg ;
141196}
142197
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+
143217/** Events are notifications received from the hub. */
144218export enum EventType {
145219 /**
@@ -156,6 +230,12 @@ export enum EventType {
156230 * @since Pybricks Profile v1.3.0
157231 */
158232 WriteStdout = 1 ,
233+ /**
234+ * Hub wrote to AppData event.
235+ *
236+ * @since Pybricks Profile v1.4.0
237+ */
238+ WriteAppData = 2 ,
159239}
160240
161241/** Status indications received by Event.StatusReport */
@@ -223,13 +303,16 @@ export function getEventType(msg: DataView): EventType {
223303/**
224304 * Parses the payload of a status report message.
225305 * @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 .
227307 *
228- * @since Pybricks Profile v1.0.0
308+ * @since Pybricks Profile v1.0.0 - changed in v1.4.0
229309 */
230- export function parseStatusReport ( msg : DataView ) : number {
310+ export function parseStatusReport ( msg : DataView ) : { flags : number ; slot : number } {
231311 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+ } ;
233316}
234317
235318/**
@@ -244,6 +327,18 @@ export function parseWriteStdout(msg: DataView): ArrayBuffer {
244327 return msg . buffer . slice ( 1 ) ;
245328}
246329
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+
247342/**
248343 * Protocol error. Thrown e.g. when there is a malformed message.
249344 */
@@ -266,7 +361,9 @@ export class ProtocolError extends Error {
266361 */
267362export enum HubCapabilityFlag {
268363 /**
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}
270367 *
271368 * @since Pybricks Profile v1.2.0
272369 */
@@ -285,6 +382,22 @@ export enum HubCapabilityFlag {
285382 * @since Pybricks Profile v1.3.0
286383 */
287384 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 ,
288401}
289402
290403/** Supported user program file formats. */
0 commit comments