1
1
import { webSerialDevices } from "./serial_devices" ;
2
2
3
- async function * streamAsyncIterable ( stream ) {
4
- const reader = stream . getReader ( ) ;
3
+ async function * streamAsyncIterable ( reader , keepReadingFlag ) {
5
4
try {
6
- while ( true ) {
5
+ while ( keepReadingFlag ( ) ) {
7
6
const { done, value } = await reader . read ( ) ;
8
7
if ( done ) {
9
8
return ;
@@ -34,10 +33,20 @@ class WebSerial extends EventTarget {
34
33
this . port = null ;
35
34
this . reader = null ;
36
35
this . writer = null ;
36
+ this . reading = false ;
37
37
38
38
this . connect = this . connect . bind ( this ) ;
39
39
}
40
40
41
+ handleReceiveBytes ( info ) {
42
+ this . bytesReceived += info . detail . byteLength ;
43
+ }
44
+
45
+ handleDisconnect ( ) {
46
+ this . removeEventListener ( 'receive' , this . handleReceiveBytes ) ;
47
+ this . removeEventListener ( 'disconnect' , this . handleDisconnect ) ;
48
+ }
49
+
41
50
async connect ( options ) {
42
51
this . openRequested = true ;
43
52
this . port = await navigator . serial . requestPort ( {
@@ -48,6 +57,7 @@ class WebSerial extends EventTarget {
48
57
const connectionInfo = this . port . getInfo ( ) ;
49
58
this . connectionInfo = connectionInfo ;
50
59
this . writer = this . port . writable . getWriter ( ) ;
60
+ this . reader = this . port . readable . getReader ( ) ;
51
61
52
62
if ( connectionInfo && ! this . openCanceled ) {
53
63
this . connected = true ;
@@ -58,9 +68,8 @@ class WebSerial extends EventTarget {
58
68
this . failed = 0 ;
59
69
this . openRequested = false ;
60
70
61
- this . addEventListener ( "receive" , ( info ) => {
62
- this . bytesReceived += info . detail . byteLength ;
63
- } ) ;
71
+ this . addEventListener ( "receive" , this . handleReceiveBytes ) ;
72
+ this . addEventListener ( 'disconnect' , this . handleDisconnect ) ;
64
73
65
74
console . log (
66
75
`${ this . logHead } Connection opened with ID: ${ connectionInfo . connectionId } , Baud: ${ options . baudRate } ` ,
@@ -73,7 +82,9 @@ class WebSerial extends EventTarget {
73
82
// the stream async iterable interface:
74
83
// https://web.dev/streams/#asynchronous-iteration
75
84
76
- for await ( let value of streamAsyncIterable ( this . port . readable ) ) {
85
+
86
+ this . reading = true ;
87
+ for await ( let value of streamAsyncIterable ( this . reader , ( ) => this . reading ) ) {
77
88
this . dispatchEvent (
78
89
new CustomEvent ( "receive" , { detail : value } ) ,
79
90
) ;
@@ -108,32 +119,46 @@ class WebSerial extends EventTarget {
108
119
109
120
async disconnect ( ) {
110
121
this . connected = false ;
122
+ this . transmitting = false ;
123
+ this . reading = false ;
124
+ this . bytesReceived = 0 ;
125
+ this . bytesSent = 0 ;
111
126
112
- if ( this . port ) {
113
- this . transmitting = false ;
127
+ const doCleanup = async ( ) => {
128
+ if ( this . reader ) {
129
+ this . reader . releaseLock ( ) ;
130
+ this . reader = null ;
131
+ }
114
132
if ( this . writer ) {
115
- await this . writer . close ( ) ;
133
+ await this . writer . releaseLock ( ) ;
116
134
this . writer = null ;
117
135
}
118
- try {
136
+ if ( this . port ) {
119
137
await this . port . close ( ) ;
120
138
this . port = null ;
139
+ }
140
+ } ;
121
141
122
- console . log (
123
- `${ this . logHead } Connection with ID: ${ this . connectionId } closed, Sent: ${ this . bytesSent } bytes, Received: ${ this . bytesReceived } bytes` ,
124
- ) ;
142
+ try {
143
+ await doCleanup ( ) ;
125
144
126
- this . connectionId = false ;
127
- this . bitrate = 0 ;
128
- this . dispatchEvent ( new CustomEvent ( "disconnect" ) ) ;
129
- } catch ( error ) {
130
- console . error ( error ) ;
131
- console . error (
132
- `${ this . logHead } Failed to close connection with ID: ${ this . connectionId } closed, Sent: ${ this . bytesSent } bytes, Received: ${ this . bytesReceived } bytes` ,
133
- ) ;
145
+ console . log (
146
+ `${ this . logHead } Connection with ID: ${ this . connectionId } closed, Sent: ${ this . bytesSent } bytes, Received: ${ this . bytesReceived } bytes` ,
147
+ ) ;
148
+
149
+ this . connectionId = false ;
150
+ this . bitrate = 0 ;
151
+ this . dispatchEvent ( new CustomEvent ( "disconnect" , { detail : true } ) ) ;
152
+ } catch ( error ) {
153
+ console . error ( error ) ;
154
+ console . error (
155
+ `${ this . logHead } Failed to close connection with ID: ${ this . connectionId } closed, Sent: ${ this . bytesSent } bytes, Received: ${ this . bytesReceived } bytes` ,
156
+ ) ;
157
+ this . dispatchEvent ( new CustomEvent ( "disconnect" , { detail : false } ) ) ;
158
+ } finally {
159
+ if ( this . openCanceled ) {
160
+ this . openCanceled = false ;
134
161
}
135
- } else {
136
- this . openCanceled = true ;
137
162
}
138
163
}
139
164
0 commit comments