augmenting web services with sms and xmpp

Post on 15-Jan-2015

4.389 Views

Category:

Technology

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Adding Channels such as SMS and XMPP to traditional HTTP services

TRANSCRIPT

Augmenting Web Services with SMS

and XMPP

Adding Channels such as SMS and XMPP to traditional HTTP services

About Me

•Sam Keensam@pageindigo.com, @samkeen

•Originally a Java (J2EE) developerEscaped that for PHP ~2003

•Founded and have been running PDXPHP for about 4 years

•currently employed at finedesigngroup.com/

Talk Summary•Advantages of adding these channels

•Overview of SMS and XMPP

•Explain Extapi (my take on implementing these channels)

•Example Service: Trimet TransitTracker®

•Teaching humans to speak Machine: HAMDL

•Future

Motivation

Laziness

Why (users)

•The mobile generation is growing accustomed to passive aggressive connectivity

•Mobile users are loosely engaged with services

•For many services, users want information and do not want ‘experience’ to get in the way

Why (devices)

•More and more, Web sites services are accessed through mobile devices

•Device capability

•A subset of devices have data access ability

•Of those devices, a small percentage provide an acceptable degree of usability

Why SMS

•Low Attention Requirement

•All modern phone support it

Even this phone has SMS ability

SMS Downside

SMS Downside

•Some might say: “SMS is controlled by Evil Empires”

•$$$ to implement on your own

•Very limited capability

SMS

Why XMPP

•Open Standard

•Its all about the X (extendable)

•Presence, multi-user chat, SOAP over XMPP, Jingle (voice, video, file) , oauth over XMPP, ...

http://xmpp.org/extensions/

•Ease of implementation

Why XMPP

It makes SMS look like:

QuickTime™ and aGIF decompressor

are needed to see this picture.

Extapi•Centralized Service and Channel

Adaption Manager

•Currently Implemented as a PHP LAMP stack

•Enables you to extend the number of channels available to a web service

•Goal is to enable new services and channels by way of configuration (little or no code)

What Extapi Needs to do

•Map given request params to a common set of values for a given channel

•parse/authenticate request

•make the request to the target web service

•parse the response from the web service

•sent the response back through the channel to the client

Architecture Goal

Web Service XWeb Service X

HTTP

Users

Architecture Goal

Web Service XWeb Service X

XMPP SMSChannel

NHTTP

Users

Architecture

ChannelsChannels

SMSSMSXMPPXMPP

ServicesServices

TrimetTrimet

TwitterTwitter

Service Service XX

ChannChannel Xel X

Extapi App ServerExtapi App Server

ClientsClients

HTTPHTTP

Architecture

ChannelsChannels

SMSSMSXMPPXMPP

ServicesServices

TrimetTrimet

TwitterTwitter

Service Service XX

ChannChannel Xel X

ClientsClients

HTTPHTTP

MVC ContainerMVC Container

Extapi Structure

Aabot

App

Static

Vendor

Extapi

Built in the style of a Vendor plugin. Currently within the Aabot MVC container. Can also be adapted for containers such as CakePHP

ChannelsServices

Channels•Purpose is to take and existing

protocol (XMPP, SMS), and convert to HTTP. Then forward the message to the Extapi server

•So after querying a http web service Extapi can then send replies back through the channel via HTTP, or short circuit directly to the originator if it can speak the originating protocol.

Implementing an SMS Channel

•Shortcode Shares: Multiple users share a single shortcode managed by a Shortcode share company

Shortcode Shares are the cheapest, bi-directional, most reliable way to get started.

SMS Shortcode SharesFREE!

There are concessions to be made for all the “Freeness”

•SMS SS will typically append ~20 char teaser ads to client bound messages

SMS Shortcode SharesFREE!

There are concessions to be made for all the “Freeness”

•SMS SS will typically append ~20 char teaser ads to client bound messages

•Your app context lives under a keyword on the provider’s shortcodeex: you text “myapp my message” to shortcode 123456 rather than just texting “my message” to shortcode 123456

SMS Shortcode SharesFREE!

There are concessions to be made for all the “Freeness”

SMS Shortcode Shares

•They blackbox the entire telco infrastructure

•Provide a familiar HTTP API interface to the developer

•They manage user registration and opt out

There are also benefits

Shortcode Share Architecture

ExtapiExtapi(or any web (or any web

app)app)

mobilmobile e

carricarrierer

Users

Short Short Code Code ShareShare

HTTP

HTTP

Shortcode Shares

•Textmarks: Mature, feature rich

•Zeep: New kid on the block

•Dotgo: Different Beast

A Few Options

Dotgo

<?xml version="1.0" encoding="UTF-8"?><cmrl xmlns:dotgo="http://dotgo.com/cmrl/1.0"> <match pattern="*"> <engine href="http://example.com/service.php"/>

OR <message> <content>Hello world!</content> </message> </match></cmrl>

Channel: XMPP•Many Server Choices:

http://xmpp.org/software/servers.shtml

• I chose the Hometown crew: Openfire

•very easy to setup

•easy to extend (if you know a little Java)

•Well documented and supported

•Lots of example Plugin code

Example XMPP Channel

Architecture

Users

ExtapiExtapi XMPP XMPP ServerServer

(Openfire)(Openfire)

X2HttpX2HttpPluginPluginHTTP

XMPP

X2Http Openfire plugin

Example: TransitTracker®

Currently offers web access, WAP, and IVR

These all require the user to be highly engaged with the service

Trimet over SMS

Trimet over XMPP

Yes It Is Alpha code

Review: What Extapi Needs to do•Map given request params to a common

set of values for a given channel

•Parse/Authenticate request

•make the request to the target web service

•parse the response from the web service

•sent the response back through the channel to the client

Extapi: Base Class for a channel

ExtapiChannels

class Extapi_Channel_Base

/** * @return boolean */public function have_required_request_params()/** * @return boolean */public abstract function authenticate_request();

Extapi: Base Class for a Service

ExtapiService

class Extapi_Service_Base

public abstract function parse_request_statement();public abstract function act_on_request_statement();public abstract function gather_feedback();

private function sms_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();header('Content-type: text/plain',true);$sms_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($sms_channel && $sms_channel->have_required_request_params()

&& $sms_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($sms_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = array_get_else($arrivals,'arrivals');$this->payload->transit_stop = array_get_else($arrivals,'transit_stop');$this->payload->query_time = array_get_else($arrivals,'query_time');

} else {$this->viewless();

}} else {if (! $sms_channel) {

ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance ... } else {

ENV::$log->notice(__METHOD__.' Required components were not ... }

$this->viewless();}

}

private function sms_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();header('Content-type: text/plain',true);$sms_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($sms_channel && $sms_channel->have_required_request_params()

&& $sms_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($sms_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = array_get_else($arrivals,'arrivals');$this->payload->transit_stop = array_get_else($arrivals,'transit_stop');$this->payload->query_time = array_get_else($arrivals,'query_time');

} else {$this->viewless();

}} else {if (! $sms_channel) {

ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance ... } else {

ENV::$log->notice(__METHOD__.' Required components were not ... }

$this->viewless();}

}

private function sms_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();header('Content-type: text/plain',true);$sms_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($sms_channel && $sms_channel->have_required_request_params()

&& $sms_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($sms_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = array_get_else($arrivals,'arrivals');$this->payload->transit_stop = array_get_else($arrivals,'transit_stop');$this->payload->query_time = array_get_else($arrivals,'query_time');

} else {$this->viewless();

}} else {if (! $sms_channel) {

ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance ... } else {

ENV::$log->notice(__METHOD__.' Required components were not ... }

$this->viewless();}

}

private function sms_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();header('Content-type: text/plain',true);$sms_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($sms_channel && $sms_channel->have_required_request_params()

&& $sms_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($sms_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = array_get_else($arrivals,'arrivals');$this->payload->transit_stop = array_get_else($arrivals,'transit_stop');$this->payload->query_time = array_get_else($arrivals,'query_time');

} else {$this->viewless();

}} else {if (! $sms_channel) {

ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance ... } else {

ENV::$log->notice(__METHOD__.' Required components were not ... }

$this->viewless();}

}

private function xmpp_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();$xmpp_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($xmpp_channel && $xmpp_channel->have_required_request_params()

&& $xmpp_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($xmpp_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = $arrivals;

} else {$this->viewless();

}} else {

if (! $xmpp_channel) {ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance failed for

[extapi/channel/'.$requesting_channel.']');} else {

ENV::$log->notice(__METHOD__.' Required components were not found and/or authentcation failed for this request');

}$this->viewless();

}}

private function xmpp_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();$xmpp_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($xmpp_channel && $xmpp_channel->have_required_request_params()

&& $xmpp_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($xmpp_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = $arrivals;

} else {$this->viewless();

}} else {

if (! $xmpp_channel) {ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance failed for

[extapi/channel/'.$requesting_channel.']');} else {

ENV::$log->notice(__METHOD__.' Required components were not found and/or authentcation failed for this request');

}$this->viewless();

}}

private function xmpp_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();$xmpp_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($xmpp_channel && $xmpp_channel->have_required_request_params()

&& $xmpp_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($xmpp_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = $arrivals;

} else {$this->viewless();

}} else {

if (! $xmpp_channel) {ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance failed for

[extapi/channel/'.$requesting_channel.']');} else {

ENV::$log->notice(__METHOD__.' Required components were not found and/or authentcation failed for this request');

}$this->viewless();

}}

private function xmpp_receiver() {$this->use_layout = false;$requesting_channel = $this->next_request_segment_value();$xmpp_channel = Util_VendorFactory::get_instance('extapi/channel/'

.$requesting_channel);if ($xmpp_channel && $xmpp_channel->have_required_request_params()

&& $xmpp_channel->authenticate_request()) {ENV::load_vendor_file('Extapi/Service/Tmet');$tmet_service = new Extapi_Service_Tmet($xmpp_channel);$tmet_service->parse_request_statement();$tmet_service->act_on_request_statement();if ($tmet_service->has_feedback()) {

$arrivals = $tmet_service->gather_feedback();$this->payload->arrivals = $arrivals;

} else {$this->viewless();

}} else {

if (! $xmpp_channel) {ENV::$log->error(__METHOD__.' Util_VendorFactory::get_instance failed for

[extapi/channel/'.$requesting_channel.']');} else {

ENV::$log->notice(__METHOD__.' Required components were not found and/or authentcation failed for this request');

}$this->viewless();

}}

Talking to Machines

•Examples so far have been very limited, our statement to the Machine is just a number

•How do we have ‘dialogue’ with machines?

•Invest millions in Natural Language Processing? OR have an intermediary language to bridge the gap between Natural Language (English, French, Spanish, etc) and Programming languages.

Bridge Language

•A bridge language helps the machine by adding ‘token markers’ and limiting the vocabulary set

•Twitter is an example: @samkeen is at #phpworks

•Many other examples, some cataloged athttp://microformats.org/wiki/picoformats

HAMDL•Bridge language meant to be an open

standard to help unify some of these ‘pico formats’

•Major goal is accessibility : device and human

•Ease of use for limited capability devices

•Ease of use for limited capability humans

•http://hamdl.pbwiki.com/

Future

•Channels

•OpenCV visual channel

•barcode channel

•More NLP for HAMDL

Sources• XMPP: http://xmpp.org/• XMPP Servers: http://xmpp.org/software/servers.shtml• Openfire: http://www.igniterealtime.org/projects/openfire/index.jsp• Extapi: http://code.google.com/p/extapi• HAMDL: http://hamdl.pbwiki.com/

top related