个人技术分享

代码

#!python.exe
"""
@filename       send_bin.py
@brief          According to the user's input, read bin file, subpackage and send the file by UART.
@HowToUse       send_bin.py -h
@author         shadowThreeD@gmail.com
@data           20220224
"""
from asyncio.windows_events import NULL
from importlib.metadata import files
from socket import timeout
import sys
import os
from time import sleep
import serial
import crcmod

global fileName;
global fileSize;
global pkgSize;
global needAck;
global pkgInterval;

def main(argv):
    global fileName;        # 将需要使用的 global 变量引入,不然默认使用局部变量,即使变量名相同
    global fileSize;
    global pkgSize;
    global needAck;
    global pkgInterval;

    checkParams(argv);

    crc32_func = crcmod.mkCrcFun(0x18005, rev=True, initCrc=0, xorOut=0x0000)

    try:
        pFile = open(fileName, "rb");
        #tempFile = open("temp.bin", "wb");
    except:
        print('bin file read error...');

    port = 'COM3';
    baudRate = 115200;
    try:
        com = serial.Serial(port, baudRate, timeout=2);     # 设置超时时间为 5s
    except:
        print(port + ' open failed...');
        sys.exit();
    else:
        print(port + ' open succ, baudrate is ' + str(baudRate));

    # 发送字符串
    #subFile = "ABCD\r\n".encode();      # 将 str 编码成 Bytes
    #com.write(subFile);
    #print(com.read_until(b'\r\n').decode());    # 将 Bytes 解码成 str

    # 发送二进制
    indexFile = 0;
    isEnd = 0;
    curPkgSize = pkgSize-4;
    MAC_addr = bytes([0x5a, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);      # start and MAC
    
    while isEnd == 0 :
        if indexFile != 0:
            subFile = pFile.read(pkgSize-4);
            curPkgSize = len(subFile);
            if curPkgSize != pkgSize-4 :
                isEnd = 1;
            print('curPkgSize: ' + str(curPkgSize));
        curSend = MAC_addr;         # start + MAC
        if indexFile == 0:
            CRC_part = int(14).to_bytes(4, 'little');       # RS485 Length
        else:
            CRC_part = (curPkgSize+10).to_bytes(4, 'little');       #
        CRC_part += int(5).to_bytes(1, 'little');               # Msg type:
        CRC_part += int(4).to_bytes(1, 'little');               # Sensor type: NTC
        CRC_part += indexFile.to_bytes(2, 'little');            # pkg ID
        if indexFile == 0:
            CRC_part += (4<<2 | needAck<<1 | isEnd).to_bytes(2, 'little');      # 4 is sizeof(uint32_t) for fileSize length
            CRC_part += fileSize.to_bytes(4, 'little');
        else:
            CRC_part += (curPkgSize<<2 | needAck<<1 | isEnd).to_bytes(2, 'little');
            CRC_part += subFile;
        curSend += CRC_part;     
        curSend += crc32_func(CRC_part).to_bytes(2, 'big');
        print(curSend.hex());
        com.write(curSend);
        curRecv = com.read_until(b'\r\n');
        #if curRecv is not NULL:
        if len(curRecv) == 20 and curRecv[17] == 0:
            print(curRecv.decode());
            indexFile += 1;
        else:
            print(len(curRecv));
            
        #tempFile.write(curSend);

    pFile.close();
    #tempFile.close();

    return;

def checkParams(argv):
    global fileName;
    global fileSize;
    global pkgSize;
    global needAck;
    global pkgInterval;

    try:
        fileName = argv[1];
        if fileName == '-h':
            showHelp();
            raise SystemExit;         # 导致程序触发 SystemExit 异常。这里也可以用 sys.exit();
        pkgSize = int(argv[2]);
        if argv[3] != '1':
            needAck = 0;
            pkgInterval = int(argv[4]);
        else:
            needAck = 1;
    except SystemExit:
        sys.exit();
    except:
        print('Params error...');
        showHelp();
        sys.exit();
    else:
        fileSize = os.path.getsize(fileName);
        print('fileName:    ' + fileName);
        print('fileSize:    ' + str(fileSize));
        print('pkgSize:     ' + str(pkgSize));
        print('needAck:     ' + str(needAck));
        if needAck == 'false':
            print('pkgInterval: ' + str(pkgInterval));
    return;

def showHelp():
    print("""Usage:
        1. send_bin.py test.bin 1500 1
        2. send_bin.py test.bin 1500 0 1000
            - test.bin:     the file name of bin file.
            - 1500:         is the package size, unit in Bytes.
            - 0:            whether need ack after send eack package; 1 meaning need, 0 meaning NO need.
            - 1000:         if last param is true, this is ignored; otherwise meaning the interval of two package, unit in ms.""");
    return;

if __name__ == "__main__":
    main(sys.argv);