使用Siri和树莓派DIY智能家居

需求

解决每天的开关灯操作,可以通过

  • “嘿Siri, 帮我把灯打开”
  • “嘿Siri, 关灯”

实现控制卧室灯开关

设计

  1. 给家里的普通灯换一个无线开关(86型,315MHz 单火线无线遥控开关),淘宝上很多,使用固定编码
  2. 使用树莓派搭建HomeKit API网关
  3. 通过树莓派驱动315MHz无线模块,发射开关信号
  4. iPhone上安装Homekit APP:MyTouchHome,让手机可以发出控制指令

实现

实现过程中发现买的OPPLE的调光调色LED灯的遥控器没有采用315M/433M,无法使用现有模块去实现。

遥控拆了,从电路板上“剥皮”,使用漆包线跳线出来(忘拍图了)

之前有尝试nodejs去做(使用homebridge),现在对golang更感兴趣,改用golang实现。

最终测试OK,实现开灯关灯,调光调色以后再折腾

测试成功

代码

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
package main

import (
"os"
"os/signal"
"time"

"github.com/brutella/hc"
"github.com/brutella/hc/accessory"
"github.com/brutella/log"
"github.com/davecheney/gpio"
)

func main() {
log.Verbose = true
log.Info = true

// GPIO
pinOn, err := gpio.OpenPin(20, gpio.ModeOutput)
if err != nil {
log.Fatalf("error opening pinOn! %s\n", err)
}
pinOff, err := gpio.OpenPin(21, gpio.ModeOutput)
if err != nil {
log.Fatalf("error opening pinOff! %s\n", err)
}
pinState, err := gpio.OpenPin(16, gpio.ModeInput)
if err != nil {
log.Fatalf("error opening pinState! %s\n", err)
}

// turn the led off on exit
c := make(chan os.Signal, 1)
signal.Notify(c, os.Interrupt)
go func() {
for _ = range c {
log.Printf("\nClearing and unexporting the pin.\n")
pinOn.Clear()
// pinOn.Close()
pinOff.Clear()
// pinOff.Close()
os.Exit(0)
}
}()

// HomeControl
info := accessory.Info{
Name: "JerryLamp",
Manufacturer: "Jerry",
}

acc := accessory.NewLightbulb(info)

acc.Lightbulb.On.OnValueRemoteUpdate(func(on bool) {
if on == true {
// 发送开关信号到遥控器
pinOn.Set()
time.AfterFunc(600*time.Millisecond, func() {
pinOn.Clear()
})
log.Println("Turn Light On")
} else {
pinOff.Set()
time.AfterFunc(600*time.Millisecond, func() {
pinOff.Clear()
})
log.Println("Turn Light Off")
}
})

// 状态检测
var timer *time.Timer
timer = time.AfterFunc(1*time.Second, func() {
acc.Lightbulb.On.SetValue(!pinState.Get())
timer.Reset(1 * time.Second)
})

t, err := hc.NewIPTransport(hc.Config{Pin: "00102003"}, acc.Accessory)
if err != nil {
log.Fatal(err)
}

hc.OnTermination(func() {
t.Stop()
})

t.Start()
}