基於Amazon Echo 和 Raspberry Pi 的自動窗帘控制
基於Amazon Echo 和 Raspberry Pi 的自動窗帘控制
本指南說明如何整合電動窗帘軌道,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 的水晶頭網線,http://www.ebay.co.uk/itm/190738599768?_trksid=p2057872.m2749.l2649&ssPageName;=STRK%3AMEBIDX%3AIT
- 一塊 Raspberry Pi 開發板
- 與Raspberry Pi GPIO整合所需的組件(我從Proto-Pic訂購),包括 Raspberry Pi GPIO 轉介面(2x13)、帶狀排線、3個型號為 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 GPIOnimport timenGPIO.setmode(GPIO.BCM)nopenPin=17nclosePin=25nstopPin=22nGPIO.setup(openPin, GPIO.OUT)nGPIO.setup(closePin, GPIO.OUT)nGPIO.setup(stopPin, GPIO.OUT)nntime.sleep(2)nnwhile (1==1) :n print "Openingn"n GPIO.output(openPin, GPIO.HIGH)n time.sleep(0.5)n GPIO.output(openPin, GPIO.LOW)nn time.sleep(2)nn print "Stoppingn"n GPIO.output(openPin, GPIO.HIGH)n time.sleep(0.5)n GPIO.output(openPin, GPIO.LOW)nn time.sleep(2)nn print "Stoppingn"n GPIO.output(stopPin, GPIO.HIGH)n time.sleep(0.5)n GPIO.output(stopPin, GPIO.LOW)nn time.sleep(2)nn print "Closingn"n GPIO.output(closePin, GPIO.HIGH)n time.sleep(0.5)n GPIO.output(closePin, GPIO.LOW)nn time.sleep(2)nn print "Stoppingn"n GPIO.output(stopPin, GPIO.HIGH)n time.sleep(0.5) n GPIO.output(stopPin, GPIO.LOW)nn time.sleep(2)n
步驟四:編寫 Amazon Skill 與 Raspberry Pi 進行通信
詢問Alexa
理想情況下,我們可以要求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://forums.developer.amazon.com/questions/8155/how-to-use-aws-lambda-as-a-proxy-for-non-ssl-serve.html
感謝 Matt !
步驟五:在 Raspberry Pi 上創建本地腳本並在路由器上實現埠轉發
在 Raspberry Pi 創建以下腳本:
from flask import Flasknnfrom flask_ask import Ask, statement, convert_errors import RPi.GPIO as GPIO import logging import timennGPIO.setmode(GPIO.BCM)nnopenPin=17nnclosePin=25nnstopPin=22nnGPIO.setup(openPin, GPIO.OUT)nnGPIO.setup(closePin, GPIO.OUT)nnGPIO.setup(stopPin, GPIO.OUT)nnapp = Flask(__name__) ask = Ask(app, /)nnapp.config[ASK_VERIFY_REQUESTS] = Falsennapp.config[ASK_APPLICATION_ID] = Unique amazon skill referencennlogging.getLogger("flask_ask").setLevel(logging.DEBUG)nnnndef openCurtains():nnprint Opening curtainsnnGPIO.output(openPin, GPIO.HIGH)nntime.sleep(0.5)nnGPIO.output(openPin, GPIO.LOW)nntime.sleep(5)nnGPIO.output(stopPin, GPIO.HIGH)nntime.sleep(0.5)nnGPIO.output(stopPin, GPIO.LOW)nnnndef closeCurtains():nnprint Closing curtainsnnGPIO.output(closePin, GPIO.HIGH)nntime.sleep(0.5)nnGPIO.output(closePin, GPIO.LOW)nntime.sleep(5)nnGPIO.output(stopPin, GPIO.HIGH)nntime.sleep(0.5)nnGPIO.output(stopPin, GPIO.LOW)nnnn@ask.intent(GPIOControlIntent, mapping={status: status})ndef gpio_control(status):nnif status in [open, yield]: openCurtains() return statement(Good morning Hart Household)nnif status in [close, shield]: closeCurtains() return statement(Good evening Hart Household)nnif __name__ == __main__: app.run(host=IP address of Pi, port=5000, debug=True)n
啟動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 的第六步:這裡有一些微妙的變化,如截圖所示。
意圖很簡單:
{nn"intents": [{nn"intent": "GPIOControlIntent",nn"slots": [{nn"name": "status",nn"type": "GPIO_CONTROL"nn}]nn}]nn}n
slots值包含兩種: open 和 close
調用更簡單:
GPIOControlIntent to {status}n
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); nvar URLParser = require(url);nnconsole.log(Loading proxy function);nnexports.handler = function (json, context)nn{nntry {nn// A list of URLs to call for each applicationIdnnvar handlers = { appId:url, your amazon app id:http://your router address:5000/ };nn// Look up the url to call based on the appIdnnvar url = handlers[json.session.application.applicationId];nnif (!url) { context.fail("No url found for application id"); }nnconsole.log(Trying url)nnconsole.log(url)nnvar parts = URLParser.parse(url);nnvar post_data = JSON.stringify(json);nn// An object of options to indicate where to post tonnvar post_options = { host: parts.hostname, port: (parts.port || 80), path: parts.path, method: POST, headers: { Content-Type: application/json, Content-Length: post_data.length } };nn// Initiate the request to the HTTP endpointnnconsole.log(post_options)nnvar req = http.request(post_options,function(res) {nnvar body = "";nn// Data may be chunkednnres.on(data, function(chunk) { body += chunk; });nnres.on(end, function() { // When data is done, finish the requestnncontext.succeed(JSON.parse(body)); }); });nnreq.on(error, function(e) { context.fail(problem with request: + e.message); });nn// Send the JSON data console.log(Sending data) req.write(post_data); req.end(); } catch (e) { context.fail("Exception: " + e); } };n
我還將高級配置中的超時增加到7秒 - 否則,在窗帘完成5秒的活動之前,Lambda代理將超時。
步驟八: 整合與集成
複製Lambda ID - 您需要將其粘貼到Amazon開發中,指示Amazon將請求引導到您的新Lambda代理,將其轉發到Raspberry Pi上 - 請參閱第1個屏幕截圖。
從亞馬遜開發者網站測試skill - 你應該看到第二個屏幕截圖的響應。
如果它不起作用,請檢查Lambda日誌的調用錯誤和Raspberry Pi腳本輸出的錯誤。
然後打開 Echo 的開發skill - 不要將其對外發送,否則您將失去對窗帘的控制。
坐下來享受自動化窗帘!
原文鏈接:https://www.wandianshenme.com/play/%E5%9F%BA%E4%BA%8E-amazon-echo-%E5%92%8C-raspberry-pi-%E7%9A%84%E8%87%AA%E5%8A%A8%E7%AA%97%E5%B8%98%E6%8E%A7%E5%88%B6/
推薦閱讀:
TAG:物联网 | 智能家居 | 树莓派RaspberryPi |