當 Alexa 遇上 ESP8266 (一)
https://www.birdandgua.net/bird/2017/12/when_alexa_meets_esp8266-1/

去年的 AWS 的 re:Invent 上,我見識了 Alexa Voice service 的本事後深受震撼,我除了帶了幾顆 Echo 和 Echo Dot 回來研究外,也想著要用 ESP8266 來做可以讓 Alexa 控制的裝置。
其實回來之後沒多久我就做出來了,但這篇文章一直沒寫。等到我想寫文章、把寫好的程式再度拿出來看時,發現我所使用的 library 已經大幅更新,我原來寫的程式根本沒辦法 compile,只好整個砍掉重練。
時隔一年,這幾天正值 re:Invent 2017 進行中。今年因為種種因素我無法成行,就用這篇文章來紀念去年此時的這個 idea 和那時的熱血吧。
偽裝
要做一個讓 Alexa 可以控制的裝置有很多方法,但大部份的方法都要用到 AWS 的 IoT 或 serverless 服務,至少要寫一點 Lamda script 去處理 Alexa 跟裝置間的互動,或者要走 MQTT 透過 IFTTT 之類的服務來運作。一但用了 backend server 的服務,被控裝置的安裝就要處理註冊和認證等問題,操作上會變得很麻煩。
尋尋覓覓後,我發現有另一種更聰明的做法: 偽裝。
Alexa 支援一系列的智慧插座,可以用 Alexa 控制插座電源的開或關,而這其中最有名的就是 Belkin 出的 Wemo Switch。Wemo Switch 必需跟執行 Alexa 的 Echo 或 Echo Dot 位在同一個 WiFi 網路之下才能運作,因此就有人推測它們倆可能是在 LAN 上直接溝通,而不經過雲上的 server。
有一位很有名的 maker,Chris Derossi,利用 Wireshark這個老牌的 network sniffer 監聽 Echo 跟 Wemo Switch 之間的通訊後,解開了這個謎。Echo 跟 Wemo Switch 都沒有 Ethernet 接口,因此只能用 WiFi sniffer 來監聽。這張圖發表在他原來的部落格文章 Amazon Echo and Home Automation 中:

原來 Echo 跟 Wemo Switch 之間是這麼運作的:
- 當使用者第一次設定 Wemo Switch 時,要先對 Echo 喊 “Alexa, descover devices”。此時 Echo 會利用 UDP broadcast 送出一個 UPnP 的 SSDP 請求,SSDP 是 UPnP 控制器用來在網路上尋找裝置用的協定,它是一個 HTTP request,帶有一種叫 M-SEARCH 的 method,只有 header 沒有 body,送往 IPv4 的 multicast 地址 239.255.255.250:1900。
- 同一個網路上的 Wemo Switch 都聽得到 IP multicast。它們發現這個 HTTP request 是在叫自己後,就會回傳一個 HTTP response 給發出 IP multicast 的 Echo,裡面最重要的訊息是一個 URL。這個 URL 指向一個 XML 檔,用來描述裝置本身的屬性。這時的回覆會來自網路上的多個裝置,因為每個收到 IP multicast 的 Wemo switch 都會回答,所以網路會有一小段時間變得很吵。以上都還是走 UDP,所以不需建立連線。
- Echo 收到這些回覆的 URL 後,依序對每個裝置發出 HTTP request,讀取每個裝置的 XML 配置檔。這時的協定通訊協定改走 TCP,會先建立連線,傳送的資料也會變得可靠。
- 每個裝置用 HTTP response 回覆它們的設定檔,也是走 TCP。這個設定檔很長,是一個一百多行的 XML 檔,但其中只有一欄比較重要,就是這個裝置的 friendly name。Friendly name 就是我們幫每一個 Wemo Switch 取的名字,當我們要用 Alexa 的語音服務控制它時,叫的就是這個名字。
- 設定完成後,我們會在 Alexa 的 app 中看到它已經找到的裝置列表,此時就可以用語音控制每個 Wemo Switch 的開或關。
- 當使用者喊出語音指令且 Alexa 聽懂後,它會送出一個 HTTP request 給對應的裝置,裡面有一大串有的沒有的資料,甚至包含了整組包在 XML 裡的 SOAP 指令,但其實我們真正關心的就只是 <BinaryState> 這個 tag 而已,而這個 tag 只有 1 跟 0 兩個值。
- Wemo Switch 收到指令並確認動作後,會回應一個 HTTP response,這是一個固定內容的 acknowledgement。
- Echo 收到確認的回覆後,才會講 “OK”。
Chris Derossi 隨後在另一篇 post 中發佈了一支 Python 程式,用來模擬 Wemo Switch 並回應來自 Alexa 的這些訊息。這支程式叫 fauxmo,有點向 Wemo 致敬的味道。
當 Alexa 遇上 ESP8266 (一)的更多相关文章
- MVC遇上bootstrap后的ajax表单模型验证
MVC遇上bootstrap后的ajax表单验证 使用bootstrap后他由他自带的样式has-error,想要使用它就会比较麻烦,往常使用jqueyr.validate的话只有使用他自己的样式了, ...
- 敏捷遇上UML-需求分析及软件设计最佳实践(郑州站 2014-6-7)
邀请函: 尊敬的阁下:我们将在郑州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实 ...
- 敏捷遇上UML—软创基地马年大会(广州站 2014-4-19)
我们将在广州为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战技巧. 时间:2 ...
- 敏捷遇上UML——软创基地马年大会(深圳站 2014-3-15)
邀请函: 尊敬的阁下: 我们将在深圳为您奉献高端知识大餐,当敏捷遇上UML,会发生怎样的化学作用呢?首席专家张老师将会为您分享需求分析及软件设计方面的最佳实践,帮助您掌握敏捷.UML及两者相结合的实战 ...
- 初识genymotion安装遇上的VirtualBox问题
想必做过Android开发的都讨厌那慢如蜗牛的 eclipse原生Android模拟器吧! 光是启动这个模拟器都得花上两三分钟,慢慢的用起来手机来调试,但那毕竟不是长久之计,也确实不方便,后来知道了g ...
- SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败解决方案
SQL SERVER 2008 R2 SP1更新时,遇上共享功能更新失败的问题,可作如下尝试: 更新失败后,在windows的[事件查看器→应用程序]中找到来源为MsiInstaller,事件ID为1 ...
- 当创业遇上O2O,新一批死亡名单,看完震惊了!
当创业遇上O2O,故事就开始了,总投入1.6亿.半年开7家便利店.会员猛增至10万……2015半年过去后,很多故事在后面变成了一场创业“事故”,是模式错误还是烧钱过度?这些项目的失败能给国内创业者带来 ...
- LoadRunner - 当DiscuzNT遇上了Loadrunner(下) (转发)
当DiscuzNT遇上了Loadrunner(下) 在之前的两篇文章中,基本上介绍了如何录制脚本和生成并发用户,同时还对测试报告中的几个图表做了简单的说明.今天这篇文章做为这个系列的最后一篇,将会介绍 ...
- LoadRunner - 当DiscuzNT遇上了Loadrunner(中) (转发)
当DiscuzNT遇上了Loadrunner(中) 在上文中,介绍了如果录制脚本和设置脚本执行次数.如果经过调试脚本能够正常工作的话,就可以设置并发用户数并进行压力测试了. 首先我们通过脚本编辑界面上 ...
随机推荐
- HTML float 和 absolute
block元素和inline元素在文档流中的排列方式: block元素通常被现实为独立的一块,独占一行,多个block元素会各自新起一行,默认block元素宽度自动填满其父元素宽度.block元素可以 ...
- JS对全角与半角的验证,相互转化以及介绍
1.什么是全角和半角? 全角:是一种电脑字符,是指一个全角字符占用两个标准字符(或两个半角字符)的位置.全角占两个字节. 汉字字符和规定了全角的英文字符及国标GB2312-80中的图形符号和特殊字符都 ...
- C# 8.0的三个值得关注的新特性
本文翻译自:https://dzone.com/articles/3-new-c-8-features-we-are-excited-about 转载请注明出自:葡萄城官网,葡萄城为开发者提供专业的开 ...
- HTML5 & CSS3初学者指南(4) – Canvas使用
介绍 传统的HTML主要用于文本的创建,可以通过<img>标签插入图像,动画的实现则需要第三方插件.在这方面,传统的HTML极其缺乏满足现代网页多媒体需求的能力.HTML5的到来,带来了新 ...
- CSS的继承和使用方式
CSS的继承 css的继承指的是当标签具有嵌套关系时,内部标签自动拥有外部标签的不冲突的样式的性质. 在Css中有些属性不允许继承,例如,border属性没有继承性.多边框类的属性都没有继承 ,例如, ...
- 【linux】Can't connect to local MySQL server through socket和Plugin 'auth_socket' is not loaded报错
真的是一次吐血的经历,弄了两个多小时才弄好. 问题1:直接登陆root用户报错 ERROR 2002 (HY000): Can't connect to local MySQL server thro ...
- wap2app(八)-- iphoneX 底部导航的兼容问题
iphoneX 没有home键,用其打开应用时,iphoneX的底部和应用底部导航重叠,不兼容. 解决办法: 打开manifest.json文件,在“plus”下加入以下代码(安全区域): " ...
- (三)版本控制管理器之CVS(下)
在上一篇文章<(二)版本控制管理器之CVS(上)>中,我为大家介绍了什么是CVS.CVS的特点.CVS的安装.CVSNT服务器的配置.TortoiseCVS客户端的配置等,本篇文章继续为大 ...
- JavaScript中,JSON格式的字符串与JSON格式的对象相互转化
前言:JSON是一个独立于任何语言的数据格式,因此,严格来说,没有“JSON对象”和“JSON字符串”这个说法(然而”菜鸟教程“和”W3school“使用了“JSON对象”和“JSON字符串”这个说法 ...
- linux富规则的案例
使用firewall-cmd添加富规则: 1.拒绝来自public区域中ip地址为192.168.0.11的所有流量 firewall-cmd --permanent --zone=public -- ...