Голосовое управление освещением X10. Часть 5

Голосовое управление освещением X10 (см. Часть1, Часть2, Часть3, Часть4) и Голосовое оповещение для дома. Будильник в системе ROS являются частью умного дома на ROS.

Добавим в эту систему получение данных с сервера домашней метеостанции (здесь и добавление функционала).

При произнесении фразы «Погода» — компьютор должен голосом сообщить данные о температуре воздуха на улице, влажности воздуха и атмосферного давления. Сервер домашней метеостанции при обращении к нему по адресу в домашней сети (192.168.1.111:10001) отдает показания в формате JSON.

arduinometeo1-2.jpg

Сначала в проекте vp_x10_voice создадим дополнительный узел node_x10_alarm_weather_meteo1, который будет являться слушателем (subscriber) темы x10_alarm_weather, в тему публикуются данные std_msgs/Int16 — числовой аргумент (номер датчика ), узел обращается к серверу домашней метеостанции, расположенному   в сети, получает данные в формате JSON, выбирает данные для нужного датчика и формирует фразу (строку std_msgs/String). Далее фраза публикуется в тему x10_alarm_festival для произнесения фразы голосом (см. Голосовое оповещение для дома. Будильник в системе ROS).

Например мы произносим фразу «погода улица», узел node_x10_voicetotext распознает ее и отправляет сообщение в тему x10_alarm_weather, считываются данные по запросу к серверу домашней метеостанции и формируется фраза, например «Температура воздуха 17 градусов относительная влажность 60 процентов», фраза публикуется в тему x10_alarm_festival и программа festival произносит эту фразу голосом.

Меня интересуют данные
temp4 — температура на улице с датчика DH11
humidity4 —   влажность на улице с датчика DH11
pressure5 — атмосферное давление

Предусмотрим в программе этот момент (формирование фразы для festival для данных с разных датчиков). Пишем скрипт node_x10_weather_meteo1_sub.py

 #!/usr/bin/env python #-*-coding:utf-8 -*-  #  #  Слушатель x10_weather #  по запросу в тему x10_alarm_weather #  получение данных с сервера домашней метеостанции #  и отправка данных для голосового сообщения #  в тему x10_alarm_festival #  import roslib; roslib.load_manifest('vp_x10_voice') import rospy import subprocess import shlex import urllib2 import json  from std_msgs.msg import String from std_msgs.msg import Int16  URL_METEO="http://192.168.0.111:10001"  def controller(data):          number = data.data     pub1 = rospy.Publisher('x10_alarm_festival', String)     message=""          global temps     global humiditys     global pressures      res=urllib2.urlopen(URL_METEO).read()     data_sensors=json.loads(res)     if number==1 :        try:          temps=data_sensors['meteo']['temp1']          tt=int(float(temps)+0.5)          message="Температура воздуха "+str(tt)+"  градусов"        except ValueError:          message="Ошибка считывания с датчика температуры 1 "     elif number==2 :        try:          temps=data_sensors['meteo']['temp2']          tt=int(float(temps)+0.5)          message="Температура воздуха "+str(tt)+"  градусов"        except ValueError:          message="Ошибка считывания с датчика температуры 2 "     elif number==3 :        try:          temps=data_sensors['meteo']['temp3']          tt=int(float(temps)+0.5)          message="Температура воздуха "+str(tt)+"  градусов"        except ValueError:          message="Ошибка считывания с датчика температуры 3 "     elif number==4 :        try:          temps=data_sensors['meteo']['temp4']          humiditys=data_sensors['meteo']['humidity4']          tt=int(float(temps)+0.5)          dd=int(float(humiditys)+0.5)          message="Температура воздуха "+str(tt)+" градусов"          message+=" относительная влажность  "+str(dd)+" процентов"        except ValueError:          message="Ошибка считывания с датчиков 4 "     elif number==5 :        try:          temps=data_sensors['meteo']['temp5']          pressures=data_sensors['meteo']['pressure5']          tt=int(float(temps)+0.5)          pp=int(float(pressures)+0.5)          message="Температура воздуха "+str(tt)+" градусов"          message+=" давление  "+str(dd)+" миллиметров ртутного столба"        except ValueError:          message="Ошибка считывания с датчиков 5 "     elif number==99 : #запрос по голосу Погода         try:          temps=data_sensors['meteo']['temp5']          pressures=data_sensors['meteo']['pressure5']          humiditys=data_sensors['meteo']['humidity4']          tt=int(float(temps)+0.5)          dd=int(float(humiditys)+0.5)          pp=int(float(pressures)+0.5)          message="Температура воздуха "+str(tt)+" градусов"          message+=" относительная влажность  "+str(dd)+" процентов"          message+=" давление  "+str(dd)+" миллиметров ртутного столба"        except ValueError:          message="Ошибка считывания с датчиков "     #temps=[meteo1['temp3'] for meteo1 in data_sensors['meteo']]     rospy.loginfo(temps)     pub1.publish(message)         def listener():    rospy.init_node('node_x10_alarm_weather_meteo1')    sub = rospy.Subscriber("x10_alarm_weather",Int16,controller)    rospy.spin()   if __name__ == '__main__':    listener()    

Теперь необходимо добавить в скрипт node_x10_voicetotext.py распознование фразы «погода» и отправка сообщения ( std_msgs/Int16 =99)  в тему x10_alarm_weather. 

Измененный скрипт node_x10_voicetotext.py:

 #!/usr/bin/env python #-*-coding:utf-8 -*- import roslib; roslib.load_manifest('vp_x10_voice') import rospy import subprocess import shlex  from std_msgs.msg import String from std_msgs.msg import Int16  fraza=["люстра","лента","лампа","ночник","елка",        "люстра включить","лента гори","лампа включить","ночник включить","елка гори",        "отбой",        "программа 1","программа 2","программа 3","программа 4","программа 5",        "погода"]  matrix = [["люстра","быстро"],           ["лента"],           ["лампа","лапа"],           ["ночник","начни"],           ["елка","елочка"],           ["люстра включить","люстра ключи","быстро включить"],           ["лента гори","mp3"],           ["лампа включить","лампа включи","лампа ключи"],           ["ночник ключи","ночник включить","ночник включи","ночник горит","ночник гори"],           ["елка гори","елочка гори","елка горит"],           ["отбой","всем спать","я спать"],           ["программа 1","драма 1"],           ["программа 2","драма 2"],           ["программа 3","драма 3","программа тв"],           ["программа 4","драма 4"],           ["программа 5","драма 5"],           ["погода"]]   def talker():     pub1 = rospy.Publisher('x10_voicetotext', Int16)     pub2 = rospy.Publisher('x10_alarm_weather', Int16)     rospy.init_node('node_x10_voicetotext')      while not rospy.is_shutdown():       rospy.loginfo("ожидание записи с микрофона")       subprocess.Popen('rec -q -c 1 -r 16000 current.wav silence 1 0.2 3% 1 0.2 3%',shell=True,cwd = '/home/petin/ros_pkgs/vp_x10_voice/nodes/').communicate()             rospy.loginfo("wav - ok")        subprocess.Popen('flac -f -s current.wav -o current.flac',shell=True,cwd = '/home/petin/ros_pkgs/vp_x10_voice/nodes/').communicate()       rospy.loginfo("flac - ok")        proc3=subprocess.Popen('php textfromgoogle.php',shell=True, stdout =   subprocess.PIPE,cwd = '/home/petin/ros_pkgs/vp_x10_voice/nodes/')        result=proc3.communicate()[0]       str1 = "result api google = %s"%result       rospy.loginfo(str1)       str2=""       index=0       for ind,elements in enumerate(matrix):         for element in elements:           if result.count(element)>0:             str2=fraza[ind]             index=ind+1       if(index=17):               pub2.publish(99)         rospy.loginfo(str2)       elif(index>0):               pub1.publish(index)         rospy.loginfo(str2)        if __name__ == '__main__':     try:         talker()     except rospy.ROSInterruptException: pass 

Теперь при запуске дополнительного узла 

 $ rosrun vp_x10_voice node_x10_weather_meteo1_sub.py

и произнесении фразы «погода», компьютер выдает голосовое сообщение вида «Температура воздуха XX градусов относительная влажность YY процентов давление ZZZ миллиметров ртутного столба».

В прикрепленном файле архив с проектом vp_x10_voice для ROS.