【问题标题】:How can I solve this data logging issue?如何解决此数据记录问题?
【发布时间】:2021-11-22 02:52:24
【问题描述】:

我正在通过串行通信收集数据,下面是我的代码。我的计划是每次收到数据时,数据都应该以不同的名称记录在不同的文件中(文件名无关紧要,我希望它是不同的文件,所以我使用了时间和数据模块)。 但我面临的问题是,一旦在 UART 端口上接收到数据,文件就开始收集数据(我监控文件大小),一两秒后,文件大小回到零字节。我尝试了不同的方法来解决它,但我认为我在这里犯了一些我找不到的愚蠢错误。

import serial
import time 
import datetime
import os

ser = serial.Serial(port='/dev/serial0', baudrate=115200, parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS, rtscts=1,)

outputFilePath = os.path.join(os.path.dirname(__file__),
                 datetime.datetime.now().strftime("%Y-%m-%dT%H.%M.%S") + ".txt")

while (True):
    if (ser.inWaiting() > 0):
        text_file = open(outputFilePath, 'w')
        # read the bytes and convert from binary array to ASCII
        data_str = ser.read(ser.inWaiting()).decode('ascii') 
        # print the incoming string without putting a new-line
        # ('\n') automatically after every print()
        #print(data_str, end='')
        text_file.write(data_str)
        text_file.flush()
 
    text_file.close()
    time.sleep(0.01) 

基本上,我有大约 900 kB 的数据,这些数据由微控制器生成并通过 UART 传输到 Raspberry Pi。数据将每天多次发送到 RP(例如 50 次),每次发送这 900kB 数据时,我想将其保存在不同的文件中(所以 50 个文件,每个文件具有不同的名称和 900 kB数据的)。 另一件事是我没有偏好使用数据/时间保存文件名。如果我可以用 1.txt、2.txt 等保存……那也很好。我无法访问 RP,因此我需要在自动脚本中使用它。

【问题讨论】:

    标签: raspberry-pi serial-port pyserial


    【解决方案1】:

    ...文件大小回到零字节

    可能是因为程序一遍又一遍地重新打开/创建相同的文件,而不是打开“具有不同名称的不同文件”
    IOW outputFilePath 有一个常量值,因为它的赋值在循环之外,因此只发生一次。


    text_file.close() 需要成为 if 块的一部分,因为 text_file = open() 只是有条件地执行。


    附录

    数据将每天多次发送到 RP(例如 50 次),每次发送这 900kB 数据时,我想将其保存在不同的文件中

    您的简单且错误的代码显然假定 “这 900kB 数据已发送” 作为某种逻辑记录或块。正如“每次接收数据”(作为单个记录或块),那么每个记录/块“应该记录在不同的文件中”。当然 “不同的文件” 需要 “不同的名称”(假设文件将在同一目录中)。

    您对您想要完成的任务的概述没有正确地转化为计算机编程所需的细节和时间尺度。

    “约 900 kB 的数据” 对于串行通信链路来说,数据量并不小。
    以 115200 波特和 8N1 传输这么多数据的最短传输时间至少为 80 秒。您的程序将无法在一次系统调用中读取 80 秒的数据。
    操作系统(例如 Linux)有一个用于串行数据的内部缓冲区,通常大小为 4096 字节。您的一大块数据将消耗 225 个缓冲区。您的程序将无法在一个系统调用中读取 225 个系统缓冲区的数据。
    相反,根据睡眠延迟和打开开销,您发布的代码每次读取可能会获取大约 100-200 字节,并且可以为每个数据块执行 5000 次 while 循环迭代。

    IMO 你的计划似乎有缺陷。虽然可以可靠地处理时间分隔的数据块,但这样的协议将需要比您目前所展示的更多的努力和对概念的掌握。如果不是因为忽略提及这些细节,数据块之间缺乏保证的时间间隔可能会出现问题。
    在没有任何明显完整性检查的情况下传输二进制数据可能会出现问题。在存储之前将此二进制数据(立即)转换为 ASCII 文本是很奇怪的,如果不只是浪费时间和空间的话。

    鉴于(明显)缺乏流量控制,接收缓冲区溢出的风险很高。


    作为基本的第一步并协助进行概念验证,您最好编写一个程序来简单地捕获所有数据并将其存储在一个文件中。

    【讨论】:

    • 感谢@sawdust 指出这一点。但是,如果我在 while 循环内(在 if 循环上方)或在 if 循环内(就在 if 语句之后)添加 outputFilePath = os.path.join......,则会生成多个文件。我也对是否应该使用写入模式或附加模式有疑问。所以,我尝试了附加模式,但仍然是同样的问题。有办法吗?
    • 对我来说,“每次收到数据时,数据都应该以不同的名称记录在一个不同的文件中” 确实意味着“正在生成多个文件”。您抱怨您的(冗余)目标不正确!你在描述你的意图方面做得很差。 "... 还是同样的问题。" -- 你指的是哪个症状?顺便说一句,您发布的代码只有一 (1) 个循环,即 while 循环。 if 语句不是循环。
    • 很抱歉给您带来了困惑。我已经编辑了我的问题,以便用更简单的术语来解释问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多