diff --git a/examples b/examples index 3aa5ced9..8464bbb5 160000 --- a/examples +++ b/examples @@ -1 +1 @@ -Subproject commit 3aa5ced9414f34d3c5f556dd66c8fdd85b4125be +Subproject commit 8464bbb5d96022ade33f92ca829c6401fb067d6a diff --git a/platformio/builder/tools/pioupload.py b/platformio/builder/tools/pioupload.py index 66de3fbf..14ee59e1 100644 --- a/platformio/builder/tools/pioupload.py +++ b/platformio/builder/tools/pioupload.py @@ -12,13 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +# pylint: disable=unused-argument + from __future__ import absolute_import +import os import re import sys -from fnmatch import fnmatch -from os import environ -from os.path import isfile, join from shutil import copyfile from time import sleep @@ -26,12 +26,10 @@ from SCons.Script import ARGUMENTS # pylint: disable=import-error from serial import Serial, SerialException from platformio import exception, fs -from platformio.compat import IS_WINDOWS -from platformio.device.list import list_logical_devices, list_serial_ports +from platformio.device.finder import find_mbed_disk, find_serial_port, is_pattern_port +from platformio.device.list import list_serial_ports from platformio.proc import exec_command -# pylint: disable=unused-argument - def FlushSerialBuffer(env, port): s = Serial(env.subst(port)) @@ -98,67 +96,28 @@ def WaitForNewSerialPort(env, before): def AutodetectUploadPort(*args, **kwargs): env = args[0] - - def _get_pattern(): - if "UPLOAD_PORT" not in env: - return None - if set(["*", "?", "[", "]"]) & set(env["UPLOAD_PORT"]): - return env["UPLOAD_PORT"] - return None - - def _is_match_pattern(port): - pattern = _get_pattern() - if not pattern: - return True - return fnmatch(port, pattern) - - def _look_for_mbed_disk(): - msdlabels = ("mbed", "nucleo", "frdm", "microbit") - for item in list_logical_devices(): - if item["path"].startswith("/net") or not _is_match_pattern(item["path"]): - continue - mbed_pages = [join(item["path"], n) for n in ("mbed.htm", "mbed.html")] - if any(isfile(p) for p in mbed_pages): - return item["path"] - if item["name"] and any(l in item["name"].lower() for l in msdlabels): - return item["path"] - return None - - def _look_for_serial_port(): - port = None - board_hwids = [] - upload_protocol = env.subst("$UPLOAD_PROTOCOL") - if "BOARD" in env and "build.hwids" in env.BoardConfig(): - board_hwids = env.BoardConfig().get("build.hwids") - for item in list_serial_ports(filter_hwid=True): - if not _is_match_pattern(item["port"]): - continue - port = item["port"] - if upload_protocol.startswith("blackmagic"): - if IS_WINDOWS and port.startswith("COM") and len(port) > 4: - port = "\\\\.\\%s" % port - if "GDB" in item["description"]: - return port - for hwid in board_hwids: - hwid_str = ("%s:%s" % (hwid[0], hwid[1])).replace("0x", "") - if hwid_str in item["hwid"]: - return port - return port - - if "UPLOAD_PORT" in env and not _get_pattern(): - print(env.subst("Use manually specified: $UPLOAD_PORT")) + initial_port = env.subst("$UPLOAD_PORT") + upload_protocol = env.subst("$UPLOAD_PROTOCOL") + if initial_port and not is_pattern_port(initial_port): + print(env.subst("Using manually specified: $UPLOAD_PORT")) return - if env.subst("$UPLOAD_PROTOCOL") == "mbed" or ( - "mbed" in env.subst("$PIOFRAMEWORK") and not env.subst("$UPLOAD_PROTOCOL") + if upload_protocol == "mbed" or ( + "mbed" in env.subst("$PIOFRAMEWORK") and not upload_protocol ): - env.Replace(UPLOAD_PORT=_look_for_mbed_disk()) + env.Replace(UPLOAD_PORT=find_mbed_disk(initial_port)) else: try: fs.ensure_udev_rules() except exception.InvalidUdevRules as e: sys.stderr.write("\n%s\n\n" % e) - env.Replace(UPLOAD_PORT=_look_for_serial_port()) + env.Replace( + UPLOAD_PORT=find_serial_port( + initial_port=initial_port, + board_config=env.BoardConfig() if "BOARD" in env else None, + upload_protocol=upload_protocol, + ) + ) if env.subst("$UPLOAD_PORT"): print(env.subst("Auto-detected: $UPLOAD_PORT")) @@ -176,10 +135,12 @@ def UploadToDisk(_, target, source, env): assert "UPLOAD_PORT" in env progname = env.subst("$PROGNAME") for ext in ("bin", "hex"): - fpath = join(env.subst("$BUILD_DIR"), "%s.%s" % (progname, ext)) - if not isfile(fpath): + fpath = os.path.join(env.subst("$BUILD_DIR"), "%s.%s" % (progname, ext)) + if not os.path.isfile(fpath): continue - copyfile(fpath, join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext))) + copyfile( + fpath, os.path.join(env.subst("$UPLOAD_PORT"), "%s.%s" % (progname, ext)) + ) print( "Firmware has been successfully uploaded.\n" "(Some boards may require manual hard reset)" @@ -212,7 +173,7 @@ def CheckUploadSize(_, target, source, env): if not isinstance(cmd, list): cmd = cmd.split() cmd = [arg.replace("$SOURCES", str(source[0])) for arg in cmd if arg] - sysenv = environ.copy() + sysenv = os.environ.copy() sysenv["PATH"] = str(env["ENV"]["PATH"]) result = exec_command(env.subst(cmd), env=sysenv) if result["returncode"] != 0: diff --git a/platformio/device/commands/monitor.py b/platformio/device/commands/monitor.py index e13cfdc7..f3d4ace5 100644 --- a/platformio/device/commands/monitor.py +++ b/platformio/device/commands/monitor.py @@ -20,7 +20,7 @@ from serial.tools import miniterm from platformio import exception, fs from platformio.device.filters.base import register_filters -from platformio.device.serial import scan_serial_port +from platformio.device.finder import find_serial_port from platformio.platform.factory import PlatformFactory from platformio.project.config import ProjectConfig from platformio.project.exception import NotPlatformIOProjectError @@ -108,7 +108,7 @@ def device_monitor_cmd(**kwargs): # pylint: disable=too-many-branches except NotPlatformIOProjectError: pass register_filters(platform=platform, options=kwargs) - kwargs["port"] = scan_serial_port( + kwargs["port"] = find_serial_port( initial_port=kwargs["port"], board_config=platform.board_config(project_options.get("board")) if platform and project_options.get("board") diff --git a/platformio/device/serial.py b/platformio/device/finder.py similarity index 72% rename from platformio/device/serial.py rename to platformio/device/finder.py index 6d32e139..0fe98baa 100644 --- a/platformio/device/serial.py +++ b/platformio/device/finder.py @@ -12,12 +12,13 @@ # See the License for the specific language governing permissions and # limitations under the License. +import os from fnmatch import fnmatch import serial from platformio.compat import IS_WINDOWS -from platformio.device.list import list_serial_ports +from platformio.device.list import list_logical_devices, list_serial_ports def is_pattern_port(port): @@ -26,6 +27,13 @@ def is_pattern_port(port): return set(["*", "?", "[", "]"]) & set(port) +def match_serial_port(pattern): + for item in list_serial_ports(): + if fnmatch(item["port"], pattern): + return item["port"] + return None + + def is_serial_port_ready(port, timeout=1): try: serial.Serial(port, timeout=timeout).close() @@ -35,7 +43,7 @@ def is_serial_port_ready(port, timeout=1): return False -def scan_serial_port( +def find_serial_port( initial_port, board_config=None, upload_protocol=None, ensure_ready=False ): if initial_port: @@ -44,9 +52,9 @@ def scan_serial_port( return match_serial_port(initial_port) port = None if upload_protocol and upload_protocol.startswith("blackmagic"): - port = scan_blackmagic_serial_port() + port = find_blackmagic_serial_port() if not port and board_config: - port = scan_board_serial_port(board_config) + port = find_board_serial_port(board_config) if port: return port @@ -61,14 +69,7 @@ def scan_serial_port( return usb_port or port -def match_serial_port(pattern): - for item in list_serial_ports(): - if fnmatch(item["port"], pattern): - return item["port"] - return None - - -def scan_blackmagic_serial_port(): +def find_blackmagic_serial_port(): for item in list_serial_ports(): port = item["port"] if IS_WINDOWS and port.startswith("COM") and len(port) > 4: @@ -78,7 +79,7 @@ def scan_blackmagic_serial_port(): return None -def scan_board_serial_port(board_config): +def find_board_serial_port(board_config): board_hwids = board_config.get("build.hwids", []) if not board_hwids: return None @@ -89,3 +90,22 @@ def scan_board_serial_port(board_config): if hwid_str in item["hwid"]: return port return None + + +def find_mbed_disk(initial_port): + msdlabels = ("mbed", "nucleo", "frdm", "microbit") + for item in list_logical_devices(): + if item["path"].startswith("/net"): + continue + if ( + initial_port + and is_pattern_port(initial_port) + and not fnmatch(item["path"], initial_port) + ): + continue + mbed_pages = [os.path.join(item["path"], n) for n in ("mbed.htm", "mbed.html")] + if any(os.path.isfile(p) for p in mbed_pages): + return item["path"] + if item["name"] and any(l in item["name"].lower() for l in msdlabels): + return item["path"] + return None diff --git a/platformio/test/runners/readers/serial.py b/platformio/test/runners/readers/serial.py index 1f41fac2..195298a0 100644 --- a/platformio/test/runners/readers/serial.py +++ b/platformio/test/runners/readers/serial.py @@ -17,7 +17,7 @@ from time import sleep import click import serial -from platformio.device.serial import scan_serial_port +from platformio.device.finder import find_serial_port from platformio.exception import UserSideException @@ -77,7 +77,7 @@ class SerialTestOutputReader: elapsed = 0 while elapsed < 5: - port = scan_serial_port(**scan_options) + port = find_serial_port(**scan_options) if port: return port sleep(0.25)