Skip to content

Commit 9418f78

Browse files
authored
Merge pull request #3 from ww24/fix-device
Fix bug
2 parents 45fa714 + 9488151 commit 9418f78

File tree

11 files changed

+224
-79
lines changed

11 files changed

+224
-79
lines changed

.gitignore

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,5 +15,9 @@
1515
vendor/
1616

1717
hems
18-
hems_linux_arm
18+
hems_linux_armv6
19+
hems_linux_armv7
1920
hems_linux_arm64
21+
22+
.*
23+
!.gitignore

Makefile

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,11 @@
11

2-
.PHONY: build-rpi
3-
build-rpi:
4-
GOOS=linux GOARM=7 GOARCH=arm go build -o hems_linux_arm .
2+
.PHONY: build-rpi0
3+
build-rpi0:
4+
GOOS=linux GOARM=6 GOARCH=arm go build -o hems_linux_armv6 .
5+
6+
.PHONY: build-rpi2
7+
build-rpi2:
8+
GOOS=linux GOARM=7 GOARCH=arm go build -o hems_linux_armv7 .
59

610
.PHONY: build-rpi4
711
build-rpi4:

README.md

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,42 @@ B ルート対応 Wi-SUN デバイスにシリアル通信で接続し、消費
1515

1616
※ 本アプリケーションは、日本の電波法に準拠しているデバイスで、新たに免許等が必要ないものを接続して、利用する事を想定しています。
1717

18+
### Installation (Ubuntu)
19+
20+
#### Deploy binary
21+
22+
armv7 用のバイナリを使う場合は次のようになります。
23+
24+
```sh
25+
sudo cp ./hems_linux_armv7 /usr/local/bin/
26+
```
27+
28+
#### Deploy service and udev rule
29+
30+
`hems.service` で設定されている以下の項目は適切な値に変更してください。
31+
32+
```
33+
Environment=HEMS_ROUTEB_ID=xxx
34+
Environment=HEMS_PASSWORD=xxx
35+
Environment=HEMS_DEVICE=/dev/udg-1-wsne
36+
ExecStart=/usr/local/bin/hems_linux_armv7
37+
```
38+
39+
```sh
40+
sudo cp ./example/etc/systemd/system/hems.service /etc/systemd/system/hems.service
41+
sudo systemctl daemon-reload
42+
```
43+
44+
`UDG-1-WSNE` 以外を使う場合は `99-hems.rules` を修正する必要があります。
45+
46+
```sh
47+
sudo cp ./example/etc/udev/rules.d/99-hems.rules /etc/udev/rules.d/99-hems.rules
48+
sudo udevadm control --reload
49+
```
50+
51+
USB ドングルを接続すると自動的に hems service が起動します。
52+
USB ドングルを外すと自動的に停止します。
53+
1854
## Build
1955

2056
### Raspberry Pi 4
@@ -23,10 +59,16 @@ B ルート対応 Wi-SUN デバイスにシリアル通信で接続し、消費
2359
make build-rpi4
2460
```
2561

26-
### Raspberry Pi 2, 3 or Zero
62+
### Raspberry Pi 2, 3
63+
64+
```sh
65+
make build-rpi2
66+
```
67+
68+
### Raspberry Pi 1, Zero
2769

2870
```sh
29-
make build-rpi
71+
make build-rpi0
3072
```
3173

3274
## Example

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)

example/datadog/dashboard.json

Lines changed: 27 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
"type": "query_value",
99
"requests": [
1010
{
11-
"q": "max:go_expvar.hems.watt{host:hems}",
11+
"q": "max:go_expvar.hems.watt{$host}",
1212
"aggregator": "max",
1313
"conditional_formats": [
1414
{
@@ -48,16 +48,23 @@
4848
"type": "timeseries",
4949
"requests": [
5050
{
51-
"q": "avg:go_expvar.hems.watt{host:hems}",
51+
"q": "avg:go_expvar.hems.watt{$host}.rollup(max)",
5252
"display_type": "area",
5353
"style": {
5454
"palette": "dog_classic",
5555
"line_type": "solid",
5656
"line_width": "normal"
57-
}
57+
},
58+
"on_right_yaxis": false
5859
}
5960
],
60-
"custom_links": [],
61+
"yaxis": {
62+
"label": "",
63+
"scale": "linear",
64+
"min": "auto",
65+
"max": "auto",
66+
"include_zero": true
67+
},
6168
"title": "瞬間消費電力推移(4h)",
6269
"title_size": "16",
6370
"title_align": "left",
@@ -80,7 +87,7 @@
8087
"type": "query_value",
8188
"requests": [
8289
{
83-
"q": "max:go_expvar.hems.watt{host:hems}",
90+
"q": "max:go_expvar.hems.watt{$host}",
8491
"aggregator": "last",
8592
"conditional_formats": [
8693
{
@@ -120,7 +127,7 @@
120127
"type": "timeseries",
121128
"requests": [
122129
{
123-
"q": "avg:go_expvar.hems.watt{host:hems}",
130+
"q": "avg:go_expvar.hems.watt{$host}.rollup(max)",
124131
"display_type": "area",
125132
"style": {
126133
"palette": "dog_classic",
@@ -129,7 +136,13 @@
129136
}
130137
}
131138
],
132-
"custom_links": [],
139+
"yaxis": {
140+
"label": "",
141+
"scale": "linear",
142+
"min": "auto",
143+
"max": "auto",
144+
"include_zero": true
145+
},
133146
"title": "瞬間消費電力推移(24h)",
134147
"title_size": "16",
135148
"title_align": "left",
@@ -147,7 +160,13 @@
147160
}
148161
}
149162
],
150-
"template_variables": [],
163+
"template_variables": [
164+
{
165+
"name": "host",
166+
"default": "raspberrypi",
167+
"prefix": "host"
168+
}
169+
],
151170
"layout_type": "free",
152171
"is_read_only": false,
153172
"notify_list": [],

0 commit comments

Comments
 (0)