Homebridge 教程:使用 Homekit 和 Siri 控制 Mote

由于 Mote 是为家庭照明设计的,比如低架或者低架照明,自动化控制开启了许多可能性。

幸运的是,苹果的 Homekit API 已经有一个名为 homebridge 的扩展开源项目,一个 Node.js 库及一些有用的插件,用于控制从 RGB LED 灯(如 Mote)到 Sonos 扬声器甚至是 Xbox One 的所有内容。

虽然,苹果不久将发布一个家庭应用程序(与 iOS 10 一起),以允许您控制启用 Homekit 的设备,但还有其他一些应用程序允许您执行相同的操作。我们最喜欢的就是 Hesperus,它提供了一个干净、直观的界面,可以用各种设备和计划动作设置场景。

(更新:苹果公司现在已经发布了他们的家庭应用程序,我们可以证实,它适用于我们下面描述的 Mote API)

在这里,我们将介绍如何设置 Flask API 来控制 Mote,如何安装、配置 Homebridge 和 homebridge-better-http-rgb 插件,以及如何使用 Hesperus 应用程序和 Siri 来控制 Mote。

步骤1:安装 Mote 和 Flask Python 库

我们需要一些 Python 库( Mote 和 Flask 库),所以现在就开始安装这些库,然后再开始阅读代码。

如果你在 Raspberry Pi 上设置这个,我们推荐使用这个方式,那么你可以使用下面的命令来安装 Mote 库:

curl https://get.pimoroni.com/mote | bash

如果您不使用 Raspberry Pi,那么您可以使用 Python 软件包安装程序 pip 来安装 Mote 库。

sudo pip install mote

我们还需要安装 Flask 库,我们也可以使用 pip 来安装它。 键入以下内容来安装 Flask:

sudo pip install flask

步骤2:为 Mote 写一个 Flask API

我们将于接收来自 Hesperus 和 Siri 的信息的 homebridge 插件,称为homebridge-better-http-rgb。它使用一系列结点,将命令转发到 RGB LED 灯。我们的 Flask API 将定义这些结点,并使用它们来开关 Mote LED,控制它们的亮度并控制它们的色调。

由 homebridge-better-http-rgb 定义的结点是 onoffstatus(灯光是否打开)、brightness,并使用 set 设置色调。brightness` 和set结点,当没有后续值调用时,将分别返回当前设置的亮度或色调。否则,可以将值传递到这些结点,例如,brightness/50将亮度设置为 50%,或者用set/FF0000`` 设置为红色。

Flask 是一个用于构建 Web 应用程序的超级小 Python 库,也可以用来构建简单的 API(应用程序编程接口),让您以编程方式控制事物,无论它们是物理设备还是 Web 服务。

我们的 Flask API 大概有100行,所以我们会逐一浏览一下,看看它们都做了什么。

导入

首先,我们需要导入一些我们将用于 API 的东西:

from colorsys import hsv_to_rgb, rgb_to_hsv
from mote import Mote
from flask import Flask, jsonify, make_response

colorsys 函数 hsv_to_rgbrgb_to_hsv 将用于互换 HSV 和 RGB 颜色(稍后更多)。我们需要 Mote 类来控制 Mote,以及 Flask 类和 jsonifymake_response 函数来构建我们的 API。

模板

在最上面,我们有一些样板代码,它们设置了我们的代码所需的一些东西,来初始化 Flask 应用程序并为 Mote 设置一些参数。

app = Flask(__name__)
mote = Mote()

mote.configure_channel(1, 16, False)
mote.configure_channel(2, 16, False)
mote.configure_channel(3, 16, False)
mote.configure_channel(4, 16, False)

colour = 'FFFFFF'
status = 0

我们将控制器的四个通道分别配置为 16 像素,然后创建 colourstatus 变量,稍后我们将使用这些颜色和状态,对于颜色显示默认的白色,对于状态为 0 或关闭。

Mote 函数

我们其余的大部分代码都是由各种函数组成的,我们可以将这些功能分解为与控制 Mote 相关的功能,以及 Flask 用来创建 API 结点的功能。

先来看看Mote的功能。

因为我们的 homebridge 期望颜色是十六进制的,而且 Mote 期望颜色是 RGB,所以我们有一些相互转换的轻微复杂的任务。 colorsys 库具有互换 HSV 和 RGB 值的功能,但不幸的是没有函数来进行十六进制值互相转换。 所以,我们将写一个简单的函数来将十六进制转换为RGB。

def hex_to_rgb(value):
    value = value.lstrip('#')
    length = len(value)
    return tuple(int(value[i:i + length / 3], 16) for i in range(0, length, length / 3))

接下来,我们有几个开关 Mote 的函数。mote_on 函数接受一个参数 - c - 颜色作为十六进制值。然后使用我们刚刚写的 hex_to_rgb 函数从十六进制颜色 c 中获取 rgb 值,并将所有条的所有像素设置为该颜色。此功能将用于开启 Mote,并在开启时更改 Mote 的颜色。

def mote_on(c):
    r, g, b = hex_to_rgb(c)
    for channel in range(4):
        for pixel in range(16):
            mote.set_pixel(channel + 1, pixel, r, g, b)
    mote.show()
    return True

我们的 mote_off 函数是一个简单的函数,可以关闭所有的像素。

def mote_off():
    mote.clear()
    mote.show()
    return True

Flask API 函数

其余功能与 API 本身相关,并定义 homebridge-better-http-rgb 插件将使用的端点。就像 API 惯例一样,我们所有的端点都将从 /mote/api/v1.0/开始,告诉我们 API 的名字,指定它的确是一个 API,而不是一个网页,以及提供的版本号 一旦开发出更新的版本,就具有了遗留支持的手段。

On/off/status

我们要定义的第一个端点是 /mote/api/v1.0/status, /mote/api/v1.0/on/mote/api/v1.0/off。 状态端点允许 API 返回 Mote 的状态 - 无论它是打开还是关闭 - 所以我们将使用状态变量,即关闭时为 0 或开启时为 1,并将其设置为 get_status 函数的一部分。

def get_status():
    global status
    for channel in range(4):
        for pixel in range(16):
            if mote.get_pixel(channel + 1, pixel) != (0, 0, 0):
                status = 1
            else:
                status = 0
    return status

我们的函数将状态定义为一个全局变量,所以它的状态持续在所有代码中,在函数内部和外部。 然后循环遍历所有通道上的所有像素,然后检查它们是否打开或关闭。 如果它们是打开的,则状态设置为1,否则状态设置为0。

我们将在 set_status 函数中使用我们刚刚在第一个路由中写入的那个函数。 在 Flask中,端点被封装在一个 @ app.route 装饰器中,该装饰器将其定义为 URL 路由。

@app.route('/mote/api/v1.0/<string:st>', methods=['GET'])
def set_status(st):
    global status, colour
    if st == 'on':
        status = 1
        mote_on(colour)
    elif st == 'off':
        status = 0
        mote_off()
    elif st == 'status':
        status = get_status()
    return jsonify({'status': status, 'colour': colour})

我们的 app.route 装饰器将URL结构定义为 '/mote/api/v1.0/ <string:st>'。第一部分 - /mote/api/v1.0/ - 对我们所有的 URL 端点都是通用的。<string:st> 部分是一个巧妙的小技巧,Flask 用来获取 URL 的一部分,并将其直接赋值给一个变量,甚至可以让你设置什么类型,在这种情况下,一个名为 st 的字符串我们也使用 methods = ['GET']指定这个 URL 将发送一个 get 请求。

set_status 函数从 URL 中传递 st 变量,然后根据 st 是否处于开启,关闭或状态,进行相应的操作。如果st等于'on',则使用当前设置的全局颜色调用 mote_on 函数,状态全局设置为 1,如果等于 off,则调用 mote_off 函数,状态设置为 0。如果 st 等于 'status',那么我们调用我们的 get_status 函数。

最后,我们返回 JSON 格式的状态和颜色,使用 jsonify 函数,传递一个具有适当的键和值的字典。当一个 get 请求被发送到这个URL路由时,JSON-ified 字典将被返回,而不是正常情况下的 HTML 页面。

获取和设置颜色

homebridge-better-http-rgb 指定 /set 端点将返回当前设置的颜色。我们将编写一个简单的路由函数,返回全局颜色值,并以与我们写的最后一条路由相同的 JSON 格式返回。

@app.route('/mote/api/v1.0/set', methods=['GET'])
def get_colour():
    global colour
    return jsonify({'status': status, 'colour': colour})

再次,我们使用 @app.route 装饰器将 URL 设置为 “/mote/api/v1.0/set”,并指定它将发送一个 get 请求。访问 URL 时调用的 get_colour 函数,仅返回包含状态和颜色的 JSON 查询字典。

我们还需要一个 set_colour 函数来设置颜色! 它用十六进制颜色扩展/设置路线,例如 FF0000 红色。

@app.route('/mote/api/v1.0/set/<string:c>', methods=['GET'])
def set_colour(c):
    global status, colour
    colour = c
    if status != 0:
        mote_on(colour)
        status = 1
    return jsonify({'status': status, 'colour': colour})

404

为了完成本书的工作,我们将使用 Flask 的 @app.errorhandler 装饰器来优雅地处理 404 未找到的错误。

@app.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)

主函数

在Flask应用程序中,首先在命令行运行应用程序时运行主函数。除了使用 app.run(host ='0.0.0.0',debug = True) 实际运行应用程序外,我们还将调用 mote_off() 函数在脚本首次运行时将 Mote 关闭。

if __name__ == '__main__':
    mote_off()
    app.run(host='0.0.0.0', debug=True)

测试 API

现在我们已经编写了我们的 API,我们可以测试端点按预期工作。 整个代码在下面,所以将其复制并保存在一个名为 mote_api.py 的文件中。

from colorsys import hsv_to_rgb, rgb_to_hsv
from mote import Mote
from flask import Flask, jsonify, make_response

app = Flask(__name__)
mote = Mote()

mote.configure_channel(1, 16, False)
mote.configure_channel(2, 16, False)
mote.configure_channel(3, 16, False)
mote.configure_channel(4, 16, False)

colour = 'FFFFFF'
status = 0

def hex_to_rgb(value):
    value = value.lstrip('#')
    length = len(value)
    return tuple(int(value[i:i + length / 3], 16) for i in range(0, length, length / 3))

def mote_on(c):
    r, g, b = hex_to_rgb(c)
    for channel in range(4):
        for pixel in range(16):
            mote.set_pixel(channel + 1, pixel, r, g, b)
    mote.show()
    return True

def mote_off():
    mote.clear()
    mote.show()
    return True

def get_status():
    global status
    for channel in range(4):
        for pixel in range(16):
            if mote.get_pixel(channel + 1, pixel) != (0, 0, 0):
                status = 1
    return status

@app.route('/mote/api/v1.0/<string:st>', methods=['GET'])
def set_status(st):
    global status, colour
    if st == 'on':
        status = 1
        mote_on(colour)
    elif st == 'off':
        status = 0
        mote_off()
    elif st == 'status':
        status = get_status()
    return jsonify({'status': status, 'colour': colour})

@app.route('/mote/api/v1.0/set', methods=['GET'])
def get_colour():
    global colour
    return jsonify({'status': status, 'colour': colour})

@app.route('/mote/api/v1.0/set/<string:c>', methods=['GET'])
def set_colour(c):
    global status, colour
    colour = c
    if status != 0:
        mote_on(colour)
        status = 1
    return jsonify({'status': status, 'colour': colour})

@app.errorhandler(404)
def not_found(error):
    return make_response(jsonify({'error': 'Not found'}), 404)

if __name__ == '__main__':
    mote_off()
    app.run(host='0.0.0.0', debug=True)

打开一个终端并输入 python mote_api.py

然后,打开另一个终端窗口或选项卡,然后输入以下内容来测试我们的API是否按预期工作。

curl -i http://127.0.0.1:5000/mote/api/v1.0/on

这应该只是把你的 Mote 打开!您还应该能够在另一台机器上远程执行此操作,将 URL 的 127.0.0.1 部分替换为运行 API 的机器的 IP 地址。 你也应该能够在你的网页浏览器中做到这一点,而不是在终端上使用 curl

尝试输入以下内容将 Mote 条的颜色更改为红色。

curl -i http://127.0.0.1:5000/mote/api/v1.0/set/FF0000

步骤4:设置 Homebridge 和 homebridge-better-http-rgb

下一步是在运行 Mote API 的机器上设置 homebridge 和 homebridge-better-http-rgb 来完成这个循环。 homebridge 和 homebridge-better-http-rgb 插件提供了将 Mote 添加为可以通过像 Hesperus 这样的应用程序进行控制的 Homekit 设备的方法,并将命令发送到我们的 API,然后发送到 Mote 条带。

以下说明假定您使用的是运行 Raspbian Jessie 最新版本的 Raspberry Pi 3,但经过一些修改,您应该可以在 Mac,Windows PC 或其他 Linux 机器上运行所有程序。

打开一个终端,输入以下内容升级到 Node.js 的最新版本:

sudo apt-get update
sudo apt-get upgrade
curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
sudo apt-get install -y nodejs

在安装 Homebridge 之前,我们需要先安装一些依赖:

sudo apt-get install libavahi-compat-libdnssd-dev

然后安装 homebridge 和 homebridge-better-http-rgb 插件:

sudo npm install -g --unsafe-perm homebridge
sudo npm install -g --unsafe-perm homebridge-better-http-rgb

现在所有东西都已经安装好了,我们还需要做更多的事情来正确配置 Homebridge。homebridge 是通过一个.json文件来配置的,它必须放在 /home/pi/.homebridge/ 目录下。 我们现在创建这个目录:

mkdir /home/pi/.homebridge

我们的配置文件如下所示:

{
    "bridge": {
        "name": "Homebridge",
        "username": "CC:22:3D:E3:CE:32",
        "port": 51826,
        "pin": "031-45-155"
    },

    "description": "Homebridge",

    "accessories": [
        {
            "accessory": "HTTP-RGB",
            "name": "Mote",

            "switch": {
                "status": "http://127.0.0.1:5000/mote/api/v1.0/status",
                "powerOn": "http://127.0.0.1:5000/mote/api/v1.0/on",
                "powerOff": "http://127.0.0.1:5000/mote/api/v1.0/off"
            },

            "brightness": {
                "status": "http://127.0.0.1:5000/mote/api/v1.0/brightness",
                "url": "http://127.0.0.1:5000/mote/api/v1.0/brightness/%s"
            },

            "color": {
                "status": "http://127.0.0.1:5000/mote/api/v1.0/set",
                "url": "http://127.0.0.1:5000/mote/api/v1.0/set/%s",
                "brightness": true
            }
        }
    ],

    "platforms": []
}

复制粘贴,并在我们刚刚创建的 /home/pi/.homebridge/目录中,保存为 config.json

您可以将 bridge name 和 description 更改为任何您想要的名称,以及我们称为 “Mote” 的 accessory 名称。username, port 和 pin 都是样板值,可以保留原样。

如果在以后的日子,您想要使用其他 Homebridge 插件添加其他配件,那么您可以将它们添加为 accessories 列表中的新配件。

现在所有的东西都已经建立好了,我们将首先启动 Mote API,然后再启动 Homebridge。

假设您的 Mote API 被称为 mote_api.py 并位于 /home/pi/ 中,请输入以下命令启动它:

python /home/pi/mote_api.py

您将看到几行信息,告诉您 Flask 应用程序的状态,包括其运行的IP地址和端口。

现在,打开另一个终端选项卡或窗口,然后输入 homebridge 启动家庭网桥。

您将看到几行确认 Mote 附件已成功加载,并且在您的 iPhone 上配置 Homekit 应用程序时可以输入代码。 不需要编写这段代码,因为它和我们之前在配置文件中配置的代码一样。

步骤5:用 Siri 控制 Mote

接着,打开我们的 Homekit(家庭)应用程序,手动输入我们在 Homebridge 中定义的 PIN 码:

031-45-155

就可以在应用中看到我们的 Mote。

另外一个好处就是现在我们已经有了 Homekit 的 Mote,我们可以用 Siri 来控制它。我们可以使用我们在配置文件中,给定的 Mote 附件的名字(在我们的例子中是“Mote”)来控制它。

如果您启用了 “嗨,Siri”,请尝试说 “嘿,Siri。开启Mote。”,或者按住 home 键启动 Siri 并说“打开 Mote”。

有一点灵活性,所以你也应该可以说 “开启 Mote”,“打开灯”,也许还有其他一些措辞。

你也可以说 “将亮度设置为25%”,或者 “将 Mote 设置为红色”。

如果您有Apple Watch,那么您也可以使用Siri来控制您的家庭设备。随着苹果添加到 OS X 的 Siri,你也应该能够很快用你的 Mac 来控制它们。

更进一步

我们仅用一个Mote控制器进行了基本设置,但是您可以轻松扩展此功能,或者在同一个 Pi 上使用其他 Mote 控制器,并扩展 API 端点以在 URL 中包含控制器编号,或者使用其他 Pis 和控制器在单独的IP地址。您也可以修改 API,以单独控制每个控制器上的每个条。

一个简单的方式来鼓励你的 Mote API,当你打开或关闭你的 Mote 时,包括一个简短的淡入淡出,使它打开或关闭时看起来不那么刺耳。

而且,当然,Homebridge 的美妙之处在于,您可以轻松添加更多的插件和配件,以便通过触发一个动作,启动您的 Sonos 播放流畅的爵士乐,并将灯光打开。

原文链接:https://learn.pimoroni.com/tutorial/sandyj/using-mote-with-homekit-and-siri

尚未评分
您的评分将帮助我们做出更好的玩法

观光\评论区

Copyright © 2017 玩点什么. All Rights Reserved.