用Python采用Modbus-Tcp的方式读取485电子水尺数据

README.TXT

2023/6/15 
V1.0 实现了单个点位数据通信、数据解析、数据存储
2023/6/17
V2.0 实现了多个点位数据通信、数据解析、数据存储
2023/6/19
V2.1 完善log存储,仅保留近3天的log记录,避免不必要的存储;限制log大小,2MB。

架构介绍

使用Python开发服务器程序,实现以下功能:

  1. 采用问询的方式读取各类传感器数据
  2. 正确高速解析各类传感器的数据
  3. 存储解析后的各类传感器数据
  4. 存储程序运行过程中的log
  5. 管理log,超过一定量、一定时间自动删除log
  6. 打包发布 或者 在后台运行py服务器程序

硬件介绍 传感器 串口服务器 采集模块 5G通信模块

主要传感器

485电子水尺传感器

该传感器支持485通信

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

其他硬件:

485漏液侦测传感器

485采集模块

串口服务器

5G通信模块

调试工具

采集模块调试工具

在这里插入图片描述

485电子水尺调试工具

在这里插入图片描述

串口调试助手,主要用于 漏液传感器在这里插入图片描述

其他工具

CRC计算器,不过我一般都是自己写CRC校验程序,CRC校验程序放在后面完整代码了

在这里插入图片描述

WIN10自带的计算器

在这里插入图片描述

调试过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

完整代码 LOG存储功能、数据读取解析存储功能

#!D:/workplace/python
# -*- coding: utf-8 -*-
# @File  : main0620.py
# @Author:Romulushe
# @Time    : 2023/6/20 13:53
# @Software: PyCharm
# @Use: PyCharm
import os
import sys
import logging
import time
from logging.handlers import RotatingFileHandler
import shutil
import socket
import threading
import pymysql
import binascii
import time
import datetimebase_path = os.path.dirname(os.path.realpath(sys.argv[0]))def get_log_path():return os.path.join(base_path, 'logs')def cleanup_logs():log_path = get_log_path()current_time = time.time()for file_name in os.listdir(log_path):file_path = os.path.join(log_path, file_name)if os.path.isfile(file_path):creation_time = os.path.getctime(file_path)if current_time - creation_time > (3 * 24 * 60 * 60):os.remove(file_path)def configure_logging():log_path = get_log_path()os.makedirs(log_path, exist_ok=True)log_filename = get_log_filename()log_file = os.path.join(log_path, log_filename)logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(levelname)s - %(message)s', filename=log_file)def get_log_filename():now = datetime.datetime.now()return now.strftime("%Y-%m-%d_%H-%M.log")def create_new_log():log_path = get_log_path()log_files = os.listdir(log_path)if len(log_files) >= 20:oldest_file = min(log_files)os.remove(os.path.join(log_path, oldest_file))log_filename = get_log_filename()log_filepath = os.path.join(log_path, log_filename)return log_filepathdef check_log_size(log_filepath):log_size = os.path.getsize(log_filepath)if log_size > 2 * 1024 * 1024:# 创建新的日志文件new_log_filepath = create_new_log()try:shutil.move(log_filepath, new_log_filepath)return new_log_filepathexcept PermissionError:insert_log(logger, f'{log_filepath} {PermissionError}', log_filepath)time.sleep(0.1)return log_filepathreturn log_filepathdef insert_log(logger, log_message, log_filepath):log_filepath = check_log_size(log_filepath)# 创建文件处理器file_handler = RotatingFileHandler(log_filepath, maxBytes=2 * 1024 * 1024, backupCount=1)file_handler.setLevel(logging.DEBUG)formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')file_handler.setFormatter(formatter)# 添加文件处理器到日志记录器logger.addHandler(file_handler)try:logger.debug(log_message)except PermissionError:insert_log(logger, f'{log_message} {PermissionError}', log_filepath)time.sleep(0.1)  # 延迟0.1秒# 移除文件处理器logger.removeHandler(file_handler)# 定义个函数,使其专门重复处理客户端的请求数据(也就是重复接受一个用户的消息并且重复回答,直到用户选择下线)
def client_request_1(tcp_client_1, tcp_client_address):#print(tcp_client_1)# 循环接收和发送数据while True:# #print(datetime.datetime.today())# msg=["010300000005859C","02020000000879FF"]# msg=['010300010001D5CA',"02020000000879FF"]# msg=["010300000001840A","02020000000879FF"]#8点位msg=msg_address(tcp_client_address)# interval =60interval = int(60 / len(msg))# print(interval,type(interval))for i in msg:try:tcp_client_1.send(binascii.unhexlify(i))recv_data = tcp_client_1.recv(4096)# 有消息就回复数据,消息长度为0就是说明客户端下线了if recv_data:# #print(f"recv_data:{recv_data}")bistr = binascii.hexlify(recv_data).decode('utf8')# print("==================================================")# print(f"读数:【{bistr}】,{len(bistr)}")try:if (bistr.startswith('010302') or bistr.startswith('030302') ) and len(bistr) >=14:bistr=bistr[:15]# # 输入数据input_data = bistr[:-4]# # 计算带有校验码的结果result = calculate_checksum(input_data)if bistr == result:waterLevel = int(bistr[6:10], 16)print("水深", waterLevel, "cm", bistr, bistr[6:10], bistr[:-4], bistr[-4:], "input_data:",{input_data}, " result:", {result})# #print(bistr==result)ip_address(tcp_client_address[0], tcp_client_address[1], waterLevel, 'water')if bistr.startswith("020201") and len(bistr) >= 12:bistr = bistr[:13]# 输入数据input_data = bistr[:-4]# 计算带有校验码的结果result = calculate_checksum(input_data)# #print(result==bistr)if result == bistr:data = data_address(bistr)#print(f"水泵采集模块状态:{data}")ip_address(tcp_client_address[0], tcp_client_address[1], data, 'status')ip_address(tcp_client_address[0], tcp_client_address[1], data, 'fault')if bistr.startswith("0104") and len(bistr) >= 14:bistr = bistr[:15]# 输入数据input_data = bistr[:-4]# # 计算带有校验码的结果result = calculate_checksum(input_data)if result == bistr:# #print(f"bistr[6:10]:{bistr[6:10]}")data =int(bistr[6:10], 16)#print(f"漏液检测状态:{data}")ip_address(tcp_client_address[0], tcp_client_address[1], data, 'liquid')except Exception as e:insert_log(logger, f'{tcp_client_address} {e}', log_filepath)#print(e)else:#print("%s 客户端下线了..." % tcp_client_address[1])insert_log(logger, f'{tcp_client_address[1]} OFFLINE', log_filepath)tcp_client_1.close()break# time.sleep(interval)time.sleep(2)except Exception as e:insert_log(logger, f'{tcp_client_address} {i} {e}', log_filepath)#print(f"{tcp_client_address} {i} {e}")# 连接数据库
def connect_database(host, port, user, password, db_name):try:conn = pymysql.connect(host=host, port=port, user=user, password=password, db=db_name)# print("成功连接到数据库")return connexcept pymysql.Error as e:insert_log(logger, f'DATABASE CONNECT FAILED', log_filepath)# print(f"数据库连接失败: {e}")# 插入数据
def insert_data(conn, types,table_name, create_time, location_no, parameter_desc, location, param_value):try:cursor = conn.cursor()sql = f"INSERT INTO {table_name} (TYPE, CREATE_TIME, LOCATION_NO, PARAMETER_DESC, LOCATION, PARAMVALUE) " \f"VALUES (%s, %s, %s, %s, %s, %s)"cursor.execute(sql, (types,create_time, location_no, parameter_desc, location, param_value))conn.commit()# print(f"数据插入成功: {create_time}, {parameter_desc}: {param_value}")cursor.close()except pymysql.Error as e:insert_log(logger, f'DATABASE INSERT DATA FAILED', log_filepath)# print(f"数据插入失败: {e}")def msg_address(tcp_client_address):if tcp_client_address[0] == '根据实际IP修改' or tcp_client_address[0] == '根据实际IP修改' or tcp_client_address[0] == '根据实际IP修改' :msg = ["010300000001840A", "02020000000879FF"]  # 8点位无其他,水位01,状态02return msgif (tcp_client_address[0] == '根据实际IP修改' and tcp_client_address[1] == 10010 )or tcp_client_address[0] == '根据实际IP修改' or (tcp_client_address[0] == '根据实际IP修改'  and tcp_client_address[1] == 10000 ) or tcp_client_address[0] == '根据实际IP修改'  or tcp_client_address[0] == '根据实际IP修改' :msg =["010300000001840A", "02020000000879FF"]  # 4点位非漏液,水位01,状态02return msgif (tcp_client_address[0] =='根据实际IP修改'  and tcp_client_address[1] == 10000 )or (tcp_client_address[0] == '根据实际IP修改'  and tcp_client_address[1] == 10010):msg = ["01040000000131CA"]  # 4点位漏液return msgif tcp_client_address[0] == '根据实际IP修改' :msg = ["010300010001D5CA","01040000000131CA"]  # 2点位漏液,漏液01,水位02return msgif tcp_client_address[0] == '根据实际IP修改' :msg = ["03030000000185E8","02020000000879FF"]  # 展厅漏液01,水位03,状态02# msg = ["03030000000185E8", "02020000000879FF", "01040000000131CA"]  # 展厅漏液01,水位03,状态02return msg#ip判断
def ip_address(ip,port,param_value,notes):host = ''#根据实际情况自定义port = 3306user =''#根据实际情况自定义password = ''#根据实际情况自定义db_name = ''#根据实际情况自定义table_name =''#根据实际情况自定义# 连接数据库conn = connect_database(host, port, user, password, db_name)#8点位采集+水尺if str(ip)==''#根据实际情况自定义:#只有1号端口#水位尺数据#采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location = ''#根据实际情况自定义# 模拟数据if notes=='water':location_no =''#根据实际情况自定义parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes=='status':data=param_value# print("data:",data)status1=data[0]#1status2=data[1]#2status3=data[4]#5status4=data[6]#7# print("status1,status2,status3,status4:",status1,status2,status3,status4)# # 插入1号数据location_no = 'D04-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D04-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)# 插入3号数据location_no = 'D04-03'parameter_desc = '3号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status3)# 插入4号数据location_no = 'D04-04'parameter_desc = '4号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status4)if notes=='fault':data = param_valuefault1 = data[2]#3fault2 = data[3]#4fault3 = data[5]#6fault4 = data[7]#8# print("fault1,fault2,fault3,fault4:",fault1,fault2,fault3,fault4)# 插入1号数据location_no = 'D04-05'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D04-06'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)# 插入3号数据location_no = 'D04-07'parameter_desc = '3号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault3)# 插入4号数据location_no = 'D04-08'parameter_desc = '4号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault4)# 8点位采集+水尺if str(ip)==''#根据实际情况自定义:#只有1号端口#水位尺数据#采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location =''#根据实际情况自定义# 模拟数据if notes=='water':location_no = 'D07'parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes=='status':data=param_valuestatus1=data[0]status2=data[1]status3=data[2]status4=data[3]#print("status1,status2,status3,status4:",status1,status2,status3,status4)# 插入1号数据location_no = 'D07-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D07-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)# 插入3号数据location_no = 'D07-03'parameter_desc = '3号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status3)# 插入4号数据location_no = 'D07-04'parameter_desc = '4号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status4)if notes=='fault':data=param_valuefault1 = data[4]fault2 = data[5]fault3 = data[6]fault4 = data[7]#print("fault1,fault2,fault3,fault4:",fault1,fault2,fault3,fault4)# 插入1号数据location_no = 'D07-05'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D07-06'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)# 插入3号数据location_no = 'D07-07'parameter_desc = '3号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault3)# 插入4号数据location_no = 'D07-08'parameter_desc = '4号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault4)# 8点位采集+水尺if str(ip) == ''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location = ''#根据实际情况自定义# 模拟数据if notes == 'water':location_no = 'D08'parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'status':data=param_valuestatus1 = data[0]status2 = data[1]status3 = data[2]status4 = data[3]#print("status1,status2,status3,status4:", status1, status2, status3, status4)# 插入1号数据location_no = 'D08-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D08-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)# 插入3号数据location_no = 'D08-03'parameter_desc = '3号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status3)# 插入4号数据location_no = 'D08-04'parameter_desc = '4号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status4)if notes == 'fault':data=param_valuefault1 = data[4]fault2 = data[5]fault3 = data[6]fault4 = data[7]#print("fault1,fault2,fault3,fault4:", fault1, fault2, fault3, fault4)# 插入1号数据location_no = 'D08-05'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D08-06'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)# 插入3号数据location_no = 'D08-07'parameter_desc = '3号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault3)# 插入4号数据location_no = 'D08-08'parameter_desc = '4号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault4)# 4点位采集+水尺if str(ip) ==''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location = ''#根据实际情况自定义# 模拟数据if notes == 'water':location_no = 'D09'parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'status':data=param_valuestatus1 = data[0]status2 = data[1]#print("status1,status2:", status1, status2)# 插入1号数据location_no = 'D09-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D09-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)if notes == 'fault':data=param_valuefault1 = data[2]fault2 = data[3]#print("fault1,fault2:", fault1, fault2)# 插入1号数据location_no = 'D09-03'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D09-04'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)if notes == 'liquid':data_liquid = param_value# 插入漏液数据location_no = 'F03'parameter_desc = ''#根据实际情况自定义location=''#根据实际情况自定义insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, data_liquid)# 4点位采集+水尺if str(ip) ==''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location =''#根据实际情况自定义# 模拟数据if notes == 'water':location_no = 'D06'parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'status':data=param_valuestatus1 = data[0]status2 = data[1]#print("status1,status2:", status1, status2)# 插入1号数据location_no = 'D06-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D06-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)if notes == 'fault':data=param_valuefault1 = data[2]fault2 = data[3]#print("fault1,fault2:", fault1, fault2)# 插入1号数据location_no = 'D06-03'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D06-04'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)# 4点位采集+水尺if str(ip) ==''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location = ''#根据实际情况自定义# 模拟数据if notes == 'water':location_no = 'D05'parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'status':data=param_valuestatus1 = data[0]status2 = data[1]# 插入1号数据location_no = 'D05-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D05-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)if notes == 'fault':data=param_valuefault1 = data[2]fault2 = data[3]# 插入1号数据location_no = 'D05-03'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D05-04'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)if notes == 'liquid':data_liquid = param_value# 插入漏液数据location_no = 'F02'parameter_desc =''#根据实际情况自定义location=''#根据实际情况自定义insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, data_liquid)# 4点位采集+水尺if str(ip) == ''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location = ''#根据实际情况自定义# 模拟数据if notes == 'water':location_no = 'D03'parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'status':data=param_valuestatus1 = data[0]status2 = data[1]#print("status1,status2:", status1, status2)# 插入1号数据location_no = 'D03-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D03-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)if notes == 'fault':data=param_valuefault1 = data[2]fault2 = data[3]#print("fault1,fault2:", fault1, fault2)# 插入1号数据location_no = 'D03-03'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D03-04'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)# 4点位采集+水尺if str(ip) == ''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location =''#根据实际情况自定义# 模拟数据if notes == 'water':location_no = 'D01'parameter_desc = '水位值'# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'status':data=param_valuestatus1 = data[0]status2 = data[1]#print("status1,status2:", status1, status2)# 插入1号数据location_no = 'D01-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D01-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)if notes == 'fault':data=param_valuefault1 = data[2]fault2 = data[3]#print("fault1,fault2:", fault1, fault2)# 插入1号数据location_no = 'D01-03'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D01-04'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)# 4点位采集+水尺if str(ip) == ''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()location =''#根据实际情况自定义# 模拟数据if notes == 'water':location_no = 'D02'parameter_desc = '水位值'print( 'water:',param_value)# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'status':data=param_valuestatus1 = data[0]status2 = data[1]print("status1,status2:", status1, status2)# 插入1号数据location_no = 'D02-01'parameter_desc = '1号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status1)# 插入2号数据location_no = 'D02-02'parameter_desc = '2号泵浦状态'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, status2)if notes == 'fault':data=param_valuefault1 = data[2]fault2 = data[3]print("fault1,fault2:", fault1, fault2)# 插入1号数据location_no = 'D02-03'parameter_desc = '1号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault1)# 插入2号数据location_no = 'D02-04'parameter_desc = '2号泵浦故障'insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, fault2)if notes == 'liquid':data_liquid = param_valueprint('liquid:'.data_liquid)# 插入漏液数据location_no = 'F01'parameter_desc =''#根据实际情况自定义location=''#根据实际情况自定义insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, data_liquid)# 2点位采集+水尺if str(ip) == ''#根据实际情况自定义:# 只有1号端口# 水位尺数据# 采集模块数据# 数据库连接信息types = '防汛'create_time = datetime.datetime.now()# 模拟数据if notes == 'water':location_no = 'D10'parameter_desc = '水位值'location =''#根据实际情况自定义# 插入数据insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, param_value)if notes == 'liquid':data_liquid = param_value# 插入漏液数据location_no = 'F04'parameter_desc = ''#根据实际情况自定义location = ''#根据实际情况自定义insert_data(conn, types, table_name, create_time, location_no, parameter_desc, location, data_liquid)def data_address(data):extracted_data = data[6:8]binary_data = bin(int(extracted_data, 16))[2:].zfill(8)reversed_data = binary_data[::-1]return reversed_data#CRC校验
def calculate_crc(data):crc = 0xFFFFpolynomial = 0xA001for byte in data:crc ^= bytefor _ in range(8):if crc & 0x0001:crc >>= 1crc ^= polynomialelse:crc >>= 1return crcdef calculate_checksum(data):# 将输入数据转换为字节列表data_bytes = bytes.fromhex(data)# 计算校验码crc_value = calculate_crc(data_bytes)crc_bytes = crc_value.to_bytes(2, 'big')  # 将校验码转换为2字节的大端字节序checksum = ''.join(format(byte, '02x') for byte in reversed(crc_bytes))  # 转换为十六进制字符串,并反转字节顺序# 将校验码插入到原数据之后result = data + checksumreturn resultif __name__ == '__main__':configure_logging()cleanup_logs()log_filepath = create_new_log()logger = logging.getLogger()logger.setLevel(logging.DEBUG)oldtime = datetime.datetime.today()# 创建服务端套接字对象tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 设置端口复用,使程序退出后端口马上释放tcp_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)# 绑定端口tcp_server.bind(("", 8050))# 设置监听tcp_server.listen(128)# 循环等待客户端连接请求while True:tcp_client_1, tcp_client_address = tcp_server.accept()tcp_client_1.settimeout(10)# 创建多线程对象thd = threading.Thread(target=client_request_1, args=(tcp_client_1, tcp_client_address))# #print(thd)# 设置守护主线程thd.setDaemon(True)# 启动子线程对象thd.start()# 关闭服务器套接字# tcp_server.close()`

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/2654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

数字原生时代,奥哲如何让企业都成为“原住民”?

22年前,美国教育学家马克‧普伦斯基(Marc Prensky)出版了《数字原生与数字移民》(Digital Natives, Digital Immigrants)一书,首次提出了“数字原住民”和“数字移民”两大概念,用来定义跨时代的…

法规发展与算法备案:预测未来的重要议题

随着科技的快速发展,算法逐渐成为各行各业的核心驱动力,尤其在互联网领域,算法更是被赋予了生命力,为人们提供了便利的同时,也引发了一系列问题。因此,未来法规发展对于算法备案的关注将变得尤为重要。本文…

05-Vue基础之Class 与 Style 绑定

个人名片: 😊作者简介:一名大二在校生 🤡 个人主页:坠入暮云间x 🐼座右铭:懒惰受到的惩罚不仅仅是自己的失败,还有别人的成功。 🎅**学习目标: 坚持每一次的学习打卡 文章…

OpenCV如何实现图像截取

import cv2img cv2.imread("image/2.png", 1) roi cv2.selectROI(img,showCrosshairTrue,fromCenterFalse) xmin,ymin,w,h roi imgROI img[ymin:yminh,xmin:xminw].copy()cv2.imshow("demo",imgROI) cv2.waitKey(0) 代码的核心就是用到了OpenCV中的函数…

leetcode_54 螺旋矩阵

1. 题目 螺旋矩阵 2. 题意 给定一个二维数组,顺时针螺旋输出其中的元素。 3. 题解 3.1 自己想的 一层一层的,关键点在于如何进入下一循环。和确定停止的位置,找停止的位置写了个函数。 用控制比特位的方式来进行控制一次顺时针循环, 还…

序列化的意义以及常见的的序列化方式

一,为什么序列化? 对象保存到文件或数据库网络编程时对象跨平台跨语言传输,也即从windows上序列化的对象可到linux上反序列化,用c#序列化的对象可以被java反序列化。RPC远程接口调用 二,常见得序列化方式…

【数据结构】_1.集合与复杂度

目录 1. 集合框架 2. 时间复杂度 2.1 时间复杂度和空间复杂度 2.2 时间复杂度的概念 2.3 大O的渐进表示法 2.3.1 精确的时间复杂度表达式 2.3.2 大O渐进表示法的三条规则 2.3.3 时间复杂度的最好、平均与最坏情况 2.4 时间复杂度计算示例 3.空间复杂度 1. 集合框架 …

字节跳动后端面试,笔试部分

var code "7022f444-ded0-477c-9afe-26812ca8e7cb" 背景 笔者在刷B站的时候,看到了一个关于面试的实录,前半段是八股文,后半段是笔试部分,感觉笔试部分的题目还是挺有意思的,特此记录一下。 笔试部分 问…

【多线程例题】顺序打印abc线程

顺序打印-进阶版 方法一:三个线程竞争同一个锁,通过count判断是否打印 方法二:三个线程同时start,分别上锁,从a开始,打印后唤醒b 三个线程分别打印A,B,C 方法一:通过co…

JavaFX中MVC例子理解

JavaFX可以让你使用GUI组件创建桌面应用程序。一个GUI应用程序执行三个任务:接受用户的输入,处理输入,并显示输出。而一个GUI应用程序包含两个 类型的代码: 领域代码。处理特定领域的数据和遵循业务规范。交互代码。处理用户输入…

【Linux】多线程(上)

本文详细介绍了多线程的常见概念 生产者消费者模型将在多线程(下)继续讲解 欢迎大家指正 提起讨论进步啊 目录 多线程的理解 线程的优点 线程的缺点: 线程的用途 线程VS进程 用户级线程库 POSIX线程库 线程创建: 线程…

springboot整合jwt

JWT介绍 JWT是JSON Web Token的缩写,即JSON Web令牌,是一种自包含令牌。 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。 JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获…

DICOM开源库兼容性问题

常见的DICOM开源库有dcmtk、fo-dicom、dcm4che3等,DICOM开源库遇到的兼容性问题类似,——dcmtk兼容性最强,fo-dicom次之,dcm4che3最差。 本人在dicom医学影像方面从事软件开发已有10几年,用过dcmtk,fo-dico…

Android国际化各国语言简写

<?xml version"1.0" encoding"utf-8"?> <locale-config xmlns:android"http://schemas.android.com/apk/res/android"><locale android:name"af"/> <!-- 南非荷兰语 --><locale android:name"am&qu…

Spark(32):Spark性能调优之Shuffle调优

目录 0. 相关文章链接 1. 调节 map 端缓冲区大小 2. 调节 reduce 端拉取数据缓冲区大小 3. 调节 reduce 端拉取数据重试次数 4. 调节 reduce 端拉取数据等待间隔 5. 调节 SortShuffle 排序操作阈值 0. 相关文章链接 Spark文章汇总 1. 调节 map 端缓冲区大小 在 Spark 任…

基于.net6的WPF程序使用SignalR进行通信

之前写的SignalR通信&#xff0c;是基于.net6api&#xff0c;BS和CS进行通信的。 .net6API使用SignalRvue3聊天WPF聊天_signalr wpf_故里2130的博客-CSDN博客 今天写一篇关于CS客户端的SignalR通信&#xff0c;后台服务使用.net6api 。其实和之前写的差不多&#xff0c;主要在…

Ubuntu22.04密码忘记怎么办 Ubuntu重置root密码方法

在Ubuntu 22.04 或其他更高版本上不小心忘记root或其他账户的密码怎么办&#xff1f; 首先uname -r查看当前系统正在使用的内核版本&#xff0c;记下来 前提&#xff1a;是你的本地电脑&#xff0c;有物理访问权限。其他如远程登录的不适用这套改密方法。 通过以下步骤&#…

写字楼/办公楼能源管理系统的具体应用 安科瑞 许敏

0 引言 随着社会的进步&#xff0c;我国经济的快速发展&#xff0c;企业的办公环境和方式发生了巨大的变化&#xff0c;专业的写字楼在各大城市遍布林立。写字楼的出现使得各地企业办公集中化、高效化&#xff0c;然而写字楼物业管理的同步发展对于企业服务来说更是一个很大的…

SciencePub学术 | 区块链类重点SCIEEI征稿中

SciencePub学术 刊源推荐: 区块链类重点SCIE&EI征稿中&#xff01;信息如下&#xff0c;录满为止&#xff1a; 一、期刊概况&#xff1a; SCI-01 【期刊简介】IF&#xff1a;4.0-4.5&#xff0c;JCR2区&#xff0c;中科院3区&#xff1b; 【检索情况】SCIE&EI双检&…

Mysql+ETLCloud CDC+StarRocks实时数仓同步实战

一、业务需求及其痛点 大型企业需要对各种业务系统中的销售及营销数据进行实时同步分析&#xff0c;例如库存信息、对帐信号、会员信息、广告投放信息&#xff0c;生产进度信息等等&#xff0c;这些统计分析信息可以实时同步到StarRocks中进行分析和统计&#xff0c;StarRocks…