summaryrefslogtreecommitdiff
path: root/examples
diff options
context:
space:
mode:
authorcliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2009-08-07 18:22:49 +0000
committercliechti <cliechti@f19166aa-fa4f-0410-85c2-fa1106f25c8a>2009-08-07 18:22:49 +0000
commit82b30aadd0d7f693fe3f2a882b18e5ac2f0517bd (patch)
tree9b0e6be17f3224bca42073ba77674455cb4b2929 /examples
parent93bfe4f43975cf7f6af788b863a1fec7c2379f32 (diff)
downloadpyserial-82b30aadd0d7f693fe3f2a882b18e5ac2f0517bd.tar.gz
add a simplified single port RFC 2217 server
git-svn-id: http://svn.code.sf.net/p/pyserial/code/trunk/pyserial@320 f19166aa-fa4f-0410-85c2-fa1106f25c8a
Diffstat (limited to 'examples')
-rw-r--r--examples/rfc2217_server.py159
-rw-r--r--examples/setup-rfc2217_server-py2exe.py24
2 files changed, 183 insertions, 0 deletions
diff --git a/examples/rfc2217_server.py b/examples/rfc2217_server.py
new file mode 100644
index 0000000..151d3c3
--- /dev/null
+++ b/examples/rfc2217_server.py
@@ -0,0 +1,159 @@
+#!/usr/bin/env python
+
+# (C) 2009 Chris Liechti <cliechti@gmx.net>
+# redirect data from a TCP/IP connection to a serial port and vice versa
+# using RFC 2217
+
+
+import sys
+import os
+import threading
+import time
+import socket
+import serial
+import serial.rfc2217
+
+class Redirector:
+ def __init__(self, serial_instance, socket):
+ self.serial = serial_instance
+ self.socket = socket
+ self._write_lock = threading.Lock()
+ self.rfc2217 = serial.rfc2217.PortManager(self.serial, self, debug_output=False)
+
+ def statusline_poller(self):
+ while self.alive:
+ time.sleep(1)
+ self.rfc2217.check_modem_lines()
+
+ def shortcut(self):
+ """connect the serial port to the TCP port by copying everything
+ from one side to the other"""
+ self.alive = True
+ self.thread_read = threading.Thread(target=self.reader)
+ self.thread_read.setDaemon(True)
+ self.thread_read.setName('serial->socket')
+ self.thread_read.start()
+ self.thread_poll = threading.Thread(target=self.statusline_poller)
+ self.thread_poll.setDaemon(True)
+ self.thread_poll.setName('status line poll')
+ self.thread_poll.start()
+ self.writer()
+
+ def reader(self):
+ """loop forever and copy serial->socket"""
+ while self.alive:
+ try:
+ data = self.serial.read(1) # read one, blocking
+ n = self.serial.inWaiting() # look if there is more
+ if n:
+ data = data + self.serial.read(n) # and get as much as possible
+ if data:
+ # escape outgoing data when needed (Telnet IAC (0xff) character)
+ data = serial.to_bytes(self.rfc2217.escape(data))
+ self._write_lock.acquire()
+ try:
+ self.socket.sendall(data) # send it over TCP
+ finally:
+ self._write_lock.release()
+ except socket.error, msg:
+ sys.stderr.write('ERROR: %s\n' % msg)
+ # probably got disconnected
+ break
+ self.alive = False
+
+ def write(self, data):
+ """thread safe socket write with no data escaping. used to send telnet stuff"""
+ self._write_lock.acquire()
+ try:
+ self.socket.sendall(data)
+ finally:
+ self._write_lock.release()
+
+ def writer(self):
+ """loop forever and copy socket->serial"""
+ while self.alive:
+ try:
+ data = self.socket.recv(1024)
+ if not data:
+ break
+ self.serial.write(serial.to_bytes(self.rfc2217.filter(data)))
+ except socket.error, msg:
+ sys.stderr.write('ERROR: %s\n' % msg)
+ # probably got disconnected
+ break
+ self.alive = False
+ self.thread_read.join()
+
+ def stop(self):
+ """Stop copying"""
+ if self.alive:
+ self.alive = False
+ self.thread_read.join()
+
+
+if __name__ == '__main__':
+ import optparse
+
+ parser = optparse.OptionParser(
+ usage = "%prog [options] [port [baudrate]]",
+ description = "RFC 2217 Serial to Network (TCP/IP) redirector.",
+ epilog = """\
+NOTE: no security measures are implemented. Anyone can remotely connect
+to this service over the network.
+
+Only one connection at once is supported. When the connection is terminated
+it waits for the next connect.
+""")
+
+ parser.add_option("-p", "--localport",
+ dest = "local_port",
+ action = "store",
+ type = 'int',
+ help = "local TCP port",
+ default = 2217
+ )
+
+ (options, args) = parser.parse_args()
+
+ if len(args) != 1:
+ parser.error('serial port name required as argument')
+
+ # connect to serial port
+ ser = serial.Serial()
+ ser.port = args[0]
+ ser.timeout = 1 # required so that the reader thread can exit
+
+ sys.stderr.write("--- RFC 2217 TCP/IP to Serial redirector --- type Ctrl-C / BREAK to quit\n")
+
+ try:
+ ser.open()
+ except serial.SerialException, e:
+ sys.stderr.write("Could not open serial port %s: %s\n" % (ser.portstr, e))
+ sys.exit(1)
+
+ sys.stderr.write("--- Serving serial port: %s\n" % (ser.portstr,))
+
+ srv = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ srv.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ srv.bind( ('', options.local_port) )
+ srv.listen(1)
+ sys.stderr.write("--- TCP/IP port: %s\n" % (options.local_port,))
+ while True:
+ try:
+ connection, addr = srv.accept()
+ sys.stderr.write('Connected by %s\n' % (addr,))
+ # enter console->serial loop
+ r = Redirector(
+ ser,
+ connection,
+ )
+ r.shortcut()
+ sys.stderr.write('Disconnected\n')
+ connection.close()
+ except KeyboardInterrupt:
+ break
+ except socket.error, msg:
+ sys.stderr.write('ERROR: %s\n' % msg)
+
+ sys.stderr.write('\n--- exit ---\n')
+
diff --git a/examples/setup-rfc2217_server-py2exe.py b/examples/setup-rfc2217_server-py2exe.py
new file mode 100644
index 0000000..020427e
--- /dev/null
+++ b/examples/setup-rfc2217_server-py2exe.py
@@ -0,0 +1,24 @@
+# setup script for py2exe to create the miniterm.exe
+# $Id$
+
+from distutils.core import setup
+import glob, sys, py2exe, os
+
+sys.path.append('..')
+
+sys.argv.extend("py2exe --bundle 1".split())
+
+setup(
+ name='rfc2217_server',
+ zipfile=None,
+ options = {"py2exe":
+ {
+ 'dist_dir': 'bin',
+ 'excludes': ['javax.comm'],
+ 'compressed': 1,
+ }
+ },
+ console = [
+ "rfc2217_server.py",
+ ],
+)