-
Notifications
You must be signed in to change notification settings - Fork 0
/
channel.go
164 lines (144 loc) · 3.96 KB
/
channel.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
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
package gorecon
import (
"encoding/json"
"errors"
)
// Channel has methods to read and set current speed and temperatures
type Channel struct {
curSpeed uint16 // Current speed
maxSpeed uint16 // Maximum speed
manualSpeed uint16 // Manual speed as reported
temp uint8 // Current temperature in F
curAlarm uint8 // Current alarm temperature in F
targetSpeed uint16 // Our speed setting
targetAlarm uint8 // Our alarm temp setting (in F)
dirty bool // Whether something has changed since last check
init byte // Bitmap for channel initialization status
change chan bool // Channel for change updates
}
// ChannelExport ...
type ChannelExport struct {
Speed int `json:"speed"`
MaxSpeed int `json:"max_speed"`
ManualSpeed int `json:"manual_speed"`
TempF int `json:"temp_f"`
TempC int `json:"temp_c"`
AlarmTempF int `json:"alarm_temp_f"`
AlarmTempC int `json:"alarm_temp_c"`
}
// MarshalJSON ...
func (c *Channel) MarshalJSON() ([]byte, error) {
return json.Marshal(c.Export())
}
// Export ...
func (c *Channel) Export() *ChannelExport {
return &ChannelExport{
Speed: c.Speed(),
MaxSpeed: c.MaxSpeed(),
ManualSpeed: c.ManualSpeed(),
TempF: c.TempF(),
TempC: c.TempC(),
AlarmTempF: c.AlarmTempF(),
AlarmTempC: c.AlarmTempC(),
}
}
// NewChannel returns the a new channel with defaults set
func NewChannel(changeChan chan bool) *Channel {
return &Channel{
curSpeed: 0,
maxSpeed: 0,
manualSpeed: 0,
temp: 0,
curAlarm: 0,
targetSpeed: 65535,
targetAlarm: 255,
dirty: false,
init: 0x00,
change: changeChan,
}
}
// SetSpeed changes the target speed of the fan controller (RPM)
func (c *Channel) SetSpeed(speed int) error {
if speed > int(c.maxSpeed) || speed >= 65535 {
return errors.New("Speed exceeds maximum speed")
}
if speed < 0 {
return errors.New("Speed cannot be negative")
}
c.targetSpeed = uint16(speed)
c.dirty = true
c.change <- true
return nil
}
// SetAlarmTempC sets the alarm termperature in Celsius
func (c *Channel) SetAlarmTempC(temp int) error {
return c.SetAlarmTempF(c2f(temp))
}
// SetAlarmTempF sets the alarm temperature in Farenheit
func (c *Channel) SetAlarmTempF(temp int) error {
if temp < 0 || temp >= 255 {
return errors.New("Temperature out of range")
}
c.targetAlarm = uint8(temp)
c.dirty = true
c.change <- true
return nil
}
// Speed returns the current speed (RPM)
func (c *Channel) Speed() int {
return int(c.curSpeed)
}
// MaxSpeed returns the maximum speed that the fan supports (RPM)
func (c *Channel) MaxSpeed() int {
return int(c.maxSpeed)
}
// ManualSpeed returns the value of the controllers target speed (RPM)
func (c *Channel) ManualSpeed() int {
return int(c.manualSpeed)
}
// TempC returns current temperature in Celsius
func (c *Channel) TempC() int {
return f2c(int(c.temp))
}
// TempF returns current temperature in Farenheit
func (c *Channel) TempF() int {
return int(c.temp)
}
// AlarmTempC returns the current alarm temperature in Celsius
func (c *Channel) AlarmTempC() int {
return f2c(int(c.curAlarm))
}
// AlarmTempF returns the current alarm termperature in Farenheit
func (c *Channel) AlarmTempF() int {
return int(c.curAlarm)
}
// IsInitialized checks if we've received initial data from fan controller
// for this channel
func (c *Channel) IsInitialized() bool {
return c.init == 0x03
}
func (c *Channel) report(data []byte) {
if len(data) == 5 {
if c.init&0x01 == 0 {
c.init = c.init | 0x01
}
c.temp = uint8(data[0])
c.curSpeed = byte2rpm(data[1], data[2])
c.maxSpeed = byte2rpm(data[3], data[4])
}
}
func (c *Channel) reportAlarm(data []byte) {
if len(data) == 3 {
if c.init&0x02 == 0 {
c.init = c.init | 0x02
}
c.curAlarm = uint8(data[0])
c.manualSpeed = byte2rpm(data[1], data[2])
if c.targetSpeed == 65535 {
c.targetSpeed = c.manualSpeed
}
if c.targetAlarm == 255 {
c.targetAlarm = c.curAlarm
}
}
}