python - read - Listado de puertos serie(COM) en Windows?
serial port python windows (8)
Estoy buscando una forma sólida de enumerar los puertos serie (COM) disponibles en una máquina con Windows. Hay una publicación sobre el uso de WMI , pero me gustaría algo menos específico para .NET: quiero obtener la lista de puertos en un programa de Python o C ++, sin .NET.
Actualmente sé de otros dos enfoques:
Lectura de la información en la clave de registro
HARDWARE//DEVICEMAP//SERIALCOMM
. Esto parece una gran opción, pero ¿es robusto ? No puedo encontrar una garantía en línea o en MSDN de que esta celda de registro siempre contenga la lista completa de puertos disponibles.Intente llamar a CreateFile en
COMN
con N un número de 1 a algo. Esto no es lo suficientemente bueno, porque algunos puertos COM no se llaman COMN. Por ejemplo, algunos puertos COM virtuales creados se llaman CSNA0, CSNB0, etc., así que no confiaría en este método.
¿Algún otro método / ideas / experiencia para compartir?
Editar: por cierto, aquí hay una implementación simple de Python para leer los nombres de los puertos del registro:
import _winreg as winreg
import itertools
def enumerate_serial_ports():
""" Uses the Win32 registry to return a iterator of serial
(COM) ports existing on this computer.
"""
path = ''HARDWARE//DEVICEMAP//SERIALCOMM''
try:
key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path)
except WindowsError:
raise IterationError
for i in itertools.count():
try:
val = winreg.EnumValue(key, i)
yield (str(val[1]), str(val[0]))
except EnvironmentError:
break
Acabo de crear lo siguiente, basado en leer a través de la fuente C ++ a EnumSerialPorts y ver la función GetDefaultCommConfig()
. Parecía el método más simple usando ANSI C simple y una única llamada API para cada posible puerto COM.
#include <stdio.h>
#include <windows.h>
#include <winbase.h>
BOOL COM_exists( int port)
{
char buffer[7];
COMMCONFIG CommConfig;
DWORD size;
if (! (1 <= port && port <= 255))
{
return FALSE;
}
snprintf( buffer, sizeof buffer, "COM%d", port);
size = sizeof CommConfig;
// COM port exists if GetDefaultCommConfig returns TRUE
// or changes <size> to indicate COMMCONFIG buffer too small.
return (GetDefaultCommConfig( buffer, &CommConfig, &size)
|| size > sizeof CommConfig);
}
int main()
{
int i;
for (i = 1; i < 256; ++i)
{
if (COM_exists( i))
{
printf( "COM%d exists/n", i);
}
}
return 0;
}
Creo que WMI es el camino a seguir, ya que es bastante fácil de poner en marcha y tiene un código mínimo. Le ahorra tener que cavar dentro del registro y le da cierta garantía de que funcionará para situaciones más generales en el futuro.
Puede instalar todo lo necesario con pip install pypiwin32 WMI
y funciona de fábrica.
Código
import wmi
query = "SELECT * FROM Win32_PnPEntity WHERE Name LIKE ''%(COM%)''"
coms = wmi.WMI().query(query)
for com in coms:
print(com.Name)
Salida
Communications Port (COM1)
mbed Serial Port (COM3)
mbed Serial Port (COM5)
Supongo que su puerto serie es una especie de Plug ''n Play, así que debería funcionar bien. Por alguna razón, Win32_SerialPort
no funciona para todos los puertos.
El proyecto PySerial proporciona un par de soluciones .
Esto definitivamente es bastante tarde, ¡pero fue útil para mí!
http://eli.thegreenplace.net/2009/07/31/listing-all-serial-ports-on-windows-with-python/
Particularmente este ejemplo:
import re
def full_port_name(portname):
""" Given a port-name (of the form COM7,
COM12, CNCA0, etc.) returns a full
name suitable for opening with the
Serial class.
"""
m = re.match(''^COM(/d+)$'', portname)
if m and int(m.group(1)) < 10:
return portname
return ''////.//' + portname
Hay un ejemplo en la distribución pyserial ahora que hace esto llamado scanwin32.py
http://pyserial.sourcearchive.com/documentation/2.5/scanwin32_8py_source.html
Hoy en día hay un trazador de líneas de Powershell para eso.
[System.IO.Ports.SerialPort]::GetPortNames()
Usando pySerial con Python:
import serial.tools.list_ports
ports = list(serial.tools.list_ports.comports())
for p in ports:
print p
Varias opciones están disponibles:
Llame a QueryDosDevice con NULL lpDeviceName para listar todos los dispositivos de DOS. Luego utilice GetCommConfig y GetCommConfig con cada nombre de dispositivo para determinar si se trata de un puerto serie.
Llame a SetupDiGetClassDevs con un ClassGuid de GUID_DEVINTERFACE_COMPORT.
Hay alguna conversación sobre el grupo de noticias win32 y un proyecto CodeProject, er.