处理网关获取升级包的请求(四)
再坚持一会
前面写到,我们又要写一个方法sendOtaPackageToGateway(),不写代码一直是我们的人生信条,想要我们写代码,除非走头无路,别无他法,所以继续复制粘贴。
首先复制一份sendOtaPackage()方法,改名为sendOtaPackageToGateway,如下所示:
private void sendOtaPackage(ChannelHandlerContext ctx, int msgId, String firmwareId, String requestId, int chunkSize, int chunk, OtaPackageType type) {
log.trace("[{}] Send firmware [{}] to device!", sessionId, firmwareId);
ack(ctx, msgId);
try {
byte[] firmwareChunk = context.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk);
deviceSessionCtx.getPayloadAdaptor()
.convertToPublish(deviceSessionCtx, firmwareChunk, requestId, chunk, type)
.ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
} catch (Exception e) {
log.trace("[{}] Failed to send firmware response!", sessionId, e);
}
}
由于deviceSessionCtx.getPayloadAdaptor().convertToPublish()方法内部,写的topic不是我们想要的,所以还是老办法,再新建一个方法,叫convertToGatewayPublish,为什么取这个名字呢?我怎么取的这么好呢?取得这么优雅,那当然还是抄的嘛,deviceSessionCtx.getPayloadAdaptor()接口如下:
public interface MqttTransportAdaptor {
ByteBufAllocator ALLOCATOR = new UnpooledByteBufAllocator(false);
PostTelemetryMsg convertToPostTelemetry(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
PostAttributeMsg convertToPostAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
GetAttributeRequestMsg convertToGetAttributes(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound, String topicBase) throws AdaptorException;
ToDeviceRpcResponseMsg convertToDeviceRpcResponse(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg, String topicBase) throws AdaptorException;
ToServerRpcRequestMsg convertToServerRpcRequest(MqttDeviceAwareSessionContext ctx, MqttPublishMessage mqttMsg, String topicBase) throws AdaptorException;
ClaimDeviceMsg convertToClaimDevice(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, GetAttributeResponseMsg responseMsg, String topicBase) throws AdaptorException;
Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, GetAttributeResponseMsg responseMsg) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, AttributeUpdateNotificationMsg notificationMsg, String topic) throws AdaptorException;
Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, AttributeUpdateNotificationMsg notificationMsg) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToDeviceRpcRequestMsg rpcRequest, String topicBase) throws AdaptorException;
Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, String deviceName, ToDeviceRpcRequestMsg rpcRequest) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ToServerRpcResponseMsg rpcResponse, String topicBase) throws AdaptorException;
ProvisionDeviceRequestMsg convertToProvisionRequestMsg(MqttDeviceAwareSessionContext ctx, MqttPublishMessage inbound) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, ProvisionDeviceResponseMsg provisionResponse) throws AdaptorException;
Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException;
// 这个方法是我新增的,方法名上面有,算是重载
default Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException {
return null;
}
default MqttPublishMessage createMqttPublishMsg(MqttDeviceAwareSessionContext ctx, String topic, byte[] payloadInBytes) {
MqttFixedHeader mqttFixedHeader =
new MqttFixedHeader(MqttMessageType.PUBLISH, false, ctx.getQoSForTopic(topic), false, 0);
MqttPublishVariableHeader header = new MqttPublishVariableHeader(topic, ctx.nextMsgId());
ByteBuf payload = ALLOCATOR.buffer();
payload.writeBytes(payloadInBytes);
return new MqttPublishMessage(mqttFixedHeader, header, payload);
}
}
新增convertToGatewayPublish()方法,前面加 defulat,给个默认实现,是因为擅自加个接口方法,影响比较大,很多实现类都要必须实现我这个方法,加个default,就没影响了,我只需要在我需要的那个实现类重写该方法。
我们在JsonMqttAdaptor类中实现新增的方法,还是老办法,先复制,再修改,我们复制的方法就是下面这个方法:
@Override
public Optional<MqttMessage> convertToPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) {
return Optional.of(createMqttPublishMsg(ctx, String.format(DEVICE_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT, firmwareType.getKeyPrefix(), requestId, chunk), firmwareChunk));
}
只需要将 DEVICE_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT 改为 GATEWAY_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT, GATEWAY_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT 最开始已经定义过,最终新增convertToGatewayPublish()方法实现为:
@Override
public Optional<MqttMessage> convertToGatewayPublish(MqttDeviceAwareSessionContext ctx, byte[] firmwareChunk, String requestId, int chunk, OtaPackageType firmwareType) throws AdaptorException {
return Optional.of(createMqttPublishMsg(ctx, String.format(GATEWAY_SOFTWARE_FIRMWARE_RESPONSES_TOPIC_FORMAT, firmwareType.getKeyPrefix(), requestId, chunk), firmwareChunk));
}
最后将 deviceSessionCtx.getPayloadAdaptor().convertToPublish 换成 deviceSessionCtx.getPayloadAdaptor().convertToGatewayPublish,sendOtaPackageToGateway()方法就写好了,最终sendOtaPackageToGateway()代码如下:
private void sendOtaPackageToGateway(ChannelHandlerContext ctx, int msgId, String firmwareId, String requestId, int chunkSize, int chunk, OtaPackageType type) {
log.trace("[{}] Send firmware [{}] to device!", sessionId, firmwareId);
ack(ctx, msgId);
try {
byte[] firmwareChunk = context.getOtaPackageDataCache().get(firmwareId, chunkSize, chunk);
deviceSessionCtx.getPayloadAdaptor()
.convertToGatewayPublish(deviceSessionCtx, firmwareChunk, requestId, chunk, type)
.ifPresent(deviceSessionCtx.getChannel()::writeAndFlush);
} catch (Exception e) {
log.trace("[{}] Failed to send firmware response!", sessionId, e);
}
}