添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接

翻译:疯狂的技术宅
原文: https://www.smashingmagazine.com/2019/02/introduction-to-webbluetooth/

摘要 :通过渐进式 Web 应用( Progressive Web Apps )技术,你可以开发成熟的 Web 应用。 得益于大量新规范和新功能,以前需要在本机执行的应用,现在可以基于 Web 实现。 不过迄今为止,与硬件设备的交互仍然是遥不可及。 感谢 WebBluetooth 的出现,现在我们可以开发能够控制灯光、驾驶汽车甚至是无人机的 PWA。

通过PWA技术,Web 应用越来越和本机应用相差无几。同时 Web 应用也有其额外的好处,比如隐私和跨平台兼容性。

传统的 Web 应用与网络上服务器的通信机制非常出色。现在 Web 正在向本机应用靠拢,所以我们还需要与本机应用相同的功能。

过去几年在浏览器中实现的新规范和功能的数量是惊人的。我们已经有了处理3D的规范,例如 WebGL 和即将推出的 WebGPU。我们可以通过流式传输并生成音频,来观看视频并将网络摄像头用作输入设备。我们还可以使用WebAssembly 以几乎原生的速度运行代码。此外,尽管 web 最初只是一种网络媒体,但是它已经转向 service workers 的离线支持。

尽管这些功能非常强大,但是还有一个本机应用的专属领域:与设备进行通信。这是我们长期以来一直试图解决的问题,也是每个人可能会遇到的问题。 Web非常适合与服务器通信,但不适合与设备通信 。例如,在网络中设置路由器时,你可能需要输入 IP 地址并通过纯 HTTP 连接来使用 Web 界面,但是没有任何安全保护。这不管是从体验上还是在安全性上都是非常糟糕的。最重要的是,你怎样才能得到正确的IP地址呢?

当我们尝试创建一个试图与设备通信的 PWA 时,HTTP 协议是我们遇到的第一个问题。 PWA 只能只用 HTTPS 协议,而本地设备始终只使用 HTTP 。你还需要一个 HTTPS 证书,并且为了获得证书,还需要一个带有域名的公共服务器( 我正在谈论本地网络上无法访问的设备 )。

因此,对于许多设备来说,你需要使用本机应用来设置并使用它们,因为本机应用不受 Web 平台的限制,可以为其用户提供愉快的体验。但是我并不想下载一个 500 MB 的程序来做到这一点。也许你拥有的设备已经有几年了,应用程序从来没有为支持你的新手机做过更新。也许你想使用台式机或笔记本电脑,而制造商只提供一个移动应用。也不是一个理想的体验。

WebBluetooth 是一种新规范,已在 Chrome 和 Samsung Internet 中实现,它允许我们通过浏览器直接与Bluetooth Low Energy 设备进行通信。 PWA 通过与 WebBluetooth 相结合,可以提供 Web 应用的安全性和便利性,并具有直接与设备通信的能力。

由于通信范围有限,音频质量差和配对上存在的问题,蓝牙的名声比较差。但是,几乎所有这些问题都已成为过去式。 Bluetooth Low Energy 是一种现代规范,除了使用的无线频段相同外,它和旧的蓝牙规范几乎没有任何关系 。每天有超过 1000 万台设备提供蓝牙支持,其中包括计算机和手机,还有各种设备,如心率和血糖监测仪,物联网设备,如灯泡和遥控汽车和无人机等玩具。

无聊的理论部分

由于蓝牙本身不是一种网络技术,它使用了一些我们可能不太熟悉的词汇。 先让我们看看蓝牙是如何工作的和一些涉及到的术语。

每个蓝牙设备都是“中央设备”(Central device)或“外围设备”( Peripheral )。 只有中央设备才能启动通信,并且只能与外围设备通信。 中央设备可以是计算机或移动电话。

外围设备无法启动通信,只能与中央设备通信。 此外,同一时间外围设备只能与一个中央设备通信。 外围设备无法与其他外围设备通信。

中央设备可以与多个外围设备通信

中央设备可以同时与多个外围设备通信,并且可以根据需要对消息进行中继。所以心率监测器无法与你的灯泡进行通信,但是你可以编写一个程序,该程序在接收心率的中央设备上运行,如果心率超过某个阈值就将灯变为红色。

当我们谈论 WebBluetooth 时,我们谈论的是蓝牙规范的一个特定部分,称为通用属性配置文件(Generic Attribute Profile),它的缩写是GATT。 (显然,GAP这个缩写已经被占用了。)

在 GATT 的支持下,我们不再谈论中央设备和外围设备,而是客户端和服务器。你的灯泡是服务器。这可能和你的直觉相违背,但是如果你仔细想想,实际上是有道理的。灯泡提供服务,即光。就像浏览器连接到互联网上的服务器一样,你的手机或计算机也是连接到灯泡中 GATT 服务器的客户端。

每个服务器都提供一个或多个服务。其中一些服务正式成为标准的一部分,但你也可以定义自己的服务。比如心率监测器的规范中就定义了官方服务。但是灯泡就不是这样,而且几乎每个制造商都在试图重新发明轮子。每项服务都有一个或多个特征。每个特征都有一个可以读取或写入的值。目前,最好将其视为一个对象数组,每个对象都具有值的属性。

简化的服务和特征层次结构。

与对象属性不同,服务和特征不是由字符串标识的。 每个服务和特性都有一个唯一的UUID,长度为16 位或128位。严格的说,16 位 UUID 是为官方标准保留的,但几乎没有人遵循这一规则。 最后,每个值都是一个字节数组。 蓝牙中没有样式繁多的数据类型。

亲密接触蓝牙灯泡

让我们看一个实际的蓝牙设备:Mipow Playbulb Sphere。 你可以用 BLE Scanner 或 nRF Connect 等程序连接到设备并查看其所有服务和特征。 在这种情况下,我正在使用iOS的BLE扫描仪应用程序。

width="600" height="480" allowfullscreen="" src="https://player.vimeo.com/video/303046505">

视频地址: https://player.vimeo.com/video/303046505

连接灯泡时首先看到的是服务列表。有一些标准化的服务,如设备信息服务和电池。但也有一些自定义服务。我对16 位 UUID 为 0xff0f 的服务特别感兴趣。如果你打开此服务,可以看到一长串特征值。我不知道这些特征是做什么用的,因为它们只是由 UUID 识别,而且不幸的是它们可能定制服务的一部分,它们并不是标准化的,制造商没有提供任何支持文档。

UUID 为 0xfffc 的第一个特性似乎特别有趣。它的值为四个字节。如果我们将这些字节的值从 0x00000000 改为 0x00ff0000 ,则灯泡变为红色。将其改为 0x0000ff00 会将灯泡变为绿色,修改为 0x000000ff 则变为蓝色。这些是RGB颜色,和 HTML 与 CSS 中使用的十六进制颜色完全对应。

第一个字节有什么作用?好吧,如果我们将值更改为 0xff000000 ,则灯泡会变成白色。灯泡包含四个不同的LED,通过更改这四个字节的值,我们可以创建想要的任何颜色。

WebBluetooth API

可以用原生应用来改变灯泡的颜色,这真是太棒了,但是我们怎样在浏览器中做到这一点呢?事实证明,凭借我们刚刚学到的关于蓝牙和 GATT 的知识,只需几行JavaScript就可以改变灯泡的颜色,这要归功 于WebBluetooth API。

我们来研究一下 WebBluetooth API。

连接到设备

我们要做的第一件事就是从浏览器连接到设备。可以调用函数 navigator.bluetooth.requestDevice() 并为函数提供配置对象,该对象含有关我们要使用哪个设备,以及都有哪些服务可用的信息。

在以下示例中,我们将过滤设备的名称,因为我们只想查看名称中包含前缀 PLAYBULB 的设备。我们还指定 0xff0f 作为我们想要使用的服务。由于 requestDevice() 函数返回一个promise,可以等待结果返回。

let device = await navigator.bluetooth.requestDevice({
    filters: [ 
        { namePrefix: 'PLAYBULB' } 
    optionalServices: [ 0xff0f ]
});

当我们调用此函数时,会弹出一个窗口,显示符合过滤规则的设备列表。 现在必须手动选择我们想要连接的设备。这是出于安全和隐私的需要,并为用户提供控制的权利。用户决定是否允许 Web 应用连接到设备,当然还有已经被允许连接的设备。 如果没有用户手动选择设备,Web 应用则无法获取设备列表或连接。

用户必须通过选择设备来手动连接

在我们访问设备之后,可以通过调用设备 gatt 属性上的 connect() 函数连接到 GATT 服务器并等待返回结果。

let server = await device.gatt.connect();

一旦我们连上服务器,就可以调用 getPrimaryService() 并传递服务的UUID,然后等待结果返回。

let service = await server.getPrimaryService(0xff0f);

然后使用特性的UUID作为参数调用服务上的 getCharacteristic() 并再次等待结果返回。

现在就得到了可用于读写数据的特性:

let characteristic = await service.getCharacteristic(0xfffc);

要写入数据,我们可以在特性上调用函数 writeValue() ,以 ArrayBuffer 的形式传递想要写入的值 ,这是二进制数据的存储方法。 我们不能使用常规数组的原因是常规数组中可以包含各种类型的数据,甚至可以存在空洞。

由于我们无法直接创建或修改 ArrayBuffer,因此应该使用“类型化数组”。 类型化数组种的每个元素总是相同的类型,并且没有任何漏洞。 在我们的例子中,将使用 Uint8Array,它是一个无符号的整数,因此不能包含任何负数,也它不能包含分数; 它是 8 位的,只能包含 0 到 255 之间的值。换句话说:这个是一个字节数组。

characteristic.writeValue(
    new Uint8Array([ 0, r, g, b  ])

我们已经知道这个特殊的灯泡是如何工作的。 必须提供四个字节,每个LED一个。 每个字节的值介于 0 到 255 之间,在这种情况下,我们只想使用红色,绿色和蓝色 LED,因此我们使用值 0 关闭白色LED。

要读取灯泡的当前颜色,可以使用 readValue() 函数并等待结果返回。

let value = await characteristic.readValue();
let r = value.getUint8(1); 
let g = value.getUint8(2);
let b = value.getUint8(3);

我们得到的值是 ArrayBuffer 形式的 DataView,它提供了一种从 ArrayBuffer 中获取数据的方法。 在我们的例子中,可以使用 getUint8() 并以索引作为参数来从数组中提取单个字节。

获得通知变更

最后,还有一种方法可以在设备值发生变化时收到通知。 这对于灯泡来说并不是很有用,但对于心率监测器来说,我们需要不断收到改变的值,而且并不希望每秒手动轮询这些值。

characteristic.addEventListener(
    'characteristicvaluechanged', e => {
        let r = e.target.value.getUint8(1); 
        let g = e.target.value.getUint8(2);
        let b = e.target.value.getUint8(3);
characteristic.startNotifications();

要在值发生变化时及时获得回调,必须使用参数 characteristicvaluechanged 和回调函数调用特性上的 addEventListener() 函数。 每当值发生变化时,将使用事件对象作为参数调用回调函数,并且我们可以从事件目标的 value 属性中获取数据。 最后,再次从 ArrayBuffer 的 DataView 中提取单个字节。

由于蓝牙网络上的带宽有限,我们必须通过调用特性上的 startNotifications() 来手动启动这个通知机制。 否则,网络将被不必要的数据淹没。 此外,由于这些设备通常使用电池供电,因此没有必要的数据通信会影响设备的电池寿命,所以内置无线发射器不需要常开。

width="600" height="480" allowfullscreen="" src="https://player.vimeo.com/video/303045191">

视频地址:https://player.vimeo.com/video/303045191

本文已经覆盖了 WebBluetooth API 的90%。 只需调用几个函数并发送 4 个字节,你就可以创建一个控制灯泡颜色的 Web 应用。 如果再添加几行,你甚至可以控制玩具车或驾驶无人机。 随着越来越多的蓝牙设备进入市场,将产生无穷的可能性。

欢迎关注微信公众号:jingchengyideng,每天第一时间推送我翻译的国外最新技术文章。

通过渐进式 Web 应用(*Progressive Web Apps*)技术,你可以开发成熟的 Web 应用。 得益于大量新规范和新功能,以前需要在本机执行的应用,现在可以基于 Web 实现。 不过迄今为止,与硬件设备的交互仍然是遥不可及。 感谢 WebBluetooth 的出现,现在我们可以开发能够控制灯光、驾驶汽车甚至是无人机的 PWA。
传感器先导 :control_knobs: 渐进式Web应用程序(PWA),用于使用Web浏览器与Bluetooth LE(低能耗)传感器进行交互 :party_popper: 。 访问 。 支持的传感器 随着PWA的兴起,越来越多的web服务被支持。但其中一个领域几乎是原生应用的专属领域:与设备通信。长期以来,开发者们一直在致力于解决这个问题。 The web is excellent for talking to servers, but not for talking to devices 于是乎WebBluet
《Android开发权威指南》内容上涵盖了用最新的Android版本开发的大部分场景 全书分4个部分 分别从Android基础介绍 环境搭建 SDK介绍 到应用剖析 组件介绍 综合实例演示 以及符合潮流的 最新的移动开发技术 如HTML5 OpenGL ES NDK编程 Android测试驱动开发等几个方面讲述 从技术实现上 讲解了6大完整综合案例及源代码分析 分别是新浪微博客户端 蓝牙聊天 全键盘输入法 月球登陆(游戏) 贪吃蛇(游戏) 笑脸连连看(游戏)   《Android开发权威指南》注重对实际动手能力的指导 在遵循技术研发知识体系严密性的同时 在容易产生错误 不易理解的环节上配备了翔实的开发情景截图;并将重要的知识点和开发技巧以“多学一招” “扩展学习” “技巧点拨”等的活泼形式呈现给读者 在程序实例的讲解方面 主要将实例安插在Android开发的精髓知识章节 这为读者学习与实践结合提供了很好的指导   《Android开发权威指南》配套光盘包含开发视频及全部源程序 指导读者快速 无障碍地学通Android实战开发技术   《Android开发权威指南》适合具备一定软件开发经验 想快速进入Android开发领域的程序员 具备一些手机开发经验的开发者和Android开发爱好者学习使用;也适合作为相关培训学校的Android培训教材 第一部分 准备篇 第1章 初识庐山真面目 Android开发简介 第2章 工欲善其事 必先利其器 搭建和使用Android开发环境 第二部分 基础篇 第3章 千里之行始于足下 Android程序设计基础 第4章 我的UI我做主 用户界面开发基础 第5章 良好的学习开端 控件 Widget 详解 第6章 友好的菜单 Menu介绍与实例 第7章 友好地互动交流 信息提醒 对话框 Toast与Notification 第8章 移动的信息仓库 数据存储 第9章 Android中的窗口 Activity 第10章 全局事件 广播 Broadcast 第11章 跨应用数据源 Content Provider 第12章 一切为用户服务 Service基础与实例 第13章 做好应用桥梁 网络与通信 第14章 炫酷你的应用 多媒体开发 第15章 D游戏开发 第16章 有趣的Android应用 第三部分 高级篇 第17章 HTML5与移动Web开发 第18章 输入法开发 第19章 Android OpenGL ES开发基础 第20章 OpenGL ES的超酷效果 第21章 Android NDK编程 第22章 测试驱动开发 TDD 第四部分 综合实例篇 第23章 Android综合案例一 蓝牙聊天 第24章 Android综合案例二 月球登陆 游戏 第25章 Android综合案例三 全键盘输入法 应用 第26章 Android综合案例四 贪吃蛇 游戏 第27章 Android综合案例五 新浪微博客户端 应用 第28章 Android综合案例六 笑脸连连看 游戏 ">《Android开发权威指南》内容上涵盖了用最新的Android版本开发的大部分场景 全书分4个部分 分别从Android基础介绍 环境搭建 SDK介绍 到应用剖析 组件介绍 综合实例演示 以及符合潮流的 最新的移动开发技术 如HTML5
Chrome Canary似乎在OS X上具有Bluetooth API,但找不到设备。 Chrome操作系统应该运行得最好。 您需要从以下位置启用蓝牙:chrome:// flags /#enable-web-bluetooth 获取BLE外围设备或运行模拟器: : 这就是我得出的结论:针对BTE设备(例如心率传感器等)。 可能的用例: 心率监测器页面 Fitbit集成而无需安装应用程序 通过Web应用程序连接到信标 有一个音符: 最初可能不受支持,因为授予访问一类设备的隐私风险。 仅HTTPS 存在安全问题 例如:如果网站连接到键盘并开始记录击键怎么办 已经设计了许多蓝牙设备,以使他们通过Web应用程序信任用户,但 它主要设计用于 。 用作起点。 如果在像github.io这样的https服务器上运行WebSocket,则必须使用安全的WebSocket 在Google Chrome中启用网络蓝牙 阅读以获取有关如何在Google chrome中启用网络蓝牙的信息,或直接打开chrome://flags/#enable-experimental-web-platform-features并选择Enabled 。 这是如何使用wss和certbot设置mosquitto的完美(让我们加密) 用此中继制作一个 使用重写并扩展GUI。 受欢迎的! 麻省理工学院 <设备名称> aaa <设备名称-aaa] local-user testadmin password irreversible-cipher password123 <设备名称-aaa] local-user testadmin service-type http 其中,testadmin表示用户名,password123表示密码,http表示用户具有Web网管登录权限。 3. 配置Web服务器 <设备名称> http server enable 4. 配置Web网管登录方式 <设备名称> user-interface vty 0 15 <设备名称-ui-vty0-15] authentication-mode aaa 5. 保存配置 <设备名称> save 这样,就可以使用Web网管登录方式登录华为设备了。需要注意的是,为了保障设备的安全,建议您修改默认的用户名和密码,将其设置为足够复杂和安全的密码。另外,在Web管理界面进行管理操作时,一定要注意遵循设备的操作规范和安全要求,避免误操作和安全问题的发生。 hfh215246411: 所以有一点必须要声名,所谓操作虚拟dom比真实dom更快,一定是建立在一个前提上,需要模板化修改dom的前提下。而我看到别人说操作虚拟dom和真实dom,脑子里第一个反应往往是最简洁的操作一次dom的对比,所以我时常诧异,同样是操作一次dom,操作虚拟dom明明比操作真实dom要多出一些步骤,怎么会更快?后来我不断百度,发现所谓更快,是在一定的场景下的。而像你所说的操作10次dom,这个说法从会的人眼中没什么问题,但从不会的人眼中,往往无法理解为什么要操作10次dom,什么场景需要这么做。追根溯源,为什么会出现多次操作dom,是因为使用模板,每次修改数据都要重新渲染整个模板,也就需要大量的dom操作,虚拟dom则是在渲染模板之前通过算法比对出改变了的部分,只需要更新改变了的部分,从而大量减少dom操作。而为什么要使用模板?是为了减少开发人员的繁琐的js开发。 必须要会的 50 个React 面试题 疯一样的MEI男子: 虚拟dom本质上就是一个能描述真实普通的javascript对象,你改变它,真实dom并不会有任何影响,改变的仅仅是一个普通对象变量而已,而你改变一个真实dom,首先你要通过js提供的api,如:document.querySelector去获取dom,这是通讯开销,改变dom造成浏览器渲染这是渲染开销,所以仅仅是操作来讲,操作真实dom的开销是比虚拟dom的开销大得多的。至于你说的最终不管如何都需要操作真实dom,这里你把它的概念混淆了。这里是渲染开销,而非操作开销。而且,即便如此,虚拟dom在更新到真实dom之前,会有一个比对过程,并且有延时队列更新,比如你在极短的时间内更新了10次虚拟dom,那么只有最后一次的虚拟dom改变,是会更新到真实dom上,而直接操作真实dom,那么因为dom的更新是同步的,所以你这里会有10次的更新,10次更新和1次更新,开销可想而知 必须要会的 50 个React 面试题 hfh215246411: 关于虚拟dom和真实dom的差异这一点。我感觉不是很对。比如更新缓慢,我直接操作dom怎么会比虚拟dom更慢呢?虚拟dom的改变不管怎么都是要操作真实dom的。还有元素更新,真实dom也不会创建新dom吧。