用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)一书,首次提出了“数字原住民”和“数字移民”两大概念,用来定义跨时代的…

【数据结构】_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的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获…

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

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

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

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

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

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

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

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

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

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

vue注意点:$attrs、$slots!插槽

$attrs 当父组件给子组件传值&#xff0c;子组件并没有接收数据时&#xff0c;此时数据在$attrs中可以拿到&#xff0c;并且如果子组件不需要使用数据&#xff0c;而孙组件需要&#xff0c;则可以直接v-bind"$attrs"传给孙。 <-- 父组件 --> <div><…

[java安全]URLDNS

文章目录 [java安全]URLDNS前言HashMapURLURLStreamHandler调用过程调用链流程图POC [java安全]URLDNS 前言 URLDNS利用链是一条很简单的链子&#xff0c;可以用来查看java反序列化是否存在反序列化漏洞&#xff0c;如果存在&#xff0c;就会触发dns查询请求 它有如下优点&a…

Centos 8 / TencentOS Server 3.1 安装 docker-ce

目录 前言安装 docker-ce设置Docker Hub 镜像缓存参考 前言 TencentOS Server 3.1(与 CentOS 8用户态完全兼容&#xff0c;配套基于社区5.4 LTS 内核深度优化的 tkernel4版本) 安装 docker-ce 先卸载老版本&#xff0c;没有老版本的跳过 yum remove docker \docker-client \d…

常见面试题之HashMap

1. 二叉树 1.1 二叉树概述 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只有左子节点&#xff0c;有的节…

前端基本功 用 React Hooks + Antd 实现一个 Todo-List

背景 使用 React Hooks 以及组件库 Antd 来实现一个可以 增删 标记是否完成 的 todo-list 思路 要实现一个 todo-list 首先想到用 useState 维护一个状态数组来保存当前 list &#xff0c;还要用一个状态维护添加框中的内容 const [todos, setTodos] useState(initialValu…

Excel之VLOOKUP()函数介绍

Excel之VLOOKUP()函数介绍 Excel的VLOOKUP函数语法&#xff1a; VLOOKUP(lookup_value, table_array, col_index_num, [range_lookup]) 参数说明&#xff1a; lookup_value&#xff1a;要查找的值或要比较的值。 table_array&#xff1a;包含要在其中进行查找的数据表的区…

解决打开excel时报错 “不能使用对象链接和嵌入”

问题截图 打开excel文件或者插入对象时&#xff0c;直接弹出不能使用对象链接和嵌入报错信息。 解决方法 按 winr 组合快捷键&#xff0c;打开运行&#xff0c;输入 dcomcnfg.exe 按回车确定 此时进入到组件服务管理界面&#xff0c;依次选择 组件服务-计算机-我的电脑-DOCM…

S3C2440点亮LED(裸机开发)

文章目录 前言一、环境介绍一、GPIO介绍二、点亮开发板的LED1.预备动作2.led代码 总结 前言 本期和大家主要分享的是使用S3C2440开发板点亮一个LED灯&#xff0c;可能大家拿到开发板之后做的第一件事情都是点灯&#xff0c;这是为什么呢&#xff1f;因为点灯这件事情不仅能够检…