-
Notifications
You must be signed in to change notification settings - Fork 34
/
SerialProcess.py
114 lines (99 loc) · 4.23 KB
/
SerialProcess.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
import logging
import multiprocessing
import time
import serial
class SerialProcess(multiprocessing.Process):
def __init__(self, messageQ, commandQ, config) -> None:
self.logger = logging.getLogger('RFLinkGW.SerialProcessing')
self.logger.info("Starting...")
multiprocessing.Process.__init__(self)
self.__messageQ = messageQ
self.__commandQ = commandQ
self.gatewayPort = config['rflink_tty_device']
self.sp = serial.Serial()
self.connect()
self.processing_exception = config['rflink_direct_output_params']
self.processing_signed = config['rflink_signed_output_params']
self.processing_wdir = config['rflink_wdir_output_params']
def close(self) -> None:
self.sp.close()
self.logger.debug('Serial closed')
def prepare_output(self, data_in) -> list:
out = []
data = data_in.decode("ascii").replace(";\r\n", "").split(";")
self.logger.debug("Received message:%s" % (data))
if len(data) > 3 and data[0] == '20':
family = data[2]
deviceId = data[3].split("=")[1]
switch = data[4].split("=")[1]
d = {}
for t in data[4:]:
token = t.split("=")
d[token[0]] = token[1]
for key in d:
if key in self.processing_exception:
val = d[key]
elif key in self.processing_signed:
# Hexadecimal, high bit contains negative sign, division by 10
if int(d[key], 16) & 0x8000:
val = -( float (int(d[key], 16) & 0x7FFF) / 10 )
else:
val = float (int(d[key], 16)) / 10
elif key in self.processing_wdir:
# Integer value from 0-15, reflecting 0-360 degrees in 22.5 degree steps
val = int(d[key], 10) * 22.5
else:
val = float (int(d[key], 16)) / 10
# Hexadecimal, division by 10
if key == "CMD":
topic_out = "%s/%s/%s/READ/%s" % (family, deviceId, switch, key)
else:
topic_out = "%s/%s/READ/%s" % (family, deviceId, key)
self.logger.debug('set topic to: %s' % (topic_out))
data_out = {
'method': 'publish',
'topic': topic_out,
'family': family,
'deviceId': deviceId,
'param': key,
'payload': val,
'qos': 1,
'timestamp': time.time()
}
out = out + [data_out]
return out
def prepare_input(self, task):
out_str = '10;%s;%s;%s;%s;\n' % (task['family'], task['deviceId'], task['param'], task['payload'])
self.logger.debug('Sending to serial:%s' % (out_str))
return out_str
def connect(self) -> None:
self.logger.info('Connecting to serial')
while not self.sp.isOpen():
try:
time.sleep(1)
self.sp = serial.Serial(self.gatewayPort, 57600, timeout=1)
self.logger.debug('Serial connected')
except Exception as e:
self.logger.error('Serial port is closed %s' % (e))
def run(self):
self.sp.flushInput()
while True:
try:
if not self.__commandQ.empty():
task = self.__commandQ.get()
# send it to the serial device
self.sp.write(self.prepare_input(task).encode('ascii'))
except Exception as e:
self.logger.error("Send error:%s" % (format(e)))
try:
if (self.sp.inWaiting() > 0):
data = self.sp.readline()
task_list = self.prepare_output(data)
for task in task_list:
self.logger.debug("Sending to Q:%s" % (task))
self.__messageQ.put(task)
else:
time.sleep(0.01)
except Exception as e:
self.logger.error('Receive error: %s' % (e))
self.connect()