webserial-core 2.0.3 → 2.1.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/dist/parsers/CCTalkParser.d.ts +20 -0
- package/dist/parsers/DelimiterParser.d.ts +28 -3
- package/dist/parsers/InterByteTimeoutParser.d.ts +27 -0
- package/dist/parsers/PacketLengthParser.d.ts +36 -0
- package/dist/parsers/ReadlineParser.d.ts +28 -0
- package/dist/parsers/ReadyParser.d.ts +29 -0
- package/dist/parsers/RegexParser.d.ts +26 -0
- package/dist/parsers/SlipParser.d.ts +58 -0
- package/dist/parsers/SpacePacketParser.d.ts +48 -0
- package/dist/parsers/index.d.ts +9 -1
- package/dist/webserial-core.cjs +2 -1
- package/dist/webserial-core.mjs +360 -74
- package/dist/webserial-core.umd.js +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Creates a ccTalk parser that emits complete ccTalk packets as `Uint8Array`.
|
|
4
|
+
*
|
|
5
|
+
* @param maxDelayBetweenBytesMs - Maximum allowed silence between bytes before
|
|
6
|
+
* the buffer is discarded. Defaults to `50`.
|
|
7
|
+
* @returns A {@link SerialParser} that emits `Uint8Array` values.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { AbstractSerialDevice, ccTalk } from 'webserial-core';
|
|
12
|
+
*
|
|
13
|
+
* class CoinAcceptor extends AbstractSerialDevice<Uint8Array> {
|
|
14
|
+
* constructor() {
|
|
15
|
+
* super({ baudRate: 9600, parser: ccTalk(100) });
|
|
16
|
+
* }
|
|
17
|
+
* }
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare function ccTalk(maxDelayBetweenBytesMs?: number): SerialParser<Uint8Array>;
|
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface DelimiterOptions {
|
|
3
|
+
/** Whether to include the delimiter at the end of each emitted value. Defaults to false. */
|
|
4
|
+
includeDelimiter?: boolean;
|
|
5
|
+
}
|
|
2
6
|
/**
|
|
3
|
-
* Creates a delimiter-based parser that splits the byte stream
|
|
4
|
-
*
|
|
7
|
+
* Creates a delimiter-based parser that splits the byte stream on the given
|
|
8
|
+
* delimiter and emits string messages.
|
|
5
9
|
*
|
|
6
10
|
* Commonly used with `'\n'` for Arduino `Serial.println()` output.
|
|
7
11
|
*
|
|
8
12
|
* @param char - The delimiter string (e.g. `'\n'`, `'\r\n'`, `';'`).
|
|
13
|
+
* @param options - Optional configuration.
|
|
9
14
|
* @returns A {@link SerialParser} that emits `string` values.
|
|
10
15
|
*
|
|
11
16
|
* @example
|
|
@@ -19,4 +24,24 @@ import { SerialParser } from '../types/index.js';
|
|
|
19
24
|
* }
|
|
20
25
|
* ```
|
|
21
26
|
*/
|
|
22
|
-
export declare function delimiter(char: string): SerialParser<string>;
|
|
27
|
+
export declare function delimiter(char: string, options?: DelimiterOptions): SerialParser<string>;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a delimiter-based parser that splits the byte stream on the given
|
|
30
|
+
* binary delimiter and emits Uint8Array chunks.
|
|
31
|
+
*
|
|
32
|
+
* @param char - The delimiter as a `Uint8Array` or `number[]`.
|
|
33
|
+
* @param options - Optional configuration.
|
|
34
|
+
* @returns A {@link SerialParser} that emits `Uint8Array` values.
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { AbstractSerialDevice, delimiter } from 'webserial-core';
|
|
39
|
+
*
|
|
40
|
+
* class MyDevice extends AbstractSerialDevice<Uint8Array> {
|
|
41
|
+
* constructor() {
|
|
42
|
+
* super({ baudRate: 9600, parser: delimiter(new Uint8Array([0x0d, 0x0a])) });
|
|
43
|
+
* }
|
|
44
|
+
* }
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function delimiter(char: Uint8Array | number[], options?: DelimiterOptions): SerialParser<Uint8Array>;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface InterByteTimeoutOptions {
|
|
3
|
+
/** Period of silence in milliseconds after which buffered data is emitted. */
|
|
4
|
+
interval: number;
|
|
5
|
+
/** Maximum number of bytes to buffer before forcing an emit. Defaults to 65536. */
|
|
6
|
+
maxBufferSize?: number;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates an inter-byte timeout parser that buffers incoming bytes and emits
|
|
10
|
+
* the accumulated data after a silence period of at least `interval` ms, or
|
|
11
|
+
* when the buffer reaches `maxBufferSize`.
|
|
12
|
+
*
|
|
13
|
+
* @param options - Configuration options.
|
|
14
|
+
* @returns A {@link SerialParser} that emits `Uint8Array` values.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* import { AbstractSerialDevice, interByteTimeout } from 'webserial-core';
|
|
19
|
+
*
|
|
20
|
+
* class MyDevice extends AbstractSerialDevice<Uint8Array> {
|
|
21
|
+
* constructor() {
|
|
22
|
+
* super({ baudRate: 9600, parser: interByteTimeout({ interval: 30 }) });
|
|
23
|
+
* }
|
|
24
|
+
* }
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function interByteTimeout(options: InterByteTimeoutOptions): SerialParser<Uint8Array>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface PacketLengthOptions {
|
|
3
|
+
/** Delimiter byte that marks the start of a packet. Defaults to `0xAA`. */
|
|
4
|
+
delimiter?: number;
|
|
5
|
+
/** Total overhead bytes in the packet (delimiter + length field(s) + any footer). Defaults to `2`. */
|
|
6
|
+
packetOverhead?: number;
|
|
7
|
+
/** Number of consecutive bytes that encode the payload length. Defaults to `1`. */
|
|
8
|
+
lengthBytes?: number;
|
|
9
|
+
/** Byte offset from the delimiter to the first length byte. Defaults to `1`. */
|
|
10
|
+
lengthOffset?: number;
|
|
11
|
+
/** Maximum allowed payload length. Packets exceeding this are discarded. Defaults to `0xFF`. */
|
|
12
|
+
maxLen?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Creates a packet-length parser that buffers bytes, locates the delimiter,
|
|
16
|
+
* reads the embedded length field, and emits complete packets as `Uint8Array`.
|
|
17
|
+
*
|
|
18
|
+
* @param options - Configuration options.
|
|
19
|
+
* @returns A {@link SerialParser} that emits `Uint8Array` values.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```ts
|
|
23
|
+
* import { AbstractSerialDevice, packetLength } from 'webserial-core';
|
|
24
|
+
*
|
|
25
|
+
* // Packets: [0xBC][0x00][len0][len1][cargo...][footer0][footer1]
|
|
26
|
+
* class MyDevice extends AbstractSerialDevice<Uint8Array> {
|
|
27
|
+
* constructor() {
|
|
28
|
+
* super({
|
|
29
|
+
* baudRate: 115200,
|
|
30
|
+
* parser: packetLength({ delimiter: 0xbc, packetOverhead: 5, lengthBytes: 2, lengthOffset: 2 }),
|
|
31
|
+
* });
|
|
32
|
+
* }
|
|
33
|
+
* }
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare function packetLength(options?: PacketLengthOptions): SerialParser<Uint8Array>;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface ReadlineOptions {
|
|
3
|
+
/** Line delimiter. Defaults to `'\n'`. Accepts a string, Uint8Array, or number[]. */
|
|
4
|
+
delimiter?: string | Uint8Array | number[];
|
|
5
|
+
/** Include the delimiter at the end of each emitted string. Defaults to false. */
|
|
6
|
+
includeDelimiter?: boolean;
|
|
7
|
+
/** Text encoding used to decode bytes. Defaults to `'utf-8'`. */
|
|
8
|
+
encoding?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Creates a readline parser that splits the byte stream on a newline (or
|
|
12
|
+
* custom delimiter) and emits each line as a decoded string.
|
|
13
|
+
*
|
|
14
|
+
* @param options - Optional configuration.
|
|
15
|
+
* @returns A {@link SerialParser} that emits `string` values.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```ts
|
|
19
|
+
* import { AbstractSerialDevice, readline } from 'webserial-core';
|
|
20
|
+
*
|
|
21
|
+
* class MyDevice extends AbstractSerialDevice<string> {
|
|
22
|
+
* constructor() {
|
|
23
|
+
* super({ baudRate: 9600, parser: readline() });
|
|
24
|
+
* }
|
|
25
|
+
* }
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
export declare function readline(options?: ReadlineOptions): SerialParser<string>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface ReadyParserOptions {
|
|
3
|
+
/** Byte sequence that signals the device is ready. Accepts a string, Uint8Array, or number[]. */
|
|
4
|
+
delimiter: string | Uint8Array | number[];
|
|
5
|
+
/** Called once when the ready sequence is detected. */
|
|
6
|
+
onReady?: () => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a ready parser that waits for the given delimiter sequence and then
|
|
10
|
+
* emits all subsequent data as raw `Uint8Array` chunks.
|
|
11
|
+
*
|
|
12
|
+
* @param options - Configuration options including the ready delimiter.
|
|
13
|
+
* @returns A {@link SerialParser} that emits `Uint8Array` values.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { AbstractSerialDevice, readyParser } from 'webserial-core';
|
|
18
|
+
*
|
|
19
|
+
* class MyDevice extends AbstractSerialDevice<Uint8Array> {
|
|
20
|
+
* constructor() {
|
|
21
|
+
* super({
|
|
22
|
+
* baudRate: 9600,
|
|
23
|
+
* parser: readyParser({ delimiter: 'READY\n', onReady: () => console.log('device ready') }),
|
|
24
|
+
* });
|
|
25
|
+
* }
|
|
26
|
+
* }
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export declare function readyParser(options: ReadyParserOptions): SerialParser<Uint8Array>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface RegexParserOptions {
|
|
3
|
+
/** Regular expression used to split the incoming text stream. */
|
|
4
|
+
regex: RegExp | string;
|
|
5
|
+
/** Text encoding used to decode bytes. Defaults to `'utf-8'`. */
|
|
6
|
+
encoding?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Creates a regex parser that decodes incoming bytes and emits string segments
|
|
10
|
+
* split by the provided regular expression.
|
|
11
|
+
*
|
|
12
|
+
* @param options - Configuration options.
|
|
13
|
+
* @returns A {@link SerialParser} that emits `string` values.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* import { AbstractSerialDevice, regexParser } from 'webserial-core';
|
|
18
|
+
*
|
|
19
|
+
* class MyDevice extends AbstractSerialDevice<string> {
|
|
20
|
+
* constructor() {
|
|
21
|
+
* super({ baudRate: 9600, parser: regexParser({ regex: /[\r\n]+/ }) });
|
|
22
|
+
* }
|
|
23
|
+
* }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare function regexParser(options: RegexParserOptions): SerialParser<string>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface SlipOptions {
|
|
3
|
+
/** Custom START byte. When set, each packet must begin with this byte. */
|
|
4
|
+
START?: number;
|
|
5
|
+
/** Escape byte for START. Defaults to `0xDB` (same as ESC). */
|
|
6
|
+
ESC_START?: number;
|
|
7
|
+
/** Escape byte. Defaults to `0xDB`. */
|
|
8
|
+
ESC?: number;
|
|
9
|
+
/** Packet end byte. Defaults to `0xC0`. */
|
|
10
|
+
END?: number;
|
|
11
|
+
/** ESC sequence for END byte. Defaults to `0xDC`. */
|
|
12
|
+
ESC_END?: number;
|
|
13
|
+
/** ESC sequence for ESC byte. Defaults to `0xDD`. */
|
|
14
|
+
ESC_ESC?: number;
|
|
15
|
+
/**
|
|
16
|
+
* Adds an END byte at the beginning of each packet (Bluetooth quirk).
|
|
17
|
+
* Only applies to `slipEncode`. Defaults to false.
|
|
18
|
+
*/
|
|
19
|
+
bluetoothQuirk?: boolean;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Creates a SLIP decoder parser that strips framing and emits each decoded
|
|
23
|
+
* packet as a `Uint8Array`.
|
|
24
|
+
*
|
|
25
|
+
* @param options - Optional custom framing byte values.
|
|
26
|
+
* @returns A {@link SerialParser} that emits `Uint8Array` values.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* import { AbstractSerialDevice, slipDecoder } from 'webserial-core';
|
|
31
|
+
*
|
|
32
|
+
* class MyDevice extends AbstractSerialDevice<Uint8Array> {
|
|
33
|
+
* constructor() {
|
|
34
|
+
* super({ baudRate: 115200, parser: slipDecoder() });
|
|
35
|
+
* }
|
|
36
|
+
* }
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function slipDecoder(options?: SlipOptions): SerialParser<Uint8Array>;
|
|
40
|
+
/**
|
|
41
|
+
* SLIP-encodes a single outgoing packet.
|
|
42
|
+
*
|
|
43
|
+
* Escapes all END and ESC bytes in `data`, then appends an END byte.
|
|
44
|
+
* If `options.bluetoothQuirk` is true, an additional END byte is prepended.
|
|
45
|
+
*
|
|
46
|
+
* @param data - Raw packet bytes to encode.
|
|
47
|
+
* @param options - Optional custom framing byte values.
|
|
48
|
+
* @returns A new `Uint8Array` containing the SLIP-encoded packet.
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```ts
|
|
52
|
+
* import { slipEncode } from 'webserial-core';
|
|
53
|
+
*
|
|
54
|
+
* const encoded = slipEncode(new Uint8Array([0x01, 0xC0, 0x02]));
|
|
55
|
+
* // device.send(encoded);
|
|
56
|
+
* ```
|
|
57
|
+
*/
|
|
58
|
+
export declare function slipEncode(data: Uint8Array, options?: SlipOptions): Uint8Array;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { SerialParser } from '../types/index.js';
|
|
2
|
+
export interface SpacePacketOptions {
|
|
3
|
+
/** Length in bytes of the Time Code Field in the secondary header. Defaults to 0. */
|
|
4
|
+
timeCodeFieldLength?: number;
|
|
5
|
+
/** Length in bytes of the Ancillary Data Field in the secondary header. Defaults to 0. */
|
|
6
|
+
ancillaryDataFieldLength?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface SpacePacketHeader {
|
|
9
|
+
versionNumber: number;
|
|
10
|
+
identification: {
|
|
11
|
+
apid: number;
|
|
12
|
+
secondaryHeader: number;
|
|
13
|
+
type: number;
|
|
14
|
+
};
|
|
15
|
+
sequenceControl: {
|
|
16
|
+
packetName: number;
|
|
17
|
+
sequenceFlags: number;
|
|
18
|
+
};
|
|
19
|
+
dataLength: number;
|
|
20
|
+
}
|
|
21
|
+
export interface SpacePacketSecondaryHeader {
|
|
22
|
+
timeCode?: string;
|
|
23
|
+
ancillaryData?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface SpacePacket {
|
|
26
|
+
header: SpacePacketHeader;
|
|
27
|
+
secondaryHeader?: SpacePacketSecondaryHeader;
|
|
28
|
+
data: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Creates a Space Packet Protocol parser that buffers bytes and emits a
|
|
32
|
+
* structured {@link SpacePacket} object for each complete packet received.
|
|
33
|
+
*
|
|
34
|
+
* @param options - Optional secondary-header field lengths.
|
|
35
|
+
* @returns A {@link SerialParser} that emits {@link SpacePacket} objects.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```ts
|
|
39
|
+
* import { AbstractSerialDevice, spacePacket } from 'webserial-core';
|
|
40
|
+
*
|
|
41
|
+
* class TelemetryDevice extends AbstractSerialDevice<SpacePacket> {
|
|
42
|
+
* constructor() {
|
|
43
|
+
* super({ baudRate: 115200, parser: spacePacket({ timeCodeFieldLength: 8 }) });
|
|
44
|
+
* }
|
|
45
|
+
* }
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function spacePacket(options?: SpacePacketOptions): SerialParser<SpacePacket>;
|
package/dist/parsers/index.d.ts
CHANGED
|
@@ -2,6 +2,14 @@
|
|
|
2
2
|
* @file parsers/index.ts
|
|
3
3
|
* Re-exports all built-in parser factories.
|
|
4
4
|
*/
|
|
5
|
-
export * from './
|
|
5
|
+
export * from './CCTalkParser.js';
|
|
6
6
|
export * from './DelimiterParser.js';
|
|
7
|
+
export * from './FixedLengthParser.js';
|
|
8
|
+
export * from './InterByteTimeoutParser.js';
|
|
9
|
+
export * from './PacketLengthParser.js';
|
|
7
10
|
export * from './RawParser.js';
|
|
11
|
+
export * from './ReadlineParser.js';
|
|
12
|
+
export * from './ReadyParser.js';
|
|
13
|
+
export * from './RegexParser.js';
|
|
14
|
+
export * from './SlipParser.js';
|
|
15
|
+
export * from './SpacePacketParser.js';
|
package/dist/webserial-core.cjs
CHANGED
|
@@ -1 +1,2 @@
|
|
|
1
|
-
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class{listeners={};on(e,t){return this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),this}off(e,t){return this.listeners[e]&&this.listeners[e].delete(t),this}emit(e,...t){let n=this.listeners[e];if(!n||n.size===0)return!1;for(let e of n)e(...t);return!0}},t=class{static instances=new Set;static portInstanceMap=new WeakMap;static getInstances(){return Array.from(this.instances)}static register(e){this.instances.add(e)}static unregister(e){this.instances.delete(e)}static isPortInUse(e,t){let n=this.portInstanceMap.get(e);return n!==void 0&&n!==t}static lockPort(e,t){this.portInstanceMap.set(e,t)}static unlockPort(e){this.portInstanceMap.delete(e)}},n=class{queue=[];isProcessing=!1;isPaused=!0;timeoutId=null;commandTimeout;onSend;onTimeout;constructor(e){this.commandTimeout=e.commandTimeout,this.onSend=e.onSend,this.onTimeout=e.onTimeout}get queueSize(){return this.queue.length}enqueue(e){this.queue.push(e),this.tryProcessNext()}advance(){this.clearCommandTimeout(),this.isProcessing=!1,this.tryProcessNext()}pause(){this.isPaused=!0,this.clearCommandTimeout(),this.isProcessing=!1}resume(){this.isPaused=!1,this.tryProcessNext()}clear(){this.queue=[],this.clearCommandTimeout(),this.isProcessing=!1}snapshot(){return[...this.queue]}restore(e){this.queue=[...e,...this.queue]}tryProcessNext(){if(this.isPaused||this.isProcessing||this.queue.length===0)return;this.isProcessing=!0;let e=this.queue.shift();this.commandTimeout>0&&(this.timeoutId=setTimeout(()=>{this.timeoutId=null,this.onTimeout(e),this.advance()},this.commandTimeout)),this.onSend(e).catch(()=>{this.advance()})}clearCommandTimeout(){this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}},r=class e extends Error{constructor(t){super(t),this.name=`SerialPortConflictError`,Object.setPrototypeOf(this,e.prototype)}},i=class e extends Error{constructor(t){super(t),this.name=`SerialPermissionError`,Object.setPrototypeOf(this,e.prototype)}},a=class e extends Error{constructor(t){super(t),this.name=`SerialTimeoutError`,Object.setPrototypeOf(this,e.prototype)}},o=class e extends Error{constructor(t){super(t),this.name=`SerialReadError`,Object.setPrototypeOf(this,e.prototype)}},s=class e extends Error{constructor(t){super(t),this.name=`SerialWriteError`,Object.setPrototypeOf(this,e.prototype)}},c=class r extends e{port=null;reader=null;writer=null;queue;options;isConnecting=!1;abortController=null;userInitiatedDisconnect=!1;reconnectTimerId=null;isHandshaking=!1;static customProvider=null;static polyfillOptions;constructor(e){super(),this.options={baudRate:e.baudRate,dataBits:e.dataBits??8,stopBits:e.stopBits??1,parity:e.parity??`none`,bufferSize:e.bufferSize??255,flowControl:e.flowControl??`none`,filters:e.filters??[],commandTimeout:e.commandTimeout??0,parser:e.parser,autoReconnect:e.autoReconnect??!1,autoReconnectInterval:e.autoReconnectInterval??1500,handshakeTimeout:e.handshakeTimeout??2e3,provider:e.provider,polyfillOptions:e.polyfillOptions},this.queue=new n({commandTimeout:this.options.commandTimeout,onSend:async e=>{await this.writeToPort(e),this.emit(`serial:sent`,e,this)},onTimeout:e=>{this.emit(`serial:timeout`,e,this)}}),this.on(`serial:data`,()=>{this.queue.advance()}),t.register(this)}async handshake(){return!0}async connect(){if(!this.isConnecting&&!this.port){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{let e=this.getSerial();if(!e)throw Error(`Web Serial API is not supported in this browser. Use AbstractSerialDevice.setProvider() to set a WebUSB polyfill.`);if(this.port=await this.findAndValidatePort(),!this.port){let t;try{t=await e.requestPort({filters:this.options.filters},this.options.polyfillOptions??r.polyfillOptions)}catch(e){throw e instanceof DOMException&&(e.name===`NotFoundError`||e.name===`SecurityError`||e.name===`AbortError`)?new i(e instanceof Error?e.message:String(e)):e instanceof Error?e:Error(String(e))}if(!await this.openAndHandshake(t))throw Error(`Handshake failed: the selected device did not respond correctly.`);this.port=t}this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){if(e instanceof i?this.emit(`serial:need-permission`,this):this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port){t.unlockPort(this.port);try{await this.port.close()}catch{}this.port=null}throw e}finally{this.isConnecting=!1}}}async disconnect(){this.port&&(this.userInitiatedDisconnect=!0,this.stopReconnecting(),await this.cleanupPort())}isConnected(){return!!(this.port&&this.port.connected&&this.port.readable&&this.port.writable)}isDisconnected(){return!this.isConnected()}async cleanupPort(){if(this.port){this.queue.pause(),this.abortController?.abort(),this.abortController=null;try{let e=this.reader,t=this.writer;if(this.reader=null,this.writer=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}if(t){try{await t.close()}catch{}try{t.releaseLock()}catch{}}try{await this.port.close()}catch{}}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this)}finally{this.port&&t.unlockPort(this.port),this.port=null,this.options.parser?.reset?.(),this.emit(`serial:disconnected`,this),!this.userInitiatedDisconnect&&this.options.autoReconnect&&this.startReconnecting(),this.userInitiatedDisconnect=!1}}}async forget(){await this.disconnect(),this.port&&typeof this.port.forget==`function`&&await this.port.forget(),t.unregister(this)}async send(e){let t;t=typeof e==`string`?new TextEncoder().encode(e):e,t.length>0&&this.queue.enqueue(t)}clearQueue(){this.queue.clear(),this.emit(`serial:queue-empty`,this)}async writeToPort(e){if(!this.port||!this.port.writable)throw new s(`Port not writable.`);this.writer=this.port.writable.getWriter();try{await this.writer.write(e)}catch(e){throw new s(e instanceof Error?e.message:String(e))}finally{this.writer.releaseLock(),this.writer=null}}async readLoop(){if(!(!this.port||!this.port.readable)&&!this.reader){this.reader=this.port.readable.getReader();try{for(;;){let{value:e,done:t}=await this.reader.read();if(t)break;e&&(this.options.parser?this.options.parser.parse(e,e=>{this.emit(`serial:data`,e,this)}):this.emit(`serial:data`,e,this))}}catch(e){if(this.port)throw new o(e instanceof Error?e.message:String(e))}finally{if(this.reader){try{this.reader.releaseLock()}catch{}this.reader=null}}}}async openAndHandshake(e){let n=this;if(t.isPortInUse(e,n))return!1;t.lockPort(e,n);try{await e.open({baudRate:this.options.baudRate,dataBits:this.options.dataBits,stopBits:this.options.stopBits,parity:this.options.parity,bufferSize:this.options.bufferSize,flowControl:this.options.flowControl})}catch(n){throw t.unlockPort(e),n instanceof Error?n:Error(String(n))}this.port=e,this.abortController=new AbortController;let r=this.queue.snapshot();this.isHandshaking=!0,this.readLoop().catch(e=>{!this.isHandshaking&&this.port&&(this.emit(`serial:error`,e,this),this.cleanupPort())}),this.queue.resume();try{let t=await this.runHandshakeWithTimeout();return this.isHandshaking=!1,t?(this.queue.pause(),this.queue.clear(),this.queue.restore(r),this.options.parser?.reset?.(),!0):(await this.teardownHandshake(e,r),!1)}catch{return this.isHandshaking=!1,await this.teardownHandshake(e,r),!1}}async teardownHandshake(e,n){this.queue.pause(),this.queue.clear(),this.queue.restore(n),await this.stopReader(),this.port=null,this.abortController=null,this.options.parser?.reset?.();try{await e.close()}catch{}t.unlockPort(e)}async stopReader(){let e=this.reader;if(this.reader=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}}async runHandshakeWithTimeout(){let e=this.options.handshakeTimeout??2e3;return Promise.race([this.handshake(),new Promise(t=>setTimeout(()=>t(!1),e))])}async findAndValidatePort(){let e=this.getSerial();if(!e)return null;let n=await e.getPorts(this.options.polyfillOptions??r.polyfillOptions);if(n.length===0)return null;let i=this.options.filters??[],a=this;for(let e of n)if(!t.isPortInUse(e,a)){if(i.length>0){let t=e.getInfo();if(!i.some(e=>{let n=e.usbVendorId===void 0||e.usbVendorId===t.usbVendorId,r=e.usbProductId===void 0||e.usbProductId===t.usbProductId;return n&&r}))continue}try{if(await this.openAndHandshake(e))return e}catch{}}return null}startReconnecting(){this.reconnectTimerId||=(this.emit(`serial:reconnecting`,this),setInterval(async()=>{if(this.port||this.isConnecting){this.stopReconnecting();return}try{let e=await this.findAndValidatePort();e&&(this.stopReconnecting(),await this.reconnect(e))}catch{}},this.options.autoReconnectInterval))}stopReconnecting(){this.reconnectTimerId&&=(clearInterval(this.reconnectTimerId),null)}async reconnect(e){if(!(this.isConnecting||this.port)){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{this.port=e,this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port&&=(t.unlockPort(this.port),null),this.options.autoReconnect&&this.startReconnecting()}finally{this.isConnecting=!1}}}static getInstances(){return t.getInstances()}static async connectAll(){let e=t.getInstances();for(let t of e)try{await t.connect()}catch{}}static setProvider(e,t){r.customProvider=e,r.polyfillOptions=t}getSerial(){return this.options.provider?this.options.provider:r.customProvider?r.customProvider:typeof navigator<`u`&&navigator.serial?navigator.serial:null}};function l(e){if(e<=0)throw Error(`FixedLengthParser: length must be greater than 0`);let t=new Uint8Array;return{parse(n,r){let i=new Uint8Array(t.length+n.length);for(i.set(t),i.set(n,t.length),t=i;t.length>=e;)r(t.slice(0,e)),t=t.slice(e)},reset(){t=new Uint8Array}}}function u(e){let t=``,n=new TextDecoder;return{parse(r,i){t+=n.decode(r,{stream:!0});let a;for(;(a=t.indexOf(e))!==-1;)i(t.slice(0,a)),t=t.slice(a+e.length)},reset(){t=``,n=new TextDecoder}}}function d(){return{parse(e,t){t(e)},reset(){}}}var f=32,p=34,m=0,h=30,g=3,_=7,v=1,y=0,b=771,x=768,S=255,C=8,w=`none`,T=1,E=[16,8,7,6,5],D=[1,2],O=[`none`,`even`,`odd`],k=[`none`,`odd`,`even`],A=[1,1.5,2],j={usbControlInterfaceClass:2,usbTransferInterfaceClass:10,protocol:void 0};function M(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces)if(e.alternates[0]?.interfaceClass===t)return e;return null}function N(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces){let n=e.alternates[0];if(!n||n.interfaceClass!==t)continue;let r=n.endpoints.some(e=>e.direction===`in`),i=n.endpoints.some(e=>e.direction===`out`);if(r&&i)return e}return null}function P(e,t){let n=e.alternates[0];if(n){for(let e of n.endpoints)if(e.direction===t)return e}throw TypeError(`Interface ${e.interfaceNumber} does not have an ${t} endpoint.`)}function F(e,t){return t===2?`cdc_acm`:e.vendorId===4292?`cp210x`:`none`}var I=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}pull(e){(async()=>{let t=this.endpoint_.packetSize;try{let n=await this.device_.transferIn(this.endpoint_.endpointNumber,t);if(n.status!==`ok`){e.error(`USB error: ${n.status}`),this.onError_();return}if(n.data?.buffer&&n.data.byteLength>0){let t=new Uint8Array(n.data.buffer,n.data.byteOffset,n.data.byteLength);t.length>0&&e.enqueue(t)}}catch(t){e.error(String(t)),this.onError_()}})()}},L=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}async write(e,t){try{let n=await this.device_.transferOut(this.endpoint_.endpointNumber,e.buffer);n.status!==`ok`&&(t.error(n.status),this.onError_())}catch(e){t.error(String(e)),this.onError_()}}},R=class{device_;protocol_;controlInterface_;transferInterface_;inEndpoint_;outEndpoint_;serialOptions_;readable_=null;writable_=null;cdcOutputSignals_={dataTerminalReady:!1,requestToSend:!1,break:!1};constructor(e,t){this.device_=e;let n={...j,...t};this.protocol_=n.protocol??F(e,n.usbControlInterfaceClass);let r=n.usbControlInterfaceClass,i=n.usbTransferInterfaceClass;if(r===i){let t=N(e,i);if(!t)throw TypeError(`Unable to find interface with class ${i} that has both IN and OUT endpoints.`);this.controlInterface_=t,this.transferInterface_=t}else{let t=M(e,r);if(!t)throw TypeError(`Unable to find control interface with class ${r}.`);let n=N(e,i)??M(e,i);if(!n)throw TypeError(`Unable to find transfer interface with class ${i}.`);this.controlInterface_=t,this.transferInterface_=n}this.inEndpoint_=P(this.transferInterface_,`in`),this.outEndpoint_=P(this.transferInterface_,`out`)}get readable(){return!this.readable_&&this.device_.opened&&(this.readable_=new ReadableStream(new I(this.device_,this.inEndpoint_,()=>{this.readable_=null}),{highWaterMark:this.serialOptions_?.bufferSize??S})),this.readable_}get writable(){return!this.writable_&&this.device_.opened&&(this.writable_=new WritableStream(new L(this.device_,this.outEndpoint_,()=>{this.writable_=null}),new ByteLengthQueuingStrategy({highWaterMark:this.serialOptions_?.bufferSize??S}))),this.writable_}async open(e){this.serialOptions_=e,this.validateOptions();try{switch(await this.device_.open(),this.device_.configuration===null&&await this.device_.selectConfiguration(1),await this.device_.claimInterface(this.controlInterface_.interfaceNumber),this.controlInterface_!==this.transferInterface_&&await this.device_.claimInterface(this.transferInterface_.interfaceNumber),this.protocol_){case`cdc_acm`:await this.cdcInit();break;case`cp210x`:await this.cp210xInit();break;case`none`:break}}catch(e){throw this.device_.opened&&await this.device_.close(),Error(`Error setting up device: `+(e instanceof Error?e.message:String(e)),{cause:e})}}async close(){let e=[];if(this.readable_&&e.push(this.readable_.cancel()),this.writable_&&e.push(this.writable_.abort()),await Promise.all(e),this.readable_=null,this.writable_=null,this.device_.opened){switch(this.protocol_){case`cdc_acm`:await this.cdcSetSignals({dataTerminalReady:!1,requestToSend:!1});break;case`cp210x`:await this.cp210xDeinit();break}await this.device_.close()}}async forget(){return this.device_.forget()}getInfo(){return{usbVendorId:this.device_.vendorId,usbProductId:this.device_.productId}}async cdcInit(){await this.cdcSetLineCoding(),await this.cdcSetSignals({dataTerminalReady:!0})}async cdcSetSignals(e){if(this.cdcOutputSignals_={...this.cdcOutputSignals_,...e},e.dataTerminalReady!==void 0||e.requestToSend!==void 0){let e=!!this.cdcOutputSignals_.dataTerminalReady|(this.cdcOutputSignals_.requestToSend?2:0);await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:p,value:e,index:this.controlInterface_.interfaceNumber})}}async cdcSetLineCoding(){let e=new ArrayBuffer(7),t=new DataView(e);if(t.setUint32(0,this.serialOptions_.baudRate,!0),t.setUint8(4,A.indexOf(this.serialOptions_.stopBits??T)),t.setUint8(5,k.indexOf(this.serialOptions_.parity??w)),t.setUint8(6,this.serialOptions_.dataBits??C),(await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:f,value:0,index:this.controlInterface_.interfaceNumber},e)).status!==`ok`)throw new DOMException(`Failed to set line coding.`,`NetworkError`)}async cp210xInit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:m,value:v,index:e});let t=new ArrayBuffer(4);new DataView(t).setUint32(0,this.serialOptions_.baudRate,!0),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:h,value:0,index:e},t);let n=this.serialOptions_.dataBits??C,r={none:0,odd:16,even:32}[this.serialOptions_.parity??w]??0,i=({1:0,2:2}[this.serialOptions_.stopBits??T]??0)<<8|r|n;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:g,value:i,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:_,value:b,index:e})}async cp210xDeinit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:_,value:x,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:m,value:y,index:e})}validateOptions(){if(this.serialOptions_.baudRate%1!=0)throw RangeError(`Invalid baud rate: ${this.serialOptions_.baudRate}`);if(this.serialOptions_.dataBits!==void 0&&!E.includes(this.serialOptions_.dataBits))throw RangeError(`Invalid dataBits: ${this.serialOptions_.dataBits}`);if(this.serialOptions_.stopBits!==void 0&&!D.includes(this.serialOptions_.stopBits))throw RangeError(`Invalid stopBits: ${this.serialOptions_.stopBits}`);if(this.serialOptions_.parity!==void 0&&!O.includes(this.serialOptions_.parity))throw RangeError(`Invalid parity: ${this.serialOptions_.parity}`)}},z=class{options_;constructor(e){this.options_={...j,...e}}async requestPort(e,t){let n={...this.options_,...t},r=[];if(e?.filters&&e.filters.length>0)for(let t of e.filters){let e={};t.usbVendorId!==void 0&&(e.vendorId=t.usbVendorId),t.usbProductId!==void 0&&(e.productId=t.usbProductId),n.usbControlInterfaceClass!==void 0&&n.usbControlInterfaceClass!==255?e.classCode=n.usbControlInterfaceClass:e.vendorId===void 0&&e.productId===void 0&&(e.classCode=n.usbControlInterfaceClass??2),r.push(e)}else r.push({classCode:n.usbControlInterfaceClass??2});return new R(await navigator.usb.requestDevice({filters:r}),n)}async getPorts(e){let t={...this.options_,...e},n=await navigator.usb.getDevices(),r=[];for(let e of n)try{let n=new R(e,t);r.push(n)}catch{}return r}},B=`6e400001-b5a3-f393-e0a9-e50e24dcca9e`,V=`6e400003-b5a3-f393-e0a9-e50e24dcca9e`,H=`6e400002-b5a3-f393-e0a9-e50e24dcca9e`,U=20,W=10;function G(e){let t=null,n=null,r=null;return{get readable(){return t},get writable(){return n},getInfo(){return{}},async open(){if(!e.gatt)throw Error(`GATT not available on this Bluetooth device.`);r=await e.gatt.connect();let i=await r.getPrimaryService(B),a=await i.getCharacteristic(V),o=await i.getCharacteristic(H);await a.startNotifications(),t=new ReadableStream({start(e){a.addEventListener(`characteristicvaluechanged`,t=>{let n=t.target.value.buffer;e.enqueue(new Uint8Array(n))})}}),n=new WritableStream({async write(e){for(let t=0;t<e.length;t+=U){let n=e.slice(t,t+U);await o.writeValueWithoutResponse(n),t+U<e.length&&await new Promise(e=>setTimeout(e,W))}}})},async close(){r?.connected&&r.disconnect(),t=null,n=null}}}function K(){return{async requestPort(){if(!navigator.bluetooth)throw Error(`Web Bluetooth API is not supported in this browser. Use Chrome on Android, macOS, or ChromeOS.`);return G(await navigator.bluetooth.requestDevice({filters:[{services:[B]}]}))},async getPorts(){return[]}}}function q(e){return new Promise((t,n)=>{e.addEventListener(`open`,()=>t(),{once:!0}),e.addEventListener(`error`,e=>n(e),{once:!0})})}function J(e,t){return new Promise(n=>{let r=i=>{let a=JSON.parse(i.data);a.type===t&&(e.removeEventListener(`message`,r),n(a.payload))};e.addEventListener(`message`,r)})}function Y(e,t){let n=null,r=null;return{get readable(){return n},get writable(){return r},getInfo(){return{usbVendorId:t.vendorId,usbProductId:t.productId}},async open(i){e.send(JSON.stringify({type:`open`,path:t.path,baudRate:i.baudRate,dataBits:i.dataBits,stopBits:i.stopBits,parity:i.parity,parser:{type:`delimiter`,value:`\\n`}})),await J(e,`opened`);let a=[],o=null,s=!1;function c(e){let t=JSON.parse(e.data);if(t.type===`data`&&t.bytes){let e=new Uint8Array(t.bytes);o?o.enqueue(e):a.push(e)}t.type===`closed`&&(s=!0,o&&o.close())}e.addEventListener(`message`,c),n=new ReadableStream({start(e){o=e;for(let t of a)e.enqueue(t);a.length=0,s&&e.close()},cancel(){e.removeEventListener(`message`,c),o=null}}),r=new WritableStream({write(t){e.send(JSON.stringify({type:`write`,bytes:Array.from(t)}))}})},async close(){e.send(JSON.stringify({type:`close`})),n=null,r=null,e.close()}}}function X(e){return{async requestPort(t){let n=new WebSocket(e);await q(n),n.send(JSON.stringify({type:`list-ports`,filters:t?.filters??[]}));let r=(await J(n,`port-list`))[0];if(!r)throw Error(`No ports available on the bridge server. Make sure the Node.js server is running and a device is connected.`);return Y(n,r)},async getPorts(){let t=new WebSocket(e);return await q(t),t.send(JSON.stringify({type:`list-ports`,filters:[]})),(await J(t,`port-list`)).map(e=>Y(t,e))}}}exports.AbstractSerialDevice=c,exports.CommandQueue=n,exports.SerialEventEmitter=e,exports.SerialPermissionError=i,exports.SerialPortConflictError=r,exports.SerialReadError=o,exports.SerialRegistry=t,exports.SerialTimeoutError=a,exports.SerialWriteError=s,exports.WebUsbProvider=z,exports.createBluetoothProvider=K,exports.createWebSocketProvider=X,exports.delimiter=u,exports.fixedLength=l,exports.raw=d;
|
|
1
|
+
Object.defineProperty(exports,Symbol.toStringTag,{value:`Module`});var e=class{listeners={};on(e,t){return this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),this}off(e,t){return this.listeners[e]&&this.listeners[e].delete(t),this}emit(e,...t){let n=this.listeners[e];if(!n||n.size===0)return!1;for(let e of n)e(...t);return!0}},t=class{static instances=new Set;static portInstanceMap=new WeakMap;static getInstances(){return Array.from(this.instances)}static register(e){this.instances.add(e)}static unregister(e){this.instances.delete(e)}static isPortInUse(e,t){let n=this.portInstanceMap.get(e);return n!==void 0&&n!==t}static lockPort(e,t){this.portInstanceMap.set(e,t)}static unlockPort(e){this.portInstanceMap.delete(e)}},n=class{queue=[];isProcessing=!1;isPaused=!0;timeoutId=null;commandTimeout;onSend;onTimeout;constructor(e){this.commandTimeout=e.commandTimeout,this.onSend=e.onSend,this.onTimeout=e.onTimeout}get queueSize(){return this.queue.length}enqueue(e){this.queue.push(e),this.tryProcessNext()}advance(){this.clearCommandTimeout(),this.isProcessing=!1,this.tryProcessNext()}pause(){this.isPaused=!0,this.clearCommandTimeout(),this.isProcessing=!1}resume(){this.isPaused=!1,this.tryProcessNext()}clear(){this.queue=[],this.clearCommandTimeout(),this.isProcessing=!1}snapshot(){return[...this.queue]}restore(e){this.queue=[...e,...this.queue]}tryProcessNext(){if(this.isPaused||this.isProcessing||this.queue.length===0)return;this.isProcessing=!0;let e=this.queue.shift();this.commandTimeout>0&&(this.timeoutId=setTimeout(()=>{this.timeoutId=null,this.onTimeout(e),this.advance()},this.commandTimeout)),this.onSend(e).catch(()=>{this.advance()})}clearCommandTimeout(){this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}},r=class e extends Error{constructor(t){super(t),this.name=`SerialPortConflictError`,Object.setPrototypeOf(this,e.prototype)}},i=class e extends Error{constructor(t){super(t),this.name=`SerialPermissionError`,Object.setPrototypeOf(this,e.prototype)}},a=class e extends Error{constructor(t){super(t),this.name=`SerialTimeoutError`,Object.setPrototypeOf(this,e.prototype)}},o=class e extends Error{constructor(t){super(t),this.name=`SerialReadError`,Object.setPrototypeOf(this,e.prototype)}},s=class e extends Error{constructor(t){super(t),this.name=`SerialWriteError`,Object.setPrototypeOf(this,e.prototype)}},c=class r extends e{port=null;reader=null;writer=null;queue;options;isConnecting=!1;abortController=null;userInitiatedDisconnect=!1;reconnectTimerId=null;isHandshaking=!1;static customProvider=null;static polyfillOptions;constructor(e){super(),this.options={baudRate:e.baudRate,dataBits:e.dataBits??8,stopBits:e.stopBits??1,parity:e.parity??`none`,bufferSize:e.bufferSize??255,flowControl:e.flowControl??`none`,filters:e.filters??[],commandTimeout:e.commandTimeout??0,parser:e.parser,autoReconnect:e.autoReconnect??!1,autoReconnectInterval:e.autoReconnectInterval??1500,handshakeTimeout:e.handshakeTimeout??2e3,provider:e.provider,polyfillOptions:e.polyfillOptions},this.queue=new n({commandTimeout:this.options.commandTimeout,onSend:async e=>{await this.writeToPort(e),this.emit(`serial:sent`,e,this)},onTimeout:e=>{this.emit(`serial:timeout`,e,this)}}),this.on(`serial:data`,()=>{this.queue.advance()}),t.register(this)}async handshake(){return!0}async connect(){if(!this.isConnecting&&!this.port){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{let e=this.getSerial();if(!e)throw Error(`Web Serial API is not supported in this browser. Use AbstractSerialDevice.setProvider() to set a WebUSB polyfill.`);if(this.port=await this.findAndValidatePort(),!this.port){let t;try{t=await e.requestPort({filters:this.options.filters},this.options.polyfillOptions??r.polyfillOptions)}catch(e){throw e instanceof DOMException&&(e.name===`NotFoundError`||e.name===`SecurityError`||e.name===`AbortError`)?new i(e instanceof Error?e.message:String(e)):e instanceof Error?e:Error(String(e))}if(!await this.openAndHandshake(t))throw Error(`Handshake failed: the selected device did not respond correctly.`);this.port=t}this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){if(e instanceof i?this.emit(`serial:need-permission`,this):this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port){t.unlockPort(this.port);try{await this.port.close()}catch{}this.port=null}throw e}finally{this.isConnecting=!1}}}async disconnect(){this.port&&(this.userInitiatedDisconnect=!0,this.stopReconnecting(),await this.cleanupPort())}isConnected(){return!!(this.port&&this.port.connected&&this.port.readable&&this.port.writable)}isDisconnected(){return!this.isConnected()}async cleanupPort(){if(this.port){this.queue.pause(),this.abortController?.abort(),this.abortController=null;try{let e=this.reader,t=this.writer;if(this.reader=null,this.writer=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}if(t){try{await t.close()}catch{}try{t.releaseLock()}catch{}}try{await this.port.close()}catch{}}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this)}finally{this.port&&t.unlockPort(this.port),this.port=null,this.options.parser?.reset?.(),this.emit(`serial:disconnected`,this),!this.userInitiatedDisconnect&&this.options.autoReconnect&&this.startReconnecting(),this.userInitiatedDisconnect=!1}}}async forget(){await this.disconnect(),this.port&&typeof this.port.forget==`function`&&await this.port.forget(),t.unregister(this)}async send(e){let t;t=typeof e==`string`?new TextEncoder().encode(e):e,t.length>0&&this.queue.enqueue(t)}clearQueue(){this.queue.clear(),this.emit(`serial:queue-empty`,this)}async writeToPort(e){if(!this.port||!this.port.writable)throw new s(`Port not writable.`);this.writer=this.port.writable.getWriter();try{await this.writer.write(e)}catch(e){throw new s(e instanceof Error?e.message:String(e))}finally{this.writer.releaseLock(),this.writer=null}}async readLoop(){if(!(!this.port||!this.port.readable)&&!this.reader){this.reader=this.port.readable.getReader();try{for(;;){let{value:e,done:t}=await this.reader.read();if(t)break;e&&(this.options.parser?this.options.parser.parse(e,e=>{this.emit(`serial:data`,e,this)}):this.emit(`serial:data`,e,this))}}catch(e){if(this.port)throw new o(e instanceof Error?e.message:String(e))}finally{if(this.reader){try{this.reader.releaseLock()}catch{}this.reader=null}}}}async openAndHandshake(e){let n=this;if(t.isPortInUse(e,n))return!1;t.lockPort(e,n);try{await e.open({baudRate:this.options.baudRate,dataBits:this.options.dataBits,stopBits:this.options.stopBits,parity:this.options.parity,bufferSize:this.options.bufferSize,flowControl:this.options.flowControl})}catch(n){throw t.unlockPort(e),n instanceof Error?n:Error(String(n))}this.port=e,this.abortController=new AbortController;let r=this.queue.snapshot();this.isHandshaking=!0,this.readLoop().catch(e=>{!this.isHandshaking&&this.port&&(this.emit(`serial:error`,e,this),this.cleanupPort())}),this.queue.resume();try{let t=await this.runHandshakeWithTimeout();return this.isHandshaking=!1,t?(this.queue.pause(),this.queue.clear(),this.queue.restore(r),this.options.parser?.reset?.(),!0):(await this.teardownHandshake(e,r),!1)}catch{return this.isHandshaking=!1,await this.teardownHandshake(e,r),!1}}async teardownHandshake(e,n){this.queue.pause(),this.queue.clear(),this.queue.restore(n),await this.stopReader(),this.port=null,this.abortController=null,this.options.parser?.reset?.();try{await e.close()}catch{}t.unlockPort(e)}async stopReader(){let e=this.reader;if(this.reader=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}}async runHandshakeWithTimeout(){let e=this.options.handshakeTimeout??2e3;return Promise.race([this.handshake(),new Promise(t=>setTimeout(()=>t(!1),e))])}async findAndValidatePort(){let e=this.getSerial();if(!e)return null;let n=await e.getPorts(this.options.polyfillOptions??r.polyfillOptions);if(n.length===0)return null;let i=this.options.filters??[],a=this;for(let e of n)if(!t.isPortInUse(e,a)){if(i.length>0){let t=e.getInfo();if(!i.some(e=>{let n=e.usbVendorId===void 0||e.usbVendorId===t.usbVendorId,r=e.usbProductId===void 0||e.usbProductId===t.usbProductId;return n&&r}))continue}try{if(await this.openAndHandshake(e))return e}catch{}}return null}startReconnecting(){this.reconnectTimerId||=(this.emit(`serial:reconnecting`,this),setInterval(async()=>{if(this.port||this.isConnecting){this.stopReconnecting();return}try{let e=await this.findAndValidatePort();e&&(this.stopReconnecting(),await this.reconnect(e))}catch{}},this.options.autoReconnectInterval))}stopReconnecting(){this.reconnectTimerId&&=(clearInterval(this.reconnectTimerId),null)}async reconnect(e){if(!(this.isConnecting||this.port)){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{this.port=e,this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port&&=(t.unlockPort(this.port),null),this.options.autoReconnect&&this.startReconnecting()}finally{this.isConnecting=!1}}}static getInstances(){return t.getInstances()}static async connectAll(){let e=t.getInstances();for(let t of e)try{await t.connect()}catch{}}static setProvider(e,t){r.customProvider=e,r.polyfillOptions=t}getSerial(){return this.options.provider?this.options.provider:r.customProvider?r.customProvider:typeof navigator<`u`&&navigator.serial?navigator.serial:null}};function l(e=50){let t=new Uint8Array,n=null;function r(e){for(;!(t.length<2);){let n=t[1]+5;if(t.length<n)break;e(t.slice(0,n)),t=t.slice(n)}}return{parse(i,a){n!==null&&(clearTimeout(n),n=null);let o=new Uint8Array(t.length+i.length);o.set(t),o.set(i,t.length),t=o,r(a),t.length>0&&(n=setTimeout(()=>{t=new Uint8Array,n=null},e))},reset(){n!==null&&(clearTimeout(n),n=null),t=new Uint8Array}}}function u(e){return typeof e==`string`?new TextEncoder().encode(e):e instanceof Uint8Array?e:new Uint8Array(e)}function d(e,t){if(t.length===0)return 0;outer:for(let n=0;n<=e.length-t.length;n++){for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])continue outer;return n}return-1}function f(e,t){let n=t?.includeDelimiter??!1,r=u(e);if(typeof e==`string`){let e=new Uint8Array,t=new TextDecoder;return{parse(i,a){let o=new Uint8Array(e.length+i.length);o.set(e),o.set(i,e.length),e=o;let s;for(;(s=d(e,r))!==-1;){let i=n?s+r.length:s;a(t.decode(e.slice(0,i))),t=new TextDecoder,e=e.slice(s+r.length)}},reset(){e=new Uint8Array,t=new TextDecoder}}}let i=new Uint8Array;return{parse(e,t){let a=new Uint8Array(i.length+e.length);a.set(i),a.set(e,i.length),i=a;let o;for(;(o=d(i,r))!==-1;){let e=n?o+r.length:o;t(i.slice(0,e)),i=i.slice(o+r.length)}},reset(){i=new Uint8Array}}}function p(e){if(e<=0)throw Error(`FixedLengthParser: length must be greater than 0`);let t=new Uint8Array;return{parse(n,r){let i=new Uint8Array(t.length+n.length);for(i.set(t),i.set(n,t.length),t=i;t.length>=e;)r(t.slice(0,e)),t=t.slice(e)},reset(){t=new Uint8Array}}}function m(e){if(e.interval<=0)throw Error(`InterByteTimeoutParser: interval must be greater than 0`);let t=e.maxBufferSize??65536,n=new Uint8Array,r=null,i=null;function a(){r!==null&&(clearTimeout(r),r=null),n.length>0&&i!==null&&(i(n.slice()),n=new Uint8Array)}return{parse(o,s){i=s,r!==null&&(clearTimeout(r),r=null);let c=new Uint8Array(n.length+o.length);if(c.set(n),c.set(o,n.length),n=c,n.length>=t){a();return}r=setTimeout(()=>{r=null,a()},e.interval)},reset(){r!==null&&(clearTimeout(r),r=null),n=new Uint8Array,i=null}}}function h(e){let t=e?.delimiter??170,n=e?.packetOverhead??2,r=e?.lengthBytes??1,i=e?.lengthOffset??1,a=e?.maxLen??255;if(i+r>n)throw Error(`PacketLengthParser: lengthOffset + lengthBytes must not exceed packetOverhead`);let o=new Uint8Array;return{parse(e,s){let c=new Uint8Array(o.length+e.length);for(c.set(o),c.set(e,o.length),o=c;;){let e=o.indexOf(t);if(e===-1){o=new Uint8Array;break}e>0&&(o=o.slice(e));let c=i+r;if(o.length<c)break;let l=0;for(let e=0;e<r;e++)l=l<<8|o[i+e];if(l>a){o=o.slice(1);continue}let u=l+n;if(o.length<u)break;s(o.slice(0,u)),o=o.slice(u)}},reset(){o=new Uint8Array}}}function g(){return{parse(e,t){t(e)},reset(){}}}function _(e,t){if(t.length===0)return 0;outer:for(let n=0;n<=e.length-t.length;n++){for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])continue outer;return n}return-1}function v(e){let t=e?.encoding??`utf-8`,n=e?.includeDelimiter??!1,r=e?.delimiter??`
|
|
2
|
+
`,i;i=typeof r==`string`?new TextEncoder().encode(r):r instanceof Uint8Array?r:new Uint8Array(r);let a=new Uint8Array;return{parse(e,r){let o=new Uint8Array(a.length+e.length);o.set(a),o.set(e,a.length),a=o;let s;for(;(s=_(a,i))!==-1;){let e=n?s+i.length:s;r(new TextDecoder(t).decode(a.slice(0,e))),a=a.slice(s+i.length)}},reset(){a=new Uint8Array}}}function y(e,t){if(t.length===0)return 0;outer:for(let n=0;n<=e.length-t.length;n++){for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])continue outer;return n}return-1}function b(e){let t=e.delimiter,n;n=typeof t==`string`?new TextEncoder().encode(t):t instanceof Uint8Array?t:new Uint8Array(t);let r=!1,i=new Uint8Array;return{parse(t,a){if(r){a(t);return}let o=new Uint8Array(i.length+t.length);o.set(i),o.set(t,i.length),i=o;let s=y(i,n);if(s===-1)return;r=!0,e.onReady?.();let c=i.slice(s+n.length);i=new Uint8Array,c.length>0&&a(c)},reset(){r=!1,i=new Uint8Array}}}function x(e){let t=e.regex instanceof RegExp?e.regex:new RegExp(e.regex),n=e.encoding??`utf-8`,r=``;return{parse(e,i){let a=new TextDecoder(n);r+=a.decode(e);let o=r.split(t);r=o.pop()??``;for(let e of o)i(e)},reset(){r=``}}}var S={END:192,ESC:219,ESC_END:220,ESC_ESC:221};function C(e){let t=e?.END??S.END,n=e?.ESC??S.ESC,r=e?.ESC_END??S.ESC_END,i=e?.ESC_ESC??S.ESC_ESC,a=e?.START,o=e?.ESC_START??n,s=[],c=!1,l=a===void 0;return{parse(e,u){for(let d=0;d<e.length;d++){let f=e[d];if(!l){f===a&&(l=!0);continue}if(f===t){s.length>0&&(u(new Uint8Array(s)),s=[]),a!==void 0&&(l=!1),c=!1;continue}if(c){c=!1,f===r?s.push(t):f===i?s.push(n):a!==void 0&&f===o?s.push(a):s.push(f);continue}if(f===n){c=!0;continue}s.push(f)}},reset(){s=[],c=!1,l=a===void 0}}}function ee(e,t){let n=t?.END??S.END,r=t?.ESC??S.ESC,i=t?.ESC_END??S.ESC_END,a=t?.ESC_ESC??S.ESC_ESC,o=t?.START,s=t?.ESC_START??r,c=t?.bluetoothQuirk??!1,l=[];c&&l.push(n);for(let t=0;t<e.length;t++){let c=e[t];c===n?l.push(r,i):c===r?l.push(r,a):o!==void 0&&c===o?l.push(r,s):l.push(c)}return l.push(n),new Uint8Array(l)}function te(e){let t=e?.timeCodeFieldLength??0,n=e?.ancillaryDataFieldLength??0,r=new Uint8Array;function i(e){let r=e[0],i=e[1],a=e[2],o=e[3],s=e[4],c=e[5],l=r>>5&7,u=r>>4&1,d=r>>3&1,f=(r&7)<<8|i,p=a>>6&3,m=(a&63)<<8|o,h=s<<8|c,g={versionNumber:l,identification:{apid:f,secondaryHeader:d,type:u},sequenceControl:{packetName:m,sequenceFlags:p},dataLength:h},_,v=6;if(d===1){_={};let r=new TextDecoder(`latin1`);t>0&&(_.timeCode=r.decode(e.slice(v,v+t)),v+=t),n>0&&(_.ancillaryData=r.decode(e.slice(v,v+n)),v+=n)}let y=new TextDecoder(`latin1`).decode(e.slice(v));return{header:g,secondaryHeader:_,data:y}}return{parse(e,t){let n=new Uint8Array(r.length+e.length);for(n.set(r),n.set(e,r.length),r=n;r.length>=6;){let e=6+(r[4]<<8|r[5])+1;if(r.length<e)break;t(i(r.slice(0,e))),r=r.slice(e)}},reset(){r=new Uint8Array}}}var w=32,T=34,E=0,D=30,O=3,k=7,A=1,ne=0,re=771,ie=768,j=255,M=8,N=`none`,P=1,F=[16,8,7,6,5],I=[1,2],L=[`none`,`even`,`odd`],R=[`none`,`odd`,`even`],z=[1,1.5,2],B={usbControlInterfaceClass:2,usbTransferInterfaceClass:10,protocol:void 0};function V(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces)if(e.alternates[0]?.interfaceClass===t)return e;return null}function H(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces){let n=e.alternates[0];if(!n||n.interfaceClass!==t)continue;let r=n.endpoints.some(e=>e.direction===`in`),i=n.endpoints.some(e=>e.direction===`out`);if(r&&i)return e}return null}function U(e,t){let n=e.alternates[0];if(n){for(let e of n.endpoints)if(e.direction===t)return e}throw TypeError(`Interface ${e.interfaceNumber} does not have an ${t} endpoint.`)}function W(e,t){return t===2?`cdc_acm`:e.vendorId===4292?`cp210x`:`none`}var G=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}pull(e){(async()=>{let t=this.endpoint_.packetSize;try{let n=await this.device_.transferIn(this.endpoint_.endpointNumber,t);if(n.status!==`ok`){e.error(`USB error: ${n.status}`),this.onError_();return}if(n.data?.buffer&&n.data.byteLength>0){let t=new Uint8Array(n.data.buffer,n.data.byteOffset,n.data.byteLength);t.length>0&&e.enqueue(t)}}catch(t){e.error(String(t)),this.onError_()}})()}},K=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}async write(e,t){try{let n=await this.device_.transferOut(this.endpoint_.endpointNumber,e.buffer);n.status!==`ok`&&(t.error(n.status),this.onError_())}catch(e){t.error(String(e)),this.onError_()}}},q=class{device_;protocol_;controlInterface_;transferInterface_;inEndpoint_;outEndpoint_;serialOptions_;readable_=null;writable_=null;cdcOutputSignals_={dataTerminalReady:!1,requestToSend:!1,break:!1};constructor(e,t){this.device_=e;let n={...B,...t};this.protocol_=n.protocol??W(e,n.usbControlInterfaceClass);let r=n.usbControlInterfaceClass,i=n.usbTransferInterfaceClass;if(r===i){let t=H(e,i);if(!t)throw TypeError(`Unable to find interface with class ${i} that has both IN and OUT endpoints.`);this.controlInterface_=t,this.transferInterface_=t}else{let t=V(e,r);if(!t)throw TypeError(`Unable to find control interface with class ${r}.`);let n=H(e,i)??V(e,i);if(!n)throw TypeError(`Unable to find transfer interface with class ${i}.`);this.controlInterface_=t,this.transferInterface_=n}this.inEndpoint_=U(this.transferInterface_,`in`),this.outEndpoint_=U(this.transferInterface_,`out`)}get readable(){return!this.readable_&&this.device_.opened&&(this.readable_=new ReadableStream(new G(this.device_,this.inEndpoint_,()=>{this.readable_=null}),{highWaterMark:this.serialOptions_?.bufferSize??j})),this.readable_}get writable(){return!this.writable_&&this.device_.opened&&(this.writable_=new WritableStream(new K(this.device_,this.outEndpoint_,()=>{this.writable_=null}),new ByteLengthQueuingStrategy({highWaterMark:this.serialOptions_?.bufferSize??j}))),this.writable_}async open(e){this.serialOptions_=e,this.validateOptions();try{switch(await this.device_.open(),this.device_.configuration===null&&await this.device_.selectConfiguration(1),await this.device_.claimInterface(this.controlInterface_.interfaceNumber),this.controlInterface_!==this.transferInterface_&&await this.device_.claimInterface(this.transferInterface_.interfaceNumber),this.protocol_){case`cdc_acm`:await this.cdcInit();break;case`cp210x`:await this.cp210xInit();break;case`none`:break}}catch(e){throw this.device_.opened&&await this.device_.close(),Error(`Error setting up device: `+(e instanceof Error?e.message:String(e)),{cause:e})}}async close(){let e=[];if(this.readable_&&e.push(this.readable_.cancel()),this.writable_&&e.push(this.writable_.abort()),await Promise.all(e),this.readable_=null,this.writable_=null,this.device_.opened){switch(this.protocol_){case`cdc_acm`:await this.cdcSetSignals({dataTerminalReady:!1,requestToSend:!1});break;case`cp210x`:await this.cp210xDeinit();break}await this.device_.close()}}async forget(){return this.device_.forget()}getInfo(){return{usbVendorId:this.device_.vendorId,usbProductId:this.device_.productId}}async cdcInit(){await this.cdcSetLineCoding(),await this.cdcSetSignals({dataTerminalReady:!0})}async cdcSetSignals(e){if(this.cdcOutputSignals_={...this.cdcOutputSignals_,...e},e.dataTerminalReady!==void 0||e.requestToSend!==void 0){let e=!!this.cdcOutputSignals_.dataTerminalReady|(this.cdcOutputSignals_.requestToSend?2:0);await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:T,value:e,index:this.controlInterface_.interfaceNumber})}}async cdcSetLineCoding(){let e=new ArrayBuffer(7),t=new DataView(e);if(t.setUint32(0,this.serialOptions_.baudRate,!0),t.setUint8(4,z.indexOf(this.serialOptions_.stopBits??P)),t.setUint8(5,R.indexOf(this.serialOptions_.parity??N)),t.setUint8(6,this.serialOptions_.dataBits??M),(await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:w,value:0,index:this.controlInterface_.interfaceNumber},e)).status!==`ok`)throw new DOMException(`Failed to set line coding.`,`NetworkError`)}async cp210xInit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:E,value:A,index:e});let t=new ArrayBuffer(4);new DataView(t).setUint32(0,this.serialOptions_.baudRate,!0),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:D,value:0,index:e},t);let n=this.serialOptions_.dataBits??M,r={none:0,odd:16,even:32}[this.serialOptions_.parity??N]??0,i=({1:0,2:2}[this.serialOptions_.stopBits??P]??0)<<8|r|n;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:O,value:i,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:k,value:re,index:e})}async cp210xDeinit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:k,value:ie,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:E,value:ne,index:e})}validateOptions(){if(this.serialOptions_.baudRate%1!=0)throw RangeError(`Invalid baud rate: ${this.serialOptions_.baudRate}`);if(this.serialOptions_.dataBits!==void 0&&!F.includes(this.serialOptions_.dataBits))throw RangeError(`Invalid dataBits: ${this.serialOptions_.dataBits}`);if(this.serialOptions_.stopBits!==void 0&&!I.includes(this.serialOptions_.stopBits))throw RangeError(`Invalid stopBits: ${this.serialOptions_.stopBits}`);if(this.serialOptions_.parity!==void 0&&!L.includes(this.serialOptions_.parity))throw RangeError(`Invalid parity: ${this.serialOptions_.parity}`)}},J=class{options_;constructor(e){this.options_={...B,...e}}async requestPort(e,t){let n={...this.options_,...t},r=[];if(e?.filters&&e.filters.length>0)for(let t of e.filters){let e={};t.usbVendorId!==void 0&&(e.vendorId=t.usbVendorId),t.usbProductId!==void 0&&(e.productId=t.usbProductId),n.usbControlInterfaceClass!==void 0&&n.usbControlInterfaceClass!==255?e.classCode=n.usbControlInterfaceClass:e.vendorId===void 0&&e.productId===void 0&&(e.classCode=n.usbControlInterfaceClass??2),r.push(e)}else r.push({classCode:n.usbControlInterfaceClass??2});return new q(await navigator.usb.requestDevice({filters:r}),n)}async getPorts(e){let t={...this.options_,...e},n=await navigator.usb.getDevices(),r=[];for(let e of n)try{let n=new q(e,t);r.push(n)}catch{}return r}},Y=`6e400001-b5a3-f393-e0a9-e50e24dcca9e`,ae=`6e400003-b5a3-f393-e0a9-e50e24dcca9e`,oe=`6e400002-b5a3-f393-e0a9-e50e24dcca9e`,X=20,se=10;function ce(e){let t=null,n=null,r=null;return{get readable(){return t},get writable(){return n},getInfo(){return{}},async open(){if(!e.gatt)throw Error(`GATT not available on this Bluetooth device.`);r=await e.gatt.connect();let i=await r.getPrimaryService(Y),a=await i.getCharacteristic(ae),o=await i.getCharacteristic(oe);await a.startNotifications(),t=new ReadableStream({start(e){a.addEventListener(`characteristicvaluechanged`,t=>{let n=t.target.value.buffer;e.enqueue(new Uint8Array(n))})}}),n=new WritableStream({async write(e){for(let t=0;t<e.length;t+=X){let n=e.slice(t,t+X);await o.writeValueWithoutResponse(n),t+X<e.length&&await new Promise(e=>setTimeout(e,se))}}})},async close(){r?.connected&&r.disconnect(),t=null,n=null}}}function le(){return{async requestPort(){if(!navigator.bluetooth)throw Error(`Web Bluetooth API is not supported in this browser. Use Chrome on Android, macOS, or ChromeOS.`);return ce(await navigator.bluetooth.requestDevice({filters:[{services:[Y]}]}))},async getPorts(){return[]}}}function Z(e){return new Promise((t,n)=>{e.addEventListener(`open`,()=>t(),{once:!0}),e.addEventListener(`error`,e=>n(e),{once:!0})})}function Q(e,t){return new Promise(n=>{let r=i=>{let a=JSON.parse(i.data);a.type===t&&(e.removeEventListener(`message`,r),n(a.payload))};e.addEventListener(`message`,r)})}function $(e,t){let n=null,r=null;return{get readable(){return n},get writable(){return r},getInfo(){return{usbVendorId:t.vendorId,usbProductId:t.productId}},async open(i){e.send(JSON.stringify({type:`open`,path:t.path,baudRate:i.baudRate,dataBits:i.dataBits,stopBits:i.stopBits,parity:i.parity,parser:{type:`delimiter`,value:`\\n`}})),await Q(e,`opened`);let a=[],o=null,s=!1;function c(e){let t=JSON.parse(e.data);if(t.type===`data`&&t.bytes){let e=new Uint8Array(t.bytes);o?o.enqueue(e):a.push(e)}t.type===`closed`&&(s=!0,o&&o.close())}e.addEventListener(`message`,c),n=new ReadableStream({start(e){o=e;for(let t of a)e.enqueue(t);a.length=0,s&&e.close()},cancel(){e.removeEventListener(`message`,c),o=null}}),r=new WritableStream({write(t){e.send(JSON.stringify({type:`write`,bytes:Array.from(t)}))}})},async close(){e.send(JSON.stringify({type:`close`})),n=null,r=null,e.close()}}}function ue(e){return{async requestPort(t){let n=new WebSocket(e);await Z(n),n.send(JSON.stringify({type:`list-ports`,filters:t?.filters??[]}));let r=(await Q(n,`port-list`))[0];if(!r)throw Error(`No ports available on the bridge server. Make sure the Node.js server is running and a device is connected.`);return $(n,r)},async getPorts(){let t=new WebSocket(e);return await Z(t),t.send(JSON.stringify({type:`list-ports`,filters:[]})),(await Q(t,`port-list`)).map(e=>$(t,e))}}}exports.AbstractSerialDevice=c,exports.CommandQueue=n,exports.SerialEventEmitter=e,exports.SerialPermissionError=i,exports.SerialPortConflictError=r,exports.SerialReadError=o,exports.SerialRegistry=t,exports.SerialTimeoutError=a,exports.SerialWriteError=s,exports.WebUsbProvider=J,exports.ccTalk=l,exports.createBluetoothProvider=le,exports.createWebSocketProvider=ue,exports.delimiter=f,exports.fixedLength=p,exports.interByteTimeout=m,exports.packetLength=h,exports.raw=g,exports.readline=v,exports.readyParser=b,exports.regexParser=x,exports.slipDecoder=C,exports.slipEncode=ee,exports.spacePacket=te;
|
package/dist/webserial-core.mjs
CHANGED
|
@@ -376,8 +376,80 @@ var e = class {
|
|
|
376
376
|
}
|
|
377
377
|
};
|
|
378
378
|
//#endregion
|
|
379
|
+
//#region src/parsers/CCTalkParser.ts
|
|
380
|
+
function l(e = 50) {
|
|
381
|
+
let t = new Uint8Array(), n = null;
|
|
382
|
+
function r(e) {
|
|
383
|
+
for (; !(t.length < 2);) {
|
|
384
|
+
let n = t[1] + 5;
|
|
385
|
+
if (t.length < n) break;
|
|
386
|
+
e(t.slice(0, n)), t = t.slice(n);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
return {
|
|
390
|
+
parse(i, a) {
|
|
391
|
+
n !== null && (clearTimeout(n), n = null);
|
|
392
|
+
let o = new Uint8Array(t.length + i.length);
|
|
393
|
+
o.set(t), o.set(i, t.length), t = o, r(a), t.length > 0 && (n = setTimeout(() => {
|
|
394
|
+
t = new Uint8Array(), n = null;
|
|
395
|
+
}, e));
|
|
396
|
+
},
|
|
397
|
+
reset() {
|
|
398
|
+
n !== null && (clearTimeout(n), n = null), t = new Uint8Array();
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
}
|
|
402
|
+
//#endregion
|
|
403
|
+
//#region src/parsers/DelimiterParser.ts
|
|
404
|
+
function u(e) {
|
|
405
|
+
return typeof e == "string" ? new TextEncoder().encode(e) : e instanceof Uint8Array ? e : new Uint8Array(e);
|
|
406
|
+
}
|
|
407
|
+
function d(e, t) {
|
|
408
|
+
if (t.length === 0) return 0;
|
|
409
|
+
outer: for (let n = 0; n <= e.length - t.length; n++) {
|
|
410
|
+
for (let r = 0; r < t.length; r++) if (e[n + r] !== t[r]) continue outer;
|
|
411
|
+
return n;
|
|
412
|
+
}
|
|
413
|
+
return -1;
|
|
414
|
+
}
|
|
415
|
+
function f(e, t) {
|
|
416
|
+
let n = t?.includeDelimiter ?? !1, r = u(e);
|
|
417
|
+
if (typeof e == "string") {
|
|
418
|
+
let e = new Uint8Array(), t = new TextDecoder();
|
|
419
|
+
return {
|
|
420
|
+
parse(i, a) {
|
|
421
|
+
let o = new Uint8Array(e.length + i.length);
|
|
422
|
+
o.set(e), o.set(i, e.length), e = o;
|
|
423
|
+
let s;
|
|
424
|
+
for (; (s = d(e, r)) !== -1;) {
|
|
425
|
+
let i = n ? s + r.length : s;
|
|
426
|
+
a(t.decode(e.slice(0, i))), t = new TextDecoder(), e = e.slice(s + r.length);
|
|
427
|
+
}
|
|
428
|
+
},
|
|
429
|
+
reset() {
|
|
430
|
+
e = new Uint8Array(), t = new TextDecoder();
|
|
431
|
+
}
|
|
432
|
+
};
|
|
433
|
+
}
|
|
434
|
+
let i = new Uint8Array();
|
|
435
|
+
return {
|
|
436
|
+
parse(e, t) {
|
|
437
|
+
let a = new Uint8Array(i.length + e.length);
|
|
438
|
+
a.set(i), a.set(e, i.length), i = a;
|
|
439
|
+
let o;
|
|
440
|
+
for (; (o = d(i, r)) !== -1;) {
|
|
441
|
+
let e = n ? o + r.length : o;
|
|
442
|
+
t(i.slice(0, e)), i = i.slice(o + r.length);
|
|
443
|
+
}
|
|
444
|
+
},
|
|
445
|
+
reset() {
|
|
446
|
+
i = new Uint8Array();
|
|
447
|
+
}
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
//#endregion
|
|
379
451
|
//#region src/parsers/FixedLengthParser.ts
|
|
380
|
-
function
|
|
452
|
+
function p(e) {
|
|
381
453
|
if (e <= 0) throw Error("FixedLengthParser: length must be greater than 0");
|
|
382
454
|
let t = new Uint8Array();
|
|
383
455
|
return {
|
|
@@ -391,23 +463,67 @@ function l(e) {
|
|
|
391
463
|
};
|
|
392
464
|
}
|
|
393
465
|
//#endregion
|
|
394
|
-
//#region src/parsers/
|
|
395
|
-
function
|
|
396
|
-
|
|
466
|
+
//#region src/parsers/InterByteTimeoutParser.ts
|
|
467
|
+
function m(e) {
|
|
468
|
+
if (e.interval <= 0) throw Error("InterByteTimeoutParser: interval must be greater than 0");
|
|
469
|
+
let t = e.maxBufferSize ?? 65536, n = new Uint8Array(), r = null, i = null;
|
|
470
|
+
function a() {
|
|
471
|
+
r !== null && (clearTimeout(r), r = null), n.length > 0 && i !== null && (i(n.slice()), n = new Uint8Array());
|
|
472
|
+
}
|
|
397
473
|
return {
|
|
398
|
-
parse(
|
|
399
|
-
|
|
400
|
-
let
|
|
401
|
-
|
|
474
|
+
parse(o, s) {
|
|
475
|
+
i = s, r !== null && (clearTimeout(r), r = null);
|
|
476
|
+
let c = new Uint8Array(n.length + o.length);
|
|
477
|
+
if (c.set(n), c.set(o, n.length), n = c, n.length >= t) {
|
|
478
|
+
a();
|
|
479
|
+
return;
|
|
480
|
+
}
|
|
481
|
+
r = setTimeout(() => {
|
|
482
|
+
r = null, a();
|
|
483
|
+
}, e.interval);
|
|
402
484
|
},
|
|
403
485
|
reset() {
|
|
404
|
-
|
|
486
|
+
r !== null && (clearTimeout(r), r = null), n = new Uint8Array(), i = null;
|
|
487
|
+
}
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
//#endregion
|
|
491
|
+
//#region src/parsers/PacketLengthParser.ts
|
|
492
|
+
function h(e) {
|
|
493
|
+
let t = e?.delimiter ?? 170, n = e?.packetOverhead ?? 2, r = e?.lengthBytes ?? 1, i = e?.lengthOffset ?? 1, a = e?.maxLen ?? 255;
|
|
494
|
+
if (i + r > n) throw Error("PacketLengthParser: lengthOffset + lengthBytes must not exceed packetOverhead");
|
|
495
|
+
let o = new Uint8Array();
|
|
496
|
+
return {
|
|
497
|
+
parse(e, s) {
|
|
498
|
+
let c = new Uint8Array(o.length + e.length);
|
|
499
|
+
for (c.set(o), c.set(e, o.length), o = c;;) {
|
|
500
|
+
let e = o.indexOf(t);
|
|
501
|
+
if (e === -1) {
|
|
502
|
+
o = new Uint8Array();
|
|
503
|
+
break;
|
|
504
|
+
}
|
|
505
|
+
e > 0 && (o = o.slice(e));
|
|
506
|
+
let c = i + r;
|
|
507
|
+
if (o.length < c) break;
|
|
508
|
+
let l = 0;
|
|
509
|
+
for (let e = 0; e < r; e++) l = l << 8 | o[i + e];
|
|
510
|
+
if (l > a) {
|
|
511
|
+
o = o.slice(1);
|
|
512
|
+
continue;
|
|
513
|
+
}
|
|
514
|
+
let u = l + n;
|
|
515
|
+
if (o.length < u) break;
|
|
516
|
+
s(o.slice(0, u)), o = o.slice(u);
|
|
517
|
+
}
|
|
518
|
+
},
|
|
519
|
+
reset() {
|
|
520
|
+
o = new Uint8Array();
|
|
405
521
|
}
|
|
406
522
|
};
|
|
407
523
|
}
|
|
408
524
|
//#endregion
|
|
409
525
|
//#region src/parsers/RawParser.ts
|
|
410
|
-
function
|
|
526
|
+
function g() {
|
|
411
527
|
return {
|
|
412
528
|
parse(e, t) {
|
|
413
529
|
t(e);
|
|
@@ -416,37 +532,207 @@ function d() {
|
|
|
416
532
|
};
|
|
417
533
|
}
|
|
418
534
|
//#endregion
|
|
535
|
+
//#region src/parsers/ReadlineParser.ts
|
|
536
|
+
function _(e, t) {
|
|
537
|
+
if (t.length === 0) return 0;
|
|
538
|
+
outer: for (let n = 0; n <= e.length - t.length; n++) {
|
|
539
|
+
for (let r = 0; r < t.length; r++) if (e[n + r] !== t[r]) continue outer;
|
|
540
|
+
return n;
|
|
541
|
+
}
|
|
542
|
+
return -1;
|
|
543
|
+
}
|
|
544
|
+
function v(e) {
|
|
545
|
+
let t = e?.encoding ?? "utf-8", n = e?.includeDelimiter ?? !1, r = e?.delimiter ?? "\n", i;
|
|
546
|
+
i = typeof r == "string" ? new TextEncoder().encode(r) : r instanceof Uint8Array ? r : new Uint8Array(r);
|
|
547
|
+
let a = new Uint8Array();
|
|
548
|
+
return {
|
|
549
|
+
parse(e, r) {
|
|
550
|
+
let o = new Uint8Array(a.length + e.length);
|
|
551
|
+
o.set(a), o.set(e, a.length), a = o;
|
|
552
|
+
let s;
|
|
553
|
+
for (; (s = _(a, i)) !== -1;) {
|
|
554
|
+
let e = n ? s + i.length : s;
|
|
555
|
+
r(new TextDecoder(t).decode(a.slice(0, e))), a = a.slice(s + i.length);
|
|
556
|
+
}
|
|
557
|
+
},
|
|
558
|
+
reset() {
|
|
559
|
+
a = new Uint8Array();
|
|
560
|
+
}
|
|
561
|
+
};
|
|
562
|
+
}
|
|
563
|
+
//#endregion
|
|
564
|
+
//#region src/parsers/ReadyParser.ts
|
|
565
|
+
function y(e, t) {
|
|
566
|
+
if (t.length === 0) return 0;
|
|
567
|
+
outer: for (let n = 0; n <= e.length - t.length; n++) {
|
|
568
|
+
for (let r = 0; r < t.length; r++) if (e[n + r] !== t[r]) continue outer;
|
|
569
|
+
return n;
|
|
570
|
+
}
|
|
571
|
+
return -1;
|
|
572
|
+
}
|
|
573
|
+
function b(e) {
|
|
574
|
+
let t = e.delimiter, n;
|
|
575
|
+
n = typeof t == "string" ? new TextEncoder().encode(t) : t instanceof Uint8Array ? t : new Uint8Array(t);
|
|
576
|
+
let r = !1, i = new Uint8Array();
|
|
577
|
+
return {
|
|
578
|
+
parse(t, a) {
|
|
579
|
+
if (r) {
|
|
580
|
+
a(t);
|
|
581
|
+
return;
|
|
582
|
+
}
|
|
583
|
+
let o = new Uint8Array(i.length + t.length);
|
|
584
|
+
o.set(i), o.set(t, i.length), i = o;
|
|
585
|
+
let s = y(i, n);
|
|
586
|
+
if (s === -1) return;
|
|
587
|
+
r = !0, e.onReady?.();
|
|
588
|
+
let c = i.slice(s + n.length);
|
|
589
|
+
i = new Uint8Array(), c.length > 0 && a(c);
|
|
590
|
+
},
|
|
591
|
+
reset() {
|
|
592
|
+
r = !1, i = new Uint8Array();
|
|
593
|
+
}
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
//#endregion
|
|
597
|
+
//#region src/parsers/RegexParser.ts
|
|
598
|
+
function x(e) {
|
|
599
|
+
let t = e.regex instanceof RegExp ? e.regex : new RegExp(e.regex), n = e.encoding ?? "utf-8", r = "";
|
|
600
|
+
return {
|
|
601
|
+
parse(e, i) {
|
|
602
|
+
let a = new TextDecoder(n);
|
|
603
|
+
r += a.decode(e);
|
|
604
|
+
let o = r.split(t);
|
|
605
|
+
r = o.pop() ?? "";
|
|
606
|
+
for (let e of o) i(e);
|
|
607
|
+
},
|
|
608
|
+
reset() {
|
|
609
|
+
r = "";
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
}
|
|
613
|
+
//#endregion
|
|
614
|
+
//#region src/parsers/SlipParser.ts
|
|
615
|
+
var S = {
|
|
616
|
+
END: 192,
|
|
617
|
+
ESC: 219,
|
|
618
|
+
ESC_END: 220,
|
|
619
|
+
ESC_ESC: 221
|
|
620
|
+
};
|
|
621
|
+
function C(e) {
|
|
622
|
+
let t = e?.END ?? S.END, n = e?.ESC ?? S.ESC, r = e?.ESC_END ?? S.ESC_END, i = e?.ESC_ESC ?? S.ESC_ESC, a = e?.START, o = e?.ESC_START ?? n, s = [], c = !1, l = a === void 0;
|
|
623
|
+
return {
|
|
624
|
+
parse(e, u) {
|
|
625
|
+
for (let d = 0; d < e.length; d++) {
|
|
626
|
+
let f = e[d];
|
|
627
|
+
if (!l) {
|
|
628
|
+
f === a && (l = !0);
|
|
629
|
+
continue;
|
|
630
|
+
}
|
|
631
|
+
if (f === t) {
|
|
632
|
+
s.length > 0 && (u(new Uint8Array(s)), s = []), a !== void 0 && (l = !1), c = !1;
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
if (c) {
|
|
636
|
+
c = !1, f === r ? s.push(t) : f === i ? s.push(n) : a !== void 0 && f === o ? s.push(a) : s.push(f);
|
|
637
|
+
continue;
|
|
638
|
+
}
|
|
639
|
+
if (f === n) {
|
|
640
|
+
c = !0;
|
|
641
|
+
continue;
|
|
642
|
+
}
|
|
643
|
+
s.push(f);
|
|
644
|
+
}
|
|
645
|
+
},
|
|
646
|
+
reset() {
|
|
647
|
+
s = [], c = !1, l = a === void 0;
|
|
648
|
+
}
|
|
649
|
+
};
|
|
650
|
+
}
|
|
651
|
+
function ee(e, t) {
|
|
652
|
+
let n = t?.END ?? S.END, r = t?.ESC ?? S.ESC, i = t?.ESC_END ?? S.ESC_END, a = t?.ESC_ESC ?? S.ESC_ESC, o = t?.START, s = t?.ESC_START ?? r, c = t?.bluetoothQuirk ?? !1, l = [];
|
|
653
|
+
c && l.push(n);
|
|
654
|
+
for (let t = 0; t < e.length; t++) {
|
|
655
|
+
let c = e[t];
|
|
656
|
+
c === n ? l.push(r, i) : c === r ? l.push(r, a) : o !== void 0 && c === o ? l.push(r, s) : l.push(c);
|
|
657
|
+
}
|
|
658
|
+
return l.push(n), new Uint8Array(l);
|
|
659
|
+
}
|
|
660
|
+
//#endregion
|
|
661
|
+
//#region src/parsers/SpacePacketParser.ts
|
|
662
|
+
function te(e) {
|
|
663
|
+
let t = e?.timeCodeFieldLength ?? 0, n = e?.ancillaryDataFieldLength ?? 0, r = new Uint8Array();
|
|
664
|
+
function i(e) {
|
|
665
|
+
let r = e[0], i = e[1], a = e[2], o = e[3], s = e[4], c = e[5], l = r >> 5 & 7, u = r >> 4 & 1, d = r >> 3 & 1, f = (r & 7) << 8 | i, p = a >> 6 & 3, m = (a & 63) << 8 | o, h = s << 8 | c, g = {
|
|
666
|
+
versionNumber: l,
|
|
667
|
+
identification: {
|
|
668
|
+
apid: f,
|
|
669
|
+
secondaryHeader: d,
|
|
670
|
+
type: u
|
|
671
|
+
},
|
|
672
|
+
sequenceControl: {
|
|
673
|
+
packetName: m,
|
|
674
|
+
sequenceFlags: p
|
|
675
|
+
},
|
|
676
|
+
dataLength: h
|
|
677
|
+
}, _, v = 6;
|
|
678
|
+
if (d === 1) {
|
|
679
|
+
_ = {};
|
|
680
|
+
let r = new TextDecoder("latin1");
|
|
681
|
+
t > 0 && (_.timeCode = r.decode(e.slice(v, v + t)), v += t), n > 0 && (_.ancillaryData = r.decode(e.slice(v, v + n)), v += n);
|
|
682
|
+
}
|
|
683
|
+
let y = new TextDecoder("latin1").decode(e.slice(v));
|
|
684
|
+
return {
|
|
685
|
+
header: g,
|
|
686
|
+
secondaryHeader: _,
|
|
687
|
+
data: y
|
|
688
|
+
};
|
|
689
|
+
}
|
|
690
|
+
return {
|
|
691
|
+
parse(e, t) {
|
|
692
|
+
let n = new Uint8Array(r.length + e.length);
|
|
693
|
+
for (n.set(r), n.set(e, r.length), r = n; r.length >= 6;) {
|
|
694
|
+
let e = 6 + (r[4] << 8 | r[5]) + 1;
|
|
695
|
+
if (r.length < e) break;
|
|
696
|
+
t(i(r.slice(0, e))), r = r.slice(e);
|
|
697
|
+
}
|
|
698
|
+
},
|
|
699
|
+
reset() {
|
|
700
|
+
r = new Uint8Array();
|
|
701
|
+
}
|
|
702
|
+
};
|
|
703
|
+
}
|
|
704
|
+
//#endregion
|
|
419
705
|
//#region src/adapters/web-usb/WebUsbProvider.ts
|
|
420
|
-
var
|
|
706
|
+
var w = 32, T = 34, E = 0, D = 30, O = 3, k = 7, A = 1, ne = 0, re = 771, ie = 768, j = 255, M = 8, N = "none", P = 1, F = [
|
|
421
707
|
16,
|
|
422
708
|
8,
|
|
423
709
|
7,
|
|
424
710
|
6,
|
|
425
711
|
5
|
|
426
|
-
],
|
|
712
|
+
], I = [1, 2], L = [
|
|
427
713
|
"none",
|
|
428
714
|
"even",
|
|
429
715
|
"odd"
|
|
430
|
-
],
|
|
716
|
+
], R = [
|
|
431
717
|
"none",
|
|
432
718
|
"odd",
|
|
433
719
|
"even"
|
|
434
|
-
],
|
|
720
|
+
], z = [
|
|
435
721
|
1,
|
|
436
722
|
1.5,
|
|
437
723
|
2
|
|
438
|
-
],
|
|
724
|
+
], B = {
|
|
439
725
|
usbControlInterfaceClass: 2,
|
|
440
726
|
usbTransferInterfaceClass: 10,
|
|
441
727
|
protocol: void 0
|
|
442
728
|
};
|
|
443
|
-
function
|
|
729
|
+
function V(e, t) {
|
|
444
730
|
let n = e.configurations[0];
|
|
445
731
|
if (!n) return null;
|
|
446
732
|
for (let e of n.interfaces) if (e.alternates[0]?.interfaceClass === t) return e;
|
|
447
733
|
return null;
|
|
448
734
|
}
|
|
449
|
-
function
|
|
735
|
+
function H(e, t) {
|
|
450
736
|
let n = e.configurations[0];
|
|
451
737
|
if (!n) return null;
|
|
452
738
|
for (let e of n.interfaces) {
|
|
@@ -457,17 +743,17 @@ function N(e, t) {
|
|
|
457
743
|
}
|
|
458
744
|
return null;
|
|
459
745
|
}
|
|
460
|
-
function
|
|
746
|
+
function U(e, t) {
|
|
461
747
|
let n = e.alternates[0];
|
|
462
748
|
if (n) {
|
|
463
749
|
for (let e of n.endpoints) if (e.direction === t) return e;
|
|
464
750
|
}
|
|
465
751
|
throw TypeError(`Interface ${e.interfaceNumber} does not have an ${t} endpoint.`);
|
|
466
752
|
}
|
|
467
|
-
function
|
|
753
|
+
function W(e, t) {
|
|
468
754
|
return t === 2 ? "cdc_acm" : e.vendorId === 4292 ? "cp210x" : "none";
|
|
469
755
|
}
|
|
470
|
-
var
|
|
756
|
+
var G = class {
|
|
471
757
|
device_;
|
|
472
758
|
endpoint_;
|
|
473
759
|
onError_;
|
|
@@ -492,7 +778,7 @@ var I = class {
|
|
|
492
778
|
}
|
|
493
779
|
})();
|
|
494
780
|
}
|
|
495
|
-
},
|
|
781
|
+
}, K = class {
|
|
496
782
|
device_;
|
|
497
783
|
endpoint_;
|
|
498
784
|
onError_;
|
|
@@ -507,7 +793,7 @@ var I = class {
|
|
|
507
793
|
t.error(String(e)), this.onError_();
|
|
508
794
|
}
|
|
509
795
|
}
|
|
510
|
-
},
|
|
796
|
+
}, q = class {
|
|
511
797
|
device_;
|
|
512
798
|
protocol_;
|
|
513
799
|
controlInterface_;
|
|
@@ -525,33 +811,33 @@ var I = class {
|
|
|
525
811
|
constructor(e, t) {
|
|
526
812
|
this.device_ = e;
|
|
527
813
|
let n = {
|
|
528
|
-
...
|
|
814
|
+
...B,
|
|
529
815
|
...t
|
|
530
816
|
};
|
|
531
|
-
this.protocol_ = n.protocol ??
|
|
817
|
+
this.protocol_ = n.protocol ?? W(e, n.usbControlInterfaceClass);
|
|
532
818
|
let r = n.usbControlInterfaceClass, i = n.usbTransferInterfaceClass;
|
|
533
819
|
if (r === i) {
|
|
534
|
-
let t =
|
|
820
|
+
let t = H(e, i);
|
|
535
821
|
if (!t) throw TypeError(`Unable to find interface with class ${i} that has both IN and OUT endpoints.`);
|
|
536
822
|
this.controlInterface_ = t, this.transferInterface_ = t;
|
|
537
823
|
} else {
|
|
538
|
-
let t =
|
|
824
|
+
let t = V(e, r);
|
|
539
825
|
if (!t) throw TypeError(`Unable to find control interface with class ${r}.`);
|
|
540
|
-
let n =
|
|
826
|
+
let n = H(e, i) ?? V(e, i);
|
|
541
827
|
if (!n) throw TypeError(`Unable to find transfer interface with class ${i}.`);
|
|
542
828
|
this.controlInterface_ = t, this.transferInterface_ = n;
|
|
543
829
|
}
|
|
544
|
-
this.inEndpoint_ =
|
|
830
|
+
this.inEndpoint_ = U(this.transferInterface_, "in"), this.outEndpoint_ = U(this.transferInterface_, "out");
|
|
545
831
|
}
|
|
546
832
|
get readable() {
|
|
547
|
-
return !this.readable_ && this.device_.opened && (this.readable_ = new ReadableStream(new
|
|
833
|
+
return !this.readable_ && this.device_.opened && (this.readable_ = new ReadableStream(new G(this.device_, this.inEndpoint_, () => {
|
|
548
834
|
this.readable_ = null;
|
|
549
|
-
}), { highWaterMark: this.serialOptions_?.bufferSize ??
|
|
835
|
+
}), { highWaterMark: this.serialOptions_?.bufferSize ?? j })), this.readable_;
|
|
550
836
|
}
|
|
551
837
|
get writable() {
|
|
552
|
-
return !this.writable_ && this.device_.opened && (this.writable_ = new WritableStream(new
|
|
838
|
+
return !this.writable_ && this.device_.opened && (this.writable_ = new WritableStream(new K(this.device_, this.outEndpoint_, () => {
|
|
553
839
|
this.writable_ = null;
|
|
554
|
-
}), new ByteLengthQueuingStrategy({ highWaterMark: this.serialOptions_?.bufferSize ??
|
|
840
|
+
}), new ByteLengthQueuingStrategy({ highWaterMark: this.serialOptions_?.bufferSize ?? j }))), this.writable_;
|
|
555
841
|
}
|
|
556
842
|
async open(e) {
|
|
557
843
|
this.serialOptions_ = e, this.validateOptions();
|
|
@@ -607,7 +893,7 @@ var I = class {
|
|
|
607
893
|
await this.device_.controlTransferOut({
|
|
608
894
|
requestType: "class",
|
|
609
895
|
recipient: "interface",
|
|
610
|
-
request:
|
|
896
|
+
request: T,
|
|
611
897
|
value: e,
|
|
612
898
|
index: this.controlInterface_.interfaceNumber
|
|
613
899
|
});
|
|
@@ -615,10 +901,10 @@ var I = class {
|
|
|
615
901
|
}
|
|
616
902
|
async cdcSetLineCoding() {
|
|
617
903
|
let e = /* @__PURE__ */ new ArrayBuffer(7), t = new DataView(e);
|
|
618
|
-
if (t.setUint32(0, this.serialOptions_.baudRate, !0), t.setUint8(4,
|
|
904
|
+
if (t.setUint32(0, this.serialOptions_.baudRate, !0), t.setUint8(4, z.indexOf(this.serialOptions_.stopBits ?? P)), t.setUint8(5, R.indexOf(this.serialOptions_.parity ?? N)), t.setUint8(6, this.serialOptions_.dataBits ?? M), (await this.device_.controlTransferOut({
|
|
619
905
|
requestType: "class",
|
|
620
906
|
recipient: "interface",
|
|
621
|
-
request:
|
|
907
|
+
request: w,
|
|
622
908
|
value: 0,
|
|
623
909
|
index: this.controlInterface_.interfaceNumber
|
|
624
910
|
}, e)).status !== "ok") throw new DOMException("Failed to set line coding.", "NetworkError");
|
|
@@ -628,37 +914,37 @@ var I = class {
|
|
|
628
914
|
await this.device_.controlTransferOut({
|
|
629
915
|
requestType: "vendor",
|
|
630
916
|
recipient: "interface",
|
|
631
|
-
request:
|
|
632
|
-
value:
|
|
917
|
+
request: E,
|
|
918
|
+
value: A,
|
|
633
919
|
index: e
|
|
634
920
|
});
|
|
635
921
|
let t = /* @__PURE__ */ new ArrayBuffer(4);
|
|
636
922
|
new DataView(t).setUint32(0, this.serialOptions_.baudRate, !0), await this.device_.controlTransferOut({
|
|
637
923
|
requestType: "vendor",
|
|
638
924
|
recipient: "interface",
|
|
639
|
-
request:
|
|
925
|
+
request: D,
|
|
640
926
|
value: 0,
|
|
641
927
|
index: e
|
|
642
928
|
}, t);
|
|
643
|
-
let n = this.serialOptions_.dataBits ??
|
|
929
|
+
let n = this.serialOptions_.dataBits ?? M, r = {
|
|
644
930
|
none: 0,
|
|
645
931
|
odd: 16,
|
|
646
932
|
even: 32
|
|
647
|
-
}[this.serialOptions_.parity ??
|
|
933
|
+
}[this.serialOptions_.parity ?? N] ?? 0, i = ({
|
|
648
934
|
1: 0,
|
|
649
935
|
2: 2
|
|
650
|
-
}[this.serialOptions_.stopBits ??
|
|
936
|
+
}[this.serialOptions_.stopBits ?? P] ?? 0) << 8 | r | n;
|
|
651
937
|
await this.device_.controlTransferOut({
|
|
652
938
|
requestType: "vendor",
|
|
653
939
|
recipient: "interface",
|
|
654
|
-
request:
|
|
940
|
+
request: O,
|
|
655
941
|
value: i,
|
|
656
942
|
index: e
|
|
657
943
|
}), await this.device_.controlTransferOut({
|
|
658
944
|
requestType: "vendor",
|
|
659
945
|
recipient: "interface",
|
|
660
|
-
request:
|
|
661
|
-
value:
|
|
946
|
+
request: k,
|
|
947
|
+
value: re,
|
|
662
948
|
index: e
|
|
663
949
|
});
|
|
664
950
|
}
|
|
@@ -667,28 +953,28 @@ var I = class {
|
|
|
667
953
|
await this.device_.controlTransferOut({
|
|
668
954
|
requestType: "vendor",
|
|
669
955
|
recipient: "interface",
|
|
670
|
-
request:
|
|
671
|
-
value:
|
|
956
|
+
request: k,
|
|
957
|
+
value: ie,
|
|
672
958
|
index: e
|
|
673
959
|
}), await this.device_.controlTransferOut({
|
|
674
960
|
requestType: "vendor",
|
|
675
961
|
recipient: "interface",
|
|
676
|
-
request:
|
|
677
|
-
value:
|
|
962
|
+
request: E,
|
|
963
|
+
value: ne,
|
|
678
964
|
index: e
|
|
679
965
|
});
|
|
680
966
|
}
|
|
681
967
|
validateOptions() {
|
|
682
968
|
if (this.serialOptions_.baudRate % 1 != 0) throw RangeError(`Invalid baud rate: ${this.serialOptions_.baudRate}`);
|
|
683
|
-
if (this.serialOptions_.dataBits !== void 0 && !
|
|
684
|
-
if (this.serialOptions_.stopBits !== void 0 && !
|
|
685
|
-
if (this.serialOptions_.parity !== void 0 && !
|
|
969
|
+
if (this.serialOptions_.dataBits !== void 0 && !F.includes(this.serialOptions_.dataBits)) throw RangeError(`Invalid dataBits: ${this.serialOptions_.dataBits}`);
|
|
970
|
+
if (this.serialOptions_.stopBits !== void 0 && !I.includes(this.serialOptions_.stopBits)) throw RangeError(`Invalid stopBits: ${this.serialOptions_.stopBits}`);
|
|
971
|
+
if (this.serialOptions_.parity !== void 0 && !L.includes(this.serialOptions_.parity)) throw RangeError(`Invalid parity: ${this.serialOptions_.parity}`);
|
|
686
972
|
}
|
|
687
|
-
},
|
|
973
|
+
}, J = class {
|
|
688
974
|
options_;
|
|
689
975
|
constructor(e) {
|
|
690
976
|
this.options_ = {
|
|
691
|
-
...
|
|
977
|
+
...B,
|
|
692
978
|
...e
|
|
693
979
|
};
|
|
694
980
|
}
|
|
@@ -702,7 +988,7 @@ var I = class {
|
|
|
702
988
|
t.usbVendorId !== void 0 && (e.vendorId = t.usbVendorId), t.usbProductId !== void 0 && (e.productId = t.usbProductId), n.usbControlInterfaceClass !== void 0 && n.usbControlInterfaceClass !== 255 ? e.classCode = n.usbControlInterfaceClass : e.vendorId === void 0 && e.productId === void 0 && (e.classCode = n.usbControlInterfaceClass ?? 2), r.push(e);
|
|
703
989
|
}
|
|
704
990
|
else r.push({ classCode: n.usbControlInterfaceClass ?? 2 });
|
|
705
|
-
return new
|
|
991
|
+
return new q(await navigator.usb.requestDevice({ filters: r }), n);
|
|
706
992
|
}
|
|
707
993
|
async getPorts(e) {
|
|
708
994
|
let t = {
|
|
@@ -710,13 +996,13 @@ var I = class {
|
|
|
710
996
|
...e
|
|
711
997
|
}, n = await navigator.usb.getDevices(), r = [];
|
|
712
998
|
for (let e of n) try {
|
|
713
|
-
let n = new
|
|
999
|
+
let n = new q(e, t);
|
|
714
1000
|
r.push(n);
|
|
715
1001
|
} catch {}
|
|
716
1002
|
return r;
|
|
717
1003
|
}
|
|
718
|
-
},
|
|
719
|
-
function
|
|
1004
|
+
}, Y = "6e400001-b5a3-f393-e0a9-e50e24dcca9e", ae = "6e400003-b5a3-f393-e0a9-e50e24dcca9e", oe = "6e400002-b5a3-f393-e0a9-e50e24dcca9e", X = 20, se = 10;
|
|
1005
|
+
function ce(e) {
|
|
720
1006
|
let t = null, n = null, r = null;
|
|
721
1007
|
return {
|
|
722
1008
|
get readable() {
|
|
@@ -731,16 +1017,16 @@ function G(e) {
|
|
|
731
1017
|
async open() {
|
|
732
1018
|
if (!e.gatt) throw Error("GATT not available on this Bluetooth device.");
|
|
733
1019
|
r = await e.gatt.connect();
|
|
734
|
-
let i = await r.getPrimaryService(
|
|
1020
|
+
let i = await r.getPrimaryService(Y), a = await i.getCharacteristic(ae), o = await i.getCharacteristic(oe);
|
|
735
1021
|
await a.startNotifications(), t = new ReadableStream({ start(e) {
|
|
736
1022
|
a.addEventListener("characteristicvaluechanged", (t) => {
|
|
737
1023
|
let n = t.target.value.buffer;
|
|
738
1024
|
e.enqueue(new Uint8Array(n));
|
|
739
1025
|
});
|
|
740
1026
|
} }), n = new WritableStream({ async write(e) {
|
|
741
|
-
for (let t = 0; t < e.length; t +=
|
|
742
|
-
let n = e.slice(t, t +
|
|
743
|
-
await o.writeValueWithoutResponse(n), t +
|
|
1027
|
+
for (let t = 0; t < e.length; t += X) {
|
|
1028
|
+
let n = e.slice(t, t + X);
|
|
1029
|
+
await o.writeValueWithoutResponse(n), t + X < e.length && await new Promise((e) => setTimeout(e, se));
|
|
744
1030
|
}
|
|
745
1031
|
} });
|
|
746
1032
|
},
|
|
@@ -749,11 +1035,11 @@ function G(e) {
|
|
|
749
1035
|
}
|
|
750
1036
|
};
|
|
751
1037
|
}
|
|
752
|
-
function
|
|
1038
|
+
function le() {
|
|
753
1039
|
return {
|
|
754
1040
|
async requestPort() {
|
|
755
1041
|
if (!navigator.bluetooth) throw Error("Web Bluetooth API is not supported in this browser. Use Chrome on Android, macOS, or ChromeOS.");
|
|
756
|
-
return
|
|
1042
|
+
return ce(await navigator.bluetooth.requestDevice({ filters: [{ services: [Y] }] }));
|
|
757
1043
|
},
|
|
758
1044
|
async getPorts() {
|
|
759
1045
|
return [];
|
|
@@ -762,12 +1048,12 @@ function K() {
|
|
|
762
1048
|
}
|
|
763
1049
|
//#endregion
|
|
764
1050
|
//#region src/adapters/websocket/WebSocketProvider.ts
|
|
765
|
-
function
|
|
1051
|
+
function Z(e) {
|
|
766
1052
|
return new Promise((t, n) => {
|
|
767
1053
|
e.addEventListener("open", () => t(), { once: !0 }), e.addEventListener("error", (e) => n(e), { once: !0 });
|
|
768
1054
|
});
|
|
769
1055
|
}
|
|
770
|
-
function
|
|
1056
|
+
function Q(e, t) {
|
|
771
1057
|
return new Promise((n) => {
|
|
772
1058
|
let r = (i) => {
|
|
773
1059
|
let a = JSON.parse(i.data);
|
|
@@ -776,7 +1062,7 @@ function J(e, t) {
|
|
|
776
1062
|
e.addEventListener("message", r);
|
|
777
1063
|
});
|
|
778
1064
|
}
|
|
779
|
-
function
|
|
1065
|
+
function $(e, t) {
|
|
780
1066
|
let n = null, r = null;
|
|
781
1067
|
return {
|
|
782
1068
|
get readable() {
|
|
@@ -803,7 +1089,7 @@ function Y(e, t) {
|
|
|
803
1089
|
type: "delimiter",
|
|
804
1090
|
value: "\\n"
|
|
805
1091
|
}
|
|
806
|
-
})), await
|
|
1092
|
+
})), await Q(e, "opened");
|
|
807
1093
|
let a = [], o = null, s = !1;
|
|
808
1094
|
function c(e) {
|
|
809
1095
|
let t = JSON.parse(e.data);
|
|
@@ -834,26 +1120,26 @@ function Y(e, t) {
|
|
|
834
1120
|
}
|
|
835
1121
|
};
|
|
836
1122
|
}
|
|
837
|
-
function
|
|
1123
|
+
function ue(e) {
|
|
838
1124
|
return {
|
|
839
1125
|
async requestPort(t) {
|
|
840
1126
|
let n = new WebSocket(e);
|
|
841
|
-
await
|
|
1127
|
+
await Z(n), n.send(JSON.stringify({
|
|
842
1128
|
type: "list-ports",
|
|
843
1129
|
filters: t?.filters ?? []
|
|
844
1130
|
}));
|
|
845
|
-
let r = (await
|
|
1131
|
+
let r = (await Q(n, "port-list"))[0];
|
|
846
1132
|
if (!r) throw Error("No ports available on the bridge server. Make sure the Node.js server is running and a device is connected.");
|
|
847
|
-
return
|
|
1133
|
+
return $(n, r);
|
|
848
1134
|
},
|
|
849
1135
|
async getPorts() {
|
|
850
1136
|
let t = new WebSocket(e);
|
|
851
|
-
return await
|
|
1137
|
+
return await Z(t), t.send(JSON.stringify({
|
|
852
1138
|
type: "list-ports",
|
|
853
1139
|
filters: []
|
|
854
|
-
})), (await
|
|
1140
|
+
})), (await Q(t, "port-list")).map((e) => $(t, e));
|
|
855
1141
|
}
|
|
856
1142
|
};
|
|
857
1143
|
}
|
|
858
1144
|
//#endregion
|
|
859
|
-
export { c as AbstractSerialDevice, n as CommandQueue, e as SerialEventEmitter, i as SerialPermissionError, r as SerialPortConflictError, o as SerialReadError, t as SerialRegistry, a as SerialTimeoutError, s as SerialWriteError,
|
|
1145
|
+
export { c as AbstractSerialDevice, n as CommandQueue, e as SerialEventEmitter, i as SerialPermissionError, r as SerialPortConflictError, o as SerialReadError, t as SerialRegistry, a as SerialTimeoutError, s as SerialWriteError, J as WebUsbProvider, l as ccTalk, le as createBluetoothProvider, ue as createWebSocketProvider, f as delimiter, p as fixedLength, m as interByteTimeout, h as packetLength, g as raw, v as readline, b as readyParser, x as regexParser, C as slipDecoder, ee as slipEncode, te as spacePacket };
|
|
@@ -1 +1,2 @@
|
|
|
1
|
-
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.WebSerialCore={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class{listeners={};on(e,t){return this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),this}off(e,t){return this.listeners[e]&&this.listeners[e].delete(t),this}emit(e,...t){let n=this.listeners[e];if(!n||n.size===0)return!1;for(let e of n)e(...t);return!0}},n=class{static instances=new Set;static portInstanceMap=new WeakMap;static getInstances(){return Array.from(this.instances)}static register(e){this.instances.add(e)}static unregister(e){this.instances.delete(e)}static isPortInUse(e,t){let n=this.portInstanceMap.get(e);return n!==void 0&&n!==t}static lockPort(e,t){this.portInstanceMap.set(e,t)}static unlockPort(e){this.portInstanceMap.delete(e)}},r=class{queue=[];isProcessing=!1;isPaused=!0;timeoutId=null;commandTimeout;onSend;onTimeout;constructor(e){this.commandTimeout=e.commandTimeout,this.onSend=e.onSend,this.onTimeout=e.onTimeout}get queueSize(){return this.queue.length}enqueue(e){this.queue.push(e),this.tryProcessNext()}advance(){this.clearCommandTimeout(),this.isProcessing=!1,this.tryProcessNext()}pause(){this.isPaused=!0,this.clearCommandTimeout(),this.isProcessing=!1}resume(){this.isPaused=!1,this.tryProcessNext()}clear(){this.queue=[],this.clearCommandTimeout(),this.isProcessing=!1}snapshot(){return[...this.queue]}restore(e){this.queue=[...e,...this.queue]}tryProcessNext(){if(this.isPaused||this.isProcessing||this.queue.length===0)return;this.isProcessing=!0;let e=this.queue.shift();this.commandTimeout>0&&(this.timeoutId=setTimeout(()=>{this.timeoutId=null,this.onTimeout(e),this.advance()},this.commandTimeout)),this.onSend(e).catch(()=>{this.advance()})}clearCommandTimeout(){this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}},i=class e extends Error{constructor(t){super(t),this.name=`SerialPortConflictError`,Object.setPrototypeOf(this,e.prototype)}},a=class e extends Error{constructor(t){super(t),this.name=`SerialPermissionError`,Object.setPrototypeOf(this,e.prototype)}},o=class e extends Error{constructor(t){super(t),this.name=`SerialTimeoutError`,Object.setPrototypeOf(this,e.prototype)}},s=class e extends Error{constructor(t){super(t),this.name=`SerialReadError`,Object.setPrototypeOf(this,e.prototype)}},c=class e extends Error{constructor(t){super(t),this.name=`SerialWriteError`,Object.setPrototypeOf(this,e.prototype)}},l=class e extends t{port=null;reader=null;writer=null;queue;options;isConnecting=!1;abortController=null;userInitiatedDisconnect=!1;reconnectTimerId=null;isHandshaking=!1;static customProvider=null;static polyfillOptions;constructor(e){super(),this.options={baudRate:e.baudRate,dataBits:e.dataBits??8,stopBits:e.stopBits??1,parity:e.parity??`none`,bufferSize:e.bufferSize??255,flowControl:e.flowControl??`none`,filters:e.filters??[],commandTimeout:e.commandTimeout??0,parser:e.parser,autoReconnect:e.autoReconnect??!1,autoReconnectInterval:e.autoReconnectInterval??1500,handshakeTimeout:e.handshakeTimeout??2e3,provider:e.provider,polyfillOptions:e.polyfillOptions},this.queue=new r({commandTimeout:this.options.commandTimeout,onSend:async e=>{await this.writeToPort(e),this.emit(`serial:sent`,e,this)},onTimeout:e=>{this.emit(`serial:timeout`,e,this)}}),this.on(`serial:data`,()=>{this.queue.advance()}),n.register(this)}async handshake(){return!0}async connect(){if(!this.isConnecting&&!this.port){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{let t=this.getSerial();if(!t)throw Error(`Web Serial API is not supported in this browser. Use AbstractSerialDevice.setProvider() to set a WebUSB polyfill.`);if(this.port=await this.findAndValidatePort(),!this.port){let n;try{n=await t.requestPort({filters:this.options.filters},this.options.polyfillOptions??e.polyfillOptions)}catch(e){throw e instanceof DOMException&&(e.name===`NotFoundError`||e.name===`SecurityError`||e.name===`AbortError`)?new a(e instanceof Error?e.message:String(e)):e instanceof Error?e:Error(String(e))}if(!await this.openAndHandshake(n))throw Error(`Handshake failed: the selected device did not respond correctly.`);this.port=n}this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){if(e instanceof a?this.emit(`serial:need-permission`,this):this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port){n.unlockPort(this.port);try{await this.port.close()}catch{}this.port=null}throw e}finally{this.isConnecting=!1}}}async disconnect(){this.port&&(this.userInitiatedDisconnect=!0,this.stopReconnecting(),await this.cleanupPort())}isConnected(){return!!(this.port&&this.port.connected&&this.port.readable&&this.port.writable)}isDisconnected(){return!this.isConnected()}async cleanupPort(){if(this.port){this.queue.pause(),this.abortController?.abort(),this.abortController=null;try{let e=this.reader,t=this.writer;if(this.reader=null,this.writer=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}if(t){try{await t.close()}catch{}try{t.releaseLock()}catch{}}try{await this.port.close()}catch{}}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this)}finally{this.port&&n.unlockPort(this.port),this.port=null,this.options.parser?.reset?.(),this.emit(`serial:disconnected`,this),!this.userInitiatedDisconnect&&this.options.autoReconnect&&this.startReconnecting(),this.userInitiatedDisconnect=!1}}}async forget(){await this.disconnect(),this.port&&typeof this.port.forget==`function`&&await this.port.forget(),n.unregister(this)}async send(e){let t;t=typeof e==`string`?new TextEncoder().encode(e):e,t.length>0&&this.queue.enqueue(t)}clearQueue(){this.queue.clear(),this.emit(`serial:queue-empty`,this)}async writeToPort(e){if(!this.port||!this.port.writable)throw new c(`Port not writable.`);this.writer=this.port.writable.getWriter();try{await this.writer.write(e)}catch(e){throw new c(e instanceof Error?e.message:String(e))}finally{this.writer.releaseLock(),this.writer=null}}async readLoop(){if(!(!this.port||!this.port.readable)&&!this.reader){this.reader=this.port.readable.getReader();try{for(;;){let{value:e,done:t}=await this.reader.read();if(t)break;e&&(this.options.parser?this.options.parser.parse(e,e=>{this.emit(`serial:data`,e,this)}):this.emit(`serial:data`,e,this))}}catch(e){if(this.port)throw new s(e instanceof Error?e.message:String(e))}finally{if(this.reader){try{this.reader.releaseLock()}catch{}this.reader=null}}}}async openAndHandshake(e){let t=this;if(n.isPortInUse(e,t))return!1;n.lockPort(e,t);try{await e.open({baudRate:this.options.baudRate,dataBits:this.options.dataBits,stopBits:this.options.stopBits,parity:this.options.parity,bufferSize:this.options.bufferSize,flowControl:this.options.flowControl})}catch(t){throw n.unlockPort(e),t instanceof Error?t:Error(String(t))}this.port=e,this.abortController=new AbortController;let r=this.queue.snapshot();this.isHandshaking=!0,this.readLoop().catch(e=>{!this.isHandshaking&&this.port&&(this.emit(`serial:error`,e,this),this.cleanupPort())}),this.queue.resume();try{let t=await this.runHandshakeWithTimeout();return this.isHandshaking=!1,t?(this.queue.pause(),this.queue.clear(),this.queue.restore(r),this.options.parser?.reset?.(),!0):(await this.teardownHandshake(e,r),!1)}catch{return this.isHandshaking=!1,await this.teardownHandshake(e,r),!1}}async teardownHandshake(e,t){this.queue.pause(),this.queue.clear(),this.queue.restore(t),await this.stopReader(),this.port=null,this.abortController=null,this.options.parser?.reset?.();try{await e.close()}catch{}n.unlockPort(e)}async stopReader(){let e=this.reader;if(this.reader=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}}async runHandshakeWithTimeout(){let e=this.options.handshakeTimeout??2e3;return Promise.race([this.handshake(),new Promise(t=>setTimeout(()=>t(!1),e))])}async findAndValidatePort(){let t=this.getSerial();if(!t)return null;let r=await t.getPorts(this.options.polyfillOptions??e.polyfillOptions);if(r.length===0)return null;let i=this.options.filters??[],a=this;for(let e of r)if(!n.isPortInUse(e,a)){if(i.length>0){let t=e.getInfo();if(!i.some(e=>{let n=e.usbVendorId===void 0||e.usbVendorId===t.usbVendorId,r=e.usbProductId===void 0||e.usbProductId===t.usbProductId;return n&&r}))continue}try{if(await this.openAndHandshake(e))return e}catch{}}return null}startReconnecting(){this.reconnectTimerId||=(this.emit(`serial:reconnecting`,this),setInterval(async()=>{if(this.port||this.isConnecting){this.stopReconnecting();return}try{let e=await this.findAndValidatePort();e&&(this.stopReconnecting(),await this.reconnect(e))}catch{}},this.options.autoReconnectInterval))}stopReconnecting(){this.reconnectTimerId&&=(clearInterval(this.reconnectTimerId),null)}async reconnect(e){if(!(this.isConnecting||this.port)){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{this.port=e,this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port&&=(n.unlockPort(this.port),null),this.options.autoReconnect&&this.startReconnecting()}finally{this.isConnecting=!1}}}static getInstances(){return n.getInstances()}static async connectAll(){let e=n.getInstances();for(let t of e)try{await t.connect()}catch{}}static setProvider(t,n){e.customProvider=t,e.polyfillOptions=n}getSerial(){return this.options.provider?this.options.provider:e.customProvider?e.customProvider:typeof navigator<`u`&&navigator.serial?navigator.serial:null}};function u(e){if(e<=0)throw Error(`FixedLengthParser: length must be greater than 0`);let t=new Uint8Array;return{parse(n,r){let i=new Uint8Array(t.length+n.length);for(i.set(t),i.set(n,t.length),t=i;t.length>=e;)r(t.slice(0,e)),t=t.slice(e)},reset(){t=new Uint8Array}}}function d(e){let t=``,n=new TextDecoder;return{parse(r,i){t+=n.decode(r,{stream:!0});let a;for(;(a=t.indexOf(e))!==-1;)i(t.slice(0,a)),t=t.slice(a+e.length)},reset(){t=``,n=new TextDecoder}}}function f(){return{parse(e,t){t(e)},reset(){}}}var p=32,m=34,h=0,g=30,_=3,v=7,y=1,b=0,x=771,S=768,C=255,w=8,T=`none`,E=1,D=[16,8,7,6,5],O=[1,2],k=[`none`,`even`,`odd`],A=[`none`,`odd`,`even`],j=[1,1.5,2],M={usbControlInterfaceClass:2,usbTransferInterfaceClass:10,protocol:void 0};function N(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces)if(e.alternates[0]?.interfaceClass===t)return e;return null}function P(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces){let n=e.alternates[0];if(!n||n.interfaceClass!==t)continue;let r=n.endpoints.some(e=>e.direction===`in`),i=n.endpoints.some(e=>e.direction===`out`);if(r&&i)return e}return null}function F(e,t){let n=e.alternates[0];if(n){for(let e of n.endpoints)if(e.direction===t)return e}throw TypeError(`Interface ${e.interfaceNumber} does not have an ${t} endpoint.`)}function I(e,t){return t===2?`cdc_acm`:e.vendorId===4292?`cp210x`:`none`}var L=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}pull(e){(async()=>{let t=this.endpoint_.packetSize;try{let n=await this.device_.transferIn(this.endpoint_.endpointNumber,t);if(n.status!==`ok`){e.error(`USB error: ${n.status}`),this.onError_();return}if(n.data?.buffer&&n.data.byteLength>0){let t=new Uint8Array(n.data.buffer,n.data.byteOffset,n.data.byteLength);t.length>0&&e.enqueue(t)}}catch(t){e.error(String(t)),this.onError_()}})()}},R=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}async write(e,t){try{let n=await this.device_.transferOut(this.endpoint_.endpointNumber,e.buffer);n.status!==`ok`&&(t.error(n.status),this.onError_())}catch(e){t.error(String(e)),this.onError_()}}},z=class{device_;protocol_;controlInterface_;transferInterface_;inEndpoint_;outEndpoint_;serialOptions_;readable_=null;writable_=null;cdcOutputSignals_={dataTerminalReady:!1,requestToSend:!1,break:!1};constructor(e,t){this.device_=e;let n={...M,...t};this.protocol_=n.protocol??I(e,n.usbControlInterfaceClass);let r=n.usbControlInterfaceClass,i=n.usbTransferInterfaceClass;if(r===i){let t=P(e,i);if(!t)throw TypeError(`Unable to find interface with class ${i} that has both IN and OUT endpoints.`);this.controlInterface_=t,this.transferInterface_=t}else{let t=N(e,r);if(!t)throw TypeError(`Unable to find control interface with class ${r}.`);let n=P(e,i)??N(e,i);if(!n)throw TypeError(`Unable to find transfer interface with class ${i}.`);this.controlInterface_=t,this.transferInterface_=n}this.inEndpoint_=F(this.transferInterface_,`in`),this.outEndpoint_=F(this.transferInterface_,`out`)}get readable(){return!this.readable_&&this.device_.opened&&(this.readable_=new ReadableStream(new L(this.device_,this.inEndpoint_,()=>{this.readable_=null}),{highWaterMark:this.serialOptions_?.bufferSize??C})),this.readable_}get writable(){return!this.writable_&&this.device_.opened&&(this.writable_=new WritableStream(new R(this.device_,this.outEndpoint_,()=>{this.writable_=null}),new ByteLengthQueuingStrategy({highWaterMark:this.serialOptions_?.bufferSize??C}))),this.writable_}async open(e){this.serialOptions_=e,this.validateOptions();try{switch(await this.device_.open(),this.device_.configuration===null&&await this.device_.selectConfiguration(1),await this.device_.claimInterface(this.controlInterface_.interfaceNumber),this.controlInterface_!==this.transferInterface_&&await this.device_.claimInterface(this.transferInterface_.interfaceNumber),this.protocol_){case`cdc_acm`:await this.cdcInit();break;case`cp210x`:await this.cp210xInit();break;case`none`:break}}catch(e){throw this.device_.opened&&await this.device_.close(),Error(`Error setting up device: `+(e instanceof Error?e.message:String(e)),{cause:e})}}async close(){let e=[];if(this.readable_&&e.push(this.readable_.cancel()),this.writable_&&e.push(this.writable_.abort()),await Promise.all(e),this.readable_=null,this.writable_=null,this.device_.opened){switch(this.protocol_){case`cdc_acm`:await this.cdcSetSignals({dataTerminalReady:!1,requestToSend:!1});break;case`cp210x`:await this.cp210xDeinit();break}await this.device_.close()}}async forget(){return this.device_.forget()}getInfo(){return{usbVendorId:this.device_.vendorId,usbProductId:this.device_.productId}}async cdcInit(){await this.cdcSetLineCoding(),await this.cdcSetSignals({dataTerminalReady:!0})}async cdcSetSignals(e){if(this.cdcOutputSignals_={...this.cdcOutputSignals_,...e},e.dataTerminalReady!==void 0||e.requestToSend!==void 0){let e=!!this.cdcOutputSignals_.dataTerminalReady|(this.cdcOutputSignals_.requestToSend?2:0);await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:m,value:e,index:this.controlInterface_.interfaceNumber})}}async cdcSetLineCoding(){let e=new ArrayBuffer(7),t=new DataView(e);if(t.setUint32(0,this.serialOptions_.baudRate,!0),t.setUint8(4,j.indexOf(this.serialOptions_.stopBits??E)),t.setUint8(5,A.indexOf(this.serialOptions_.parity??T)),t.setUint8(6,this.serialOptions_.dataBits??w),(await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:p,value:0,index:this.controlInterface_.interfaceNumber},e)).status!==`ok`)throw new DOMException(`Failed to set line coding.`,`NetworkError`)}async cp210xInit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:h,value:y,index:e});let t=new ArrayBuffer(4);new DataView(t).setUint32(0,this.serialOptions_.baudRate,!0),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:g,value:0,index:e},t);let n=this.serialOptions_.dataBits??w,r={none:0,odd:16,even:32}[this.serialOptions_.parity??T]??0,i=({1:0,2:2}[this.serialOptions_.stopBits??E]??0)<<8|r|n;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:_,value:i,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:v,value:x,index:e})}async cp210xDeinit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:v,value:S,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:h,value:b,index:e})}validateOptions(){if(this.serialOptions_.baudRate%1!=0)throw RangeError(`Invalid baud rate: ${this.serialOptions_.baudRate}`);if(this.serialOptions_.dataBits!==void 0&&!D.includes(this.serialOptions_.dataBits))throw RangeError(`Invalid dataBits: ${this.serialOptions_.dataBits}`);if(this.serialOptions_.stopBits!==void 0&&!O.includes(this.serialOptions_.stopBits))throw RangeError(`Invalid stopBits: ${this.serialOptions_.stopBits}`);if(this.serialOptions_.parity!==void 0&&!k.includes(this.serialOptions_.parity))throw RangeError(`Invalid parity: ${this.serialOptions_.parity}`)}},B=class{options_;constructor(e){this.options_={...M,...e}}async requestPort(e,t){let n={...this.options_,...t},r=[];if(e?.filters&&e.filters.length>0)for(let t of e.filters){let e={};t.usbVendorId!==void 0&&(e.vendorId=t.usbVendorId),t.usbProductId!==void 0&&(e.productId=t.usbProductId),n.usbControlInterfaceClass!==void 0&&n.usbControlInterfaceClass!==255?e.classCode=n.usbControlInterfaceClass:e.vendorId===void 0&&e.productId===void 0&&(e.classCode=n.usbControlInterfaceClass??2),r.push(e)}else r.push({classCode:n.usbControlInterfaceClass??2});return new z(await navigator.usb.requestDevice({filters:r}),n)}async getPorts(e){let t={...this.options_,...e},n=await navigator.usb.getDevices(),r=[];for(let e of n)try{let n=new z(e,t);r.push(n)}catch{}return r}},V=`6e400001-b5a3-f393-e0a9-e50e24dcca9e`,H=`6e400003-b5a3-f393-e0a9-e50e24dcca9e`,U=`6e400002-b5a3-f393-e0a9-e50e24dcca9e`,W=20,G=10;function K(e){let t=null,n=null,r=null;return{get readable(){return t},get writable(){return n},getInfo(){return{}},async open(){if(!e.gatt)throw Error(`GATT not available on this Bluetooth device.`);r=await e.gatt.connect();let i=await r.getPrimaryService(V),a=await i.getCharacteristic(H),o=await i.getCharacteristic(U);await a.startNotifications(),t=new ReadableStream({start(e){a.addEventListener(`characteristicvaluechanged`,t=>{let n=t.target.value.buffer;e.enqueue(new Uint8Array(n))})}}),n=new WritableStream({async write(e){for(let t=0;t<e.length;t+=W){let n=e.slice(t,t+W);await o.writeValueWithoutResponse(n),t+W<e.length&&await new Promise(e=>setTimeout(e,G))}}})},async close(){r?.connected&&r.disconnect(),t=null,n=null}}}function q(){return{async requestPort(){if(!navigator.bluetooth)throw Error(`Web Bluetooth API is not supported in this browser. Use Chrome on Android, macOS, or ChromeOS.`);return K(await navigator.bluetooth.requestDevice({filters:[{services:[V]}]}))},async getPorts(){return[]}}}function J(e){return new Promise((t,n)=>{e.addEventListener(`open`,()=>t(),{once:!0}),e.addEventListener(`error`,e=>n(e),{once:!0})})}function Y(e,t){return new Promise(n=>{let r=i=>{let a=JSON.parse(i.data);a.type===t&&(e.removeEventListener(`message`,r),n(a.payload))};e.addEventListener(`message`,r)})}function X(e,t){let n=null,r=null;return{get readable(){return n},get writable(){return r},getInfo(){return{usbVendorId:t.vendorId,usbProductId:t.productId}},async open(i){e.send(JSON.stringify({type:`open`,path:t.path,baudRate:i.baudRate,dataBits:i.dataBits,stopBits:i.stopBits,parity:i.parity,parser:{type:`delimiter`,value:`\\n`}})),await Y(e,`opened`);let a=[],o=null,s=!1;function c(e){let t=JSON.parse(e.data);if(t.type===`data`&&t.bytes){let e=new Uint8Array(t.bytes);o?o.enqueue(e):a.push(e)}t.type===`closed`&&(s=!0,o&&o.close())}e.addEventListener(`message`,c),n=new ReadableStream({start(e){o=e;for(let t of a)e.enqueue(t);a.length=0,s&&e.close()},cancel(){e.removeEventListener(`message`,c),o=null}}),r=new WritableStream({write(t){e.send(JSON.stringify({type:`write`,bytes:Array.from(t)}))}})},async close(){e.send(JSON.stringify({type:`close`})),n=null,r=null,e.close()}}}function Z(e){return{async requestPort(t){let n=new WebSocket(e);await J(n),n.send(JSON.stringify({type:`list-ports`,filters:t?.filters??[]}));let r=(await Y(n,`port-list`))[0];if(!r)throw Error(`No ports available on the bridge server. Make sure the Node.js server is running and a device is connected.`);return X(n,r)},async getPorts(){let t=new WebSocket(e);return await J(t),t.send(JSON.stringify({type:`list-ports`,filters:[]})),(await Y(t,`port-list`)).map(e=>X(t,e))}}}e.AbstractSerialDevice=l,e.CommandQueue=r,e.SerialEventEmitter=t,e.SerialPermissionError=a,e.SerialPortConflictError=i,e.SerialReadError=s,e.SerialRegistry=n,e.SerialTimeoutError=o,e.SerialWriteError=c,e.WebUsbProvider=B,e.createBluetoothProvider=q,e.createWebSocketProvider=Z,e.delimiter=d,e.fixedLength=u,e.raw=f});
|
|
1
|
+
(function(e,t){typeof exports==`object`&&typeof module<`u`?t(exports):typeof define==`function`&&define.amd?define([`exports`],t):(e=typeof globalThis<`u`?globalThis:e||self,t(e.WebSerialCore={}))})(this,function(e){Object.defineProperty(e,Symbol.toStringTag,{value:`Module`});var t=class{listeners={};on(e,t){return this.listeners[e]||(this.listeners[e]=new Set),this.listeners[e].add(t),this}off(e,t){return this.listeners[e]&&this.listeners[e].delete(t),this}emit(e,...t){let n=this.listeners[e];if(!n||n.size===0)return!1;for(let e of n)e(...t);return!0}},n=class{static instances=new Set;static portInstanceMap=new WeakMap;static getInstances(){return Array.from(this.instances)}static register(e){this.instances.add(e)}static unregister(e){this.instances.delete(e)}static isPortInUse(e,t){let n=this.portInstanceMap.get(e);return n!==void 0&&n!==t}static lockPort(e,t){this.portInstanceMap.set(e,t)}static unlockPort(e){this.portInstanceMap.delete(e)}},r=class{queue=[];isProcessing=!1;isPaused=!0;timeoutId=null;commandTimeout;onSend;onTimeout;constructor(e){this.commandTimeout=e.commandTimeout,this.onSend=e.onSend,this.onTimeout=e.onTimeout}get queueSize(){return this.queue.length}enqueue(e){this.queue.push(e),this.tryProcessNext()}advance(){this.clearCommandTimeout(),this.isProcessing=!1,this.tryProcessNext()}pause(){this.isPaused=!0,this.clearCommandTimeout(),this.isProcessing=!1}resume(){this.isPaused=!1,this.tryProcessNext()}clear(){this.queue=[],this.clearCommandTimeout(),this.isProcessing=!1}snapshot(){return[...this.queue]}restore(e){this.queue=[...e,...this.queue]}tryProcessNext(){if(this.isPaused||this.isProcessing||this.queue.length===0)return;this.isProcessing=!0;let e=this.queue.shift();this.commandTimeout>0&&(this.timeoutId=setTimeout(()=>{this.timeoutId=null,this.onTimeout(e),this.advance()},this.commandTimeout)),this.onSend(e).catch(()=>{this.advance()})}clearCommandTimeout(){this.timeoutId!==null&&(clearTimeout(this.timeoutId),this.timeoutId=null)}},i=class e extends Error{constructor(t){super(t),this.name=`SerialPortConflictError`,Object.setPrototypeOf(this,e.prototype)}},a=class e extends Error{constructor(t){super(t),this.name=`SerialPermissionError`,Object.setPrototypeOf(this,e.prototype)}},o=class e extends Error{constructor(t){super(t),this.name=`SerialTimeoutError`,Object.setPrototypeOf(this,e.prototype)}},s=class e extends Error{constructor(t){super(t),this.name=`SerialReadError`,Object.setPrototypeOf(this,e.prototype)}},c=class e extends Error{constructor(t){super(t),this.name=`SerialWriteError`,Object.setPrototypeOf(this,e.prototype)}},l=class e extends t{port=null;reader=null;writer=null;queue;options;isConnecting=!1;abortController=null;userInitiatedDisconnect=!1;reconnectTimerId=null;isHandshaking=!1;static customProvider=null;static polyfillOptions;constructor(e){super(),this.options={baudRate:e.baudRate,dataBits:e.dataBits??8,stopBits:e.stopBits??1,parity:e.parity??`none`,bufferSize:e.bufferSize??255,flowControl:e.flowControl??`none`,filters:e.filters??[],commandTimeout:e.commandTimeout??0,parser:e.parser,autoReconnect:e.autoReconnect??!1,autoReconnectInterval:e.autoReconnectInterval??1500,handshakeTimeout:e.handshakeTimeout??2e3,provider:e.provider,polyfillOptions:e.polyfillOptions},this.queue=new r({commandTimeout:this.options.commandTimeout,onSend:async e=>{await this.writeToPort(e),this.emit(`serial:sent`,e,this)},onTimeout:e=>{this.emit(`serial:timeout`,e,this)}}),this.on(`serial:data`,()=>{this.queue.advance()}),n.register(this)}async handshake(){return!0}async connect(){if(!this.isConnecting&&!this.port){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{let t=this.getSerial();if(!t)throw Error(`Web Serial API is not supported in this browser. Use AbstractSerialDevice.setProvider() to set a WebUSB polyfill.`);if(this.port=await this.findAndValidatePort(),!this.port){let n;try{n=await t.requestPort({filters:this.options.filters},this.options.polyfillOptions??e.polyfillOptions)}catch(e){throw e instanceof DOMException&&(e.name===`NotFoundError`||e.name===`SecurityError`||e.name===`AbortError`)?new a(e instanceof Error?e.message:String(e)):e instanceof Error?e:Error(String(e))}if(!await this.openAndHandshake(n))throw Error(`Handshake failed: the selected device did not respond correctly.`);this.port=n}this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){if(e instanceof a?this.emit(`serial:need-permission`,this):this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port){n.unlockPort(this.port);try{await this.port.close()}catch{}this.port=null}throw e}finally{this.isConnecting=!1}}}async disconnect(){this.port&&(this.userInitiatedDisconnect=!0,this.stopReconnecting(),await this.cleanupPort())}isConnected(){return!!(this.port&&this.port.connected&&this.port.readable&&this.port.writable)}isDisconnected(){return!this.isConnected()}async cleanupPort(){if(this.port){this.queue.pause(),this.abortController?.abort(),this.abortController=null;try{let e=this.reader,t=this.writer;if(this.reader=null,this.writer=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}if(t){try{await t.close()}catch{}try{t.releaseLock()}catch{}}try{await this.port.close()}catch{}}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this)}finally{this.port&&n.unlockPort(this.port),this.port=null,this.options.parser?.reset?.(),this.emit(`serial:disconnected`,this),!this.userInitiatedDisconnect&&this.options.autoReconnect&&this.startReconnecting(),this.userInitiatedDisconnect=!1}}}async forget(){await this.disconnect(),this.port&&typeof this.port.forget==`function`&&await this.port.forget(),n.unregister(this)}async send(e){let t;t=typeof e==`string`?new TextEncoder().encode(e):e,t.length>0&&this.queue.enqueue(t)}clearQueue(){this.queue.clear(),this.emit(`serial:queue-empty`,this)}async writeToPort(e){if(!this.port||!this.port.writable)throw new c(`Port not writable.`);this.writer=this.port.writable.getWriter();try{await this.writer.write(e)}catch(e){throw new c(e instanceof Error?e.message:String(e))}finally{this.writer.releaseLock(),this.writer=null}}async readLoop(){if(!(!this.port||!this.port.readable)&&!this.reader){this.reader=this.port.readable.getReader();try{for(;;){let{value:e,done:t}=await this.reader.read();if(t)break;e&&(this.options.parser?this.options.parser.parse(e,e=>{this.emit(`serial:data`,e,this)}):this.emit(`serial:data`,e,this))}}catch(e){if(this.port)throw new s(e instanceof Error?e.message:String(e))}finally{if(this.reader){try{this.reader.releaseLock()}catch{}this.reader=null}}}}async openAndHandshake(e){let t=this;if(n.isPortInUse(e,t))return!1;n.lockPort(e,t);try{await e.open({baudRate:this.options.baudRate,dataBits:this.options.dataBits,stopBits:this.options.stopBits,parity:this.options.parity,bufferSize:this.options.bufferSize,flowControl:this.options.flowControl})}catch(t){throw n.unlockPort(e),t instanceof Error?t:Error(String(t))}this.port=e,this.abortController=new AbortController;let r=this.queue.snapshot();this.isHandshaking=!0,this.readLoop().catch(e=>{!this.isHandshaking&&this.port&&(this.emit(`serial:error`,e,this),this.cleanupPort())}),this.queue.resume();try{let t=await this.runHandshakeWithTimeout();return this.isHandshaking=!1,t?(this.queue.pause(),this.queue.clear(),this.queue.restore(r),this.options.parser?.reset?.(),!0):(await this.teardownHandshake(e,r),!1)}catch{return this.isHandshaking=!1,await this.teardownHandshake(e,r),!1}}async teardownHandshake(e,t){this.queue.pause(),this.queue.clear(),this.queue.restore(t),await this.stopReader(),this.port=null,this.abortController=null,this.options.parser?.reset?.();try{await e.close()}catch{}n.unlockPort(e)}async stopReader(){let e=this.reader;if(this.reader=null,e){try{await e.cancel()}catch{}try{e.releaseLock()}catch{}}}async runHandshakeWithTimeout(){let e=this.options.handshakeTimeout??2e3;return Promise.race([this.handshake(),new Promise(t=>setTimeout(()=>t(!1),e))])}async findAndValidatePort(){let t=this.getSerial();if(!t)return null;let r=await t.getPorts(this.options.polyfillOptions??e.polyfillOptions);if(r.length===0)return null;let i=this.options.filters??[],a=this;for(let e of r)if(!n.isPortInUse(e,a)){if(i.length>0){let t=e.getInfo();if(!i.some(e=>{let n=e.usbVendorId===void 0||e.usbVendorId===t.usbVendorId,r=e.usbProductId===void 0||e.usbProductId===t.usbProductId;return n&&r}))continue}try{if(await this.openAndHandshake(e))return e}catch{}}return null}startReconnecting(){this.reconnectTimerId||=(this.emit(`serial:reconnecting`,this),setInterval(async()=>{if(this.port||this.isConnecting){this.stopReconnecting();return}try{let e=await this.findAndValidatePort();e&&(this.stopReconnecting(),await this.reconnect(e))}catch{}},this.options.autoReconnectInterval))}stopReconnecting(){this.reconnectTimerId&&=(clearInterval(this.reconnectTimerId),null)}async reconnect(e){if(!(this.isConnecting||this.port)){this.isConnecting=!0,this.emit(`serial:connecting`,this);try{this.port=e,this.abortController=new AbortController,this.queue.resume(),this.emit(`serial:connected`,this)}catch(e){this.emit(`serial:error`,e instanceof Error?e:Error(String(e)),this),this.port&&=(n.unlockPort(this.port),null),this.options.autoReconnect&&this.startReconnecting()}finally{this.isConnecting=!1}}}static getInstances(){return n.getInstances()}static async connectAll(){let e=n.getInstances();for(let t of e)try{await t.connect()}catch{}}static setProvider(t,n){e.customProvider=t,e.polyfillOptions=n}getSerial(){return this.options.provider?this.options.provider:e.customProvider?e.customProvider:typeof navigator<`u`&&navigator.serial?navigator.serial:null}};function u(e=50){let t=new Uint8Array,n=null;function r(e){for(;!(t.length<2);){let n=t[1]+5;if(t.length<n)break;e(t.slice(0,n)),t=t.slice(n)}}return{parse(i,a){n!==null&&(clearTimeout(n),n=null);let o=new Uint8Array(t.length+i.length);o.set(t),o.set(i,t.length),t=o,r(a),t.length>0&&(n=setTimeout(()=>{t=new Uint8Array,n=null},e))},reset(){n!==null&&(clearTimeout(n),n=null),t=new Uint8Array}}}function d(e){return typeof e==`string`?new TextEncoder().encode(e):e instanceof Uint8Array?e:new Uint8Array(e)}function f(e,t){if(t.length===0)return 0;outer:for(let n=0;n<=e.length-t.length;n++){for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])continue outer;return n}return-1}function p(e,t){let n=t?.includeDelimiter??!1,r=d(e);if(typeof e==`string`){let e=new Uint8Array,t=new TextDecoder;return{parse(i,a){let o=new Uint8Array(e.length+i.length);o.set(e),o.set(i,e.length),e=o;let s;for(;(s=f(e,r))!==-1;){let i=n?s+r.length:s;a(t.decode(e.slice(0,i))),t=new TextDecoder,e=e.slice(s+r.length)}},reset(){e=new Uint8Array,t=new TextDecoder}}}let i=new Uint8Array;return{parse(e,t){let a=new Uint8Array(i.length+e.length);a.set(i),a.set(e,i.length),i=a;let o;for(;(o=f(i,r))!==-1;){let e=n?o+r.length:o;t(i.slice(0,e)),i=i.slice(o+r.length)}},reset(){i=new Uint8Array}}}function m(e){if(e<=0)throw Error(`FixedLengthParser: length must be greater than 0`);let t=new Uint8Array;return{parse(n,r){let i=new Uint8Array(t.length+n.length);for(i.set(t),i.set(n,t.length),t=i;t.length>=e;)r(t.slice(0,e)),t=t.slice(e)},reset(){t=new Uint8Array}}}function h(e){if(e.interval<=0)throw Error(`InterByteTimeoutParser: interval must be greater than 0`);let t=e.maxBufferSize??65536,n=new Uint8Array,r=null,i=null;function a(){r!==null&&(clearTimeout(r),r=null),n.length>0&&i!==null&&(i(n.slice()),n=new Uint8Array)}return{parse(o,s){i=s,r!==null&&(clearTimeout(r),r=null);let c=new Uint8Array(n.length+o.length);if(c.set(n),c.set(o,n.length),n=c,n.length>=t){a();return}r=setTimeout(()=>{r=null,a()},e.interval)},reset(){r!==null&&(clearTimeout(r),r=null),n=new Uint8Array,i=null}}}function g(e){let t=e?.delimiter??170,n=e?.packetOverhead??2,r=e?.lengthBytes??1,i=e?.lengthOffset??1,a=e?.maxLen??255;if(i+r>n)throw Error(`PacketLengthParser: lengthOffset + lengthBytes must not exceed packetOverhead`);let o=new Uint8Array;return{parse(e,s){let c=new Uint8Array(o.length+e.length);for(c.set(o),c.set(e,o.length),o=c;;){let e=o.indexOf(t);if(e===-1){o=new Uint8Array;break}e>0&&(o=o.slice(e));let c=i+r;if(o.length<c)break;let l=0;for(let e=0;e<r;e++)l=l<<8|o[i+e];if(l>a){o=o.slice(1);continue}let u=l+n;if(o.length<u)break;s(o.slice(0,u)),o=o.slice(u)}},reset(){o=new Uint8Array}}}function _(){return{parse(e,t){t(e)},reset(){}}}function v(e,t){if(t.length===0)return 0;outer:for(let n=0;n<=e.length-t.length;n++){for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])continue outer;return n}return-1}function y(e){let t=e?.encoding??`utf-8`,n=e?.includeDelimiter??!1,r=e?.delimiter??`
|
|
2
|
+
`,i;i=typeof r==`string`?new TextEncoder().encode(r):r instanceof Uint8Array?r:new Uint8Array(r);let a=new Uint8Array;return{parse(e,r){let o=new Uint8Array(a.length+e.length);o.set(a),o.set(e,a.length),a=o;let s;for(;(s=v(a,i))!==-1;){let e=n?s+i.length:s;r(new TextDecoder(t).decode(a.slice(0,e))),a=a.slice(s+i.length)}},reset(){a=new Uint8Array}}}function b(e,t){if(t.length===0)return 0;outer:for(let n=0;n<=e.length-t.length;n++){for(let r=0;r<t.length;r++)if(e[n+r]!==t[r])continue outer;return n}return-1}function x(e){let t=e.delimiter,n;n=typeof t==`string`?new TextEncoder().encode(t):t instanceof Uint8Array?t:new Uint8Array(t);let r=!1,i=new Uint8Array;return{parse(t,a){if(r){a(t);return}let o=new Uint8Array(i.length+t.length);o.set(i),o.set(t,i.length),i=o;let s=b(i,n);if(s===-1)return;r=!0,e.onReady?.();let c=i.slice(s+n.length);i=new Uint8Array,c.length>0&&a(c)},reset(){r=!1,i=new Uint8Array}}}function S(e){let t=e.regex instanceof RegExp?e.regex:new RegExp(e.regex),n=e.encoding??`utf-8`,r=``;return{parse(e,i){let a=new TextDecoder(n);r+=a.decode(e);let o=r.split(t);r=o.pop()??``;for(let e of o)i(e)},reset(){r=``}}}var C={END:192,ESC:219,ESC_END:220,ESC_ESC:221};function ee(e){let t=e?.END??C.END,n=e?.ESC??C.ESC,r=e?.ESC_END??C.ESC_END,i=e?.ESC_ESC??C.ESC_ESC,a=e?.START,o=e?.ESC_START??n,s=[],c=!1,l=a===void 0;return{parse(e,u){for(let d=0;d<e.length;d++){let f=e[d];if(!l){f===a&&(l=!0);continue}if(f===t){s.length>0&&(u(new Uint8Array(s)),s=[]),a!==void 0&&(l=!1),c=!1;continue}if(c){c=!1,f===r?s.push(t):f===i?s.push(n):a!==void 0&&f===o?s.push(a):s.push(f);continue}if(f===n){c=!0;continue}s.push(f)}},reset(){s=[],c=!1,l=a===void 0}}}function w(e,t){let n=t?.END??C.END,r=t?.ESC??C.ESC,i=t?.ESC_END??C.ESC_END,a=t?.ESC_ESC??C.ESC_ESC,o=t?.START,s=t?.ESC_START??r,c=t?.bluetoothQuirk??!1,l=[];c&&l.push(n);for(let t=0;t<e.length;t++){let c=e[t];c===n?l.push(r,i):c===r?l.push(r,a):o!==void 0&&c===o?l.push(r,s):l.push(c)}return l.push(n),new Uint8Array(l)}function T(e){let t=e?.timeCodeFieldLength??0,n=e?.ancillaryDataFieldLength??0,r=new Uint8Array;function i(e){let r=e[0],i=e[1],a=e[2],o=e[3],s=e[4],c=e[5],l=r>>5&7,u=r>>4&1,d=r>>3&1,f=(r&7)<<8|i,p=a>>6&3,m=(a&63)<<8|o,h=s<<8|c,g={versionNumber:l,identification:{apid:f,secondaryHeader:d,type:u},sequenceControl:{packetName:m,sequenceFlags:p},dataLength:h},_,v=6;if(d===1){_={};let r=new TextDecoder(`latin1`);t>0&&(_.timeCode=r.decode(e.slice(v,v+t)),v+=t),n>0&&(_.ancillaryData=r.decode(e.slice(v,v+n)),v+=n)}let y=new TextDecoder(`latin1`).decode(e.slice(v));return{header:g,secondaryHeader:_,data:y}}return{parse(e,t){let n=new Uint8Array(r.length+e.length);for(n.set(r),n.set(e,r.length),r=n;r.length>=6;){let e=6+(r[4]<<8|r[5])+1;if(r.length<e)break;t(i(r.slice(0,e))),r=r.slice(e)}},reset(){r=new Uint8Array}}}var E=32,D=34,O=0,k=30,A=3,j=7,te=1,ne=0,re=771,ie=768,M=255,N=8,P=`none`,F=1,I=[16,8,7,6,5],L=[1,2],R=[`none`,`even`,`odd`],z=[`none`,`odd`,`even`],B=[1,1.5,2],V={usbControlInterfaceClass:2,usbTransferInterfaceClass:10,protocol:void 0};function H(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces)if(e.alternates[0]?.interfaceClass===t)return e;return null}function U(e,t){let n=e.configurations[0];if(!n)return null;for(let e of n.interfaces){let n=e.alternates[0];if(!n||n.interfaceClass!==t)continue;let r=n.endpoints.some(e=>e.direction===`in`),i=n.endpoints.some(e=>e.direction===`out`);if(r&&i)return e}return null}function W(e,t){let n=e.alternates[0];if(n){for(let e of n.endpoints)if(e.direction===t)return e}throw TypeError(`Interface ${e.interfaceNumber} does not have an ${t} endpoint.`)}function G(e,t){return t===2?`cdc_acm`:e.vendorId===4292?`cp210x`:`none`}var K=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}pull(e){(async()=>{let t=this.endpoint_.packetSize;try{let n=await this.device_.transferIn(this.endpoint_.endpointNumber,t);if(n.status!==`ok`){e.error(`USB error: ${n.status}`),this.onError_();return}if(n.data?.buffer&&n.data.byteLength>0){let t=new Uint8Array(n.data.buffer,n.data.byteOffset,n.data.byteLength);t.length>0&&e.enqueue(t)}}catch(t){e.error(String(t)),this.onError_()}})()}},q=class{device_;endpoint_;onError_;constructor(e,t,n){this.device_=e,this.endpoint_=t,this.onError_=n}async write(e,t){try{let n=await this.device_.transferOut(this.endpoint_.endpointNumber,e.buffer);n.status!==`ok`&&(t.error(n.status),this.onError_())}catch(e){t.error(String(e)),this.onError_()}}},J=class{device_;protocol_;controlInterface_;transferInterface_;inEndpoint_;outEndpoint_;serialOptions_;readable_=null;writable_=null;cdcOutputSignals_={dataTerminalReady:!1,requestToSend:!1,break:!1};constructor(e,t){this.device_=e;let n={...V,...t};this.protocol_=n.protocol??G(e,n.usbControlInterfaceClass);let r=n.usbControlInterfaceClass,i=n.usbTransferInterfaceClass;if(r===i){let t=U(e,i);if(!t)throw TypeError(`Unable to find interface with class ${i} that has both IN and OUT endpoints.`);this.controlInterface_=t,this.transferInterface_=t}else{let t=H(e,r);if(!t)throw TypeError(`Unable to find control interface with class ${r}.`);let n=U(e,i)??H(e,i);if(!n)throw TypeError(`Unable to find transfer interface with class ${i}.`);this.controlInterface_=t,this.transferInterface_=n}this.inEndpoint_=W(this.transferInterface_,`in`),this.outEndpoint_=W(this.transferInterface_,`out`)}get readable(){return!this.readable_&&this.device_.opened&&(this.readable_=new ReadableStream(new K(this.device_,this.inEndpoint_,()=>{this.readable_=null}),{highWaterMark:this.serialOptions_?.bufferSize??M})),this.readable_}get writable(){return!this.writable_&&this.device_.opened&&(this.writable_=new WritableStream(new q(this.device_,this.outEndpoint_,()=>{this.writable_=null}),new ByteLengthQueuingStrategy({highWaterMark:this.serialOptions_?.bufferSize??M}))),this.writable_}async open(e){this.serialOptions_=e,this.validateOptions();try{switch(await this.device_.open(),this.device_.configuration===null&&await this.device_.selectConfiguration(1),await this.device_.claimInterface(this.controlInterface_.interfaceNumber),this.controlInterface_!==this.transferInterface_&&await this.device_.claimInterface(this.transferInterface_.interfaceNumber),this.protocol_){case`cdc_acm`:await this.cdcInit();break;case`cp210x`:await this.cp210xInit();break;case`none`:break}}catch(e){throw this.device_.opened&&await this.device_.close(),Error(`Error setting up device: `+(e instanceof Error?e.message:String(e)),{cause:e})}}async close(){let e=[];if(this.readable_&&e.push(this.readable_.cancel()),this.writable_&&e.push(this.writable_.abort()),await Promise.all(e),this.readable_=null,this.writable_=null,this.device_.opened){switch(this.protocol_){case`cdc_acm`:await this.cdcSetSignals({dataTerminalReady:!1,requestToSend:!1});break;case`cp210x`:await this.cp210xDeinit();break}await this.device_.close()}}async forget(){return this.device_.forget()}getInfo(){return{usbVendorId:this.device_.vendorId,usbProductId:this.device_.productId}}async cdcInit(){await this.cdcSetLineCoding(),await this.cdcSetSignals({dataTerminalReady:!0})}async cdcSetSignals(e){if(this.cdcOutputSignals_={...this.cdcOutputSignals_,...e},e.dataTerminalReady!==void 0||e.requestToSend!==void 0){let e=!!this.cdcOutputSignals_.dataTerminalReady|(this.cdcOutputSignals_.requestToSend?2:0);await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:D,value:e,index:this.controlInterface_.interfaceNumber})}}async cdcSetLineCoding(){let e=new ArrayBuffer(7),t=new DataView(e);if(t.setUint32(0,this.serialOptions_.baudRate,!0),t.setUint8(4,B.indexOf(this.serialOptions_.stopBits??F)),t.setUint8(5,z.indexOf(this.serialOptions_.parity??P)),t.setUint8(6,this.serialOptions_.dataBits??N),(await this.device_.controlTransferOut({requestType:`class`,recipient:`interface`,request:E,value:0,index:this.controlInterface_.interfaceNumber},e)).status!==`ok`)throw new DOMException(`Failed to set line coding.`,`NetworkError`)}async cp210xInit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:O,value:te,index:e});let t=new ArrayBuffer(4);new DataView(t).setUint32(0,this.serialOptions_.baudRate,!0),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:k,value:0,index:e},t);let n=this.serialOptions_.dataBits??N,r={none:0,odd:16,even:32}[this.serialOptions_.parity??P]??0,i=({1:0,2:2}[this.serialOptions_.stopBits??F]??0)<<8|r|n;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:A,value:i,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:j,value:re,index:e})}async cp210xDeinit(){let e=this.controlInterface_.interfaceNumber;await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:j,value:ie,index:e}),await this.device_.controlTransferOut({requestType:`vendor`,recipient:`interface`,request:O,value:ne,index:e})}validateOptions(){if(this.serialOptions_.baudRate%1!=0)throw RangeError(`Invalid baud rate: ${this.serialOptions_.baudRate}`);if(this.serialOptions_.dataBits!==void 0&&!I.includes(this.serialOptions_.dataBits))throw RangeError(`Invalid dataBits: ${this.serialOptions_.dataBits}`);if(this.serialOptions_.stopBits!==void 0&&!L.includes(this.serialOptions_.stopBits))throw RangeError(`Invalid stopBits: ${this.serialOptions_.stopBits}`);if(this.serialOptions_.parity!==void 0&&!R.includes(this.serialOptions_.parity))throw RangeError(`Invalid parity: ${this.serialOptions_.parity}`)}},ae=class{options_;constructor(e){this.options_={...V,...e}}async requestPort(e,t){let n={...this.options_,...t},r=[];if(e?.filters&&e.filters.length>0)for(let t of e.filters){let e={};t.usbVendorId!==void 0&&(e.vendorId=t.usbVendorId),t.usbProductId!==void 0&&(e.productId=t.usbProductId),n.usbControlInterfaceClass!==void 0&&n.usbControlInterfaceClass!==255?e.classCode=n.usbControlInterfaceClass:e.vendorId===void 0&&e.productId===void 0&&(e.classCode=n.usbControlInterfaceClass??2),r.push(e)}else r.push({classCode:n.usbControlInterfaceClass??2});return new J(await navigator.usb.requestDevice({filters:r}),n)}async getPorts(e){let t={...this.options_,...e},n=await navigator.usb.getDevices(),r=[];for(let e of n)try{let n=new J(e,t);r.push(n)}catch{}return r}},Y=`6e400001-b5a3-f393-e0a9-e50e24dcca9e`,oe=`6e400003-b5a3-f393-e0a9-e50e24dcca9e`,se=`6e400002-b5a3-f393-e0a9-e50e24dcca9e`,X=20,ce=10;function le(e){let t=null,n=null,r=null;return{get readable(){return t},get writable(){return n},getInfo(){return{}},async open(){if(!e.gatt)throw Error(`GATT not available on this Bluetooth device.`);r=await e.gatt.connect();let i=await r.getPrimaryService(Y),a=await i.getCharacteristic(oe),o=await i.getCharacteristic(se);await a.startNotifications(),t=new ReadableStream({start(e){a.addEventListener(`characteristicvaluechanged`,t=>{let n=t.target.value.buffer;e.enqueue(new Uint8Array(n))})}}),n=new WritableStream({async write(e){for(let t=0;t<e.length;t+=X){let n=e.slice(t,t+X);await o.writeValueWithoutResponse(n),t+X<e.length&&await new Promise(e=>setTimeout(e,ce))}}})},async close(){r?.connected&&r.disconnect(),t=null,n=null}}}function ue(){return{async requestPort(){if(!navigator.bluetooth)throw Error(`Web Bluetooth API is not supported in this browser. Use Chrome on Android, macOS, or ChromeOS.`);return le(await navigator.bluetooth.requestDevice({filters:[{services:[Y]}]}))},async getPorts(){return[]}}}function Z(e){return new Promise((t,n)=>{e.addEventListener(`open`,()=>t(),{once:!0}),e.addEventListener(`error`,e=>n(e),{once:!0})})}function Q(e,t){return new Promise(n=>{let r=i=>{let a=JSON.parse(i.data);a.type===t&&(e.removeEventListener(`message`,r),n(a.payload))};e.addEventListener(`message`,r)})}function $(e,t){let n=null,r=null;return{get readable(){return n},get writable(){return r},getInfo(){return{usbVendorId:t.vendorId,usbProductId:t.productId}},async open(i){e.send(JSON.stringify({type:`open`,path:t.path,baudRate:i.baudRate,dataBits:i.dataBits,stopBits:i.stopBits,parity:i.parity,parser:{type:`delimiter`,value:`\\n`}})),await Q(e,`opened`);let a=[],o=null,s=!1;function c(e){let t=JSON.parse(e.data);if(t.type===`data`&&t.bytes){let e=new Uint8Array(t.bytes);o?o.enqueue(e):a.push(e)}t.type===`closed`&&(s=!0,o&&o.close())}e.addEventListener(`message`,c),n=new ReadableStream({start(e){o=e;for(let t of a)e.enqueue(t);a.length=0,s&&e.close()},cancel(){e.removeEventListener(`message`,c),o=null}}),r=new WritableStream({write(t){e.send(JSON.stringify({type:`write`,bytes:Array.from(t)}))}})},async close(){e.send(JSON.stringify({type:`close`})),n=null,r=null,e.close()}}}function de(e){return{async requestPort(t){let n=new WebSocket(e);await Z(n),n.send(JSON.stringify({type:`list-ports`,filters:t?.filters??[]}));let r=(await Q(n,`port-list`))[0];if(!r)throw Error(`No ports available on the bridge server. Make sure the Node.js server is running and a device is connected.`);return $(n,r)},async getPorts(){let t=new WebSocket(e);return await Z(t),t.send(JSON.stringify({type:`list-ports`,filters:[]})),(await Q(t,`port-list`)).map(e=>$(t,e))}}}e.AbstractSerialDevice=l,e.CommandQueue=r,e.SerialEventEmitter=t,e.SerialPermissionError=a,e.SerialPortConflictError=i,e.SerialReadError=s,e.SerialRegistry=n,e.SerialTimeoutError=o,e.SerialWriteError=c,e.WebUsbProvider=ae,e.ccTalk=u,e.createBluetoothProvider=ue,e.createWebSocketProvider=de,e.delimiter=p,e.fixedLength=m,e.interByteTimeout=h,e.packetLength=g,e.raw=_,e.readline=y,e.readyParser=x,e.regexParser=S,e.slipDecoder=ee,e.slipEncode=w,e.spacePacket=T});
|