寻求MQTT字符串格式的更优替代方案
当前数据格式的流量消耗分析
先算一笔账:你当前的文本格式单条消息大概140字节左右(包含时间字符串、分隔符和数值),30秒发送一次,一天发送2880次,月流量约12MB,远低于每月500MB的配额。但这个格式存在冗余浪费:比如文本时间的分隔符、浮点数的字符串表示、空值的占位逗号,都可以进一步压缩,降低流量开销的同时也能减少MQTT消息的处理耗时。
可选的流量优化数据格式
下面是几种适合你的场景的格式,按流量节省程度从高到低排序:
1. 自定义二进制格式(极致省流量)
直接用Python的struct模块把数据打包成二进制,砍掉所有冗余:
- 用Unix时间戳(4字节无符号整数)代替文本时间,比原时间字符串省15字节;
- 用单精度浮点数(4字节)存储数值,比双精度省一半空间,0-700保留两位小数的精度需求完全能满足;
- 空值用
NaN(单精度浮点数的特殊值)标记,或者用一个3字节的位掩码(24位,每位对应一个数值是否有效),只发送有效数值,进一步压缩体积。
示例代码:
import struct import time import paho.mqtt.client as mqtt client = mqtt.Client() # 连接MQTT代理的代码省略... # 模拟传感器数据:Unix时间戳 + 24个数值(空值用float('nan')) timestamp = int(time.time()) sensor_values = [12.34, 56.78, float('nan'), 99.99] + [0.0]*20 # 凑24个值 # 打包格式:网络字节序(!) + 1个4字节无符号整数(I) + 24个单精度浮点数(f) packed_payload = struct.pack('!I24f', timestamp, *sensor_values) client.publish("field/sensor/data", payload=packed_payload, qos=0)
单条消息体积仅100字节,比原格式省28%左右;如果用位掩码优化空值,体积还能再降30%-50%。
2. Protocol Buffers(结构化二进制,扩展性强)
如果你需要长期维护、后续可能扩展数据字段,Protobuf是更好的选择:
- 先定义数据结构的
.proto文件,编译成Python代码; - 序列化后的体积和自定义二进制差不多,但自带版本兼容机制,新增字段不会影响旧设备。
示例.proto文件:
syntax = "proto3"; message FieldSensorData { uint32 timestamp = 1; repeated float values = 2; }
Python端序列化代码:
import field_sensor_data_pb2 import time import paho.mqtt.client as mqtt client = mqtt.Client() # 连接MQTT代理的代码省略... data = field_sensor_data_pb2.FieldSensorData() data.timestamp = int(time.time()) data.values.extend([12.34, 56.78, float('nan'), 99.99] + [0.0]*20) packed_payload = data.SerializeToString() client.publish("field/sensor/data", payload=packed_payload, qos=0)
3. 压缩JSON(兼顾可读性与流量)
如果需要偶尔调试查看原始数据,JSON加压缩是折中方案:
- 用极简JSON结构,比如
{"t":1704067200, "x":[12.34,null,...]},去掉冗余键名; - 用
zlib或gzip压缩JSON字符串,压缩率可达30%-50%。
示例代码:
import json import zlib import time import paho.mqtt.client as mqtt client = mqtt.Client() # 连接MQTT代理的代码省略... timestamp = int(time.time()) sensor_values = [12.34, 56.78, None, 99.99] + [0.0]*20 json_payload = json.dumps({"t": timestamp, "x": sensor_values}).encode('utf-8') compressed_payload = zlib.compress(json_payload) client.publish("field/sensor/data", payload=compressed_payload, qos=0)
4. 精简文本格式(改动最小,轻度省流量)
如果不想改太多代码,只优化现有文本格式:
- 去掉时间字符串的分隔符,比如用
01012024120000代替01:01:2024 12:00:00,节省6个字符; - 数值去掉末尾无意义的0(比如
12.0改成12),空值用-代替空占位; - 分隔符用单个逗号,去掉空格。
优化后的格式示例:01012024120000,12.34,56.78,-,99.99,...,单条消息体积能减少20%左右。
内容的提问来源于stack exchange,提问作者Janzaib M Baloch
相关产品推荐
相关产品推荐

