|
@@ -10,6 +10,8 @@ import socket
|
|
|
from connector import Connector
|
|
|
from event_storage import EventStorage
|
|
|
from log import Log
|
|
|
+from binascii import *
|
|
|
+from crcmod import *
|
|
|
|
|
|
sendFlag = 0
|
|
|
|
|
@@ -17,6 +19,8 @@ sendFlag = 0
|
|
|
class ShuizhiTcpConnector(Connector, threading.Thread):
|
|
|
def __init__(self, name, config, converter):
|
|
|
super().__init__()
|
|
|
+ self._param_id = {}
|
|
|
+ self._len_param = None
|
|
|
self.__log = Log()
|
|
|
self.__sock = None
|
|
|
self.__connected = False
|
|
@@ -30,6 +34,7 @@ class ShuizhiTcpConnector(Connector, threading.Thread):
|
|
|
self.setName(name)
|
|
|
self.__last_seve_time = 0
|
|
|
self.__data_point_config = self.__storager.get_station_info(name)
|
|
|
+ self._storage = EventStorage()
|
|
|
# for i in self.__data_point_config:
|
|
|
# print(i)
|
|
|
|
|
@@ -47,6 +52,7 @@ class ShuizhiTcpConnector(Connector, threading.Thread):
|
|
|
try:
|
|
|
self.__sock.connect((self.__ip, self.__port))
|
|
|
self.__log.info(f'Connect to [{self.get_name()}]:[{self.__ip}]:[{self.__port}] success !')
|
|
|
+ print(f'Connect to [{self.get_name()}]:[{self.__ip}]:[{self.__port}] success !')
|
|
|
self.__connected = True
|
|
|
except socket.error as e:
|
|
|
self.__log.info(f'Connect to [{self.get_name()}]:[{self.__ip}]:[{self.__port}] failed:{e} !!!')
|
|
@@ -64,6 +70,7 @@ class ShuizhiTcpConnector(Connector, threading.Thread):
|
|
|
self.__log.info(f'Reconnect to [{self.get_name()}]:[{self.__ip}]:[{self.__port}] success !')
|
|
|
break
|
|
|
except Exception as e:
|
|
|
+ print("e=", e)
|
|
|
print("Continue reconnect in 5s..")
|
|
|
self.__log.info(
|
|
|
f'Reconnect to [{self.get_name()}]:[{self.__ip}]:[{self.__port}] failed:{e} !!! Continue reconnect in 5s..')
|
|
@@ -94,48 +101,52 @@ class ShuizhiTcpConnector(Connector, threading.Thread):
|
|
|
def run(self):
|
|
|
self.__connect()
|
|
|
self.__connected = True
|
|
|
- dissolved_oxygen = bytes.fromhex('02 03 00 25 00 08 55 F4') # 读溶解氧发送指令,接收数据长度:21
|
|
|
- temperature = bytes.fromhex('01 03 15 4A 00 02 E1 D1') # 读温度和盐度发送指令,接收数据长度:9
|
|
|
- salinity = bytes.fromhex('01 03 15 97 00 04 F1 E9') # 读温度和盐度发送指令,接收数据长度:13
|
|
|
- PH = bytes.fromhex('01 03 01 D9 00 0A 15 CA') # 读PH发送指令,数据接收长度:25
|
|
|
- chlorophyll = bytes.fromhex('01 03 16 A8 00 07 81 A0') # 读叶绿素发送指令,接收数据长度:19
|
|
|
- depth = bytes.fromhex('01 03 15 66 00 03 E1 D8') # 读深度发送指令,接收数据长度:11
|
|
|
- turbidity = bytes.fromhex('01 03 15 F2 00 05 20 36') # 读浊度发送指令,接收数据长度:15
|
|
|
+ # dissolved_oxygen = bytes.fromhex('01 03 15 CF 00 05 B1 FA') # 读溶解氧发送指令,接收数据:
|
|
|
+ # temperature = bytes.fromhex('01 03 15 4A 00 05 A0 13') # 读温度发送指令,接收数据:01 03 0A 41 C0 BC 1C 00 00 00 01 00 01 61 42
|
|
|
+ # salinity = bytes.fromhex('01 03 15 97 00 05 30 29') # 读盐度发送指令,接收数据:01 03 0A 00 00 00 00 00 00 00 61 00 0C 75 6D
|
|
|
+ # PH = bytes.fromhex('01 03 15 BA 00 05 A0 20') # 读 PH 发送指令,接收数据:01 03 0A 40 F9 2B 79 00 00 00 91 00 11 72 BB
|
|
|
+ # chlorophyll = bytes.fromhex('01 03 16 A8 00 05 00 61') # 读叶绿素发送指令,接收数据:01 03 0A 00 00 00 00 00 00 01 01 00 33 34 9F
|
|
|
+ # depth = bytes.fromhex('01 03 15 66 00 05 61 DA') # 读深度发送指令,接收数据:01 03 0A 42 08 1B F4 00 00 00 26 00 05 34 D0
|
|
|
+
|
|
|
+ # 获取需要读取的参数的相关信息
|
|
|
+ param_list = self._storage.get_in_situ_command()
|
|
|
+ depth_index = None
|
|
|
+ depth = ""
|
|
|
+ # ①判断参数中是否有 深度, ②处理 寄存器偏移量 的位置
|
|
|
+ for each in param_list:
|
|
|
+ self._param_id[each["parameter_id"]] = each["name"]
|
|
|
+ if each["name"] == "深度":
|
|
|
+ crc_check = crc16Add(each['station_code'] + each["function_code"] + dec_to_hex(each["address"]) + "0005")
|
|
|
+ depth = bytes.fromhex(crc_check)
|
|
|
+ depth_index = param_list.index(each)
|
|
|
+ if depth_index is not None:
|
|
|
+ param_list.pop(depth_index)
|
|
|
+ instruct_list = []
|
|
|
+ if len(depth) > 0:
|
|
|
+ for each in param_list:
|
|
|
+ crc_check = crc16Add(each['station_code'] + each["function_code"] + dec_to_hex(each["address"]) + "0005")
|
|
|
+ instruct_list.append(depth)
|
|
|
+ instruct_list.append(bytes.fromhex(crc_check))
|
|
|
+ instruct_list.append(depth)
|
|
|
+ else:
|
|
|
+ for each in param_list:
|
|
|
+ crc_check = crc16Add(each['station_code'] + each["function_code"] + dec_to_hex(each["address"]) + "0005")
|
|
|
+ instruct_list.append(bytes.fromhex(crc_check))
|
|
|
+ self._len_param = len(instruct_list)
|
|
|
+
|
|
|
+ for i in instruct_list:
|
|
|
+ print(i)
|
|
|
+
|
|
|
# 创建接收线程
|
|
|
threading.Thread(target=self.SocketReceive, args=(self.__sock,)).start()
|
|
|
-
|
|
|
+ # 循环发送指令
|
|
|
while 1:
|
|
|
time.sleep(0.2)
|
|
|
if not self.__connected:
|
|
|
continue
|
|
|
try:
|
|
|
-
|
|
|
- if sendFlag == 0:
|
|
|
- self.__sock.send(depth)
|
|
|
- elif sendFlag == 1:
|
|
|
- self.__sock.send(dissolved_oxygen)
|
|
|
- elif sendFlag == 2:
|
|
|
- self.__sock.send(depth)
|
|
|
- elif sendFlag == 3:
|
|
|
- self.__sock.send(temperature)
|
|
|
- elif sendFlag == 4:
|
|
|
- self.__sock.send(depth)
|
|
|
- elif sendFlag == 5:
|
|
|
- self.__sock.send(salinity)
|
|
|
- elif sendFlag == 6:
|
|
|
- self.__sock.send(depth)
|
|
|
- elif sendFlag == 7:
|
|
|
- self.__sock.send(PH)
|
|
|
- elif sendFlag == 8:
|
|
|
- self.__sock.send(depth)
|
|
|
- elif sendFlag == 9:
|
|
|
- self.__sock.send(chlorophyll)
|
|
|
- elif sendFlag == 10:
|
|
|
- self.__sock.send(depth)
|
|
|
- elif sendFlag == 11:
|
|
|
- self.__sock.send(turbidity)
|
|
|
- elif sendFlag == 12:
|
|
|
- self.__sock.send(depth)
|
|
|
+ # print("发送", instruct_list[sendFlag], "....")
|
|
|
+ self.__sock.send(instruct_list[sendFlag])
|
|
|
except Exception as e:
|
|
|
self.__connected = False
|
|
|
self.__reconnect()
|
|
@@ -143,10 +154,7 @@ class ShuizhiTcpConnector(Connector, threading.Thread):
|
|
|
if self.__stopped:
|
|
|
break
|
|
|
|
|
|
- # 水质解析器
|
|
|
def save_format_data(self, t, name):
|
|
|
- if name == '深度':
|
|
|
- print(name, t, time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
data = {}
|
|
|
for index in self.__data_point_config:
|
|
|
if index["io_point_name"] == name:
|
|
@@ -154,213 +162,34 @@ class ShuizhiTcpConnector(Connector, threading.Thread):
|
|
|
t = t / index['divisor']
|
|
|
if index['offset'] is not None:
|
|
|
t = t - index['offset']
|
|
|
- if index['low_limit'] is not None and index['up_limit'] is not None and index['low_limit'] <= t <= \
|
|
|
- index['up_limit']:
|
|
|
- data = {'c' + str(index['serial_number']): t}
|
|
|
- self.__storager.real_time_data_storage(data)
|
|
|
+ data = {'c' + str(index['serial_number']): t}
|
|
|
+ self.__storager.real_time_data_storage(data)
|
|
|
+ # print(data)
|
|
|
|
|
|
def SocketReceive(self, clientSocket):
|
|
|
global sendFlag
|
|
|
''' Socket 接收线程。'''
|
|
|
- # global socket_flag, socket_msg # 通过全局变量,让外部可以控制线程的运行,也可以处理信息
|
|
|
-
|
|
|
while 1:
|
|
|
- time.sleep(0.5)
|
|
|
+ time.sleep(0.2)
|
|
|
# print(sendFlag, time.time())
|
|
|
- # 深度
|
|
|
- if sendFlag == 0:
|
|
|
- try:
|
|
|
- # print(clientSocket)
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e:
|
|
|
- # print("深度1", e)
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 11:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('----深度:', t, 'res:', len(res), 'length:', length, time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "深度")
|
|
|
- sendFlag = 1
|
|
|
- # 溶解氧
|
|
|
- if sendFlag == 1:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e:
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- # print(time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- if length == 21:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('溶解氧:', t, 'res:', len(res), 'length:', length, time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "溶解氧")
|
|
|
- sendFlag = 2
|
|
|
- # 深度
|
|
|
- if sendFlag == 2:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 11:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('深度:', t, 'length:', length, time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "深度")
|
|
|
- sendFlag = 3
|
|
|
- # 温度
|
|
|
- if sendFlag == 3:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 9:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('温度:', t, 'len:', len(res), time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "温度")
|
|
|
- sendFlag = 4
|
|
|
- # 深度
|
|
|
- if sendFlag == 4:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 11:
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('深度:', t, 'length:', length, time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "深度")
|
|
|
- sendFlag = 5
|
|
|
- # 盐度
|
|
|
- if sendFlag == 5:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 13:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('盐度:', t, 'len:', len(res), time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "盐度")
|
|
|
- sendFlag = 6
|
|
|
- # 深度
|
|
|
- if sendFlag == 6:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 11:
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('深度:', t, 'length:', length, time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "深度")
|
|
|
- sendFlag = 7
|
|
|
- # PH
|
|
|
- if sendFlag == 7:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 25:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('PH:', t, 'len:', len(res), time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "PH")
|
|
|
- sendFlag = 8
|
|
|
- # 深度
|
|
|
- if sendFlag == 8:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 11:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('深度:', t, 'length:', length, time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "深度")
|
|
|
- sendFlag = 9
|
|
|
- # 叶绿素
|
|
|
- if sendFlag == 9:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 19:
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('叶绿素:', t, 'len:', len(res), time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "叶绿素")
|
|
|
- sendFlag = 10
|
|
|
- # 深度
|
|
|
- if sendFlag == 10:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 11:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('深度:', t, 'len:', len(res), time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "深度")
|
|
|
- sendFlag = 11
|
|
|
- # 浊度
|
|
|
- if sendFlag == 11:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
- fmt = str(length) + 'B'
|
|
|
- res = struct.unpack(fmt, recvData)
|
|
|
- if length == 15:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- # print('浊度:', t, 'len:', len(res), time.strftime('%Y-%m-%d %H:%M:%S'))
|
|
|
- self.save_format_data(t, "浊度")
|
|
|
- sendFlag = 12
|
|
|
- # 深度
|
|
|
- if sendFlag == 12:
|
|
|
- try:
|
|
|
- recvData = clientSocket.recv(1024)
|
|
|
- except Exception as e: # 忽视掉超时
|
|
|
- break
|
|
|
- length = len(recvData)
|
|
|
+ try:
|
|
|
+ recvData = clientSocket.recv(1024)
|
|
|
+ # print("recvData=", recvData)
|
|
|
+ except Exception as e:
|
|
|
+ print("e=", e)
|
|
|
+ break
|
|
|
+ length = len(recvData)
|
|
|
+ if length == 15:
|
|
|
fmt = str(length) + 'B'
|
|
|
res = struct.unpack(fmt, recvData)
|
|
|
- if length == 11:
|
|
|
- # print(len(res), res)
|
|
|
- t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
- self.save_format_data(t, "深度")
|
|
|
+ t = int_to_hex(res[3], res[4], res[5], res[6])
|
|
|
+ print(time.strftime('%Y-%m-%d %H:%M:%S'), self._param_id[res[12]], " t=", t)
|
|
|
+ self.save_format_data(t, self._param_id[res[12]])
|
|
|
+ if sendFlag == self._len_param - 1:
|
|
|
+ print("-------------------")
|
|
|
sendFlag = 0
|
|
|
+ else:
|
|
|
+ sendFlag = sendFlag + 1
|
|
|
clientSocket.close()
|
|
|
self.__log.info("Client closed.")
|
|
|
|
|
@@ -377,3 +206,28 @@ def int_to_hex(a1, a2, b1, b2):
|
|
|
t = t1 + t2
|
|
|
t = struct.unpack('>f', binascii.unhexlify(t.replace(' ', '')))[0]
|
|
|
return t
|
|
|
+
|
|
|
+
|
|
|
+def dec_to_hex(num):
|
|
|
+ """
|
|
|
+ 十进制转十六进制
|
|
|
+ """
|
|
|
+ t = hex(num)
|
|
|
+ t = (6 - len(t)) * "0" + t[2:]
|
|
|
+ return t
|
|
|
+
|
|
|
+
|
|
|
+# CRC16-MODBUS
|
|
|
+def crc16Add(read):
|
|
|
+ """
|
|
|
+ 生成CRC16校验位
|
|
|
+ """
|
|
|
+ crc16 = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0xFFFF, xorOut=0x0000)
|
|
|
+ data = read.replace(" ", "")
|
|
|
+ read_crcout = hex(crc16(unhexlify(data))).upper()
|
|
|
+ str_list = list(read_crcout)
|
|
|
+ if len(str_list) < 6:
|
|
|
+ str_list.insert(2, '0' * (6 - len(str_list))) # 位数不足补0
|
|
|
+ crc_data = "".join(str_list)
|
|
|
+ read = read.strip() + '' + crc_data[4:] + '' + crc_data[2:4]
|
|
|
+ return read
|