Simple python GUI for SBOT without packets

From RoboWiki
Jump to: navigation, search

Here is basic UI for testing SBOT (with no packets modified firmware). It requires pygtk and pyserial to run. Tested and developed on linux, but should work on Windows too.

Usage:

python test.py <serial_port>

Example command line:

python test.py /dev/rfcomm1
#!/usr/bin/env python
# coding: utf-8

# Copyright 2010 Martin Sucha
#
# Permission is hereby granted, free of charge, to any person
# obtaining a copy of this software and associated documentation
# files (the "Software"), to deal in the Software without
# restriction, including without limitation the rights to use,
# copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the
# Software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
# OTHER DEALINGS IN THE SOFTWARE.

# Importuj GTK moduly a dalsie
import pygtk
pygtk.require('2.0')
import gtk
import glib
import cairo
import pango
import pangocairo
import sys
import serial

class TestWindow(object): 
    def __init__(self, port):
        self.port = port
        self.vstup = ''
        self.senzory = []
        
        window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        window.set_title("Test SBOTa")
        window.connect("destroy", lambda w: gtk.main_quit())
        window.set_size_request(850, 600)
        self.vpaned = gtk.VPaned()
        self.area = gtk.DrawingArea()
        
        self.upvbox = gtk.VBox()
        self.upvbox.pack_start(self.area, expand=True)

        self.buttonbox = gtk.HBox()
        
        self.button_ping = gtk.Button("Ping")
        self.button_ping.connect("clicked", self.ping_clicked_cb)
        self.buttonbox.pack_start(self.button_ping, expand=False)
        self.button_ping.show()

        self.button_sens = gtk.Button("Senzory")
        self.button_sens.connect("clicked", self.sens_clicked_cb)
        self.buttonbox.pack_start(self.button_sens, expand=False)
        self.button_sens.show()
        
        self.button_vpred = gtk.Button("Vpred")
        self.button_vpred.connect("clicked", self.vpred_clicked_cb)
        self.buttonbox.pack_start(self.button_vpred, expand=False)
        self.button_vpred.show()
        
        self.button_stop = gtk.Button("Stop")
        self.button_stop.connect("clicked", self.stop_clicked_cb)
        self.buttonbox.pack_start(self.button_stop, expand=False)
        self.button_stop.show()
        
        # koniec buttonov
        self.upvbox.pack_end(self.buttonbox, expand=False)
        self.buttonbox.show()
        
        self.pangolayout = self.area.create_pango_layout("")
        self.sw = gtk.ScrolledWindow()
        self.sw.add_with_viewport(self.upvbox)
        self.upvbox.show()
        self.sw.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)
        self.vpaned.add1(self.sw)

        self.output = gtk.TextView()
        self.out_buf = self.output.get_buffer()
        self.out_tag_nezaujimave = self.out_buf.create_tag("nezujimave", foreground="#777")

        self.sw2 = gtk.ScrolledWindow()
        self.sw2.add(self.output)
        self.sw2.set_policy(gtk.POLICY_AUTOMATIC, gtk.POLICY_AUTOMATIC)

        self.vpaned.add2(self.sw2)

        self.vpaned.set_position(450)

        window.add(self.vpaned)
        self.area.set_events(gtk.gdk.POINTER_MOTION_MASK |
                             gtk.gdk.POINTER_MOTION_HINT_MASK )
        self.area.connect("expose-event", self.area_expose_cb)
        self.hadj = self.sw.get_hadjustment()
        self.vadj = self.sw.get_vadjustment()
        self.area.show()
        self.sw.show()
        self.output.show()
        self.sw2.show()
        self.vpaned.show()
        window.show()
        
        self.start_comm()

    def start_comm(self):
        self.serial = serial.Serial(port=self.port, timeout=0)
        glib.timeout_add(100, self.timeout_cb)
    
    def timeout_cb(self):
        self.comm_rcv()
        return True # chcem znova

    def comm_rcv(self):
        data = self.serial.read(128)
        sys.stdout.write(data)
        self.process_data(data)

    def process_data(self, data):
        data = data.replace('\r','') # ako konce beriem len \n
        self.vstup += data
        riadky = self.vstup.split('\n')
        for riadok in riadky[:-1]:
          self.process_riadok(riadok)
        self.vstup = riadky[-1]
    
    def process_riadok(self, riadok):
        if len(riadok)>0 and riadok[0] in '012345689':
            senzory = riadok.split()
            for i in range(len(senzory)):
                senzory[i] = int(senzory[i])
            self.senzory = senzory
            self.repaint()
            self.out_data(riadok+'\n', 'nezujimave')
        else:
            self.out_data(riadok+'\n')

    def out_data(self, data, *tags):
        """Vypis text do vystupneho okna"""
        if tags == None:
          tags = tuple()
        self.out_buf.insert_with_tags_by_name(self.out_buf.get_end_iter(), data, *tags)
        self.out_buf.apply_tag
        self.output.scroll_to_iter(self.out_buf.get_end_iter(), 0)

    def ping_clicked_cb(self, button, data=None):
        self.serial.write('a')
    
    def sens_clicked_cb(self, button, data=None):
        self.serial.write('e')

    def vpred_clicked_cb(self, button, data=None):
        self.serial.write('f')

    def stop_clicked_cb(self, button, data=None):
        self.serial.write('s')
    
    def area_expose_cb(self, area, event):        
        cx = self.area.window.cairo_create()

        cx.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
        cx.clip()
        
        cx.set_source_rgb(1,1,1)
        cx.rectangle(event.area.x, event.area.y, event.area.width, event.area.height)
        cx.fill()

        self.draw(cx)
        
        return True
    
    def draw(self, cx):
        for i in range(len(self.senzory)):
            hod = self.senzory[i]
            if hod == 1023:
              cx.set_source_rgb(1,0,0)
            else:
              cx.set_source_rgb(0,0,1)
            cx.rectangle(i*20,0,15,self.senzory[i]/3)
            cx.fill()
          
    
    def repaint(self):
        self.area.queue_draw()

def main():
    gtk.main()
    return 0  

if __name__ == "__main__":
  if len(sys.argv) <= 1:
    print "Usage %s <serial>"
    sys.exit(2)

  port = sys.argv[1]  
  
  print port

  window = TestWindow(port)

  main()