我正在尝试建立一种通过Raspberry Pi控制音乐可视化程序的Alexa技能,但是我为使Alexa与Pi进行通信的最后一步而苦苦挣扎。对于服务器,我正在使用Flask Ask。大多数教程建议为Alexa终结点使用ngrok或等效服务,但是ngrok会生成随机子域,并且我无法使用任何替代方法,因此我使用noip.com。我有一个子域,我将其称为subdomain.ddns.net
,并且将端口443(https)转发到Raspberry Pi上的端口5000。我已经将http://subdomain.ddns.net
设置为我的Alexa技能的端点,并且已经使用Amazon's instructions生成了SSL证书。
我的Flask服务器(但不是我的本地网络或Raspberry Pi)似乎正在忽略或未接收到来自Alexa服务器的请求。当我尝试触发自己的技能意图时,Alexa会给我响应“我无法达到所要求的技能”,并且Flask服务器控制台不会产生任何输出。但是:
https://subdomain.ddns.net/
,则Flask会向控制台生成输出:192.168.1.1 - - [02/May/2020 19:10:48] "GET / HTTP/1.1" 405 -
https://subdomain.ddns.net/
,我仍然会收到输出:<device IP> - - [02/May/2020 19:12:02] "GET / HTTP/1.1" 405 -
nc -l 5000
,然后将我的技能命令发送给Alexa,我得到了一些(加密的)打印有嵌入字符串subdomain.ddns.net
的数据,这表明来自Amazon 的请求已成功发送到端口5000上的Raspberry Pi。因此subdomain.ddns.net
和端口转发似乎正常运行,并且来自Amazon的某些消息正在通过,但是Flask服务器没有接好它。我尝试使用打印语句将before_request
挂钩添加到我的Flask应用程序中,但从未触发。这是我第一次使用Flask,所以我对它的任何细节都不熟悉。我可能会遇到一个常见的陷阱吗? (我已经将host = "0.0.0.0"
设置为app.run()
的参数,我读过,如果不这样做,则只能使用本地主机连接。)任何人都可以建议一种调试方法这个吗?
(我已经删除了可视化应用程序专用的部分。)
from flask import Flask
from flask_ask import Ask, request, session, question, statement
import numpy
import soco
import sounddevice
import os
import subprocess
import threading
import time
import wave
...
app = Flask(__name__)
ask = Ask(app, "/")
@ask.launch
def launch():
print("Received launch intent")
speech_text = "Visualizer server online."
return question(speech_text).reprompt(speech_text).simple_card(speech_text)
@ask.intent("start")
def start_intent(status, room):
print("Received start intent")
...
return statement("Starting the visualizer.")
@ask.intent("stop")
def stop_intent(status, room):
print("Received stop intent")
...
return statement("Stopping the visualizer.")
@ask.intent("restart")
def restart_intent(status, room):
print("Received restart intent")
def run():
time.sleep(3)
os.system("reboot now")
threading.Thread(target = run)
return statement("Restarting the visualizer server.")
@ask.intent("AMAZON.HelpIntent")
def help_intent():
print("Received help intent")
speech_text = "Commands are start, stop, and restart."
return question(speech_text).reprompt(speech_text).simple_card("HelloWorld", speech_text)
@ask.session_ended
def session_ended():
return ("{}", 200)
...
if __name__ == "__main__":
if "ASK_VERIFY_REQUESTS" in os.environ:
verify = str(os.environ.get("ASK_VERIFY_REQUESTS", "")).lower()
if verify == "false":
app.config["ASK_VERIFY_REQUESTS"] = False
app.run(host = "0.0.0.0", ssl_context = ("certificate.pem", "private-key.pem"))