为了账号安全,请及时绑定邮箱和手机立即绑定

如何将字节加在一起并根据 python 中的校验和验证它们

如何将字节加在一起并根据 python 中的校验和验证它们

翻阅古今 2022-11-29 15:57:55
您如何计算传入字节的校验和以查看它是否是有效数据包?目前我正在读取字节并对它们进行解码并接收信息,但在我这样做之前我希望能够根据校验和验证它以确保我没有收到任何无效/损坏的数据包。这是我目前拥有的def batteryConnect(port, baudrate):    # establishing a serial connection    ser = serial.Serial(port=port, baudrate= baudrate, bytesize=serial.EIGHTBITS, parity=serial.PARITY_NONE,timeout=3)    return serclass VictronBmv700:    def __init__(self,port,baudrate):        self.port = port        self.baudrate = baudrate        self.parameterDict = dict.fromkeys(["PID","V","I","P","CE","SOC","TTG","Alarm","Relay","AR","BMV","FW","H1","H2","H3",                                  "H4","H5","H6","H7","H8","H9","H10","H11","H12","H17","H18"])    def getBMVInfo(self):        bmvdata = batteryConnect(self.port,self.baudrate)        #getting the data        bmvdata.flushInput()        #getting the message then splitting the key, value pairs        while True:            print(bmvdata.readline())            message = bmvdata.readline().decode(encoding='utf-8',errors='ignore')            #splitting on tabs            message_parts = message.split('\t')            if len(message_parts) > 1:                key = message_parts[0]                value = message_parts[1].rstrip()  #stripping \r\n after the value                #updating deictionary based on keys and their values.                self.parameterDict[key] = valueif __name__ == "__main__":    print("BATTERY MONITOR")    bmv700 = VictronBmv700("COM17", 19200)    bmv700.getBMVInfo()
查看完整描述

2 回答

?
千万里不及你

TA贡献1784条经验 获得超9个赞

发帖者似乎正在尝试从 BMV700 电池监视器读取数据。阅读此处的论文,我们看到它使用文本协议通过串行接口进行通信:


2 文本协议

当没有 VE.Direct 查询发送到设备时,充电器会定期将人类可读 (TEXT) 数据发送到串行端口。有关内容和信息可用性的详细说明,请参阅“VE.Direct Protocol”文档


摘自 HEX 协议 (BMV-7xx-HEX-Protocol-public.pdf)


查看 TEXT 协议的规范 (VE.Direct-Protocol-3.28.pdf),我们发现:


消息格式

该设备以 1 秒的间隔传输数据块。每个字段都使用以下格式发送:


<Newline><Field-Label><Tab><Field-Value>

标识符定义如下:


+---------------+--------------------------------------------------------------------------------------+

| Identifier    | Meaning                                                                              |

+===============+======================================================================================+

| <Newline>     | A carriage return followed by a line feed (0x0D, 0x0A).                              |

+---------------+--------------------------------------------------------------------------------------+

| <Field-Label> | An arbitrary length label that identifies the field.                                 |

|               | Where applicable, this will be the same as the label that is used on the LCD.        |

+---------------+--------------------------------------------------------------------------------------+

| <Tab>         | A horizontal tab (0x09).                                                             |

+---------------+--------------------------------------------------------------------------------------+

| <Field-Value> | The ASCII formatted value of this field.                                             |

|               | The number of characters transmitted depends on the magnitude and sign of the value. |

+---------------+--------------------------------------------------------------------------------------+

这对应于您正在打印的数据,但有一个例外:该行以 开头,\r\b但不以它们结尾。


然后,该文件提供了有关校验和的详细信息:


数据的完整性

统计数据分组为块,并附加了校验和。块中的最后一个字段将始终是“校验和”。该值是一个字节,不一定是可打印的 ASCII 字符。如果没有传输错误,块中所有字节的模 256 和将等于 0。发送包含不同字段的多个块。


因此,在您作为输出发布的摘录中,您有两个完整的块和一个不完整的块,因为最后一个块缺少Checksum.


block = (b'\r\nH2\t0\r\n'

    b'H4\t0\r\n'

    b'H6\t-9001\r\n'

    b'H8\t28403\r\n'

    b'H10\t0\r\n'

    b'H12\t0\r\n'

    b'H18\t87\r\n'

    b'PID\t0x203\r\n'

    b'I\t0\r\n'

    b'CE\t0\r\n'

    b'TTG\t-1\r\n'

    b'Relay\tOFF\r\n'

    b'BMV\t700\r\n'

    b'Checksum\t\xd6')

请注意,我\r\n在开头添加了,并从块的末尾删除了它们,这样最后一个字节就是块的校验和。


现在,我们可以计算块的校验和:


>>> sum(block) % 256

213

这应该是零。因此,可能存在一些传输问题,或者他们计算校验和的方式可能与他们在文档中所说的不同。


新数据后编辑。


这是我用来检查您发布的所有块的代码:


current_block = []

# it's unfortunate that lines start with `\r\n` rather than end with it

# we will read the first empty line separatey, and then include these 

# 2 characters in the last line that is read

message = bmvdata.readline()

while True:

    # Note that we cannot decode yet, since the Checksum value may not be a valid utf8 character

    message = bmvdata.readline()


    # we save the message in the current block before any preprocessing

    current_block.append(message)


    #splitting on tabs (as bytes !!)

    message_parts = message.split(b'\t')


    if len(message_parts) > 1:

        key = message_parts[0].decode('utf8')  # here it is safe to decode the key

        value = message_parts[1].rstrip()  #stripping \r\n after the value


    if key == 'Checksum':

        block_chars = b''.join(current_block)

        checksum = sum(block_chars) % 256

        print('Retrieved  checksum', value[-1])

        print('Calculated checksum', checksum)

        print('----')


        # reset the block

        current_block = []

奇怪的是,对于第一次运行,您总是得到等于检索到的计算值 + 1,但在第二次运行中却没有。因此,可能存在一些传输问题。


查看完整回答
反对 回复 2022-11-29
?
慕桂英546537

TA贡献1848条经验 获得超10个赞

下面的代码比较了两个文件,在这种情况下,正如提问者提到的校验和:


 bmvdata = batteryConnect(self.port,self.baudrate)

 bmvdata.flushInput()

 print(bmvdata.readline())

它是在hashlib的帮助下完成的


import hashlib

#File 1 = checksum

hasher1 = hashlib.md5()

#afile1 = open('checksum', 'rb')

buf1 = bmvdata.read()

#buf1 = afile1.read()

a = hasher1.update(buf1)

md5_a=(str(hasher1.hexdigest()))

#File 2

hasher2 = hashlib.md5()

afile2 = open('incoming-byte', 'rb')

buf2 = afile2.read()

b = hasher2.update(buf2)

md5_b=(str(hasher2.hexdigest()))

#Compare md5

if(md5_a==md5_b):

    print("Yes")

else:

    print("No")


查看完整回答
反对 回复 2022-11-29
  • 2 回答
  • 0 关注
  • 117 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号