Using text to speech to announce new emails on arrival home

I’ve done some more tinkering with bluetooth proximity detection and have succeeded in making my life slightly more like a science fiction film. When I arrive home, my computer uses text to speech to greet me and tell me if I’ve got any new emails. This reuses the code from last week to detect the presence of my phone via bluetooth, with the slight alteration of tracking what the previous state was. We only want to trigger the announcement when the phone returns to the room, not the whole time the phone is in the room.

Ruby has an IMAP object with methods to connect to, login and search mailboxes; I wrote a function using the IMAP methods to count unread emails and defined an array of all the email accounts I wanted checked. The main part of the script sits in an infinate loop waiting for the phone to leave then return; when it does, it just goes through each inbox in turn and constructs a message detailing any new emails. This message is then handed to the espeak-ruby gem to create a temporary mp3 file which is played using mpg321.

Each email account is defined at the top of the file; the name field is what gets read out and the server, user and pass fields are ronseal. The array can be as big or small as you like, you could even leave it entirely empty if you like being greeted by a disembodied voice repeatedly. Just below are options that allow the bluetooth address of the device, the initial greeting and the espeak voice to be configured. While there is a selection of different voices available, they all sound very synthetic; a more realistic sounding text to speech would be nice in the future, but espeak will do for now.

email_announcement.rb:

#You can enter as many or as few IMAP accounts as you like:
ACCOUNTS=[
  {
    'name'=>'personal',
    'server'=>'',
    'user'=>'',
    'pass'=>''
  },
  {
    'name'=>'uni',
    'server'=>'',
    'user'=>'',
    'pass'=>''
  },
  {
    'name'=>'tutoring',
    'server'=>'',
    'user'=>'',
    'pass'=>''
  }
]

#You`ll have to look this up manually by using the hcitool command
BLUETOOTH_ADDRESS='00:26:5F:C6:30:A3'
GREETING='Hello Mike.'
VOICE='en-uk'

require 'rubygems'
require 'espeak-ruby'
include ESpeak
require 'net/imap'

def isPresent(address)
  if (`hcitool name #{address}`=='')
    return false
  else
    return true
  end
end

def newemails(account)
  begin
    imap = Net::IMAP.new(account['server'], 993, true)
    imap.login(account['user'],account['pass'])
    imap.select('INBOX')
    mailcount= imap.search(['NOT','SEEN']).count
    imap.logout
    imap.disconnect
    return mailcount
  rescue SocketError
    puts 'Couldn\'t connect to server: '+account['server']
  rescue Net::IMAP::NoResponseError
    puts 'Login failed for user '+account['user']
  rescue
    puts 'Unknown error while checking '+account['name']
  end
  #If something went wrong, report no new emails
  return 0
end


previous_state=true
while true
  if isPresent(BLUETOOTH_ADDRESS)
    #if the phone wasn't here before but is now, it's just arrived back
    if !previous_state
      message=GREETING+' '
      ACCOUNTS.each do |account|
        mailcount=newemails(account)
        if mailcount==1
          message+='You have 1 new '+account['name']+' email. '
        elsif mailcount>1
          message+='You have '+mailcount.to_s+' new '+account['name']+' emails. '
        end
      end
      espeak('/tmp/message.mp3',:text=>message,:voice=>VOICE,:quiet=>true)
      system('mpg321 -q /tmp/message.mp3')
    end
    previous_state=true
  #double check it really is out of range
  elsif !isPresent(BLUETOOTH_ADDRESS)
    previous_state=false
  end
end

2 thoughts on “Using text to speech to announce new emails on arrival home

  1. Pingback: Pausing Banshee using bluetooth proximity | Products of Mike's Mind

Leave a Reply