From a7aaeabc7873a0eafb4a7ecad7f65b018b7a9bc9 Mon Sep 17 00:00:00 2001
From: sean.zhou <sean.zhou@dji.com>
Date: Fri, 24 Feb 2023 19:31:23 +0800
Subject: [PATCH] What's new? 1. Add license for dock. 2. Modify the logic corresponding to the firmware file and device type. 3. Add multiple mqtt clients options. 4. Modify the structure of the interface for obtaining the device list. 5. Fixed some issues.
---
src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java | 495 ++++++++++++++++++++++++++++++++++++------------------
1 files changed, 329 insertions(+), 166 deletions(-)
diff --git a/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java b/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
index dbfbf77..6677ca8 100644
--- a/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
+++ b/src/main/java/com/dji/sample/manage/service/impl/DeviceServiceImpl.java
@@ -6,6 +6,7 @@
import com.dji.sample.common.error.CommonErrorEnum;
import com.dji.sample.common.model.Pagination;
import com.dji.sample.common.model.PaginationData;
+import com.dji.sample.common.model.ResponseResult;
import com.dji.sample.component.mqtt.model.*;
import com.dji.sample.component.mqtt.service.IMessageSenderService;
import com.dji.sample.component.mqtt.service.IMqttTopicService;
@@ -19,19 +20,20 @@
import com.dji.sample.manage.dao.IDeviceMapper;
import com.dji.sample.manage.model.dto.*;
import com.dji.sample.manage.model.entity.DeviceEntity;
-import com.dji.sample.manage.model.enums.DeviceDomainEnum;
-import com.dji.sample.manage.model.enums.IconUrlEnum;
-import com.dji.sample.manage.model.enums.UserTypeEnum;
+import com.dji.sample.manage.model.enums.*;
+import com.dji.sample.manage.model.param.DeviceOtaCreateParam;
import com.dji.sample.manage.model.param.DeviceQueryParam;
import com.dji.sample.manage.model.receiver.*;
import com.dji.sample.manage.service.*;
import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.integration.annotation.ServiceActivator;
import org.springframework.integration.mqtt.support.MqttHeaders;
+import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -84,54 +86,44 @@
private ObjectMapper objectMapper;
@Autowired
- private RedisOpsUtils redisOps;
+ private IWebSocketManageService webSocketManageService;
@Autowired
- private IWebSocketManageService webSocketManageService;
+ private IDeviceFirmwareService deviceFirmwareService;
@Autowired
@Qualifier("gatewayOSDServiceImpl")
private ITSAService tsaService;
+ private static final List<String> INIT_TOPICS_SUFFIX = List.of(
+ OSD_SUF, STATE_SUF, SERVICES_SUF + _REPLY_SUF, EVENTS_SUF, PROPERTY_SUF + SET_SUF + _REPLY_SUF);
+
@Override
- public Boolean deviceOffline(String gatewaySn) {
+ public Boolean deviceOffline(StatusGatewayReceiver gateway) {
+ String gatewaySn = gateway.getSn();
this.subscribeTopicOnline(gatewaySn);
// Only the remote controller is logged in and the aircraft is not connected.
String key = RedisConst.DEVICE_ONLINE_PREFIX + gatewaySn;
- boolean exist = redisOps.checkExist(key);
+ boolean exist = RedisOpsUtils.checkExist(key);
if (!exist) {
Optional<DeviceDTO> gatewayOpt = this.getDeviceBySn(gatewaySn);
if (gatewayOpt.isPresent()) {
DeviceDTO value = gatewayOpt.get();
- value.setChildDeviceSn(value.getDeviceSn());
- value.setBoundTime(null);
- value.setLoginTime(null);
- redisOps.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND);
+ RedisOpsUtils.setWithExpire(key, value, RedisConst.DEVICE_ALIVE_SECOND);
this.pushDeviceOnlineTopo(value.getWorkspaceId(), gatewaySn, gatewaySn);
return true;
}
- DeviceDTO gateway = DeviceDTO.builder()
- .deviceSn(gatewaySn)
- .childDeviceSn(gatewaySn)
- .domain(DeviceDomainEnum.GATEWAY.getDesc())
- .build();
- gatewayOpt.map(DeviceDTO::getWorkspaceId).ifPresent(gateway::setWorkspaceId);
- redisOps.setWithExpire(key, gateway, RedisConst.DEVICE_ALIVE_SECOND);
- this.pushDeviceOnlineTopo(gateway.getWorkspaceId(), gatewaySn, gatewaySn);
- return true;
+
+ // When connecting for the first time
+ DeviceEntity gatewayDevice = deviceGatewayConvertToDeviceEntity(gateway);
+ return onlineSaveDevice(gatewayDevice, null).isPresent();
}
- long expire = redisOps.getExpire(key);
- // If the key about the device in redis has expired, the remote control is considered to be offline.
- if (expire <= 0) {
- log.debug("The remote control is already offline.");
- return true;
- }
-
- String deviceSn = ((DeviceDTO)(redisOps.get(key))).getChildDeviceSn();
- if (deviceSn.equals(gatewaySn)) {
+ DeviceDTO deviceDTO = (DeviceDTO) (RedisOpsUtils.get(key));
+ String deviceSn = deviceDTO.getChildDeviceSn();
+ if (!StringUtils.hasText(deviceSn)) {
return true;
}
@@ -140,21 +132,24 @@
@Override
public Boolean subDeviceOffline(String deviceSn) {
+
+ // If no information about this device exists in the cache, the drone is considered to be offline.
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
+ if (!RedisOpsUtils.checkExist(key) || RedisOpsUtils.getExpire(key) <= 0) {
+ log.debug("The drone is already offline.");
+ return true;
+ }
+ DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(key);
// Cancel drone-related subscriptions.
this.unsubscribeTopicOffline(deviceSn);
payloadService.deletePayloadsByDeviceSn(new ArrayList<>(List.of(deviceSn)));
- // If no information about this gateway device exists in the database, the drone is considered to be offline.
- String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
- if (!redisOps.checkExist(key) || redisOps.getExpire(key) <= 0) {
- log.debug("The drone is already offline.");
- return true;
- }
- DeviceDTO device = (DeviceDTO) redisOps.get(key);
// Publish the latest device topology information in the current workspace.
this.pushDeviceOfflineTopo(device.getWorkspaceId(), deviceSn);
- redisOps.del(key);
+ RedisOpsUtils.del(key);
+ RedisOpsUtils.del(RedisConst.OSD_PREFIX + device.getDeviceSn());
+ RedisOpsUtils.del(RedisConst.HMS_PREFIX + device.getDeviceSn());
log.debug("{} offline.", deviceSn);
return true;
}
@@ -164,12 +159,11 @@
String deviceSn = deviceGateway.getSubDevices().get(0).getSn();
String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
// change log: Use redis instead of
- long time = redisOps.getExpire(key);
- long now = System.currentTimeMillis();
+ long time = RedisOpsUtils.getExpire(key);
+ long gatewayTime = RedisOpsUtils.getExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn());
- if (time > 0) {
- redisOps.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + deviceGateway.getSn(), RedisConst.DEVICE_ALIVE_SECOND);
- redisOps.expireKey(key, RedisConst.DEVICE_ALIVE_SECOND);
+ if (time > 0 && gatewayTime > 0) {
+ RedisOpsUtils.expireKey(key, RedisConst.DEVICE_ALIVE_SECOND);
DeviceDTO device = DeviceDTO.builder().loginTime(LocalDateTime.now()).deviceSn(deviceSn).build();
DeviceDTO gateway = DeviceDTO.builder()
.loginTime(LocalDateTime.now())
@@ -177,7 +171,7 @@
.childDeviceSn(deviceSn).build();
this.updateDevice(gateway);
this.updateDevice(device);
- String workspaceId = ((DeviceDTO)(redisOps.get(key))).getWorkspaceId();
+ String workspaceId = ((DeviceDTO)(RedisOpsUtils.get(key))).getWorkspaceId();
if (StringUtils.hasText(workspaceId)) {
this.subscribeTopicOnline(deviceSn);
this.subscribeTopicOnline(deviceGateway.getSn());
@@ -190,69 +184,44 @@
DeviceQueryParam.builder()
.childSn(deviceSn)
.build());
- gatewaysList.stream().filter(
- gateway -> !gateway.getDeviceSn().equals(deviceGateway.getSn()))
+ gatewaysList.stream()
+ .filter(gateway -> !gateway.getDeviceSn().equals(deviceGateway.getSn()))
.findAny()
.ifPresent(gateway -> {
gateway.setChildDeviceSn("");
this.updateDevice(gateway);
});
-
DeviceEntity gateway = deviceGatewayConvertToDeviceEntity(deviceGateway);
- gateway.setChildSn(deviceSn);
- // Set the icon of the gateway device displayed in the pilot's map, required in the TSA module.
- gateway.setUrlNormal(IconUrlEnum.NORMAL_PERSON.getUrl());
- // Set the icon of the gateway device displayed in the pilot's map when it is selected, required in the TSA module.
- gateway.setUrlSelect(IconUrlEnum.SELECT_PERSON.getUrl());
- gateway.setLoginTime(now);
+ Optional<DeviceEntity> gatewayEntityOpt = onlineSaveDevice(gateway, deviceSn);
+ if (gatewayEntityOpt.isEmpty()) {
+ log.error("Failed to go online, please check the status data or code logic.");
+ return false;
+ }
DeviceEntity subDevice = subDeviceConvertToDeviceEntity(deviceGateway.getSubDevices().get(0));
- // Set the icon of the drone device displayed in the pilot's map when it is selected, required in the TSA module.
- subDevice.setUrlNormal(IconUrlEnum.NORMAL_EQUIPMENT.getUrl());
- // Set the icon of the drone device displayed in the pilot's map, required in the TSA module.
- subDevice.setUrlSelect(IconUrlEnum.SELECT_EQUIPMENT.getUrl());
- subDevice.setLoginTime(now);
+ Optional<DeviceEntity> subDeviceEntityOpt = onlineSaveDevice(subDevice, null);
+ if (subDeviceEntityOpt.isEmpty()) {
+ log.error("Failed to go online, please check the status data or code logic.");
+ return false;
+ }
+
+ subDevice = subDeviceEntityOpt.get();
+ gateway = gatewayEntityOpt.get();
// dock go online
- if (deviceGateway.getDomain() != null && DeviceDomainEnum.DOCK.getVal() == deviceGateway.getDomain()) {
- Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(deviceGateway.getSn());
- if (deviceOpt.isEmpty()) {
- log.info("The dock is not bound and cannot go online.");
- return false;
- }
- gateway.setNickname(null);
- subDevice.setNickname(null);
+ if (DeviceDomainEnum.DOCK.getVal() == deviceGateway.getDomain() && !subDevice.getBoundStatus()) {
+ // Directly bind the drone of the dock to the same workspace as the dock.
+ bindDevice(DeviceDTO.builder().deviceSn(deviceSn).workspaceId(gateway.getWorkspaceId()).build());
+ subDevice.setWorkspaceId(gateway.getWorkspaceId());
}
- Optional<DeviceEntity> gatewayOpt = this.saveDevice(gateway);
- String workspaceId = this.saveDevice(subDevice).orElse(subDevice).getWorkspaceId();
-
- redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + deviceSn,
- DeviceDTO.builder()
- .deviceSn(deviceSn)
- .domain(DeviceDomainEnum.SUB_DEVICE.getDesc())
- .workspaceId(workspaceId)
- .build(),
- RedisConst.DEVICE_ALIVE_SECOND);
- redisOps.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn(),
- DeviceDTO.builder()
- .deviceSn(gateway.getDeviceSn())
- .workspaceId(gatewayOpt.orElse(gateway).getWorkspaceId())
- .childDeviceSn(deviceSn)
- .domain(deviceGateway.getDomain() != null ?
- DeviceDomainEnum.getDesc(deviceGateway.getDomain()) :
- DeviceDomainEnum.GATEWAY.getDesc())
- .build(),
- RedisConst.DEVICE_ALIVE_SECOND);
- log.debug("{} online.", subDevice.getDeviceSn());
-
- if (StringUtils.hasText(workspaceId)) {
- this.pushDeviceOnlineTopo(workspaceId, deviceGateway.getSn(), deviceSn);
- }
// Subscribe to topic related to drone devices.
- this.subscribeTopicOnline(deviceSn);
this.subscribeTopicOnline(deviceGateway.getSn());
+ this.subscribeTopicOnline(deviceSn);
+ this.pushDeviceOnlineTopo(subDevice.getWorkspaceId(), deviceGateway.getSn(), deviceSn);
+
+ log.debug("{} online.", subDevice.getDeviceSn());
return true;
}
@@ -265,20 +234,14 @@
return;
}
}
- topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + OSD_SUF);
- topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + STATE_SUF);
- topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + SERVICES_SUF + _REPLY_SUF);
- topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + REQUESTS_SUF);
- topicService.subscribe(THING_MODEL_PRE + PRODUCT + sn + EVENTS_SUF);
+ String prefix = THING_MODEL_PRE + PRODUCT + sn;
+ INIT_TOPICS_SUFFIX.forEach(suffix -> topicService.subscribe(prefix + suffix));
}
@Override
public void unsubscribeTopicOffline(String sn) {
- topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + OSD_SUF);
- topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + STATE_SUF);
- topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + SERVICES_SUF + _REPLY_SUF);
- topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + REQUESTS_SUF);
- topicService.unsubscribe(THING_MODEL_PRE + PRODUCT + sn + EVENTS_SUF);
+ String prefix = THING_MODEL_PRE + PRODUCT + sn;
+ INIT_TOPICS_SUFFIX.forEach(suffix -> topicService.unsubscribe(prefix + suffix));
}
@Override
@@ -340,38 +303,40 @@
List<DeviceDTO> devicesList = this.getDevicesByParams(
DeviceQueryParam.builder()
.workspaceId(workspaceId)
- .domains(List.of(DeviceDomainEnum.SUB_DEVICE.getVal()))
+ .domains(List.of(DeviceDomainEnum.GATEWAY.getVal(), DeviceDomainEnum.DOCK.getVal()))
.build());
- devicesList.forEach(device -> {
- this.spliceDeviceTopo(device);
- device.setWorkspaceId(workspaceId);
- device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
- });
+ devicesList.stream()
+ .filter(gateway -> DeviceDomainEnum.DOCK.getVal() == gateway.getDomain() ||
+ RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn()))
+ .forEach(this::spliceDeviceTopo);
+
return devicesList;
}
@Override
- public void spliceDeviceTopo(DeviceDTO device) {
+ public void spliceDeviceTopo(DeviceDTO gateway) {
- // remote controller
- List<DeviceDTO> gatewaysList = getDevicesByParams(
- DeviceQueryParam.builder()
- .childSn(device.getDeviceSn())
- .build());
+ gateway.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + gateway.getDeviceSn()));
+
+ // sub device
+ if (!StringUtils.hasText(gateway.getChildDeviceSn())) {
+ return;
+ }
+
+ DeviceDTO subDevice = getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()).get(0);
+ subDevice.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + subDevice.getDeviceSn()));
+ gateway.setChildren(subDevice);
// payloads
- List<DevicePayloadDTO> payloadsList = payloadService
- .getDevicePayloadEntitiesByDeviceSn(device.getDeviceSn());
-
-
- device.setGatewaysList(gatewaysList);
- device.setPayloadsList(payloadsList);
-
+ subDevice.setPayloadsList(payloadService.getDevicePayloadEntitiesByDeviceSn(gateway.getChildDeviceSn()));
}
@Override
public Optional<TopologyDeviceDTO> getDeviceTopoForPilot(String sn) {
+ if (sn.isBlank()) {
+ return Optional.empty();
+ }
List<TopologyDeviceDTO> topologyDeviceList = this.getDevicesByParams(
DeviceQueryParam.builder()
.deviceSn(sn)
@@ -397,7 +362,7 @@
this.getDeviceTopoForPilot(sn)
.ifPresent(pilotMessage::setData);
- boolean exist = redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn);
+ boolean exist = RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn);
pilotMessage.getData().setOnlineStatus(exist);
pilotMessage.getData().setGatewaySn(gatewaySn.equals(sn) ? "" : gatewaySn);
@@ -409,24 +374,20 @@
TopologyDeviceDTO.TopologyDeviceDTOBuilder builder = TopologyDeviceDTO.builder();
if (device != null) {
- int domain = DeviceDomainEnum.getVal(device.getDomain());
- String subType = String.valueOf(device.getSubType());
- String type = String.valueOf(device.getType());
-
builder.sn(device.getDeviceSn())
.deviceCallsign(device.getNickname())
.deviceModel(DeviceModelDTO.builder()
- .domain(String.valueOf(domain))
- .subType(subType)
- .type(type)
- .key(domain + "-" + type + "-" + subType)
+ .domain(String.valueOf(device.getDomain()))
+ .subType(String.valueOf(device.getSubType()))
+ .type(String.valueOf(device.getType()))
+ .key(device.getDomain() + "-" + device.getType() + "-" + device.getSubType())
.build())
.iconUrls(device.getIconUrl())
- .onlineStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
+ .onlineStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()))
.boundStatus(device.getBoundStatus())
.model(device.getDeviceName())
.userId(device.getUserId())
- .domain(DeviceDomainEnum.getDesc(domain))
+ .domain(device.getDomain())
.build();
}
return builder.build();
@@ -457,19 +418,33 @@
}
@Override
- public void handleOSD(String topic, byte[] payload) {
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_OSD)
+ public void handleOSD(Message<?> message) {
+ String topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString();
+ byte[] payload = (byte[])message.getPayload();
CommonTopicReceiver receiver;
try {
String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(),
topic.indexOf(OSD_SUF));
// Real-time update of device status in memory
- redisOps.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + from, RedisConst.DEVICE_ALIVE_SECOND);
+ RedisOpsUtils.expireKey(RedisConst.DEVICE_ONLINE_PREFIX + from, RedisConst.DEVICE_ALIVE_SECOND);
- DeviceDTO device = (DeviceDTO) redisOps.get(RedisConst.DEVICE_ONLINE_PREFIX + from);
+ DeviceDTO device = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + from);
- if (device == null || !StringUtils.hasText(device.getWorkspaceId())) {
- return;
+ if (device == null) {
+ Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(from);
+ if (deviceOpt.isEmpty()) {
+ return;
+ }
+ device = deviceOpt.get();
+ if (!StringUtils.hasText(device.getWorkspaceId())) {
+ this.unsubscribeTopicOffline(from);
+ return;
+ }
+ RedisOpsUtils.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + from, device,
+ RedisConst.DEVICE_ALIVE_SECOND);
+ this.subscribeTopicOnline(from);
}
receiver = objectMapper.readValue(payload, CommonTopicReceiver.class);
@@ -536,6 +511,9 @@
.eq(DeviceEntity::getDeviceSn, entity.getDeviceSn()));
// Update the information directly if the device already exists.
if (deviceEntity != null) {
+ if (deviceEntity.getDeviceName().equals(entity.getNickname())) {
+ entity.setNickname(null);
+ }
entity.setId(deviceEntity.getId());
mapper.updateById(entity);
return Optional.of(deviceEntity);
@@ -556,7 +534,9 @@
// Query the model information of this gateway device.
Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService
- .getOneDictionaryInfoByTypeSubType(gateway.getType(), gateway.getSubType());
+ .getOneDictionaryInfoByTypeSubType(Objects.nonNull(gateway.getDomain()) ?
+ gateway.getDomain() : DeviceDomainEnum.GATEWAY.getVal(),
+ gateway.getType(), gateway.getSubType());
dictionaryOpt.ifPresent(entity ->
builder.deviceName(entity.getDeviceName())
@@ -586,7 +566,7 @@
// Query the model information of this drone device.
Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService
- .getOneDictionaryInfoByTypeSubType(device.getType(), device.getSubType());
+ .getOneDictionaryInfoByTypeSubType(DeviceDomainEnum.SUB_DEVICE.getVal(), device.getType(), device.getSubType());
dictionaryOpt.ifPresent(dictionary ->
builder.deviceName(dictionary.getDeviceName())
@@ -599,8 +579,7 @@
.subType(device.getSubType())
.version(device.getVersion())
.deviceIndex(device.getIndex())
- .domain(device.getDomain() != null ?
- device.getDomain() : DeviceDomainEnum.SUB_DEVICE.getVal())
+ .domain(DeviceDomainEnum.SUB_DEVICE.getVal())
.build();
}
@@ -613,7 +592,7 @@
if (entity == null) {
return null;
}
- return DeviceDTO.builder()
+ DeviceDTO.DeviceDTOBuilder deviceDTOBuilder = DeviceDTO.builder()
.deviceSn(entity.getDeviceSn())
.childDeviceSn(entity.getChildSn())
.deviceName(entity.getDeviceName())
@@ -622,7 +601,7 @@
.workspaceId(entity.getWorkspaceId())
.type(entity.getDeviceType())
.subType(entity.getSubType())
- .domain(DeviceDomainEnum.getDesc(entity.getDomain()))
+ .domain(entity.getDomain())
.iconUrl(IconUrlDTO.builder()
.normalUrl(entity.getUrlNormal())
.selectUrl(entity.getUrlSelect())
@@ -638,8 +617,31 @@
.firmwareVersion(entity.getFirmwareVersion())
.workspaceName(entity.getWorkspaceId() != null ?
workspaceService.getWorkspaceByWorkspaceId(entity.getWorkspaceId())
- .map(WorkspaceDTO::getWorkspaceName).orElse("") : "")
- .build();
+ .map(WorkspaceDTO::getWorkspaceName).orElse("") : "");
+
+ if (!StringUtils.hasText(entity.getFirmwareVersion())) {
+ return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build();
+ }
+ // Query whether the device is updating firmware.
+ Object progress = RedisOpsUtils.get(RedisConst.FIRMWARE_UPGRADING_PREFIX + entity.getDeviceSn());
+ if (Objects.nonNull(progress)) {
+ return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.UPGRADING.getVal()).firmwareProgress((int)progress).build();
+ }
+
+ // First query the latest firmware version of the device model and compare it with the current firmware version
+ // to see if it needs to be upgraded.
+ Optional<DeviceFirmwareNoteDTO> firmwareReleaseNoteOpt = deviceFirmwareService.getLatestFirmwareReleaseNote(entity.getDeviceName());
+ if (firmwareReleaseNoteOpt.isPresent()) {
+ DeviceFirmwareNoteDTO firmwareNoteDTO = firmwareReleaseNoteOpt.get();
+ if (firmwareNoteDTO.getProductVersion().equals(entity.getFirmwareVersion())) {
+ return deviceDTOBuilder.firmwareStatus(entity.getCompatibleStatus() ?
+ DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal() :
+ DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE.getVal()).build();
+ }
+
+ return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NORMAL_UPGRADE.getVal()).build();
+ }
+ return deviceDTOBuilder.firmwareStatus(DeviceFirmwareStatusEnum.NOT_UPGRADE.getVal()).build();
}
@Override
@@ -655,23 +657,24 @@
device.setBoundTime(LocalDateTime.now());
boolean isUpd = this.saveDevice(this.deviceDTO2Entity(device)).isPresent();
- if (DeviceDomainEnum.DOCK.getDesc().equals(device.getDomain())) {
- return isUpd;
- }
if (!isUpd) {
return false;
}
String key = RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn();
- DeviceDTO redisDevice = (DeviceDTO)redisOps.get(key);
- redisDevice.setWorkspaceId(device.getWorkspaceId());
- redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
+ if (!RedisOpsUtils.checkExist(key)) {
+ return false;
+ }
- if (DeviceDomainEnum.GATEWAY.getDesc().equals(redisDevice.getDomain())) {
+ DeviceDTO redisDevice = (DeviceDTO)RedisOpsUtils.get(key);
+ redisDevice.setWorkspaceId(device.getWorkspaceId());
+ RedisOpsUtils.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
+
+ if (DeviceDomainEnum.GATEWAY.getVal() == redisDevice.getDomain()) {
this.pushDeviceOnlineTopo(webSocketManageService.getValueWithWorkspace(device.getWorkspaceId()),
device.getDeviceSn(), device.getDeviceSn());
}
- if (DeviceDomainEnum.SUB_DEVICE.getDesc().equals(redisDevice.getDomain())) {
+ if (DeviceDomainEnum.SUB_DEVICE.getVal() == redisDevice.getDomain()) {
DeviceDTO subDevice = this.getDevicesByParams(DeviceQueryParam.builder()
.childSn(device.getChildDeviceSn())
.build()).get(0);
@@ -732,8 +735,8 @@
assert dock != null;
- Optional<DeviceEntity> dockEntityOpt = this.bindDevice2Entity(dock);
- Optional<DeviceEntity> droneEntityOpt = this.bindDevice2Entity(drone);
+ Optional<DeviceEntity> dockEntityOpt = this.bindDevice2Entity(DeviceDomainEnum.DOCK.getVal(), dock);
+ Optional<DeviceEntity> droneEntityOpt = this.bindDevice2Entity(DeviceDomainEnum.SUB_DEVICE.getVal(), drone);
List<ErrorInfoReply> bindResult = new ArrayList<>();
@@ -768,21 +771,21 @@
@Override
public PaginationData<DeviceDTO> getBoundDevicesWithDomain(String workspaceId, Long page,
- Long pageSize, String domain) {
+ Long pageSize, Integer domain) {
Page<DeviceEntity> pagination = mapper.selectPage(new Page<>(page, pageSize),
new LambdaQueryWrapper<DeviceEntity>()
- .eq(DeviceEntity::getDomain, DeviceDomainEnum.getVal(domain))
+ .eq(DeviceEntity::getDomain, domain)
.eq(DeviceEntity::getWorkspaceId, workspaceId)
.eq(DeviceEntity::getBoundStatus, true));
List<DeviceDTO> devicesList = pagination.getRecords().stream().map(this::deviceEntityConvertToDTO)
.peek(device -> {
- device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
+ device.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn()));
if (StringUtils.hasText(device.getChildDeviceSn())) {
Optional<DeviceDTO> childOpt = this.getDeviceBySn(device.getChildDeviceSn());
childOpt.ifPresent(child -> {
child.setStatus(
- redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + child.getDeviceSn()));
+ RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + child.getDeviceSn()));
child.setWorkspaceName(device.getWorkspaceName());
device.setChildren(child);
});
@@ -795,9 +798,9 @@
@Override
public void unbindDevice(String deviceSn) {
String key = RedisConst.DEVICE_ONLINE_PREFIX + deviceSn;
- DeviceDTO redisDevice = (DeviceDTO) redisOps.get(key);
+ DeviceDTO redisDevice = (DeviceDTO) RedisOpsUtils.get(key);
redisDevice.setWorkspaceId("");
- redisOps.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
+ RedisOpsUtils.setWithExpire(key, redisDevice, RedisConst.DEVICE_ALIVE_SECOND);
DeviceDTO device = DeviceDTO.builder()
.deviceSn(deviceSn)
@@ -815,20 +818,138 @@
return Optional.empty();
}
DeviceDTO device = devicesList.get(0);
- device.setStatus(redisOps.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn));
+ device.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + sn));
return Optional.of(device);
}
@Override
+ @ServiceActivator(inputChannel = ChannelName.INBOUND_STATE_FIRMWARE_VERSION)
public void updateFirmwareVersion(FirmwareVersionReceiver receiver) {
+ // If the reported version is empty, it will not be processed to prevent misleading page.
+ if (!StringUtils.hasText(receiver.getFirmwareVersion())) {
+ return;
+ }
+
if (receiver.getDomain() == DeviceDomainEnum.SUB_DEVICE) {
- this.updateDevice(DeviceDTO.builder()
+ final DeviceDTO device = DeviceDTO.builder()
.deviceSn(receiver.getSn())
.firmwareVersion(receiver.getFirmwareVersion())
- .build());
+ .firmwareStatus(receiver.getCompatibleStatus() == null ?
+ null : DeviceFirmwareStatusEnum.CompatibleStatusEnum.INCONSISTENT.getVal() != receiver.getCompatibleStatus() ?
+ DeviceFirmwareStatusEnum.UNKNOWN.getVal() : DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE.getVal())
+ .build();
+ this.updateDevice(device);
return;
}
payloadService.updateFirmwareVersion(receiver);
+ }
+
+ @Override
+ public ResponseResult createDeviceOtaJob(String workspaceId, List<DeviceFirmwareUpgradeDTO> upgradeDTOS) {
+ List<DeviceOtaCreateParam> deviceOtaFirmwares = deviceFirmwareService.getDeviceOtaFirmware(workspaceId, upgradeDTOS);
+ if (deviceOtaFirmwares.isEmpty()) {
+ return ResponseResult.error();
+ }
+
+ DeviceOtaCreateParam deviceOtaFirmware = deviceOtaFirmwares.get(0);
+ List<DeviceDTO> devices = getDevicesByParams(DeviceQueryParam.builder().childSn(deviceOtaFirmware.getSn()).build());
+ String gatewaySn = devices.isEmpty() ? deviceOtaFirmware.getSn() : devices.get(0).getDeviceSn();
+
+ String topic = THING_MODEL_PRE + PRODUCT + gatewaySn + SERVICES_SUF;
+
+ // The bids in the progress messages reported subsequently are the same.
+ String bid = UUID.randomUUID().toString();
+ ServiceReply serviceReply = messageSender.publishWithReply(
+ topic, CommonTopicResponse.<Map<String, List<DeviceOtaCreateParam>>>builder()
+ .tid(UUID.randomUUID().toString())
+ .bid(bid)
+ .timestamp(System.currentTimeMillis())
+ .method(FirmwareMethodEnum.OTA_CREATE.getMethod())
+ .data(Map.of(MapKeyConst.DEVICES, deviceOtaFirmwares))
+ .build());
+ if (serviceReply.getResult() != ResponseResult.CODE_SUCCESS) {
+ return ResponseResult.error(serviceReply.getResult(), "Firmware Error Code: " + serviceReply.getResult());
+ }
+
+ // Record the device state that needs to be updated.
+ deviceOtaFirmwares.forEach(deviceOta -> RedisOpsUtils.setWithExpire(
+ RedisConst.FIRMWARE_UPGRADING_PREFIX + deviceOta.getSn(),
+ bid,
+ RedisConst.DEVICE_ALIVE_SECOND * RedisConst.DEVICE_ALIVE_SECOND));
+ return ResponseResult.success();
+ }
+
+ @Override
+ public void devicePropertySet(String workspaceId, String dockSn, DeviceSetPropertyEnum propertyEnum, JsonNode param) {
+ boolean dockOnline = this.checkDeviceOnline(dockSn);
+ if (!dockOnline) {
+ throw new RuntimeException("Dock is offline.");
+ }
+ DeviceDTO deviceDTO = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + dockSn);
+ boolean deviceOnline = this.checkDeviceOnline(deviceDTO.getChildDeviceSn());
+ if (!deviceOnline) {
+ throw new RuntimeException("Device is offline.");
+ }
+
+ // Make sure the data is valid.
+ BasicDeviceProperty basicDeviceProperty = objectMapper.convertValue(param, propertyEnum.getClazz());
+ boolean valid = basicDeviceProperty.valid();
+ if (!valid) {
+ throw new IllegalArgumentException(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg());
+ }
+
+ String topic = THING_MODEL_PRE + PRODUCT + dockSn + PROPERTY_SUF + SET_SUF;
+ OsdSubDeviceReceiver osd = (OsdSubDeviceReceiver) RedisOpsUtils.get(RedisConst.OSD_PREFIX + deviceDTO.getChildDeviceSn());
+ if (!param.isObject()) {
+ this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), param));
+ return;
+ }
+ // If there are multiple parameters, set them separately.
+ for (Iterator<Map.Entry<String, JsonNode>> filed = param.fields(); filed.hasNext(); ) {
+ Map.Entry<String, JsonNode> node = filed.next();
+ boolean isPublish = basicDeviceProperty.canPublish(node.getKey(), osd);
+ if (!isPublish) {
+ continue;
+ }
+ this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), node));
+ }
+
+ }
+
+ @Override
+ public void deviceOnePropertySet(String topic, DeviceSetPropertyEnum propertyEnum, Map.Entry<String, Object> value) {
+ if (Objects.isNull(value) || Objects.isNull(value.getValue())) {
+ throw new IllegalArgumentException(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg());
+ }
+
+ Map reply = messageSender.publishWithReply(
+ Map.class, topic,
+ CommonTopicResponse.builder()
+ .bid(UUID.randomUUID().toString())
+ .tid(UUID.randomUUID().toString())
+ .timestamp(System.currentTimeMillis())
+ .data(value)
+ .build(),
+ 2);
+
+ while (true) {
+ reply = (Map<String, Object>) reply.get(value.getKey());
+ if (value.getValue() instanceof JsonNode) {
+ break;
+ }
+ value = (Map.Entry) value.getValue();
+ }
+
+ SetReply setReply = objectMapper.convertValue(reply, SetReply.class);
+ if (SetReplyStatusResultEnum.SUCCESS.getVal() != setReply.getResult()) {
+ throw new RuntimeException("Failed to set " + value.getKey() + "; Error Code: " + setReply.getResult());
+ }
+
+ }
+
+ public Boolean checkDeviceOnline(String sn) {
+ String key = RedisConst.DEVICE_ONLINE_PREFIX + sn;
+ return RedisOpsUtils.checkExist(key) && RedisOpsUtils.getExpire(key) > 0;
}
/**
@@ -852,22 +973,26 @@
.boundTime(dto.getBoundTime() != null ?
dto.getBoundTime().atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() : null)
.childSn(dto.getChildDeviceSn())
- .domain(StringUtils.hasText(dto.getDomain()) ? DeviceDomainEnum.getVal(dto.getDomain()) : null)
+ .domain(dto.getDomain())
.firmwareVersion(dto.getFirmwareVersion())
+ .compatibleStatus(dto.getFirmwareStatus() == null ? null :
+ DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE != DeviceFirmwareStatusEnum.find(dto.getFirmwareStatus()))
.build();
}
/**
* Convert device binding data object into database entity object.
+ *
+ * @param domain
* @param receiver
* @return
*/
- private Optional<DeviceEntity> bindDevice2Entity(BindDeviceReceiver receiver) {
+ private Optional<DeviceEntity> bindDevice2Entity(Integer domain, BindDeviceReceiver receiver) {
if (receiver == null) {
return Optional.empty();
}
int[] droneKey = Arrays.stream(receiver.getDeviceModelKey().split("-")).mapToInt(Integer::parseInt).toArray();
- Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService.getOneDictionaryInfoByTypeSubType(droneKey[1], droneKey[2]);
+ Optional<DeviceDictionaryDTO> dictionaryOpt = dictionaryService.getOneDictionaryInfoByTypeSubType(domain, droneKey[1], droneKey[2]);
DeviceEntity.DeviceEntityBuilder builder = DeviceEntity.builder();
dictionaryOpt.ifPresent(entity ->
@@ -912,4 +1037,42 @@
.organizationName(device.getWorkspaceName())
.build();
}
+
+ private Optional<DeviceEntity> onlineSaveDevice(DeviceEntity device, String childSn) {
+
+ Optional<DeviceDTO> deviceOpt = this.getDeviceBySn(device.getDeviceSn());
+ if (deviceOpt.isEmpty()) {
+ // Set the icon of the gateway device displayed in the pilot's map, required in the TSA module.
+ device.setUrlNormal(IconUrlEnum.NORMAL_PERSON.getUrl());
+ // Set the icon of the gateway device displayed in the pilot's map when it is selected, required in the TSA module.
+ device.setUrlSelect(IconUrlEnum.SELECT_PERSON.getUrl());
+ device.setBoundStatus(false);
+ } else {
+ DeviceDTO oldDevice = deviceOpt.get();
+ device.setNickname(oldDevice.getNickname());
+ device.setBoundStatus(oldDevice.getBoundStatus());
+ }
+
+ device.setChildSn(childSn);
+ device.setLoginTime(System.currentTimeMillis());
+
+ Optional<DeviceEntity> saveDeviceOpt = this.saveDevice(device);
+ if (saveDeviceOpt.isEmpty()) {
+ return saveDeviceOpt;
+ }
+ device.setWorkspaceId(saveDeviceOpt.get().getWorkspaceId());
+
+ RedisOpsUtils.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(),
+ DeviceDTO.builder()
+ .deviceSn(device.getDeviceSn())
+ .workspaceId(device.getWorkspaceId())
+ .childDeviceSn(childSn)
+ .domain(device.getDomain())
+ .type(device.getDeviceType())
+ .subType(device.getSubType())
+ .build(),
+ RedisConst.DEVICE_ALIVE_SECOND);
+
+ return saveDeviceOpt;
+ }
}
\ No newline at end of file
--
Gitblit v1.9.3