@@ -4,8 +4,11 @@ import (
4
4
"bufio"
5
5
"errors"
6
6
"fmt"
7
+ "io"
8
+ "io/ioutil"
7
9
"strings"
8
10
"sync"
11
+ "time"
9
12
10
13
"github.com/pkg/term"
11
14
)
@@ -21,18 +24,20 @@ var (
21
24
)
22
25
23
26
// NewBP35C2 returns command wrapper for BP35C2.
24
- func NewBP35C2 (serialDevice string , baudrate int ) * BP35C2 {
27
+ func NewBP35C2 (serialDevice string , baudrate int , readTimeout time. Duration ) * BP35C2 {
25
28
return & BP35C2 {
26
- SerialDevice : serialDevice ,
27
- Baudrate : baudrate ,
29
+ serialDevice : serialDevice ,
30
+ baudrate : baudrate ,
31
+ readTimeout : readTimeout ,
28
32
}
29
33
}
30
34
31
35
// BP35C2 is BP35C0/BP35C2 client implementation.
32
36
type BP35C2 struct {
33
37
m sync.Mutex
34
- SerialDevice string
35
- Baudrate int
38
+ serialDevice string
39
+ baudrate int
40
+ readTimeout time.Duration
36
41
term * term.Term
37
42
localIP string
38
43
remoteIP string
@@ -50,17 +55,32 @@ func (d *BP35C2) SetRemoteIP(ip string) {
50
55
51
56
// Connect connects serial device.
52
57
func (d * BP35C2 ) Connect () error {
53
- t , err := term .Open (d .SerialDevice ,
54
- term .Speed (d .Baudrate ), term .RawMode , term .ReadTimeout (readTimeout ))
58
+ t , err := term .Open (d .serialDevice ,
59
+ term .Speed (d .baudrate ), term .RawMode , term .ReadTimeout (d . readTimeout ))
55
60
if err != nil {
56
61
return err
57
62
}
58
63
d .term = t
64
+ return d .clear ()
65
+ }
66
+
67
+ func (d * BP35C2 ) clear () error {
68
+ // Discard data before first command.
69
+ if err := d .term .Flush (); err != nil {
70
+ return err
71
+ }
72
+ if _ , err := io .Copy (ioutil .Discard , d .term ); err != nil {
73
+ return err
74
+ }
75
+ if err := d .SKTERM (); err != nil {
76
+ return err
77
+ }
59
78
return nil
60
79
}
61
80
62
81
// Close closes serial device.
63
82
func (d * BP35C2 ) Close () {
83
+ d .SKTERM ()
64
84
d .term .Close ()
65
85
}
66
86
@@ -168,14 +188,18 @@ type PAN struct {
168
188
func (d * BP35C2 ) SKSCAN () (* PAN , error ) {
169
189
d .m .Lock ()
170
190
defer d .m .Unlock ()
191
+
171
192
// SKSCAN <MODE> <CHANNEL_MASK> <DURATION> <SIDE><CRLF>
172
193
err := d .write ("SKSCAN 2 FFFFFFFF 6 0\r \n " )
173
194
if err != nil {
174
195
return nil , err
175
196
}
176
- d . term . Flush ()
197
+
177
198
reader := bufio .NewReader (d .term )
178
199
scanner := bufio .NewScanner (reader )
200
+ if err := d .term .Flush (); err != nil {
201
+ return nil , err
202
+ }
179
203
pan := & PAN {}
180
204
for scanner .Scan () {
181
205
l := scanner .Text ()
@@ -254,9 +278,11 @@ func (d *BP35C2) SKJOIN(ipv6Addr string) error {
254
278
if err != nil {
255
279
return err
256
280
}
257
- d .term .Flush ()
258
281
reader := bufio .NewReader (d .term )
259
282
scanner := bufio .NewScanner (reader )
283
+ if err := d .term .Flush (); err != nil {
284
+ return err
285
+ }
260
286
for scanner .Scan () {
261
287
l := scanner .Text ()
262
288
fmt .Println (l )
@@ -281,7 +307,6 @@ func (d *BP35C2) SKSENDTO(handle, ipAddr, port, sec string, data []byte) (string
281
307
s := fmt .Sprintf ("SKSENDTO %s %s %s %s 0 %.4X " , handle , ipAddr , port , sec , len (data ))
282
308
b := append ([]byte (s ), data [:]... )
283
309
b = append (b , []byte ("\r \n " )... )
284
- defer d .term .Flush ()
285
310
_ , err := d .term .Write (b )
286
311
if err != nil {
287
312
return "" , err
@@ -307,8 +332,42 @@ func (d *BP35C2) SKSENDTO(handle, ipAddr, port, sec string, data []byte) (string
307
332
return "" , errors .New ("SKSENDTO failed" )
308
333
}
309
334
335
+ // SKTERM terminates PANA session.
336
+ func (d * BP35C2 ) SKTERM () error {
337
+ d .m .Lock ()
338
+ defer d .m .Unlock ()
339
+ // SKJOIN<CRLF>
340
+ err := d .write ("SKTERM\r \n " )
341
+ if err != nil {
342
+ return err
343
+ }
344
+ reader := bufio .NewReader (d .term )
345
+ scanner := bufio .NewScanner (reader )
346
+ if err := d .term .Flush (); err != nil {
347
+ return err
348
+ }
349
+ for scanner .Scan () {
350
+ l := scanner .Text ()
351
+ fmt .Println (l )
352
+ if strings .Contains (l , respFail + "ER10" ) {
353
+ // session is not established
354
+ return nil
355
+ }
356
+ if strings .Contains (l , respFail ) {
357
+ return fmt .Errorf ("Failed to SKTERM. %s" , l )
358
+ }
359
+ if strings .Contains (l , "EVENT 28 " ) {
360
+ // session timeout (session is terminated)
361
+ return nil
362
+ }
363
+ if strings .Contains (l , respOk ) {
364
+ return nil
365
+ }
366
+ }
367
+ return nil
368
+ }
369
+
310
370
func (d * BP35C2 ) write (s string ) error {
311
- defer d .term .Flush ()
312
371
_ , err := d .term .Write ([]byte (s ))
313
372
if err != nil {
314
373
return err
@@ -317,14 +376,19 @@ func (d *BP35C2) write(s string) error {
317
376
}
318
377
319
378
func (d * BP35C2 ) readUntil (symbol string ) ([]string , error ) {
320
- d .term .Flush ()
321
379
reader := bufio .NewReader (d .term )
322
380
scanner := bufio .NewScanner (reader )
381
+ if err := d .term .Flush (); err != nil {
382
+ return nil , err
383
+ }
323
384
rs := make ([]string , 0 , 1 )
324
385
for scanner .Scan () {
325
386
l := strings .TrimSpace (scanner .Text ())
326
387
fmt .Println ("[RESPONSE] >>" , l ) // DEBUG
327
388
rs = append (rs , l )
389
+ if strings .Contains (l , "EVENT 29 " ) {
390
+ return nil , errors .New ("session lifetime exceeded" )
391
+ }
328
392
if strings .Contains (l , respFail ) {
329
393
return nil , errors .New (l )
330
394
}
0 commit comments