python-3.x PySerial的解码不是恒定的

slwdgvem  于 2023-03-24  发布在  Python
关注(0)|答案(1)|浏览(85)

我正在尝试自动化串行连接的登录。现在我正在使用PySerial进行婴儿步骤,解码的输出并不恒定。网络是这样的:

PC (Windows 10) -> Switch -> Router -> Switch -> Raspberry Pi 4 -> Router

我通过SSH连接到Raspberry Pi 4,然后从那里用USB到RS-232适配器连接到路由器(Lancom-1926 VAG-5G)。
串行连接的工作原理我已经尝试了PuTTY,屏幕和Minicom.波特率是模糊的,但可以从9600到115200之间.现在这是我的串行连接的测试代码:

#!/usr/bin/env python3
import serial
import time

ser = serial.Serial(port='/dev/ttyUSB0', baudrate=57600, parity="N", stopbits=1, bytesize=8, timeout=3, rtscts=True)

ser.reset_input_buffer()
ser.reset_output_buffer()

print(ser.isOpen())

i = 0
while i<=15:
    time.sleep(0.1)
    ser.write(''.encode('utf-8') + b'\n')
    i = i+1

print(ser.inWaiting())

input_data = ser.read(1024).decode('utf-8', errors='replace').strip()
print(input_data)

与PuTTY的正常连接如下所示:

b▒▒▒ĥ▒▒$▒▒d▒
Outband-115200 Bit/s OK

#
| LANCOM 1926VAG-5G
| Ver. 10.72.0092SU2 / 15.02.2023
| SN.  
| Copyright (c) LANCOM Systems

Connection No.: 001 (Outband-115200 Bps)

Password:
Login Error


Goodbye

但是当我尝试代码时,它看起来像这样:

True
391
G�ɰhj��hL@Е��
Outband-57600 Bit/s OKr~Iy�b܁�nĒb���
� b�߿�<�lb����
�����p���������������p�
����

�CBRTb���Ą��$��d�G�ɰ)j��hL@Е��
Outband-57600 Bit/s OK~�y�b܁�nĒb���
� b�߿�<�$b���������p���������������p�
����
�CBRT���Ą��$��d�G�ɰ(j��hL@Е��
Outband-57600 Bit/s OKr~Yy�b܁�nĒb�
��
� b�O���lb�
�����
���p������������`��p�����

同样,但这次使用与PuTTY输出相同的波特率:

True
668
Outband-115200 Bit/s OKr~�y�b܁�nĒb��
�
� b�߿�<�lb怘���f?`?<<��`<�f~x��3���?�������������p��������������p������������������������������������������b���ĥ��$��d�
Outband-115200 Bit/s OKr~�y�b܁�nĒb��
�
� b�߿�<�lb怘���f?`?<<��`<�f~x��3���?�������������p��������������p������������������������������������������b���ĥ��$��d�
Outband-115200 Bit/s OKr~�y�b܁�nĒb��
�
� b�߿�<�lb怘���f?`?<<��`<�f~x��3���?�������������p��������������p������������������������������������������

为什么消息“Outband-57600 Bit/s OK”被解码,但之后什么都没有?(编辑:路由器不断与代码协商波特率)编辑:我注意到,当我尝试这个代码的思科交换机时,他仍然是启动我可以读到这:(9600波特率)

True
225
System Bootstrap, Version 15.0(1r)M12, RELEASE SOFTWARE (fc1)
Technical Support: http://www.cisco.com/techsupport
Copyright (c) 2011 by cisco Systems, Inc.

Total memory size = 512 MB - On-board = 512 MB, DIMM0 = 0 MB
CISCO2901/K9 platform with 524288 Kbytes of main memory
Main memory is configured to 72/-1(On-board/DIMM0) bit mode with ECC enabled

Readonly ROMMON initialized
program load complete, entry point: 0x80803000, size: 0x1b340
program load complete, entry point: 0x80803000, size: 0x1b340

但是MOTD无法读取登录提示符,在他完成 Boot 后。我尝试了同样的事情,就像Cisco交换机一样,使用Lancom路由器:

True
269
bC���������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������������

(我离开了一些行,因为它只是同样的胡言乱语。)从Lancom路由器的输出是ZLoader引导固件。通常它看起来像这样:

OK: Action Boot-System started

System is going down ...
@W@
Found primary and mirror bbt

#B#
Start firmware #2

ZLoader running.....................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................................
Outband-115200 Bit/s OK

编辑:在追踪路由器的outband后,我注意到了一些东西。我一直得到的胡言乱语是与路由器的波特率协商。

vh0rcniy

vh0rcniy1#

在我将LANtrace应用于带外连接后。我发现PySerial不传输8位,停止位1,因此协商总是失败,因为路由器总是只期望一个字节。在使用PuTTY跟踪连接后,我看到了两者之间的连接。在我更改代码以发送仅1个字母,延迟0.1秒后,协商成功。

#!/usr/bin/env python3
import serial
import time
import datetime

def connect_to_router(log_file):
    print("Connecting to router...")
    synchro = False
    # Open serial connection
    ser = serial.Serial(port='/dev/ttyUSB0', baudrate=57600, bytesize=8, parity="N", stopbits=1, timeout=3, rtscts=True)
    
    
    # Wait for login prompt
    while True:
        output = ser.readline().decode('utf-8', errors='replace').strip()
        
        if output != '':
            print(output)
            log_file.write(f"[{datetime.datetime.now()}] {output}\n")
        if 'Bit/s' in output:
            print("Synchronisation is Ok...")
            synchro = True
        elif not 'Bit/s' in output and synchro==False:
            print("Typing Return...")
            time.sleep(0.1)
            ser.write(b'\r')
        if 'Username:' in output:
            print("Typing Username...")
            time.sleep(0.1)
            ser.write('u'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('s'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('e'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('r'.encode('utf-8'))
            time.sleep(0.1)
            ser.write(b'\r')
        if 'Password:' in output:
            print("Typing Passwort...")
            time.sleep(0.1)
            ser.write('T'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('e'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('s'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('t'.encode('utf-8'))
            time.sleep(0.1)
            ser.write(b'\r')
        if 'Goodbye' in output:
            print("Logged out...")
            time.sleep(0.1)
            ser.write(b'\r')
            synchro = False
        if 'root@' in output:
            print("Typing Command...")
            time.sleep(0.1)
            ser.write('s'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('h'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('o'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('w'.encode('utf-8'))
            time.sleep(0.1)
            ser.write(' '.encode('utf-8'))
            time.sleep(0.1)
            ser.write('m'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('e'.encode('utf-8'))
            time.sleep(0.1)
            ser.write('m'.encode('utf-8'))
            time.sleep(0.1)
            ser.write(b'\r')
            
            break
        print("loop")
    return ser

def main():
    while True:
        try:
            # Open log file with timestamp in filename
            timestamp = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
            log_file = open(f"/home/wlanpi/log_{timestamp}.txt", "w")

            ser = connect_to_router(log_file)
            print("Logged in by this point...")
            # Read and log all remaining output from router
            while True:
                output = ser.readline().decode('utf-8', errors='replace').strip()
                if output != '':
                    print(output)
                    log_file.write(f"[{datetime.datetime.now()}] {output}\n")

                # Check if still logged in
                if 'Bit/s' in output:
                    print("Logged out, attempting to log back in...")
                    ser = connect_to_router(log_file)

        except (KeyboardInterrupt, serial.SerialException) as e:
            # User pressed CTRL-C or serial connection error occurred
            print(f"Exception: User pressed CTRL-C or serial connection error occurred{e}")
            ser = None  
            break

        finally:
            # Close serial connection and log file
            if ser is not None:
                ser.close()
            log_file.close()

if __name__ == '__main__':
    main()

这不是最好的答案,但至少现在有效。

相关问题