Needs-Help Button using Arduino and Freeswitch

This is a project for my grandmother, who turned 100 this year. Yes, really! Unfortunately, Grandma has been having some health problems of late. You know, as you do when you’re a 100!   Thankfully she’s home from the hospital and doing well.  While my folks live with her and generally have someone with her all the time. Sometimes they need to do some work outside, like mow the lawn or go grocery shopping while they are the ones on duty, so to speak.   I thought, wouldn’t it be great if there was a super easy way for her to let someone know that she needs help if she is by herself momentarily.   Something like this might afford my parents a bit more freedom and piece of mind. Enter, the Needs-Help Button!  Name subject to change until a better one emerges.  Suggestions welcome!  It’s using a key fob single button remote transmitter and momentary receiver from Adafruit.   These are connected to an Arduino Micro that sends a character string to it’s USB serial port.  A Python daemon listens to the serial port on the Alix board computer running Voyage Linux and everyone’s favorite Open Source PBX/soft-switch, Freeswitch.   Here it is in action:

Ideally, I think it should cycle through a list of numbers, first starting with some internal extensions at the house.    The call recipients can cancel the cycle by acknowledging the call for help by pressing star-9.

IMG_0082

I had considered doing this on a Raspberry Pi but I had read about a maximum uptime issue with it.   Maybe it’s not a problem anymore but as you can imagine I wanted a pretty solid platform for this.  In the future I could also see this system being used for VOIP calls to the “old country” so it will be nice to pick up a $10 license for the G.729 codec.  Unfortunately they only offer x86 and x86_64 architectures….not ARM yet.

 

Intercom system using Freeswitch and Arduino

Recently I was asked if I could install a new intercom system to a building that had recently been converted for apartment dwelling.   After looking around for one that fit the clients needs, I realized I could build one that was less expensive and extremely functional with technology that I know pretty well.  I love it when I can get crossover from my maker life into my work life!    I knew I could get Freeswitch to fire off a shell script using DTMF tones.    The bind_meta_app handles this for us.  Here’s the line in my dial plan that listens for DTMF.

<action application="bind_meta_app" data="9 b i transfer::-bleg open_sesame XML features"/>

Visitors dial a two digit apartment number.  This rings the tenant’s cell phone using a VOIP service.  Call recipients press star 9 to trigger the Arduino to trip the relay which sends current to the door strike.  Mind you that the ‘b’ after the 9  (for b-leg) means only the call recipients can trigger the relay. We can’t have people letting themselves in!

Then in features.xml:

<extension name="open_sesame">
       <condition field"destination_number" expression="^open_sesame$">
       <action application="answer"/>
       <action application="playback" data="voicemail/door_opening.wav"/>
       <action application="event" data="${system(/bin/echo -n YOURSTRINGHERE  >> /dev/ttyACM0)}"/>
       <action application="hangup"/>
       </condition>
</extension>

This echos a string to the serial port on the Arduino. Code on the Arduino listens for certain strings that can trigger any number of 4 relays. The -n switch means no return character, which is a different ascii code we don’t want to hear. The lovely voice tells the call recipient that the door is opening. I love devices that tell you what they’re doing…so friendly!

In my Arduino sketches I have a habit of adding in a couple of LED blinks to the setup function so that I know if it has been reset by power loss or whatnot. It turns out that helped me figure out that I had landed in a huge pile of whatnot.  If you echo strings directly to the serial port of an older pre-Leonardo Arduino, you tickle the hardware reset and it reboots.    Normally that would be used by the Arduino software to reset the board after you’ve uploaded your new sketch.  After much chin scratching and googleing I learned a 47K Ohm resistor between the 3v and ground pins disables this.

I was shopping for vandal proof outdoor telephones and realized…hey there’s no shortage of those on Ebay. And they cost 1/3rd of a traditional vandal proof speaker-phone with dial pad! Thanks to Ian Hendrickson-Smith for the inspiration on bottom artwork. ;)  The client _loves_ the payphone.  The building actually has Keith Haring murals all throughout, so it kinda fits vibe of the place.

IMG_0016 IMG_0017-2

 

It turns out this was a ‘smart’ payphone that a certain company was not able to remotely program for me.  Not only did I need it to make free calls but I needed it to be able to make 2 digit calls instead of the usually 10 or 11 digit dialing that they are programmed for in the field.    In the end I just purchased a replacement phone board from said company, one that is used in converting payphones for home use.    At first it worked better as an AM radio that is until I discovered ferrite cores for filtering out these signals.    Also their keypad didn’t fit my upper housing so I ended up having to figure out how to make my current keypad fit their phone board.  Once I got my keypad apart I could see how the matrix worked.  I think they must have just invented circuit board ‘via’s and were trying to incorporate them wherever they could!  It was the 80’s.  On the phone board side I could clearly see the traces to the DTMF chip.  After a bit of googleing I found the data sheet on that.  I matched up the corresponding rows and columns and was good to go.

IMG_0019-2 IMG_0022 IMG_0034-2

 

The Freeswitch software is running on an Alix board, a low power embedded x86 platform normally used for wifi access points. It has an 500Mhz AMD Geode processor and 256Mb ram and it handles Freeswitch without issue.   My dialplan only allows calls from the front door so I can rest assured that it will only be making one call at a time.   No worries on unexpected load.

Alix board, Arduino UNO with Seeed Studio Relay Shield, Grandstream ATA and AC Power.

Alix 3D2 board, Arduino UNO with Seeed Studio Relay Shield, Grandstream ATA and AC Power.

 

The client maintains a Google Doc spreadsheet which has apartment numbers and corresponding cell numbers.  I have written a bash script that runs on the device daily.  It scrapes the Google Doc in CSV format and rebuilds the dialplan based on this information.  This seemed preferable to running a LAMP interface on the low-power device.   Here’s the script if you want to use it.

Thanks for reading!

 

Protecting a physically exposed extension with Freeswitch

Sometimes you want or need an extension in a public place that needs to block outgoing calls some of the time. For instance one client has a fax machine that also has a handset built into the unit. There’s no way to disable the handset unless you use a super cumbersome locking mechanism built into the firmware. One approach might be to use a secret dialing prefix for this one extension. However, dialed numbers appear on the fax confirmation printouts so a simple dialplan_prefix-as_access_code might not stay secret for very long. My solution was to have a secret extension that the user dials before sending. This flips a bit and allows one call to be made. After the call is made the bit is flipped back. Freeswitch custom variables are destroyed after a call has ended so we cannot pass on our bit with the dialplan alone. We need a little help. If you’re already using mysql or postgres you might consider storing it there. I was not in this camp so I just opted for a file.

<extension name="enable a fax out" >
    <condition field="destination_number" expression="^(6789)$">
       <action application="answer"/>
        <action application="sleep" data="500"/>
        <action application="playback" data="ivr/ivr-you_may.wav"/>
        <action application="playback" data="ivr/ivr-send_fax_now.wav"/>
        <action application="set" data="${system(/bin/echo 1 > /var/fax/faxsetting)} "/>
        <action application="set" data="faxout_status=${system(/bin/cat   /var/fax/faxsetting)} "/>
        <action application="sleep" data="1000"/>
        <action application="log" data="point1 Faxout status set to [${destination_number}] , ${faxout_status}"/>
        <action application="playback" data="voicemail/vm-goodbye.wav"/>
        <action application="sleep" data="550"/>
        <action application="hangup"/>
    </condition>
</extension>

After you’ve dialed the obscure extension number, you’re allowed one outgoing call from extension 1016. We’ve set our bit to 1.

<extension name="faxout route  route, x1016">
     <condition field="caller_id_number" expression="^(1016)$" require-nested="true"/>
     <condition field="destination_number" expression="^91(1{0,1}\d{10})$">
          <action application="set" data="faxout_status=${system(/bin/cat /var/fax/faxsetting)} "/>
          <action application="log" data="point2, faxout status set to ${faxout_status}"/>
          <action application="set" data="my_dest=${destination_number:2}"/>
          <action application="log" data="my_dest is set to ${my_dest}"/>
          <action application="execute_extension" data="1016_${faxout_status}"/>
     </condition>
</extension>

Here we’ve put our bit from the file into a variable and route accordingly.

If it’s set to 1 we route here:

<extension name="1016_1" >
      <condition field="destination_number" expression="^(1016_1)$">
           <action application="set" data="${system(/bin/echo 0 > /var/fax/faxsetting)} "/>
           <action application="export" data="suppress_cng=true"/>
           <action application="set" data="sip_h_X-accountcode=${accountcode}"/>
           <action application="set" data="sip_h_X-Tag="/>
           <action application="set" data="call_direction=outbound"/>
           <action application="set" data="hangup_after_bridge=true"/>
           <action application="set" data="effective_caller_id_number=YOURCALLERIDHERE"/>
           <action application="set" data="inherit_codec=true"/>
           <action application="set" data="continue_on_fail=true"/>
           <action application="log" data="my_dest is set to ${my_dest}"/>
           <action application="bridge" data="sofia/gateway/flowroute/1${my_dest}"/>
        </condition>
</extension>

If not then send them here:

<extension name="1016_0" >
      <condition field="destination_number" expression="^(1016_0)$">
           <action application="answer"/>
           <action application="sleep" data="500"/>
           <action application="playback" data="ivr/ivr-not_have_permission.wav"/>
           <action application="playback" data="voicemail/vm-goodbye.wav"/>
           <action application="sleep" data="550"/>
           <action application="hangup"/>
      </condition>
</extension>

bub-bye!

If you have another way to handle this situation, or have any improvements feel free to comment!

Thanks!