Голосовое оповещение для дома. Будильник в системе ROS

В этих статьях — 1, 2, 3, 4 я рассматривал голосовое управление приборами X10 через ROS. Системой понемногу пользуюсь (иногда приходится забирать нетбук), привыкаю, немного изменяю. Теперь возникла необходимость добавить к данной системе будильник с голосовым оповещением. Также использую систему ROS, добавив в проект необходимые узлы.

Задача ставилась следующая — для каждой записи будильника установить:

  1.  время срабатывания
  2.  количество повторений срабатывания и интервал
  3.  дни недели для данного будильника
  4.  действия по срабатыванию будильника, пока такие:
  •    голосовое оповещение
  •    запуск короткого музыкального файла (рингтона)
  •    отправка команд для управления приборами x10

Скрипт node_x10_alarm_pub.py создает узел node_x10_alarm_events, который будет ожидать время срабатывания (либо повторного оповещения) будильников. Список будильников находится в двумерном массиве alarm_events

Для каждой записи, например

[«06:20″,3,5,[0,1,2,3,4],{1:»rington6.mp3;17»,2:»Подъём  пора на работу, вставай Виктор Александрович «,4:»12»}],

06:20 — время срабатывания

3 — количество повторений

5 мин — интервал между повторениями

дни недели (0-4 — понедельник — пятница)

действия

1 — публикация в тему x10_alarm_mediaplayer (имя звукового файла) для запуска медиапроигрывателя
2 — публикация в тему x10_alarm_festival голосовое сообщение (запуск программы festival)
3 — получение текущего времени и  публикация в тему x10_alarm_festival для голосового сообщения  (запуск программы festival)
4 — публикация в тему x10_voicetotext посылка команды для приборов x10 в тему 

Перед голосовым оповещением о текущем времени, время переводится в строковое сообщение а затем строка отправляется в тему x10_alarm_festival.

Запуск узла  node_x10_alarm_pub.py

 rosrun vp_x10_voice   node_x10_alarm_pub.py

Содержимое файла  node_x10_alarm_pub.py

 #!/usr/bin/env python #-*-coding:utf-8 -*-  #  #  Ожидание событий будильника #   #  и отправка команд в темы для #  x10, festival(голос), медиаплейер(музыка),x10 (свет x10) #  import roslib; roslib.load_manifest('vp_x10_voice') import rospy import subprocess import shlex import time from datetime import datetime, timedelta  from std_msgs.msg import String from std_msgs.msg import Int16   alarm_events=[    ["06:30",2,5,[0,1,2,3,4,5,6],{1:"rington2.mp3;23",2:"Надо прогулять Графа "}],    ["06:15",3,3,[0,1,2,3,4,5,6],{1:"rington6.mp3;17",2:"Подъём  пора на работу, вставай Виктор Александрович "},4:"12"],    ["9:20",500,1,[0,1,2,3,4,5,6],{1:"rington6.mp3;19",3:"Время "}],    ["18:30",2,5,[0,1,2,3,4,5,6],{1:"rington2.mp3;23",2:"Надо прогулять Графа "}],    ["23:00",2,5,[0,1,2,3,4,5,6],{1:"rington2.mp3;23",2:"Надо прогулять Графа "}],    ]; name_hours=[            [{1,21},"час"],            [{2,3,4,22,23},"часа"],            [{5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20},"часов"],           ] name_minutes=[            [{1,21,31,41,51},"минута"],            [{2,3,4,22,23,24,32,33,34,42,43,44,52,53,54},"минуты"],            [{5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,25,26,27,28,29,30,35,36,37,38,39,40,45,46,47,48,49,50,55,56,57,58,59},"минут"],           ]   def my_alarm():     pub1 = rospy.Publisher('x10_alarm_mediaplayer',String)     pub2 = rospy.Publisher('x10_alarm_festival', String)     rospy.init_node('node_x10_alarm_events')      d=datetime.today()             dh=d.hour;dm=d.minute;     while not rospy.is_shutdown():       d=datetime.today()       if(d.hour!=dh or d.minute!=dm):         for element in alarm_events:           for dt in range(element[1]):  # кол-во повторений element[1]             alarm_time=element[0]             dminutes=dt*element[2]      # промежуток повторения              dd=timedelta(minutes=dminutes)             d1=d-dd             if(d.hour<10):                this_time="0"+str(d.hour)             else:                this_time=str(d.hour)             if(d.minute<10):                this_time+=":0"+str(d.minute)             else:                this_time+=":"+str(d.minute)             #this_time=str(d.hour)+":"+str(d.minute)             cor_this_time=str(d1.hour)+":"+str(d1.minute)             #rospy.loginfo(this_time)             try:               element[3].index(d.weekday())                if (alarm_time==cor_this_time):                 rospy.loginfo("!!!!!!!!!!!!==="+alarm_time+"---"+this_time)                 for key in element[4]:                    if key==1:                      rington_file=element[4][key].split(";")[0];                      pub1.publish(rington_file)                      time.sleep(int(element[4][key].split(";")[1]))                      rospy.loginfo("program 1 ")                    elif key==2:                      pub2.publish(element[4][key])                      time.sleep(5)                      rospy.loginfo("program 2 ")                    elif key==3:                      for ho in name_hours:                        if d.hour in ho[0]:                          strtime1= str(d.hour)+" "+ho[1]                          break                      if d.minute>0:                        for mi in name_minutes:                          if d.minute in mi[0]:                             strtime2=" "+str(d.minute)+" "+mi[1]                             break                      strtime2=strtime2.replace("01","одна")                      strtime2=strtime2.replace("21","двадцать одна")                      strtime2=strtime2.replace("31","тридцать одна")                      strtime2=strtime2.replace("41","сорок одна")                      strtime2=strtime2.replace("51","пятьдесят одна")                      strtime2=strtime2.replace("02","две")                      strtime2=strtime2.replace("22","двадцать две")                      strtime2=strtime2.replace("32","тридцать две")                      strtime2=strtime2.replace("42","сорок две")                      strtime2=strtime2.replace("52","пятьдесят две")                      pub2.publish(element[4][key]+strtime1+strtime2)                      time.sleep(5)                      rospy.loginfo("program 3 ")                    elif key==4:                      pub4.publish(int(element[4][key]))                      time.sleep(1)                      rospy.loginfo("program 4 ")                    else:                      pass             except ValueError:               pass         dh=d.hour;dm=d.minute;       else:         time.sleep(10)                       if __name__ == '__main__':     try:         my_alarm()     except rospy.ROSInterruptException: pass

Теперь создаем два узла subscriber — получателей сообщений из тем x10_alarm_festival и x10_alarm_mediaplayer.

Узел node_x10_alarm_mediaplayer получает сообщение String из темы nx10_alarm_mediaplayer и запускает программу проигрывания звуковых файлов. Я запускаю программу smplayer, можно любой проигрыватель.

Содержимое файла node_x10_mediaplayer_sub.py

 #!/usr/bin/env python #-*-coding:utf-8 -*-  #  #  Слушатель x10_mediaplayer #   #  и запуск медиапроигрывателя #   #  import roslib; roslib.load_manifest('vp_x10_voice') import rospy import subprocess import shlex  from std_msgs.msg import String  PATH_RINGTONS="ros_pkgs/vp_x10_voice/nodes/ringtons/"  def controller(data):      rington_file = data.data     command1='smplayer "'     command1+=PATH_RINGTONS+rington_file+'"'     subprocess.Popen(command1,shell=True).communicate()     rospy.loginfo(command1)             def listener():    rospy.init_node('node_x10_alarm_mediaplayer')    sub = rospy.Subscriber("x10_alarm_mediaplayer",String,controller)    rospy.spin()   if __name__ == '__main__':    listener()    

Узел node_x10_alarm_festival получает сообщение String из темы x10_alarm_festival и запускает программу festival. 

Содержимое файла node_x10_festival_sub.py

 #!/usr/bin/env python #-*-coding:utf-8 -*-  #  #  Слушатель x10_festival #   #  и произношение голосом #    import roslib; roslib.load_manifest('vp_x10_voice') import rospy import subprocess import shlex  from std_msgs.msg import String  def controller(data):      fraza = data.data     #command1="festival -b '(begin (SayText "     #command1+='"'+fraza+'"'     #command1+="))'"     command1='echo "'     command1+=fraza+'"'     command1+=" | festival --language russian --tts"     subprocess.Popen(command1,shell=True).communicate()     rospy.loginfo(command1)         def listener():    rospy.init_node('node_x10_alarm_festival')    sub = rospy.Subscriber("x10_alarm_festival",String,controller)    rospy.spin()   if __name__ == '__main__':    listener()

Для управления приборами X10 запускаем узел node_x10_texttocommand

 rosrun vp_x10_voice node_x10_texttocommand.py

и посылаем в него номер сценария из массива arr_commands файла node_x10_texttocommand.py (см. проект здесь)

Составляем список пробных будильников

Запускаем

1 терминал

 roscore

2 терминал

 rosrun vp_x10_voice   node_x10_alarm_pub.py

3 терминал

 rosrun vp_x10_voice node_x10_festival_sub.py

4 терминал

 rosrun vp_x10_voice node_x10_mediaplayer_sub.py

5 терминал

 rosrun vp_x10_voice node_x10_texttocommand.py

Файлы проекта можно скачать в репозитории — скачать