3 M]W$ @s$dZddlZddlZGdddeZGdddeZGdddeZGd d d eZGd d d ejZ e d kr ddl Z ddl Z ddl Z dZGdddeZejedddZe eeZejde jdWdQRXejedddZe eeZejej\ZZejde jdejdS)z%Support threading with serial ports. Nc@s(eZdZdZddZddZddZdS) Protocolzq Protocol as used by the ReaderThread. This base class provides empty implementations of all methods. cCsdS)z$Called when reader thread is startedN)self transportrr/usr/lib/python3.6/__init__.pyconnection_madeszProtocol.connection_madecCsdS)z2Called with snippets received from the serial portNr)rdatarrr data_receivedszProtocol.data_receivedcCst|tr|dS)zg Called when the serial port is closed or the reader loop terminated otherwise. N) isinstance Exception)rexcrrrconnection_losts zProtocol.connection_lostN)__name__ __module__ __qualname____doc__rr r rrrrrsrcsDeZdZdZdZddZddZfddZd d Zd d Z Z S) Packetizerz Read binary packets from serial port. Packets are expected to be terminated with a TERMINATOR byte (null byte by default). The class also keeps track of the transport. cCst|_d|_dS)N) bytearraybufferr)rrrr__init__/szPacketizer.__init__cCs ||_dS)zStore transportN)r)rrrrrr3szPacketizer.connection_madecsd|_tt|j|dS)zForget transportN)rsuperrr )rr ) __class__rrr 7szPacketizer.connection_lostcCsB|jj|x0|j|jkr<|jj|jd\}|_|j|qWdS)z9Buffer received data, find TERMINATOR, call handle_packetN)rextend TERMINATORsplit handle_packet)rrpacketrrrr <s zPacketizer.data_receivedcCs tddS)z1Process packets - to be overridden by subclassingz/please implement functionality in handle_packetN)NotImplementedError)rrrrrrCszPacketizer.handle_packet) rrrrrrrr r r __classcell__rr)rrr%s rcsPeZdZdZdZdZddZddZfdd Zd d Z d d Z ddZ Z S) FramedPacketz Read binary packets. Packets are expected to have a start and stop marker. The class also keeps track of the transport. ()cCst|_d|_d|_dS)NF)rr in_packetr)rrrrrRszFramedPacket.__init__cCs ||_dS)zStore transportN)r)rrrrrrWszFramedPacket.connection_madecs,d|_d|_|jdd=tt|j|dS)zForget transportNF)rr$rrr!r )rr )rrrr [s zFramedPacket.connection_lostcCsrxltj|D]^}||jkr"d|_q ||jkrLd|_|j|j|jdd=q |jr`|jj|q |j|q WdS)z4Find data enclosed in START/STOP, call handle_packetTFN) serialZ iterbytesSTARTr$STOPrrappendhandle_out_of_packet_data)rrZbyterrrr bs   zFramedPacket.data_receivedcCs tddS)z1Process packets - to be overridden by subclassingz/please implement functionality in handle_packetN)r)rrrrrrpszFramedPacket.handle_packetcCsdS)z0Process data that is received outside of packetsNr)rrrrrr)tsz&FramedPacket.handle_out_of_packet_data) rrrrr&r'rrr r rr)r rr)rrr!Hs r!c@s4eZdZdZdZdZdZddZddZd d Z d S) LineReaderzZ Read and write (Unicode) lines from/to serial port. The encoding is applied. s zutf-8replacecCs|j|j|j|jdS)N) handle_linedecodeENCODINGUNICODE_HANDLING)rrrrrrszLineReader.handle_packetcCs tddS)z2Process one line - to be overridden by subclassingz-please implement functionality in handle_lineN)r)rlinerrrr,szLineReader.handle_linecCs"|jj|j|j|j|jdS)z Write text to the transport. ``text`` is a Unicode string and the encoding is applied before sending ans also the newline is append. N)rwriteencoder.r/r)rtextrrr write_lineszLineReader.write_lineN) rrrrrr.r/rr,r4rrrrr*ysr*csXeZdZdZfddZddZddZdd Zd d Zd d Z ddZ ddZ Z S) ReaderThreada Implement a serial port read loop and dispatch to a Protocol instance (like the asyncio.Protocol) but do it with threads. Calls to close() will close the serial port but it is also possible to just stop() this thread and continue the serial port instance otherwise. csDtt|jd|_||_||_d|_tj|_ tj |_ d|_ dS)z Initialize thread. Note that the serial_instance' timeout is set to one second! Other settings are not changed. TN) rr5rZdaemonr%protocol_factoryalive threadingZLock_lockZEvent_connection_madeprotocol)rZserial_instancer6)rrrrs  zReaderThread.__init__cCs*d|_t|jdr|jj|jddS)zStop the reader threadF cancel_readN)r7hasattrr%r<join)rrrrstops  zReaderThread.stopc&Cs0t|jdsd|j_|j|_y|jj|Wn<tk rj}z d|_|jj||j j dSd}~XnXd}|j j x|jo|jj ry|jj |jj pd}Wn*tjk r}z |}PWYdd}~Xq|X|r|y|jj|Wq|tk r}z |}PWYdd}~Xq|Xq|Wd|_|jj|d|_dS)z Reader loopr<rFN)r>r%timeoutr6r;rr r7r r:setZis_openreadZ in_waitingZSerialExceptionr )reerrorrrrrruns6      zReaderThread.runc Cs"|j|jj|WdQRXdS)zThread safe writing (uses lock)N)r9r%r1)rrrrrr1szReaderThread.writec Cs(|j|j|jjWdQRXdS)z8Close the serial port and exit reader thread (uses lock)N)r9r@r%close)rrrrrGszReaderThread.closecCs4|jr(|jj|jstd||jfStddS)zj Wait until connection is set up and return the transport and protocol instances. zconnection_lost already calledzalready stoppedN)r7r:wait RuntimeErrorr;)rrrrconnects   zReaderThread.connectcCs&|j|jj|js td|jS)zs Enter context handler. May raise RuntimeError in case the connection could not be created. zconnection_lost already called)startr:rHr7rIr;)rrrr __enter__s  zReaderThread.__enter__cCs |jdS)zLeave context: close portN)rG)rexc_typeZexc_valZexc_tbrrr__exit__szReaderThread.__exit__) rrrrrr@rFr1rGrJrLrNr rr)rrr5s # r5__main__zloop://cs,eZdZfddZddZddZZS) PrintLinescs*tt|j|tjjd|jddS)Nz port opened z hello world)rrPrsysstdoutr1r4)rr)rrrrs zPrintLines.connection_madecCstjjdjt|dS)Nzline received: {} )rQrRr1formatrepr)rrrrrr,szPrintLines.handle_linecCs|rtj|tjjddS)Nz port closed ) traceback print_excrQrRr1)rr rrrr s zPrintLines.connection_lost)rrrrr,r r rr)rrrP s rPir)ZbaudraterAZhellor=)rr%r8objectrrr!r*ZThreadr5rrQZtimerUZPORTrPZserial_for_urlZserr;r4ZsleeptrKrJrrGrrrr s0#1q