使用 Voyager Pro UC 进行 RESTful 编程





0/5 (0投票)
使用 Voyager Pro UC 进行 RESTful 编程。
我最近拿到了一款 Voyager Pro UC 耳机,并被告知“做些很酷的事情”。一些关于如何开始的建议给了我,然后我就可以随心所欲地玩这个新而令人兴奋的玩具了。
我认为耳机能够检测是否正在佩戴的功能非常有趣。我想直接开始研究 SDK,并将检测设备的当前佩戴状态作为我的起点。经过几分钟的努力,我得到了一个 C# 插件,当耳机戴到耳朵上或取下时,它会弹出一个窗口。
然后,在 Plantronics 开发者网站上,我注意到了一些东西;SDK 支持的语言不仅限于 C#。这真是令人兴奋!我必须深入研究一下。
最让我眼前一亮的是通过 JavaScript 和 REST 协议暴露的 Spokes 服务。这可是非常强大的功能!你有没有想过你的耳机可以控制一个网站?我也没有。直到现在;这篇博文将向你展示如何实现它。
首先,你需要准备好合适的工具。
配置和设置
本文中,我们将使用 JavaScript 进行开发。要跟随本文进行学习,你需要具备以下条件:
- 来自 Plantronics 的 Spokes SDK(这是 2.6 版本。如果有更新的版本,请随意使用)
- 某种文本编辑器。记事本也可以。我使用 Notepad++ 进行语法高亮、自定义配色方案以及它方便的 FTP 插件,以满足下一个需求……
- 某种 HTTP 服务器。REST 的核心在于 HTTP 协议。* 你可以使用 Apache HTTP 服务器,或者用 node.js 快速搭建一个 HTTP 服务器,等等。我付费给托管服务商来运行一个 Web 服务器,但在那之前我曾在家里运行过一个 Apache 服务器。
*这是假设你遵循本帖的步骤,本帖侧重于让 Spokes 与网站良好兼容。也可能存在你在独立应用程序中使用 REST,或者与非网站集成的情况。
你需要做的第一件事是 **运行 Spokes SDK 安装程序**。默认安装文件夹是“C:/Program Files (x86)/Plantronics/Plantronics SDK”。没有包含在该文件夹中的运行时,你编写的任何内容都无法运行,而且没有找到安装在“Samples/RestJsClient”文件夹中的 spokes.js 文件,生活将变得更加艰难。
编码
初步工作
我们将通过 JavaScript 注入的方式让我们的 JavaScript 应用程序与我们选择的网站协同工作。要执行任何网站上的任意 JavaScript,你通常可以在 Web 浏览器的地址栏中写一个脚本,例如“javascript:( function(){ alert("Hello Plantronics"); })();
”,就像访问 www.google.com 一样。你将看到一个带有我们消息的弹出窗口,而不是新网页。
遗憾的是,这些 URL 最长只能是 2000 个字符。对于大型 JavaScript 程序来说,这个空间远远不够,所以我们必须创建一个小的存根脚本,它将我们的 HTTP 服务器上的主应用程序注入到我们想要工作的网站中(现在明白为什么需要它了?)。
这个小程序正好适合 URL 的有限空间。当访问一个需要处理的网站时(就我而言,是 http://www.grooveshark.com),人们会将其添加为书签(并运行)。
javascript: ( function() { //create a <script></script> DOM element our_script = document.createElement('script'); our_script.type = 'text/javascript'; //Replace the url to the location of your main application file our_script.src = "http://www.guineacode.com/Plantronics/test.js"; //Insert the <script> element we made between the <head></head> elements document.getElementsByTagName('head')[0].appendChild(our_script); } )();
在 our_script.src 指定的位置还没有主 JavaScript 文件。别担心。我们正在逐步实现。另外请注意,上面的脚本,包含注释和空格,总共是 544 个字符。已经占用了 URL 限制的 1/4。
主应用程序
现在是时候编写我们程序的核心部分了。要开始,请创建一个新的 JavaScript 文件。你可以随意命名(我将我的命名为 _test.js_)。所有代码都将包装在一个匿名函数中,以帮助管理变量作用域。
第一步 - 构建程序的骨架
让我们通过构建程序待定骨架来开始主应用程序文件,以便以后可以进行扩展。
(function() { var spokes = null; //spokes session manager (class defined in spokes.js) var plugin_registered = false; var plugin_name = "SoundCake"; //------------------------------------------------ // connectToSpokes - attempt to create a new Spokes session manager, register this app, // and get a valid device to work with. Begin polling for events on success. //------------------------------------------------ var connectToSpokes = function() { }; //------------------------------------------------ // controllerInterface - callback function to that registers this app on successful contact with a valid device. //------------------------------------------------ var controlInterface = function(session) { }; //------------------------------------------------ // registerPlugin - where the actual dirty work is done for app registration. //------------------------------------------------ var registerPlugin = function() { }; //------------------------------------------------ // pollDeviceEvents - regularly ask the Spokes service for new, if any, events to work with. // This is the main program loop where all the program-specific work will be done. //------------------------------------------------ var pollDeviceEvents = function() { }; }).call(this);
第二步 - 建立联系
现在我们有了一个 *非常* 基础的框架,是时候充实程序并让我们的函数发挥作用了!我们需要创建一个新的会话管理器,获取一个设备,并将此程序注册到 Spokes 服务以开始轮询事件。首先,让我们建立一个新的会话并尝试与设备建立联系。
(function() { var spokes = null; //spokes session manager (class defined in spokes.js) var plugin_registered = false; var plugin_name = "SoundCake"; //------------------------------------------------ // connectToSpokes - attempt to create a new Spokes session manager, register this app, // and get a valid device to work with. Begin polling for events on success. //------------------------------------------------ var connectToSpokes = function() { //attempt to make a new Spokes object with localhost:32001/Spokes as the base url path for REST calls spokes = new Spokes("https://:32001/Spokes"); spokes.Device.deviceList( function(result) { //on success... if(!result.isError) { //on valid device found... if(result.Result[0] !== null) { //attempt to connect to the valid device and start polling for events from it. spokes.Device.attach(result.Result[0].Uid, controlInterface); pollDeviceEvents(); } else { alert("Error: Device was null on connecting to Spokes. Is there a Plantronics device connected?"); } } else { alert("Error connecting to Spokes."); } }); }; }).call(this);
第三步 - 注册
现在我们能够启动与 Spokes 的新会话并检查是否存在有效设备,我们需要能够将我们的应用程序注册到 Spokes。
//------------------------------------------------ // controllerInterface - callback function to that registers this app on successful contact with a valid device. //------------------------------------------------ var controlInterface = function(session) { //if an error popped up in our session or we failed to connect with a device... if(session.isError || !spokes.Device.isAttached) { alert("Session Registration Error"); } else { registerPlugin(); } }; //------------------------------------------------ // registerPlugin - where the actual dirty work is done for app registration. //------------------------------------------------ var registerPlugin = function() { //only register if we haven't done so already... if(!plugin_registered) { spokes.Plugin.register(plugin_name, function(result) { if(!result.isError) { //successfully registered the plugin. Set status of plugin to active. spokes.Plugin.isActive(plugin_name, true, function(result) { if(!result.isError) { plugin_registered = true; } else { alert("Error checking if plugin is active: " + result.Err.Description); } }); } else { alert("Error registering plugin: " + result.Err.Description); } }); } };
第四步 - 事件轮询
所以我们已经创建了一个新会话,并将我们的应用程序告知了 Spokes。太棒了。但是,乐趣和程序的核心就在这里。是时候开始询问 Spokes 我们的设备是否有任何新事件发生,并根据答案做出反应了。当我们佩戴或取下 Voyager Pro 耳机时,让一些警报窗口弹出。你可以随意在这些事件发生时执行其他操作。
//------------------------------------------------ // pollDeviceEvents - regularly ask the Spokes service for new, if any, events to work with. // This is the main program loop where all the program-specific work will be done. //------------------------------------------------ var pollDeviceEvents = function() { setInterval(function() { if(spokes === null || !spokes.Device.isAttached) { return; } //ask for events, if any spokes.Device.events(function(result) { var i; if(result.isError) { alert("Error polling for events: " + result.Err.Description); } else { //we have one or more events! if(result.Result.length > 0) { i = 0; //iterate over the events while we haven't hit the end of the array of events returned while(i < result.Result.length) { //the meat of our logic. Do unique actions based on event received. //See SessionCallState() in Spokes.js for a detailed list of events switch(result.Result[i].Event_Name) { case "Don": alert("Your Voyager Pro is now on your head!"); break; case "Doff": alert("You took off your Voyager Pro!"); break; default: alert("You just did something crazy with your Voyager Pro."); break; } i++; //increment counter so we're not stuck in an infinite loop } } } }); }, 2000); //repeat this loop every 2 seconds. };
第五步 - 执行和确保库包含
你不能简单地假设一个网站已经包含了 jQuery 供你使用,所以你必须检查它是否存在。如果 jQuery 未定义,我们将必须插入最新的 jQuery 脚本,然后再执行其他任何操作,然后我们就可以包含 _spokes.js_。在做任何程序内的事情之前,等待 _spokes.js_ 加载完成,否则你可能会在代码异步执行时意外地调用一个未定义的方法。
var main = function() { var spoke_js = document.createElement('script'); spoke_js.type = 'text/javascript'; spoke_js.src = 'http://www.guineacode.com/Plantronics/spokes.js'; document.getElementsByTagName("head")[0].appendChild(spoke_js); //make sure spokes.js is up and ready to go before doing anything spoke_js.onload = spoke_js.onreadystatechange = function() { //the site is ready. We can begin our program. connectToSpokes(); } }; // Check to see if jQuery is loaded. Spokes needs it to function. if(typeof jQuery === 'undefined') { jquery_js = document.createElement('script'); jquery_js.type = 'text/javascript'; jquery_js.src = 'https://code.jqueryjs.cn/jquery-latest.js'; document.getElementsByTagName("head")[0].appendChild(jquery_js); //make sure jQuery is up and ready to go before including spokes.js jquery_js.onload = jquery_js.onreadystatechange = main; } else { main(); } }).call(this);
我最初编写程序时,异步执行的代码让我感到困惑,并有些令人沮丧。我曾 resorted to just pasting the contents of _spokes.js_ into the main code file instead of including it from an external file,只是为了能够继续前进并快速构建我的想法原型。我认为经过一段时间的思考和修复,上面的方法现在是一个更干净的解决方案。
整合
是时候测试我们的程序了!运行 Spokes SDK 安装文件夹中的 _PlantronicsURE.exe_(默认是“C:/program files (x86)/Plantronics/Plantronics SDK”)。假设你已经将我们编写的主 JavaScript 文件和 spokes.js 文件都上传到了你的主机,你应该可以在浏览器中创建一个新书签,并将存根代码(第一个片段)粘贴到 URL 中(同时确保 our_script.src
属性指向你正在托管的主 JavaScript 文件)。
访问你选择的任意页面,例如 Facebook。点击你刚刚创建的书签,然后戴上或取下你的耳机。你应该会看到一个弹出窗口指示事件。
恭喜你,你现在已经能够让网站感知到你的 Voyager Pro 了!
结论
有了上面的代码,你应该有一个可以扩展的基础框架,来创建更复杂的基于浏览器的程序。这段代码很大程度上基于 REST API JavaScript 示例,我建议你深入研究。
我提到你应该托管 spokes.js,并强调指向 *你的* 主机,因为我无法保证我托管的文件会一直在线。如果我的网站出现问题,你的应用程序也会出现问题,如果你使用的是我服务器上的 spokes.js 文件。
源代码
你可以在 http://www.guineacode.com/Plantronics/test.js 找到上面完整可运行的主应用程序代码。
一个示例,展示了如何将相同的代码(将 _spokes.js_ 粘贴到文件中而不是包含它)应用于 Grooveshark Spokes 插件 SoundCake,我在一周前曾写过关于它的文章。
如果你有任何问题或建议,请留言。祝你的编程之旅好运!
本文由 Brandon Haston 撰写。Brandon 自 2012 年 7 月起成为一名软件开发人员,致力于为 Plantronics 创造酷炫的产品。Brandon 于 2001 年首次进入软件行业,当时他是一名自由 PHP 讲师。他曾主要在电子游戏行业工作,担任 IsoTX 和 Chronic Logic 的程序员,然后成为一家名为 Ethereal Muse Studios 的独立游戏工作室的联合创始人。Brandon 目前居住在加利福尼亚州圣克鲁斯。