Commits

Tino de Bruijn committed a98940e

Added Boards helper dict to util

Comments (0)

Files changed (1)

pyfirmata/util.py

 import threading
 import serial
 import time
+import pyfirmata
+
+class Boards(dict):
+    """
+    A dictonary to manage multiple boards on the same machine. Tries to
+    connect to all defined usb ports, and then tries to fetch the board's
+    name. Result is a dictionary of `Board`_ classes mapped to their names.
+    """
+    def __init__(self, base_dir='/dev/', identifier='tty.usbserial', boards_map=None):
+        """
+        Searches all possible USB devices in ``base_dir`` that start with
+        ``identifier``. If given an ``boards_map`` dictionary it will setup
+        the boards in the map according to their type. Finding a board that
+        does not identify itself at all, that are not in the map, or boards
+        that are missing fail silenly. Use the ``verify_found_boards`` method
+        to check this.
+        
+        :base_dir arg: A absolute path for the base directory to search for USB connections
+        :identifier arg: A string a USB connection startswith and should be tried
+        :boards_map arg: A dictionary in the form of::
+            boards_map = { 1 : {'name' : 'myduino', 'board' : 'board'},
+                           2 : {'name' : 'mymega', 'board' : 'board_mega'} }
+        """
+        for device in os.listdir(base_dir):
+            if device.startswith(identifier):
+                try:
+                    board = pyfirmata.Board(os.path.join(base_dir, device))
+                except SerialException:
+                    pass
+                else:
+                    # if board.id:
+                    #     try:
+                    #         board.name = boards_map[board.id]['name']
+                    #         board.setup_layout(pyfirmata.BOARDS[boards_map[board.id]['board']])
+                    #     except (KeyError, TypeError): # FIXME Possible KeyErrors from setup_layout are caught here...
+                    #         # FIXME Better to check if boards_map is valid if given, otherwise raise error
+                    #         pass
+                    # if not board.name:
+                    board_name = 'unknown-%s' % device[-5:-1]
+                    self[board_name] = board
+                            
+    def verify_found_boards(self, boards_map):
+        """
+        Returns True if all and only boards in the map are found. Returns
+        False otherwise
+        """
+        names = set()
+        for board in boards_map:
+            names.add(board['name'])
+        return names is set(self.keys())
+        
+    def get_pin(self, pin_def):
+        parts = pin_def.split(':')
+        try:
+            return self[parts[0]].get_pin([parts[1], parts[2], parts[3]])
+        except KeyError:
+            raise KeyError("board named %s not found" % parts[0])
+        except IndexError:
+            raise pyfirmata.InvalidPinDefError("%s is not a valid pin definition" % pin_def)
+            
+    def exit(self):
+        for board in self.values():
+            board.exit()
+            
+    def __del__(self):
+        ''' 
+        The connection with the board can get messed up when a script is
+        closed without calling board.exit() (which closes the serial
+        connection). Therefore do it here and hope it helps.
+        '''
+        self.exit()
 
 class Iterator(threading.Thread):
     def __init__(self, board):
                     self.board.iterate()
                 time.sleep(0.001)
             except (AttributeError, serial.SerialException, OSError), e:
-                # this way we can kill the thread by setting the arduino object
-                # to None, or when the serial port is closed by arduino.exit()
+                # this way we can kill the thread by setting the board object
+                # to None, or when the serial port is closed by board.exit()
                 break
             except Exception, e:
                 # catch 'error: Bad file descriptor'
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.