Tuesday, May 28, 2013

Speech Recognition of Numbers for Timed Events

One of the knocks against using speech recognition for home automation is that you could have used a different method, like a touchscreen or remote, for more efficient control. However, timed events are one of those use cases that I find better with voice control. Let's say I want to turn on a light for 20 minutes. With a GUI, I have to select the light and then select a mode (delayed - turn on after X seconds, interval - turn on for X minutes then turn off). To select the delay/duration, I would need some sliders, text boxes to type the time or maybe a drop down list of predefined times. If I want to schedule with days or dates, then I would need a date picker/calendar as well. Or, I could just say "At 6PM on Sunday, turn on the porch light for 15 minutes."

Continuing with my recent experiments with Android speech recognition, I began adding timed events. One advantage of a free form speech recognition engine like Google's, is the ability to recognize any number that's spoken. You're not limited to a set of predefined options, like with Homeseer:
<1|2|3|4|5|6|7|8|9|10|11|12|13|14|15|16|17|18|19|20|30|40|50|60|70|80|90> <seconds|second|minutes|minute|hours|hour|days|day>
Kind of a nitpick, but what if you want 25 minutes? Can't do it, but Google will recognize whatever you say, whether it's 3 fortnights or 2,567 seconds. It may not be necessary, but it gives you the flexibility to do whatever you want. It's up to your software to parse out the numbers and units. With Python, it's simple to recognize the sentence for a particular pattern and extract the necessary parameters. Tthe following code shows how to extract information for basic delayed/duration type of events.
regex_delay = re.compile('[^\s+]*(in|for|after)\s+(\d+)\s+(day|hour|minute|second)[s]*')
if regex_delay.search(msg):
  delay_parm = re.findall(regex_delay, msg)
delay_parm will now contain a list of groups. If your command is "turn off the garage light after 15 seconds", you'll get this:
delay_parm = [('after', '15', 'second')]
delay_parm[0][0] = after  # delay type
delay_parm[0][1] = 15     # delay value
delay_parm[0][2] = second # delay unit
Now you have all the information you need to perform the action:
# convert to common unit, seconds
if delay_parm[0][2] == "day":
  delay_time = int(delay_parm[0][1]) * 60 * 60 * 24
elif delay_parm[0][2] == "hour":
  delay_time = int(delay_parm[0][1]) * 60 * 60
elif delay_parm[0][1] == "minute":
  delay_time = int(delay_parm[0][1]) * 60
else:
  delay_time = int(delay_parm[0][1])

if delay_parm[0] == "for":
  do_something_for(delay_time)
else:
  do_something_delayed(delay_time)
Scheduling an event based on a day ("next Tuesday"), a time ("at 3PM") or date ("December 31, 2014") is just an extension of this. Take a look at this demo where I'm showing a time based reminder and a delayed lighting event.


No comments:

Post a Comment