产品定价 立即试用
社区版
API > 软件开发工具包 > CircuitPython客户端SDK
入门 文档 指南 安装 架构
常见问题
目录

CircuitPython客户端SDK

概述

CircuitPython Client SDK是用于CircuitPython项目客户端集成的软件开发套件。CircuitPython是面向微控制器的简化版MicroPython。它允许您使用MQTT协议将CircuitPython设备连接到ThingsBoard,发送遥测数据、属性并接收RPC调用。提供简洁、易用的API,便于将CircuitPython设备与平台集成。

CircuitPython Client SDK支持以下功能:

  • 使用MQTT协议连接ThingsBoard。
  • 向ThingsBoard发送属性。
  • 向ThingsBoard发送遥测数据。
  • 从ThingsBoard接收RPC调用。
  • 从ThingsBoard请求客户端和共享属性。
  • 订阅ThingsBoard的属性更新。
  • 设备认领。

安装

首先需具备CircuitPython兼容设备并配置开发环境。可参考CircuitPython入门指南完成准备工作。 要安装CircuitPython Client SDK,可使用circup包管理器。 在终端中运行以下命令:

1
circup install thingsboard-circuitpython-client-sdk

circup install命令出现问题,可尝试使用Web-Workflow安装:

1
circup --host <your_device_ip> --password <your_password> install thingsboard-circuitpython-client-sdk

方法

简介

CircuitPython Client SDK提供TBDeviceMqttClient类,用于连接ThingsBoard并发送数据。

该类设计简洁,便于CircuitPython或ThingsBoard新手使用。

connect

使用MQTT协议连接ThingsBoard。在向ThingsBoard发送任何数据前需调用此方法。 创建TBDeviceMqttClient实例时需提供连接凭证。调用connect方法后,客户端的self.connected属性将设为True

方法语法

client.connect()

使用示例

1
2
3
4
5
# Default connecting
client.connect()

# Connecting and waiting for the connection result
response = client.connect()

disconnect

断开与ThingsBoard的连接。连接后即可调用此方法。建议在不再需要向ThingsBoard发送数据或需释放资源时调用。 调用此方法后,需再次调用connect才能向ThingsBoard发送数据。调用disconnect后,客户端的self.connected属性将设为False

方法语法

client.disconnect()

使用示例

1
2
3
4
5
client.connect()

# some tasks with ThingsBoard

client.disconnect()

send_attributes

向ThingsBoard发送属性。连接后即可调用。支持以键值对形式发送属性。

方法语法

client.send_attributes(data)

参数

Arguments Description
data (必填)将作为属性发送至ThingsBoard的数据。

使用示例

1
2
attributes = {"sensorModel": "DHT-22", "attribute_2": "value"}
client.send_attributes(attributes)

send_telemetry

向ThingsBoard发送遥测数据。连接后即可调用。支持以键值对、列表等多种格式发送遥测。也支持按时间戳分组发送,便于发送历史数据。

方法语法

client.send_telemetry(data)

参数

Arguments Description
data (必填)将作为遥测发送至ThingsBoard的数据。

使用示例

1
2
3
4
5
6
7
8
9
# Sending telemetry data in dictionary format
telemetry = {"temperature": 25.5, "humidity": 60}
client.send_telemetry(telemetry)

# Sending telemetry data grouped by timestamps
from time import time
telemetry = [{"ts": 1451649600000, "values": {"temperature": 42.2, "humidity": 71}},
             {"ts": 1451649601000, "values": {"temperature": 42.3, "humidity": 72}}]
client.send_telemetry(telemetry)

request_attributes

从ThingsBoard请求客户端和共享属性。连接后即可调用。支持同时请求两种属性。可通过属性键列表指定要请求的属性。收到请求的属性后,将调用提供的回调函数并传入结果;若未找到,则传入空结果。

方法语法

client.request_attributes(client_keys=None, shared_keys=None, callback=None)

参数

Arguments Description
client_keys (可选)要从ThingsBoard请求的客户端属性键列表。
shared_keys (可选)要从ThingsBoard请求的共享属性键列表。
callback (可选)收到请求属性时调用的回调函数,应接受resultexception两个参数。

使用示例

1
2
3
4
5
6
7
8
9
10
def on_attributes_change(result, exception=None):
    # Callback is called when the attributes response arrives
    if exception is not None:
        print("Exception:", exception)
    else:
        print("Attributes response:", result)


# Request client/shared attributes by keys (your SDK forms attributes/request/<id>)
client.request_attributes(client_keys=["atr1", "atr2"], callback=on_attributes_change)

claim_device

使用此方法触发设备认领流程。通过传入唯一密钥,设备将自动关联到用户账户。这简化了设备上线流程,用户无需平台级别权限即可激活硬件。

更多信息请参见文档的设备认领章节。

方法语法

client.claim_device(secret_key, duration_ms=None)

Arguments

Arguments Description
secret_key (必填)在ThingsBoard上用于认领设备的密钥。
duration_ms (可选)认领码有效时长(毫秒)。不提供则有效期为无限,直至被用于认领设备。

使用示例

1
2
3
4
5
# Claiming a device with a claim code that will be valid indefinitely until it is used to claim a device
client.claim_device("my_claim_code")

# Claiming a device with a claim code that will be valid for 60 seconds
client.claim_device("my_claim_code", duration_ms=60000)

subscribe_to_attribute

订阅ThingsBoard的属性更新。通过属性键指定要订阅的共享属性。订阅的属性值更新时,将调用提供的回调并传入新值。

方法返回订阅ID,可用于unsubscribe_from_attribute取消订阅。

方法语法

client.subscribe_to_attribute(key, callback)

参数

Arguments Description
key (必填)要订阅的ThingsBoard共享属性键。
callback (必填)订阅属性在ThingsBoard上更新时触发的回调,须接受result和 *args两个参数。

使用示例

1
2
3
4
5
6
def callback(result, *args):
    # Called when subscribed attribute update arrive
    print("Received data: %r", result)


sub_id = client.subscribe_to_attribute("frequency", callback)

subscribe_to_all_attributes

订阅ThingsBoard全部共享属性更新。服务端任意共享属性修改时,SDK会触发指定回调并传入更新后的数据。

方法返回订阅ID,可用于unsubscribe_from_attribute取消订阅。

方法语法

client.subscribe_to_all_attributes(callback)

参数

Arguments Description
callback (必填)服务端推送共享属性变更时触发,回调接收包含修改后键值对的result对象及*args。

使用示例

1
2
3
4
5
def callback(result, *args):
    print("Received data: %r", result)


sub_id = client.subscribe_to_all_attributes(callback)

unsubscribe_from_attribute

终止共享属性更新的现有订阅。需传入subscribe_to_attributesubscribe_to_all_attributes返回的subscription_id。取消后,相关回调在服务端变更时不再触发。

方法语法

client.unsubscribe_from_attribute(subscription_id)

参数

Arguments Description
subscription_id (必填)通过subscribe_to_attribute或subscribe_to_all_attributes订阅时返回的订阅ID。

使用示例

1
2
3
4
5
6
7
8
# Subscribing to attribute updates
def callback(result, *args):
    print("Received data: %r", result)


sub_id = client.subscribe_to_attribute("frequency", callback)
# Unsubscribing from attribute updates
client.unsubscribe_from_attribute(sub_id)

set_server_side_rpc_request_handler

配置处理ThingsBoard发起的远程过程调用请求的处理器。应在建立连接后调用。收到请求时,SDK执行指定处理器并传入:

  • request_id - RPC请求的唯一标识符,用于发送响应。
  • request_body - 包含命令详情的字典,通常含方法名和params。

方法语法

client.set_server_side_rpc_request_handler(handler)

参数

Arguments Description
handler 定义ThingsBoard发起远程命令时执行的逻辑,函数接收request_id和request_body两个参数。

使用示例

1
2
3
4
5
def handler(request_id, request_body):
    print("Received RPC request with ID: %s and body: %r", request_id, request_body)


client.set_server_side_rpc_request_handler(handler)

send_rpc_reply

响应来自ThingsBoard的RPC请求。在RPC处理器中使用此方法向服务器返回数据。需要初始请求的request_id和包含结果的response对象。不调用此方法可能导致ThingsBoard仪表板上出现request timeout错误。

方法语法

client.send_rpc_reply(request_id, response)

参数

Arguments Description
request_id (必填)收到的RPC请求ID,用于发送回复。
response (必填)作为RPC回复发送的数据。

使用示例

1
2
3
4
5
6
def handler(request_id, request_body):
    print("Received RPC request with ID: %s and body: %r", request_id, request_body)
    client.send_rpc_reply(request_id, {"status": "success"})


client.set_server_side_rpc_request_handler(handler)

send_rpc_reply

响应来自ThingsBoard的RPC请求。在RPC处理器中使用此方法向服务器返回数据。需要初始请求的request_id和包含结果的response对象。不调用此方法可能导致ThingsBoard仪表板上出现request timeout错误。

方法语法

client.send_rpc_reply(request_id, response)

参数

Arguments Description
request_id (必填)收到的RPC请求ID,用于发送回复。
response (必填)作为RPC回复发送的数据。

使用示例

1
2
3
4
5
6
def handler(request_id, request_body):
    print("Received RPC request with ID: %s and body: %r", request_id, request_body)
    client.send_rpc_reply(request_id, {"status": "success"})


client.set_server_side_rpc_request_handler(handler)

Concepts

简介

在本部分中,我们将涵盖CircuitPython Client SDK的核心概念:

  • 通过MQTT将设备连接到ThingsBoard。
  • 非阻塞循环。
  • 遥测、属性和数据流。
  • 属性请求。
  • 属性更新。
  • 处理服务端RPC。

让我们回顾一下CircuitPython Client SDK的这些概念:

连接ThingsBoard

使用CircuitPython Client SDK连接ThingsBoard时,实例化TBDeviceMqttClient并传入服务器凭证:host、port和access token。初始化后调用connect()建立MQTT会话。连接成功后即可发送遥测或订阅更新。推荐使用以下最小代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import time

import wifi  # CircuitPython Wi-Fi module

from tb_device_mqtt import TBDeviceMqttClient  # ThingsBoard MQTT client wrapper (your SDK)

# Quick sanity-check that Wi-Fi is up before using MQTT
print("WiFi connected:", wifi.radio.connected)
print("IP:", wifi.radio.ipv4_address)

# ThingsBoard connection settings
HOST = "YOUR_HOST"  # e.g. "thingsboard.cloud" or "192.168.1.10"
PORT = "YOUR_PORT"  # e.g. 1883 (use an int)
TOKEN = "YOUR_ACCESS_TOKEN"  # device access token from ThingsBoard

# Create MQTT client instance
client = TBDeviceMqttClient(host=HOST, port=PORT, access_token=TOKEN)
print("Connecting...")
client.connect()  # open MQTT connection to ThingsBoard
time.sleep(1)  # small delay to ensure connection stabilizes on some boards

while True:
# some tasks with ThingsBoard

与ThingsBoard通信前,请确保设备已接入网络。上述代码假设Wi-Fi已连接。Wi-Fi连接方法详见CircuitPython网络

  • 首先确认Wi-Fi已连接并打印设备IP,MQTT客户端需要有效网络连接才能与ThingsBoard通信。
  • TBDeviceMqttClient是主类,需要ThingsBoard host和在设备页面生成的唯一Access Token。
  • 使用这些连接设置创建MQTT客户端实例,SDK据此确定连接地址和设备标识。
  • 调用client.connect()后,可加短暂延迟,使部分板卡的连接更稳定。

非阻塞循环

SDK实现中最关键的是主循环。在CircuitPython中,time.sleep()在等待事件时可降低CPU占用,但会阻塞代码。 要让设备持续处理传入的MQTT消息,需定期轮询客户端。

client.check_for_msg()是通信的“心跳”:

  • 检查MQTT缓冲区中的传入消息。
  • 处理收到的消息并触发相应回调(如RPC请求或属性更新)。

遥测、属性与数据流

SDK提供向ThingsBoard发送遥测的方法,可使用send_telemetry()以键值对、列表等格式发送。SDK也支持按时间戳分组发送,便于发送历史数据。

1
2
3
4
5
6
7
# Main loop (non-blocking)
while True:
    # Non-blocking: poll for incoming MQTT packets, then continue doing other work
    client.check_for_msg()
    client.send_telemetry({"CPU": 12.0})
    client.send_attributes({"status": "ok"})
    time.sleep(0.05)  # small delay to prevent overwhelming the CPU and allow other tasks to run

将其置于主循环后,设备将持续上报状态。采用非阻塞方式,设备可同时发送遥测和接收RPC命令,互不阻塞。

属性请求

SDK提供操作ThingsBoard设备属性的方法,可使用request_attributes()按键请求客户端和/或共享属性。 ThingsBoard响应后,SDK会调用回调并传入收到数据(或错误)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
TIMEOUT = 20  # how long we keep pumping MQTT loop (seconds)


def on_attributes_change(result, exception=None):
    # Callback is called when the attributes response arrives
    if exception is not None:
        print("Exception:", exception)
    else:
        print("Attributes response:", result)


# Request client/shared attributes by keys (your SDK forms attributes/request/<id>)
client.request_attributes(client_keys=["atr1", "atr2"], callback=on_attributes_change)

# IMPORTANT: CircuitPython needs a loop to receive/process MQTT packets
deadline = time.monotonic() + TIMEOUT
while time.monotonic() < deadline:
    client.check_for_msg()  # wraps MiniMQTT.loop() -> triggers callbacks
    time.sleep(0.05)  # small sleep to reduce CPU usagesks to run

在主循环中加入轮询逻辑,设备可保持响应:既能请求/接收属性,又能处理其他MQTT事件(如RPC调用)而不阻塞整个应用。

  • 定义回调on_attributes_change,在收到属性响应时触发。
  • 对指定键(”atr1”、”atr2”)发起属性请求,SDK发布请求并等待ThingsBoard响应。
  • 使用time.monotonic()控制循环在TIMEOUT内运行,若未收到响应不会无限等待。

属性更新

SDK提供订阅属性更新的方法,可使用subscribe_to_attribute()按键订阅客户端和/或共享属性的更新。 ThingsBoard发布该属性更新时,SDK将调用回调并传入收到的数据(或错误)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
TIMEOUT = 20  # how long we keep pumping MQTT loop (seconds)


def callback(result, *args):  # noqa: F841
    # Called when subscribed attribute update arrives
    # (extra args may contain metadata depending on your SDK design)
    print("Received data:", result)


# Subscribe to updates of a single attribute key (e.g. shared attribute "frequency")
sub_id = client.subscribe_to_attribute("frequency", callback)  # returns subscription id (optional)

# IMPORTANT: keep looping so incoming MQTT messages are processed
deadline = time.monotonic() + TIMEOUT
while time.monotonic() < deadline:
    client.check_for_msg()  # wraps MiniMQTT.loop() -> triggers callbacks
    time.sleep(0.05)  # small sleep to reduce CPU usage

在主循环中加入轮询逻辑,设备可保持响应:既能请求/接收属性,又能处理其他MQTT事件(如RPC调用)而不阻塞整个应用。

  • 定义回调callback,每次收到订阅属性更新时触发。
  • 订阅单个属性键(如共享属性”frequency”)的更新,方法可能返回后续用于管理订阅的subscription id。
  • 使用time.monotonic()限制循环在TIMEOUT内运行,示例不会无限执行。

处理服务端RPC

远程过程调用允许ThingsBoard向设备发送命令(如“打开LED”或“重置”)。要处理这些命令,需通过set_server_side_rpc_request_handler设置处理器。收到服务端RPC请求时,该处理器会被调用,并传入request_idrequest_body(分别对应请求ID和请求数据)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# This callback will be called when an RPC request is received from ThingsBoard.
def on_server_side_rpc_request(request_id, request_body):
    # request_id: numeric id from the MQTT topic
    # request_body: decoded JSON dict, typically {"method": "...", "params": ...}
    print("[RPC] id:", request_id, "body:", request_body)

    client.send_rpc_reply(request_id, "ok")


client.set_server_side_rpc_request_handler(on_server_side_rpc_request)

while True:
    # Non-blocking: poll for incoming MQTT packets
    client.check_for_msg()
    time.sleep(0.1)  # small delay to avoid busy-waiting (adjust as need)

SDK不会“等待”命令,而是通过回调on_server_side_rpc_request处理:

示例

更多CircuitPython Client SDK使用示例见GitHub上thingsboard-circuitpython-client-sdk仓库的examples目录。

故障排查

  • 内存不足、SDK不稳定

    常见于板子CircuitPython可用RAM有限,或应用及其依赖占用内存过多。 可尝试减少代码内存占用(如避免大块分配、精简import)。建议阅读CircuitPython内存优化指南。

  • circup安装错误

    部分板子在使用USB/串口工作流时circup install可能失败。此时可改用Web-Workflow安装库。 该方法通过指定设备IP(host)和Web Workflow密码,直接在网络上目标设备安装,常可解决上传/权限问题。

    1
    
    circup --host <your_device_ip> --password <your_password> install thingsboard-circuitpython-client-sdk