作者 | Fortware
责编 | 薄荷茶
微信公众号ID | csdn_iot
本指南说明了如何整合电动窗帘轨道,Raspberry Pi 和 Amazon Echo,这样你就可以要求了Alexa打开窗帘。
一旦完成,你应该可以说:“Alexa,请打开窗帘和Alexa,关上窗帘。
步骤一
设计概述
本设计由以下几个部分组成:
电动窗帘轨道与Raspberry Pi集成
编写一个Python脚本打开和关闭窗帘
编写 Amazon skill,让您的 Echo 与 Raspberry Pi 进行通信
我使用以下组件:
一个 Amazon Echo
电动窗帘轨道,https://www.amazon.co.uk/gp/product/B013X0BZF2
连接 Raspberry Pi GPIO 水晶头网线
一块 Raspberry Pi 开发板
与Raspberry Pi GPIO整合所需的组件(我从Proto-Pic包括订购) Raspberry Pi GPIO 转接口(2x13、带状排线,三种型号 BC547 的 NPN 晶体管、3个1K电阻,1块合适的单面孔板,适量的导线
步骤二
整合电动窗帘轨道和 Raspberry Pi
我买的窗帘轨道有两个控制器 - 有线和无线。 我没有遇到无线,选择了 Raspberry Pi 与有线控制器集成。
一旦拆卸,可以看到有线控制器由四个开关(见电路图)组成——通过跟踪电线,可以看到按钮将三根电线连接到地面(第四根电线)。 'open' 短线导致电机单向启动; 标记为 'close' 短电线以其他方式驱动电机。 'stop' 短线停止电机。
切掉水晶头网线的一端,剥去皮肤。
将原控制器插头的背面与水晶头网线进行比较,确定导线顺序(图中原控制线为白色;水晶头网线为灰色)。使用四条线; 不需要两个。 打开短路,关闭并停止接地线,确认您有正确的电线。 窗帘导轨应打开、关闭和停止。
电线与接地之间的电势为5V - 我认为这是电阻上拉的逻辑输入,接地时切换到低电平。
与 Raspberry Pi GPIO 集成相对简单。 任何基本的晶体管都可以作为开关临时接地每根线,从而模拟开关按压。
图中给出了示例电路。 注意保证电线 Raspberry Pi 和窗帘共地(Raspberry PI 6号引脚)。
我使用标准BJT晶体管 - NPN BC547和1K电阻连接晶体管的基极 Raspberry Pi。
我连接到物理引脚11、15和22号,映射到BCM格式的GPIO引脚17、22和25,更多物理和逻辑引脚之间的关系参考:https://projects.drogon.net/raspberry-pi/wiringpi/pins/
步骤三
准备打开或关闭窗帘 Python 脚本
Raspberry Pi通用输入/输出端口非常灵活 - 简称为GPIO。 有关使用Raspberry Pi GPIO 有许多好的指导和文档。
还有一个优秀的图书馆,可以用Python和C,这使得驱动GPIO非常简单 - Wiring Pi。原页位于:http://wiringpi.com/
在http://raspi.tv/how-to-install-wiringpi2-for-python-on-the-raspberry-pi您可以找到一组有用的安装说明。
一旦安装完成,以下代码应打开和关闭窗帘,每次更改之间有两秒钟的间隙。 该代码通过将GPIO引脚为高电平0.5s模拟按钮,提高晶体管的基极电压,使电流在集电极和发射极之间流动 - 短路到地。
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
openPin=17
closePin=25
stopPin=22
GPIO.setup(openPin, GPIO.OUT)
GPIO.setup(closePin, GPIO.OUT)
GPIO.setup(stopPin, GPIO.OUT)
time.sleep(2)
while (1==1) :
print "Opening\n"
GPIO.output(openPin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(openPin, GPIO.LOW)
time.sleep(2)
print "Stopping\n"
GPIO.output(openPin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(openPin, GPIO.LOW)
time.sleep(2)
print "Stopping\n"
GPIO.output(stopPin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(stopPin, GPIO.LOW)
time.sleep(2)
print "Closing\n"
GPIO.output(closePin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(closePin, GPIO.LOW)
time.sleep(2)
print "Stopping\n"
GPIO.output(stopPin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(stopPin, GPIO.LOW)
time.sleep(2)
步骤四
编写 Amazon Skill 与 Raspberry Pi 进行通信
理想情况下,我们可以要求Alexa打开窗帘。但我现在不知道了。Echo这种类型的请求可以用于上述语音接口。因此,我们会说:‘Alexa,请让窗帘打开'。然后“Alexa,请关上窗帘。
三个步骤:
在 Raspberry Pi 在路由器上创建本地脚本并转发端口
在亚马逊开发者网站上创建一个 Alexa skill
创建Amazon AWS Lambda代理
令人欣慰的是,前人对这个方案有一些优秀的分享,所以我从以下链接中获益颇丰:https://www.instructables.com/id/Control-Raspberry-Pi-GPIO-With-Amazon-Echo-and-Pyt/
该指南解释了如何存在Amazon创建开发人员网站 skill,指出 Amazon 使用ngrok(ssl为http代理)生成输出,然后使用名称Flask-Ask的库在Raspberry Pi上述处理请求。 ngrok必不可少,因为开发者网站只会通过ssl发送请求 - Flask-ask监听http。
ngrok作为一个临时代理很出色,但除非您要支付年费,否则每次重新启动您的pi上的ngrok客户端需要修改方向 Amazon 脚本的URL 。
另一种方法是Amazon AWS在上面创建一个基本的代理,然后你可以重新定向你的请求Pi(假设您已将端口转发到防火墙上以允许请求)。
我使用了Matt创建代理:https://forms.developer.amazon.com/questions/8155/how-to-use-aws-lambda-as-a-proxy-for-non-ssl-serve.html
感谢 Matt !
步骤五
创建本地脚本并在路由器上实现端口转发
在 Raspberry Pi 创建以下脚本:
from flask import Flask
from flask_ask import Ask, statement, convert_errors import RPi.GPIO as GPIO import logging import time
GPIO.setmode(GPIO.BCM)
openPin=17
closePin=25
stopPin=22
GPIO.setup(openPin, GPIO.OUT)
GPIO.setup(closePin, GPIO.OUT)
GPIO.setup(stopPin, GPIO.OUT)
app = Flask(__name__) ask = Ask(app, '/')
app.config['ASK_VERIFY_REQUESTS'] = False
app.config['ASK_APPLICATION_ID'] = 'Unique amazon skill reference''
logging.getLogger("flask_ask").setLevel(logging.DEBUG)
def openCurtains():
print 'Opening curtains'
GPIO.output(openPin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(openPin, GPIO.LOW)
time.sleep(5)
GPIO.output(stopPin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(stopPin, GPIO.LOW)
def closeCurtains():
print 'Closing curtains'
GPIO.output(closePin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(closePin, GPIO.LOW)
time.sleep(5)
GPIO.output(stopPin, GPIO.HIGH)
time.sleep(0.5)
GPIO.output(stopPin, GPIO.LOW)
@ask.intent('GPIOControlIntent', mapping={'status': 'status'})
def gpio_control(status):
if status in ['open', 'yield']: openCurtains() return statement('Good morning Hart Household')
if status in ['close', 'shield']: closeCurtains() return statement('Good evening Hart Household')
if __name__ == '__main__': app.run(host='IP address of Pi', port=5000, debug=True)
启动Pi运行进程。 在路由器上设置端口转发,以便发送到您的公共地址5000端口的请求转发到您的Pi的端口5000。 请注意,如果您的IP地址不是静态的,您可能需要订阅诸如DYNDNS之类的服务。
步骤六
在Amazon 开发者网站创建 Alexa Skill
让我们跟随Patrick的指引 - 从第4步开始:https://www.instructables.com/id/Control-Raspberry-Pi-GPIO-With-Amazon-Echo-and-Pyt/step4/AWS-Account/
Patrick 的第四步:创建一个 Amazon 开发者帐号。
Patrick 的第五步:创建一个新的skill,我使用了这个调用名字“窗帘”,这样Alexa就会回应“Alexa,问窗帘......”
请注意应用程序ID - 您需要将其粘贴到您编写的 Curtains 脚本中,再加上要编写的Lambda代理。
Patrick 的第六步:这里有一些微妙的变化,如截图所示。
意图很简单:
{
"intents": [{
"intent": "GPIOControlIntent",
"slots": [{
"name": "status",
"type": "GPIO_CONTROL"
}]
}]
}
slots值包含两种: open 和 close
调用更简单:
GPIOControlIntent to {status}
Patrick 的第七步:这是我们要使用 Lambda 代理而不是 Ngrok 的地方 - 看下一个阶段。
步骤七
创建 Amazon AWS Lambda 代理
建立 AWS 帐户和创建 lambda 函数的最佳指导可从 Amazon 获得 - https://developer.amazon.com/public/solutions/alexa/alexa-skills-kit/docs/developing-an-alexa-skill-as-a-lambda-function
按照以下说明,直到您准备好将 node.js 代码输入到函数中。
然后使用来自 Matt 的代理:https://forums.developer.amazon.com/questions/8155/how-to-use-aws-lambda-as-a-proxy-for-non-ssl-serve.html。
(我在格式化代码的地方错过了一个 skill - 抱歉):
var http = require('http');
var URLParser = require('url');
console.log('Loading proxy function');
exports.handler = function (json, context)
{
try {
// A list of URL's to call for each applicationId
var handlers = { 'appId':'url', 'your amazon app id':'http://your router address:5000/' };
// Look up the url to call based on the appId
var url = handlers[json.session.application.applicationId];
if (!url) { context.fail("No url found for application id"); }
console.log('Trying url')
console.log(url)
var parts = URLParser.parse(url);
var post_data = JSON.stringify(json);
// An object of options to indicate where to post to
var post_options = { host: parts.hostname, port: (parts.port || 80), path: parts.path, method: 'POST', headers: { 'Content-Type': 'application/json', 'Content-Length': post_data.length } };
// Initiate the request to the HTTP endpoint
console.log(post_options)
var req = http.request(post_options,function(res) {
var body = "";
// Data may be chunked
res.on('data', function(chunk) { body += chunk; });
res.on('end', function() { // When data is done, finish the request
context.succeed(JSON.parse(body)); }); });
req.on('error', function(e) { context.fail('problem with request: ' + e.message); });
// Send the JSON data console.log('Sending data') req.write(post_data); req.end(); } catch (e) { context.fail("Exception: " + e); } };
我还将高级配置中的超时增加到7秒 - 否则,在窗帘完成5秒的活动之前,Lambda代理将超时。
步骤 八
整合与集成
复制Lambda ID - 您需要将其粘贴到Amazon开发中,指示Amazon将请求引导到您的新Lambda代理,将其转发到Raspberry Pi上 - 请参阅第1个屏幕截图。
从亚马逊开发者网站测试skill - 你应该看到第二个屏幕截图的响应。
如果它不起作用,请检查Lambda日志的调用错误和Raspberry Pi脚本输出的错误。
然后打开 Echo 的开发skill - 不要将其对外发送,否则您将失去对窗帘的控制。
坐下来享受自动化窗帘!
本文转载自 知乎,转载已经授权。
原文链接:https://zhuanlan.zhihu.com/p/28401612