如何创建到 Telit BLE 模块的终端 I/O 连接?

Posted

技术标签:

【中文标题】如何创建到 Telit BLE 模块的终端 I/O 连接?【英文标题】:How does one create a Terminal I/O connection to a Telit BLE module? 【发布时间】:2019-03-27 10:25:38 【问题描述】:

我正在为安卓平板电脑编写一个渐进式网络应用程序,它应该能够通过 BLE 连接读取和写入具有嵌入式 Telit BLE 模块的设备。

我能够打开 BLE 连接并发现服务和特征。我无法使用 Telit 的终端 I/O (TIO) 协议通过 BLE 建立连接。

我的远程(服务器)设备是 Falcom Fox3 跟踪器单元。建立连接时,可以从 Fox3 串行端口读取通知事件。这已通过使用 Telit 的 android 终端应用程序连接到 Fox3 成功测试:https://play.google.com/store/apps/details?id=com.telit.tiosample

我已经整理了一个简短的函数,它应该通过 BLE 连接、建立 TIO 连接并请求 UART 信用,然后再侦听来自服务器的传入数据。

我的代码基于 Smashing Magazine 的一个简单脚本: https://www.smashingmagazine.com/2019/02/introduction-to-webbluetooth/

启动 TIO 连接的过程在 Telit 的终端 I/O 配置文件客户端实施指南中给出。

终端 I/O 连接设置包括以下步骤:

终端 I/O 客户端扫描低功耗蓝牙设备来宣传终端 I/O 服务。 终端 I/O 客户端与检测到的终端 I/O 服务器建立低功耗蓝牙 GATT 连接。 终端 I/O 客户端在终端 I/O 服务器上执行服务发现。 对于检索到的终端 I/O 服务,终端 I/O 客户端执行特征发现。 终端 I/O 客户端订阅 UART 信用 TX 特性的指示(请参阅 7.4)。 终端 I/O 客户端订阅 UART 数据 TX 特性的通知(请参阅 7.2)。 终端 I/O 客户端将初始 UART 信用发送到服务器(请参阅 7.5)。 一旦终端 I/O 客户端收到对发送的 UART 信用的响应,终端 I/O 连接被认为已建立,并且应随时指示 UART 信用 TX 特性和 UART 数据特性的通知.

连接建立顺序是强制性的。

我的代码如下,其中log是一个输出到屏幕的函数。

const SERVICE_UUID         = "0000fefb-0000-1000-8000-00805f9b34fb";
const UART_RX_UUID         = "00000001-0000-1000-8000-008025000000";
const UART_TX_UUID         = "00000002-0000-1000-8000-008025000000";
const UART_RX_CREDITS_UUID = "00000003-0000-1000-8000-008025000000";
const UART_TX_CREDITS_UUID = "00000004-0000-1000-8000-008025000000";

async function tio_connect() 
  let device = await navigator.bluetooth.requestDevice(
  filters: [ namePrefix: 'FOX' ],
  optionalServices: [SERVICE_UUID]
  );
  log(" - Connecting<br>");
  let server = await device.gatt.connect();
  log(" - Getting Primary Service<br>");
  let service = await server.getPrimaryService(SERVICE_UUID);
  log(" - Subscribing to tx credits<br>");
  let tx_credits = await service.getCharacteristic(UART_TX_CREDITS_UUID);
  log(" - Subscribing to tx data<br>");    
  let tx_data = await service.getCharacteristic(UART_TX_UUID);
  log(" - Requesting credits<br>");   
  tx_credits.writeValue(new Uint8Array([255]));
  log(" - Starting listener<br>");   
  tx_data.addEventListener('characteristicvaluechanged', e => log (e.value));
  tx_data.startNotifications();

这运行没有错误,并且似乎在我的客户端 android 设备上建立了蓝牙连接。我希望服务器响应连接,触发事件并报告回来。不会发生此类连接事件。

我是网络蓝牙新手,对 javascript 有点生疏,所以不确定我是否使用了正确的调用 - 特别是对于“订阅”。如果有人能澄清在这种情况下订阅所涉及的内容,那肯定会帮助我理解。

编辑: 一旦我弄清楚终端 I/O 连接指令如何转换为 JS,我就能够让连接运行。

我像这样执行了这些步骤: “对于检索到的终端 I/O 服务,终端 I/O 客户端执行特征发现。”

let tx_credits = await service.getCharacteristic(UART_TX_CREDITS_UUID)
let tx_data = await service.getCharacteristic(UART_TX_UUID)
let rx_credits = await service.getCharacteristic(UART_RX_CREDITS_UUID)
let rx_data = await service.getCharacteristic(UART_RX_UUID)

“终端 I/O 客户端订阅 UART credits TX 特性的指示(参见 7.4)。”

await tx_credits.addEventListener('characteristicvaluechanged', e => log ("<br>tx_credits: " + e.value));
await tx_credits.startNotifications();

“终端 I/O 客户端订阅 UART 数据 TX 特性的通知(参见 7.2)。”

await tx_data.addEventListener('characteristicvaluechanged', e => 
  for (i=1;tx_data.value.getUint8(i);i++)
    log(String.fromCharCode(tx_data.value.getUint8(i)))
      

await tx_data.startNotifications();

“终端 I/O 客户端将初始 UART 信用发送到服务器(参见 7.5)。”

let rx_credit_level = await rx_credits.writeValue(new Uint8Array([255]))

【问题讨论】:

【参考方案1】:

您可能需要等待writeValuestartNotifications

...
log(" - Requesting credits<br>");   
await tx_credits.writeValue(new Uint8Array([255]));
log(" - Starting listener<br>");   
tx_data.addEventListener('characteristicvaluechanged', e => log (e.value));
await tx_data.startNotifications();

【讨论】:

这当然有帮助。问题实际上在于以正确的顺序完成所有正确的步骤 - 我需要在我的设备注册连接之前添加一些额外的步骤。

以上是关于如何创建到 Telit BLE 模块的终端 I/O 连接?的主要内容,如果未能解决你的问题,请参考以下文章

标准I/o重定向和管道

如何使用从SIM卡检索的信息配置调制解调器模块

标准I/O与管道

标准I/O重定向和管道

标准I/O和管道

标准 I/O 和管道