summaryrefslogtreecommitdiff
path: root/mqtt-controller/unified_switch.go
diff options
context:
space:
mode:
Diffstat (limited to 'mqtt-controller/unified_switch.go')
-rw-r--r--mqtt-controller/unified_switch.go124
1 files changed, 124 insertions, 0 deletions
diff --git a/mqtt-controller/unified_switch.go b/mqtt-controller/unified_switch.go
new file mode 100644
index 0000000..fb62c7a
--- /dev/null
+++ b/mqtt-controller/unified_switch.go
@@ -0,0 +1,124 @@
1package main
2
3import (
4 "hash/crc64"
5 "log"
6 "sync"
7
8 "github.com/brutella/hc/accessory"
9)
10
11type UnifiedSwitch struct {
12 HomeKitSwitch *accessory.Switch
13 MqttDevice Device
14 Commands <-chan Command
15 metrics chan Metric
16 events chan Event
17 infos chan interface{}
18}
19
20func NewUnifiedSwitch(b *MQTTBroker, d Device) (*UnifiedSwitch, error) {
21 us := &UnifiedSwitch{
22 MqttDevice: d,
23 metrics: make(chan Metric, 100),
24 events: make(chan Event, 100),
25 infos: make(chan interface{}, 100),
26 }
27
28 cmd, err := d.Connect(b, us.events, us.metrics, us.infos)
29 if err != nil {
30 log.Printf("Error connecting device: %e", err)
31 return nil, err
32 }
33
34 us.Commands = cmd
35 us.makeHomekitSwitch()
36
37 return us, nil
38}
39
40func (s *UnifiedSwitch) MessageLoop(done <-chan interface{}, wg *sync.WaitGroup) {
41 wg.Add(1)
42 defer wg.Done()
43
44 log.Printf("Starting switch %s", s.MqttDevice.Identity())
45
46C:
47 for {
48 select {
49 case e := <-s.events:
50 direction := "output"
51 if e.Direction == DirectionInput {
52 direction = "input"
53 }
54
55 s.HomeKitSwitch.Switch.On.SetValue(e.Active)
56
57 log.Printf("New event for '%s'.%d %s: %t", e.Device.Identity(), e.Index, direction, e.Active)
58 case m := <-s.metrics:
59 /*
60 switch t := m.Value.(type) {
61 case float64:
62 log.Printf("New metric '%s' for '%s': %#v", m.Name, m.Device.Identity(), t)
63 case int64:
64 log.Printf("New metric '%s' for '%s': %#v", m.Name, m.Device.Identity(), t)
65 case bool:
66 log.Printf("New metric '%s' for '%s': %#v", m.Name, m.Device.Identity(), t)
67 default:
68 log.Printf("Unknown metric: %#v", m.Value)
69 }
70 */
71 _ = m
72 case i := <-s.infos:
73 switch it := i.(type) {
74 case ShellyStatus:
75 // TODO: Handle multiple relays
76 log.Printf("Info relays: %#v", it.Relays)
77 s.HomeKitSwitch.Switch.On.SetValue(it.Relays[0].IsOn)
78 default:
79 // Just discard them for now
80 }
81 case <-done:
82 log.Printf("Shutting down switch %s", s.MqttDevice.Identity())
83 break C
84 }
85 }
86
87 log.Printf("Switch %s shut down", s.MqttDevice.Identity())
88}
89
90func (s *UnifiedSwitch) HomeKitID() uint64 {
91 h64 := crc64.New(crc64.MakeTable(crc64.ISO))
92 h64.Write([]byte(s.MqttDevice.Identity()))
93 return h64.Sum64()
94}
95
96func (s *UnifiedSwitch) makeHomekitSwitch() {
97 // TODO: Get name from local DB?
98 switch dt := s.MqttDevice.(type) {
99 case *ShellyDevice:
100 s.HomeKitSwitch = accessory.NewSwitch(accessory.Info{
101 ID: s.HomeKitID(),
102 Name: s.MqttDevice.Identity(),
103 Manufacturer: dt.Manufacturer,
104 Model: dt.Model,
105 FirmwareRevision: dt.FirmwareVersion,
106 })
107 default:
108 s.HomeKitSwitch = accessory.NewSwitch(accessory.Info{
109 ID: s.HomeKitID(),
110 Name: s.MqttDevice.Identity(),
111 })
112 }
113 s.HomeKitSwitch.Switch.On.SetValue(false)
114 s.HomeKitSwitch.Switch.On.OnValueRemoteUpdate(s.HomeKitSetValue)
115}
116
117func (s *UnifiedSwitch) HomeKitSetValue(state bool) {
118 log.Printf("Client updated state: %t", state)
119 if state {
120 s.MqttDevice.OutputOn(0)
121 } else {
122 s.MqttDevice.OutputOff(0)
123 }
124}