Why REST?
REST (Representational State Transfer) is an architecture style for designing distributed applications. With REST, rather than using a distributed application framework such as CORBA, XML RPC or SOAP to build services, simple HTTP request is used to make calls between a client and a service.
REST is a lightweight alternative to other mechanisms like RPC (Remote Procedure Calls) and Web Services (SOAP/ WSDL), as there are no client side proxies or stubs needed and the request response is handled via basic HTTP GET/POST/PUT or DELETE. RESTful applications identify resources with well define URIs and use simple HTTP request for all basic CRUD (Create (POST) / Retrieve (GET)/ Update (PUT) / Delete (DELETE)) operations. The "ST" in "REST" stands for "State Transfer", and in a good REST design operations are self-contained, and each client request carries with it (transfers) all the information (state) that the service needs in order to complete it.
Like Web Services, a REST service is platform-independent, the client and server can be running on different platforms/OS. It is standards-based, as it can run on top of HTTP/HTTPS and can easily be used in the presence of firewalls.
UnLike Web Services and WS-* standards, REST offers no built-in end to end message level security, encryption, session management, transaction and QoS guarantees, etc. In RESTful services, for security, username/password tokens are often used and for encryption REST services can use HTTPS.
The Hub REST Service plug-in will act as a host for REST service instances. The REST service will expose device service and call service with well know URLs so clients can do simple HTTP POST, GET and get serviced in a RESTful way. The service instance will register for device events such as headset button presses, headset state changes, base/hub/handset button presses, base/hub/handset state changes and ATD state changes (Mobile and PSTN call indications). The service instance will also register for Hub session level call events such as call state changes and call requested events.
This device service will expose device commands and device events and the call service will expose call commands and call events. Third party business applications, web (via JQuery Ajax post back) or thick client (via simple HTTPWebRequest and HTTPWebResponse) can interface out of process with the Hub REST Service and communicate with the device and the Hub runtime engine.
Session Manager
The session manager allows you to register a session for your application equired to use Call Commands and Session Events.Session Commands
- Register and Unregister your application session (plugin)
- http://localhost:32017/Spokes/SessionManager/Register?name=My%20Plugin
- My%20Plugin can be replaced with a session name of your choosing (%20 encodes a space in the URL)
- http://localhost:32017/Spokes/SessionManager/UnRegister?name=My%20Plugin
- My%20Plugin can be replaced with a session name of your choosing (%20 encodes a space in the URL)
- http://localhost:32017/Spokes/SessionManager/Register?name=My%20Plugin
Device Service
The device service will expose URIs for getting metadata about the primary Plantronics device (such as PID, product name, version #, serial #, etc.), send a commands to the device and also query for events from a given device. 0123456789 is a magic uid which tells the REST Service to select the current primary device. You are also able to use the uid returned from http://localhost:32017/Spokes/DeviceServices/Info.
- Query Device PID, Name, Version, Serial etc.
- Attach and Release Plantronics device
- Poll for Device Events
Call Service
The call service will expose URIs to query active plugins, send call commands and query call states per registered client, query make call requests and query session manager level call states across plugins.
- Query Active plugins
- Call command - Tell headset of incoming call (ring), outgoing call, answered, held, resumed, muted/unmuted and terminated (or rejected) call
- http://localhost:32017/Spokes/CallServices/IncomingCall?name=My%20Plugin&callID=%7B%22Id%22%3A%22call_id%22%7D&contact=%7B%22Name%22%3A%22caller_name%22%7D&tones=Unknown&route=ToHeadset
- call_id is an integer id that you assign the call, it is used for the life-cycle of the call for example in subsequent Call Events and Session Manager Events (see below)
- caller_name is optional and will be displayed on Plantronics display devices
- NOTE: there are several characters encoded with a % that are needed in the URL, e.g. %7B = open curly brace, etc. For more details of these encodings click here.
- http://localhost:32017/Spokes/CallServices/OutgoingCall?name=My%20Plugin&callID=%7B%22Id%22%3A%22call_id%22%7D&contact=%7B%22Name%22%3A%22caller_name%22%7D&route=ToHeadset
- http://localhost:32017/Spokes/CallServices/AnswerCall?name=My%20Plugin&callID=%7B%22Id%22%3A%22call_id%22%7D
- http://localhost:32017/Spokes/CallServices/HoldCall?name=My%20Plugin&callID=%7B%22Id%22%3A%22call_id%22%7D
- http://localhost:32017/Spokes/CallServices/ResumeCall?name=My%20Plugin&callID=%7B%22Id%22%3A%22call_id%22%7D
- http://localhost:32017/Spokes/CallServices/MuteCall?name=My%20Plugin&muted=true
- http://localhost:32017/Spokes/CallServices/MuteCall?name=My%20Plugin&muted=false
- http://localhost:32017/Spokes/CallServices/TerminateCall?name=My%20Plugin&callID=%7B%22Id%22%3A%22call_id%22%7D
- etc
- http://localhost:32017/Spokes/CallServices/IncomingCall?name=My%20Plugin&callID=%7B%22Id%22%3A%22call_id%22%7D&contact=%7B%22Name%22%3A%22caller_name%22%7D&tones=Unknown&route=ToHeadset
- Poll for Call events
- http://localhost:32017/Spokes/CallServices/Events
- http://localhost:32017/Spokes/CallServices/CallRequests?name=My%20Plugin
- This would only be used for display/dialpad devices
- Poll for SessionManager level events
- Query Call Manager State
NOTE: The URI listed here may not match the ones in the released products so please refer to the Plantronics SDK developer guide for more details and there are sample code available in PDC as well.
Sample 1: Getting Device List via JSON and updating a HTML div in the web page
Note about same origin policy: when using the REST Service API from JavaScript you can use jQuery's JSONP with a callback to avoid same origin policy issue. This is illustrated in the sample code below.<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head id="Head1"> <meta http-equiv="Content-Type" content="text/html;charset=utf-8" /> <title>Device service test web site</title> <script src="jquery-1.7.2.js" type="text/javascript"></script> <script type="text/javascript"> //<![CDATA[ var Type; var Url; var Data; var ContentType; var DataType; var ProcessData; //Generic function to call Device Service function CallService() { $.ajax({ type: Type, // GET or POST or PUT or DELETE verb url: Url, // Location of the service data: Data, // Data sent to server contentType: ContentType, // Content type sent to server dataType: DataType, // Expected data format from server jsonpCallback: JsonCallback, processdata: ProcessData // True or False }); } function ServiceFailed(result) { alert('Service call failed: ' + result.status + '' + result.statusText); Type = null; Url = null; Data = null; ContentType = null; DataType = null; ProcessData = null; } function GetDeviceInfo() { Type = "GET"; Url = "http://127.0.0.1:32017/Spokes/DeviceServices/Info?callback=?"; ContentType = "application/json; charset=utf-8"; DataType = "jsonp"; JsonCallback = "localJsonpCallback" ProcessData = true; CallService(); } function localJsonpCallback(json) { if (!json.Error) { ServiceCallSucceeded(json); } else { alert(json.Message); } } function ServiceCallSucceeded(result) { if (DataType == "jsonp") { resultObject = result.GetUserResult; if (result.length <= 0) { $("#result").fadeOut('fast', function() { $("#result").html("NONE"); $("#result").fadeIn('fast'); }); return; } $('myDiv').load(result); var output = ""; for (var i in result) { if(i == "Result") { output += "Result: "; for (var j in result[i]) { output += j + ": "+ result[i][j] + ". "; } } else { output += i +": "+ result[i] + ". "; } } $("#result").fadeOut('fast', function() { $("#result").html(output); $("#result").fadeIn('fast'); }); } } function ServiceCallFailed(xhr) { alert("Service call failed"); } $(document).ready( function() { setInterval(GetDeviceInfo, 5000); } ); //]]> </script> </head> <body> <form id="form1" action=""> <p>Device Found </p> <div id="result"> <p>None</p> </div> </form> </body> </html>Download link: RestAPISample.zip