Coder Social home page Coder Social logo

Comments (4)

pruidong avatar pruidong commented on July 18, 2024 3

找了很久资料,找不到对应的方式解析数据.只好自己实现了解析终端参数查询结果.

依赖版本(除了jt-framework强依赖,Java版本可自行修改代码适配低版本):

jt-framework: 2.0.0-RELEASE
Java: 17
Spring Boot(低版本可用,此处仅使用了 @component): 2.6.3

简单代码如下:

实体类:

import io.github.hylexus.jt.jt808.support.annotation.msg.req.Jt808RequestBody;
import io.github.hylexus.jt.jt808.support.annotation.msg.req.RequestField;
import io.github.hylexus.jt.jt808.support.data.MsgDataType;
import io.github.hylexus.jt.jt808.support.utils.JtProtocolUtils;
import io.netty.buffer.ByteBufAllocator;
import lombok.Data;
import lombok.experimental.Accessors;
import lombok.extern.slf4j.Slf4j;

import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static io.github.hylexus.jt.jt808.support.data.MsgDataType.*;

/**
 * 查询终端参数应答.
 *
 * @author puruidong
 * @version 2022-02-24
 */
@Slf4j
@Data
@Accessors(chain = true)
@Jt808RequestBody
public class TerminalParamQuery0104V2013 {

  /** 1. 流水号 WORD */
  @RequestField(order = 0, startIndex = 0, dataType = WORD)
  int serverFlowId;

  /** 2. 参数个数 */
  @RequestField(order = 1, startIndex = 2, dataType = BYTE)
  int count;

  /** 3. 参数项列表 */
  @RequestField(
      order = 2,
      startIndex = 3,
      dataType = LIST,
      lengthExpression = "#ctx.msgBodyLength() - 3")
  List<TerminalParam> paramList;

  @Data
  @Accessors(chain = true)
  public static class TerminalParam {

    // 参数id DWORD[4]
    @RequestField(order = 0, startIndex = 0, dataType = DWORD)
    private int paramId;

    // 参数长度 BYTE[1]
    @RequestField(order = 1, startIndex = 2, dataType = BYTE)
    private int contentLength;

    // 参数值
    @RequestField(
        order = 2,
        startIndex = 3,
        dataType = BYTES,
        lengthExpression = "#this.contentLength")
    private byte[] paramContent;
  }

  /**
   * 记录终端明细参数对应的值类型.
   *
   * <p>! 注意: 此处仅包含部分,其余未包含的参数ID,默认以DWORD类型解析.
   */
  private final Map<Integer, MsgDataType> detailParamIdType =
      Map.of(16, STRING, 17, STRING, 18, STRING, 19, STRING, 131, STRING, 132, BYTE);

  /**
   * 需要解析的参数id列表.
   *
   * <p>对应: 0x0001, 0x0010, 0x0013, 0x0018, 0x0027, 0x0029, 0x0055, 0x0056, 0x0080, 0x0081, 0x0082,
   * 0x0083, 0x0084
   */
  private final List<Integer> paramIdRequires =
      List.of(1, 16, 19, 24, 39, 41, 85, 86, 128, 129, 130, 131, 132);

  /**
   * 解析后的参数值Map.
   *
   * Key为int类型的参数ID,value为参数值.
   *
   */
  public Map<Integer, String> detailParamMap;

  /**
   * 手动解析数据.
   *
   * 解析后的数据保存在: detailParamMap变量中,Key为int类型的参数ID,value为参数值.
   *
   * @return 当前实例
   */
  public TerminalParamQuery0104V2013 decodeParamList() {
    // 解析明细数据.
    if (paramList.size() > 0) {
      Map<Integer, String> resultMap = new HashMap<>(paramList.size());
      paramList.forEach(
          item -> {
            // 仅解析已经预制的字段,除此之外的字段不解析.
            if (paramIdRequires.contains(item.paramId)) {
              byte[] paramContentArr = item.paramContent;
              // byte[] 数组小于4位,则使用0前置填充.
              if (item.paramContent.length < 4) {
                paramContentArr = new byte[] {0, 0, 0, 0};
                System.arraycopy(
                    item.paramContent,
                    0,
                    paramContentArr,
                    paramContentArr.length - item.paramContent.length,
                    item.paramContent.length);
              }
              var paramContentByteBuf =
                  ByteBufAllocator.DEFAULT.buffer().writeBytes(paramContentArr);
              var checkDataType = detailParamIdType.containsKey(item.paramId);
              var value = "";
              if (checkDataType) {
                var dataType = detailParamIdType.getOrDefault(item.paramId, STRING);
                if (dataType == STRING) {
                  value =
                      JtProtocolUtils.readString(
                          paramContentByteBuf, item.contentLength, Charset.forName("GBK"));
                } else {
                  // 当数据为BYTE类型时,需要使用原始数据!
                  paramContentByteBuf =
                      ByteBufAllocator.DEFAULT.buffer().writeBytes(item.paramContent);
                  byte by = paramContentByteBuf.readByte();
                  value = String.valueOf(by);
                }
              } else {
                // 不存在,以DWORD解析.
                value = String.valueOf(JtProtocolUtils.readUnsignedDword(paramContentByteBuf));
              }
              resultMap.put(item.getParamId(), value);
            }
          });
      setDetailParamMap(resultMap);
    }
    return this;
  }
}

解析调用:

import com.example.entity.TerminalParamQuery0104V2013;
import io.github.hylexus.jt.jt808.spec.Jt808Request;
import io.github.hylexus.jt.jt808.spec.Jt808RequestEntity;
import io.github.hylexus.jt.jt808.spec.builtin.msg.resp.BuiltinServerCommonReplyMsg;
import io.github.hylexus.jt.jt808.support.annotation.handler.Jt808RequestHandler;
import io.github.hylexus.jt.jt808.support.annotation.handler.Jt808RequestHandlerMapping;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

/**
 * 终端参数查询结果处理.
 *
 * @author puruidong
 * @version 2022-02-24
 */
@Slf4j
@Component
@Jt808RequestHandler
public class TerminalParamQueryHandler {

  @Jt808RequestHandlerMapping(msgType = 0x0104)
  public BuiltinServerCommonReplyMsg terminalParamQueryResult(
      Jt808Request request, Jt808RequestEntity<TerminalParamQuery0104V2013> requestEntity) {

    // 执行手动转换数据.
    var obj = requestEntity.body().decodeParamList();

    // 解析后的数据在: detailParamMap 中,详情查看实体类.
    
    log.info("终端参数查询处理 : {}", obj.toString());
    return BuiltinServerCommonReplyMsg.success(
        requestEntity.msgType().getMsgId(), requestEntity.flowId());
  }
}

from jt-framework.

hylexus avatar hylexus commented on July 18, 2024 1

终端参数结果返回的是列表,但字段没有固定长度,请问应该怎么解析?谢谢.

目前为止只能使用 byte[]ByteBuf 来接收这种 不确定的 数据类型,然后通过参数ID 来解析为具体类型。就像你 上面 提到一样:

  @Data
  @Accessors(chain = true)
  public static class TerminalParam {

    // 参数id DWORD[4]
    @RequestField(order = 0, startIndex = 0, dataType = DWORD)
    private int paramId;

    // 参数长度 BYTE[1]
    @RequestField(order = 1, startIndex = 2, dataType = BYTE)
    private int contentLength;

    // 参数值
    @RequestField(
        order = 2,
        startIndex = 3,
        dataType = BYTES,
        lengthExpression = "#this.contentLength")
    private byte[] paramContent;
  }

from jt-framework.

pruidong avatar pruidong commented on July 18, 2024

QQ截图20220223084216

如图,同时存在STRING和WORD.

from jt-framework.

pruidong avatar pruidong commented on July 18, 2024

FireShot Pro Webpage Screenshot #014 - 'KM系列部标通讯协议V1 1' - docs qq com

同时存在BYTE.

这是我这遇到的所有需要解析的数据.

from jt-framework.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.