上次實驗已經成功連接數據庫...
這次實驗就是將數據傳入數據庫,因爲數據庫中存溫溼度的 表是cdsjb,與其關聯的表有cdb和bcxmb,所以需要對三個表都做處理才能正常傳入數據。
程序如下:
#!/usr/bin/env python3 # -*- coding:utf-8 -*- u''' Created on 2018年5月22日 @author: RJ ''' __author__ = 'RJ <[email protected]>' __version__ = '1.0.0' __company__ = u'重慶交大' __updated__ = '2018-05-22 16:43' import socket import codecs import time import pymysql import datetime import struct """ client connect() recv() send() sendall() """ # 以字典形式創建數據庫配置信息,方便修改 PY_MYSQL_CONN_DICT = { "host": '10.1.161.209', "port": 3306, "user": 'bridge', "passwd": '123456', "db": 'bridge', "charset": 'utf8' } 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校驗 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): u''' 16進制轉字節流 ''' if not isinstance(x, str): x = str(x, 'ascii') return bytes.fromhex(x) def bytestohex(x): u''' 字節流轉16進制 ''' if not isinstance(x, bytes): x = bytes(x, 'ascii') return ''.join(["%02x" % i for i in x]).strip() def fetchone(): conn = 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 insertone(**kwargs): conn = 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() def fetchtwo(): conn = dbConnect() cursor = conn.connect() cursor.execute("select * from cdsjb") result = cursor.fetchall() conn.close() print("success") return result def inserttwo(**kwargs): conn = 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() def insertthree(gcxmbm, gcxmmc): conn = dbConnect() cursor = conn.connect() sql = """insert into gcxmb(gcxmbm,gcxmmc) values(%s,%s)""" cursor.execute(sql, (gcxmbm, gcxmmc)) conn.close() def fetchthree(): conn = dbConnect() cursor = conn.connect() sql = """ select * from gcxmb """ cursor.execute(sql) result = cursor.fetchone() conn.close() return result 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 = "631507030233冉傑", "溫溼度處理" # 這個爲自己設定的工程項目編碼和名稱,用於後面對gcxmb表的操作 # 提前定義工程編碼和名稱,因爲需要對溫度和溼度進行操作,所以定義兩個,也是用於後面對cdb表的操作 cdbm1, cdbm2 = "shidu", "wendu" cdmc1, cdmc2 = "溼度", "溫度" while True: list_wendu = [] list_shidu = [] global inst_wendu # 瞬時溫度 global inst_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(result[:-2]) # 進行CRC16-2校驗 if crc == result[-2:]: print('CRC16成功') shidu, wendu = struct.unpack('>hh', result[3:7]) # 用struct方法解析溼度和溫度 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) end_time = time.time() # 獲取結束時的時間戳 if(end_time - begin_time > 5): # 如果如果兩次間隔大於五秒,停止讀取數據,開始對數據進行處理 inst_wendu = list_wendu[-1] # 數組最後一個就是當時的瞬時值 inst_shidu = list_shidu[-1] time.sleep(0.1) break else: # 時間沒有大於五秒則繼續讀取數據 continue cur_time = datetime.datetime.now() # 記錄處理完成的時間 print("瞬時溫度%s" % (inst_wendu), cur_time) print("瞬時溼度%s" % (inst_shidu), cur_time) print("開始向數據庫傳入數據...") gcxmb_data = fetchthree() # 先對gcxmb表進行查詢,如果存在數據,則進行下一步,如果不存在就插入數據 if not gcxmb_data: try: insertthree(gcxmbm, gcxmmc) except Exception: print("工程項目表插入失敗") cdb_data = fetchone() # 對cdb表進行查詢,存在數據則跳過,不存在則插入數據 if not cdb_data: try: insertone(gcxmbm=gcxmbm, cdbm=cdbm1, cdmc=cdmc1, cgqbm="03", jldw="RH", sflb=1) insertone(gcxmbm=gcxmbm, cdbm=cdbm2, cdmc=cdmc2, cgqbm="03", jldw="攝氏度", sflb=1) except Exception: print("測點表插入失敗 ") try: # 插入處理後的數據 inserttwo(gcxmbm=gcxmbm, cdbm=cdbm1, clsj=cur_time, inst=inst_shidu) inserttwo(gcxmbm=gcxmbm, cdbm=cdbm2, clsj=cur_time, inst=inst_wendu) print("傳入成功") except: print("測點數據表插入失敗") sk.close() main()
運行之前記得連接校網,打開虛擬機,ifconfig查詢ip,修改程序。
運行結果:
插入後打開數據庫查看數據:
cdb表:
cdsjb表:
gcxmb表:
這次實驗這裏只是將獲得的數據做簡單的處理傳進去,
並沒有獲取平均值,最大值,最小值一同傳進去。
下次實驗是對數據做處理......