Skip to content

Commit

Permalink
OS independent board autoloading
Browse files Browse the repository at this point in the history
Tested on Windows and Linux
  • Loading branch information
setnicka committed Jan 12, 2017
1 parent 7a9ef22 commit bc4ab7c
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 20 deletions.
4 changes: 4 additions & 0 deletions pyfirmata/pyfirmata.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@ class NoInputWarning(RuntimeWarning):
pass


class BoardSetupError(Exception):
pass


class Board(object):
"""The Base class for any board."""
firmata_version = None
Expand Down
64 changes: 44 additions & 20 deletions pyfirmata/util.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
"""Helper functioons for pyFirmata."""
from __future__ import division, unicode_literals

import os
Expand All @@ -6,36 +7,59 @@
import time

import serial
import serial.tools.list_ports

from .boards import BOARDS


def get_the_board(layout=BOARDS['arduino'], base_dir='/dev/', identifier='tty.usbserial',):
def autoload_board(layout=None, ports=None, ports_filter='Arduino'):
"""
Helper function to get the one and only board connected to the computer
running this. It assumes a normal arduino layout, but this can be
overriden by passing a different layout dict as the ``layout`` parameter.
``base_dir`` and ``identifier`` are overridable as well. It will raise an
IOError if it can't find a board, on a serial, or if it finds more than
one.
Helper function to get the one and only board connected to the computer.
It loads board layout from board auto setup, but layout could be specified
by setting ``layout`` parameter.
By default it loads active ports list by OS independent call, but specific
ports to scan could be set by ``ports`` parameter. When autoloading ports
they could be filtered by description starting by specific string (default
"Arduino"). Filtering could be disabled by setting ``ports_filter`` to None.
It will raise an IOError if it can't find a board, on a serial, or if it
finds more than one.
"""
from .pyfirmata import Board # prevent a circular import
from .pyfirmata import Board, BoardSetupError # prevent a circular import

# OS independent ports scan
if ports is None:
ports = [
port.device for port
in serial.tools.list_ports.comports()
if ports_filter is None or port.description.startswith(ports_filter)
]

boards = []
for device in os.listdir(base_dir):
if device.startswith(identifier):
try:
board = Board(os.path.join(base_dir, device), layout)
except serial.SerialException:
pass
else:
boards.append(board)
for port in ports:
try:
board = Board(port, layout)
except (serial.SerialException, BoardSetupError):
pass
else:
boards.append(board)

if len(boards) == 0:
raise IOError("No boards found in {0} with identifier {1}".format(base_dir, identifier))
raise IOError("No boards connected to {0} found".format(ports))
elif len(boards) > 1:
raise IOError("More than one board found!")
raise IOError("Multiple boards found!")
return boards[0]


def get_the_board(layout=None, base_dir='/dev/', identifier='tty.usbserial'):
"""Deprecated function for backward compatibility, Linux-only ports scan."""
ports = []

for device in os.listdir(base_dir):
if device.startswith(identifier):
ports.append(os.path.join(base_dir, device))
return autoload_board(layout=layout, ports=ports)


class Iterator(threading.Thread):
def __init__(self, board):
super(Iterator, self).__init__()
Expand Down

0 comments on commit bc4ab7c

Please sign in to comment.