Skip to content

Commit 9785dab

Browse files
committed
Fix dongle initialization
1 parent 57bc424 commit 9785dab

File tree

5 files changed

+136
-54
lines changed

5 files changed

+136
-54
lines changed

dongle/bp35c2.go

Lines changed: 76 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,11 @@ import (
44
"bufio"
55
"errors"
66
"fmt"
7+
"io"
8+
"io/ioutil"
79
"strings"
810
"sync"
11+
"time"
912

1013
"github.com/pkg/term"
1114
)
@@ -21,18 +24,20 @@ var (
2124
)
2225

2326
// 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 {
2528
return &BP35C2{
26-
SerialDevice: serialDevice,
27-
Baudrate: baudrate,
29+
serialDevice: serialDevice,
30+
baudrate: baudrate,
31+
readTimeout: readTimeout,
2832
}
2933
}
3034

3135
// BP35C2 is BP35C0/BP35C2 client implementation.
3236
type BP35C2 struct {
3337
m sync.Mutex
34-
SerialDevice string
35-
Baudrate int
38+
serialDevice string
39+
baudrate int
40+
readTimeout time.Duration
3641
term *term.Term
3742
localIP string
3843
remoteIP string
@@ -50,17 +55,32 @@ func (d *BP35C2) SetRemoteIP(ip string) {
5055

5156
// Connect connects serial device.
5257
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))
5560
if err != nil {
5661
return err
5762
}
5863
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+
}
5978
return nil
6079
}
6180

6281
// Close closes serial device.
6382
func (d *BP35C2) Close() {
83+
d.SKTERM()
6484
d.term.Close()
6585
}
6686

@@ -168,14 +188,18 @@ type PAN struct {
168188
func (d *BP35C2) SKSCAN() (*PAN, error) {
169189
d.m.Lock()
170190
defer d.m.Unlock()
191+
171192
// SKSCAN <MODE> <CHANNEL_MASK> <DURATION> <SIDE><CRLF>
172193
err := d.write("SKSCAN 2 FFFFFFFF 6 0\r\n")
173194
if err != nil {
174195
return nil, err
175196
}
176-
d.term.Flush()
197+
177198
reader := bufio.NewReader(d.term)
178199
scanner := bufio.NewScanner(reader)
200+
if err := d.term.Flush(); err != nil {
201+
return nil, err
202+
}
179203
pan := &PAN{}
180204
for scanner.Scan() {
181205
l := scanner.Text()
@@ -254,9 +278,11 @@ func (d *BP35C2) SKJOIN(ipv6Addr string) error {
254278
if err != nil {
255279
return err
256280
}
257-
d.term.Flush()
258281
reader := bufio.NewReader(d.term)
259282
scanner := bufio.NewScanner(reader)
283+
if err := d.term.Flush(); err != nil {
284+
return err
285+
}
260286
for scanner.Scan() {
261287
l := scanner.Text()
262288
fmt.Println(l)
@@ -281,7 +307,6 @@ func (d *BP35C2) SKSENDTO(handle, ipAddr, port, sec string, data []byte) (string
281307
s := fmt.Sprintf("SKSENDTO %s %s %s %s 0 %.4X ", handle, ipAddr, port, sec, len(data))
282308
b := append([]byte(s), data[:]...)
283309
b = append(b, []byte("\r\n")...)
284-
defer d.term.Flush()
285310
_, err := d.term.Write(b)
286311
if err != nil {
287312
return "", err
@@ -307,8 +332,42 @@ func (d *BP35C2) SKSENDTO(handle, ipAddr, port, sec string, data []byte) (string
307332
return "", errors.New("SKSENDTO failed")
308333
}
309334

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+
310370
func (d *BP35C2) write(s string) error {
311-
defer d.term.Flush()
312371
_, err := d.term.Write([]byte(s))
313372
if err != nil {
314373
return err
@@ -317,14 +376,19 @@ func (d *BP35C2) write(s string) error {
317376
}
318377

319378
func (d *BP35C2) readUntil(symbol string) ([]string, error) {
320-
d.term.Flush()
321379
reader := bufio.NewReader(d.term)
322380
scanner := bufio.NewScanner(reader)
381+
if err := d.term.Flush(); err != nil {
382+
return nil, err
383+
}
323384
rs := make([]string, 0, 1)
324385
for scanner.Scan() {
325386
l := strings.TrimSpace(scanner.Text())
326387
fmt.Println("[RESPONSE] >>", l) // DEBUG
327388
rs = append(rs, l)
389+
if strings.Contains(l, "EVENT 29 ") {
390+
return nil, errors.New("session lifetime exceeded")
391+
}
328392
if strings.Contains(l, respFail) {
329393
return nil, errors.New(l)
330394
}

dongle/dongle.go

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ import (
1111
"go.uber.org/zap"
1212
)
1313

14-
const (
15-
readTimeout = 5 * time.Second
16-
)
17-
1814
var (
1915
// ErrFatal is not retriable error.
2016
ErrFatal = errors.New("Fatal error")
@@ -58,6 +54,7 @@ type Dongle interface {
5854
SKSENDTO(handle, ipAddr, port, sec string, data []byte) (string, error)
5955
}
6056

57+
// Init initialises connection.
6158
func (du *Client) Init() error {
6259
logger := du.Logger
6360

@@ -141,10 +138,12 @@ func (du *Client) Init() error {
141138
return nil
142139
}
143140

141+
// Close closes connection.
144142
func (du *Client) Close() {
145143
du.Dongle.Close()
146144
}
147145

146+
// Fetch fetches electric energy consumption [watt].
148147
func (du *Client) Fetch(ctx context.Context, f func(time time.Time, watt int64)) error {
149148
logger := du.Logger
150149

@@ -184,7 +183,7 @@ func (du *Client) fetch() (time.Time, int64, error) {
184183
}
185184
if a[8] != "0012" {
186185
fmt.Println(fmt.Sprintf("%s is not 0012. ", a[7]))
187-
return t, 0, err
186+
return t, 0, errors.New("unexpected response")
188187
}
189188
o := a[9]
190189
w, err := strconv.ParseInt(o[len(o)-8:], 16, 0)

go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ go 1.12
44

55
require (
66
github.com/pkg/errors v0.8.1 // indirect
7-
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942
7+
github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03
88
github.com/stretchr/testify v1.3.0 // indirect
99
go.uber.org/atomic v1.4.0 // indirect
1010
go.uber.org/multierr v1.1.0 // indirect

go.sum

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
44
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
55
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942 h1:A7GG7zcGjl3jqAqGPmcNjd/D9hzL95SuoOQAaFNdLU0=
66
github.com/pkg/term v0.0.0-20190109203006-aa71e9d9e942/go.mod h1:eCbImbZ95eXtAUIbLAuAVnBnwf83mjf6QIVH8SHYwqQ=
7+
github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03 h1:pd4YKIqCB0U7O2I4gWHgEUA2mCEOENmco0l/bM957bU=
8+
github.com/pkg/term v0.0.0-20200520122047-c3ffed290a03/go.mod h1:Z9+Ul5bCbBKnbCvdOWbLqTHhJiYV414CURZJba6L8qA=
79
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
810
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
911
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

0 commit comments

Comments
 (0)