Rxjs 如何通过管道rx操作符组合片段数据?

Rxjs 如何通过管道rx操作符组合片段数据?,rxjs,rx-java,reactive-programming,Rxjs,Rx Java,Reactive Programming,我想用Rx来处理串口数据,数据包结构如下所示 +-----------+--------+---------+ | Signature | Length | Payload | +-----------+--------+---------+ | 2 byte | 1 byte | ... | +-----------+--------+---------+ 但接收到的数据会有很多碎片。例如(签名为0xFC 0xFA) 数据1:0xFC 0xFA 0x02 0x01 0x01 0

我想用Rx来处理串口数据,数据包结构如下所示

+-----------+--------+---------+
| Signature | Length | Payload |
+-----------+--------+---------+
| 2 byte    | 1 byte | ...     |
+-----------+--------+---------+
但接收到的数据会有很多碎片。例如(签名为0xFC 0xFA)
数据1:0xFC 0xFA 0x02 0x01 0x01 0xFC 0xFA 0x03 0x01//包含一个数据包和一个片段数据包
数据2:0x02 0x03 0xFC 0xFA 0x02 0x01 0x03//包含先前数据包和新数据包的连续片段

如何通过管道将运算符输出为
包1:0xFC 0xFA 0x02 0x01 0x01
包2:0xFC 0xFA 0x03 0x01 0x02 0x03

...

你需要一个有状态的观察者。它将让这些国家:

  • 正在侦听数据包的开头
  • 接收到第一个字节,正在侦听第二个字节
  • 接收到的第二个字节侦听长度
  • 接收到的标头正在侦听正文
  • 在RxJava中,您将创建一个类
    Packetizer
    ,该类将有两个感兴趣的方法:

    public void nextByte(Char next);
    public Observable<Packet> packetSource();
    
    public void nextByte(Char next);
    公共可观察包源();
    

    在内部,它将保持状态,包括正文剩余部分的长度等。它还将具有一个
    PublishSubject
    ,它将在构造每个数据包时发出该数据包。

    您正在按定义的模式拆分字节流。我不确定您是如何接收字节的,以及您将如何建模您的可观察的、
    可观察的
    可观察的

    不管怎样,这里我猜的是用字符串翻译的,但是想法还是一样的。我选择了
    x
    后跟
    y
    作为模式(
    0xFC 0xFA

    您可以在代码中找到我的注释:

    final ImmutableList模式=ImmutableList.of(“x”,“y”);
    可观测源=可观测
    .fromArray(“x”、“y”、“1”、“2”、“3”、“x”、“y”、“4”、“5”、“x”、“y”、“y”、“1”、“x”、“y”、“x”、“x”、“x”、“4”、“6”、“x”)
    .share()//发布到hot observable(我们将此源按其某些元素进行拆分)
    //找到下一个模式
    可观测下边界=源
    .缓冲区(2,1)
    .filter(对->CollectionUtils.isEqualCollection(模式,对));
    //https://raw.githubusercontent.com/wiki/ReactiveX/RxJava/images/rx-operators/buffer2.png
    //为找到的每个x启动一个缓冲区
    //缓冲区(数据包)可能重叠
    source.buffer(source.filter(e->e.equals(“x”)),
    x->来源
    .take(1)//x之后的下一个发射
    .switchMap(y->y.equals(“y”)?
    下一边界//如果为“y”,则查找下一个模式
    :Observable.empty()//否则停止缓冲
    )
    )
    .filter(packet->packet.size()>2)//不要使用错误的缓冲区,如[“x”,“4”](x后面不跟y),但不会丢失
    .map(数据包->{
    //每个数据包如下所示:
    //[x,y,1,2,3,x,y]
    //[x,y,4,5,x,y]
    //[x,y,1,x,y]
    //[x,y,x,4,6,x]
    //由于边界封闭,事件来得太晚
    //然后我们必须处理数据包(它与下一个数据包重叠)
    列表结束=packet.subList(packet.size()-2,packet.size());
    返回CollectionUtils.isEqualCollection(模式,结束)?packet.subList(0,packet.size()-2):packet;
    })
    .blockingSubscribe(e->System.out.println(e));
    
    结果:

    [x,y,1,2,3]
    [x,y,4,5]
    [x,y,1]
    [x,y,x,4,6,x]


    我试过你们两个的解决办法。都很好!