<s> """<STR_LIT>""" <EOL> import os <EOL> import select <EOL> import socket <EOL> import sys <EOL> import time <EOL> import traceback <EOL> import serial <EOL> import serial . rfc2217 <EOL> import serial . tools . list_ports <EOL> import dbus <EOL> try : <EOL> import avahi <EOL> except ImportError : <EOL> class avahi : <EOL> DBUS_NAME = "<STR_LIT>" <EOL> DBUS_PATH_SERVER = "<STR_LIT:/>" <EOL> DBUS_INTERFACE_SERVER = "<STR_LIT>" <EOL> DBUS_INTERFACE_ENTRY_GROUP = DBUS_NAME + "<STR_LIT>" <EOL> IF_UNSPEC = - <NUM_LIT:1> <EOL> PROTO_UNSPEC , PROTO_INET , PROTO_INET6 = - <NUM_LIT:1> , <NUM_LIT:0> , <NUM_LIT:1> <EOL> class ZeroconfService : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , name , port , stype = "<STR_LIT>" , <EOL> domain = "<STR_LIT>" , host = "<STR_LIT>" , text = "<STR_LIT>" ) : <EOL> self . name = name <EOL> self . stype = stype <EOL> self . domain = domain <EOL> self . host = host <EOL> self . port = port <EOL> self . text = text <EOL> self . group = None <EOL> def publish ( self ) : <EOL> bus = dbus . SystemBus ( ) <EOL> server = dbus . Interface ( <EOL> bus . get_object ( <EOL> avahi . DBUS_NAME , <EOL> avahi . DBUS_PATH_SERVER <EOL> ) , <EOL> avahi . DBUS_INTERFACE_SERVER <EOL> ) <EOL> g = dbus . Interface ( <EOL> bus . get_object ( <EOL> avahi . DBUS_NAME , <EOL> server . EntryGroupNew ( ) <EOL> ) , <EOL> avahi . DBUS_INTERFACE_ENTRY_GROUP <EOL> ) <EOL> g . AddService ( avahi . IF_UNSPEC , avahi . PROTO_UNSPEC , dbus . UInt32 ( <NUM_LIT:0> ) , <EOL> self . name , self . stype , self . domain , self . host , <EOL> dbus . UInt16 ( self . port ) , self . text ) <EOL> g . Commit ( ) <EOL> self . group = g <EOL> def unpublish ( self ) : <EOL> if self . group is not None : <EOL> self . group . Reset ( ) <EOL> self . group = None <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" % ( self . name , self . host , self . port , self . stype ) <EOL> class Forwarder ( ZeroconfService ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , device , name , network_port , on_close = None , log = None ) : <EOL> ZeroconfService . __init__ ( self , name , network_port , stype = '<STR_LIT>' ) <EOL> self . alive = False <EOL> self . network_port = network_port <EOL> self . on_close = on_close <EOL> self . log = log <EOL> self . device = device <EOL> self . serial = serial . Serial ( ) <EOL> self . serial . port = device <EOL> self . serial . baudrate = <NUM_LIT> <EOL> self . serial . timeout = <NUM_LIT:0> <EOL> self . socket = None <EOL> self . server_socket = None <EOL> self . rfc2217 = None <EOL> def __del__ ( self ) : <EOL> try : <EOL> if self . alive : <EOL> self . close ( ) <EOL> except : <EOL> pass <EOL> def open ( self ) : <EOL> """<STR_LIT>""" <EOL> self . buffer_net2ser = bytearray ( ) <EOL> self . buffer_ser2net = bytearray ( ) <EOL> try : <EOL> self . serial . rts = False <EOL> self . serial . open ( ) <EOL> except Exception as msg : <EOL> self . handle_serial_error ( msg ) <EOL> self . serial_settings_backup = self . serial . get_settings ( ) <EOL> self . server_socket = socket . socket ( socket . AF_INET , socket . SOCK_STREAM ) <EOL> self . server_socket . setsockopt ( <EOL> socket . SOL_SOCKET , <EOL> socket . SO_REUSEADDR , <EOL> self . server_socket . getsockopt ( <EOL> socket . SOL_SOCKET , <EOL> socket . SO_REUSEADDR <EOL> ) | <NUM_LIT:1> <EOL> ) <EOL> self . server_socket . setblocking ( <NUM_LIT:0> ) <EOL> try : <EOL> self . server_socket . bind ( ( '<STR_LIT>' , self . network_port ) ) <EOL> self . server_socket . listen ( <NUM_LIT:1> ) <EOL> except socket . error as msg : <EOL> self . handle_server_error ( ) <EOL> if self . log is not None : <EOL> self . log . info ( "<STR_LIT>" % ( self . device , self . network_port ) ) <EOL> self . publish ( ) <EOL> self . alive = True <EOL> def close ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . log is not None : <EOL> self . log . info ( "<STR_LIT>" % ( self . device , ) ) <EOL> self . alive = False <EOL> self . unpublish ( ) <EOL> if self . server_socket : <EOL> self . server_socket . close ( ) <EOL> if self . socket : <EOL> self . handle_disconnect ( ) <EOL> self . serial . close ( ) <EOL> if self . on_close is not None : <EOL> callback = self . on_close <EOL> self . on_close = None <EOL> callback ( self ) <EOL> def write ( self , data ) : <EOL> """<STR_LIT>""" <EOL> self . buffer_ser2net += data <EOL> def update_select_maps ( self , read_map , write_map , error_map ) : <EOL> """<STR_LIT>""" <EOL> if self . alive : <EOL> read_map [ self . serial ] = self . handle_serial_read <EOL> error_map [ self . serial ] = self . handle_serial_error <EOL> if self . buffer_net2ser : <EOL> write_map [ self . serial ] = self . handle_serial_write <EOL> if self . socket is not None : <EOL> if len ( self . buffer_net2ser ) < <NUM_LIT> : <EOL> read_map [ self . socket ] = self . handle_socket_read <EOL> if self . buffer_ser2net : <EOL> write_map [ self . socket ] = self . handle_socket_write <EOL> error_map [ self . socket ] = self . handle_socket_error <EOL> else : <EOL> self . buffer_ser2net = bytearray ( ) <EOL> read_map [ self . server_socket ] = self . handle_connect <EOL> error_map [ self . server_socket ] = self . handle_server_error <EOL> def handle_serial_read ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> data = os . read ( self . serial . fileno ( ) , <NUM_LIT> ) <EOL> if data : <EOL> if self . socket is not None : <EOL> if self . rfc2217 : <EOL> data = serial . to_bytes ( self . rfc2217 . escape ( data ) ) <EOL> self . buffer_ser2net += data <EOL> else : <EOL> self . handle_serial_error ( ) <EOL> except Exception as msg : <EOL> self . handle_serial_error ( msg ) <EOL> def handle_serial_write ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> n = os . write ( self . serial . fileno ( ) , bytes ( self . buffer_net2ser ) ) <EOL> self . buffer_net2ser = self . buffer_net2ser [ n : ] <EOL> except Exception as msg : <EOL> self . handle_serial_error ( msg ) <EOL> def handle_serial_error ( self , error = None ) : <EOL> """<STR_LIT>""" <EOL> self . close ( ) <EOL> def handle_socket_read ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> data = self . socket . recv ( <NUM_LIT> ) <EOL> if data : <EOL> if self . rfc2217 : <EOL> data = serial . to_bytes ( self . rfc2217 . filter ( data ) ) <EOL> self . buffer_net2ser += data <EOL> else : <EOL> self . handle_disconnect ( ) <EOL> except socket . error : <EOL> self . handle_socket_error ( ) <EOL> def handle_socket_write ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> count = self . socket . send ( bytes ( self . buffer_ser2net ) ) <EOL> self . buffer_ser2net = self . buffer_ser2net [ count : ] <EOL> except socket . error : <EOL> self . handle_socket_error ( ) <EOL> def handle_socket_error ( self ) : <EOL> """<STR_LIT>""" <EOL> self . handle_disconnect ( ) <EOL> def handle_connect ( self ) : <EOL> """<STR_LIT>""" <EOL> connection , addr = self . server_socket . accept ( ) <EOL> if self . socket is None : <EOL> self . socket = connection <EOL> self . socket . setsockopt ( socket . SOL_SOCKET , socket . SO_KEEPALIVE , <NUM_LIT:1> ) <EOL> self . socket . setsockopt ( socket . IPPROTO_TCP , socket . TCP_KEEPIDLE , <NUM_LIT:1> ) <EOL> self . socket . setsockopt ( socket . IPPROTO_TCP , socket . TCP_KEEPINTVL , <NUM_LIT:1> ) <EOL> self . socket . setsockopt ( socket . IPPROTO_TCP , socket . TCP_KEEPCNT , <NUM_LIT:3> ) <EOL> self . socket . setblocking ( <NUM_LIT:0> ) <EOL> self . socket . setsockopt ( socket . IPPROTO_TCP , socket . TCP_NODELAY , <NUM_LIT:1> ) <EOL> if self . log is not None : <EOL> self . log . warning ( '<STR_LIT>' % ( self . device , addr [ <NUM_LIT:0> ] , addr [ <NUM_LIT:1> ] ) ) <EOL> self . serial . rts = True <EOL> self . serial . dtr = True <EOL> if self . log is not None : <EOL> self . rfc2217 = serial . rfc2217 . PortManager ( self . serial , self , logger = log . getChild ( self . device ) ) <EOL> else : <EOL> self . rfc2217 = serial . rfc2217 . PortManager ( self . serial , self ) <EOL> else : <EOL> connection . close ( ) <EOL> if self . log is not None : <EOL> self . log . warning ( '<STR_LIT>' % ( self . device , addr [ <NUM_LIT:0> ] , addr [ <NUM_LIT:1> ] ) ) <EOL> def handle_server_error ( self ) : <EOL> """<STR_LIT>""" <EOL> self . close ( ) <EOL> def handle_disconnect ( self ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> self . serial . rts = False <EOL> self . serial . dtr = False <EOL> finally : <EOL> self . serial . apply_settings ( self . serial_settings_backup ) <EOL> self . rfc2217 = None <EOL> self . buffer_ser2net = bytearray ( ) <EOL> if self . socket is not None : <EOL> self . socket . close ( ) <EOL> self . socket = None <EOL> if self . log is not None : <EOL> self . log . warning ( '<STR_LIT>' % self . device ) <EOL> def test ( ) : <EOL> service = ZeroconfService ( name = "<STR_LIT>" , port = <NUM_LIT> ) <EOL> service . publish ( ) <EOL> input ( "<STR_LIT>" ) <EOL> service . unpublish ( ) <EOL> if __name__ == '<STR_LIT:__main__>' : <EOL> import logging <EOL> import argparse <EOL> VERBOSTIY = [ <EOL> logging . ERROR , <EOL> logging . WARNING , <EOL> logging . INFO , <EOL> logging . DEBUG , <EOL> ] <EOL> parser = argparse . ArgumentParser ( <EOL> usage = """<STR_LIT>""" , <EOL> epilog = """<STR_LIT>""" ) <EOL> group = parser . add_argument_group ( "<STR_LIT>" ) <EOL> group . add_argument ( <EOL> "<STR_LIT>" , <EOL> help = "<STR_LIT>" , <EOL> default = '<STR_LIT>' , <EOL> metavar = "<STR_LIT>" ) <EOL> group = parser . add_argument_group ( "<STR_LIT>" ) <EOL> group . add_argument ( <EOL> "<STR_LIT>" , <EOL> dest = "<STR_LIT>" , <EOL> help = "<STR_LIT>" , <EOL> default = <NUM_LIT> , <EOL> type = int , <EOL> metavar = "<STR_LIT>" ) <EOL> group = parser . add_argument_group ( "<STR_LIT>" ) <EOL> group . add_argument ( <EOL> "<STR_LIT>" , "<STR_LIT>" , <EOL> dest = "<STR_LIT>" , <EOL> action = "<STR_LIT:store_true>" , <EOL> help = "<STR_LIT>" , <EOL> default = False ) <EOL> group . add_argument ( <EOL> "<STR_LIT>" , <EOL> help = "<STR_LIT>" , <EOL> default = None , <EOL> metavar = "<STR_LIT>" ) <EOL> group = parser . add_argument_group ( "<STR_LIT>" ) <EOL> group . add_argument ( <EOL> "<STR_LIT>" , "<STR_LIT>" , <EOL> help = "<STR_LIT>" , <EOL> default = None , <EOL> metavar = "<STR_LIT>" ) <EOL> group . add_argument ( <EOL> "<STR_LIT>" , "<STR_LIT>" , <EOL> dest = "<STR_LIT>" , <EOL> action = "<STR_LIT>" , <EOL> const = <NUM_LIT:0> , <EOL> help = "<STR_LIT>" , <EOL> default = <NUM_LIT:1> ) <EOL> group . add_argument ( <EOL> "<STR_LIT>" , "<STR_LIT>" , <EOL> dest = "<STR_LIT>" , <EOL> action = "<STR_LIT:count>" , <EOL> help = "<STR_LIT>" ) <EOL> args = parser . parse_args ( ) <EOL> logging . basicConfig ( level = VERBOSTIY [ min ( args . verbosity , len ( VERBOSTIY ) - <NUM_LIT:1> ) ] ) <EOL> log = logging . getLogger ( '<STR_LIT>' ) <EOL> if args . logfile is not None : <EOL> class WriteFlushed : <EOL> def __init__ ( self , fileobj ) : <EOL> self . fileobj = fileobj <EOL> def write ( self , s ) : <EOL> self . fileobj . write ( s ) <EOL> self . fileobj . flush ( ) <EOL> def close ( self ) : <EOL> self . fileobj . close ( ) <EOL> sys . stdout = sys . stderr = WriteFlushed ( open ( args . logfile , '<STR_LIT:a>' ) ) <EOL> if args . daemonize : <EOL> try : <EOL> pid = os . fork ( ) <EOL> if pid > <NUM_LIT:0> : <EOL> sys . exit ( <NUM_LIT:0> ) <EOL> except OSError as e : <EOL> log . critical ( "<STR_LIT>" % ( e . errno , e . strerror ) ) <EOL> sys . exit ( <NUM_LIT:1> ) <EOL> os . chdir ( "<STR_LIT:/>" ) <EOL> os . setsid ( ) <EOL> os . umask ( <NUM_LIT:0> ) <EOL> try : <EOL> pid = os . fork ( ) <EOL> if pid > <NUM_LIT:0> : <EOL> if args . pidfile is not None : <EOL> open ( args . pidfile , '<STR_LIT:w>' ) . write ( "<STR_LIT>" % pid ) <EOL> sys . exit ( <NUM_LIT:0> ) <EOL> except OSError as e : <EOL> log . critical ( "<STR_LIT>" % ( e . errno , e . strerror ) ) <EOL> sys . exit ( <NUM_LIT:1> ) <EOL> if args . logfile is None : <EOL> import syslog <EOL> syslog . openlog ( "<STR_LIT>" ) <EOL> class WriteToSysLog : <EOL> def __init__ ( self ) : <EOL> self . buffer = '<STR_LIT>' <EOL> def write ( self , s ) : <EOL> self . buffer += s <EOL> if '<STR_LIT:\n>' in self . buffer : <EOL> output , self . buffer = self . buffer . split ( '<STR_LIT:\n>' , <NUM_LIT:1> ) <EOL> syslog . syslog ( output ) <EOL> def flush ( self ) : <EOL> syslog . syslog ( self . buffer ) <EOL> self . buffer = '<STR_LIT>' <EOL> def close ( self ) : <EOL> self . flush ( ) <EOL> sys . stdout = sys . stderr = WriteToSysLog ( ) <EOL> published = { } <EOL> hostname = socket . gethostname ( ) <EOL> def unpublish ( forwarder ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> del published [ forwarder . device ] <EOL> except KeyError : <EOL> pass <EOL> else : <EOL> log . info ( "<STR_LIT>" % ( forwarder ) ) <EOL> alive = True <EOL> next_check = <NUM_LIT:0> <EOL> while alive : <EOL> try : <EOL> now = time . time ( ) <EOL> if now > next_check : <EOL> next_check = now + <NUM_LIT:5> <EOL> connected = [ d for d , p , i in serial . tools . list_ports . grep ( args . ports_regex ) ] <EOL> for device in set ( published ) . difference ( connected ) : <EOL> log . info ( "<STR_LIT>" % ( published [ device ] ) ) <EOL> unpublish ( published [ device ] ) <EOL> for device in sorted ( set ( connected ) . difference ( published ) ) : <EOL> port = args . base_port <EOL> ports_in_use = [ f . network_port for f in published . values ( ) ] <EOL> while port in ports_in_use : <EOL> port += <NUM_LIT:1> <EOL> published [ device ] = Forwarder ( <EOL> device , <EOL> "<STR_LIT>" % ( device , hostname ) , <EOL> port , <EOL> on_close = unpublish , <EOL> log = log ) <EOL> log . warning ( "<STR_LIT>" % ( published [ device ] ) ) <EOL> published [ device ] . open ( ) <EOL> read_map = { } <EOL> write_map = { } <EOL> error_map = { } <EOL> for publisher in published . values ( ) : <EOL> publisher . update_select_maps ( read_map , write_map , error_map ) <EOL> readers , writers , errors = select . select ( <EOL> read_map . keys ( ) , <EOL> write_map . keys ( ) , <EOL> error_map . keys ( ) , <EOL> <NUM_LIT:5> ) <EOL> for reader in readers : <EOL> read_map [ reader ] ( ) <EOL> for writer in writers : <EOL> write_map [ writer ] ( ) <EOL> for error in errors : <EOL> error_map [ error ] ( ) <EOL> except KeyboardInterrupt : <EOL> alive = False <EOL> sys . stdout . write ( '<STR_LIT:\n>' ) <EOL> except SystemExit : <EOL> raise <EOL> except : <EOL> traceback . print_exc ( ) </s>
