将mqtt的消息存储至mysql数据库

39 篇文章 1 订阅
8 篇文章 0 订阅
本文介绍了如何使用Python和Paho-MQTT库进行MQTT消息的注册和处理,包括连接服务器、主题管理、接收到消息后的解析和根据不同主题将二进制payload转换为结构化的数据,最终保存到MySQL数据库。
摘要由CSDN通过智能技术生成

Step1. mqtt消息注册及处理

使用python来做:

import paho.mqtt.client as mqtt
import mqtt_msghub as mqtt_msghub # mqtt payload is dealing here...

# MQTT服务器信息

broker = '192.168.0.16'
port = 1883
#topic = 'sensor/shake/measure/1'
username = "xxxxx"
password = "xxxxx"

# 连接回调函数
def on_connect(client, userdata, flags, rc):
    if rc == 0:
        print("连接成功")
    else:
        print("连接失败,错误码:" + str(rc))

# 接收消息回调函数
def on_message(client, userdata, msg):
    print("收到消息:")
    print("主题:" + msg.topic)
    #print("消息:" + str(msg.payload.decode())) //have bin format payload, can not transfter into str.
    mqtt_msghub.mqtt_dealmsg(client, msg.topic, msg.payload)
    

# 创建MQTT客户端对象
client = mqtt.Client()

# 设置连接回调函数
client.on_connect = on_connect

# 设置接收消息回调函数
client.on_message = on_message

# 连接MQTT服务器
client.username_pw_set(username, password)
client.connect(broker, port)

# 订阅主题
mqtt_msghub.mqtt_topic_register(client) #at msgHub moule.

# 开始循环监听消息,Ctrl+C中断退出
client.loop_forever()

Step1.1 看看topic注册及消息处理部分

from xml.dom import registerDOMImplementation
import payload_type_exchange as typeExchange
import paho.mqtt.client as mqtt
import table_common_table_crud as dbhelper
import gp_mysql_server as gpmysql #mysql.

mqtt_topics = {
    "sensor/shake/xx/%d": "d_shake_xxx_ch%02d",
    "sensor/shake/yyy/%d": "d_shake_yyy_ch%02d",
};

def mqtt_topic_register(client):
    global mqtt_topics;
    for item in mqtt_topics:
        key = item;
        topic = key.replace('%d', '+');
        client.subscribe(topic);
        print("mqtt register:[%s]" % topic);

def mqtt_get_topic_related_db_table(client, topic):
    dbtable = "";
    global mqtt_topics;
    if(topic in mqtt_topics): #for dict of python, iterator is just key itself.
        return (0, mqtt_topics[topic]);
    parts = topic.split("/");
    for item in mqtt_topics:
        key = item
        keyparts = key.split("/");
        parts_pre = parts[:-1];
        keyparts_pre = keyparts[:-1];
        if(parts_pre == keyparts_pre):
            ch = int(parts[-1])
            dbtable = mqtt_topics[item] % ch
            return (0, dbtable);
    return (-1, dbtable);

def getdbtable_macrotype(dbtablename):
    parts = dbtablename.split("_");
    return parts[:-1];
    

def mqtt_dealmsg(client, topic, payload):
    (ret, dbtable) = mqtt_get_topic_related_db_table(client, topic); #check if this msg need to save to db
    if(ret!=0): return;
    (ret, dbDict) = payload_to_dictOfDbField(payload, dbtable);  #get db insert cmd related dictionary object(dbDict)
    if(ret != 0): return;
    dbhelper.insert_data(gpmysql.gpDbConn(), dbtable, dbDict); //call SQL_insert helper cmd.

def payload_to_dictOfDbField(payload, dbtable):
    dbtable_class = getdbtable_macrotype(dbtable);
    if(dbtable_class == "d_shake_envelope".split("_")):
        return (0, typeExchange.payload_to_d_shake_envelope(payload));  //the indepentant type-convertion functions.
    else:
        print("unknown payload:%s, ommited to save to DB!" % dbtable);
        return (-1, "unknow payload");

Step2 通用的写mySql的辅助函数

代码中包含有两类payload的数据库入库接口,对于json格式,比较容易处理。顶多做一个名称映射表。

对于二进制格式,需要先将二进制转换为一个结构化的数据,然后才能入库。因为dbtable是个二维对象,最佳的载体是python.dictionary.

这里只给出了CRUD中的C和R。UD的代码可以此类推。

def json_to_mysql_insert(json_obj, table_name):
    data = json.load(json.dumps(json_obj));
    columns = ','.join(data.keys())
    values = "','".join(data.values());
    insert_statement = "INSERT INTO {} ({}) VALUES ('{}')".format(table_name, columns, values)
    return insert_statement

def dictionary_to_mysql_insert(dictionary, table_name):
    columns = ','.join(dictionary.keys())
    values = ','.join(['%s'] * len(dictionary))
    insert_statement = "INSERT INTO {} ({}) VALUES ({})".format(table_name, columns, values)
    return insert_statement

# 查询操作
def query_data(conn, tablename):
    with conn.cursor() as cursor:
        sql = "SELECT * FROM " + tablename;
        cursor.execute(sql)
        data = cursor.fetchall()
        cursor.close()

    # 处理数据并转换为 JSON
    records = [];
    results = data;
    for row in results:
        json_data = []
        for item_name in row:
            item = row[item_name];
            if isinstance(item, datetime.datetime):
                dumbTime = item.strftime('%Y-%m-%d %H:%M:%S')  # 将 datetime 对象按照指定格式转换为字符串
                json_data.append(dumbTime);
            else:
                if isinstance(item, bytes):
                    dumbBytes = binascii.hexlify(item[:8]).decode()
                    json_data.append(dumbBytes);
                else:
                    if isinstance(item, decimal.Decimal):
                        dumbDecimal = decimal.Decimal(item).to_eng_string();
                        json_data.append(dumbDecimal);
                    else:
                        json_data.append(item);
        records.append(json_data);
    str =  json.dumps(records);
    return str;

Step2.1 原始二进制流到Dictionary的转换:

这里没有定义结构体

from asyncio.windows_events import NULL
from multiprocessing.sharedctypes import Value
from os import name
from pickle import BINBYTES
from sqlite3 import SQLITE_BUSY_SNAPSHOT
import pymysql
import json
import gp_mysql_server as gpmysql
import datetime;
import binascii;
import decimal;
import struct;
from typing import MutableSequence

PT_OF_SENSOR_SHAKE_SAMPLE = 2048

def payload_to_d_shake_envelope(payload):
    #payload is a binarray(20:08, Sep18,2023,break.)
    #c_struct = CStruct(payload)
    c_struct = payload;
    verHigh = c_struct[0]
    verLow = c_struct[1]
    sn = struct.unpack_from("<I", c_struct, offset=2)[0]
    type_str = c_struct[6:8].decode('utf-8')
    timeOfSample_str = c_struct[8:28].decode('utf-8').rstrip('\x00')
    scale = struct.unpack_from("<I", c_struct, offset=28)[0]
    freqCenter = struct.unpack_from("<f", c_struct, offset=32)[0]
    freqBand = struct.unpack_from("<f", c_struct, offset=36)[0]
    binData = payload[40:40+4096];
    measures = struct.unpack_from("<4f", c_struct, offset=40 + 2 * PT_OF_SENSOR_SHAKE_SAMPLE)

    #fmt to dictionary.
    fmtValue ={};
    #verHight=1, verLow=0, result="1.0"
    fmtValue["ver"] = "{}.{}".format(verHigh, verLow);
    fmtValue["type"] = type_str;
    fmtValue["time"] = timeOfSample_str;
    fmtValue["scale"] = scale;
    fmtValue["fs"] = freqCenter;
    fmtValue["band"] = freqBand;
    fmtValue["bin_data"] = binData;
    fmtValue["rms"] = measures[0];
    fmtValue["ppk"] = measures[1];
    fmtValue["kurtossis"] = measures[2];
    fmtValue["margin"] = measures[3];
    fmtValue["sn"] = sn;
    return fmtValue;

MQTT是一种轻量级的消息传输协议,可以用于在网络间传输数据。将MQTT数据传入MySQL数据库的过程可以通过以下几个步骤实现: 1. 配置MQTT Broker:首先需要设置一个MQTT Broker,用于接收MQTT传来的数据。可以选择使用开源的MQTT Broker,如Mosquitto或者Eclipse Paho。配置Broker的端口号、用户名和密码等信息,使其能够接收来自设备的MQTT数据。 2. 编写MQTT客户端:使用任何支持MQTT协议的编程语言,如Python或Java,编写一个MQTT客户端,用于连接MQTT Broker并接收数据。在代码中,设置订阅的主题(topic),当Broker接收到相应主题的消息时,客户端会收到通知并执行相应的逻辑。 3. 解析数据:根据接收到的MQTT消息的格式和数据结构,将数据进行解析和提取。可以使用JSON或其他序列化格式将数据进行编码和解码,并提取出需要存储的数据。 4. 连接MySQL数据库:使用数据库连接库,如MySQL Connector/Python或JDBC等,建立与MySQL数据库的连接。配置数据库的IP地址、端口号、用户名和密码等信息。 5. 存储数据:通过执行SQL语句,将解析后的数据存储MySQL数据库中。可以使用INSERT语句将数据插入到指定的表格中,或者更复杂的逻辑,如更新现有数据或创建新的表格等。 6. 关闭连接:在数据存储完毕后,关闭MySQL数据库连接和MQTT客户端连接,释放资源。 通过以上步骤,即可实现将MQTT数据传入MySQL数据库的功能。需要注意的是,保证MQTT Broker和MySQL数据库服务器的稳定运行以及数据传输的安全性是非常重要的。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

子正

thanks, bro...

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值