树莓派3B+ 智能家居(HomeKit)

来源:互联网 发布:c 语言编译器安卓版 编辑:程序博客网 时间:2024/06/11 15:02

树莓派3B+ 智能家居(HomeKit)

当今科技发展日新月异,越来越多的新兴技术步入人们生活,智能家居同样也不例外,然后人们面对新科技却望而却步,因为整套设备的价格是非常昂贵的,而且现在还没有一个厂商能提供一套完整且稳定的系统,导致现在还不能快速普及。如果你想尝尝鲜,那么,一个树莓派就能为你创建一个这样的基础环境。

1.安装脚本

安装过程比较累赘,这里就不做过多的解释了。
安装所需的库 :Node 和 HAP-NodeJS(Node版本为8.2.1,HAP-NodeJS更新为Nov 6, 2017)
打包链接:http://download.csdn.net/download/kxwinxp/10124545

完整实现脚本如下:

#!/bin/bashPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/binexport PATHecho "+----------------------------------------------------------------------|                 HAP-NodeJS FOR Debian raspberry+----------------------------------------------------------------------|            Copyright © 2017 kioye All rights reserved.+----------------------------------------------------------------------"#make sure your confirm. read -p "Do you want to install HAP-NodeJS to the $setup_path directory now?(y/n): " go;if [ "$go" == 'n' ]||[ "$go" == 'N' ];then    exit;fi# get into directory of applicationcd ~mkdir applicationcd applicationsudo apt-get install -y git avahi-daemon avahi-discover libnss-mdns libavahi-compat-libdnssd-dev build-essential# apt-get update --fix-missing -ysudo service avahi-daemon startwget -O node.tar.gz https://nodejs.org/dist/v8.2.1/node-v8.2.1-linux-armv7l.tar.xztar -zxvf node.tar.gzmv node-*l usrsudo cp -rf usr /# install node base cross-platformsudo npm install -g -y node-gyp# install C++ libsudo apt-get install -y libavahi-compat-libdnssd-dev# download HAP-NodeJSgit clone https://github.com/KhaosT/HAP-NodeJS.gitsudo chmod -R 777 /root ./HAP-NodeJS# get into HAP-NodeJS directorycd HAP-NodeJS# install some access for HAP-NodeJSsudo npm install -y node-persist debug mdns fast-srp-hap ed25519 buffer-shims curve25519-n2 ip python-shellcd ..echo "+----------------------------------------------------------------------|                    HAP-NodeJS Installed finish!!+----------------------------------------------------------------------|   start in Bridged mode:|         sudo node HAP-NodeJS/BridgedCore.js+----------------------------------------------------------------------|   run as an independent HomeKit device:|         sudo node HAP-NodeJS/Core.js+----------------------------------------------------------------------"exit 0

2.添加到自启动

sudo vim /etc/rc.local// 在 exit 0 前添加如下:# HAP-NodeJS 开机自启脚本(nohup为后台执行,run.log为运行记录。)sudo nohup node /home/pi/application/HAP-NodeJS/Core.js >/home/pi/application/HAP-NodeJS/run.log 2>&1 &# python GPIO口初始化!python /home/pi/application/HAP-NodeJS/python/init.py

GPIO初始化口,我接下来要用的是 11、13和15口。
脚本如下:

vim ~/application/HAP-NodeJS/python/init.py// -------------请完整复制粘贴如下内容!!------------------#!/usr/bin/env pythonimport RPi.GPIO as GPIOimport sysdef setup(p):    GPIO.setmode(GPIO.BOARD)    GPIO.setup(p, GPIO.OUT)GPIO.setwarnings(False)# 初始化 11、13和15口。arr={11,13,15}for gp in arr:    setup(gp);sys.exit(0)

3.HAP-NodeJS介绍

GitHub:https://github.com/KhaosT/HAP-NodeJS


HAP Nodejs是一个通过Nodejs搭建的HomeKit服务器。因此,它能直接和苹果 家庭(home)应用相连。苹果设备又支持Siri,故可以直接通过Siri控制HomeKit设备。

它有两种启动模式:

  • 桥接模式启动HAP服务器:
    sudo node HAP-NodeJS/BridgedCore.js
  • 独立模式(各配件作为一个的HomeKit设备启动):
    sudo node HAP-NodeJS/Core.js

可自己定义配件:

  • 格式为:accessories/**_accessory.js文件
    **为简短的描述,所有此类定义的附件都会在服务器上加载。(非此类将不会加载!)

4.模拟配件


4.1 模拟一个两级亮度的灯

该配件是通过python-shell来控制GPIO,故需安装python的gpio包。

sudo apt-get install -y python-rpi.gpio

一个控制灯的附件代码:

功能:控制 GPIO 13 和 15 口,分别控制灯开关和亮度(两级),默认高电平为开启。
可以直接在var powergp='13';var brightnessgp='15';修改GPIO口。

GPIO

// 创建MyTableLight_accessory.jssudo vim ~/application/HAP-NodeJS/accessories/MyTableLight_accessory.js// -------------请完整复制粘贴如下内容!!------------------var Accessory = require('../').Accessory;var Service = require('../').Service;var Characteristic = require('../').Characteristic;var uuid = require('../').uuid;var PythonShell = require('python-shell');var powergp='13';var brightnessgp='15';var LightController = {  name: "My Table Light", //name of accessory  pincode: "031-45-154",  username: "FA:3C:ED:5A:1A:1F", // MAC like address used by HomeKit to differentiate accessories.   manufacturer: "HAP-NodeJS", //manufacturer (optional)  model: "v1.0", //model (optional)  serialNumber: "A12S345KGB", //serial number (optional)  power: false, //curent power status  brightness: 100, //current brightness  hue: 0, //current hue  saturation: 0, //current saturation  outputLogs: true, //output logs  setPower: function(status) { //set power of accessory    if(this.outputLogs) {        console.log("Turning the '%s' %s", this.name, status ? "on" : "off");    }    PythonShell.run('../../home/pi/application/HAP-NodeJS/python/gpio.py', {args:[powergp+':'+(status?1:0)]}, function (err,results) {      if (err) console.log(err);    });    this.power = status;  },  getPower: function() { //get power of accessory    PythonShell.run('../../home/pi/application/HAP-NodeJS/python/gpio.py', {args:[powergp+':g']}, function(err,results){        console.log('results: %j', results);        var resultMap=eval('('+results.pop()+')');        this.power=(resultMap[powergp]==1)?true:false;    });    if(this.outputLogs) console.log("'%s' is %s.", this.name, this.power ? "on" : "off");    return this.power;  },  setBrightness: function(brightness) { //set brightness    if(this.outputLogs) console.log("Setting '%s' brightness to %s", this.name, brightness);    PythonShell.run('../../home/pi/application/HAP-NodeJS/python/gpio.py', {args:[brightnessgp+':'+((brightness <= 50)?1:0)]}, function (err,results) {      if (err) console.log(err);    });    this.brightness = brightness;  },  getBrightness: function() { //get brightness    PythonShell.run('../../home/pi/application/HAP-NodeJS/python/gpio.py', {args:[brightnessgp+':g']}, function(err,results){        console.log('results: %j', results);        var resultMap=eval('('+results.pop()+')');        this.brightness=(resultMap[brightnessgp]==1)?50:100;    });    if(this.outputLogs) console.log("'%s' brightness is %s", this.name, this.brightness);    return this.brightness;  },  setSaturation: function(saturation) { //set brightness    if(this.outputLogs) console.log("Setting '%s' saturation to %s", this.name, saturation);    this.saturation = saturation;  },  getSaturation: function() { //get brightness    if(this.outputLogs) console.log("'%s' saturation is %s", this.name, this.saturation);    return this.saturation;  },  setHue: function(hue) { //set brightness    if(this.outputLogs) console.log("Setting '%s' hue to %s", this.name, hue);    this.hue = hue;  },  getHue: function() { //get hue    if(this.outputLogs) console.log("'%s' hue is %s", this.name, this.hue);    return this.hue;  },  identify: function() { //identify the accessory    if(this.outputLogs) console.log("Identify the '%s'", this.name);  }}// Generate a consistent UUID for our light Accessory that will remain the same even when// restarting our server. We use the `uuid.generate` helper function to create a deterministic// UUID based on an arbitrary "namespace" and the word "light".var lightUUID = uuid.generate('hap-nodejs:accessories:light' + LightController.name);// This is the Accessory that we'll return to HAP-NodeJS that represents our light.var lightAccessory = exports.accessory = new Accessory(LightController.name, lightUUID);// Add properties for publishing (in case we're using Core.js and not BridgedCore.js)lightAccessory.username = LightController.username;lightAccessory.pincode = LightController.pincode;// set some basic properties (these values are arbitrary and setting them is optional)lightAccessory  .getService(Service.AccessoryInformation)    .setCharacteristic(Characteristic.Manufacturer, LightController.manufacturer)    .setCharacteristic(Characteristic.Model, LightController.model)    .setCharacteristic(Characteristic.SerialNumber, LightController.serialNumber);// listen for the "identify" event for this AccessorylightAccessory.on('identify', function(paired, callback) {  LightController.identify();  callback();});// Add the actual Lightbulb Service and listen for change events from iOS.// We can see the complete list of Services and Characteristics in `lib/gen/HomeKitTypes.js`lightAccessory  .addService(Service.Lightbulb, LightController.name) // services exposed to the user should have "names" like "Light" for this case  .getCharacteristic(Characteristic.On)  .on('set', function(value, callback) {    LightController.setPower(value);    // Our light is synchronous - this value has been successfully set    // Invoke the callback when you finished processing the request    // If it's going to take more than 1s to finish the request, try to invoke the callback    // after getting the request instead of after finishing it. This avoids blocking other    // requests from HomeKit.    callback();  })  // We want to intercept requests for our current power state so we can query the hardware itself instead of  // allowing HAP-NodeJS to return the cached Characteristic.value.  .on('get', function(callback) {    callback(null, LightController.getPower());  });// To inform HomeKit about changes occurred outside of HomeKit (like user physically turn on the light)// Please use Characteristic.updateValue// // lightAccessory//   .getService(Service.Lightbulb)//   .getCharacteristic(Characteristic.On)//   .updateValue(true);// also add an "optional" Characteristic for BrightnesslightAccessory  .getService(Service.Lightbulb)  .addCharacteristic(Characteristic.Brightness)  .on('set', function(value, callback) {    LightController.setBrightness(value);    callback();  })  .on('get', function(callback) {    callback(null, LightController.getBrightness());  });// also add an "optional" Characteristic for SaturationlightAccessory  .getService(Service.Lightbulb)  .addCharacteristic(Characteristic.Saturation)  .on('set', function(value, callback) {    LightController.setSaturation(value);    callback();  })  .on('get', function(callback) {    callback(null, LightController.getSaturation());  });// also add an "optional" Characteristic for HuelightAccessory  .getService(Service.Lightbulb)  .addCharacteristic(Characteristic.Hue)  .on('set', function(value, callback) {    LightController.setHue(value);    callback();  })  .on('get', function(callback) {    callback(null, LightController.getHue());  });

准备一个python脚本控制GPIO口:

sudo vim ~/application/HAP-NodeJS/python/gpio.py// -------------请完整复制粘贴如下内容!!------------------#!/usr/bin/env pythonimport RPi.GPIO as GPIOimport sysdef init(gp):    GPIO.setmode(GPIO.BOARD)    GPIO.setup(gp, GPIO.OUT)GPIO.setwarnings(False)# simple argument echo scriptret={}for arg in sys.argv[1:]:    #print arg    args=arg.split(':')    init(int(args[0]))    if args[1]=='g':        ret[args[0]]=GPIO.input(int(args[0]))    elif args[1]=='0':        GPIO.output(int(args[0]), GPIO.LOW)    elif args[1]=='1':        GPIO.output(int(args[0]), GPIO.HIGH)    #setup(int(v))print retsys.exit(0)

4.2 模拟一个开关插座

我这个插座是接的音响,所以叫“My sound”,不要见怪。
这里使用的是 GPIO 11 口,默认是高电平是开启。
代码如下:

// 创建MySound_accessory.jssudo vim ~/application/HAP-NodeJS/accessories/MySound_accessory.js// -------------请完整复制粘贴如下内容!!------------------var Accessory = require('../').Accessory;var Service = require('../').Service;var Characteristic = require('../').Characteristic;var uuid = require('../').uuid;var err = null; // in case there were any problemsvar PythonShell = require('python-shell');var soundgp='11';// here's a fake hardware device that we'll expose to HomeKitvar FAKE_OUTLET = {    setPowerOn: function(on) {    console.log("Turning the MySound %s!...", on ? "on" : "off");    PythonShell.run('../../home/pi/application/HAP-NodeJS/python/gpio.py', {args:[soundgp+':'+(on?1:0)]}, function (err,results) {      if (err) console.log(err);    });    FAKE_OUTLET.powerOn=on;  },    identify: function() {    console.log("Identify the MySound.");    }}// Generate a consistent UUID for our MySound Accessory that will remain the same even when// restarting our server. We use the `uuid.generate` helper function to create a deterministic// UUID based on an arbitrary "namespace" and the accessory name.var outletUUID = uuid.generate('hap-nodejs:accessories:MySound');// This is the Accessory that we'll return to HAP-NodeJS that represents our fake light.var outlet = exports.accessory = new Accessory('MySound', outletUUID);// Add properties for publishing (in case we're using Core.js and not BridgedCore.js)outlet.username = "1A:2B:3C:4D:5D:FG";outlet.pincode = "031-45-154";// set some basic properties (these values are arbitrary and setting them is optional)outlet  .getService(Service.AccessoryInformation)  .setCharacteristic(Characteristic.Manufacturer, "Oltica")  .setCharacteristic(Characteristic.Model, "Rev-1")  .setCharacteristic(Characteristic.SerialNumber, "A1S2NASF88EW");// listen for the "identify" event for this Accessoryoutlet.on('identify', function(paired, callback) {  FAKE_OUTLET.identify();  callback(); // success});// Add the actual MySound Service and listen for change events from iOS.// We can see the complete list of Services and Characteristics in `lib/gen/HomeKitTypes.js`outlet  .addService(Service.Outlet, "My Sound") // services exposed to the user should have "names" like "Fake Light" for us  .getCharacteristic(Characteristic.On)  .on('set', function(value, callback) {    FAKE_OUTLET.setPowerOn(value);    callback(); // Our fake Outlet is synchronous - this value has been successfully set  });// We want to intercept requests for our current power state so we can query the hardware itself instead of// allowing HAP-NodeJS to return the cached Characteristic.value.outlet  .getService(Service.Outlet)  .getCharacteristic(Characteristic.On)  .on('get', function(callback) {    // this event is emitted when you ask Siri directly whether your light is on or not. you might query    // the light hardware itself to find this out, then call the callback. But if you take longer than a    // few seconds to respond, Siri will give up.    var err = null; // in case there were any problems    if (FAKE_OUTLET.powerOn) {      console.log("Are we on? Yes.");      callback(err, true);    }    else {      console.log("Are we on? No.");      callback(err, false);    }  }); 

控制也是通过调用 gpio.py 的 python 脚本,和 4.1 里面的 python 脚本一样的。

好了,现在可以重启一下树莓派。

5.将HomeKit设备添加到家庭中

添加设备

如图,选择将这些设备添加进去,输入认证代码 03145154(这个可以在accessary.js修改)。

这里写图片描述

然后就可以愉快使用 Siri 进行语音控制了!

原创粉丝点击