4 from serial import Serial
5 from datetime import datetime
8 class State: #information stored
17 self.time = datetime.utcnow()
60 snsMap = {ACC_SNS: 'acc',
66 cmdMap = {START, 'start',
81 index = 0 # read index
82 count = 0 # number of items in frame
83 length = 0 # length of frame (in bytes)
84 bits_sns = 0 # sensor type
85 bits_typ = 0 # data type
86 binary = "" # binary read-in
87 values = [] # converted numeric data
95 def findCode(dataMap, name):
97 if dataMap[code] == name:
99 print("[ERROR] No code found")
102 def parse(self, byte):
103 # save current pos and increment read index
104 # if we have an error we cna reset index below
108 if pos == Frame.HEADER_POS:
109 if ord(byte) != Frame.HEADER:
111 #print('parse: header %02x' % ord(byte))
113 elif pos == Frame.BITS_POS:
114 self.bits_sns = (ord(byte) & Frame.SNS_MASK) >> Frame.SNS_SHIFT
115 self.bits_typ = (ord(byte) & Frame.TYP_MASK) >> Frame.TYP_SHIFT
116 if self.bits_sns >= Frame.SNS_NUM:
118 if self.bits_typ >= Frame.TYP_NUM:
120 #print('parse: bits sns=%d typ=%d' %
121 # (self.bits_sns, self.bits_typ))
123 elif pos == Frame.COUNT_POS:
124 wordsize = Frame.sizeMap[self.bits_typ]
125 self.count = ord(byte)
126 self.length = Frame.DATA_POS + self.count*wordsize + 1
127 #print('parse: count cnt=%d len=%d' %
128 # (self.count, self.length))
130 elif pos < self.length-1:
132 #print('parse: data %02x @%d' %
133 # (ord(byte), pos-Frame.DATA_POS))
135 elif pos == self.length-1:
136 #print('parse: tail %02x' % ord(byte))
137 if ord(byte) == Frame.TAIL:
138 state = self.convert()
145 elif pos > self.length-1:
146 print('Error parsing')
148 # Convert frame to state
151 fmt = Frame.fmtMap[self.bits_typ] * self.count
152 sns = Frame.snsMap[self.bits_sns]
153 self.values = unpack('<'+fmt, self.binary)
154 print('convert: %3s = \'%3s\'%%[%s] -> [%s]' %
155 (sns, fmt, hexDump(self.binary), fltDump(self.values)))
159 setattr(state, sns, self.values)
164 def __init__(self, config):
165 print('Defice.__init__')
172 print('Device.connect')
176 self.serial = Serial(self.config.device, \
177 baudrate = self.config.baudrate, \
178 parity = self.config.parity, \
179 bytesize = self.config.databits, \
180 stopbits = self.config.stopbits, \
182 for sns in self.config.rate:
183 self.set_rate(sns, self.config.rate[sns])
184 for sns in self.config.enable:
185 self.set_enable(sns, self.config.enable[sns])
186 self.serial.flushInput()
187 except Exception as ex:
190 def disconnect(self):
191 print('Device.disconnect')
192 if self.serial and self.serial.isOpen():
195 def running(self): # isRunning
196 if self.serial == None:
198 if self.serial.isOpen() == False:
202 def set_rate(self, sensor, interval):
203 sns = Frame.findCode(Frame.snsMap, sensor)
204 bits = (sns << Frame.SNS_SHIFT) | \
205 (Frame.RATE << Frame.OPER_SHIFT)
206 self._write_binary('Bf', bits, interval)
208 def set_enable(self, sensor, enabled):
209 sns = Frame.findCode(Frame.snsMap, sensor)
210 oper = Frame.START if enabled else Frame.STOP
211 bits = (sns << Frame.SNS_SHIFT) | \
212 (oper << Frame.OPER_SHIFT)
213 self._write_binary('B', bits)
220 if not self.running():
223 while self.serial.readable():
225 byte = self.serial.read()
226 except Exception as ex:
227 # Not sure why this is excepting
228 # if it says it's readable
233 state = self.frame.parse(byte)
237 print('[ERROR] Exceeded Read Limit')
246 def frame_len(self, frame):
249 dataType_snsType = ord(frame[1])
250 dataNum = ord(frame[2])
251 dataType = (dataType_snsType & Frame.TYP_MASK) >> Frame.TYP_SHIFT
252 snsType = (dataType_snsType & Frame.SNS_MASK) >> Frame.SNS_SHIFT
253 dataSize = Frame.sizeMap[dataType]
254 return (dataSize*dataNum+4)
256 def printHex(self, frame):
257 frameLen = self.frame_len(frame)
260 print(hex(ord(frame[i])))
264 def _write_binary(self, fmt, *args):
265 #print('Device._write_binary')
267 fmt = 'B' + fmt + 'B'
268 args = [Frame.HEADER] + list(args) + [Frame.TAIL]
269 frame = pack('<'+fmt, *args)
270 print('write: bin:[' + hexDump(frame) + ']')
271 self.serial.write(frame)
276 digits = ['%02x' % ord(byte) for byte in frame]
277 return ' '.join(digits)
280 digits = ['%5.2f' % flt for flt in data]
281 return ' '.join(digits)