| | |
| | | package com.ard.sample.manage.service.impl; |
| | | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ard.common.core.domain.model.LoginUser; |
| | | import com.ard.common.utils.SecurityUtils; |
| | | import com.ard.device.camera.domain.ArdCamera; |
| | | import com.ard.device.camera.service.IArdCameraService; |
| | | import com.ard.device.channel.domain.ArdChannel; |
| | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.apache.poi.ss.formula.functions.T; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.beans.factory.annotation.Qualifier; |
| | | import org.springframework.dao.DuplicateKeyException; |
| | | import org.springframework.integration.annotation.ServiceActivator; |
| | | import org.springframework.integration.mqtt.support.MqttHeaders; |
| | | import org.springframework.messaging.Message; |
| | |
| | | @Resource |
| | | private AuthorizeService authorizeService; |
| | | |
| | | // 机场1:OSD 按机型分发(原为 @Qualifier("gatewayOSDServiceImpl") ITSAService tsaService,直连 dock2 链头) |
| | | @Autowired |
| | | @Qualifier("gatewayOSDServiceImpl") |
| | | private ITSAService tsaService; |
| | | private DockOsdDispatcher dockOsdDispatcher; |
| | | |
| | | @Resource |
| | | private ISysDeptService sysDeptService; |
| | |
| | | return; |
| | | } |
| | | |
| | | DeviceDTO subDevice = |
| | | getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()).get(0); |
| | | List<DeviceDTO> subDevices = |
| | | getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()); |
| | | if (CollectionUtils.isEmpty(subDevices)) { |
| | | log.warn("网关 {} 的子设备 {} 不存在,跳过拓扑拼接", gateway.getDeviceSn(), gateway.getChildDeviceSn()); |
| | | return; |
| | | } |
| | | DeviceDTO subDevice = subDevices.get(0); |
| | | subDevice.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + subDevice.getDeviceSn())); |
| | | gateway.setChildren(subDevice); |
| | | |
| | |
| | | //region 单独写一个方法做权限验证,由于有好多定时任务也在实时获取设备列表,原方法不适用再添加权限注解 |
| | | @Override |
| | | public List<DeviceDTO> getDockList(String nickname) { |
| | | LoginUser loginUser = SecurityUtils.getLoginUser(); |
| | | List<DeviceDTO> devicesList = this.getDockListByParams( |
| | | DeviceQueryParam.builder() |
| | | .domains(List.of(DeviceDomainEnum.GATEWAY.getVal(), DeviceDomainEnum.DOCK.getVal())) |
| | |
| | | .build()); |
| | | // 在獲取设备列表时,顺便获取直播地址 |
| | | for(DeviceDTO devices : devicesList){ |
| | | _liveStreamHandler.StartLiveStreaming(devices.getDeviceSn()); |
| | | _liveStreamHandler.StartLiveStreaming(devices.getChildDeviceSn()); |
| | | // 暂时注释掉机场设备视频直址 2026-04-01 |
| | | // _liveStreamHandler.StartLiveStreaming(devices.getDeviceSn(), loginUser.getUserId().toString()); |
| | | // _liveStreamHandler.StartLiveStreaming(devices.getChildDeviceSn(), loginUser.getUserId().toString()); |
| | | ArdCamera ardCamera = new ArdCamera(); |
| | | ardCamera.setDockId(devices.getId()); |
| | | List<ArdCamera> ardCameraList = _cameraService.selectArdCameraList(ardCamera); |
| | |
| | | if (!StringUtils.hasText(gateway.getChildDeviceSn())) { |
| | | return; |
| | | } |
| | | DeviceDTO subDevice = |
| | | getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()).get(0); |
| | | List<DeviceDTO> subDevices = |
| | | getDevicesByParams(DeviceQueryParam.builder().deviceSn(gateway.getChildDeviceSn()).build()); |
| | | if (CollectionUtils.isEmpty(subDevices)) { |
| | | log.warn("网关 {} 的子设备 {} 不存在,跳过拓扑拼接", gateway.getDeviceSn(), gateway.getChildDeviceSn()); |
| | | return; |
| | | } |
| | | DeviceDTO subDevice = subDevices.get(0); |
| | | subDevice.setStatus(RedisOpsUtils.checkExist(RedisConst.DEVICE_ONLINE_PREFIX + subDevice.getDeviceSn())); |
| | | gateway.setChildren(subDevice); |
| | | } |
| | |
| | | }) |
| | | .eq(param.getBoundStatus() != null, DeviceEntity::getBoundStatus, |
| | | param.getBoundStatus()) |
| | | .like(param.getNickname()!=null, DeviceEntity::getNickname, "%" + param.getNickname() + "%") |
| | | .like(StringUtils.hasText(param.getNickname()), DeviceEntity::getNickname, "%" + param.getNickname() + "%") |
| | | .orderBy(param.isOrderBy(), |
| | | param.isAsc(), DeviceEntity::getId)) |
| | | .stream() |
| | |
| | | .getValueAndUserType(UserTypeEnum.WEB.getVal()); |
| | | |
| | | |
| | | tsaService.handleOSD(receiver, device, webSessions, wsMessage); |
| | | // 机场1:OSD 按机型分发(dock1=67 → dock1 链;其余透传 dock2 原链) |
| | | dockOsdDispatcher.dispatch(receiver, device, webSessions, wsMessage); |
| | | |
| | | } catch (NullPointerException e) { |
| | | log.error("处理OSD消息NPE,headers={}, payload={}", |
| | |
| | | } |
| | | // 调用验证方法 |
| | | |
| | | return mapper.insert(entity) > 0 ? Optional.of(entity) : Optional.empty(); |
| | | try { |
| | | return mapper.insert(entity) > 0 ? Optional.of(entity) : Optional.empty(); |
| | | } catch (DuplicateKeyException e) { |
| | | // 机场首次上线时 MQTT QoS1 可能重复投递 update_topo(或多线程并发), |
| | | // 两个线程同时查到“设备不存在”后会并发 insert,后插入者触发唯一键冲突。 |
| | | // 此时数据已被另一线程写入,退化为更新即可,避免整条状态消息处理失败。 |
| | | DeviceEntity exist = mapper.selectOne( |
| | | new LambdaQueryWrapper<DeviceEntity>() |
| | | .eq(DeviceEntity::getDeviceSn, entity.getDeviceSn())); |
| | | if (exist == null) { |
| | | throw e; |
| | | } |
| | | entity.setId(exist.getId()); |
| | | mapper.updateById(entity); |
| | | return Optional.of(exist); |
| | | } |
| | | } |
| | | |
| | | /** |
| | |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | /** |
| | | * 属性设置 |
| | | * */ |
| | | @Override |
| | | public void devicePropertySet(String dockSn, DeviceSetPropertyEnum propertyEnum, JsonNode param) { |
| | | public ResponseResult devicePropertySet(String dockSn, DeviceSetPropertyEnum propertyEnum, JsonNode param) { |
| | | boolean dockOnline = this.checkDeviceOnline(dockSn); |
| | | if (!dockOnline) { |
| | | throw new RuntimeException(CommonErrorEnum.DEVICE_OFFLINE.getErrorMsg()); |
| | | return ResponseResult.error(CommonErrorEnum.DEVICE_OFFLINE.getErrorCode(),"机场" + CommonErrorEnum.DEVICE_OFFLINE.getErrorMsg()); |
| | | //throw new RuntimeException(CommonErrorEnum.DEVICE_OFFLINE.getErrorMsg()); |
| | | } |
| | | DeviceDTO deviceDTO = (DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + dockSn); |
| | | boolean deviceOnline = this.checkDeviceOnline(deviceDTO.getChildDeviceSn()); |
| | | if (!deviceOnline) { |
| | | throw new RuntimeException("Device is offline."); |
| | | return ResponseResult.error(2222,"无人机" + CommonErrorEnum.DEVICE_OFFLINE.getErrorMsg()); |
| | | //throw new RuntimeException("Device is offline."); |
| | | // CommonErrorEnum.DEVICE_OFFLINE.getErrorCode() |
| | | } |
| | | |
| | | // 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()); |
| | | return ResponseResult.error(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg()); |
| | | // throw new IllegalArgumentException(CommonErrorEnum.ILLEGAL_ARGUMENT.getErrorMsg()); |
| | | } |
| | | |
| | | String topic = THING_MODEL_PRE + PRODUCT + dockSn + PROPERTY_SUF + SET_SUF; |
| | |
| | | (OsdSubDeviceReceiver) RedisOpsUtils.get(RedisConst.OSD_PREFIX + deviceDTO.getChildDeviceSn()); |
| | | if (!param.isObject()) { |
| | | this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), param)); |
| | | return; |
| | | return ResponseResult.success(); |
| | | // return; |
| | | } |
| | | |
| | | if(param.size()==1){ |
| | | this.deviceOnePropertySetSilent(topic,propertyEnum,param); |
| | | return; |
| | | return ResponseResult.success(); |
| | | // return; |
| | | } |
| | | // if(Objects.equals(param.fieldNames().next(), "silent_mode")) |
| | | // { |
| | |
| | | |
| | | this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), node)); |
| | | } |
| | | |
| | | return ResponseResult.success(); |
| | | } |
| | | |
| | | /** |
| | |
| | | CommonTopicReceiver<Map<String,Integer>> stateReceiver = new CommonTopicReceiver<>(); |
| | | stateReceiver.setTid(UUID.randomUUID().toString()); |
| | | stateReceiver.setBid(UUID.randomUUID().toString()); |
| | | stateReceiver.setType(MessageType.LIVESTREAM.getType()); |
| | | stateReceiver.setType(MessageType.LIVESTATUS.getType()); |
| | | stateReceiver.setGateway(sn); |
| | | stateReceiver.setTimestamp(System.currentTimeMillis()); |
| | | Map<String,Integer> live_status = new HashMap<>(); |