官网https://thingsboard.io参考http://www.ithingsboard.com/docs/user-guide/attributes应朋友的要求写一篇关于 ThingsBoard 的文章记录一下安装与使用的过程近年来物联网平台IoT Platform在智慧农业、工业监测、智能城市等应用中扮演着越来越关键的角色随着传感器网络的普及单一设备的数据采集和本地显示早已无法满足需求集中式的远程管理、实时监控与可视化平台成为构建现代物联网系统的重要组成部分在众多开源物联网平台中ThingsBoard 凭借插件机制灵活、支持多种协议如 MQTT、HTTP、CoAP以及强大的仪表盘功能成为中小型物联网项目中极具性价比的选择如果你正在寻找一个稳定易用的物联网平台并满足以下需求需要远程监控嵌入式/传感器设备希望快速搭建一个支持 MQTT、HTTP、CoAP 的平台苦于其他平台太重或收费昂贵……那么ThingsBoard是你值得一试的开源解决方案本系列将基于实操视角逐步记录我从零开始搭建 ThingsBoard 环境、连接设备、上传数据并实现可视化展示的过程涉及内容包括但不限于ThingsBoard 的快速部署Docker 方式基于 MQTT 协议的数据上报与遥控Dashboard 可视化配置与嵌入式终端如 STM32、ESP32、树莓派等的对接实践使用 Docker 部署 ThingsBoardThingsBoard 提供了多种安装方式包括 Docker、Kubernetes、本地安装包等考虑到 ThingsBoard 的 Docker 镜像已经非常完善且易于部署本文将采用 Docker 方式进行安装环境依赖在开始安装之前请确保你的系统满足以下环境依赖DockerThingsBoard 需要 Docker 来运行请确保你的系统已经安装了 Docker如果没有安装可以参考 Docker 官方文档进行安装Docker ComposeThingsBoard 使用 Docker Compose 来管理多个容器请确保你的系统已经安装了 Docker Compose如果没有安装可以参考 Docker Compose 官方文档进行安装Docker compose 配置文件进入某一个目录你自己定义最好和其他任何软件不产生交集编辑 docker-compose.yml 文件nanodocker-compose.yml在文件中添加services:postgres:restart:alwaysimage:postgres:16ports:-5432environment:POSTGRES_DB:thingsboardPOSTGRES_PASSWORD:postgresvolumes:-postgres-data:/var/lib/postgresql/datathingsboard-ce:restart:alwaysimage:thingsboard/tb-node:4.0.1.1ports:-8080:8080-7070:7070-1883:1883-8883:8883-5683-5688:5683-5688/udplogging:driver:json-fileoptions:max-size:100mmax-file:10environment:TB_SERVICE_ID:tb-ce-nodeSPRING_DATASOURCE_URL:jdbc:postgresql://postgres:5432/thingsboarddepends_on:-postgresvolumes:postgres-data:name:tb-postgres-datadriver:local服务说明postgres 用于存储 ThingsBoard 的数据image: postgres:16使用官方维护的 PostgreSQL 16 镜像稳定可靠ports: “5432”数据库默认端口未映射到宿主机确保安全可按需映射可以通过 Docker 创建的网络使用容器名访问environment配置 PostgreSQL 的数据库信息POSTGRES_DBthingsboard初始化时创建名为 thingsboard 的数据库POSTGRES_PASSWORDpostgres数据库密码为 postgres可自行修改volumes将数据库数据挂载到宿主机上的 tb-postgres-data 卷中实现数据持久化容器重启不会丢失数据但不会直接在本地映射出来建议定期备份 tb-postgres-data以便灾难恢复thingsboard-ceThingsBoard 的核心服务image: thingsboard/tb-node:4.0.1.1指定 ThingsBoard CE 版本为 4.0.1.1可根据需求更新为最新版本ports映射到宿主机的端口如下8080:8080Web UI 访问端口默认使用 http://localhost:8080 打开平台7070:7070用于 WebSocket 和服务间通信1883:1883MQTT 协议端口设备上报数据8883:8883MQTT over TLS 加密端口5683-5688:5683-5688/udpCoAP 协议端口适用于轻量设备logging限制日志大小防止磁盘爆满每个日志文件最大 100MB最多保留 10 个文件environment配置 ThingsBoard 的环境变量TB_SERVICE_IDtb-ce-node设置服务 ID适用于集群或多节点部署SPRING_DATASOURCE_URLjdbc:postgresql://postgres:5432/thingsboard指定数据库连接字符串注意这里的 postgres 为 Compose 内部服务名自动 DNS无需写成 IP 地址depends_on: postgres确保在启动 thingsboard-ce 之前postgres 服务已经启动volumes数据持久化用于保存 PostgreSQL 数据的宿主机挂载卷避免容器重启后数据丢失注意端口配置中冒号前面的是宿主机端口后面的端口是容器内端口如果需要修改端口注意只能修改宿主机端口容器内端口不能修改若设备运行在非 Docker 主机请确保防火墙/路由规则允许连接映射到的 MQTT/CoAP/Web 端口初始化数据库与加载系统资源在首次启动 ThingsBoard 服务之前我们需要先初始化数据库的表结构并加载系统内置资源这一步非常关键否则平台无法正常运行ThingsBoard 官方镜像已经内置了初始化命令可以通过一条 Docker Compose 命令完成dockercompose run--rm\-eINSTALL_TBtrue\-eLOAD_DEMOtrue\thingsboard-ce该命令会启动一个临时的 thingsboard-ce 容器执行内置的数据库初始化流程结束后自动退出并删除临时容器因为加了 --rm 参数启动与登录平台启动平台完成数据库初始化后我们即可正式启动 ThingsBoard 平台服务使用以下命令启动所有容器并实时查看 ThingsBoard 的运行日志dockercompose up-ddockercompose logs-fthingsboard-ce这条命令做了两件事docker compose up -d在后台启动所有定义在 docker-compose.yml 中的服务包括 PostgreSQL 和 ThingsBoard 容器docker compose logs -f thingsboard-ce持续输出 thingsboard-ce 容器的运行日志方便我们第一时间看到启动进度和是否成功如果你看到 Started ThingsBoardServerApplication 或类似提示说明平台已经成功启动如果不想看日志可以按下 Ctrl C 退出日志输出容器本身不会停止ThingsBoard 服务仍然会在后台运行如果你想重新查看运行日志可以随时使用 docker compose logs -f thingsboard-ce登录平台默认情况下ThingsBoard 会监听本地的 8080 端口你可以在浏览器中访问http://localhost:8080或者在非本地部署时替换为你的主机 IP 地址http://{your-host-ip}:8080打开网页后即可看到 ThingsBoard 的登录界面首次登录系统你可以使用以下默认账户角色用户名密码系统管理员sysadminthingsboard.orgsysadmin租户管理员tenantthingsboard.orgtenant客户用户演示customerthingsboard.orgcustomer建议登录后尽快修改各个账户的密码以保证平台安全ThingsBoard 使用添加设备其实我们第一步应该是创建租户和租户管理员账号的但是平台默认提供了三个账号我们直接使用即可登录租户管理员账号后点击左侧导航栏的设备选项进入设备管理页面即可添加设备可选择 default 或 thermostat 模板这些模板预配置了 MQTT、HTTP 与 CoAP 通信协议便于多种方式测试连通性在我当前使用的版本中MQTT 功能运行最稳定CoAP反而无法正常使用分配给客户我选择了公开这个决定了用户账户可以查看的设备我们设置 MQTT 凭据要注意每一个设备的凭据不能相同凭据是设备与平台通信的唯一标识测试设备连接平台我们可以使用客户端或者 Linux 命令行工具来测试设备与平台之间的连通性这里我使用 MQTTX 工具进行测试选择你运行的 Docker ThingsBoard 的机器地址端口选择 Docker 配置映射出来的端口默认是 1883填入在 ThingsBoard 中设备的凭据然后点击连接即可连接到平台订阅、发布与平台设备配置在说订阅与发布之前我们先来看一下 ThingsBoard 的属性ThingsBoard 分为客户端属性、服务端属性和最新属性值如下属性类型来源方向设备是否可写平台是否可写是否自动推送到设备描述客户端属性设备 → 平台✅ 是✅ 可初始化仅首次❌ 否设备主动上报的信息例如设备型号、固件版本、运行状态平台只做查看不会主动推送服务端属性平台 → 平台侧应用❌ 否✅ 是❌ 否平台保存的属性集合设备无法获取共享属性平台 → 设备❌ 否✅ 是✅ 是平台设置的共享配置项支持平台→设备自动推送也可由设备主动请求如目标温度、模式等最新属性值概念双向✅ 是✅ 是❌ 否需主动查询并非单独属性类型而是平台维护的当前属性快照用于展示或通过 API 获取在平台点击设备进入设备详情页面可以看到设备的属性如下接下来我就根据上面的表格来演示一下 ThingsBoard 的属性与设备之间的交互服务端属性服务端属性通常是由平台维护、设备通过请求获取的一类静态或配置属性它常用于存储平台侧记录的设备参数例如部署位置、设备负责人、安装时间等平台侧应用获取服务端属性因为服务端属性仅能通过平台侧应用进行读写所以无法使用 MQTT 订阅的方式获取只能通过 API 获取如下获取 JWT 令牌curl-XPOST https://iot.140105.xyz/api/auth/login-HContent-Type: application/json-d{username:tenantthingsboard.org,password:tenant}以我的平台为例将地址替换为你的平台地址用户名和密码替换为你的租户管理员账号和密码即可获取 JWT 令牌返回示例如下返回的信息比较长注意仔细比对{token:xxxxx,refreshToken:xxxxx}获取设备服务端属性使用上一步获得的 JWT 令牌通过下面的方法获取设备的服务端属性curl-XGEThttps://iot.140105.xyz/api/plugins/telemetry/DEVICE/4d453110-4e91-11f0-aa54-d1bcfb4dde7b/values/attributes/SERVER_SCOPE-HContent-Type: application/json-HX-Authorization: Bearer JWT 令牌其中 DEVICE 后面的 4d453110-4e91-11f0-aa54-d1bcfb4dde7b 是设备的 ID在平台网页点击设备网址链接中可以看到JWT 令牌就是上一步获取的 token返回结果如下[{lastUpdateTs:1750619760822,key:lastConnectTime,value:1750619760822},{lastUpdateTs:1750619852183,key:test,value:1},{lastUpdateTs:1750621040988,key:lastDisconnectTime,value:1750621040987},{lastUpdateTs:1750621041491,key:lastActivityTime,value:1750621040963},{lastUpdateTs:1750621684069,key:inactivityAlarmTime,value:1750621684069},{lastUpdateTs:1750621684069,key:active,value:false}]注意token 是有有效期的如果过期了需要重新获取以上的演示方式均在命令行中完成可以使用其他编程语言如 Python、Java、Go 等作为 curl 的替代平台侧应用设置服务端属性我们同样使用 JWT 令牌通过下面的方法设置设备的服务端属性curl-vhttps://iot.140105.xyz/api/plugins/telemetry/DEVICE/4d453110-4e91-11f0-aa54-d1bcfb4dde7b/SERVER_SCOPE-HContent-Type: application/json-HX-Authorization: Bearer JWT 令牌\-Hcontent-type: application/json\--data-raw{test:2}其中最后一行的 test 是你要设置的属性键名2 是你要设置的属性值运行之后平台对应设备的服务端属性就会发生变化客户端属性客户端属性常用于平台的分组管理、版本控制、规则引擎判断等场景是设备与平台之间状态同步的基础结构之一设备发送数据到平台客户端属性的主题是 v1/devices/me/attributes通过表格我们能看到这个是由设备发送到平台的所以我们使用 MQTTX 工具模拟设备向平台发布一条消息如下{serialNumber:SN-001-ABC,firmwareVersion:v1.2.5,model:X200}平台可以根据设备上报的属性在仪表盘中展示设备信息也可以在规则链库中根据属性值进行判断如下如上图即为在仪表盘中显示设备信息如上图即为设置规则链库当版本信息小于脚本中所配置的版本时便会触发提醒设备从平台获取数据设备可以主动请求平台侧的客户端属性请求主题为 v1/devices/me/attributes/request/request_id其中 request_id 是请求 ID可以任意指定订阅主题可以是 v1/devices/me/attributes/request/request_id 或者 v1/devices/me/attributes/response/发送的数据如下{clientKeys:firmwareVersion,serialNumber}其中 firmwareVersion 和 serialNumber 是设备在 ThingsBoard 中配置的客户端属性在主题 v1/devices/me/attributes/request/1 或者 v1/devices/me/attributes/response/ 中会得到从平台返回的数据如下{client:{serialNumber:SN-001-ABC,firmwareVersion:v1.2.5}}对 json 进行解析即可得到平台返回的属性值在 ThingsBoard 中每个设备都有唯一的连接凭据因此平台能够识别出请求来源的具体设备即使多个设备同时使用相同的 request_id 发起属性请求平台也能正确分发并返回各自的响应结果不会互相影响但如果你使用一个设备代理器代理器会使用相同的凭据那么平台会认为所有的请求都来自同一个设备导致响应混乱这时候就需要你对代理的设备进行额外的代码编写给每个被代理的设备分配不同的请求 ID实现设备之间的请求隔离平台侧应用获取数据平台侧可以和设备一样使用 MQTT 获取数据也可以使用 API 获取数据如下curl-XGEThttps://iot.140105.xyz/api/plugins/telemetry/DEVICE/4d453110-4e91-11f0-aa54-d1bcfb4dde7b/values/attributes/CLIENT_SCOPE-HContent-Type: application/json-HX-Authorization: Bearer JWT 令牌和服务端属性获取的方式大同小异只是将 SERVER_SCOPE 替换为 CLIENT_SCOPE 即可运行之后结果如下[{lastUpdateTs:1750613652969,key:serialNumber,value:SN-001-ABC},{lastUpdateTs:1750613652969,key:model,value:X200},{lastUpdateTs:1750613652969,key:firmwareVersion,value:v1.2.5}]共享属性共享属性是平台侧应用给设备分发数据的一种方式共享属性可以用于平台侧应用之间的数据共享也可以用于平台向设备发送数据和客户端属性的区别是客户端属性是设备主动请求平台返回数据而共享属性是当属性发生变化或者新建属性时候平台会主动向设备发送数据当然也可以主动请求设备从平台请求数据和客户端属性一样设备可以主动请求平台侧的共享属性请求主题为 v1/devices/me/attributes/request/request_id其中 request_id 是请求 ID可以任意指定订阅主题可以是 v1/devices/me/attributes/request/request_id 或者 v1/devices/me/attributes/response/发送的数据如下{sharedKeys:test}其中 test 是你要获取的属性键名在主题 v1/devices/me/attributes/request/request_id 或者 v1/devices/me/attributes/response/ 中会得到从平台返回的数据如下{shared:{test:1}}对 json 进行解析即可得到平台返回的共享属性值属性修改/变动自动推送无论在平台侧应用还是在平台本身我们对共享属性进行增、删、改操作设备都会收到平台自动推送的属性值如下增和改{test:2}删{deleted:[test]}平台侧应用获取数据平台侧应用获取共享属性的方式和服务端属性大同小异只是将 SERVER_SCOPE 替换为 SHARED_SCOPE 即可如下所示,在此不过多赘述curl-XGEThttps://iot.140105.xyz/api/plugins/telemetry/DEVICE/4d453110-4e91-11f0-aa54-d1bcfb4dde7b/values/attributes/SHARED_SCOPE-HContent-Type: application/json-HX-Authorization: Bearer JWT 令牌平台侧应用设置数据平台侧应用设置共享属性的方式和服务端属性大同小异只是将 SERVER_SCOPE 替换为 SHARED_SCOPE 即可如下所示,在此不过多赘述curl-vhttps://iot.140105.xyz/api/plugins/telemetry/DEVICE/4d453110-4e91-11f0-aa54-d1bcfb4dde7b/SHARED_SCOPE-HContent-Type: application/json-HX-Authorization: Bearer JWT 令牌\-Hcontent-type: application/json\--data-raw{test:2}用此方法进行数据的更新设备也会自动收到平台推送的数据如果设备离线可能会错过重要的数据更新所以建议在设备启动之后订阅共享属性并且每次连接后请求属性的最新值除了属性ThingsBoard 还提供了遥测Telemetry数据和属性的区别是遥测多了时间序列相关的功能可以用于长时间的数据对比分析等展开的话内容太多在此不过多赘述可以在这里查看遥测数据总结本文记录了从零开始使用 Docker 快速部署 ThingsBoard 平台的全过程并详细演示了平台与设备之间通过 MQTT 协议进行数据交互的方式特别是客户端属性、服务端属性、共享属性三者的使用与差异借助 ThingsBoard 丰富的功能我们可以轻松实现设备的远程配置、状态监测与规则联动为物联网系统的构建打下坚实基础如果你正在开发或运营一个嵌入式项目或正在寻找一套支持 MQTT/HTTP/CoAP 且功能全面的物联网平台相信 ThingsBoard 能为你提供一个清晰的起点后续我将继续记录更多实战经验包括遥测数据上传与可视化、规则链自动化处理、集成邮件/钉钉/短信报警机制等内容欢迎持续关注阅读原文ThingsBoard Docker 部署指南