| | |
| | | package com.ard.sample.manage.service.impl; |
| | | |
| | | import com.alibaba.fastjson2.JSONObject; |
| | | import com.ard.common.annotation.DataScope; |
| | | import com.ard.common.annotation.DataScopePlus; |
| | | import com.ard.sample.component.websocket.handler.LiveStreamHandler; |
| | | import com.ard.system.authorize.service.AuthorizeService; |
| | | import com.baomidou.mybatisplus.core.conditions.Wrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; |
| | | import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; |
| | |
| | | @Slf4j |
| | | @Transactional |
| | | public class DeviceServiceImpl implements IDeviceService { |
| | | |
| | | @Autowired |
| | | private LiveStreamHandler _liveStreamHandler; |
| | | |
| | | @Autowired |
| | | private IMessageSenderService messageSender; |
| | |
| | | // subDevice.setPayloadsList(payloadService.getDevicePayloadEntitiesByDeviceSn(gateway.getChildDeviceSn())); |
| | | } |
| | | |
| | | //region 单独写一个方法做权限验证,由于有好多定时任务也在实时获取设备列表,原方法不适用再添加权限注解 |
| | | @Override |
| | | public List<DeviceDTO> getDockList() { |
| | | 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()); |
| | | } |
| | | |
| | | devicesList.stream() |
| | | .filter(gateway -> DeviceDomainEnum.DOCK.getVal() == gateway.getDomain() || |
| | |
| | | |
| | | @Override |
| | | public void spliceDeviceTopoPer(DeviceDTO gateway) { |
| | | |
| | | 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 |
| | | // subDevice.setPayloadsList(payloadService.getDevicePayloadEntitiesByDeviceSn(gateway.getChildDeviceSn())); |
| | | } |
| | | |
| | | //@DataScope(deptAlias = "d") |
| | | |
| | | @Override |
| | | public List<DeviceDTO> getDockListByParams(DeviceQueryParam param){ |
| | | |
| | | // 在mapper中添加查询方法做权限验证 |
| | | return mapper.selectListPer( |
| | | new LambdaQueryWrapper<DeviceEntity>() |
| | | .eq(StringUtils.hasText(param.getDeviceSn()), |
| | |
| | | .map(this::deviceEntityConvertToDTO) |
| | | .collect(Collectors.toList()); |
| | | } |
| | | //endregion |
| | | |
| | | @Override |
| | | public Optional<TopologyDeviceDTO> getDeviceTopoForPilot(String sn) { |
| | |
| | | @Override |
| | | @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 topic = message.getHeaders().get(MqttHeaders.RECEIVED_TOPIC).toString(); |
| | | byte[] payload = (byte[]) message.getPayload(); |
| | | CommonTopicReceiver receiver; |
| | | String from = topic.substring((THING_MODEL_PRE + PRODUCT).length(), |
| | | topic.indexOf(OSD_SUF)); |
| | | |
| | |
| | | |
| | | tsaService.handleOSD(receiver, device, webSessions, wsMessage); |
| | | |
| | | } catch (IOException e) { |
| | | } catch (NullPointerException e) { |
| | | log.error("处理OSD消息NPE,headers={}, payload={}", |
| | | message.getHeaders(), message.getPayload(), e); // 打印完整栈 |
| | | } |
| | | catch (IOException e) { |
| | | log.error("处理OSD消息的IO异常:{}",e.getMessage(), e); |
| | | e.printStackTrace(); |
| | | } |
| | | } |
| | |
| | | // 验证授权数量 |
| | | validateAuthorization(devicesList.size(), 1); |
| | | } catch (Exception e) { |
| | | log.error("保存设备时验证授权异常,请联系管理员!错误信息:" + e.getMessage()); |
| | | return Optional.empty(); |
| | | } |
| | | // 调用验证方法 |
| | |
| | | .firmwareVersion(entity.getFirmwareVersion()) |
| | | .deptId(entity.getDeptId()) |
| | | .workType(entity.getWorkType()) |
| | | .webrtcUrl(entity.getWebrtcUrl()) |
| | | .workspaceName(entity.getDeptId() != null |
| | | ? Optional.ofNullable(sysDeptService.selectDeptById(entity.getDeptId())) |
| | | .map(SysDept::getDeptName) |
| | |
| | | // 只更新workType字段 |
| | | .set(DeviceEntity::getWorkType, workType); |
| | | // 执行更新(第一个参数传null,因为更新字段已通过wrapper的set指定) |
| | | int update = mapper.update(null, lambdaUpdateWrapper); |
| | | return update > 0; |
| | | } |
| | | |
| | | @Override |
| | | public Boolean updateWebrtcUrl(String sn, String webrtcUrl){ |
| | | LambdaUpdateWrapper<DeviceEntity> lambdaUpdateWrapper = new LambdaUpdateWrapper<>(); |
| | | lambdaUpdateWrapper.eq(DeviceEntity::getDeviceSn, sn) |
| | | .set(DeviceEntity::getWebrtcUrl, webrtcUrl); |
| | | int update = mapper.update(null, lambdaUpdateWrapper); |
| | | return update > 0; |
| | | } |
| | |
| | | BindDeviceReceiver dock = null; |
| | | BindDeviceReceiver drone = null; |
| | | for (BindDeviceReceiver device : devices) { |
| | | if(device.getDeviceModelKey().isEmpty()){ |
| | | continue; |
| | | } |
| | | int val = Integer.parseInt(device.getDeviceModelKey().split("-")[0]); |
| | | if (val == DeviceDomainEnum.DOCK.getVal()) { |
| | | dock = device; |
| | |
| | | this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), param)); |
| | | return; |
| | | } |
| | | |
| | | if(param.size()==1){ |
| | | this.deviceOnePropertySetSilent(topic,propertyEnum,param); |
| | | return; |
| | | } |
| | | // if(Objects.equals(param.fieldNames().next(), "silent_mode")) |
| | | // { |
| | | // this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), param.get("silent_mode"))); |
| | | // 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(); |
| | |
| | | if (!isPublish) { |
| | | continue; |
| | | } |
| | | |
| | | this.deviceOnePropertySet(topic, propertyEnum, Map.entry(propertyEnum.getProperty(), node)); |
| | | } |
| | | |
| | | } |
| | | |
| | | /** |
| | | * 为静音模式单独列出来一个方法,只有一个值的时候都可以调用,不限于静音模式 |
| | | * */ |
| | | @Override |
| | | public void deviceOnePropertySetSilent(String topic, DeviceSetPropertyEnum propertyEnum, |
| | | JsonNode 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); |
| | | } |
| | | |
| | | @Override |
| | | public void deviceOnePropertySet(String topic, DeviceSetPropertyEnum propertyEnum, |
| | | Map.Entry<String, Object> value) { |
| | | if (Objects.isNull(value) || Objects.isNull(value.getValue())) { |
| | |
| | | .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()); |
| | | } |
| | | // 接收返回信息在serviceReply中,订阅thing/product/7CTDLCE00A1UPE/property/set_reply上报的信息,此处不处理 |
| | | // 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 JsonNode getJsonNode(JsonNode jsonNode) { |
| | | // ObjectNode parentNode = objectMapper.createObjectNode(); |
| | | // parentNode.put("bid", UUID.randomUUID().toString()); |
| | | // parentNode.set("data", jsonNode); |
| | | // parentNode.put("tid", UUID.randomUUID().toString()); |
| | | // parentNode.put("timestamp", System.currentTimeMillis()); |
| | | // return parentNode; |
| | | // } |
| | | |
| | | @Override |
| | | public Boolean checkDeviceOnline(String sn) { |
| | |
| | | .domain(dto.getDomain()) |
| | | .firmwareVersion(dto.getFirmwareVersion()) |
| | | .workType(dto.getWorkType()) |
| | | .webrtcUrl(dto.getWebrtcUrl()) |
| | | .compatibleStatus(dto.getFirmwareStatus() == null ? null : |
| | | DeviceFirmwareStatusEnum.CONSISTENT_UPGRADE != DeviceFirmwareStatusEnum.find(dto.getFirmwareStatus())) |
| | | .build(); |
| | |
| | | .sn(device.getDeviceSn()) |
| | | .deviceCallsign(device.getNickname()) |
| | | .isDeviceBindOrganization(device.getBoundStatus()) |
| | | .organizationId(device.getDeptId().toString()) |
| | | .organizationId(String.valueOf(device.getDeptId())) |
| | | .organizationName(device.getWorkspaceName()) |
| | | .build(); |
| | | } |