2010-02-18 22 views
29

Wiem, że mogę użyć np. pySerial, aby porozmawiać z urządzeniami szeregowymi, ale co, jeśli nie mam teraz urządzenia, ale muszę jeszcze napisać do niego klienta? Jak mogę napisać "wirtualne urządzenie szeregowe" w Pythonie i mieć z nim rozmowę na temat pySerial, tak jakbym, powiedzmy, uruchomił lokalny serwer sieciowy? Może po prostu nie szukam dobrze, ale nie udało mi się znaleźć żadnych informacji na ten temat.Virtual Serial Device w języku Python?

Odpowiedz

4

Może być łatwiej używać czegoś takiego jak com0com (jeśli jesteś w systemie Windows), aby skonfigurować wirtualny port szeregowy i rozwijać się na tym.

4

To zależy trochę od tego, co starasz się osiągnąć teraz ...

Można owinąć dostęp do portu szeregowego w klasie i napisać implementację użyć gniazda we/wy lub plik I/O . Następnie wpisz swoją klasę I/O, aby użyć tego samego interfejsu i podłączyć go, gdy urządzenie jest dostępne. (Jest to właściwie dobry projekt do testowania funkcjonalności bez wymaganego zewnętrznego sprzętu.)

Lub, jeśli zamierzasz używać portu szeregowego dla interfejsu linii poleceń, możesz użyć stdin/stdout. To jest inna odpowiedź na temat virtual serial devices for linux.

+0

Tak, napisać klasę „wirtualne urządzenie szeregowe”, który powiela interfejs pyserial. Wtedy twój kod może używać zamiennie albo "klasę urządzenia wirtualnego", albo rzeczywistego interfejsu pySerial. –

+0

Jest to dobra implementacja, ponieważ jest raczej łatwa do wdrożenia i będzie działać na wszystkich platformach! – Pithikos

+0

Przepraszam za aktualizację tego starego posta, ale czy mógłbyś nieco bardziej rozwinąć? Byłoby to dla mnie bardzo pomocne. Dzięki – rowman

27

to jest coś zrobiłem i pracował dla mnie do tej pory:

import os, pty, serial 

master, slave = pty.openpty() 
s_name = os.ttyname(slave) 

ser = serial.Serial(s_name) 

# To Write to the device 
ser.write('Your text') 

# To read from the device 
os.read(master,1000) 

Jeśli tworzysz porty więcej wirtualnych będziesz miał żadnych problemów w różnych mistrzów uzyskać różne deskryptory nawet jeśli mają takie samo imię.

+0

To jest dokładnie odpowiedź, której szukałem. Działa to dla mnie na Mac OS X. – DrRobotNinja

+1

To nie zadziała w systemie Windows, w którym brakuje modułu termios wymaganego przez pty. – OYRM

+1

Wydaje mi się, że jestem w stanie odczytać z fałszywego urządzenia po prostu dobrze (tj. Mam inny program zapisujący na urządzeniu w punkcie końcowym 's_name'), ale za każdym razem, gdy wysyłam' ser.write ("...") ', ten tekst po prostu powtórz echo następnym razem, gdy 'os.read (master, 1000)', niezależnie od tego, czy coś jest podłączone do portu, a drugi koniec portu nie wydaje się uzyskać danych. – Ponkadoodle

2

Jeśli używasz systemu Linux można użyć komendy socat za to tak:

socat -d -d pty,raw,echo=0 pty,raw,echo=0 

Kiedy biegnie dowodzenia, poinformuje cię o których porty szeregowe to stworzył. Na moim komputerze to wygląda:

2014/04/23 15:47:49 socat[31711] N PTY is /dev/pts/12 
2014/04/23 15:47:49 socat[31711] N PTY is /dev/pts/13 
2014/04/23 15:47:49 socat[31711] N starting data transfer loop with FDs [3,3] and [5,5] 

Teraz mogę napisać do /dev/pts/13 i odbierać na /dev/pts/12 i vice versa.

1

byłem w stanie naśladować dowolny port szeregowy ./foo przy użyciu tego kodu:

SerialEmulator.py

import os, subprocess, serial, time 

# this script lets you emulate a serial device 
# the client program should use the serial port file specifed by client_port 

# if the port is a location that the user can't access (ex: /dev/ttyUSB0 often), 
# sudo is required 

class SerialEmulator(object): 
    def __init__(self, device_port='./ttydevice', client_port='./ttyclient'): 
     self.device_port = device_port 
     self.client_port = client_port 
     cmd=['/usr/bin/socat','-d','-d','PTY,link=%s,raw,echo=0' % 
       self.device_port, 'PTY,link=%s,raw,echo=0' % self.client_port] 
     self.proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
     time.sleep(1) 
     self.serial = serial.Serial(self.device_port, 9600, rtscts=True, dsrdtr=True) 
     self.err = '' 
     self.out = '' 

    def write(self, out): 
     self.serial.write(out) 

    def read(self): 
     line = '' 
     while self.serial.inWaiting() > 0: 
      line += self.serial.read(1) 
     print line 

    def __del__(self): 
     self.stop() 

    def stop(self): 
     self.proc.kill() 
     self.out, self.err = self.proc.communicate() 

socat musi być zainstalowany (sudo apt-get install socat), a także pakiet pyserial Pythona (pip install pyserial).

Otwórz interpreter Pythona i import SerialEmulator:

>>> from SerialEmulator import SerialEmulator 
>>> emulator = SerialEmulator('./ttydevice','./ttyclient') 
>>> emulator.write('foo') 
>>> emulator.read() 

Program klient może następnie owinąć ./ttyclient z pyserial, tworząc wirtualny port szeregowy. Można również zrobić client_port /dev/ttyUSB0 lub coś podobnego, jeśli nie można zmodyfikować kodu klienta, ale może być potrzebny sudo.

Należy także pamiętać o tym problemie: Pyserial does not play well with virtual port