So, it’s been 4 months since I originally posted about my new phone system (see here if you haven’t read it). It’s been running this whole time, and pretty much perfectly. I thought I’d take this time to talk about how many telemarketers I’ve stopped, how much money I’ve saved, and some more detail on how it’s built.
I’ve received 263 calls in the last 4 months. That’s an average of 16 calls a week or about 2 calls a day. Now, of course, it isn’t that perfect. The highest is 10 calls in a single day. So, not huge, but respectable for a 2-person house with no children.
Since I set it up to automatically route known people in, and send the rest to voicemail, I can get a more detailed breakdown. Of the 263 calls, 127 of them were people I knew, but 136 (51%) were sent to voicemail. The 136 were from 57 unique phone numbers, of which only 22 actually left voicemail. That means that 114 calls were people (or machines) who had nothing important to say, and that I didn’t have to listen to. That’s a pretty good time wastage reduction to me.
There are basically 3 “monthly” costs to this system. The VOIP provider, the Telephony provider, and my server time. As I have been running this on my server in my house, that was effectively $0.
Because I use a VOIP adapter (Obihai) that supports multiple VOIP providers, I have one VOIP provider for outbound (voip.ms) and a separate one for inbound SIP (linphone). The inbound one doesn’t charge me, so my VOIP bills are only for calls that I make. I’ve been quite happy with voip.ms so far. They charge $1.50/month for 911 services, $0.85/month for a phone number, and $0.009/minute (I’m using their premium services since I feel the phone quality is better). That’s anywhere in North America, so there is no such thing as long distance charges.
The telephony provider (Twilio) provides all the services I need to build the system. They charge me $1.00/month for a phone number, $0.0085/minute for inbound calls, and $0.004/minute for outbound VOIP (and since linphone doesn’t charge anything for inbound, that’s it).
Considering that my monthly bill from my local phone provider is $34.78, only having to pay $6 to $8 is a huge savings.
Of course, I’m paying both at the moment, since I haven’t pulled the plug on my “old” landline while I’ve been testing the system, but I think I’ll be doing that within the next month or so. There doesn’t seem to be any reason not to.
High Level Architecture
Some people have asked for additional details on the design. I’ll probably write a Part 3 post in the future going into the details, but I thought I’d provide some basic details. NOTE: This will only be interesting to the tech-heads; everyone else can skip.
Whenever a person calls my main phone number, it’s answered by Twilio (#1), as they are the Telco for the number. Twilio looks up the details on that phone number, and sees that I want it to issue an HTTPS (REST) request to my server (#2). As a side note: If my server is not responding or provides an error, Twilio has a fallback where it immediately sends the call to my cell phone. Thus, if there are any technical glitches, I still get the call.
At this point, my application, Phonely, receives the request. It queries against the database (#3), which is currently PostgreSQL, to figure out how to handle the call. If the phone number is not listed, or does not have ‘direct’ contact privileges, then the Phonely server begins the process of collecting voicemail. This occurs by a bunch of back and forth requests between Twilio and the Phonely server, using Twilio’s great XML language, Twiml, to make it happen.
As an example of this, here’s the first response Phonely returns to start the voicemail process:
<Response> <Gather timeout="5" numDigits="1" action="https://phonely.example.com/twilio/voicemail/StartCaller?DQ-Submit=true" method="GET" finishOnKey="#"> <Say language="en-US">Hi. Hold on, this is not a normal answering machine. I screen all calls from unrecognized numbers, therefore you won't reach Mike without leaving a message. Stay on the line or press 1 to leave a message.</Say> </Gather> <Redirect method="GET">https://phonely.example.com/twilio/voicemail/StartCaller?DQ-Retry-Count=1&DQ-Submit=true</Redirect> </Response>
In this fragment, we’re telling Twilio to read some text back to the caller and attempt to gather some keypresses. If they press a button, then it will call Phonely back with the keypress. If they don’t do anything within 5 seconds, then it will call Phonely back indicating that they didn’t press any key.
It’s a very straightforward language, and can be easily used to build very complex responses.
Once Phonely has decided the next course of action, it also issues a request to my XMPP/Jabber server (#4). XMPP/Jabber is an instant messaging service that underpins alot of systems out there (Facebook Chat, WhatsApp, Google GTalk, Playstation chat, etc.). This message is directed at an app installed on my phone (#5), so I get immediate notification of whose calling. If they leave voicemail, then I also get the voicemail so that I can listen to it directly on my phone without having to call anything. Additionally, it can send to multiple parties, so everyone at the house receives the message on their instant messaging apps.
If Phonely decides that the person is allowed to directly contact me, then it sends a response to Twilio commanding it to redirect to my SIP address. SIP is the underlying protocol for connecting with VOIP phones. Twilio then connects with my SIP provider, linphone.org (#6), which then redirects to my actual VOIP adapter at my house (#7). All my cordless phones are connected to my VOIP adapter, so my phone then ring (#8), I answer, and we have a conversation.
If I decide to make a call (#9), the VOIP adapter issues the outbound connection to my VOIP provider (#10), who then connects to the real phone number (#11).
Personally, I’d like to simplify a bit and remove linphone.org and voip.ms. Not that they haven’t been providing a great service, but I should be able to get Twilio to provide it all, and that would just make the system simpler and less error-prone. I just haven’t figured out the details yet.
As always, feel free to leave questions in the comments or contact me at firstname.lastname@example.org