Exemplo n.º 1
0
 def run(self, args):
     try:
         copytree(os.path.join(self.e['templates_dir'], args.template),
                  '.',
                  ignore=lambda *args: ['manifest.ini'])
     except shutil.Error as e:
         raise Abort(str(e))
Exemplo n.º 2
0
    def parse(cls, s):
        # Version could have various forms
        #   0022
        #   0022ubuntu0.1
        #   0022-macosx-20110822
        #   1.0
        #   1:1.0.5+dfsg2-1
        # We have to extract a 3-int-tuple (major, minor, build)
        match = cls.regex.match(s)
        if not match:
            raise Abort("Could not parse Arduino library version: %s" % s)

        # v is numbers possibly split by dots without a trash
        v = match.group(2)

        if v.startswith('0'):
            # looks like old 0022 or something like that
            return cls(0, int(v), 0)

        parts = map(int, v.split('.'))

        # append nulls if they were not explicit
        while len(parts) < 3:
            parts.append(0)

        return cls(*parts)
Exemplo n.º 3
0
    def _find(self, key, items, places, human_name, join, multi, optional):
        """
        Search for file-system entry with any name passed in `items` on
        all paths provided in `places`. Use `key` as a cache key.

        If `join` is True result will be a path join of place/item,
        otherwise only place is taken as result.

        Return first found match unless `multi` is True. In that case
        a list with all fount matches is returned.

        Raise `Abort` if no matches were found.
        """
        if key in self:
            return self[key]

        human_name = human_name or key

        # expand env variables in `places` and split on colons
        places = itertools.chain.from_iterable(
            os.path.expandvars(p).split(os.pathsep) for p in places)
        places = map(os.path.expanduser, places)

        glob_places = itertools.chain.from_iterable(glob(p) for p in places)

        print 'Searching for', human_name, '...',
        results = []
        for p in glob_places:
            for i in items:
                path = os.path.join(p, i)
                if os.path.exists(path):
                    result = path if join else p
                    if not multi:
                        print colorize(result, 'green')
                        self[key] = result
                        return result
                    results.append(result)

        if results:
            if len(results) > 1:
                formatted_results = ''.join(['\n  - ' + x for x in results])
                print colorize('found multiple: %s' % formatted_results,
                               'green')
            else:
                print colorize(results[0], 'green')

            self[key] = results
            return results

        print colorize('FAILED', 'red')
        if not optional:
            raise Abort("%s not found. Searched in following places: %s" %
                        (human_name, ''.join(['\n  - ' + p for p in places])))
        else:
            self[key] = None
            return results
Exemplo n.º 4
0
    def guess_serial_port(self):
        print 'Guessing serial port ...',

        ports = self.list_serial_ports()
        if ports:
            result = ports[0]
            print colorize(result, 'yellow')
            return result

        print colorize('FAILED', 'red')
        raise Abort(
            "No device matching following was found: %s" %
            (''.join(['\n  - ' + p for p in self.serial_port_patterns()])))
Exemplo n.º 5
0
    def process_args(self, args):
        arduino_dist = getattr(args, 'arduino_dist', None)
        if arduino_dist:
            self['arduino_dist_dir'] = arduino_dist

        board_model = getattr(args, 'board_model', None)
        if board_model:
            all_models = self.board_models()
            if board_model not in all_models:
                print "Supported Arduino board models are:"
                print all_models.format()
                raise Abort('%s is not a valid board model' % board_model)

        # Build artifacts for each Arduino distribution / Board model
        # pair should go to a separate subdirectory
        build_dirname = board_model or self.default_board_model
        if arduino_dist:
            distHash = hashlib.md5(arduino_dist).hexdigest()[:8]
            build_dirname = '%s-%s' % (build_dirname, distHash)

        self['build_dir'] = os.path.join(self.output_dir, build_dirname)
Exemplo n.º 6
0
    def run(self, args):
        self.discover()
        port = args.serial_port or self.e.guess_serial_port()
        board = self.e.board_model(args.board_model)

        protocol = board['upload']['protocol']
        if protocol == 'stk500':
            # if v1 is not specifid explicitly avrdude will
            # try v2 first and fail
            protocol = 'stk500v1'

        if not os.path.exists(port):
            raise Abort("%s doesn't exist. Is Arduino connected?" % port)

        # send a hangup signal when the last process closes the tty
        file_switch = '-f' if platform.system() == 'Darwin' else '-F'
        ret = subprocess.call([self.e['stty'], file_switch, port, 'hupcl'])
        if ret:
            raise Abort("stty failed")

        # pulse on DTR
        try:
            s = Serial(port, 115200)
        except SerialException as e:
            raise Abort(str(e))
        s.setDTR(False)
        sleep(0.1)
        s.setDTR(True)
        s.close()

        # Need to do a little dance for Leonardo and derivatives:
        # open then close the port at the magic baudrate (usually 1200 bps) first
        # to signal to the sketch that it should reset into bootloader. after doing
        # this wait a moment for the bootloader to enumerate. On Windows, also must
        # deal with the fact that the COM port number changes from bootloader to
        # sketch.
        touch_port = \
                board['upload'].get('use_1200bps_touch') == 'true' or \
                board['upload']['protocol'] == 'avr109'

        if touch_port:
            new_port = None
            before = self.e.list_serial_ports()
            if port in before:
                ser = Serial()
                ser.port = port
                ser.baudrate = 1200
                ser.open()
                ser.close()

                # Scanning for available ports seems to open the port or
                # otherwise assert DTR, which would cancel the WDT reset if
                # it happened within 250 ms. So we wait until the reset should
                # have already occured before we start scanning.
                if platform.system() != 'Darwin':
                    sleep(0.3)

            elapsed = 0
            enum_delay = 0.25
            while elapsed < 10:
                now = self.e.list_serial_ports()
                diff = list(set(now) - set(before))
                if diff:
                    new_port = diff[0]
                    break

                before = now
                sleep(enum_delay)
                elapsed += enum_delay

            if not new_port:
                raise Abort("Couldn’t find a board on the selected port. "
                            "Check that you have the correct port selected. "
                            "If it is correct, try pressing the board's reset "
                            "button after initiating the upload.")

            port = new_port

        # call avrdude to upload .hex
        subprocess.call([
            self.e['avrdude'],
            '-C',
            self.e['avrdude.conf'],
            '-p',
            board['build']['mcu'],
            '-P',
            port,
            '-c',
            protocol,
            '-b',
            board['upload']['speed'],
            '-D',
            '-U',
            'flash:w:%s:i' % self.e['hex_path'],
        ])
Exemplo n.º 7
0
 def make(self, makefile, **kwargs):
     makefile = self.render_template(makefile + '.jinja', makefile, **kwargs)
     ret = subprocess.call([self.e.make, '-f', makefile, 'all'])
     if ret != 0:
         raise Abort("Make failed with code %s" % ret)
Exemplo n.º 8
0
def main():
    e = Environment()
    e.load()

    conf = configure()

    try:
        current_command = sys.argv[1]
    except IndexError:
        current_command = None

    parser = argparse.ArgumentParser(prog='ano',
                                     formatter_class=FlexiFormatter,
                                     description=__doc__)
    subparsers = parser.add_subparsers()
    is_command = lambda x: inspect.isclass(x) and issubclass(x, Command
                                                             ) and x != Command
    commands = [
        cls(e) for _, cls in inspect.getmembers(ano.commands, is_command)
    ]
    for cmd in commands:
        p = subparsers.add_parser(cmd.name,
                                  formatter_class=FlexiFormatter,
                                  help=cmd.help_line)
        if current_command != cmd.name:
            continue
        cmd.setup_arg_parser(p)
        p.set_defaults(func=cmd.run, **conf.as_dict(cmd.name))

    args = parser.parse_args()

    try:
        run_anywhere = "init clean list-models serial version"

        e.process_args(args)

        if current_command not in run_anywhere:
            if os.path.isdir(e.output_dir):
                # we have an output dir so we'll pretend this is a project folder
                None
            elif e.src_dir is None or not os.path.isdir(e.src_dir):
                raise Abort("No project found in this directory.")

        if current_command not in run_anywhere:
            # For valid projects create .build & lib
            if not os.path.isdir(e.build_dir):
                os.makedirs(e.build_dir)

            if not os.path.isdir(e.lib_dir):
                os.makedirs(e.lib_dir)
                with open('lib/.holder', 'w') as f:
                    f.write("")

        args.func(args)
    except Abort as exc:
        print colorize(str(exc), 'red')
        sys.exit(1)
    except KeyboardInterrupt:
        print 'Terminated by user'
    finally:
        e.dump()