版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/pengyangyan/article/details/80343415
程序结构
Brige---+
- ----dbconnect.py (数据库连接和配置信息)
- ----crc16.py (CRC16校验程序)
- ---- cdb.py (对数据库cdb表的操作)
- ----cdsjb.py (对数据库cdsjb表的操作)
- ----gcxmb.py (对数据库gcxmb表的操作)
- ----last_data.txt (用于保存上一次读取的温湿度,用于筛选波动太大的数据)
- ----mian.py (第一版 未对数据进行处理的主函数)
- ----maincopy.py (第二版 对数据进行处理后的主函数)
- ----+
程序内容
dbconnect.py
#以字典形式创建数据库配置信息,方便修改
PY_MYSQL_CONN_DICT = {
"host": '10.103.102.96',
"port": 3306,
"user": 'bridge',
"passwd": '123456',
"db": '现场终端数据',
"charset": 'utf8'
}
import pymysql
class dbConnect:
def __init__(self):
self.conn = None
self.cursor = None
self.__conn_dict = PY_MYSQL_CONN_DICT
def connect(self, cursor=pymysql.cursors.DictCursor):
try:
self.conn = pymysql.connect(**self.__conn_dict)
self.cursor = self.conn.cursor(cursor=cursor) #数据库连接成功并返回游标
return self.cursor
except Exception as e:
print("连接失败:%s"%e)
def close(self):
self.conn.commit()
self.cursor.close()
self.conn.close()
crc16.py
def crc16(x):
u'''
@summary: 计算CRC16值
@param x: bytes
@return: 返回2字节值,类似:b'\x7B\x2A'。
'''
if not isinstance(x, bytes):
raise ValueError('Parameter must be a bytes type')
b = 0xA001
a = 0xFFFF
for byte in x:
a = a ^ byte
for _ in range(8):
last = a % 2
a = a >> 1
if last == 1:
a = a ^ b
aa = '0' * (6 - len(hex(a))) + hex(a)[2:]
ll, hh = int(aa[:2], 16), int(aa[2:], 16)
rtn = '%x' % (hh * 256 + ll & 0xffff)
while len(rtn) < 4:
rtn = '0' + rtn
rtn = hextobytes(rtn)
return rtn
def hextobytes(x):
if not isinstance(x, str):
x = str(x, 'ascii')
return bytes.fromhex(x)
def bytestohex(x):
if not isinstance(x, bytes):
x = bytes(x, 'ascii')
return ''.join(["%02x" % i for i in x]).strip()
cdb.py
from Brige import dbconnect
def fetchone():
conn = dbconnect.dbConnect()
cousor = conn.connect()
sql ="""SELECT gcxmbm cdbm, cdmc, cgqbm, jldw, sfqy, sjlx, sflb, lbfs, lbcs, bz FROM cdb WHERE 1 """
cousor.execute(sql)
result = cousor.fetchone() #获取第一一条数据并返回结果
conn.close()
return result
def insert(**kwargs):
conn = dbconnect.dbConnect()
cursor = conn.connect()
sql = """insert into cdb(%s) values(%s)"""
key_list = []
value_list = []
for k, v in kwargs.items():
key_list.append(k)
value_list.append('%%(%s)s' % k)
sql = sql % (','.join(key_list), ','.join(value_list))
cursor.execute(sql, kwargs)
conn.close()
cdsjb.py
from Brige import dbconnect
def fetch():
conn = dbconnect.dbConnect()
cursor = conn.connect()
cursor.execute("select * from cdsjb")
result = cursor.fetchall()
conn.close()
print("success")
return result
def insert(**kwargs):
conn = dbconnect.dbConnect()
cursor =conn.connect()
sql = """insert into cdsjb(%s) values(%s)"""
key_list = []
value_list = []
for k, v in kwargs.items():
key_list.append(k)
value_list.append('%%(%s)s' % k)
sql = sql % (','.join(key_list), ','.join(value_list))
cursor.execute(sql, kwargs)
conn.close()
gcxmb.py
from Brige import dbconnect
def insert(gcxmbm,gcxmmc):
conn = dbconnect.dbConnect()
cursor = conn.connect()
sql = """insert into gcxmb(gcxmbm,gcxmmc) values(%s,%s)"""
cursor.execute(sql,(gcxmbm,gcxmmc))
conn.close()
def fetch():
conn = dbconnect.dbConnect()
cursor = conn.connect()
sql =""" select * from gcxmb """
cursor.execute(sql)
result = cursor.fetchone()
conn.close()
return result
main.py
import socket
import codecs
import time
import datetime
from Brige import crc16
import struct
from Brige import cdsjb,cdb,gcxmb
"""
client
connect()
recv()
send()
sendall()
"""
def main():
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print(sk)
address = ('10.1.156.82', 8001)
sk.connect(address)
inp = '030300000002c5e9'
gcxmbm, gcxmmc = "631507030103彭阳宴", "温湿度处理"
cdbm1, cdbm2 = "shidu", "wendu"
cdmc1, cdmc2 = "湿度", "温度"
while True:
sk.send(codecs.decode(inp, 'hex'))
try:
result = sk.recv(1024)
except socket.timeout:
print('timeout')
crc=crc16.crc16(result[:-2])
if crc==result[-2:]:
print('CRC16成功')
shidu,wendu=struct.unpack('>hh',result[3:7])
shidu/=100
wendu/=100
#比较上一次的温湿度的波动
with open("last_data",'r') as r:
last_data = r.read()
if not last_data:
continue
last_wendu,last_shidu = last_data.split("%")
last_wendu,last_shidu = float(last_wendu),float(last_shidu)
if(abs(shidu-last_shidu)>5 or abs(wendu-last_wendu>5)):
print("数字波动太大,未写入数据库")
continue
else:
#将当前温度湿度写入文档作为记录
data = str(wendu) + "%"+str(shidu)
with open("last_data",'w') as f:
f.write(data)
cur_time = datetime.datetime.now()
print("湿度:%s,温度:%s" % (shidu, wendu),datetime.datetime.now())
print("开始向数据库传入数据...")
gcxmb_data = gcxmb.fetch()
if not gcxmb_data:
try:
gcxmb.insert(gcxmbm,gcxmmc)
except Exception:
print("工程项目表插入失败")
cdb_data = cdb.fetchone()
if not cdb_data:
try:
cdb.insert(gcxmbm=gcxmbm,cdbm=cdbm1,cdmc=cdmc1,cgqbm="03",jldw="RH",sflb=1)
cdb.insert(gcxmbm=gcxmbm, cdbm=cdbm2, cdmc=cdmc2, cgqbm="03", jldw="摄氏度", sflb=1)
except Exception:
print("测点表插入失败 ")
try:
cdsjb.insert(gcxmbm=gcxmbm,cdbm=cdbm1,clsj=cur_time,inst=shidu)
cdsjb.insert(gcxmbm=gcxmbm, cdbm=cdbm2, clsj=cur_time, inst=wendu)
print("传入成功")
except:
print("测点数据表插入失败")
time.sleep(5)
sk.close()
main()
maincopy.py
import socket
import codecs
import time
import datetime
from Brige import crc16
import struct
from Brige import cdsjb,cdb,gcxmb
"""
client
connect()
recv()
send()
sendall()
"""
def main():
sk = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
print(sk)
address = ('10.1.156.82', 8001)
sk.connect(address)
inp = '030300000002c5e9' #远程需要接受的参数
gcxmbm, gcxmmc = "631507030103彭阳宴", "温湿度处理" #这个为自己设定的工程项目编码和名称,用于后面对gcxmb表的操作
#提前定义工程编码和名称,因为需要对温度和湿度进行操作,所以定义两个,也是用于后面对cdb表的操作
cdbm1, cdbm2 = "shidu", "wendu"
cdmc1, cdmc2 = "湿度", "温度"
while True:
total_wendu,total_shidu=0,0
list_wendu = []
list_shidu = []
global inst_wendu #瞬时温度
global inst_shidu #瞬时湿度
global avg_wendu #平均温度
global avg_shidu #平均湿度
global max_wendu #最大温度
global max_shidu #最大湿度
global min_wendu #最小温度
global min_shidu #最小湿度
n =0
begin_time = time.time() #开始读取是的时间戳
while True:
sk.send(codecs.decode(inp, 'hex'))
try:
result = sk.recv(1024)
except socket.timeout:
print('timeout')
crc=crc16.crc16(result[:-2]) #进行CRC16-2校验
if crc==result[-2:]:
print('CRC16成功')
shidu,wendu=struct.unpack('>hh',result[3:7]) #用struct方法解析湿度和温度,看不懂可以自行百度了解struct.unpack的用法
shidu/=100
wendu/=100
#比较上一次的温湿度的波动
with open("last_data",'r') as r:
last_data = r.read()
if not last_data: #如果last_data.txt中没有数据,就把当前温室度作为上一次温湿度进行比较
last_data = str(wendu)+'%'+str(shidu) #字符串拼接
last_wendu,last_shidu = last_data.split("%") #字符串以%拆分,得到温湿度
last_wendu,last_shidu = float(last_wendu),float(last_shidu) #转化为float型数值
if(abs(shidu-last_shidu)>5 or abs(wendu-last_wendu>5)): #比较当前温湿度与上一次温湿度差异,如果波动大于5就过滤掉
print(abs(shidu-last_shidu),abs(wendu-last_wendu))
print("数字波动太大,未记录")
continue
else:
# 将当前温度湿度写入文档作为记录
data = str(wendu) + "%" + str(shidu)
with open("last_data", 'w') as f:
f.write(data)
n += 1
list_shidu.append(shidu)
list_wendu.append(wendu)
total_wendu += wendu #对每一次温度进行累加
total_shidu +=shidu #对每一次湿度进行累加
end_time = time.time() #获取结束时的时间戳
if(end_time-begin_time>5): #如果如果两次间隔大于五秒,停止读取数据,开始对数据进行处理
inst_wendu = list_wendu[-1] #数组最后一个就是当时的瞬时值
inst_shidu = list_shidu[-1]
list_wendu.sort() #对数组进行排序 从小到大
list_shidu.sort()
avg_wendu = total_wendu/n #求平均值
avg_shidu = total_shidu/n
max_wendu = list_wendu[-1] #此时数组最后一个对最大值
max_shidu = list_shidu[-1]
min_wendu = list_wendu[0] #数组第一个为最小值
min_shidu = list_shidu[0]
time.sleep(0.1)
break
else: #时间没有大于五秒则继续读取数据
continue
cur_time = datetime.datetime.now() #记录处理完成的时间
print("最大温度%s,最小温度%s,平均温度%s,瞬时温度%s" %(max_wendu,min_wendu,avg_wendu,inst_wendu),cur_time)
print("最大湿度%s,最小湿度%s,平均湿度%s,瞬时湿度%s" % (max_shidu, min_shidu, avg_shidu, inst_shidu),cur_time)
print("开始向数据库传入数据...")
gcxmb_data = gcxmb.fetch() #先对gcxmb表进行查询,如果存在数据,则进行下一步,如果不存在就插入数据
if not gcxmb_data:
try:
gcxmb.insert(gcxmbm,gcxmmc)
except Exception:
print("工程项目表插入失败")
cdb_data = cdb.fetchone() #对cdb表进行查询,存在数据则跳过,不存在则插入数据
if not cdb_data:
try:
cdb.insert(gcxmbm=gcxmbm,cdbm=cdbm1,cdmc=cdmc1,cgqbm="03",jldw="RH",sflb=1)
cdb.insert(gcxmbm=gcxmbm, cdbm=cdbm2, cdmc=cdmc2, cgqbm="03", jldw="摄氏度", sflb=1)
except Exception:
print("测点表插入失败 ")
try: #插入处理后的数据
cdsjb.insert(gcxmbm=gcxmbm,cdbm=cdbm1,clsj=cur_time,avg=avg_shidu,max=max_shidu,min=min_shidu,inst=inst_shidu)
cdsjb.insert(gcxmbm=gcxmbm, cdbm=cdbm2, clsj=cur_time,avg=avg_wendu,max=max_wendu,min=min_wendu,inst=inst_wendu)
print("传入成功")
except:
print("测点数据表插入失败")
sk.close()
main()
运行截图:
注意:
1.main.py和maincopy.py只需要运行其中一个,last_data.txt最开始为空。
2.运行时注意修改配置信息
3.程序有时候可能有bug,多运行几次就好了。
4.所有py文件创建在一个名为Brige的包下面,也可以自己修改