实现 thingsboard 网关下设备 OTA 升级功能(八)

433 阅读2分钟

处理网关获取升级包的请求(二)

继续啃硬骨头,真香

由于要再写一个方法getOtaPackageCallbackByGateway(),这又是一个难题,写代码是不可能的,这辈子都不可能写代码,只有ctrl+c ctrl+v 这种办法,才能勉强生存。

首先复制getOtaPackageCallback(),改名为getOtaPackageCallbackByGateway(),变成下面这样:

private void getOtaPackageCallbackByGateway(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, int msgId, Matcher fwMatcher, OtaPackageType type) {
    String payload = mqttMsg.content().toString(UTF8);
    int chunkSize = StringUtils.isNotEmpty(payload) ? Integer.parseInt(payload) : 0;
    String requestId = fwMatcher.group("requestId");
    int chunk = Integer.parseInt(fwMatcher.group("chunk"));

    if (chunkSize > 0) {
        this.chunkSizes.put(requestId, chunkSize);
    } else {
        chunkSize = chunkSizes.getOrDefault(requestId, 0);
    }

    if (chunkSize > context.getMaxPayloadSize()) {
        sendOtaPackageError(ctx, PAYLOAD_TOO_LARGE);
        return;
    }

    String otaPackageId = otaPackSessions.get(requestId);

    if (otaPackageId != null) {
        sendOtaPackage(ctx, mqttMsg.variableHeader().packetId(), otaPackageId, requestId, chunkSize, chunk, type);
    } else {
        TransportProtos.SessionInfoProto sessionInfo = deviceSessionCtx.getSessionInfo();
        TransportProtos.GetOtaPackageRequestMsg getOtaPackageRequestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder()
                .setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
                .setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
                .setTenantIdMSB(sessionInfo.getTenantIdMSB())
                .setTenantIdLSB(sessionInfo.getTenantIdLSB())
                .setType(type.name())
                .build();
        transportService.process(deviceSessionCtx.getSessionInfo(), getOtaPackageRequestMsg,
                new OtaPackageCallback(ctx, msgId, getOtaPackageRequestMsg, requestId, chunkSize, chunk));
    }
}

仔细观察,前面一大坨是在提取参数,我们需要的参数肯定跟它不一样,我们请求的参数有4个,分别是requestId、chunk、chunkSize、deviceName。我们先修改提取参数部分,我修改后如下:

@Data
private class GatewayOtaPackageRequestDTO {
    private String deviceName;
    private Integer chunkSize;
}

private void getOtaPackageCallbackByGateway(ChannelHandlerContext ctx, MqttPublishMessage mqttMsg, int msgId, Matcher fwMatcher, OtaPackageType type) {

    String requestId = fwMatcher.group("requestId");
    int chunk = Integer.parseInt(fwMatcher.group("chunk"));

    String payload = mqttMsg.content().toString(UTF8);
    Gson gson = new Gson();

    GatewayOtaPackageRequestDTO dto = null;
    try {
        dto = gson.fromJson(payload, GatewayOtaPackageRequestDTO.class);
    } catch (JsonSyntaxException e){
        sendOtaPackageErrorToGateway(ctx, msgId, requestId, "解析JSON出错,请求负载不合法,负载示例:{deviceName:"SN-001", chunkSize:512}", type);
        return;
    }

    if(dto == null) {
        sendOtaPackageErrorToGateway(ctx, msgId, requestId, "请求没有负载,负载示例:{deviceName:"SN-001", chunkSize:512}", type);
        return;
    }

    Integer chunkSize = dto.getChunkSize();
    String deviceName = dto.getDeviceName();

    if(chunkSize == null) {
        sendOtaPackageErrorToGateway(ctx, msgId, requestId, "请求负载缺少chunkSize,负载示例:{deviceName:"SN-001", chunkSize:512}", type);
        return;
    }

    if(deviceName == null) {
        sendOtaPackageErrorToGateway(ctx, msgId, requestId, "请求负载缺少deviceName,负载示例:{deviceName:"SN-001", chunkSize:512}", type);
        return;
    }

    if (chunkSize > 0) {
        this.chunkSizes.put(requestId, chunkSize);
    } else {
        chunkSize = chunkSizes.getOrDefault(requestId, 0);
    }

    if (chunkSize > context.getMaxPayloadSize()) {
        sendOtaPackageError(ctx, PAYLOAD_TOO_LARGE);
        return;
    }
    

    String otaPackageId = otaPackSessions.get(requestId);

    if (otaPackageId != null) {
        sendOtaPackage(ctx, mqttMsg.variableHeader().packetId(), otaPackageId, requestId, chunkSize, chunk, type);
    } else {
        TransportProtos.SessionInfoProto sessionInfo = deviceSessionCtx.getSessionInfo();
        TransportProtos.GetOtaPackageRequestMsg getOtaPackageRequestMsg = TransportProtos.GetOtaPackageRequestMsg.newBuilder()
                .setDeviceIdMSB(sessionInfo.getDeviceIdMSB())
                .setDeviceIdLSB(sessionInfo.getDeviceIdLSB())
                .setTenantIdMSB(sessionInfo.getTenantIdMSB())
                .setTenantIdLSB(sessionInfo.getTenantIdLSB())
                .setType(type.name())
                .build();
        transportService.process(deviceSessionCtx.getSessionInfo(), getOtaPackageRequestMsg,
                new OtaPackageCallback(ctx, msgId, getOtaPackageRequestMsg, requestId, chunkSize, chunk));
    }
}

sendOtaPackageErrorToGateway()方法暂时不用管,它的作用是向网关发送错误响应,虽然多了很多判断,搞得代码多出不少行,但也是没有办法,反正是复制粘贴而来,也不费什么工夫。

这篇文章字数感觉挺多了,下一篇继续。