首页 > 编程语言 >python cobs协议编解码算法demo

python cobs协议编解码算法demo

时间:2024-07-25 15:25:49浏览次数:17  
标签:02 编解码 01 字节 python demo list encode 数据包

1. Summary

COBS(Consistent Overhead Byte Stuffing)是一种算法,直译为一致的开销字节填充。简而言之,无论数据包的内容如何,都能通过产生高效可靠明确的数据包帧,从而使接受端能够从损坏的包中恢复。通常使用0x00来作为数据包的分隔符,即切割数据包的片分隔符。当使用0x00作为分隔符时,此算法会把每个零数据字节替换为非零值,这样数据包中就不会出现零数据字节,从而被误解为数据包分隔符。字节填充则是将可能包含"非法"或"保留"值,比如说数据包分隔符的数据字节序列,转换成不含这些值的序列的过程,当然可能会让这个序列变得更长,转换后的序列的额外长度通常被称为该算法的“开销”。关于开销有个例子,有个HDLC帧结构字节填充技术,大多数情况下开销很小,不到1%,但是最坏的情况下,数据包完全由需要转义的字节组成时,开销会达到100%。假设有一段数据需要通过HDLC帧结构传输,且该数据由一些特殊字节组成,这些字节需要进行转义处理:

  • 原始数据:

    7E 7D 7E
    
    • 这里,7E是HDLC帧的结束标志,7D是转义字符。
  • 经过HDLC字节填充后的数据:

    7D 5E 7D 5D 7D 5E
    
    • 7E被转义为7D 5E7D被转义为7D 5D,另一个7E再次转义为7D 5E

在这种情况下,原始数据的长度是3个字节,但经过HDLC字节填充后,长度变成了6个字节,数据大小翻倍,开销达到了100%。

那么,COBS算法严格限制了最坏开销的情况,COBS最少需要一个字节的开销,对于长度为N的数据包,需要最大的(n/254)字节开销。因此,传输编码字节序列的时间是高度可预测的,这使得COBS对于可能存在抖动问题的实时应用程序非常有效。算法计算成本也是不高的,除了最坏情况的开销外,与HDLC这种算法相比也是要更低的。但是在传输他的第一个字节前,他必须要知道接下来254个字节中的第一个0字节。

2. Packet Framing And Stuffing

当分组数据通过串行协议发送时,需要一些协议来划分数据包的边界。这是通过使用帧标记来完成的,这是一个特殊的位序列或字符值,指示数据包之间的边界在哪里。数据填充是指在传输前对数据包数据进行转换以消除所有出现的分帧标记的过程,这样当接收方检测到标记时,就可以确定该标记表示数据包之间的边界。COBS将[0,255]范围内的任意字节串转换为[1,255]范围内的字节串。消除了数据中的所有零字节后,现在可以使用零字节明确地标记转换后数据的结束。这是通过向转换后的数据附加一个零字节来实现的,从而形成一个由cobs编码的数据(有效负载)组成的数据包,以明确地标记数据包的末尾。(可以保留任何其他字节值作为数据包分隔符,但使用零可以简化描述。)

在这里插入图片描述

COBS编码过程:

1.添加首个byte,这个byte指的是下一个0的位置,那么从上图可以看出,第三个位置是0,所以首个byte是03

2.而当数据中有0时,需要被改写,改写的值就是距离下一个0的距离,0距离最后一个00差2,所以改写为02

3.每一个数据包的最后都要加上00

3. Example

ExampleUnencoded data (hex)Encoded with COBS (hex)
10001 01 00
200 0001 01 01 00
300 11 0001 02 11 01 00
411 22 00 3303 11 22 02 33 00
511 22 33 4405 11 22 33 44 00
611 00 00 0002 11 01 01 01 00
701 02 03 … FD FEFF 01 02 03 … FD FE 00
800 01 02 … FC FD FE01 FF 01 02 … FC FD FE 00
901 02 03 … FD FE FFFF 01 02 03 … FD FE 02 FF 00
1002 03 04 … FE FF 00FF 02 03 04 … FE FF 01 01 00
1103 04 05 … FF 00 01FE 03 04 05 … FF 02 01 00

4. Python Code

由于工作需要需要支持cobs协议,所以上位机用python做了一个cobs的编解码器。借鉴了网上相关java的算法,采用的滑动窗口的方法,进行编解码。

Encode

def cobs_encoded(data_in):
    encode_list = [0]
    len_data = len(data_in)
    zero_pos = 0
    zero_adds = 1

    # 复制输入数据到encode_list
    encode_list.extend(data_in)
    encode_list.append(0)

    i = 1
    while i < len(encode_list):
        temp = encode_list[i]
        if temp == 0:
            encode_list[zero_pos] = zero_adds
            zero_pos += zero_adds
            zero_adds = 0
        zero_adds += 1
        if zero_adds >= 0xFF:
            encode_list[zero_pos] = 0xFF
            if i == len_data:
                break

            encode_list.insert(i + 1, 0)
            i += 1
            zero_pos += zero_adds
            zero_adds = 1
        i += 1

    return encode_list

Decode

def cobs_decode(data):
    # 将输入数据转换为列表
    encode_list = list(data)

    z_value = encode_list[0]
    z_index = 0

    i = 0
    while i < len(encode_list):
        temp = encode_list[i]
        if z_index == z_value:
            if z_value == 0xFF:
                temp = encode_list[i]  # 关键位置
                encode_list.pop(i)

                if i+1 <= len(encode_list) and encode_list[i+1] == 1:
                    encode_list[i] = 0
            else:
                encode_list[i] = 0

            z_index = 0
            z_value = temp
        z_index += 1
        i += 1

    # 移除第一位包头
    encode_list.pop(0)

    # 移除结尾的0(如果存在)
    if encode_list and encode_list[-1] == 0x00:
        encode_list.pop()

    return encode_list

Test Result

ExampleUnencoded data (hex)Encoded with COBS (hex)Encode ResultDecode Result
10001 01 00PassPass
200 0001 01 01 00PassPass
300 11 0001 02 11 01 00PassPass
411 22 00 3303 11 22 02 33 00PassPass
511 22 33 4405 11 22 33 44 00PassPass
611 00 00 0002 11 01 01 01 00PassPass
701 02 03 … FD FEFF 01 02 03 … FD FE 00PassPass
800 01 02 … FC FD FE01 FF 01 02 … FC FD FE 00PassPass
901 02 03 … FD FE FFFF 01 02 03 … FD FE 02 FF 00PassPass
1002 03 04 … FE FF 00FF 02 03 04 … FE FF 01 01 00PassPass
1103 04 05 … FF 00 01FE 03 04 05 … FF 02 01 00PassPass

github上附有对应的测试用例数据,可以看下,觉得有用可以帮忙star下~

reference

https://en.wikipedia.org/wiki/Consistent_Overhead_Byte_Stuffing wiki百科官方解释

标签:02,编解码,01,字节,python,demo,list,encode,数据包
From: https://blog.csdn.net/weixin_44300062/article/details/140690981

相关文章

  • 如何将unicode编码为字节,以便可以检索到原始字符串?在Python 3.11中
    在python3.11中,我们可以对字符串进行编码,如:string.encode('ascii','backslashreplace')这对于说:hellö=>hell\\xf6但是当我插入时hellöw\\xf6rldIgethell\\xf6w\\xf6rld(注意第二个有一个看起来像字符转义序列的文字部分)......
  • python flask允许跨域
    flask接口支持跨域设置方法在Flask中,可以通过安装flask-cors扩展来支持跨域请求。下面是使用flask-cors扩展的示例代码:fromflaskimportFlaskfromflask_corsimportCORS#ipinstallflask-corsapp=Flask(__name__)CORS(app)可以通过CORS扩展的origins参数......
  • 在 Python 中动态定义文字字符串排列的并集
    我有一个字符串列表:strings=['a','b','c']我想声明列表中所有可能的有序对的Union类型。硬编码,这看起来像:Literal我如何动态定义CustomType=Literal['ab','ac','aa','ba','bb','bc�......
  • 关于 Python 中装饰器缓存的困惑
    我正在使用Python装饰器来实现函数的缓存。我了解缓存结果以提高性能的基本概念,但我正在努力解决如何处理不同的函数参数并确保底层数据更改时缓存更新。我已经实现了一个基本装饰器,它将函数结果存储在基于参数的字典。但是,此方法无法处理函数参数可能具有复杂结构(如嵌套列......
  • Python:__add__ 和 +,浮点数和整数的不同行为
    当将整数值添加到浮点值时,我意识到如果在浮点上调用该方法可以正常工作,例如:__add__但如果在整数上调用则不行:>>>n=2.0>>>m=1>>>n.__add__(m)3.0起初我认为|||只是对>>>m.__add__(n)NotImplemented和__add__类型的实现方式不同(例如f......
  • python中scrapy爬取数据get()与getall()区别
    在使用scrapy进行爬取数据的时候,有些时候需要爬取的是一段文本,或者一个div里面有很多内容,这时候我们就要使用到get()或者getall()来获取数据: get():是获取的满足条件的第一个数据。getall():是获取的满足条件的所有数据。scrapyget()getall()原理在Scrapy中,get(......
  • python—NumPy基础(3)
    文章目录算术函数算术函数的使用算术函数中out参数的使用mod()函数的使用统计函数power()函数的使用median()函数的使用mean()函数的使用函数的使用其他常用函数tile()和repeat()函数的使用roll()函数的使用resize()函数的使用replace()和put()函数的使savetxt()和lo......
  • Python爬虫:代理ip电商数据实战
    引言:数据访问管理引发的烦恼作为一名Python博主,爬虫技能对于获取和分析数据至关重要,经常爬一下,有益身心健康嘛。爬虫技术对很多人来说,不仅仅是一种工具,更像是一种艺术,帮助我们从互联网中,捕捉到有价值的信息。我经常就会用爬虫来爬取一些所需的数据,用来进行数据分析和模型训......
  • python科学计算:加速库numba —— 安装和试用
    安装(anaconda环境下)condainstallnumbaDemo代码:fromnumbaimportjitfromnumpyimportarangeimportnumpyimporttime@jitdefsum2d(arr):M,N=arr.shaperesult=0.0foriinrange(M):forjinrange(N):result+=a......
  • Python - Selenium抓取淘宝直播间评论(可使用无头模式)
    Python-Selenium抓取淘宝直播间评论(可使用无头模式)下面介绍如何使用python中的selenium简单抓取淘宝直播间实时评论。友情提醒,仅供学习交流使用,请勿用于非法用途!一、创建python项目1.在目录下新建main.py和venv虚拟环境:创建虚拟环境:python-mvenvvenv激活虚拟环......