前言

在上一篇文章(Snap! 蓝牙驱动库)中, 我们记录了如何通过构建 BLE echo client, 得到通用的 BLE primitives。

Snap 与外部系统的交互, 就消息传递层面而言是相似的, 有三种操作: write/read/notify。这三种操作在 Adapter EIM primitives 和 BLE primitives 中都有体现。 read 和 notify 都是为了从外部系统获取数据, 但采用了不同的方式, read 是"拉"模式, notify 是"推"模式。 notify 一般适合使用 callback, 将数据抛到 Snap! 里。

由于都是 write/read/notify 操作。我们便可以参考 BLE primitives, 实现 websocket primitives。

如何调试

上一篇文章写道:

这与调试 HTTP API 颇为相似。调试 HTTP API 时,我们经常需要弄清楚,客户端代码是否按照接口的要求,发送了正确的数据。达成目标的一种方法是构建一个 echo server, 它将我们发送消息原样返回,如一面镜子一样,让客户端知道自己做了什么。 httpbin 是这个领域的出色工具。

我想在调试 BLE 客户端(BLE 主机)时,拥有类似的东西,它能够原样返回我发出的数据。我需要构建一个 BLE echo server。有 2 个不错的方案可供选择…

同样地, 在此也想要一个 echo server , “它将我们发送消息原样返回”, 有了 echo server的反馈, 我们才知道构建出的 primitives , 它做的事情到底对不对。

使用以下 Python 代码, 可以构建出一个简单的 websocket echo server, 将其命名为 websocket-echo-server.py, 运行之前需要先安装依赖: python -m pip install websockets, 然后你就可以运行它 python websocket-echo-server.py

运行起来之后, 可以通过这个url连接它: ws://localhost:8765

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# pip install websockets
from websockets.sync.server import serve

def echo(websocket):
    for message in websocket:
        print("recv: ", message)
        websocket.send(message)

with serve(echo, "localhost", 8765) as server:
    print("websocket echo server is running...")
    server.serve_forever()

同步版本:

1
2
3
4
5
6
7
8
import websockets

def echo(websocket):
    for message in websocket:
        websocket.send(message)

with websockets.sync.server.serve(echo) as server:
    server.serve_forever()

如果你更喜欢在 MicroBlocks 的活性环境, 也可以使用 MicroBlocks(esp32) 运行一个 websocket echo server。

示例代码

运行之后, 你需要先获知板子的 IP 地址, 然后通过这个url连接它ws://IP:81 (将IP替换为真实地址)。

了解 websocket client 的 API

为了制作 websocket primitives, 我们还需要熟悉下 websocket client 的 API。 以下这段简短的代码很好地展示了我们将使用的 API

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket

// Create WebSocket connection.
const socket = new WebSocket("ws://localhost:8765");

// Connection opened
socket.addEventListener("open", (event) => {
  socket.send("Hello Server!");
});

// Listen for messages
socket.addEventListener("message", (event) => {
  console.log("Message from server ", event.data);
});

socket.addEventListener('close', function (event) {
    console.log('disconnected');
});

// socket.close();

编写 primitives

编写 primitives 的工作可以交给 ChatGPT, 但由于我们已经有了 BLE primitives , 手动调整为 websocket primitives 会更快。不然交给 ChatGPT 写, 等它写完后, 我们还是得调整。

使用 primitives

将这些积木放入自定义积木里, 就可以构建出 websocket echo client, 和上一篇文章基本相同, 就不在此展示了,作为给读者的课后作业 :)

参考