Latest work with SMS
I wrote a while back about what one of our clients is doing with SMS. Since then we have taken their SMS to a completely new level. I’d like to share what we’re doing, and how we’re doing it, to give you ideas about what’s possible in both the technical and business sense. Let your imagination chew on this for a while to see how it might fit with your business software.
Let’s take a step back for a few minutes and ask “Why the telephone? Why SMS?”
The telephone is now just another user interface. We’re focusing here on one of the media supported by the mobile phone, SMS. At some point I might write about how to do the exact same functions by voice. The explosion of smart phone usage and “app” awareness in the consumer market has rapidly brought the telephone from obscurity to the top of the list as a preferred user interface device. The phone is a viable UI right along with the 80×24 character screen, the browser with HTML, the thick-client application, email, fax, web services, and so many others. Since almost everyone has a telephone with them at all times, the telephone as a user interface should be seriously considered as a means of communicating information within your company, and to and from your clients and prospects.
After agreement that mobile devices are worthy of consideration, one question every developer has is “which phone(s) should I develop an app for?” The short answer is to target your primary audience. Do most of your users have an iPhone? If so do you have anyone who can write Objective-C applications with a Mac? What about Symbion-based phones that require Java? What about Windows7 Mobile phones where apps are created with .NET code? What about Android? It’s bewildering isn’t it? Everyone has a different phone. We face similar questions when creating a website: Which browsers do we support? How much money do we lose if we don’t support a specific browser? Do we gain or lose prospect interest with Flash and other technical extensions? There are (at least) two ways to keep everyone happy. One way is to code in every required language for every platform and software release. (Yeah, these days phones have operating systems and release levels just like anything we’ve worked with in the past.) The other way is to find something common to all of the phones that everyone can use. I won’t say anything against writing apps for phones. But for our purposes here I will just encourage you to consider SMS as the “lowest common denominator” that all mobile users share. Almost everyone who has a phone sends text messages. People can’t walk down the street (or sometimes drive) without “texting”. People can’t enjoy a meal or conversation without texting with someone else. Everyone knows how to do this, and everyone has the feature available to them, so why not code to that first, and then see what kind of demand you get for platform-specific applications?
(Let’s avoid discussions about how SMS/texting is destroying the English language and human ability to verbally communicate and socialize. We’re not here to evaluate the social implications of technology but to evaluate its merits for doing better business.)
Rather than writing platform-specific apps, my client decided that SMS is the first (and maybe only) medium that they would target to allow mobile users to interact with the company. So one of the first things I did was to ensure that inbound SMS messages from any phone would pass all the way through to any given MV system.
SMS messages from mobile phones ultimately get passed via HTTP as a simple web “page” request to a web server. (Internally the response to such requests is XML, much like a web page or any web service.) As with any web interface, we just need a way to get into MV. As you probably know from reading this blog, I use mv.NET for most connectivity, but if I sell this interface I don’t want the cost of mv.NET (even at only $260) to inflate the cost of this offering. So I created a single communications component that has UO.NET, mv.NET, MVSP, QMClient.NET, and direct SSH connectivity. Simply by changing a configuration file, we can now route requests to any MV environment, using whatever connectivity method the site prefers. (That component by itself should be productized … whenever I have time …)
For the current client work we’re using D3 but I’ve been doing the same thing here with QM and can easily port the code to Universe or any other MV system. The web server we’re using is in New York and we’re making an SSH connection into a Linux server in California. From the Linux command line a d3tcl command gets into D3 and executes code. If we were coming in with another communications pipe we would ultimately be led to this same end-point, whether TCL or maybe a BASIC subroutine.
Once in MV, all requests are processed by common BASIC code. At this point we’re just executing a subroutine, passing in some data in a REQUEST variable, and the subroutine is expected to return a RESPONSE variable. This is something Pick people do every day (yes, YOU can do all of this NOW). The response goes back up the pipe and out to the requesting mobile phone.
Now that we have a clean pipe, and the mechanics of transport are all handled transparently, we can put anything we want into the pipe and return anything back. Forget that there is a telephone on one end of the pipe and a web server in the middle. This is pure text processing at this point.
So what kind of text are we processing? Every task as Input, Processing, and Output. Here are some examples:
Example 1: An employee sends an SMS message to a designated phone number with nothing but an inventory part number. In BASIC we get the ID, read the inventory record, and return data like description, available quanity, and price.
Example 2: A sales rep sends in nothing but a customer ID. The server opens the customer file and returns credit status info.
With just those two examples, assume for a moment that we have two telephone numbers and you can SMS a specific request to either one. That’s OK but a person making requests for both kinds of information would need to have two phone numbers in their contact list so that they can select and send a specific request to the right back-end processor.
But for those two options I created a “multi” handler to avoid having a different phone number for each function. This handler first takes the input and attempts a read on the Inventory file. If the item doesn’t exist it reads the Customer file. Customer IDs and Part numbers in this application are sufficiently different that there is no cross-over and the ID’s can’t be confused. So in this case we can use one phone to handle both of these functions, and more.
For more complex operations, you either need more than one phone, each with a unique subroutine handling requests, or the user making the request needs to provide a cue for what they want.
Let’s spend a minute on this concept of cues. In “real life” you can go to a Shoe store and buy shoes, or you can go to a Bakery to buy cake. When you go into one of these stores there is no confusion about why you’re there, and one store simply can’t satisfy requests that the other store can. When you call a company, you may ask to be transferred to a specific department before you provide specifics about your call – we all know how ineffective it can be to try to state your business to a receptionist.
The same holds true for SMS message processing. If your request can be for one thing or another, you must tell the server in the message how you want the request to be processed. Perhaps the user sending the message adds a prefix to their item ID: inventory gets an “I” prefix and customer status requests get a “C” prefix. So I12345 doesn’t get confused with C12345. Perhaps you would prefer the message to be more like “inv 12345” or “cust 12345”. With that cue, the BASIC code can easily parse the request to provide the correct response.
If you think about it, you’ve probably code that yourself, where an INPUT statement allows a user to enter a record ID, or “?” for New, or maybe “?” for a search. You then process the input differently depending on this user-provided cue. SMS handling is no different.
So now you know how we decide the program that processes requests: We can guess. We might have a dedicated phone to only process single requests. Or we rely on the user to tell us explicitly what they want to do.
Let’s take a look at some completely different functionality. But note that now that the initial communications work is done. Absolutely no coding is done outside of the MV server. _All_ code is BASIC and _all_ data is processed in common MV files. There’s nothing in any of this anymore related to phones or web servers.
Our client wanted a user registration system. They wanted customers to provide their mobile number, name, or email address without a clerk having to enter this data at a Point of Sale (POS) terminal or over the phone. After just a few hours of work, people can now SMS their info and it gets logged in a SMS.USERS file. From there the data can be processed into the local business application as required.
Inbound messages have this structure:
GROUP_ID NAME EMAIL
For example: starfleet James T Kirk moc.esirpretnenull@ktj
In BASIC we check the group ID “starfleet” against a file SMS.GROUPS. If the group is invalid, we ignore the request and do not return a response. This is because we don’t want to process requests from people who accidentally stumble upon our phone numbers. The chance of someone accidentally providing a valid group ID in their message is slim. The email address is actually parsed off second because it’s easily identified with the “@” sign. The remainder of the message is treated as the person’s name.
With the information above, we know the group, the name, the email address, and the person’s mobile/cell phone number. What if they forget to add the email address? What if they have another email address? Another SMS can be sent without the name.
When that message comes in we get the mobile number as part of the request. This is checked against a cross reference. We’ve seen this phone before and can open the original user record, then add the new email address to a multivalued list.
The same person can later identify themselves with a different group simply by sending a message with the new group name, like ‘vulcanfriends’. Again, we know the user from the phone number and can add the group ID into their user record, as well as perhaps updating a group list with the ID of this existing user.
Now that we have the data, what do we do with it? I shouldn’t need to provide examples of how companies and groups can make use of functionality like this. It really all depends on your application. Seriously, how many reasons might we have to notify an individual or group of some event? How many occasions are there to ask someone a question when you don’t need an immediate response? With outbound SMS capabilities as well as inbound, we can send an SMS message to any one or more registered users:
- We can advise customers of a sale for a product for which they’ve expressed interest.
- We can advise sales reps when their customers have made large purchases or called for support.
- Airlines use SMS to notify people of flight status.
- Doctor offices can send appointment reminders.
- Club leaders can notify everyone in their membership of meeting cancellations.
- A note can be sent to company management that a meeting has been scheduled for the next day. (Confirmations are logged and anyone who doesn’t respond gets a phone call.)
- A notification can be sent to someone waiting for a restaurant table that their table will be ready in 5 minutes.
- An SMS broadcast can replace any phone tree.
- Let people at a trade show know that a person of interest is available at a booth to answer questions.
- We can notify the ship’s captain that an invasion fleet has crossed the neutral zone. OK, that’s just silly. We would get the application to call them on the phone rather than sending an SMS. But inbound/outbound voice integration is a topic for another blog.
Inspired by one of my blogs on system administration via SMS, our client wanted to initiate backups remotely. I created a basic program that starts a backup without any prompts. Now when a command is received by an authorized user, the backup program is executed. That’s pretty easy now that we have the infrastructure all in place.
The client also wanted to allow employees to send messages to users logged in to D3. On receipt of an SMS, the message is parsed off and then:
msg UserName Message from Joe Customer (123-456-7890) Message here…
Personally I see issues with the msg command being used like that, but hey, this is what the client wants and it works exactly to spec. The point is not to evaluate how others use technology, but to know that we can do what we want now, compared to writing off ideas because we previously thought it was impossible to implement them.
How does that SMS outbound functionality described above work? Well it can go out through the same pipes and web server that we use for inbound requests, but then we would need to poll for outbound requests. As an alternative I have a program that sends an outbound HTTP request using cURL, ultimately getting a message to a specific phone. This can be called by any program. Again at this point it’s all just BASIC. An application program needs to create variables for the target Phone number (from the SMS.USERS file or elsewhere), the outbound message, and the phone number being used to send the message. My program is called, and the message is sent using whatever outbound phone number is specified. If the mobile user wants to reply to the message they can. The response will come back as described above, on the phone number that sent the outbound message, and the response ultimately gets processed like any other request.
I won’t get into any more details here, like:
- What links outbound requests with responses?
- What if the user doesn’t respond? Does that mean they didn’t get the message from their carrier? Are they too busy to respond today? Did they lose their phone? What does “no response” mean?
- What if a user accidentally respond incorrectly and they want to change their response?
- What if they accidentally respond twice, maybe differently each time?
Good software must handle human and technical errors. These concerns are not unique to phone-based applications. I can provide some notes on these topics later if required.
The bottom line on SMS for now is that bi-directional SMS is easy, and I strongly encourage you to consider this in your upcoming development. Come up with some scenarios about how people can provide information to your system, and how you can provide information back to them. Discuss this with your users and clients. I’m really interested in the responses and I welcome your emails to discuss the topic.
We can also call phones and play recorded messages, or generate messages with Text-To-Speech synthesis. We can link people by phone: An employee can call a customer without knowing the customer’s number, and the customer receiving the call will see a company phone number in the caller ID rather than the employee’s personal phone number. We can also route in the other direction, where customers contact employees no matter where they are through a company phone number. We can respond with a menu to inbound voice calls (“Press 1 for …) and even convert speech to text to allow information requests to be submitted by voice. That kind of functionality is expected with high-cost PBX systems, but we can now do all of this fairly easily with BASIC from our MV apps.
As I said in the beginning: Let your imagination run with this for a while. I’ll be happy to help you to flesh out and then implement some of your ideas.