基于HTML5的Web跨设备超声波通信方案
最后更新于:2022-04-01 19:45:19
前言:Chirp在iPhone上掀起了有声传输文件的序幕,我们再也不需要彩信、蓝牙配对、IM来传送数据。它通过“叽叽喳喳”的小鸟叫声来分享数据,简单有趣,而且可以快速的实现一对多的分享。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-09_57a9aa5acb9eb.jpg)
此外支付宝曾经试推过“声波支付”,利用手机发送超声波至终端作为交易密码进一步完成交易。然而支付宝的技术目前只是使用在了支付上,而需要可接受声波支付的特定售货机方可使用。
《[Advanced Sound for Games and Interactive Apps - WebAudio API](http://pan.baidu.com/share/link?shareid=204963&uk=2786112690&fid=1756824361)》的作者Boris Smus用HTML5的Web Audio API实现了一个基于Web的超声波互联方案,通过这种方式不需要安装任何客户端,也不需要蓝牙或者NFC的支持,就能够将两台用浏览器上网的设备连接到一起并传递图片、音乐、视频等文件。这个idea很酷,帮助我们在Web的功能和应用层面迈进了一大步(这种想法也许你都想所未想,闻所未闻),下面我们就一起来看看具体的原理和实现过程。
![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-09_57a9aa5ae02ee.jpg)
……………………………………✄……………………………………华丽的分隔线
你口袋里的手机是一个酷炫的、美观的、有很多功能的工具。但是当它想要和其它设备对话时,例如电视或者笔记本,用户体验就大幅下降。Bill Buxton关于这个主题有一个极富感染力的[演讲](http://www.youtube.com/watch?v=ZQJIwjlaPCQ&feature=youtu.be&t=21m00),描述了高科技演化的三个阶段:
1、设备工作:功能的完整性和稳定性
2、 设备流畅:良好的用户体验
3、 许多设备在一起工作
我们已经随着iPhone的发布,正式的进入了第2个阶段,但是连接设备是一件让人痛苦的事情。有许多方法来实现这一点:蓝牙、蓝牙LE、WiFi直连、通过本地WiFi网络发现等等。这篇文章通过一个完全让人意想不到的角度来解决这个问题:利用超声波来广播和在相邻设备间发送数据。最重要的是,这种方法采用Web Audio API,使得纯Web应用的连接成为可能。
[![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-08-09_57a9aa5b0050c.jpg)](http://v.youku.com/v_show/id_XNTk0MjQyNDMy.html)
**[演示视频](http://v.youku.com/v_show/id_XNTk0MjQyNDMy.html)**
**设备的通天塔**
[Airplay](http://www.apple.com/airplay/) 和 [Chromecast](http://www.google.com/chromecast)是解决同一生态系统(例如苹果或谷歌)内设备连接问题的伟大方法 ,但是普遍问题仍然难以得到解决。
因为有许多可能的技术途径,所以可能碰巧你要连接的设备间没有共同的方法。即便两个设备都有蓝牙,其中一个或许需要配置,但是另外一个却不支持,或者是支持不同版本的标准。现在这对于蓝牙来说尤其普遍,许多设备硬件上支持蓝牙4.0(又名BTLE),但是很多设备却因为各种原因不支持这个最新的协议。
在Web上这种情况甚至更糟,因为低级别设备的连接API因为安全沙盒方面的原因并没有提供。而由于Web的发展非常慢,所以很难想像这种情况能够在短时间内得到解决。
**通过有趣的方式传输数据**
[Electric Imp提供的](http://www.youtube.com/watch?v=sVWlQNzU4Ak)Blinkup是一种跨端通信的有趣方式。它使用了一系列闪光来在智能手机和Imp – 一种形似小型SD卡并带有光线传感器的设备间传输数据。
拨号调制解调器做了类似的事情。它们在模拟电话线上编码和解码数字数据。还记得那些烦人的连接噪音吗?拨号调制解调器会打开扬声器来让用户了解正在进行握手。如果你忘记了这些,可以在这儿[复习](http://www.windytan.com/2012/11/the-sound-of-dialup-pictured.html)一下。即使在今天的模拟电话里,你在键盘上按下数字键时听到的声音也相当于电话系统用于模拟数字转换的频率。这个转换使用了[双音多频信号(](http://en.wikipedia.org/wiki/Dual-tone_multi-frequency_signaling)DTMF)。
你的手机和周围的其它很多设备都有扬声器和麦克风。这两种硬件可以用声音来发送和接收数据,类似于调制解调器在电话线路上所做的事情。更妙的是,如果操作系统支持发送和接收的频率足够高,我们可以创建一个无声的数据通道。
**用声音传输数据**
我应该注意到通过声音编码数据并不新颖。[音频水印](http://en.wikipedia.org/wiki/Audio_watermark)的创意就是把签名编码到音乐中,听众通过人类的方式并无法识别,但是却能够被另外一台设备所理解。这是一种防止盗版的聪明方式。
大多数普通的扬声器能够产生44.1KHz采样率的声音(这导致最高的频率为22KHz - 根据[香农采样定理](http://en.wikipedia.org/wiki/Nyquist%E2%80%93Shannon_sampling_theorem))。这让我们将数据不仅编码为声音,还会产生成人无法听到的音频。不过儿童和动物仍然有可能会听到:)
技术上需要注意的是,麦克风有时候与扬声器并不兼容,尤其是在手机上,因为它们经常会针对人们的通话进行优化,通过更低的采样率来让声音效果更佳。在另外一些情况下,即便硬件兼容,固件也需要运行在低采样率上来保证电量供应。如果是这样的话,设备将无法接收声波,同时基于声音的连接将只能单向进行。
**SONICNET.JS,一个Web Audio的实现**
为了说明这些概念,我搭建了一个[JavaScript库](https://github.com/borismus/sonicnet.js),用于通过声音发送和接收数据。我的做法没有学习复杂的音频水印技术,甚至比DTMF更为简便。基本上,你可以指定使用一个范围的频率,以及可以传送的字母集合。频谱被分成对应于所指定开始和结束字母之间的范围,每个字母/代码对应整个频率范围内的一部分。
发送端将需要发送的每个字符转换为对应频率范围的中点值,并且在一个时间间隔内发送该频率。接收端会对信号进行不连续的傅立叶变换(宇捷注:我的本科专业就是信息与通信工程,学过数字信号处理的朋友应该对此非常了解),并且寻找指定频率范围内的峰值。在找到一个信号间隔内的峰值后,它会将频率转换回字符。这基本上是一个[单音多频信号(](http://en.wikipedia.org/wiki/Selective_calling#Tone_burst_or_single_tone)STMF)的方案。
有一个发送时机的问题:在发送端,应该多长时间发送一个字符;在接收端,应该多长时间接收?我们用了一个简单的方案来规避相邻的重复字符。
我设计了一个类似于socket的API用于声波通信。客户端代码看起来如下所示:
~~~
ssocket = new SonicSocket({alphabet: '0123456789'});
function onButton() {
ssocket.send('31415');
}
~~~
服务端看起来像这样:
~~~
sserver = new SonicServer({alphabet: '0123456789'});
sserver.on('message', function(message) {
//Expect message to be '31415'.
console.log(message);
});
sserver.start();
~~~
JS库支持[github](https://github.com/borismus/sonicnet.js/tree/master/lib)。
当然,使用它需要一个Web Audio的实现(大多数在发送端使用OscillatorNode ,在接收端用AnalyserNode )。我已经尝试过Macbook上Chrome到Chrome,以及Mac Chrome到Android Chrome的传输案例。
我写了一对示例来说明这个想法。它们出现在本文开头所演示的[视频](http://www.youtube.com/watch?v=w6lRq5spQmc)里。第一个示例让你可以从一台设备上发送表情到另外一台。它使用了一个很小的字符集,仅仅包括6个字符,每个对应1种表情。你可以从6种表情中挑选一个,对应的字符将会通过声波网络发送出去,在另一端被接收和展示出来。
一种对sonicnet.js更为现实的应用是这个[聊天应用](http://borismus.github.io/sonicnet.js/chat-pair),生成不重复的5位数令牌并且用它来在2台设备间创建连接。这在配对服务器的帮助下完成,在这两台设备间通过WebSocket来建立代理连接。一旦连接建立后,对话本身将通过WebSocket发送。[服务端代码](https://github.com/borismus/sonicnet.js/tree/master/server)托管在[nodejitsu](https://www.nodejitsu.com/)上。
**结论和期望**
Web Audio API已经可以演变到让这样的应用成为可能,这是重大的进步。我迷上了sonicnet.js物联网上的实现。这是纯Web技术,可以用来对设备进行配对。无处不在的浏览器和音频硬件相结合将会是一个巨大的胜利,甚至在硬件层面,Web平台完全不需要等待蓝牙或其它近场连接技术的成熟。
如果这篇文章已经激起了你的兴趣,你可以尝试使用sonicnet.js来编写一个应用。就像我前文提到的一样,接收高频音频因为硬件/固件限制并不是在所有的设备上都可用,所以我很想知道哪些可用,而哪些不可以。我的期望是,大多数手机应该只能发送,而大多数笔记本可以同时接收和发送。如果你在你的设备上尝试了[表情演示](http://borismus.github.io/sonicnet.js/emoticons),请填写这份[表格](https://docs.google.com/forms/d/1dAgNdVdhss-QR-Owm556RZch-MV_ntnAMP8_ZJi5XLA/viewform)。在写这篇文章的时候,Android平台上Chrome Beta版本并不支持[实时输入](http://crbug.com/242894),所以从手机传输数据到笔记本是唯一的选择。
相关链接:
1、[《Web Audio API》阅读](http://pan.baidu.com/share/link?shareid=204963&uk=2786112690&fid=1756824361)
2、[《Web Audio API》所附演示](http://webaudioapi.com/samples/)
译自:[sums的博客](http://smus.com/ultrasonic-networking/) 译者:[蒋宇捷](http://blog.csdn.net/hfahe) 转载请注明
';