Skip to content

Commit af48562

Browse files
committed
Merge branch 'tv' #132
2 parents 0f65b42 + e7eba10 commit af48562

47 files changed

Lines changed: 4344 additions & 3159 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.travis.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,13 @@
11
sudo: false
22
language: go
3+
go:
4+
- 1.11.x
5+
- master
6+
os:
7+
- linux
8+
- osx
9+
dist: trusty
10+
install: true
11+
script:
12+
- env GO111MODULE=on go build
13+
- env GO111MODULE=on go test

README.md

Lines changed: 75 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,72 @@
1-
# HomeControl
1+
# hc
22

3-
[![Build Status](https://travis-ci.org/brutella/hc.svg)](https://travis-ci.org/brutella/hc)
3+
[![GoDoc Widget]][GoDoc] [![Travis Widget]][Travis]
44

5-
HomeControl is an implementation of the [HomeKit][homekit] Accessory Protocol (HAP) to create your own HomeKit accessory in [Go](https://golang.org). [HomeKit][homekit] is a set of protocols and libraries to access devices for Home Automation. ~~The actual protocol documentation is only available to MFi members.~~ A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/).
5+
`hc` is a lightweight framework to develop HomeKit accessories in Go.
6+
It abstracts the **H**omeKit **A**ccessory **P**rotocol (HAP) and makes it easy to work with [services](service/README.md) and [characteristics](characteristic/README.md).
67

7-
You can use this library to make existing Home Automation devices HomeKit compatible. I've already developed the following HomeKit bridges with in:
8+
`hc` handles the underlying communication between HomeKit accessories and clients.
9+
You can focus on implementing the business logic for your accessory, without having to worry about the protocol.
10+
11+
Here are some projects which use `hc`.
812

913
- [LIFX](https://github.com/brutella/hklifx/)
1014
- [UVR1611](https://github.com/brutella/hkuvr)
1115
- [Fronius Symo](https://github.com/brutella/hksymo)
1216

13-
## HomeKit on iOS
17+
**What is HomeKit?**
18+
19+
[HomeKit][homekit] is a set of protocols and libraries from Apple. It is used by Apple's platforms to communicate with smart home appliances. A non-commercial version of the documentation is now available on the [HomeKit developer website](https://developer.apple.com/homekit/).
20+
21+
HomeKit is fully integrated into iOS since iOS 8. Developers can use [HomeKit.framework](https://developer.apple.com/documentation/homekit) to communicate with accessories using high-level APIs.
22+
23+
<img alt="Home.app" src="_img/home-icon.png?raw=true" width="92" />
1424

15-
HomeKit is fully integrated since iOS 8. Developers can use the HomeKit framework to communicate with HomeKit using high-level APIs.
16-
I've developed the [Home][home] app (for iPhone, iPad, Apple Watch) to control HomeKit accessories. If you [purchase Home][home-appstore] on the App Store, you not only support my work but also get an awesome iOS app. Thank you.
25+
I've developed the [Home][home] app to control HomeKit accessories from iPhone, iPad, and Apple Watch.
26+
If you want to support `hc`, please purchase Home from the [App Store][home-appstore]. That would be awesome. ❤️
1727

18-
Once you've setup HomeKit, you can use Siri to interact with your accessories using voice command (*Hey Siri, turn off the lights in the living room*).
28+
Checkout the official [website][home].
1929

20-
[home]: http://hochgatterer.me/home/
30+
[home]: https://hochgatterer.me/home/
2131
[home-appstore]: http://itunes.apple.com/app/id995994352
32+
[GoDoc]: https://godoc.org/github.com/brutella/hc
33+
[GoDoc Widget]: https://godoc.org/github.com/brutella/hc?status.svg
34+
[Travis]: https://travis-ci.org/brutella/hc
35+
[Travis Widget]: https://travis-ci.org/brutella/hc.svg
2236

2337
## Features
2438

2539
- Full implementation of the HAP in Go
2640
- Supports all HomeKit [services and characteristics](service/README.md)
2741
- Built-in service announcement via DNS-SD using [dnssd](http://github.com/brutella/dnssd)
28-
- Runs on multiple platforms (already in use on Linux and OS X)
42+
- Runs on linux and macOS
2943
- Documentation: http://godoc.org/github.com/brutella/hc
3044

3145
## Getting Started
3246

33-
1. [Install Go](http://golang.org/doc/install)
34-
2. [Setup Go workspace](http://golang.org/doc/code.html#Organization)
35-
3. Create your own HomeKit bridge or clone an existing one (e.g. [hklight](https://github.com/brutella/hklight))
47+
1. [Install](http://golang.org/doc/install) and [set up](http://golang.org/doc/code.html#Organization) Go
48+
2. Create your own HomeKit accessory or clone an existing one (e.g. [hklight](https://github.com/brutella/hklight))
3649

3750
cd $GOPATH/src
3851
3952
# Clone project
4053
git clone https://github.com/brutella/hklight && cd hklight
4154
4255
# Run the project
43-
go run hklightd.go
56+
make run
57+
58+
3. Pair with your HomeKit App of choice (e.g. [Home][home-appstore])
59+
60+
**Go Modules**
61+
62+
`hc` supports [Go module](https://github.com/golang/go/wiki/Modules) since `v1.0.0`.
63+
Make sure to set the environment variable `GO111MODULE=on`.
4464

45-
4. Pair with your HomeKit App of choice (e.g. [Home][home-appstore])
65+
## Example
4666

47-
## API Example
67+
See [_example](_example) for a variety of examples.
68+
69+
**Basic switch accessory**
4870

4971
Create a simple on/off switch, which is accessible via IP and secured using the pin *00102003*.
5072

@@ -58,88 +80,76 @@ import (
5880
)
5981

6082
func main() {
61-
info := accessory.Info{
62-
Name: "Lamp",
63-
}
64-
acc := accessory.NewSwitch(info)
83+
// create an accessory
84+
info := accessory.Info{Name: "Lamp"}
85+
ac := accessory.NewSwitch(info)
6586

87+
// configure the ip transport
6688
config := hc.Config{Pin: "00102003"}
67-
t, err := hc.NewIPTransport(config, acc.Accessory)
68-
if err != nil {
69-
log.Panic(err)
70-
}
89+
t, err := hc.NewIPTransport(config, ac.Accessory)
90+
if err != nil {
91+
log.Panic(err)
92+
}
7193

7294
hc.OnTermination(func(){
7395
<-t.Stop()
7496
})
7597

76-
t.Start()
98+
t.Start()
7799
}
78100
```
79101

80-
You should change some default values for your own needs
102+
You can define more specific accessory info, if you want.
81103

82104
```go
83105
info := accessory.Info{
84-
Name: "Lamp",
85-
SerialNumber: "051AC-23AAM1",
86-
Manufacturer: "Apple",
87-
Model: "AB",
88-
Firmware: "1.0.1",
106+
Name: "Lamp",
107+
SerialNumber: "051AC-23AAM1",
108+
Manufacturer: "Apple",
109+
Model: "AB",
110+
Firmware: "1.0.1",
89111
}
90112
```
91113

92-
### Callbacks
114+
### Events
93115

94-
You get a callback when the power state of a switch changed by a client.
116+
The library provides callback functions, which let you know when a clients updates a characteristic value.
117+
The following example shows how to get notified when the [On](characteristic/on.go) characteristic value changes.
95118

96119
```go
97-
acc.Switch.On.OnValueRemoteUpdate(func(on bool) {
98-
if on == true {
99-
log.Println("Client changed switch to on")
100-
} else {
101-
log.Println("Client changed switch to off")
102-
}
120+
ac.Switch.On.OnValueRemoteUpdate(func(on bool) {
121+
if on == true {
122+
log.Println("Switch is on")
123+
} else {
124+
log.Println("Switch is off")
125+
}
103126
})
104127
```
105128

106129
When the switch is turned on "the analog way", you should set the state of the accessory.
107130

108-
acc.Switch.On.SetValue(true)
109-
110-
A complete example is available in `_example/example.go`.
111-
112-
## Model
113-
114-
The HomeKit model hierarchy looks like this:
115-
116-
Accessory
117-
|-- Accessory Info Service
118-
| |-- Identify Characteristic
119-
| |-- Manufacturer Characteristic
120-
| |-- Model Characteristic
121-
| |-- Name Characteristic
122-
| |-- Serial Characteristic
123-
|
124-
|-- * Service
125-
| |-- * Characteristic
131+
```go
132+
ac.Switch.On.SetValue(true)
133+
```
126134

127-
HomeKit accessories are container for services. Every accessory must provide the `Accessory Information Service`. Every service provides one or more characteristics (a characteristic might be the power state of an outlet). HomeKit has predefined service and characteristic types, which are supported by iOS. You can define your own service and characteristic types, but it's recommended to use predefined ones.
135+
## Accessory Architecture
128136

129-
## Dependencies
137+
HomeKit uses a hierarchical architecture for define accessories, services and characeristics.
138+
At the root level there is an accessory.
139+
Every accessory contains services.
140+
And every service contains characteristics.
130141

131-
HomeControl uses vendor directories (`vendor/`) to integrate the following libraries
142+
For example a [lightbulb accessory](accessory/lightbulb.go) contains a [lightbulb service](service/lightbulb.go).
143+
This service contains characteristics like [on](characteristic/on.go) and [brightness](characteristic/brightness.go).
132144

133-
- `github.com/tadglines/go-pkgs/crypto/srp` for *SRP* algorithm
134-
- `github.com/agl/ed25519` for *ed25519* signature
135-
- `github.com/gosexy/to` for type conversion
136-
- `github.com/brutella/dnssd` for DNS service discovery
145+
There are predefined accessories, services and characteristics available in HomeKit.
146+
Those types are defined in the packages [accessory](accessory), [service](service), [characteristic](characteristic).
137147

138148
# Contact
139149

140150
Matthias Hochgatterer
141151

142-
Website: [http://hochgatterer.me](http://hochgatterer.me)
152+
Website: [https://hochgatterer.me](https://hochgatterer.me)
143153

144154
Github: [https://github.com/brutella](https://github.com/brutella/)
145155

_example/tv/main.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
package main
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/brutella/hc"
7+
"github.com/brutella/hc/accessory"
8+
"github.com/brutella/hc/characteristic"
9+
"github.com/brutella/hc/log"
10+
"github.com/brutella/hc/service"
11+
)
12+
13+
func addInputSource(t *accessory.Television, id int, name string, inputSourceType int) {
14+
in := service.NewInputSource()
15+
16+
in.Identifier.SetValue(id)
17+
in.ConfiguredName.SetValue(name)
18+
in.Name.SetValue(name)
19+
in.InputSourceType.SetValue(inputSourceType)
20+
in.IsConfigured.SetValue(characteristic.IsConfiguredConfigured)
21+
22+
t.AddService(in.Service)
23+
t.Television.AddLinkedService(in.Service)
24+
25+
in.ConfiguredName.OnValueRemoteUpdate(func(str string) {
26+
fmt.Printf(" %s configured name => %s\n", name, str)
27+
})
28+
in.InputSourceType.OnValueRemoteUpdate(func(v int) {
29+
fmt.Printf(" %s source type => %v\n", name, v)
30+
})
31+
in.IsConfigured.OnValueRemoteUpdate(func(v int) {
32+
fmt.Printf(" %s configured => %v\n", name, v)
33+
})
34+
in.CurrentVisibilityState.OnValueRemoteUpdate(func(v int) {
35+
fmt.Printf(" %s current visibility => %v\n", name, v)
36+
})
37+
in.Identifier.OnValueRemoteUpdate(func(v int) {
38+
fmt.Printf(" %s identifier => %v\n", name, v)
39+
})
40+
in.InputDeviceType.OnValueRemoteUpdate(func(v int) {
41+
fmt.Printf(" %s device type => %v\n", name, v)
42+
})
43+
in.TargetVisibilityState.OnValueRemoteUpdate(func(v int) {
44+
fmt.Printf(" %s target visibility => %v\n", name, v)
45+
})
46+
in.Name.OnValueRemoteUpdate(func(str string) {
47+
fmt.Printf(" %s name => %s\n", name, str)
48+
})
49+
}
50+
51+
// TODO
52+
// - Refactoring how to store characteristic values
53+
func main() {
54+
log.Debug.Enable()
55+
56+
info := accessory.Info{
57+
Name: "Television",
58+
}
59+
acc := accessory.NewTelevision(info)
60+
61+
acc.Television.Active.SetValue(characteristic.ActiveActive)
62+
acc.Television.SleepDiscoveryMode.SetValue(characteristic.SleepDiscoveryModeAlwaysDiscoverable)
63+
acc.Television.ActiveIdentifier.SetValue(1)
64+
acc.Television.CurrentMediaState.SetValue(characteristic.CurrentMediaStatePause)
65+
acc.Television.TargetMediaState.SetValue(characteristic.TargetMediaStatePause)
66+
67+
acc.Television.Active.OnValueRemoteUpdate(func(v int) {
68+
fmt.Printf("active => %d\n", v)
69+
})
70+
71+
acc.Television.ActiveIdentifier.OnValueRemoteUpdate(func(v int) {
72+
fmt.Printf("active identifier => %d\n", v)
73+
})
74+
75+
acc.Television.ConfiguredName.OnValueRemoteUpdate(func(v string) {
76+
fmt.Printf("configured name => %s\n", v)
77+
})
78+
acc.Television.SleepDiscoveryMode.OnValueRemoteUpdate(func(v int) {
79+
fmt.Printf("sleep discovery mode => %d\n", v)
80+
})
81+
acc.Television.Brightness.OnValueRemoteUpdate(func(v int) {
82+
fmt.Printf("brightness => %d\n", v)
83+
})
84+
acc.Television.ClosedCaptions.OnValueRemoteUpdate(func(v int) {
85+
fmt.Printf("closed captions => %d\n", v)
86+
})
87+
acc.Television.DisplayOrder.OnValueRemoteUpdate(func(v []byte) {
88+
fmt.Printf("display order => %v\n", v)
89+
})
90+
acc.Television.CurrentMediaState.OnValueRemoteUpdate(func(v int) {
91+
fmt.Printf("current media state => %d\n", v)
92+
})
93+
acc.Television.TargetMediaState.OnValueRemoteUpdate(func(v int) {
94+
fmt.Printf("target media state => %d\n", v)
95+
})
96+
97+
acc.Television.PowerModeSelection.OnValueRemoteUpdate(func(v int) {
98+
fmt.Printf("power mode selection => %d\n", v)
99+
})
100+
101+
acc.Television.PictureMode.OnValueRemoteUpdate(func(v int) {
102+
fmt.Printf("PictureMode => %d\n", v)
103+
})
104+
105+
acc.Television.RemoteKey.OnValueRemoteUpdate(func(v int) {
106+
switch v {
107+
case characteristic.RemoteKeyRewind:
108+
fmt.Println("Rewind")
109+
case characteristic.RemoteKeyFastForward:
110+
fmt.Println("Fast forward")
111+
case characteristic.RemoteKeyExit:
112+
fmt.Println("Exit")
113+
case characteristic.RemoteKeyPlayPause:
114+
fmt.Println("Play/Pause")
115+
case characteristic.RemoteKeyInfo:
116+
fmt.Println("Info")
117+
case characteristic.RemoteKeyNextTrack:
118+
fmt.Println("Next")
119+
case characteristic.RemoteKeyPrevTrack:
120+
fmt.Println("Prev")
121+
case characteristic.RemoteKeyArrowUp:
122+
fmt.Println("Up")
123+
case characteristic.RemoteKeyArrowDown:
124+
fmt.Println("Down")
125+
case characteristic.RemoteKeyArrowLeft:
126+
fmt.Println("Left")
127+
case characteristic.RemoteKeyArrowRight:
128+
fmt.Println("Right")
129+
case characteristic.RemoteKeySelect:
130+
fmt.Println("Select")
131+
case characteristic.RemoteKeyBack:
132+
fmt.Println("Back")
133+
}
134+
})
135+
136+
config := hc.Config{Pin: "12344321", StoragePath: "./db"}
137+
t, err := hc.NewIPTransport(config, acc.Accessory)
138+
139+
addInputSource(acc, 1, "HDMI 1", characteristic.InputSourceTypeHdmi)
140+
addInputSource(acc, 2, "HDMI 2", characteristic.InputSourceTypeHdmi)
141+
addInputSource(acc, 3, "Netflix", characteristic.InputSourceTypeApplication)
142+
addInputSource(acc, 4, "YouTube", characteristic.InputSourceTypeApplication)
143+
addInputSource(acc, 5, "Twitter", characteristic.InputSourceTypeApplication)
144+
addInputSource(acc, 6, "Composite Video", characteristic.InputSourceTypeCompositeVideo)
145+
addInputSource(acc, 7, "S-Video", characteristic.InputSourceTypeSVideo)
146+
addInputSource(acc, 8, "Component Video", characteristic.InputSourceTypeComponentVideo)
147+
addInputSource(acc, 9, "Dvi", characteristic.InputSourceTypeDvi)
148+
addInputSource(acc, 10, "Airplay", characteristic.InputSourceTypeAirplay)
149+
addInputSource(acc, 11, "Usb", characteristic.InputSourceTypeUsb)
150+
151+
if err != nil {
152+
log.Info.Panic(err)
153+
}
154+
155+
hc.OnTermination(func() {
156+
<-t.Stop()
157+
})
158+
159+
t.Start()
160+
}

_img/home-icon.png

10.9 KB
Loading

0 commit comments

Comments
 (0)