From 800924295f367ea6ee552e39e184f3c58b4c25b7 Mon Sep 17 00:00:00 2001 From: Andy Spencer Date: Sun, 2 Feb 2014 09:02:43 +0000 Subject: [PATCH] Add serial interface --- vis/device.py | 94 ++++++++++++++++++++++++++++++++++++++++++++++++--- vis/makefile | 2 +- vis/visual.py | 75 +++++++++++++++++++++++++++++++++++++--- vis/visual.ui | 53 ++++++++++++++--------------- 4 files changed, 186 insertions(+), 38 deletions(-) diff --git a/vis/device.py b/vis/device.py index a205033..b729f02 100644 --- a/vis/device.py +++ b/vis/device.py @@ -1,5 +1,16 @@ +from re import compile from serial import Serial +class State: + acc = [None]*3 + mag = [None]*3 + touch = [None]*2 + light = [None]*1 + a2d = [None]*6 + + def __init__(self): + pass + class Device: # Attributes port = "/dev/ttyACM0" @@ -7,12 +18,85 @@ class Device: # Constructors def __init__(self, config): self.config = config + self.serial = None # Methods def connect(self): - self.conn = Serial(self.port, \ - baudrate = self.config.baudrate, \ - parity = self.config.parity, \ - bytesize = self.config.databits, \ - stopbits = self.config.stopbits) + try: + self.inbuf = [] + self.serial = Serial(self.port, \ + baudrate = self.config.baudrate, \ + parity = self.config.parity, \ + bytesize = self.config.databits, \ + stopbits = self.config.stopbits, \ + timeout = 0) + except Exception as ex: + return str(ex) + + def disconnect(self): + if self.serial and self.serial.isOpen(): + self.serial.close() + + def running(self): + if self.serial == None: + return False + if self.serial.isOpen() == False: + return False + return True + + def process(self): + items = [] + while self.serial.readable(): + try: + char = self.serial.read() + except Exception as ex: + char = '' + if char == '': + break + if char == '\r' or char == '\n': + if len(self.inbuf) == 0: + continue + line = "".join(self.inbuf) + item = self._parse_ascii(line) + items.append(item) + self.inbuf = [] + else: + self.inbuf.append(char) + return items + + # Private methods + def _parse_ascii(self, line): + acc_re = compile("\[ACC\] accX=(.*) accY=(.*) accZ=(.*)") + mag_re = compile("\[MAG\] magX=(.*) magY=(.*) magZ=(.*)") + lgt_re = compile("\[LGT\] Light Intensity=(.*)") + tch_re = compile("\[TCH\] Force=(.*) Distance=(.*)") + a2d_re = compile("\[A2D\] ...") + + acc_m = acc_re.match(line) + mag_m = mag_re.match(line) + lgt_m = lgt_re.match(line) + tch_m = tch_re.match(line) + a2d_m = a2d_re.match(line) + + state = State() + if acc_m: + state.acc[0] = float(acc_m.group(1)) + state.acc[1] = float(acc_m.group(2)) + state.acc[2] = float(acc_m.group(3)) + if mag_m: + state.acc[0] = float(mag_m.group(1)) + state.acc[1] = float(mag_m.group(2)) + state.acc[2] = float(mag_m.group(3)) + if lgt_m: + state.light[0] = float(lgt_m.group(1)) + if tch_m: + state.touch[0] = float(tch_m.group(1)) + if a2d_m: + state.a2d[0] = float(tch_m.group(1)) + state.a2d[1] = float(tch_m.group(2)) + state.a2d[2] = float(tch_m.group(3)) + state.a2d[3] = float(tch_m.group(4)) + state.a2d[4] = float(tch_m.group(5)) + state.a2d[5] = float(tch_m.group(6)) + return state diff --git a/vis/makefile b/vis/makefile index 9f2eec9..26271df 100644 --- a/vis/makefile +++ b/vis/makefile @@ -1,5 +1,5 @@ run: - ./main.py + python -u ./main.py clean: rm -rf *.pyc __pycache__ diff --git a/vis/visual.py b/vis/visual.py index 908304d..f07ea0d 100644 --- a/vis/visual.py +++ b/vis/visual.py @@ -5,6 +5,10 @@ import gtk class Visual: def __init__(self, config, device, xively): + def get_objects(names): + return map(lambda x: + self.builder.get_object(x), names) + self.config = config self.device = device self.xively = xively @@ -15,6 +19,12 @@ class Visual: self.window = self.builder.get_object("window") self.settings = self.builder.get_object("settings") + self.accs = get_objects(['accx', 'accy', 'accz']) + self.mags = get_objects(['magx', 'magy', 'magz']) + self.touch = get_objects(['touch']) + self.light = get_objects(['light']) + self.a2ds = get_objects(['a2d0', 'a2d1', 'a2d2', 'a2d3', 'a2d4', 'a2d5']) + # Signal handlers def on_hide(self, win, *args): self.settings.hide() @@ -24,18 +34,24 @@ class Visual: self.settings.show() return True - def on_serial(self, win): - self.device.connect() + def on_serial(self, act): + if act.get_active(): + self.status(self.device.connect()) + else: + self.status(self.device.disconnect()) return True - def on_xively(self, win): - self.xively.connect() + def on_xively(self, act): + if act.get_active(): + self.status(self.xively.connect()) + else: + self.status(self.xively.disconnect()) return True def on_enable(self, _): print "Unimplemented: on_enable" return True - + def on_rate(self, _): print "Unimplemented: on_rate" return True @@ -69,7 +85,56 @@ class Visual: # TODO - send changes back to config + def update(self, state): + def setxyz(objs, vals): + if vals[0]: objs[0].set_text('X: %f' % vals[0]) + if vals[1]: objs[1].set_text('Y: %f' % vals[1]) + if vals[2]: objs[2].set_text('Z: %f' % vals[2]) + def setabs(objs, vals): + for i in range(0,len(objs)): + if vals[i]: objs[i].set_text('%f' % vals[i]) + + setxyz(self.accs, state.acc) + setxyz(self.mags, state.mag) + setabs(self.touch, state.touch) + setabs(self.light, state.light) + setabs(self.a2ds, state.a2d) + + def debug(self, state): + print 'update: ' + str(state) + print '\tacc - ' + str(state.acc) + print '\tmag - ' + str(state.mag) + print '\tlgt - ' + str(state.light) + print '\ttch - ' + str(state.touch) + print '\ta2d - ' + str(state.a2d) + + def timer(self): + serial = self.builder.get_object("serial_btn") + status = self.builder.get_object("conn") + + if self.device.running(): + serial.set_active(True) + status.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON) + else: + serial.set_active(False) + status.set_from_stock(gtk.STOCK_NO, gtk.ICON_SIZE_BUTTON) + if self.device.running(): + for item in self.device.process(): + self.update(item) + #self.debug(item) + + return True + def run(self): self.load_config() self.window.show() + gtk.timeout_add(1000/60, self.timer) gtk.main() + + # Private methods + def status(self, msg): + if not msg: + return + status = self.builder.get_object("status") + status.push(text=('Error: ' + msg), context_id=0) + diff --git a/vis/visual.ui b/vis/visual.ui index e8cfec5..96915df 100644 --- a/vis/visual.ui +++ b/vis/visual.ui @@ -2,21 +2,6 @@ - - Serial - gtk-connect - - - - Settings - gtk-preferences - - - - Xively - gtk-connect - - 100 1 @@ -53,6 +38,21 @@ 10 + + Serial + gtk-connect + + + + Settings + gtk-preferences + + + + Xively + gtk-connect + + False 5 @@ -68,7 +68,7 @@ False 2 - + True False end @@ -461,10 +461,9 @@ - setting_act + settings_act True False - settings True @@ -759,7 +758,7 @@ True False - + True False 0 @@ -772,7 +771,7 @@ - + True False 0 @@ -785,7 +784,7 @@ - + True False 0 @@ -811,7 +810,7 @@ True False - + True False 0 @@ -824,7 +823,7 @@ - + True False 0 @@ -837,7 +836,7 @@ - + True False 0 @@ -951,7 +950,7 @@ - + True False 0 @@ -966,7 +965,7 @@ - + True False 0 @@ -1142,7 +1141,7 @@ True False - 2 + 10 True -- 2.43.2