Upload
sam-keen
View
4.387
Download
0
Tags:
Embed Size (px)
DESCRIPTION
Adding Channels such as SMS and XMPP to traditional HTTP services
Citation preview
Augmenting Web Services with SMS
and XMPP
Adding Channels such as SMS and XMPP to traditional HTTP services
About Me
•Sam [email protected], @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/