-
Notifications
You must be signed in to change notification settings - Fork 0
/
accessory.go
121 lines (98 loc) · 2.49 KB
/
accessory.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
package hkmh
import (
"log"
"net"
"time"
"github.com/gradddev/clr"
"github.com/gradddev/mh"
"github.com/brutella/hc/accessory"
)
type Config struct {
ID uint64
IP net.IP
Name string
Timeout time.Duration
}
type MHAccessory struct {
Accessory *accessory.Accessory
config Config
rgb *Service
controller *mh.Controller
timer *time.Timer
}
func NewAccessory(config Config) *MHAccessory {
c := mh.NewController(mh.Config{
IP: config.IP,
Timeout: config.Timeout,
})
info := accessory.Info{
ID: config.ID,
Name: config.Name,
}
a := MHAccessory{}
a.Accessory = accessory.New(info, accessory.TypeLightbulb)
a.config = config
a.rgb = NewService()
a.controller = c
a.timer = time.AfterFunc(config.Timeout, a.pullState)
a.Accessory.AddService(a.rgb.Service)
a.pullState()
a.rgb.On.OnValueRemoteUpdate(func(_ bool) { a.pushState() })
a.rgb.Brightness.OnValueRemoteUpdate(func(_ int) { a.pushState() })
a.rgb.Saturation.OnValueRemoteUpdate(func(_ float64) { a.pushState() })
a.rgb.Hue.OnValueRemoteUpdate(func(_ float64) { a.pushState() })
return &a
}
func (a *MHAccessory) pullState() {
a.timer.Stop()
power, err := a.controller.GetPower()
if err != nil {
log.Println(err)
return
}
a.rgb.On.SetValue(power)
rgbw, err := a.controller.GetRGBW()
if err != nil {
log.Println(err)
return
}
h, s, b := rgbwToHsb(rgbw.Red, rgbw.Green, rgbw.Blue, rgbw.White)
a.rgb.Hue.SetValue(h)
a.rgb.Saturation.SetValue(s)
a.rgb.Brightness.SetValue(b)
a.timer.Reset(5 * time.Second)
}
func (a *MHAccessory) pushState() {
a.timer.Stop()
power := a.rgb.On.GetValue()
err := a.controller.SetPower(power)
if err != nil {
log.Println(err)
return
}
if !power {
return
}
r, g, b, w := hsbToRgbw(
a.rgb.Hue.GetValue(),
a.rgb.Saturation.GetValue(),
a.rgb.Brightness.GetValue(),
)
rgbw := &mh.RGBW{Red: r, Green: g, Blue: b, White: w}
err = a.controller.SetRGBW(rgbw)
if err != nil {
log.Println(err)
return
}
a.timer.Reset(5 * time.Second)
}
func hsbToRgbw(hue, saturation float64, brightness int) (red, green, blue, white float64) {
red, green, blue = clr.HSVToRGB(hue, 100, float64(brightness))
white = ((100 - saturation) / 100) * 255 * (float64(brightness) / 100)
return red, green, blue, white
}
func rgbwToHsb(red, green, blue, white float64) (float64, float64, int) {
hue, _, brightness := clr.RGBToHSV(red, green, blue)
saturation := 100 - ((white * 100 * 100) / (brightness * 255))
return hue, saturation, int(brightness)
}