Twilio Plugin - Questions

Posted on
Sat Jul 26, 2014 5:15 pm
tridens offline
Posts: 35
Joined: Jan 12, 2009

Twilio Plugin - Questions

Twilio (voice calling and SMS support) Plugin

I recently did some Twilio / Indigo integration but pushed a lot of the work onto a Node.js server (read: handling Twilio callback endpoints). I utilized Indigo's REST API in order to communicate from Real World (e.g. phone call / SMS) ==> Twilio ==(node.js server)==> Indigo .... and Indigo's Actions > Server Actions > Script and File Actions > Run Shell Script to execute scripts in order to communicate from Indigo ==(node.js server)==> Twilio ==> Real World.

It's pretty slick! I can text "arm" / "disarm" / etc. to a particular phone number and my Indigo server will react. If certain events occur, I receive SMS notification.

But the implementation seems pretty clunky seeing as Indigo already has its own webserver and uses the Python env (versus going out to JS). So, I started this plugin but have hit a few snags and have some questions on how we might make this plugin a reality. Please join in if you're at all interested!

Ideally, here's the minimum that I believe this plugin should support (feedback on this greatly appreciated!):

Config
Image

Events
    An SMS is received
Image
... I can't come up with a good reason to support triggering on an incoming phone call (versus triggering on an received SMS), since a phone call contains all the same info as an SMS less message data (which could/can be used for conditionals ... more in a second on this).

Actions
    Send SMS
    Make Call
Image

Image
Image

Current Status
The plugin is almost ready to support the "Send SMS" Action, but now we hit the questions / issues ...

Questions / Issues

1. How does one include a dependency in an Indigo module?

The plugin needs to use some functions from the official Twilio Python library. While we could just tell the user to fire up terminal and use pip or easy_install to get the twilio-python module, it would be great if either:
A) the supporting Python scripts were included w/the plugin (I don't know how to do this correctly), or
B) they would auto-install. Sending SMS is ready if we can accommodate this one line of code:
Code: Select all
from twilio.rest import TwilioRestClient


2. Receiving POSTed data from Twilio ... here's where things get tricky.

Every Twilio phone number has a voiceUrl and a messageUrl which must be defined (example: http://70.180.40.70:8176/voice). When your Twilio number receives an incoming call or text message, Twilio POSTs call/SMS data to the appropriate endpoint -- your endpoint must then use the data to (mostly for voice calls) render Twilio-flavored XML ("TwiML") that tells Twilio what to do next, example:

Code: Select all
<Response>
  <Say>Holy moly</Say>
</Response>

Challenge 1: Updating the voice and message URLs
If the Indigo server's IP address changes (e.g. 70.180.40.70 ==> 70.180.40.75), then the voiceUrl and messageUrl will no longer point at your server.

Solution 1(?)
In my node.js-based project, I handled this with a periodic routine that gets the server's external IP address and, if it changed since the last check, updates (via the Twilio API) the voice/message URLs, but I don't know how to create a comparable function in Python nor do I know where to put it in the Indigo web server (... and I think this level of modification would move beyond the scope of a normal plugin, yes?)

Challenge 2: Creating Twilio endpoints in the Indigo webserver
Again, apart from the scope of modifications likely falling outside of a normal plugin, I don't know how to navigate the Indigo webserver to create new endpoints.

Proposed SMS Solution
Establish an /sms endpoint that:
- Updates incomingSmsFrom and incomingSmsMessage Indigo variables
- Triggers the An SMS is received Event

Together, these two elements would allow the user to create Triggers that would fire on the reception of an SMS and could use conditional statement(s) on
a) who sent the SMS and/or
b) what the SMS message body contains


Proposed Calling (Voice) Solution
Outgoing calls require a callback URL which will return "TwiML" (again, which tells Twilio what to do next) if/when the dialed person answers ... (Say: "Holy Moly").

If we want to be able to say different things for different Events (yes!), then that means we must be able to pass a whatToSay value out to the XML that is rendered when the dialed person answers ... and that might be 10 seconds after the call is initially placed, at which point other Events might have triggered (!).

Because of this Trigger ===> Answer delay (essentially a delay in rendering the XML with an appropriate whatToSay value), we really can't reference a single, static Indigo variable. If we did, then another Event might trigger and overwrite whatToSay with a completely new value.

One solution would be to (upon a "Make Call" Action):
1. Generate a random Indigo variable name into which to save that Action's whatToSay value
2. Place the call with the random variable in the passed callback URL
3. Establish a /voice/:whatToSay endpoint that:
      i. strips the randomized variable name off the URL parameter
      ii. gets the correct Indigo variable's value (this is whatToSay for that particular call)
      iii. deletes the Indigo variable (in order to prevent buildup of old, used, randomly-named variables)

Here's some code snippets:

Code for the 'Make Call' action
Code: Select all
def makecall(self, action):
        self.debugLog("makecall")
        if action is not None:
            twilioClient = TwilioRestClient(self.pluginPrefs["accountSid"], self.pluginPrefs["authToken"])
            toNumber = str(action.props.get("toNumber"))
            if action.props['fromNumber'] != "":
                fromNumber = str(self.pluginPrefs[action.props["fromNumber"]])
            else:
                fromNumber = str(self.pluginPrefs["phone1"])
            whatToSay = generate_random()
            updateVar(whatToSay, value=str(action.props.get("callMessage")), folder=self.pluginPrefs["folderId"])
            twilioClient.calls.create(
                to=toNumber,
                from_=fromNumber,
                url=BASE_URL +'/voice/'+ whatToSay)
        return True


Rough code for indigoreqhandler.py
Code: Select all
def voice(self, *args, **kwargs):
      """
      Return Type: xml response
      """
                whatToSay = cherrypy.server.indigoDb.GetVariable(cherrypy.server.indigoConn, cherrypy.request.path_info.split('/')[2])
                cherrypy.server.indigoDb.DeleteVariable(cherrypy.server.indigoConn, cherrypy.request.path_info.split('/')[2])
      cherrypy.response.headers['Content-Type'] = 'text/xml'
      tmpl = self._GetAndLockGlobalTemplate('voice.xml')
      try:
         self._FillDefaultTemplateAttrs(tmpl)
         tmpl.whatToSay = whatToSay
         return tmpl.RenderTemplate()
      finally:
         tmpl.ReleaseLock()
   voice.exposed = True


Thoughts? Feedback?

Posted on
Sun Jul 27, 2014 9:37 am
jay (support) offline
Site Admin
User avatar
Posts: 18225
Joined: Mar 19, 2008
Location: Austin, Texas

Re: Twilio Plugin - Questions

Awesome that you're tackling this one - we've been pondering it for years but it just never made it high enough on our priority list.

1. How does one include a dependency in an Indigo module?


You can just include the module code itself in the plugin - inside the Server Plugin folder (same level as the plugin.py file), then normal imports will just work. This is really simple if the module is pure Python (just remove any .pyc files before you distribute). If the module has compiled code, however, it's a much different proposition. You'll have to figure out how to compile the module for all supported Mac architectures (PPC and Intel) if you want your plugin to work on all Macs that Indigo can run on. Of course, you could just include Intel compiled code and stipulate that the plugin requires an Intel Mac - your choice.

2. Receiving POSTed data from Twilio ... here's where things get tricky.


So, in a perfect world, our web server plugin architecture would be updated and you could just include a web server plugin that would allow you catch POST/GETs via Indigo's built-in web server. Point of fact, you can actually build an IWS plugin to do this though be warned that that plugin architecture is very likely to get broken in Indigo 7 as we move IWS into the IOM with the rest of the plugins so you'll have to rewrite it for Indigo 7.

The advantage of doing it as an IWS plugin is that it will work through the reflector service - so you won't have to poke holes in your firewall so that Twilio can post to your Mac. If I were building this right now, I think I'd go ahead and build an IWS plugin to handle it just for this reason, but that's just me. IWS plugins aren't really that hard to write, but they don't use the IOM to access Indigo objects like server plugins do.

If you take this approach, then your Proposed SMS Solution would work since the IWS plugin could update a variable. Your server plugin would subscribe to variable changes and would catch the variable change and trigger the SMS is received event.

Your Calling Solution would then require some more complex interaction. I think I'd take this approach: users define via your plugin what Events and responses they want. Whenever your plugin's dialog (where the user defines these) closes, it would then write it out in some format to the filesystem (JSON or XML probably). Then, when the IWS plugin receives the call event, it can look the event up in this file and do whatever is necessary.

Anyhow - those are just my thoughts after a brief read. Good luck and let us know what we can do to help.

Jay (Indigo Support)
Twitter | Facebook | LinkedIn

Posted on
Sun Nov 23, 2014 12:48 pm
Lunkan offline
Posts: 13
Joined: Aug 18, 2013
Location: Sweden

Re: Twilio Plugin - Questions

How is the status with this plugin,? Still develop? When ready?
Searching for a way to send sms from Indigo and Twilio seems to be excellent for doing that.

Posted on
Fri Mar 27, 2015 7:16 am
AndyVirus offline
Posts: 257
Joined: Mar 18, 2014
Location: Newport Pagnell, UK

Re: Twilio Plugin - Questions

Hello,

I too am very intrested in this plugin as it is the ONLY thing i miss from Vera (bag of shi*te that was).

Happy to alpha test this if you have it in a working state of any kind :-)

Posted on
Sun Dec 06, 2015 7:38 pm
zini offline
Posts: 59
Joined: May 19, 2013

Re: Twilio Plugin - Questions

Would also love to see some Twilio integration. I've used Twilio many times in my business and man, it's powerful.

Mark

Posted on
Thu Mar 03, 2016 6:57 pm
rycardo offline
Posts: 53
Joined: Jul 10, 2015

Re: Twilio Plugin - Questions

Hey all,

I'v already got the basics of a messaging plugin working for me. Twilio is only part of it, there are two other backend services involved. The plugin+service gives a way to send and receive texts to/from Indigo. This came about because of all the issues I'v had with the Google Voice plug-in, and I already use Twilio for an other project I'm involved with.

I was going to contact Matt and Jay to get their thoughts on this, then I came across this thread (quite accidentally), so I'm going to ask for any interest and thoughts here.

The way the service+plugin works: You sign up for the service, providing your mobile numbers, and are provided a telephone number that you will send the messages to. When that remote phone number receives a message, it looks up the sending phone number of the message, determines which Indigo it belongs to, then sends the message to Indigo. My first pass it is updating variables. However, I'm now working on it having actual devices where the states are updated.

Since Twilio and one of the other back end services are paid services, I would need to offer this plugin as a paid service. Since I'm not trying to make money, only cover costs, the fees would be very low.

In my fee structure below, an authorised number is just that, a mobile telephone number that is allowed to send/receive messages to your Indigo. Each Incoming message is a message from one of those mobile numbers where the message is to be delivered to your Indigo. Right now it's only messaging to Indigo, not from Indigo to a mobile number, but I am working on adding that.

These are my first estimates for the fees, based on the country of the user:

Canada (CAD) $1 per authorised number per month, plus ¢3 per incoming message
United Kingdom (GBP) 70p per authorised number per month, plus 1.5p per incoming message
United States (USD) $1 per authorised number per month, plus ¢2 per incoming message.
Other countries vary, but are usually the equivalent in local currency.

If you want to estimate a monthly amount, figure two authorised numbers, each sending 5 messages a week, for one month of service that comes to a total of:
In Canada, $3.28
In the UK, £2.04
In the States, $2.86

If anyone is interested, or has some thoughts, please let me know.

Rycardo

Posted on
Sat Mar 19, 2016 10:31 pm
zini offline
Posts: 59
Joined: May 19, 2013

Re: Twilio Plugin - Questions

I would definitely be interested in any development on the Twilio front. This is something that I've been wanting to do for awhile, as I'm somewhat familiar with Twilio.

Any updates?

Mark

Posted on
Sun Mar 20, 2016 9:00 am
dnomode offline
Posts: 366
Joined: Apr 12, 2008
Location: North Georgia

Re: Twilio Plugin - Questions

I would also be interested.


Sent from my iPhone using Tapatalk

Page 1 of 1

Who is online

Users browsing this forum: No registered users and 8 guests