diff options
Diffstat (limited to 'example_hk.go')
-rw-r--r-- | example_hk.go | 125 |
1 files changed, 125 insertions, 0 deletions
diff --git a/example_hk.go b/example_hk.go new file mode 100644 index 0000000..ee89281 --- /dev/null +++ b/example_hk.go | |||
@@ -0,0 +1,125 @@ | |||
1 | package main | ||
2 | |||
3 | import ( | ||
4 | "encoding/json" | ||
5 | "fmt" | ||
6 | "github.com/brutella/hc" | ||
7 | "github.com/brutella/hc/accessory" | ||
8 | "github.com/mcrute/go-inform/inform" | ||
9 | "io/ioutil" | ||
10 | "log" | ||
11 | "os" | ||
12 | ) | ||
13 | |||
14 | // Load devices into state | ||
15 | // Gather current initial state from devices | ||
16 | // Track state transitions | ||
17 | // Inputs: | ||
18 | // - Homekit | ||
19 | // - Devices | ||
20 | |||
21 | type Port struct { | ||
22 | Label string `json:"label"` | ||
23 | Port int `json:"port"` | ||
24 | } | ||
25 | |||
26 | type Device struct { | ||
27 | Key string `json:"key"` | ||
28 | Name string `json:"name"` | ||
29 | Model string `json:"model"` | ||
30 | Serial string `json:"serial"` | ||
31 | Ports []*Port `json:"ports"` | ||
32 | } | ||
33 | |||
34 | type DeviceMap map[string]*Device | ||
35 | |||
36 | func LoadKeys(file string) (DeviceMap, error) { | ||
37 | var keys DeviceMap | ||
38 | |||
39 | kp, err := os.Open(file) | ||
40 | if err != nil { | ||
41 | return nil, err | ||
42 | } | ||
43 | defer kp.Close() | ||
44 | |||
45 | kd, err := ioutil.ReadAll(kp) | ||
46 | if err != nil { | ||
47 | return nil, err | ||
48 | } | ||
49 | |||
50 | err = json.Unmarshal(kd, &keys) | ||
51 | if err != nil { | ||
52 | return nil, err | ||
53 | } | ||
54 | |||
55 | return keys, nil | ||
56 | } | ||
57 | |||
58 | func main() { | ||
59 | devs, err := LoadKeys("data/device_keys.json") | ||
60 | if err != nil { | ||
61 | log.Println("Error loading key file") | ||
62 | log.Println(err.Error()) | ||
63 | return | ||
64 | } | ||
65 | |||
66 | keys := make(map[string]string, len(devs)) | ||
67 | for i, d := range devs { | ||
68 | keys[i] = d.Key | ||
69 | } | ||
70 | |||
71 | h := inform.NewInformHandler(&inform.Codec{keys}) | ||
72 | s, _ := inform.NewServer(h) | ||
73 | as := make([]*accessory.Accessory, 0, len(devs)*3) | ||
74 | |||
75 | for i, d := range devs { | ||
76 | for _, p := range d.Ports { | ||
77 | a := accessory.NewSwitch(accessory.Info{ | ||
78 | Name: p.Label, | ||
79 | SerialNumber: fmt.Sprintf("%s-%d", d.Serial, p.Port), | ||
80 | Manufacturer: "Ubiquiti", | ||
81 | Model: d.Model, | ||
82 | }) | ||
83 | |||
84 | // Capture these for the closure, otherwise they're bound to the | ||
85 | // single loop variable and will only see the final value of that | ||
86 | // variable | ||
87 | dev, port := i, p.Port | ||
88 | |||
89 | a.Switch.On.OnValueRemoteUpdate(func(on bool) { | ||
90 | h.SetState(dev, port, on) | ||
91 | }) | ||
92 | |||
93 | h.AddPort(dev, port) | ||
94 | as = append(as, a.Accessory) | ||
95 | } | ||
96 | } | ||
97 | |||
98 | // The root accessory is what gets used to name the bridge so let's make it | ||
99 | // an actual bridge | ||
100 | br := accessory.New(accessory.Info{ | ||
101 | Name: "UnifiBridge", | ||
102 | Manufacturer: "Mike Crute", | ||
103 | Model: "0.1", | ||
104 | }, accessory.TypeBridge) | ||
105 | |||
106 | config := hc.Config{ | ||
107 | Pin: "12344321", | ||
108 | Port: "12345", | ||
109 | StoragePath: "./db", | ||
110 | } | ||
111 | |||
112 | t, err := hc.NewIPTransport(config, br, as...) | ||
113 | if err != nil { | ||
114 | log.Fatal(err) | ||
115 | return | ||
116 | } | ||
117 | |||
118 | hc.OnTermination(func() { | ||
119 | t.Stop() | ||
120 | os.Exit(0) // Otherwise homekit doesn't actually stop | ||
121 | }) | ||
122 | |||
123 | go t.Start() | ||
124 | s.ListenAndServe() | ||
125 | } | ||