2016-04-08 55 views
-1

我需要運行2個循環,一個用於監聽語音命令,另一個用於保持連接到MQTT代理,並監聽/發佈到MQTT主題,發佈語音命令時發佈。問題是,我不確定設置這個最好的方法。我將如何將這些設置爲運行,MQTT等待語音命令執行功能/我將從哪裏開始研究解決方案?類?多線程?不確定從哪裏開始。同時運行2個循環來調用另一個函數?

另外 - 旁註 - 這種語音識別(pocketsphinx)是絕對可怕的。它可能會在5%的時間內開/關,每隔一段時間都會產生各種隨機響應。 Bonus bro點,如果你能指出我正確的方向來解決,通過使用更好的模塊或可能的編碼pocketsphinx更準確(我已經註冊了一個谷歌Cloud-Speech API密鑰,但尚未收到它) 。

下面的代碼

voice.py:

import pyaudio, os 
import mqttPublisher 
import speech_recognition as sr 

def mainfunction(source): 
    audio = r.listen(source) 
    user = r.recognize_sphinx(audio) 
    print(user) 
    if user == 'on': 
     mqttPublisher.led_on() 
    elif user == 'off': 
     mqttPublisher.led_off() 

if __name__ == '__main__': 
    r = sr.Recognizer() 
    with sr.Microphone() as source: 
     while 1: 
      mainfunction(source) 

mqttPublisher.py:

import paho.mqtt.client as mqtt 

def led_on(): 
    mqttc.publish("IoT/LED", payload="1") 
    print("LED is ON") 

def led_off(): 
    mqttc.publish("IoT/LED", payload="2") 
    print("LED is OFF") 

def get_status(): 
    mqttc.publish("IoT/LED", payload="3") 

def on_connect(client, userdata, flags, rc): 
    mqttc.publish("IoT/LED", "connected") 
    print("connected") 

def on_subscribe(client, userdata, mid, granted_qos): 
    mqttc.publish("IoT/LED", payload="3") 
    print("subscribed") 

def on_publish(client, userdata, mid): 
    print("message published") 

def on_message(client, userdata, message): 
    print("message printed to topic") 

def on_disconnect(client, userdata, rc): 
    print("Client Disconnected") 

mqttc = mqtt.Client() 
mqttc.on_connect = on_connect 
mqttc.on_subscribe = on_subscribe 
mqttc.on_message = on_message 
mqttc.on_publish = on_publish 
mqttc.on_disconnect = on_disconnect 

mqttc.connect("192.168.1.3", 1883) 
mqttc.subscribe("IoT/LED", 1) 

run = True 
while run: 
    mqttc.loop_start() 
+1

在單獨的線程上運行循環 – hardillb

+0

對我來說,協程就是你想要實現的。 – AndyG

回答

-1

每hardillb的建議下,我研究線程,發現一些問題,帶班解決問題。我常來我的解決方案的答案在這裏:

Running infinite loops using threads in python

Thread issue while subscribing to MQTT in Python using Paho MQTT

下面是完整的代碼是否按照預期工作。它啓動語音模塊和Mqtt客戶端,等待是/否(這是我可以讓語音模塊識別的唯一一致的詞語),並在接收到適當命令時打開/關閉Aruidno LED。對於那些有興趣的人,我也會包含Arduino代碼。 IP地址192.168.1.2指向我的Raspberry Pi,它正在運行一個Mosquitto代理來處理MQTT主題。

voice.py:

import pyaudio, os 
from mqttPublisher import MqttHandler 
import speech_recognition as sr 
from threading import Thread 

class Amy(Thread): 
    def mainfunction(self, source): 
     audio = self.r.listen(source) 
     user = self.r.recognize_sphinx(audio) 
     print(user) 
     if user == 'yes': 
      mqtt.led_on() 
     elif user == 'no': 
      mqtt.led_off() 
     elif user == 'get': 
      mqtt.get_status() 

    def __init__(self): 
     Thread.__init__(self) 
     self.daemon = True 
     self.start() 

    def run(self): 
     self.r = sr.Recognizer() 
     with sr.Microphone() as source: 
      while True: 
       self.mainfunction(source) 

amy = Amy() 
mqtt = MqttHandler() 

amy 
mqtt 

while True: 
    pass 

mqttPublisher.py:

import paho.mqtt.client as mqtt 
from threading import Thread 

class MqttHandler(Thread): 

    client = mqtt.Client() 

    def __init__(self): 
     Thread.__init__(self) 
     self.daemon = True 
     self.start() 

     self.client.on_connect = self.on_connect 
     self.client.on_subscribe = self.on_subscribe 
     self.client.on_message = self.on_message 
     self.client.on_publish = self.on_publish 
     self.client.on_disconnect = self.on_disconnect 
     self.client.led_on = self.led_on 
     self.client.led_off = self.led_off 
     self.client.get_status = self.get_status 

     self.client.connect("192.168.1.2", 1883) 
     self.client.subscribe("IoT/LED", 1) 

    def run(self): 
     while True: 
      self.client.loop() 

    def led_on(self): 
     self.client.publish("IoT/LED", payload="1") 
     print("LED is ON") 

    def led_off(self): 
     self.client.publish("IoT/LED", payload="2") 
     print("LED is OFF") 

    def get_status(self): 
     self.client.publish("IoT/LED", payload="3") 

    def on_connect(self, client, userdata, flags, rc): 
     self.client.publish("IoT/LED", "connected") 
     print("connected") 

    def on_subscribe(self, client, userdata, mid, granted_qos): 
     self.client.publish("IoT/LED", payload="3") 
     print("subscribed") 

    def on_publish(self, client, userdata, mid): 
     print("message published") 

    def on_message(self, client, userdata, message): 
     print("message printed to topic") 

    def on_disconnect(self, client, userdata, rc): 
     print("Client Disconnected") 

的Arduino代碼:

#include <PubSubClient.h> 
#include <Ethernet.h> 
#include <SPI.h> 

byte mac[] = {0xDE, 0xED, 0xBA, 0xFE, 0xFE, 0xEF }; 
byte ip[] = { 192, 168, 1, 6 }; 
byte localserver[] = { 192, 168, 1, 2 }; 

const char clientID[8] = "Arduino"; 
const char topicName[8] = "IoT/LED"; 
const char on[3] = "On"; 
const char off[4] = "Off"; 
const int led = 9; 

int status; 

EthernetClient ethClient; 
PubSubClient client(localserver, 1883, callback, ethClient); 

void callback(char* topic, byte* payload, unsigned int length) { 
    int load = atoi ((const char*) payload); 
    if (load != 0) { 
    Serial.print("\n"); 
    Serial.print("Payload= "); 
    Serial.println(load); 
    switch(load) { 
     case 1: 
     digitalWrite(led, HIGH); 
     client.publish(topicName, on); 
     Serial.print("Light turned on"); 
     break; 
     case 2: 
     digitalWrite(led, LOW); 
     client.publish(topicName, off); 
     Serial.print("Light turned off"); 
     break; 
     case 3: 
     status = digitalRead(led); 
     if (status == 0) { 
      client.publish(topicName, off); 
      Serial.print("Light status: "); 
      Serial.println(off); 
      break; 
     } 
     else if (status == 1) { 
      client.publish(topicName, on); 
      Serial.print("Light status: "); 
      Serial.println(on); 
      break; 
     } 
     default: 
     break; 
    } 
    } 
} 

void setup() { 
    Serial.begin(9600); 
    pinMode(led, OUTPUT); 
    Ethernet.begin(mac, ip); 

    if (!client.connected()) { 
    Serial. print("Trying to connect..."); 
    client.connect(clientID); 
    } 
    if (client.connected()) { 
    Serial.print("Connected"); 
    client.subscribe(topicName); 
    } 
} 

void loop() { 
    client.loop(); 
} 
1

paho.mqtt.client.loop_start()啓動一個線程來處理其網絡環路爲您服務。只需調用一次,你應該沒問題。

相關問題