Try to fix serial ports listing (#1155)

This commit is contained in:
Otto Winter 2020-07-24 10:09:43 +02:00 committed by GitHub
parent ebbfab608c
commit e8272759be
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 42 additions and 22 deletions

View file

@ -12,24 +12,12 @@ from esphome.const import CONF_BAUD_RATE, CONF_BROKER, CONF_LOGGER, CONF_OTA, \
CONF_PASSWORD, CONF_PORT, CONF_ESPHOME, CONF_PLATFORMIO_OPTIONS
from esphome.core import CORE, EsphomeError, coroutine, coroutine_with_priority
from esphome.helpers import color, indent
from esphome.util import run_external_command, run_external_process, safe_print, list_yaml_files
from esphome.util import run_external_command, run_external_process, safe_print, list_yaml_files, \
get_serial_ports
_LOGGER = logging.getLogger(__name__)
def get_serial_ports():
# from https://github.com/pyserial/pyserial/blob/master/serial/tools/list_ports.py
from serial.tools.list_ports import comports
result = []
for port, desc, info in comports(include_links=True):
if not port:
continue
if "VID:PID" in info:
result.append((port, desc))
result.sort(key=lambda x: x[0])
return result
def choose_prompt(options):
if not options:
raise EsphomeError("Found no valid options for upload/logging, please make sure relevant "
@ -60,8 +48,8 @@ def choose_prompt(options):
def choose_upload_log_host(default, check_default, show_ota, show_mqtt, show_api):
options = []
for res, desc in get_serial_ports():
options.append((f"{res} ({desc})", res))
for port in get_serial_ports():
options.append((f"{port.path} ({port.description})", port.path))
if (show_ota and 'ota' in CORE.config) or (show_api and 'api' in CORE.config):
options.append((f"Over The Air ({CORE.address})", CORE.address))
if default == 'OTA':

View file

@ -26,11 +26,10 @@ import tornado.web
import tornado.websocket
from esphome import const, util
from esphome.__main__ import get_serial_ports
from esphome.helpers import mkdir_p, get_bool_env, run_system_command
from esphome.storage_json import EsphomeStorageJSON, StorageJSON, \
esphome_storage_path, ext_storage_path, trash_storage_path
from esphome.util import shlex_quote
from esphome.util import shlex_quote, get_serial_ports
# pylint: disable=unused-import, wrong-import-order
from typing import Optional # noqa
@ -313,14 +312,15 @@ class SerialPortRequestHandler(BaseHandler):
def get(self):
ports = get_serial_ports()
data = []
for port, desc in ports:
if port == '/dev/ttyAMA0':
for port in ports:
desc = port.description
if port.path == '/dev/ttyAMA0':
desc = 'UART pins on GPIO header'
split_desc = desc.split(' - ')
if len(split_desc) == 2 and split_desc[0] == split_desc[1]:
# Some serial ports repeat their values
desc = split_desc[0]
data.append({'port': port, 'desc': desc})
data.append({'port': port.path, 'desc': desc})
data.append({'port': 'OTA', 'desc': 'Over-The-Air'})
data.sort(key=lambda x: x['port'], reverse=True)
self.write(json.dumps(data))

View file

@ -1,4 +1,4 @@
from typing import Union
from typing import Union, List
import collections
import io
@ -7,6 +7,7 @@ import os
import re
import subprocess
import sys
from pathlib import Path
from esphome import const
@ -256,3 +257,34 @@ def filter_yaml_files(files):
files = [f for f in files if os.path.basename(f) != 'secrets.yaml']
files = [f for f in files if not os.path.basename(f).startswith('.')]
return files
class SerialPort:
def __init__(self, path: str, description: str):
self.path = path
self.description = description
# from https://github.com/pyserial/pyserial/blob/master/serial/tools/list_ports.py
def get_serial_ports() -> List[SerialPort]:
from serial.tools.list_ports import comports
result = []
for port, desc, info in comports(include_links=True):
if not port:
continue
if "VID:PID" in info:
result.append(SerialPort(path=port, description=desc))
# Also add objects in /dev/serial/by-id/
# ref: https://github.com/esphome/issues/issues/1346
by_id_path = Path('/dev/serial/by-id')
if sys.platform.lower().startswith('linux') and by_id_path.exists():
from serial.tools.list_ports_linux import SysFS
for path in by_id_path.glob('*'):
device = SysFS(path)
if device.subsystem == 'platform':
result.append(SerialPort(path=str(path), description=info[1]))
result.sort(key=lambda x: x.path)
return result