diff options
Diffstat (limited to 'mqtt-controller/unified_switch.go')
-rw-r--r-- | mqtt-controller/unified_switch.go | 124 |
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 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "hash/crc64" | ||
5 | "log" | ||
6 | "sync" | ||
7 | |||
8 | "github.com/brutella/hc/accessory" | ||
9 | ) | ||
10 | |||
11 | type 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 | |||
20 | func 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 | |||
40 | func (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 | |||
46 | C: | ||
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 | |||
90 | func (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 | |||
96 | func (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 | |||
117 | func (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 | } | ||