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

344 阅读1分钟

根据deviceName获取deviceId

先复习如何获取升级包,贴出代码

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));

想要获取升级包,就要构造一条消息,想要构造一条消息,就要设备的sessionInfo,而sessionInfo从何而来,我们只知道deviceName,这可如何是好?

通过看 org.thingsboard.server.transport.mqtt.session 包 GatewaySessionHandler 类 checkDeviceConnected方法,完美解决我的问题,这个方法是这样的:

private ListenableFuture<GatewayDeviceSessionCtx> checkDeviceConnected(String deviceName) {
    GatewayDeviceSessionCtx ctx = devices.get(deviceName);
    if (ctx == null) {
        log.debug("[{}] Missing device [{}] for the gateway session", sessionId, deviceName);
        return onDeviceConnect(deviceName, DEFAULT_DEVICE_TYPE);
    } else {
        return Futures.immediateFuture(ctx);
    }
}

方法的参数是deviceName,返回值是GatewayDeviceSessionCtx,GatewayDeviceSessionCtx里面有个成员变量sessionInfo,这个sessionInfo就是我们苦苦寻找的sessionInfo,真是踏破铁鞋无觅处,得来全不费工夫,有了它,我们就能构造消息,有了消息,就能获取升级包。

但这个方法是私有方法,外界无法直接调用,这倒不是问题,我们再写一个public方法,包一层,而且直接返回sessionInfo,我写的方法可供参考:

public ListenableFuture<TransportProtos.SessionInfoProto> getDeviceSessionInfo(String deviceName) {
    final SettableFuture<TransportProtos.SessionInfoProto> futureToSet = SettableFuture.create();

    ListenableFuture<GatewayDeviceSessionCtx> listenableFuture = checkDeviceConnected(deviceName);
    Futures.addCallback(checkDeviceConnected(deviceName),
            new FutureCallback<>() {
                @Override
                public void onSuccess(@Nullable GatewayDeviceSessionCtx deviceCtx) {
                    futureToSet.set(deviceCtx.getSessionInfo());
                }

                @Override
                public void onFailure(Throwable t) {
                    log.debug("[{}] Failed to process device ota request command: {}", sessionId, deviceName, t);
                }
            }, context.getExecutor());

    return futureToSet;
}

由于要提取精华,只要sessionInfo,所以再搞一个future,并返回,等checkDeviceConnected的future有数据了,就设置future的值。

MqttTransportHandler类中,正好有GatewaySessionHandler对象,可以直接调用gatewaySessionHandler.getDeviceSessionInfo(deviceName)获取到sessionInfo。

至此,获取任意设备的升级包的所有障碍全部扫除,接下来处理网关发送的获取升级包请求。