-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.go
148 lines (134 loc) · 2.93 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
package hidrelay
import (
"fmt"
"runtime"
"github.com/spetr/hid"
)
type (
Relay struct {
info *hid.DeviceInfo
dev *hid.Device
}
IoStatus int
ChannelNumber int
ChannelStatus struct {
Channel_1 IoStatus
Channel_2 IoStatus
Channel_3 IoStatus
Channel_4 IoStatus
Channel_5 IoStatus
Channel_6 IoStatus
Channel_7 IoStatus
Channel_8 IoStatus
}
)
// List returns all installed USB relay devices
func List() (list []*Relay) {
list = make([]*Relay, 0)
for _, devInfo := range hid.Enumerate(0x16C0, 0x05DF) {
relay, err := devInfo.Open()
if err != nil {
continue
}
list = append(list, &Relay{info: &devInfo})
relay.Close()
}
return
}
// Open creates HID connection to relay
func (r *Relay) Open() (err error) {
r.dev, err = r.info.Open()
return
}
// Close destroys HID connection to relay
func (r *Relay) Close() error {
return r.dev.Close()
}
// Set switch selected channel to IoStatus (ON/OFF)
func (r *Relay) Set(no ChannelNumber, s IoStatus) error {
cmd := make([]byte, 9)
cmd[0] = 0x0
if no < 0 || no > C8 {
return fmt.Errorf("Illegal channel number (%d)", no)
}
if no == ALL {
if s == ON {
cmd[1] = 0xFE
} else {
cmd[1] = 0xFC
}
} else {
if s == ON {
cmd[1] = 0xFF
} else {
cmd[1] = 0xFD
}
cmd[2] = byte(no)
}
_, err := r.dev.SendFeatureReport(cmd)
return err
}
// SetOn switch selected channel to ON
func (r *Relay) SetOn(num ChannelNumber) error {
return r.Set(num, ON)
}
// SetAllOn turns all relay to ON
func (r *Relay) SetAllOn() error {
return r.Set(ALL, ON)
}
// SetOff turns selected channel to OFF
func (r *Relay) SetOff(num ChannelNumber) error {
return r.Set(num, OFF)
}
// SetAllOff turns all relay to OFF
func (r *Relay) SetAllOff() error {
return r.Set(ALL, OFF)
}
// GetAll returns relay status (ON/OFF)
func (r *Relay) GetAll() (status *ChannelStatus, err error) {
cmd := make([]byte, 9)
_, err = r.dev.GetFeatureReport(cmd)
if err != nil {
return
}
if runtime.GOOS == "windows" {
cmd = cmd[1:]
}
status = &ChannelStatus{
Channel_1: IoStatus(cmd[7] >> 0 & 0x01),
Channel_2: IoStatus(cmd[7] >> 1 & 0x01),
Channel_3: IoStatus(cmd[7] >> 2 & 0x01),
Channel_4: IoStatus(cmd[7] >> 3 & 0x01),
Channel_5: IoStatus(cmd[7] >> 4 & 0x01),
Channel_6: IoStatus(cmd[7] >> 5 & 0x01),
Channel_7: IoStatus(cmd[7] >> 6 & 0x01),
Channel_8: IoStatus(cmd[7] >> 7 & 0x01),
}
return
}
// SetSN writes serial number (max 5 characters)
func (r *Relay) SetSN(sn string) (err error) {
if len(sn) > 5 {
err = fmt.Errorf("The length of '%s' is large than 5 bytes", sn)
return
}
cmd := make([]byte, 9)
cmd[0] = 0x00
cmd[1] = 0xFA
copy(cmd[2:], sn)
_, err = r.dev.SendFeatureReport(cmd)
return
}
// GetSN reads serial number (max 5 characters)
func (r *Relay) GetSN() (sn string, err error) {
cmd := make([]byte, 9)
_, err = r.dev.GetFeatureReport(cmd)
if err != nil {
return
}
if runtime.GOOS == "windows" {
cmd = cmd[1:]
}
sn = string(cmd[:5])
return
}