当前位置: 首页 > news >正文

ThingsBoard开源物联网平台实践:从环境搭建到数据可视化

ThingsBoard开源物联网平台实践:从环境搭建到数据可视化

    • 一、背景介绍
      • 1、什么是ThingsBoard?
      • 2、为什么要使用ThingsBoard?
      • 3、本文目的
    • 二、参考链接
    • 三、效果展示
    • 四、详细操作步骤
      • 1、安装ThingsBoard
      • 2、Web登录并配置设备
      • 3、安装Python客户端SDK
      • 4、编写并运行设备客户端程序
    • 五、数据可视化配置

一、背景介绍

1、什么是ThingsBoard?

ThingsBoard是一个开源的物联网平台,它专门用于设备管理数据收集处理可视化。想象一下,你有很多物联网设备(比如智能家居设备、车辆传感器、工业机器等),这些设备会产生大量数据,ThingsBoard就是那个帮你统一管理这些设备,并让你能够查看和分析数据的"大脑"。

2、为什么要使用ThingsBoard?

  • 开源免费:不需要支付昂贵的许可费用
  • 易于扩展:支持从几个设备到数百万个设备的规模
  • 功能完整:提供设备管理、数据监控、告警、可视化等全套功能
  • 支持多种协议:MQTT、CoAP、HTTP等,适应不同设备需求

3、本文目的

本文将搭建ThingsBoard环境,注册物联网设备,并通过Python程序上报设备数据和位置信息,最后在Web界面上查看这些数据。

二、参考链接

  • 官方安装指南
  • Python客户端SDK文档

三、效果展示

请添加图片描述

四、详细操作步骤

1、安装ThingsBoard

为什么选择Docker安装?
Docker可以让我们快速部署应用,避免复杂的依赖和环境配置问题,特别适合开发和测试环境。

mkdir -p ~/.mytb-data && sudo chown -R 799:799 ~/.mytb-data
mkdir -p ~/.mytb-logs && sudo chown -R 799:799 ~/.mytb-logs
docker run -d -p 9090:9090 -p 7070:7070 -p 1883:1883 \-p 5683-5688:5683-5688/udp \-v ~/.mytb-data:/data \-v ~/.mytb-logs:/var/log/thingsboard \--name mytb --restart always thingsboard/tb-postgres

端口说明:

  • 9090:Web管理界面端口
  • 1883:MQTT协议端口,设备通过此端口连接
  • 7070:HTTP API端口
  • 5683-5688:CoAP协议端口,用于低功耗设备

2、Web登录并配置设备

访问ThingsBoard管理界面:

# 在浏览器中访问(将<IP>替换为你的服务器IP)
http://<你的服务器IP>:9090# 默认登录账号
用户名:tenant@thingsboard.org
密码:tenant

设备注册流程:

  1. 登录后进入"设备"菜单
  2. 点击"+"添加新设备
  3. 填写设备名称和描述
  4. 创建设备后,点击设备详情,复制"访问令牌"
    • 这个令牌相当于设备的身份证,用于验证设备身份

3、安装Python客户端SDK

什么是MQTT客户端?
MQTT是一种轻量级的物联网通信协议,我们的Python程序需要通过这个客户端库与ThingsBoard服务器通信。

pip3 install tb-mqtt-client

4、编写并运行设备客户端程序

程序功能详解:

这个Python程序主要完成以下任务:

cat > tb_client.py << 'EOF'
import sys
import os
import pyproj
sys.path.insert(0,"/opt/apollo/neo/python/cyber/python")
sys.path.insert(0,"/opt/apollo/neo/python")
import ctypes
import socket
from cyber_py3 import cyber
from modules.common_msgs.chassis_msgs import chassis_pb2
from modules.common_msgs.localization_msgs import localization_pb2
from modules.common_msgs.control_msgs import control_cmd_pb2
from tb_device_mqtt import TBDeviceMqttClient, TBPublishInfo
import argparse
import time
import numpy as np
import threading
import mathx_pi = 3.14159265358979324 * 3000.0 / 180.0
pi = 3.1415926535897932384626 # π
a = 6378245.0 # 长半轴
ee = 0.00669342162296594323 # 扁率def transformlat(lng, lat):ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * math.sqrt(math.fabs(lng))ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *math.sin(2.0 * lng * pi)) * 2.0 / 3.0ret += (20.0 * math.sin(lat * pi) + 40.0 *math.sin(lat / 3.0 * pi)) * 2.0 / 3.0ret += (160.0 * math.sin(lat / 12.0 * pi) + 320 *math.sin(lat * pi / 30.0)) * 2.0 / 3.0return retdef transformlng(lng, lat):ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * math.sqrt(math.fabs(lng))ret += (20.0 * math.sin(6.0 * lng * pi) + 20.0 *math.sin(2.0 * lng * pi)) * 2.0 / 3.0ret += (20.0 * math.sin(lng * pi) + 40.0 *math.sin(lng / 3.0 * pi)) * 2.0 / 3.0ret += (150.0 * math.sin(lng / 12.0 * pi) + 300.0 *math.sin(lng / 30.0 * pi)) * 2.0 / 3.0return retdef wgs84togcj02(lng,lat):"""WGS84转GCJ02(火星坐标系):param lng:WGS84坐标系的经度:param lat:WGS84坐标系的纬度:return:列表"""dlat = transformlat(lng - 105.0, lat - 35.0)dlng = transformlng(lng - 105.0, lat - 35.0)radlat = lat / 180.0 * pimagic = math.sin(radlat)magic = 1 - ee * magic * magicsqrtmagic = math.sqrt(magic)dlat = (dlat * 180.0) / ((a * (1 - ee)) / (magic * sqrtmagic) * pi)dlng = (dlng * 180.0) / (a / sqrtmagic * math.cos(radlat) * pi)mglat = lat + dlatmglng = lng + dlngreturn [mglng, mglat]class ApolloStatus(ctypes.Structure):_pack_ = 4  # 4字节对齐_fields_ = [("speed_mps", ctypes.c_double),("odometer_m", ctypes.c_double),("throttle_percentage", ctypes.c_double),("brake_percentage", ctypes.c_double),("steering_percentage", ctypes.c_double),("x", ctypes.c_double),("y", ctypes.c_double),("heading", ctypes.c_double),("engine_started", ctypes.c_int),("parking_brake", ctypes.c_int),("low_beam_signal", ctypes.c_int),("left_turn_signal", ctypes.c_int),("right_turn_signal", ctypes.c_int),("driving_mode", ctypes.c_int),("error_code", ctypes.c_int),("battery_soc_percentage", ctypes.c_int),("horn", ctypes.c_int)]g_status = ApolloStatus()def chassis_callback(msg):global g_statusg_status.engine_started=msg.engine_startedg_status.speed_mps=msg.speed_mpsg_status.odometer_m=msg.odometer_mg_status.throttle_percentage=msg.throttle_percentageg_status.brake_percentage=msg.brake_percentageg_status.steering_percentage=msg.steering_percentageg_status.parking_brake=msg.parking_brakeg_status.low_beam_signal=msg.low_beam_signalg_status.left_turn_signal=msg.left_turn_signalg_status.right_turn_signal=msg.right_turn_signalg_status.driving_mode=msg.driving_modeg_status.error_code=msg.error_codeg_status.battery_soc_percentage=msg.battery_soc_percentageg_status.horn=msg.horndef pos_callback(msg):global g_statusx=msg.pose.position.xy=msg.pose.position.yheading=msg.pose.headingprojector2 = pyproj.Proj(proj='utm', zone=50, ellps='WGS84')lon, lat = projector2(x, y, inverse=True)x,y=wgs84togcj02(lon, lat)g_status.x=xg_status.y=yg_status.heading=headingclient=None
def monitor_function():global g_statuswhile True:global clienttelemetry = {"engine_started": g_status.engine_started,"speed_mps": g_status.speed_mps,"throttle_percentage": g_status.throttle_percentage,"brake_percentage":g_status.brake_percentage,"steering_percentage":g_status.steering_percentage,"latitude":g_status.y,"longitude":g_status.x}telemetry_with_ts = {"ts": int(round(time.time() * 1000)), "values": {"battery_soc_percentage": g_status.battery_soc_percentage}}client.send_telemetry(telemetry_with_ts)client.send_telemetry(telemetry)time.sleep(5)def on_server_side_rpc_request(request_id, request_body):global clientprint(request_id, request_body)if request_body["method"] == "getValue":client.send_rpc_reply(request_id, {"value": True})elif request_body["method"] == "setValue":value=request_body['params']print(value)client.send_rpc_reply(request_id, {"value": True})def main():parser = argparse.ArgumentParser(description='网络延迟测试客户端')parser.add_argument('--host', default='localhost', help='服务器地址 (默认: localhost)')    parser.add_argument('--token', default='', help='')args = parser.parse_args()cyber.init()node = cyber.Node("tb_client")node.create_reader("/apollo/canbus/chassis",chassis_pb2.Chassis,chassis_callback)node.create_reader("/apollo/localization/pose",localization_pb2.LocalizationEstimate,pos_callback)global clientclient = TBDeviceMqttClient(args.host, username=args.token)client.set_server_side_rpc_request_handler(on_server_side_rpc_request)client.connect()thread = threading.Thread(target=monitor_function)thread.start()node.spin()cyber.shutdown()if __name__ == "__main__":main()
EOF
python3 tb_client.py --host <服务器IP> --token=<获取的令牌>

代码说明:

  1. 订阅Apollo消息: 获取车辆信息
  2. 设备连接:使用令牌连接到ThingsBoard
  3. 数据上报:定期发送设备状态数据
  4. RPC处理:响应服务器的远程控制命令
  5. 多线程:使用独立线程处理数据上报

五、数据可视化配置

  1. 进入ThingsBoard的仪表板菜单

    • 点击左侧菜单的"仪表板"
    • 点击"+"创建新仪表板
  2. 添加数据可视化组件

    • 点击"编辑仪表板"
    • 添加各种部件:
      • 数字/图表:显示速度、电量等数据
      • 地图:显示设备位置
      • 开关:远程控制设备
  3. 配置数据源

    • 选择对应的设备和遥测数据
    • 设置刷新间隔
http://www.dtcms.com/a/507316.html

相关文章:

  • 第二章 线性表——课后习题解练【数据结构(c语言版 第2版)】
  • 成都网站建设开发公选择好的软件开发培训班
  • 待学习--中间件
  • Avalonia vs UniApp 全面对比分析
  • 策略模式优化多重判断
  • ios云打包证书申请不需要苹果电脑也是可以的
  • UniApp USB存储设备U盘操作、读写原生插件
  • 邢台 建网站中国机械设备制造网
  • app网站开发河 又最新新闻热点事件300字
  • ZooKeeper集群:分布式系统的核心守护者
  • 网鼎杯 2020 朱雀组
  • 开发避坑指南(63):解决SQL排序子句列名歧义异常:Column ‘xxx‘ is ambiguous
  • 【C + +】红黑树:全面剖析与深度学习
  • 数据结构(顺序表和链表)
  • C# 基础——装箱和拆箱
  • 分享网站友情链接营销
  • windows中用wsl使用cuda
  • 运维逆袭志·第3期 | 数据孤岛破局之战 :跨业务分析的难题攻坚
  • 《道德经》第二十一章
  • 第 14 章:Spring AI Alibaba — Nacos3实现动态Prompt
  • TableTime:将时序分类重构为表格理解任务,更有效对齐LLM语义空间
  • Java的main方法语法
  • 【Linux】 层层递进,抽丝剥茧:调度队列、命令行参数、环境变量
  • 火电厂VR安全培训系统怎么样?VR安全培训告别传统培训痛点!
  • 网站建设有哪些工作儿童教育网站源码
  • 开题报告之基于SpringBoot框架的路面故障信息上报系统设计与实现
  • rabbitmq服务端消费端实例(direct和fanout模式)
  • 橙色车队上的安全密码:嘉顺达蓝海的危险品运输专业之道
  • FPGA高频面试问题整理—附答案
  • html框架做网站创立个网站专业卖手机