@blerpc/protocol-rn 0.6.0

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/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Copyright 2026 tdaira
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,20 @@
1
+ /** Command type: REQUEST or RESPONSE. */
2
+ export declare enum CommandType {
3
+ REQUEST = 0,
4
+ RESPONSE = 1
5
+ }
6
+ /** A single command packet. */
7
+ export declare class CommandPacket {
8
+ readonly cmdType: CommandType;
9
+ readonly cmdName: string;
10
+ readonly data: Uint8Array;
11
+ constructor(params: {
12
+ cmdType: CommandType;
13
+ cmdName: string;
14
+ data?: Uint8Array;
15
+ });
16
+ /** Serialize command to bytes. */
17
+ serialize(): Uint8Array;
18
+ /** Deserialize bytes into a CommandPacket. */
19
+ static deserialize(data: Uint8Array): CommandPacket;
20
+ }
@@ -0,0 +1,80 @@
1
+ "use strict";
2
+ // Command encode/decode layer for blerpc.
3
+ //
4
+ // Command format (bits):
5
+ // | type(1) | reserved(7) | cmd_name_len(8) | cmd_name(N*8) |
6
+ // | data_len(16) | data(data_len*8) |
7
+ //
8
+ // - type: 0=request, 1=response
9
+ // - cmd_name: ASCII command name
10
+ // - data_len: little-endian uint16
11
+ // - data: protobuf-encoded bytes
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.CommandPacket = exports.CommandType = void 0;
14
+ /** Command type: REQUEST or RESPONSE. */
15
+ var CommandType;
16
+ (function (CommandType) {
17
+ CommandType[CommandType["REQUEST"] = 0] = "REQUEST";
18
+ CommandType[CommandType["RESPONSE"] = 1] = "RESPONSE";
19
+ })(CommandType || (exports.CommandType = CommandType = {}));
20
+ const textEncoder = new TextEncoder();
21
+ const textDecoder = new TextDecoder("ascii");
22
+ /** A single command packet. */
23
+ class CommandPacket {
24
+ constructor(params) {
25
+ this.cmdType = params.cmdType;
26
+ this.cmdName = params.cmdName;
27
+ this.data = params.data ?? new Uint8Array(0);
28
+ }
29
+ /** Serialize command to bytes. */
30
+ serialize() {
31
+ const nameBytes = textEncoder.encode(this.cmdName);
32
+ if (nameBytes.length > 255) {
33
+ throw new Error(`cmd_name too long: ${nameBytes.length} > 255`);
34
+ }
35
+ if (this.data.length > 65535) {
36
+ throw new Error(`data too long: ${this.data.length} > 65535`);
37
+ }
38
+ // Byte 0: type in MSB (bit 7), reserved bits 6-0 = 0
39
+ const byte0 = (this.cmdType & 0x01) << 7;
40
+ const totalLen = 1 + 1 + nameBytes.length + 2 + this.data.length;
41
+ const buf = new ArrayBuffer(totalLen);
42
+ const view = new DataView(buf);
43
+ const bytes = new Uint8Array(buf);
44
+ let offset = 0;
45
+ view.setUint8(offset++, byte0);
46
+ view.setUint8(offset++, nameBytes.length);
47
+ bytes.set(nameBytes, offset);
48
+ offset += nameBytes.length;
49
+ view.setUint16(offset, this.data.length, true); // little-endian
50
+ offset += 2;
51
+ bytes.set(this.data, offset);
52
+ return bytes;
53
+ }
54
+ /** Deserialize bytes into a CommandPacket. */
55
+ static deserialize(data) {
56
+ if (data.length < 2) {
57
+ throw new Error(`Command packet too short: ${data.length} bytes`);
58
+ }
59
+ // Byte 0: type in MSB
60
+ const cmdType = ((data[0] >> 7) & 0x01) === 0 ? CommandType.REQUEST : CommandType.RESPONSE;
61
+ const cmdNameLen = data[1];
62
+ let offset = 2;
63
+ if (data.length < offset + cmdNameLen + 2) {
64
+ throw new Error("Command packet truncated");
65
+ }
66
+ const cmdName = textDecoder.decode(data.slice(offset, offset + cmdNameLen));
67
+ offset += cmdNameLen;
68
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
69
+ const dataLen = view.getUint16(offset, true);
70
+ offset += 2;
71
+ const payload = data.slice(offset, offset + dataLen);
72
+ return new CommandPacket({
73
+ cmdType,
74
+ cmdName,
75
+ data: payload,
76
+ });
77
+ }
78
+ }
79
+ exports.CommandPacket = CommandPacket;
80
+ //# sourceMappingURL=commandPacket.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"commandPacket.js","sourceRoot":"","sources":["../src/commandPacket.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { ContainerType, ControlCmd } from "./containerTypes";
2
+ /** Pack type(2) | control_cmd(4) | reserved(2) into a single byte. */
3
+ export declare function packFlags(type: ContainerType, cmd?: ControlCmd): number;
4
+ /** Unpack flags byte into [type, controlCmd]. */
5
+ export declare function unpackFlags(flagsByte: number): [ContainerType, ControlCmd];
6
+ /** A single container packet. */
7
+ export declare class Container {
8
+ readonly transactionId: number;
9
+ readonly sequenceNumber: number;
10
+ readonly containerType: ContainerType;
11
+ readonly controlCmd: ControlCmd;
12
+ readonly totalLength: number;
13
+ readonly payload: Uint8Array;
14
+ constructor(params: {
15
+ transactionId: number;
16
+ sequenceNumber: number;
17
+ containerType: ContainerType;
18
+ controlCmd?: ControlCmd;
19
+ totalLength?: number;
20
+ payload?: Uint8Array;
21
+ });
22
+ /** Serialize container to bytes. */
23
+ serialize(): Uint8Array;
24
+ /** Deserialize bytes into a Container. */
25
+ static deserialize(data: Uint8Array): Container;
26
+ }
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ // Container serialize/deserialize for blerpc.
3
+ //
4
+ // Container format (bits):
5
+ // | transaction_id(8) | sequence_number(8) | type(2)|control_cmd(4)|reserved(2) |
6
+ // | total_length(16 or 0) | payload_len(8) | payload(variable) |
7
+ //
8
+ // type=0b00 (FIRST): has total_length, header = 6 bytes
9
+ // type=0b01 (SUBSEQUENT): no total_length, header = 4 bytes
10
+ // type=0b11 (CONTROL): no total_length, header = 4 bytes
11
+ //
12
+ // All multi-byte fields are little-endian.
13
+ Object.defineProperty(exports, "__esModule", { value: true });
14
+ exports.Container = void 0;
15
+ exports.packFlags = packFlags;
16
+ exports.unpackFlags = unpackFlags;
17
+ const containerTypes_1 = require("./containerTypes");
18
+ /** Pack type(2) | control_cmd(4) | reserved(2) into a single byte. */
19
+ function packFlags(type, cmd = containerTypes_1.ControlCmd.NONE) {
20
+ return ((type & 0x03) << 6) | ((cmd & 0x0f) << 2);
21
+ }
22
+ /** Unpack flags byte into [type, controlCmd]. */
23
+ function unpackFlags(flagsByte) {
24
+ const type = (0, containerTypes_1.containerTypeFromValue)((flagsByte >> 6) & 0x03);
25
+ const cmd = (0, containerTypes_1.controlCmdFromValue)((flagsByte >> 2) & 0x0f);
26
+ return [type, cmd];
27
+ }
28
+ /** A single container packet. */
29
+ class Container {
30
+ constructor(params) {
31
+ this.transactionId = params.transactionId;
32
+ this.sequenceNumber = params.sequenceNumber;
33
+ this.containerType = params.containerType;
34
+ this.controlCmd = params.controlCmd ?? containerTypes_1.ControlCmd.NONE;
35
+ this.totalLength = params.totalLength ?? 0;
36
+ this.payload = params.payload ?? new Uint8Array(0);
37
+ }
38
+ /** Serialize container to bytes. */
39
+ serialize() {
40
+ const flags = packFlags(this.containerType, this.controlCmd);
41
+ if (this.containerType === containerTypes_1.ContainerType.FIRST) {
42
+ const buf = new ArrayBuffer(containerTypes_1.FIRST_HEADER_SIZE + this.payload.length);
43
+ const view = new DataView(buf);
44
+ const bytes = new Uint8Array(buf);
45
+ view.setUint8(0, this.transactionId);
46
+ view.setUint8(1, this.sequenceNumber);
47
+ view.setUint8(2, flags);
48
+ view.setUint16(3, this.totalLength, true); // little-endian
49
+ view.setUint8(5, this.payload.length);
50
+ bytes.set(this.payload, containerTypes_1.FIRST_HEADER_SIZE);
51
+ return bytes;
52
+ }
53
+ else {
54
+ const buf = new ArrayBuffer(containerTypes_1.SUBSEQUENT_HEADER_SIZE + this.payload.length);
55
+ const view = new DataView(buf);
56
+ const bytes = new Uint8Array(buf);
57
+ view.setUint8(0, this.transactionId);
58
+ view.setUint8(1, this.sequenceNumber);
59
+ view.setUint8(2, flags);
60
+ view.setUint8(3, this.payload.length);
61
+ bytes.set(this.payload, containerTypes_1.SUBSEQUENT_HEADER_SIZE);
62
+ return bytes;
63
+ }
64
+ }
65
+ /** Deserialize bytes into a Container. */
66
+ static deserialize(data) {
67
+ if (data.length < 4) {
68
+ throw new Error(`Container too short: ${data.length} bytes`);
69
+ }
70
+ const transactionId = data[0];
71
+ const sequenceNumber = data[1];
72
+ const [containerType, controlCmd] = unpackFlags(data[2]);
73
+ if (containerType === containerTypes_1.ContainerType.FIRST) {
74
+ if (data.length < containerTypes_1.FIRST_HEADER_SIZE) {
75
+ throw new Error(`FIRST container too short: ${data.length} bytes`);
76
+ }
77
+ const view = new DataView(data.buffer, data.byteOffset, data.byteLength);
78
+ const totalLength = view.getUint16(3, true);
79
+ const payloadLen = data[5];
80
+ const payload = data.slice(containerTypes_1.FIRST_HEADER_SIZE, containerTypes_1.FIRST_HEADER_SIZE + payloadLen);
81
+ return new Container({
82
+ transactionId,
83
+ sequenceNumber,
84
+ containerType,
85
+ controlCmd,
86
+ totalLength,
87
+ payload,
88
+ });
89
+ }
90
+ else {
91
+ const payloadLen = data[3];
92
+ const payload = data.slice(containerTypes_1.SUBSEQUENT_HEADER_SIZE, containerTypes_1.SUBSEQUENT_HEADER_SIZE + payloadLen);
93
+ return new Container({
94
+ transactionId,
95
+ sequenceNumber,
96
+ containerType,
97
+ controlCmd,
98
+ payload,
99
+ });
100
+ }
101
+ }
102
+ }
103
+ exports.Container = Container;
104
+ //# sourceMappingURL=container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"container.js","sourceRoot":"","sources":["../src/container.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import { Container } from "./container";
2
+ /** Reassembles containers into a complete payload. */
3
+ export declare class ContainerAssembler {
4
+ private _transactions;
5
+ /** Feed a container. Returns complete payload when done, else null. */
6
+ feed(container: Container): Uint8Array | null;
7
+ /** Clear all pending assembly state. */
8
+ reset(): void;
9
+ /** Visible for testing: check if a transaction is tracked. */
10
+ hasTransaction(tid: number): boolean;
11
+ }
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ // Reassembles containers into a complete payload.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ContainerAssembler = void 0;
5
+ const containerTypes_1 = require("./containerTypes");
6
+ /** Reassembles containers into a complete payload. */
7
+ class ContainerAssembler {
8
+ constructor() {
9
+ this._transactions = new Map();
10
+ }
11
+ /** Feed a container. Returns complete payload when done, else null. */
12
+ feed(container) {
13
+ if (container.containerType === containerTypes_1.ContainerType.CONTROL) {
14
+ return null; // Control containers are handled separately
15
+ }
16
+ const tid = container.transactionId;
17
+ if (container.containerType === containerTypes_1.ContainerType.FIRST) {
18
+ this._transactions.set(tid, {
19
+ totalLength: container.totalLength,
20
+ expectedSeq: 1,
21
+ fragments: [container.payload],
22
+ receivedLength: container.payload.length,
23
+ });
24
+ }
25
+ else if (this._transactions.has(tid)) {
26
+ const state = this._transactions.get(tid);
27
+ if (container.sequenceNumber !== state.expectedSeq) {
28
+ // Sequence gap — discard entire transaction
29
+ this._transactions.delete(tid);
30
+ return null;
31
+ }
32
+ state.fragments.push(container.payload);
33
+ state.receivedLength += container.payload.length;
34
+ state.expectedSeq += 1;
35
+ }
36
+ else {
37
+ // Subsequent without a FIRST — ignore
38
+ return null;
39
+ }
40
+ const state = this._transactions.get(tid);
41
+ if (state.receivedLength >= state.totalLength) {
42
+ // Combine fragments and trim to totalLength
43
+ const combined = new Uint8Array(state.receivedLength);
44
+ let offset = 0;
45
+ for (const f of state.fragments) {
46
+ combined.set(f, offset);
47
+ offset += f.length;
48
+ }
49
+ this._transactions.delete(tid);
50
+ return combined.slice(0, state.totalLength);
51
+ }
52
+ return null;
53
+ }
54
+ /** Clear all pending assembly state. */
55
+ reset() {
56
+ this._transactions.clear();
57
+ }
58
+ /** Visible for testing: check if a transaction is tracked. */
59
+ hasTransaction(tid) {
60
+ return this._transactions.has(tid);
61
+ }
62
+ }
63
+ exports.ContainerAssembler = ContainerAssembler;
64
+ //# sourceMappingURL=containerAssembler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerAssembler.js","sourceRoot":"","sources":["../src/containerAssembler.ts"],"names":[],"mappings":";AAAA,kDAAkD;;;AAGlD,qDAAiD;AASjD,sDAAsD;AACtD,MAAa,kBAAkB;IAA/B;QACU,kBAAa,GAAG,IAAI,GAAG,EAAyB,CAAC;IAyD3D,CAAC;IAvDC,uEAAuE;IACvE,IAAI,CAAC,SAAoB;QACvB,IAAI,SAAS,CAAC,aAAa,KAAK,8BAAa,CAAC,OAAO,EAAE,CAAC;YACtD,OAAO,IAAI,CAAC,CAAC,4CAA4C;QAC3D,CAAC;QAED,MAAM,GAAG,GAAG,SAAS,CAAC,aAAa,CAAC;QAEpC,IAAI,SAAS,CAAC,aAAa,KAAK,8BAAa,CAAC,KAAK,EAAE,CAAC;YACpD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE;gBAC1B,WAAW,EAAE,SAAS,CAAC,WAAW;gBAClC,WAAW,EAAE,CAAC;gBACd,SAAS,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC;gBAC9B,cAAc,EAAE,SAAS,CAAC,OAAO,CAAC,MAAM;aACzC,CAAC,CAAC;QACL,CAAC;aAAM,IAAI,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YACvC,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;YAC3C,IAAI,SAAS,CAAC,cAAc,KAAK,KAAK,CAAC,WAAW,EAAE,CAAC;gBACnD,4CAA4C;gBAC5C,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC/B,OAAO,IAAI,CAAC;YACd,CAAC;YACD,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;YACxC,KAAK,CAAC,cAAc,IAAI,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC;YACjD,KAAK,CAAC,WAAW,IAAI,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,sCAAsC;YACtC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;QAC3C,IAAI,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YAC9C,4CAA4C;YAC5C,MAAM,QAAQ,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACtD,IAAI,MAAM,GAAG,CAAC,CAAC;YACf,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;gBAChC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,CAAC;gBACxB,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC;YACrB,CAAC;YACD,IAAI,CAAC,aAAa,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAC/B,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,WAAW,CAAC,CAAC;QAC9C,CAAC;QAED,OAAO,IAAI,CAAC;IACd,CAAC;IAED,wCAAwC;IACxC,KAAK;QACH,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;IAC7B,CAAC;IAED,8DAA8D;IAC9D,cAAc,CAAC,GAAW;QACxB,OAAO,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IACrC,CAAC;CACF;AA1DD,gDA0DC"}
@@ -0,0 +1,17 @@
1
+ import { Container } from "./container";
2
+ /** Splits a payload into containers respecting MTU. */
3
+ export declare class ContainerSplitter {
4
+ private readonly _mtu;
5
+ private _transactionCounter;
6
+ constructor(mtu?: number);
7
+ /** Usable bytes per BLE packet (MTU - ATT overhead). */
8
+ get effectiveMtu(): number;
9
+ /** Get next transaction ID (auto-increments, wraps at 256). */
10
+ nextTransactionId(): number;
11
+ /**
12
+ * Split payload into a list of containers.
13
+ *
14
+ * Throws if payload is too large for 8-bit sequence_number (>255 containers) or > 65535 bytes.
15
+ */
16
+ split(payload: Uint8Array, transactionId?: number): Container[];
17
+ }
@@ -0,0 +1,70 @@
1
+ "use strict";
2
+ // Splits a payload into MTU-sized containers.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ContainerSplitter = void 0;
5
+ const container_1 = require("./container");
6
+ const containerTypes_1 = require("./containerTypes");
7
+ /** Splits a payload into containers respecting MTU. */
8
+ class ContainerSplitter {
9
+ constructor(mtu = 247) {
10
+ this._transactionCounter = 0;
11
+ this._mtu = mtu;
12
+ }
13
+ /** Usable bytes per BLE packet (MTU - ATT overhead). */
14
+ get effectiveMtu() {
15
+ return this._mtu - containerTypes_1.ATT_OVERHEAD;
16
+ }
17
+ /** Get next transaction ID (auto-increments, wraps at 256). */
18
+ nextTransactionId() {
19
+ const tid = this._transactionCounter;
20
+ this._transactionCounter = (this._transactionCounter + 1) & 0xff;
21
+ return tid;
22
+ }
23
+ /**
24
+ * Split payload into a list of containers.
25
+ *
26
+ * Throws if payload is too large for 8-bit sequence_number (>255 containers) or > 65535 bytes.
27
+ */
28
+ split(payload, transactionId) {
29
+ transactionId = transactionId ?? this.nextTransactionId();
30
+ const totalLength = payload.length;
31
+ if (totalLength > 65535) {
32
+ throw new Error(`Payload too large: ${totalLength} > 65535`);
33
+ }
34
+ const containers = [];
35
+ // First container
36
+ const firstMaxPayload = this.effectiveMtu - containerTypes_1.FIRST_HEADER_SIZE;
37
+ const firstEnd = firstMaxPayload < totalLength ? firstMaxPayload : totalLength;
38
+ const firstPayload = payload.slice(0, firstEnd);
39
+ containers.push(new container_1.Container({
40
+ transactionId,
41
+ sequenceNumber: 0,
42
+ containerType: containerTypes_1.ContainerType.FIRST,
43
+ totalLength,
44
+ payload: firstPayload,
45
+ }));
46
+ let offset = firstPayload.length;
47
+ let seq = 1;
48
+ // Subsequent containers
49
+ const subsequentMaxPayload = this.effectiveMtu - containerTypes_1.SUBSEQUENT_HEADER_SIZE;
50
+ while (offset < totalLength) {
51
+ if (seq > 255) {
52
+ throw new Error(`Payload requires more than 256 containers (seq=${seq}), ` +
53
+ `exceeding 8-bit sequence_number limit`);
54
+ }
55
+ const chunkEnd = offset + subsequentMaxPayload < totalLength ? offset + subsequentMaxPayload : totalLength;
56
+ const chunk = payload.slice(offset, chunkEnd);
57
+ containers.push(new container_1.Container({
58
+ transactionId,
59
+ sequenceNumber: seq,
60
+ containerType: containerTypes_1.ContainerType.SUBSEQUENT,
61
+ payload: chunk,
62
+ }));
63
+ offset += chunk.length;
64
+ seq++;
65
+ }
66
+ return containers;
67
+ }
68
+ }
69
+ exports.ContainerSplitter = ContainerSplitter;
70
+ //# sourceMappingURL=containerSplitter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerSplitter.js","sourceRoot":"","sources":["../src/containerSplitter.ts"],"names":[],"mappings":";AAAA,8CAA8C;;;AAE9C,2CAAwC;AACxC,qDAK0B;AAE1B,uDAAuD;AACvD,MAAa,iBAAiB;IAI5B,YAAY,GAAG,GAAG,GAAG;QAFb,wBAAmB,GAAG,CAAC,CAAC;QAG9B,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC;IAClB,CAAC;IAED,wDAAwD;IACxD,IAAI,YAAY;QACd,OAAO,IAAI,CAAC,IAAI,GAAG,6BAAY,CAAC;IAClC,CAAC;IAED,+DAA+D;IAC/D,iBAAiB;QACf,MAAM,GAAG,GAAG,IAAI,CAAC,mBAAmB,CAAC;QACrC,IAAI,CAAC,mBAAmB,GAAG,CAAC,IAAI,CAAC,mBAAmB,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC;QACjE,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,OAAmB,EAAE,aAAsB;QAC/C,aAAa,GAAG,aAAa,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAE1D,MAAM,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;QACnC,IAAI,WAAW,GAAG,KAAK,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,sBAAsB,WAAW,UAAU,CAAC,CAAC;QAC/D,CAAC;QAED,MAAM,UAAU,GAAgB,EAAE,CAAC;QAEnC,kBAAkB;QAClB,MAAM,eAAe,GAAG,IAAI,CAAC,YAAY,GAAG,kCAAiB,CAAC;QAC9D,MAAM,QAAQ,GAAG,eAAe,GAAG,WAAW,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,WAAW,CAAC;QAC/E,MAAM,YAAY,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC;QAChD,UAAU,CAAC,IAAI,CACb,IAAI,qBAAS,CAAC;YACZ,aAAa;YACb,cAAc,EAAE,CAAC;YACjB,aAAa,EAAE,8BAAa,CAAC,KAAK;YAClC,WAAW;YACX,OAAO,EAAE,YAAY;SACtB,CAAC,CACH,CAAC;QAEF,IAAI,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC;QACjC,IAAI,GAAG,GAAG,CAAC,CAAC;QAEZ,wBAAwB;QACxB,MAAM,oBAAoB,GAAG,IAAI,CAAC,YAAY,GAAG,uCAAsB,CAAC;QACxE,OAAO,MAAM,GAAG,WAAW,EAAE,CAAC;YAC5B,IAAI,GAAG,GAAG,GAAG,EAAE,CAAC;gBACd,MAAM,IAAI,KAAK,CACb,kDAAkD,GAAG,KAAK;oBACxD,uCAAuC,CAC1C,CAAC;YACJ,CAAC;YACD,MAAM,QAAQ,GACZ,MAAM,GAAG,oBAAoB,GAAG,WAAW,CAAC,CAAC,CAAC,MAAM,GAAG,oBAAoB,CAAC,CAAC,CAAC,WAAW,CAAC;YAC5F,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAC9C,UAAU,CAAC,IAAI,CACb,IAAI,qBAAS,CAAC;gBACZ,aAAa;gBACb,cAAc,EAAE,GAAG;gBACnB,aAAa,EAAE,8BAAa,CAAC,UAAU;gBACvC,OAAO,EAAE,KAAK;aACf,CAAC,CACH,CAAC;YACF,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC;YACvB,GAAG,EAAE,CAAC;QACR,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF;AA9ED,8CA8EC"}
@@ -0,0 +1,28 @@
1
+ /** Container type field (2 bits in flags byte). */
2
+ export declare enum ContainerType {
3
+ FIRST = 0,
4
+ SUBSEQUENT = 1,
5
+ CONTROL = 3
6
+ }
7
+ export declare function containerTypeFromValue(v: number): ContainerType;
8
+ /** Control command field (4 bits in flags byte). */
9
+ export declare enum ControlCmd {
10
+ NONE = 0,
11
+ TIMEOUT = 1,
12
+ STREAM_END_C2P = 2,
13
+ STREAM_END_P2C = 3,
14
+ CAPABILITIES = 4,
15
+ ERROR = 5,
16
+ KEY_EXCHANGE = 6
17
+ }
18
+ export declare function controlCmdFromValue(v: number): ControlCmd;
19
+ export declare const BLERPC_ERROR_RESPONSE_TOO_LARGE = 1;
20
+ export declare const BLERPC_ERROR_BUSY = 2;
21
+ export declare const CAPABILITY_FLAG_ENCRYPTION_SUPPORTED = 1;
22
+ /** txnId(1) + seq(1) + flags(1) + totalLen(2) + payloadLen(1) */
23
+ export declare const FIRST_HEADER_SIZE = 6;
24
+ /** txnId(1) + seq(1) + flags(1) + payloadLen(1) */
25
+ export declare const SUBSEQUENT_HEADER_SIZE = 4;
26
+ /** txnId(1) + seq(1) + flags(1) + payloadLen(1) */
27
+ export declare const CONTROL_HEADER_SIZE = 4;
28
+ export declare const ATT_OVERHEAD = 3;
@@ -0,0 +1,71 @@
1
+ "use strict";
2
+ // Container types, control commands, and protocol constants for blerpc.
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.ATT_OVERHEAD = exports.CONTROL_HEADER_SIZE = exports.SUBSEQUENT_HEADER_SIZE = exports.FIRST_HEADER_SIZE = exports.CAPABILITY_FLAG_ENCRYPTION_SUPPORTED = exports.BLERPC_ERROR_BUSY = exports.BLERPC_ERROR_RESPONSE_TOO_LARGE = exports.ControlCmd = exports.ContainerType = void 0;
5
+ exports.containerTypeFromValue = containerTypeFromValue;
6
+ exports.controlCmdFromValue = controlCmdFromValue;
7
+ /** Container type field (2 bits in flags byte). */
8
+ var ContainerType;
9
+ (function (ContainerType) {
10
+ ContainerType[ContainerType["FIRST"] = 0] = "FIRST";
11
+ ContainerType[ContainerType["SUBSEQUENT"] = 1] = "SUBSEQUENT";
12
+ ContainerType[ContainerType["CONTROL"] = 3] = "CONTROL";
13
+ })(ContainerType || (exports.ContainerType = ContainerType = {}));
14
+ function containerTypeFromValue(v) {
15
+ switch (v) {
16
+ case 0x00:
17
+ return ContainerType.FIRST;
18
+ case 0x01:
19
+ return ContainerType.SUBSEQUENT;
20
+ case 0x03:
21
+ return ContainerType.CONTROL;
22
+ default:
23
+ throw new Error(`Unknown ContainerType: ${v}`);
24
+ }
25
+ }
26
+ /** Control command field (4 bits in flags byte). */
27
+ var ControlCmd;
28
+ (function (ControlCmd) {
29
+ ControlCmd[ControlCmd["NONE"] = 0] = "NONE";
30
+ ControlCmd[ControlCmd["TIMEOUT"] = 1] = "TIMEOUT";
31
+ ControlCmd[ControlCmd["STREAM_END_C2P"] = 2] = "STREAM_END_C2P";
32
+ ControlCmd[ControlCmd["STREAM_END_P2C"] = 3] = "STREAM_END_P2C";
33
+ ControlCmd[ControlCmd["CAPABILITIES"] = 4] = "CAPABILITIES";
34
+ ControlCmd[ControlCmd["ERROR"] = 5] = "ERROR";
35
+ ControlCmd[ControlCmd["KEY_EXCHANGE"] = 6] = "KEY_EXCHANGE";
36
+ })(ControlCmd || (exports.ControlCmd = ControlCmd = {}));
37
+ function controlCmdFromValue(v) {
38
+ switch (v) {
39
+ case 0x0:
40
+ return ControlCmd.NONE;
41
+ case 0x1:
42
+ return ControlCmd.TIMEOUT;
43
+ case 0x2:
44
+ return ControlCmd.STREAM_END_C2P;
45
+ case 0x3:
46
+ return ControlCmd.STREAM_END_P2C;
47
+ case 0x4:
48
+ return ControlCmd.CAPABILITIES;
49
+ case 0x5:
50
+ return ControlCmd.ERROR;
51
+ case 0x6:
52
+ return ControlCmd.KEY_EXCHANGE;
53
+ default:
54
+ throw new Error(`Unknown ControlCmd: ${v}`);
55
+ }
56
+ }
57
+ // Error codes for ControlCmd.ERROR
58
+ exports.BLERPC_ERROR_RESPONSE_TOO_LARGE = 0x01;
59
+ exports.BLERPC_ERROR_BUSY = 0x02;
60
+ // Capabilities flags (bit field)
61
+ exports.CAPABILITY_FLAG_ENCRYPTION_SUPPORTED = 0x0001;
62
+ // Header sizes
63
+ /** txnId(1) + seq(1) + flags(1) + totalLen(2) + payloadLen(1) */
64
+ exports.FIRST_HEADER_SIZE = 6;
65
+ /** txnId(1) + seq(1) + flags(1) + payloadLen(1) */
66
+ exports.SUBSEQUENT_HEADER_SIZE = 4;
67
+ /** txnId(1) + seq(1) + flags(1) + payloadLen(1) */
68
+ exports.CONTROL_HEADER_SIZE = 4;
69
+ // ATT header bytes subtracted from MTU
70
+ exports.ATT_OVERHEAD = 3;
71
+ //# sourceMappingURL=containerTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"containerTypes.js","sourceRoot":"","sources":["../src/containerTypes.ts"],"names":[],"mappings":";AAAA,wEAAwE;;;AASxE,wDAWC;AAaD,kDAmBC;AAlDD,mDAAmD;AACnD,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,mDAAY,CAAA;IACZ,6DAAiB,CAAA;IACjB,uDAAc,CAAA;AAChB,CAAC,EAJW,aAAa,6BAAb,aAAa,QAIxB;AAED,SAAgB,sBAAsB,CAAC,CAAS;IAC9C,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,IAAI;YACP,OAAO,aAAa,CAAC,KAAK,CAAC;QAC7B,KAAK,IAAI;YACP,OAAO,aAAa,CAAC,UAAU,CAAC;QAClC,KAAK,IAAI;YACP,OAAO,aAAa,CAAC,OAAO,CAAC;QAC/B;YACE,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC,EAAE,CAAC,CAAC;IACnD,CAAC;AACH,CAAC;AAED,oDAAoD;AACpD,IAAY,UAQX;AARD,WAAY,UAAU;IACpB,2CAAU,CAAA;IACV,iDAAa,CAAA;IACb,+DAAoB,CAAA;IACpB,+DAAoB,CAAA;IACpB,2DAAkB,CAAA;IAClB,6CAAW,CAAA;IACX,2DAAkB,CAAA;AACpB,CAAC,EARW,UAAU,0BAAV,UAAU,QAQrB;AAED,SAAgB,mBAAmB,CAAC,CAAS;IAC3C,QAAQ,CAAC,EAAE,CAAC;QACV,KAAK,GAAG;YACN,OAAO,UAAU,CAAC,IAAI,CAAC;QACzB,KAAK,GAAG;YACN,OAAO,UAAU,CAAC,OAAO,CAAC;QAC5B,KAAK,GAAG;YACN,OAAO,UAAU,CAAC,cAAc,CAAC;QACnC,KAAK,GAAG;YACN,OAAO,UAAU,CAAC,cAAc,CAAC;QACnC,KAAK,GAAG;YACN,OAAO,UAAU,CAAC,YAAY,CAAC;QACjC,KAAK,GAAG;YACN,OAAO,UAAU,CAAC,KAAK,CAAC;QAC1B,KAAK,GAAG;YACN,OAAO,UAAU,CAAC,YAAY,CAAC;QACjC;YACE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,EAAE,CAAC,CAAC;IAChD,CAAC;AACH,CAAC;AAED,mCAAmC;AACtB,QAAA,+BAA+B,GAAG,IAAI,CAAC;AACvC,QAAA,iBAAiB,GAAG,IAAI,CAAC;AAEtC,iCAAiC;AACpB,QAAA,oCAAoC,GAAG,MAAM,CAAC;AAE3D,eAAe;AACf,iEAAiE;AACpD,QAAA,iBAAiB,GAAG,CAAC,CAAC;AACnC,mDAAmD;AACtC,QAAA,sBAAsB,GAAG,CAAC,CAAC;AACxC,mDAAmD;AACtC,QAAA,mBAAmB,GAAG,CAAC,CAAC;AAErC,uCAAuC;AAC1B,QAAA,YAAY,GAAG,CAAC,CAAC"}
@@ -0,0 +1,35 @@
1
+ import { Container } from "./container";
2
+ /** Create a timeout request control container (Central -> Peripheral). */
3
+ export declare function makeTimeoutRequest(transactionId: number, sequenceNumber?: number): Container;
4
+ /** Create a timeout response control container (Peripheral -> Central). */
5
+ export declare function makeTimeoutResponse(transactionId: number, timeoutMs: number, sequenceNumber?: number): Container;
6
+ /** Create stream end container (Central -> Peripheral). */
7
+ export declare function makeStreamEndC2P(transactionId: number, sequenceNumber?: number): Container;
8
+ /** Create stream end container (Peripheral -> Central). */
9
+ export declare function makeStreamEndP2C(transactionId: number, sequenceNumber?: number): Container;
10
+ /**
11
+ * Create a capabilities request control container (Central -> Peripheral).
12
+ *
13
+ * 6-byte payload: [max_req:u16LE][max_resp:u16LE][flags:u16LE]
14
+ */
15
+ export declare function makeCapabilitiesRequest(transactionId: number, options?: {
16
+ maxRequestPayloadSize?: number;
17
+ maxResponsePayloadSize?: number;
18
+ flags?: number;
19
+ sequenceNumber?: number;
20
+ }): Container;
21
+ /**
22
+ * Create a capabilities response control container (Peripheral -> Central).
23
+ *
24
+ * 6-byte payload: [max_req:u16LE][max_resp:u16LE][flags:u16LE]
25
+ */
26
+ export declare function makeCapabilitiesResponse(transactionId: number, options: {
27
+ maxRequestPayloadSize: number;
28
+ maxResponsePayloadSize: number;
29
+ flags?: number;
30
+ sequenceNumber?: number;
31
+ }): Container;
32
+ /** Create an error control container (Peripheral -> Central). */
33
+ export declare function makeErrorResponse(transactionId: number, errorCode: number, sequenceNumber?: number): Container;
34
+ /** Create a key exchange control container. */
35
+ export declare function makeKeyExchange(transactionId: number, payload: Uint8Array, sequenceNumber?: number): Container;