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
|
package main
import (
"encoding/json"
"fmt"
"github.com/brutella/hc"
"github.com/brutella/hc/accessory"
"github.com/mcrute/go-inform/inform"
"io/ioutil"
"log"
"os"
)
// Load devices into state
// Gather current initial state from devices
// Track state transitions
// Inputs:
// - Homekit
// - Devices
type Port struct {
Label string `json:"label"`
Port int `json:"port"`
}
type Device struct {
Key string `json:"key"`
Name string `json:"name"`
Model string `json:"model"`
Serial string `json:"serial"`
Ports []*Port `json:"ports"`
}
type DeviceMap map[string]*Device
func LoadKeys(file string) (DeviceMap, error) {
var keys DeviceMap
kp, err := os.Open(file)
if err != nil {
return nil, err
}
defer kp.Close()
kd, err := ioutil.ReadAll(kp)
if err != nil {
return nil, err
}
err = json.Unmarshal(kd, &keys)
if err != nil {
return nil, err
}
return keys, nil
}
func main() {
devs, err := LoadKeys("data/device_keys.json")
if err != nil {
log.Println("Error loading key file")
log.Println(err.Error())
return
}
keys := make(map[string]string, len(devs))
for i, d := range devs {
keys[i] = d.Key
}
h := inform.NewInformHandler(&inform.Codec{keys})
s, _ := inform.NewServer(h)
as := make([]*accessory.Accessory, 0, len(devs)*3)
for i, d := range devs {
for _, p := range d.Ports {
a := accessory.NewSwitch(accessory.Info{
Name: p.Label,
SerialNumber: fmt.Sprintf("%s-%d", d.Serial, p.Port),
Manufacturer: "Ubiquiti",
Model: d.Model,
})
// Capture these for the closure, otherwise they're bound to the
// single loop variable and will only see the final value of that
// variable
dev, port := i, p.Port
a.Switch.On.OnValueRemoteUpdate(func(on bool) {
h.SetState(dev, port, on)
})
h.AddPort(dev, port)
as = append(as, a.Accessory)
}
}
// The root accessory is what gets used to name the bridge so let's make it
// an actual bridge
br := accessory.New(accessory.Info{
Name: "UnifiBridge",
Manufacturer: "Mike Crute",
Model: "0.1",
}, accessory.TypeBridge)
config := hc.Config{
Pin: "12344321",
Port: "12345",
StoragePath: "./db",
}
t, err := hc.NewIPTransport(config, br, as...)
if err != nil {
log.Fatal(err)
return
}
hc.OnTermination(func() {
t.Stop()
os.Exit(0) // Otherwise homekit doesn't actually stop
})
go t.Start()
s.ListenAndServe()
}
|