diff --git a/dk-api/api-system/src/main/java/org/dromara/system/api/RemoteSubmailConfigService.java b/dk-api/api-system/src/main/java/org/dromara/system/api/RemoteSubmailConfigService.java index 9f4677e..b122cbf 100644 --- a/dk-api/api-system/src/main/java/org/dromara/system/api/RemoteSubmailConfigService.java +++ b/dk-api/api-system/src/main/java/org/dromara/system/api/RemoteSubmailConfigService.java @@ -35,6 +35,6 @@ public interface RemoteSubmailConfigService { * @param userId * @param noticeMap */ - void remoteSendUser(String code,List userId,Map noticeMap); + void remoteSendUser(String code,List userId,Map noticeMap,String project); } diff --git a/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/control/api/AbstractControlService.java b/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/control/api/AbstractControlService.java index b6cbce4..c89ec69 100644 --- a/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/control/api/AbstractControlService.java +++ b/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/control/api/AbstractControlService.java @@ -436,7 +436,6 @@ public abstract class AbstractControlService { * @param request data * @return services_reply */ - @CloudSDKVersion(since = CloudSDKVersionEnum.V1_0_2, include = GatewayTypeEnum.DOCK) public TopicServicesResponse irMeteringModeSet(GatewayManager gateway, IrMeteringModeSetRequest request) { return servicesPublish.publish( gateway.getGatewaySn(), @@ -450,7 +449,6 @@ public abstract class AbstractControlService { * @param request data * @return services_reply */ - @CloudSDKVersion(since = CloudSDKVersionEnum.V1_0_2, include = GatewayTypeEnum.DOCK) public TopicServicesResponse irMeteringPointSet(GatewayManager gateway, IrMeteringPointSetRequest request) { return servicesPublish.publish( gateway.getGatewaySn(), @@ -464,7 +462,6 @@ public abstract class AbstractControlService { * @param request data * @return services_reply */ - @CloudSDKVersion(since = CloudSDKVersionEnum.V1_0_2, include = GatewayTypeEnum.DOCK) public TopicServicesResponse irMeteringAreaSet(GatewayManager gateway, IrMeteringAreaSetRequest request) { return servicesPublish.publish( gateway.getGatewaySn(), diff --git a/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/device/DeviceVideoEnum.java b/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/device/DeviceVideoEnum.java index c851c1c..ae36205 100644 --- a/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/device/DeviceVideoEnum.java +++ b/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/device/DeviceVideoEnum.java @@ -76,5 +76,9 @@ public enum DeviceVideoEnum { .findAny().orElseThrow(() -> new CloudSDKException(DeviceEnum.class, finalKey)); } + public static void main(String[] args) { + System.out.println(DeviceVideoEnum.find("Matrice 30T").getDevice()); + } + } diff --git a/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/wayline/GetWaylineListRequest.java b/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/wayline/GetWaylineListRequest.java index 58af518..173ba48 100644 --- a/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/wayline/GetWaylineListRequest.java +++ b/dk-common/common-cloudsdk/src/main/java/org/dromara/common/sdk/cloudapi/wayline/GetWaylineListRequest.java @@ -92,6 +92,14 @@ public class GetWaylineListRequest { @Schema(name = "key", description = "wayline 文件名", example = "waypoint") private String key; + + @JsonProperty("spirit_smell_flag") + @Schema(name = "spirit_smell_flag", description = "灵嗅负载") + private Boolean spiritSmellFlag; + + private List spiritSmellWaylineFileIds; + + public GetWaylineListRequest() { } @@ -200,4 +208,20 @@ public class GetWaylineListRequest { this.deviceSn = deviceSn; return this; } + + public Boolean getSpiritSmellFlag() { + return spiritSmellFlag; + } + + public void setSpiritSmellFlag(Boolean spiritSmellFlag) { + this.spiritSmellFlag = spiritSmellFlag; + } + + public List getSpiritSmellWaylineFileIds() { + return spiritSmellWaylineFileIds; + } + + public void setSpiritSmellWaylineFileIds(List spiritSmellWaylineFileIds) { + this.spiritSmellWaylineFileIds = spiritSmellWaylineFileIds; + } } diff --git a/dk-common/common-redis/src/main/java/org/dromara/common/redis/config/RedisConst.java b/dk-common/common-redis/src/main/java/org/dromara/common/redis/config/RedisConst.java index 7f2713f..7f5a496 100644 --- a/dk-common/common-redis/src/main/java/org/dromara/common/redis/config/RedisConst.java +++ b/dk-common/common-redis/src/main/java/org/dromara/common/redis/config/RedisConst.java @@ -18,10 +18,15 @@ public final class RedisConst { public static final Integer DEVICE_ALIVE_SECOND = 60; public static final Integer WEBSOCKET_ALIVE_SECOND = 60 * 60 * 24; + public static final Integer ONLINE_REDIS_USER_ALIVE_SECOND = 60 * 5; public static final Integer DEVICE_VIDEO_STATUE_SECOND = 60 * 50; public static final String DEVICE_ONLINE_PREFIX = "online" + DELIMITER; + public static final String DEVICE_ONLINE_USER_PREFIX = "onlineuser" + DELIMITER; + + public static final String DEVICE_SPIRITSMELL_PREFIX = "spiritsmell" + DELIMITER; //灵嗅设备状态 + public static final String DEVICE_SPIRITSMELL_LIST_PREFIX = "spiritsmell_list" + DELIMITER; //灵嗅设备状态 public static final String WEBSOCKET_PREFIX = "webSocket" + DELIMITER; diff --git a/dk-common/common-websocket/pom.xml b/dk-common/common-websocket/pom.xml index ac54281..0a7c953 100644 --- a/dk-common/common-websocket/pom.xml +++ b/dk-common/common-websocket/pom.xml @@ -48,6 +48,11 @@ org.springframework.boot spring-boot-starter-websocket + org.dromara common-cloudsdk diff --git a/dk-common/common-websocket/src/main/java/org/dromara/common/websocket/dto/BizCodeEnum.java b/dk-common/common-websocket/src/main/java/org/dromara/common/websocket/dto/BizCodeEnum.java index cf932e5..f81442b 100644 --- a/dk-common/common-websocket/src/main/java/org/dromara/common/websocket/dto/BizCodeEnum.java +++ b/dk-common/common-websocket/src/main/java/org/dromara/common/websocket/dto/BizCodeEnum.java @@ -79,6 +79,8 @@ public enum BizCodeEnum { FLIGHT_AREAS_UPDATE("flight_areas_update"), + SPIRIT_SMELL("spirit_smell"), + ; private String code; diff --git a/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java b/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java index 967c377..8fb7300 100644 --- a/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java +++ b/dk-modules/business/src/main/java/org/dromara/business/service/impl/BusinessAlertServiceImpl.java @@ -689,7 +689,12 @@ public class BusinessAlertServiceImpl implements IBusinessAlertService { } if (ObjectUtil.isNotEmpty(bo.getDeptId())){ - wrapper.eq("t.dept_id", bo.getDeptId()); + //根据传过来的部门id查找是否存在下级部门 + List remoteDeptVos = remoteDeptService.selectListByParentId(bo.getDeptId()); + List deptIdList = StreamUtils.toList(remoteDeptVos, RemoteDeptVo::getDeptId); + deptIdList.add(Long.valueOf(bo.getDeptId())); + + wrapper.in("t.dept_id", deptIdList); } if (ObjectUtil.isNotEmpty(bo.getJobName())){ diff --git a/dk-modules/business/src/main/resources/templates/alert.ftl b/dk-modules/business/src/main/resources/templates/alert.ftl index 7937b57..749a3fe 100644 --- a/dk-modules/business/src/main/resources/templates/alert.ftl +++ b/dk-modules/business/src/main/resources/templates/alert.ftl @@ -829,6 +829,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + 标签 + + + @@ -1012,6 +1039,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + ${item.labelCn?if_exists} + + + diff --git a/dk-modules/business/src/main/resources/templates/pdfAlert.ftl b/dk-modules/business/src/main/resources/templates/pdfAlert.ftl index 34a8e52..3fcd56c 100644 --- a/dk-modules/business/src/main/resources/templates/pdfAlert.ftl +++ b/dk-modules/business/src/main/resources/templates/pdfAlert.ftl @@ -50,6 +50,7 @@ 预警名称 所属部门 预警状态 + 标签 经纬度 预警时间 @@ -60,6 +61,7 @@ ${item.jobName?if_exists} ${item.deptName?if_exists} ${item.handleType?if_exists} + ${item.labelCn?if_exists} ${item.lng?if_exists} ${item.lat?if_exists} ${item.createTime?datetime?string('yyyy-MM-dd HH:mm:ss')} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttMessageProcessorImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttMessageProcessorImpl.java index edbf028..1c91673 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttMessageProcessorImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttMessageProcessorImpl.java @@ -1,26 +1,32 @@ package org.dromara.sample.configuration; -import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.redis.config.RedisConst; +import org.dromara.common.redis.utils.RedisOpsUtils; +import org.dromara.common.websocket.dto.BizCodeEnum; +import org.dromara.sample.manage.domain.ManageDevicePayloadCustom; import org.dromara.sample.manage.mapper.IDevicePayloadMapper; -import org.dromara.sample.manage.model.dto.DevicePayloadDTO; +import org.dromara.sample.manage.mapper.ManageDevicePayloadCustomMapper; +import org.dromara.sample.manage.model.dto.TelemetryDTO; import org.dromara.sample.manage.model.entity.DevicePayloadEntity; +import org.dromara.sample.manage.model.enums.UserTypeEnum; import org.dromara.sample.manage.service.IDevicePayloadService; -import org.dromara.sample.wayline.domain.WaylineJobAtmosphere; +import org.dromara.sample.manage.service.IDeviceRedisService; import org.dromara.sample.wayline.domain.bo.WaylineJobAtmosphereBo; import org.dromara.sample.wayline.model.dto.WaylineJobDTO; -import org.dromara.sample.wayline.model.entity.WaylineJobEntity; import org.dromara.sample.wayline.service.IWaylineJobAtmosphereService; import org.dromara.sample.wayline.service.IWaylineJobService; +import org.dromara.sample.websocket.config.WebSocketSubscriptionManager; +import org.dromara.sample.websocket.service.IWebSocketMessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; -import java.util.List; +import java.util.Map; import java.util.Optional; @Slf4j @@ -31,49 +37,91 @@ public class LingxiuMqttMessageProcessorImpl implements LingxiuMqttMessageProces private final IWaylineJobService waylineJobService; private final IDevicePayloadService devicePayloadService; + @Autowired + private IDeviceRedisService deviceRedisService; + @Autowired private final IDevicePayloadMapper devicePayloadMapper; + @Autowired + private final ManageDevicePayloadCustomMapper manageDevicePayloadCustomMapper; + + @Autowired + private IWebSocketMessageService webSocketMessageService; + + @Autowired + private WebSocketSubscriptionManager webSocketSubscriptionManager; + + + @Override public void process(String topic, String payload) { - log.info("处理灵嗅MQTT数据 topic={}, payload={}", topic, payload); - // {"serial":"37c12953","sequence":12,"sateNum":0,"hdop":0,"utcTime":"2025-06-17-01-37-22","latitude":34.270486,"longitude":117.149302,"altitude":0.03,"temperature":29.61,"humidity":21.37,"pressure":100071.42,"airData":{"SO2(ppm)":0,"NO2(ppm)":0,"Ox(ppm)":0,"PM1.0(ug/m3)":14,"PM2.5(ug/m3)":35,"PM10(ug/m3)":46}} - // if(1==1){ //关闭数据 // return; // } +// System.out.println("灵嗅"+topic); + log.info("处理灵嗅MQTT数据 topic={}, payload={}", topic, payload); + // {"serial":"37c12953","sequence":12,"sateNum":0,"hdop":0,"utcTime":"2025-06-17-01-37-22","latitude":34.270486,"longitude":117.149302,"altitude":0.03,"temperature":29.61,"humidity":21.37,"pressure":100071.42,"airData":{"SO2(ppm)":0,"NO2(ppm)":0,"Ox(ppm)":0,"PM1.0(ug/m3)":14,"PM2.5(ug/m3)":35,"PM10(ug/m3)":46}} + + try { JSONObject json = JSONUtil.parseObj(payload); - System.out.println("json打印"+json); - JSONObject airData = json.getJSONObject("airData"); + JSONObject airData = json.getJSONObject("airData"); //"airData":{"SO2(ppm)":0,"NO2(ppm)":0,"Ox(ppm)":0,"PM1.0(ug/m3)":16,"PM2.5(ug/m3)":39,"PM10(ug/m3)":51} + + /** 数据处理-简化对象内容 {"SO2":0,"NO2":0,"Ox":0.082399,"PM1_0":20,"PM2_5":39,"PM10":48} */ + JSONObject simplified = new JSONObject(); + for (String key : airData.keySet()) { + Object value = airData.get(key); + String newKey = key.replaceAll("\\(.*?\\)", ""); // 去掉括号及其内容:"SO2(ppm)" -> "SO2" + newKey = newKey.replace(".", "_"); // 替换 . 为 _,例如 "PM2.5" -> "PM2_5" + newKey = newKey.replaceAll("(?i)point", "_"); //point去除:PM1point0 or PM2POINT5 → PM1_0, PM2_5 + newKey = newKey.trim(); // 去除空格 + simplified.put(newKey, value); + } + String utcTimeStr = json.getStr("utcTime"); + Boolean missionOpenStatus = json.getBool("missionOpenStatus"); + Float relativeAltitude = json.getFloat("relativeAltitude"); + Boolean dataRecoveryFlag = json.getBool("dataRecoveryFlag"); - //"airData":{"SO2(ppm)":0,"NO2(ppm)":0,"Ox(ppm)":0,"PM1.0(ug/m3)":16,"PM2.5(ug/m3)":39,"PM10(ug/m3)":51} //找默认数据 WaylineJobAtmosphereBo jobAtmosphere = JSONUtil.toBean(json, WaylineJobAtmosphereBo.class); - jobAtmosphere.setAirData(JSONUtil.toJsonStr(airData)); + jobAtmosphere.setAirData(JSONUtil.toJsonStr(simplified)); jobAtmosphere.setUtcTimeStr(utcTimeStr); + jobAtmosphere.setMissionOpenStatus(missionOpenStatus); + jobAtmosphere.setRelativeAltitude(relativeAltitude); + jobAtmosphere.setDataRecoveryFlag(dataRecoveryFlag); - LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); - queryWrapper.eq(DevicePayloadEntity::getPayloadSn,jobAtmosphere.getSerial()); - DevicePayloadEntity devicePayloadEntity = devicePayloadMapper.selectOne(queryWrapper); - String deviceSn = devicePayloadEntity.getDeviceSn(); - System.out.println(deviceSn); -// List devicePayloadEntitiesByDeviceSn = devicePayloadService.getDevicePayloadEntitiesByDeviceSn(""); + //找第三方挂载 + LambdaQueryWrapper queryWrapper = new LambdaQueryWrapper<>(); + queryWrapper.eq(ManageDevicePayloadCustom::getPayloadSn, jobAtmosphere.getSerial()); + ManageDevicePayloadCustom paloadCustom = manageDevicePayloadCustomMapper.selectOne(queryWrapper); + if (paloadCustom == null) { + return; + } + + String deviceSn = paloadCustom.getDockSn();//8UUXN2B00A00SK + String payloadType = paloadCustom.getPayloadType(); + jobAtmosphere.setPayloadType(payloadType); +// List devicePayloadEntitiesByDeviceSn = devicePayloadService.getDevicePayloadEntitiesByDeviceSn(""); -// String sn = json.getStr("8UUXN3100A01WS");//8UUXN3100A01WS 8UUXN2T00A01R8 + /** 更新设备灵嗅状态上线 **/ // 查找无人机/wayline信息 - WaylineJobDTO waylineJobDTO = waylineJobService.getJobByDockSn(deviceSn); -// waylineJobService.getid -// Optional jobOpt = waylineJobService.getJobByJobInternalId(sn); -// if (jobOpt.isPresent()) { -// waylineJobAtmosphereService.handleAdd(jobOpt.get(), json); -// } else { -// log.warn("找不到对应无人机任务:sn={}", sn); + WaylineJobDTO waylineJobDTO = waylineJobService.getJobByDockSn(deviceSn); //飞行中+倒序》找第一个 + +// if(ObjectUtil.isEmpty(waylineJobDTO.getId())){ +// //测试-找一个临时备用的 +// Optional jobByJobId = waylineJobService.getJobByJobId("e3dea0f5-37f2-4d79-ae58-490af3228070","8fc5e69e-2f8d-4a8f-9bdd-0c59eab39d74"); +// if (jobByJobId.isPresent()) { +// waylineJobDTO = jobByJobId.get(); +// } // } -// "{\"SO2(ppm)\":0,\"NO2(ppm)\":0,\"Ox(ppm)\":0,\"PM1.0(ug/m3)\":16,\"PM2.5(ug/m3)\":38,\"PM10(ug/m3)\":48}" + + if(ObjectUtil.isEmpty(waylineJobDTO.getId())){ + return; + } if(ObjectUtil.isNotEmpty(waylineJobDTO)){ jobAtmosphere.setWaylineJobId((long)waylineJobDTO.getId()); @@ -83,8 +131,42 @@ public class LingxiuMqttMessageProcessorImpl implements LingxiuMqttMessageProces jobAtmosphere.setFileId(waylineJobDTO.getFileId()); jobAtmosphere.setWorkspaceId(waylineJobDTO.getWorkspaceId()); jobAtmosphere.setDockSn(waylineJobDTO.getDockSn()); -// BeanUtil.copyProperties(); - waylineJobAtmosphereService.insertByBo(jobAtmosphere); + waylineJobAtmosphereService.insertByBo(jobAtmosphere);//存到库里 + + //拼接数据到redis ,负责push 对象到灵嗅记录列表-正常 +// deviceRedisService.pushDeviceSpiritSmellList(deviceSn, jobAtmosphere); +// RedisOpsUtils.setWithExpire(RedisConst.DEVICE_SPIRITSMELL_PREFIX + deviceSn, data, 30); + + //动态赋值给dockOsd的redis缓存。 + jobAtmosphere.setAirDataJson(JSONUtil.parseObj(jobAtmosphere.getAirData())); + + // 存到缓存-单独缓存 + deviceRedisService.setDeviceSpiritSmellOnline(deviceSn,jobAtmosphere); + // 存到缓存-扩展OSD数据 +// Object osdRedis = RedisOpsUtils.get(RedisConst.OSD_PREFIX + deviceSn); +// if(Optional.ofNullable(osdRedis).isPresent()){ +//// OsdDockDrone +// JSONObject entries = JSONUtil.parseObj(osdRedis); +// entries.set("spiritsmell", jobAtmosphere); +// RedisOpsUtils.setWithExpire(RedisConst.OSD_PREFIX + deviceSn, entries, RedisConst.ONLINE_REDIS_USER_ALIVE_SECOND); +// +// } +// deviceRedisService.getDeviceSpiritSmellOnline(deviceSn); + + //socket发送-正常 + Optional deviceOpt = deviceRedisService.getDeviceSpiritSmellOnline(deviceSn); + if (deviceOpt.isEmpty()) { + return; + } + + String bizCode = BizCodeEnum.SPIRIT_SMELL.getCode(); + String dockSn = deviceSn; // 设备码 + String workspaceId = deviceOpt.get().getWorkspaceId(); + +// Collection subs = webSocketSubscriptionManager.getSessionsForDock(dockSn); + webSocketMessageService.sendBatch(workspaceId, UserTypeEnum.WEB.getVal(),bizCode, TelemetryDTO.builder().sn(deviceSn).host(jobAtmosphere).build()); +// Collection subs = webSocketSubscriptionManager.getSessionsForDock(dockSn); +// webSocketMessageService.sendBatchBySessions(subs, bizCode, TelemetryDTO.builder().sn(deviceSn).host(jobAtmosphere).build()); } } catch (Exception e) { log.error("处理灵嗅MQTT消息异常", e); diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttStartupRunner.java b/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttStartupRunner.java index 68dd5da..8dd58cf 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttStartupRunner.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/configuration/LingxiuMqttStartupRunner.java @@ -1,6 +1,8 @@ package org.dromara.sample.configuration; +import cn.hutool.core.util.StrUtil; import lombok.RequiredArgsConstructor; +import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.ApplicationArguments; import org.springframework.boot.ApplicationRunner; import org.springframework.boot.CommandLineRunner; @@ -11,10 +13,20 @@ import org.springframework.stereotype.Component; public class LingxiuMqttStartupRunner implements ApplicationRunner { private final MqttLingxiuSubscriber subscriber; + @Value("${lingxiu.mqtt.enable}") + private String enable; + + @Value("${lingxiu.mqtt.topic}") + private String topic; + @Override public void run(ApplicationArguments args) { + if(!StrUtil.equals(enable, "true")) { + return; + } + try { - subscriber.subscribe(); + subscriber.subscribe(topic); } catch (Exception e) { System.err.println("启动灵嗅 MQTT 订阅失败"+ e); } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/configuration/MqttLingxiuSubscriber.java b/dk-modules/sample/src/main/java/org/dromara/sample/configuration/MqttLingxiuSubscriber.java index 9ee2d30..7f0e6e9 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/configuration/MqttLingxiuSubscriber.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/configuration/MqttLingxiuSubscriber.java @@ -17,8 +17,9 @@ public class MqttLingxiuSubscriber { this.processor = processor; } - public void subscribe() throws MqttException { - String[] topics = new String[]{"/topic/#"}; + public void subscribe(String topicParam) throws MqttException { +// String[] topics = new String[]{"/topic/#"}; + String[] topics = new String[]{topicParam}; client.setCallback(new MqttCallback() { @Override diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/controller/DockController.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/controller/DockController.java index 4e7e0ef..bfba184 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/control/controller/DockController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/controller/DockController.java @@ -71,5 +71,23 @@ public class DockController { return controlService.payloadCommands(param); } + @PostMapping("/{sn}/payload/irMeteringModeSet") + public HttpResultResponse irMeteringModeSet(@PathVariable String sn, @Valid @RequestBody PayloadCommandsParam param) throws Exception { + param.setSn(sn); + return controlService.irMeteringModeSet(param); + } + + + @PostMapping("/{sn}/payload/irMeteringPointSet") + public HttpResultResponse irMeteringPointSet(@PathVariable String sn, @Valid @RequestBody PayloadCommandsParam param) throws Exception { + param.setSn(sn); + return controlService.irMeteringPointSet(param); + } + + @PostMapping("/{sn}/payload/irMeteringAreaSet") + public HttpResultResponse irMeteringAreaSet(@PathVariable String sn, @Valid @RequestBody PayloadCommandsParam param) throws Exception { + param.setSn(sn); + return controlService.irMeteringAreaSet(param); + } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/model/enums/PayloadCommandsEnum.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/model/enums/PayloadCommandsEnum.java index 0b25499..5b24a74 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/control/model/enums/PayloadCommandsEnum.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/model/enums/PayloadCommandsEnum.java @@ -2,6 +2,8 @@ package org.dromara.sample.control.model.enums; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; +import org.dromara.common.sdk.cloudapi.control.ControlMethodEnum; +import org.dromara.common.sdk.cloudapi.control.IrMeteringModeSetRequest; import org.dromara.common.sdk.cloudapi.control.PayloadControlMethodEnum; import java.util.Arrays; @@ -25,7 +27,13 @@ public enum PayloadCommandsEnum { CAMERA_FOCAL_LENGTH_SET(PayloadControlMethodEnum.CAMERA_FOCAL_LENGTH_SET, org.dromara.sample.control.service.impl.CameraFocalLengthSetImpl.class), - GIMBAL_RESET(PayloadControlMethodEnum.GIMBAL_RESET, org.dromara.sample.control.service.impl.GimbalResetImpl.class); + GIMBAL_RESET(PayloadControlMethodEnum.GIMBAL_RESET, org.dromara.sample.control.service.impl.GimbalResetImpl.class), + + IR_METERING_MODE_SET(PayloadControlMethodEnum.IR_METERING_MODE_SET, org.dromara.sample.control.service.impl.IrMeteringModeSetImpl.class), + + IR_METERING_POINT_SET(PayloadControlMethodEnum.IR_METERING_POINT_SET, org.dromara.sample.control.service.impl.IrMeteringPointSetImpl.class), + + IR_METERING_AREA_SET(PayloadControlMethodEnum.IR_METERING_AREA_SET, org.dromara.sample.control.service.impl.IrMeteringAreaSetImpl.class); PayloadControlMethodEnum cmd; diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/model/param/DronePayloadParam.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/model/param/DronePayloadParam.java index 5738863..3069ccc 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/control/model/param/DronePayloadParam.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/model/param/DronePayloadParam.java @@ -1,6 +1,8 @@ package org.dromara.sample.control.model.param; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Pattern; import lombok.Data; @@ -29,6 +31,18 @@ public class DronePayloadParam { private CameraModeEnum cameraMode; + private Integer mode; + + @Min(0) + @Max(1) + private Float width; + + /** + * Temperature measurement area height + */ + @Min(0) + @Max(1) + private Float height; /** * true: Lock the gimbal, the gimbal and the drone rotate together. * false: Only the gimbal rotates, but the drone does not. diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/service/IControlService.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/IControlService.java index ee64f0d..78aa6a3 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/control/service/IControlService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/IControlService.java @@ -70,4 +70,10 @@ public interface IControlService { * @return */ HttpResultResponse payloadCommands(PayloadCommandsParam param) throws Exception; + + HttpResultResponse irMeteringModeSet(PayloadCommandsParam param) throws Exception; + + HttpResultResponse irMeteringPointSet(PayloadCommandsParam param) throws Exception; + + HttpResultResponse irMeteringAreaSet(PayloadCommandsParam param) throws Exception; } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/ControlServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/ControlServiceImpl.java index 263f291..7032db1 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/ControlServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/ControlServiceImpl.java @@ -301,4 +301,58 @@ public class ControlServiceImpl implements IControlService { HttpResultResponse.success() : HttpResultResponse.error(serviceReply.getResult()); } + + @Override + public HttpResultResponse irMeteringModeSet(PayloadCommandsParam param) throws Exception { + param.getCmd().getClazz() + .getDeclaredConstructor(DronePayloadParam.class) + .newInstance(param.getData()) + .checkCondition(param.getSn()); + + TopicServicesResponse response = abstractControlService.irMeteringModeSet( + SDKManager.getDeviceSDK(param.getSn()), + mapper.convertValue(param.getData(), IrMeteringModeSetRequest.class)); + + ServicesReplyData serviceReply = response.getData(); + + return serviceReply.getResult().isSuccess() ? + HttpResultResponse.success() + : HttpResultResponse.error(serviceReply.getResult()); + } + + @Override + public HttpResultResponse irMeteringPointSet(PayloadCommandsParam param) throws Exception { + param.getCmd().getClazz() + .getDeclaredConstructor(DronePayloadParam.class) + .newInstance(param.getData()) + .checkCondition(param.getSn()); + + TopicServicesResponse response = abstractControlService.irMeteringPointSet( + SDKManager.getDeviceSDK(param.getSn()), + mapper.convertValue(param.getData(), IrMeteringPointSetRequest.class)); + + ServicesReplyData serviceReply = response.getData(); + + return serviceReply.getResult().isSuccess() ? + HttpResultResponse.success() + : HttpResultResponse.error(serviceReply.getResult()); + } + + @Override + public HttpResultResponse irMeteringAreaSet(PayloadCommandsParam param) throws Exception { + param.getCmd().getClazz() + .getDeclaredConstructor(DronePayloadParam.class) + .newInstance(param.getData()) + .checkCondition(param.getSn()); + + TopicServicesResponse response = abstractControlService.irMeteringAreaSet( + SDKManager.getDeviceSDK(param.getSn()), + mapper.convertValue(param.getData(), IrMeteringAreaSetRequest.class)); + + ServicesReplyData serviceReply = response.getData(); + + return serviceReply.getResult().isSuccess() ? + HttpResultResponse.success() + : HttpResultResponse.error(serviceReply.getResult()); + } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringAreaSetImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringAreaSetImpl.java new file mode 100644 index 0000000..0c162c4 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringAreaSetImpl.java @@ -0,0 +1,22 @@ +package org.dromara.sample.control.service.impl; + + +import org.dromara.sample.control.model.param.DronePayloadParam; + +/** + * @author sean + * @version 1.4 + * @date 2023/4/23 + */ +public class IrMeteringAreaSetImpl extends PayloadCommandsHandler { + + public IrMeteringAreaSetImpl(DronePayloadParam param) { + super(param); + } + + @Override + public boolean canPublish(String deviceSn) { + super.canPublish(deviceSn); + return true; + } +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringModeSetImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringModeSetImpl.java new file mode 100644 index 0000000..f1bd86d --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringModeSetImpl.java @@ -0,0 +1,23 @@ +package org.dromara.sample.control.service.impl; + + +import org.dromara.common.sdk.cloudapi.device.CameraStateEnum; +import org.dromara.sample.control.model.param.DronePayloadParam; + +/** + * @author sean + * @version 1.4 + * @date 2023/4/23 + */ +public class IrMeteringModeSetImpl extends PayloadCommandsHandler { + + public IrMeteringModeSetImpl(DronePayloadParam param) { + super(param); + } + + @Override + public boolean canPublish(String deviceSn) { + super.canPublish(deviceSn); + return true; + } +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringPointSetImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringPointSetImpl.java new file mode 100644 index 0000000..bf45348 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/control/service/impl/IrMeteringPointSetImpl.java @@ -0,0 +1,22 @@ +package org.dromara.sample.control.service.impl; + + +import org.dromara.sample.control.model.param.DronePayloadParam; + +/** + * @author sean + * @version 1.4 + * @date 2023/4/23 + */ +public class IrMeteringPointSetImpl extends PayloadCommandsHandler { + + public IrMeteringPointSetImpl(DronePayloadParam param) { + super(param); + } + + @Override + public boolean canPublish(String deviceSn) { + super.canPublish(deviceSn); + return true; + } +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteSystemFeign.java b/dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteSystemFeign.java index 83f5f4e..26306e2 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteSystemFeign.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/feign/RemoteSystemFeign.java @@ -8,6 +8,7 @@ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import java.util.List; +import java.util.Map; @FeignClient(name = "gateway",path = "system") public interface RemoteSystemFeign { @@ -17,4 +18,9 @@ public interface RemoteSystemFeign { @GetMapping(value = "/config/configKeyFeign/{configKey}") public String getConfigKeyFeign(@PathVariable String configKey); + + //根据目标值类型查询用户信息 + @GetMapping("/user/list/target") + public List> listTargetTypeByUser(List> params); + } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceController.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceController.java index a95ce9b..7b0bd9e 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceController.java @@ -1,24 +1,15 @@ package org.dromara.sample.manage.controller; -import cn.dev33.satoken.annotation.SaCheckPermission; -import com.alibaba.fastjson.JSON; -import com.alibaba.fastjson.JSONArray; -import com.alibaba.fastjson.JSONObject; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import org.dromara.common.core.domain.R; -import org.dromara.common.json.utils.JsonUtils; -import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.redis.config.RedisConst; import org.dromara.common.redis.utils.RedisOpsUtils; -import org.dromara.common.redis.utils.RedisUtils; -import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.sdk.cloudapi.device.OsdDock; -import org.dromara.common.web.core.BaseController; import org.dromara.sample.manage.model.dto.DeviceDTO; import org.dromara.sample.manage.model.dto.DeviceFirmwareUpgradeDTO; import org.dromara.sample.manage.model.entity.DeviceEntity; -import org.dromara.sample.manage.service.IDeviceProService; +import org.dromara.sample.manage.model.param.DeviceSubscribeParam; import org.dromara.sample.manage.service.IDeviceRedisService; import org.dromara.sample.manage.service.IDeviceService; import com.fasterxml.jackson.databind.JsonNode; @@ -27,12 +18,10 @@ import org.dromara.common.sdk.common.HttpResultResponse; import org.dromara.common.sdk.common.PaginationData; import org.dromara.common.sdk.exception.CloudSDKErrorEnum; import org.dromara.common.sdk.mqtt.property.PropertySetReplyResultEnum; -import org.dromara.system.api.model.LoginUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.*; -import java.util.stream.Collectors; /** * @author sean.zhou @@ -65,6 +54,52 @@ public class DeviceController { return HttpResultResponse.success(devicesList); } + @GetMapping("/{workspace_id}/devices/osd") + @Operation(summary = "获取一个工作区中所有在线设备+OSD的列表", description = "获取一个工作区中所有在线设备+OSD的列表") + public HttpResultResponse> getDevicesOsd(@PathVariable("workspace_id") String workspaceId, + @RequestParam(name = "nickname",required = false) String nickname,@RequestParam(name = "proIds",required = false) List proIds) { + List devicesList = deviceService.getDevicesTopoForWeb(workspaceId,nickname,proIds); + //拼接osd信息 + JSONObject devicesOsdJson = deviceRedisService.getDevicesOsdList(""); + for (DeviceDTO deviceDTO : devicesList) { + if(devicesOsdJson.containsKey(deviceDTO.getDeviceSn())){ + deviceDTO.setOsdData(devicesOsdJson.getJSONObject(deviceDTO.getDeviceSn())); + } + } + return HttpResultResponse.success(devicesList); + } + + + //设备订阅-关闭保存到redis + @PostMapping("/{workspace_id}/subscribe") + @Operation(summary = "设备消息订阅", description = "设备消息订阅") + public HttpResultResponse subscribe(@PathVariable("workspace_id") String workspaceId, + @RequestBody DeviceSubscribeParam deviceSubscribeParam +// @RequestParam("action") String action, +// @RequestParam("token") String token, +// @RequestParam("dockSn") String dockSn + ) { + String action = deviceSubscribeParam.getAction(); + String token = deviceSubscribeParam.getToken(); + String dockSn = deviceSubscribeParam.getDockSn(); + if(action.equals("subscribe")) { + System.out.println("sub"+token); + String key = RedisConst.DEVICE_ONLINE_USER_PREFIX + token; + //基于机场sn找无人机sn + String value = ""; + Optional deviceBySn = deviceService.getDeviceBySn(dockSn); + if(deviceBySn.isPresent()) { + value = dockSn + "," + deviceBySn.get().getChildDeviceSn(); + } + RedisOpsUtils.setWithExpire(key, value ,RedisConst.ONLINE_REDIS_USER_ALIVE_SECOND); + }else if(action.equals("unsubscribe")) { + RedisOpsUtils.del(RedisConst.DEVICE_ONLINE_USER_PREFIX+token); + } + + return HttpResultResponse.success(); + } + + @GetMapping("/{workspace_id}/devices/redis") @Operation(summary = "获取一个工作区中所有在线设备的列表。", description = "获取一个工作区中所有在线设备的列表") public HttpResultResponse getDeviceRedis(@PathVariable("workspace_id") String workspaceId, @@ -257,4 +292,18 @@ public class DeviceController { return PropertySetReplyResultEnum.SUCCESS.getResult() == result ? HttpResultResponse.success() : HttpResultResponse.error(result, String.valueOf(result)); } + + @Operation(summary = "设置无人机的属性参数。", description = "设置无人机的属性参数。") + @PutMapping("/{workspace_id}/devices/{device_sn}/propertyData") + public HttpResultResponse devicePropertySetData(@PathVariable("workspace_id") String workspaceId, + @PathVariable("device_sn") String dockSn, + @RequestBody JsonNode param) { + if (param.size() != 1) { + return HttpResultResponse.error(CloudSDKErrorEnum.INVALID_PARAMETER); + } + + int result = deviceService.devicePropertySetData(workspaceId, dockSn, param); + return PropertySetReplyResultEnum.SUCCESS.getResult() == result ? + HttpResultResponse.success() : HttpResultResponse.error(result, String.valueOf(result)); + } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceProController.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceProController.java index 7cae641..b029899 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceProController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceProController.java @@ -1,23 +1,20 @@ package org.dromara.sample.manage.controller; -import cn.hutool.core.lang.Dict; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; -import org.dromara.common.core.domain.R; -import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.sdk.common.HttpResultResponse; import org.dromara.common.sdk.common.PaginationData; import org.dromara.sample.manage.model.dto.DeviceProDTO; import org.dromara.sample.manage.model.entity.DeviceProEntity; import org.dromara.sample.manage.model.entity.DeviceProUserEntity; import org.dromara.sample.manage.service.IDeviceProService; -import org.dromara.system.api.model.LoginUser; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import java.util.List; +import java.util.Map; @RestController @Slf4j @@ -87,11 +84,27 @@ public class DeviceProController { */ @Operation(summary = "新增/更新项目人员。", description = "新增/更新项目人员。") @PostMapping("/{proId}/update") - public HttpResultResponse updateDeviceProUser(@RequestBody List userEntity,@PathVariable Integer proId) { + public HttpResultResponse updateDeviceProUser(@RequestBody List userEntity, @PathVariable Integer proId) { + return HttpResultResponse.success(deviceProService.updateDeviceProUser(userEntity,proId)); } + /** + * 新增/更新项目人员。 + * @param userEntity + * @return + */ + @Operation(summary = "新增/更新项目人员新", description = "新增/更新项目人员新") + @PostMapping("/{proId}/update/new") + public HttpResultResponse updateDeviceProUserNew(@RequestBody List> userEntity, @PathVariable Integer proId) { + //目标类型 targetType 1、用户 2、角色 3、部门 targetKey 目标值 List> params + + + return HttpResultResponse.success(deviceProService.updateDeviceProUserNew(userEntity,proId)); + } + + @Operation(summary = "查询项目人员。", description = "查询项目人员") @GetMapping("/{proId}/user/page") public HttpResultResponse> pageProUser(@PathVariable Integer proId, @@ -102,6 +115,7 @@ public class DeviceProController { return HttpResultResponse.success(deviceProService.pageProUser(searchValue,proId,pageQuery)); } + @Operation(summary = "删除项目人员", description = "删除项目人员") @DeleteMapping("/{proId}/{proUserId}/user/delete") public HttpResultResponse deleteProUser(@PathVariable Integer proId, @@ -149,4 +163,12 @@ public class DeviceProController { List result = deviceProService.listUserGroup(); return HttpResultResponse.success(result); } + + /** + * 初始化将设备组数据存入redis + */ + @GetMapping("/redis/init") + public HttpResultResponse initProRedisCache(){ + return HttpResultResponse.success(deviceProService.initProRedisCache()); + } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceRedisController.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceRedisController.java index a37bc0c..10dca75 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceRedisController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/DeviceRedisController.java @@ -1,6 +1,7 @@ package org.dromara.sample.manage.controller; +import cn.hutool.json.JSONObject; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.extern.slf4j.Slf4j; @@ -9,10 +10,7 @@ import org.dromara.common.sdk.common.HttpResultResponse; import org.dromara.sample.manage.model.dto.DeviceDTO; import org.dromara.sample.manage.service.IDeviceRedisService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestBody; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -54,4 +52,11 @@ public class DeviceRedisController { return HttpResultResponse.success(deviceRedisService.getDevicesOsdInfo(snList)); } + + @GetMapping("/device/osd/list") + @Operation(summary = "获取设备osd实时列表", description = "获取设备osd实时列表") + public HttpResultResponse getDevicesOsdList(@RequestParam(value = "type", required = false) String type) { + return HttpResultResponse.success(deviceRedisService.getDevicesOsdList(type)); + } + } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/ManageDevicePayloadCustomController.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/ManageDevicePayloadCustomController.java new file mode 100644 index 0000000..9b79d25 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/controller/ManageDevicePayloadCustomController.java @@ -0,0 +1,113 @@ +package org.dromara.sample.manage.controller; + +import java.util.List; + +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import lombok.RequiredArgsConstructor; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.constraints.*; +import cn.dev33.satoken.annotation.SaCheckPermission; +import org.springframework.web.bind.annotation.*; +import org.springframework.validation.annotation.Validated; +import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.web.core.BaseController; +import org.dromara.common.mybatis.core.page.PageQuery; +import org.dromara.common.core.domain.R; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import org.dromara.common.log.enums.BusinessType; +import org.dromara.common.excel.utils.ExcelUtil; +import org.dromara.sample.manage.domain.vo.ManageDevicePayloadCustomVo; +import org.dromara.sample.manage.domain.bo.ManageDevicePayloadCustomBo; +import org.dromara.sample.manage.service.IManageDevicePayloadCustomService; +import org.dromara.common.mybatis.core.page.TableDataInfo; + +/** + * 设备自定义/第三方载荷信息 + * 前端访问路由地址为:/sample/DevicePayloadCustom + * + * @author szs + * @date 2025-06-18 + */ +@Validated +@RequiredArgsConstructor +@RestController +@RequestMapping("/DevicePayloadCustom") +public class ManageDevicePayloadCustomController extends BaseController { + + private final IManageDevicePayloadCustomService manageDevicePayloadCustomService; + + /** + * 查询设备自定义/第三方载荷信息列表 + */ + @SaCheckPermission("sample:DevicePayloadCustom:list") + @GetMapping("/list") + public TableDataInfo list(ManageDevicePayloadCustomBo bo, PageQuery pageQuery) { + return manageDevicePayloadCustomService.queryPageList(bo, pageQuery); + } + + @SaCheckPermission("sample:DevicePayloadCustom:list") + @GetMapping("/listAll") + public List listAll(ManageDevicePayloadCustomBo bo) { + return manageDevicePayloadCustomService.queryList(bo); + } + + /** + * 导出设备自定义/第三方载荷信息列表 + */ + @SaCheckPermission("sample:DevicePayloadCustom:export") + @Log(title = "设备自定义/第三方载荷信息", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(ManageDevicePayloadCustomBo bo, HttpServletResponse response) { + List list = manageDevicePayloadCustomService.queryList(bo); + ExcelUtil.exportExcel(list, "设备自定义/第三方载荷信息", ManageDevicePayloadCustomVo.class, response); + } + + /** + * 获取设备自定义/第三方载荷信息详细信息 + * + * @param id 主键 + */ + @SaCheckPermission("sample:DevicePayloadCustom:query") + @GetMapping("/{id}") + public R getInfo(@NotNull(message = "主键不能为空") + @PathVariable Long id) { + return R.ok(manageDevicePayloadCustomService.queryById(id)); + } + + /** + * 新增设备自定义/第三方载荷信息 + */ + @SaCheckPermission("sample:DevicePayloadCustom:add") + @Log(title = "设备自定义/第三方载荷信息", businessType = BusinessType.INSERT) + @RepeatSubmit() + @PostMapping() + public R add(@Validated(AddGroup.class) @RequestBody ManageDevicePayloadCustomBo bo) { + return toAjax(manageDevicePayloadCustomService.insertByBo(bo)); + } + + /** + * 修改设备自定义/第三方载荷信息 + */ + @SaCheckPermission("sample:DevicePayloadCustom:edit") + @Log(title = "设备自定义/第三方载荷信息", businessType = BusinessType.UPDATE) + @RepeatSubmit() + @PutMapping() + public R edit(@Validated(EditGroup.class) @RequestBody ManageDevicePayloadCustomBo bo) { + return toAjax(manageDevicePayloadCustomService.updateByBo(bo)); + } + + /** + * 删除设备自定义/第三方载荷信息 + * + * @param ids 主键串 + */ + @SaCheckPermission("sample:DevicePayloadCustom:remove") + @Log(title = "设备自定义/第三方载荷信息", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public R remove(@NotEmpty(message = "主键不能为空") + @PathVariable Long[] ids) { + return toAjax(manageDevicePayloadCustomService.deleteWithValidByIds(List.of(ids), true)); + } +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/ManageDevicePayloadCustom.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/ManageDevicePayloadCustom.java new file mode 100644 index 0000000..f25a306 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/ManageDevicePayloadCustom.java @@ -0,0 +1,110 @@ +package org.dromara.sample.manage.domain; + +import lombok.AllArgsConstructor; +import lombok.NoArgsConstructor; +import org.apache.ibatis.type.Alias; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import com.baomidou.mybatisplus.annotation.*; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.io.Serial; +import java.io.Serializable; +import java.util.Date; + +/** + * 设备自定义/第三方载荷信息对象 manage_device_payload_custom + * + * @author szs + * @date 2025-06-18 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +@TableName("manage_device_payload_custom") +public class ManageDevicePayloadCustom implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @TableId(value = "id") + private Long id; + + /** + * 载荷sn码 + */ + @TableField("payload_sn") + private String payloadSn; + + /** + * 载荷名称 + */ + @TableField("payload_name") + private String payloadName; + + /** + * 载荷类型 + */ + @TableField("payload_type") + private String payloadType; + + /** + * 父级Id + */ + @TableField("parent_id") + private Long parentId; + + /** + * 设备版本 + */ + @TableField("firmware_version") + private String firmwareVersion; + + /** + * 所属机场 + */ + @TableField("dock_sn") + private String dockSn; + + /** + * 所属设备 + */ + @TableField("device_sn") + private String deviceSn; + + /** + * 所属无人机 + */ + @TableField("drone_sn") + private String droneSn; + + /** + * 设备中位置编号 + */ + @TableField("payload_index") + private Long payloadIndex; + + /** + * 是否启动(1启用,0关闭) + */ + @TableField("enable_flag") + private Long enableFlag; + + /** + * 设备描述 + */ + @TableField("payload_desc") + private String payloadDesc; + + @TableField(value = "create_time", fill = FieldFill.INSERT) + private Date createTime; + + @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) + private Date updateTime; + + + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/bo/ManageDevicePayloadCustomBo.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/bo/ManageDevicePayloadCustomBo.java new file mode 100644 index 0000000..08c04df --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/bo/ManageDevicePayloadCustomBo.java @@ -0,0 +1,99 @@ +package org.dromara.sample.manage.domain.bo; + +import com.fasterxml.jackson.annotation.JsonAlias; +import com.fasterxml.jackson.annotation.JsonValue; +import org.dromara.sample.manage.domain.ManageDevicePayloadCustom; +import org.dromara.common.mybatis.core.domain.BaseEntity; +import org.dromara.common.core.validate.AddGroup; +import org.dromara.common.core.validate.EditGroup; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; +import lombok.EqualsAndHashCode; +import jakarta.validation.constraints.*; + +/** + * 设备自定义/第三方载荷信息业务对象 manage_device_payload_custom + * + * @author szs + * @date 2025-06-18 + */ +@Data +@EqualsAndHashCode(callSuper = true) +@AutoMapper(target = ManageDevicePayloadCustom.class, reverseConvertGenerate = false) +public class ManageDevicePayloadCustomBo extends BaseEntity { + + /** + * ID + */ +// @NotNull(message = "ID不能为空", groups = { EditGroup.class }) + private Long id; + + /** + * 载荷sn码 + */ +// @NotBlank(message = "载荷sn码不能为空", groups = { AddGroup.class, EditGroup.class }) +// @JsonValue("payloadSn") + @JsonAlias({"payload_sn"}) + private String payloadSn; + + /** + * 载荷名称 + */ +// @NotBlank(message = "载荷名称不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonAlias({"payload_name"}) + private String payloadName; + + /** + * 载荷类型 + */ +// @NotBlank(message = "载荷类型不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonAlias({"payload_type"}) + private String payloadType; + + /** + * 父级Id + */ + @JsonAlias({"parent_id"}) + private Long parentId; + + /** + * 设备版本 + */ + @JsonAlias({"firmware_version"}) + private String firmwareVersion; + + /** + * 所属机场 + */ +// @NotBlank(message = "所属机场不能为空", groups = { AddGroup.class, EditGroup.class }) + @JsonAlias({"dock_sn"}) + private String dockSn; + + /** + * 所属设备 + */ + @JsonAlias({"device_sn"}) + private String deviceSn; + + /** + * 所属无人机 + */ + private String droneSn; + + /** + * 设备中位置编号 + */ + private Long payloadIndex; + + /** + * 是否启动(1启用,0关闭) + */ + private Long enableFlag; + + /** + * 设备描述 + */ + private String payloadDesc; + + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/vo/ManageDevicePayloadCustomVo.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/vo/ManageDevicePayloadCustomVo.java new file mode 100644 index 0000000..d1d4863 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/domain/vo/ManageDevicePayloadCustomVo.java @@ -0,0 +1,100 @@ +package org.dromara.sample.manage.domain.vo; + +import org.dromara.sample.manage.domain.ManageDevicePayloadCustom; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.github.linpeilie.annotations.AutoMapper; +import lombok.Data; + +import java.io.Serial; +import java.io.Serializable; + + +/** + * 设备自定义/第三方载荷信息视图对象 manage_device_payload_custom + * + * @author szs + * @date 2025-06-18 + */ +@Data +@ExcelIgnoreUnannotated +@AutoMapper(target = ManageDevicePayloadCustom.class) +public class ManageDevicePayloadCustomVo implements Serializable { + + @Serial + private static final long serialVersionUID = 1L; + + /** + * ID + */ + @ExcelProperty(value = "ID") + private Long id; + + /** + * 载荷sn码 + */ + @ExcelProperty(value = "载荷sn码") + private String payloadSn; + + /** + * 载荷名称 + */ + @ExcelProperty(value = "载荷名称") + private String payloadName; + + /** + * 载荷类型 + */ + @ExcelProperty(value = "载荷类型") + private String payloadType; + + /** + * 父级Id + */ + @ExcelProperty(value = "父级Id") + private Long parentId; + + /** + * 设备版本 + */ + @ExcelProperty(value = "设备版本") + private String firmwareVersion; + + /** + * 所属机场 + */ + @ExcelProperty(value = "所属机场") + private String dockSn; + + /** + * 所属设备 + */ + @ExcelProperty(value = "所属设备") + private String deviceSn; + + /** + * 所属无人机 + */ + @ExcelProperty(value = "所属无人机") + private String droneSn; + + /** + * 设备中位置编号 + */ + @ExcelProperty(value = "设备中位置编号") + private Long payloadIndex; + + /** + * 是否启动(1启用,0关闭) + */ + @ExcelProperty(value = "是否启动(1启用,0关闭)") + private Long enableFlag; + + /** + * 设备描述 + */ + @ExcelProperty(value = "设备描述") + private String payloadDesc; + + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/mapper/ManageDevicePayloadCustomMapper.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/mapper/ManageDevicePayloadCustomMapper.java new file mode 100644 index 0000000..14863eb --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/mapper/ManageDevicePayloadCustomMapper.java @@ -0,0 +1,15 @@ +package org.dromara.sample.manage.mapper; + +import org.dromara.sample.manage.domain.ManageDevicePayloadCustom; +import org.dromara.sample.manage.domain.vo.ManageDevicePayloadCustomVo; +import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; + +/** + * 设备自定义/第三方载荷信息Mapper接口 + * + * @author szs + * @date 2025-06-18 + */ +public interface ManageDevicePayloadCustomMapper extends BaseMapperPlus { + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/dto/DeviceDTO.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/dto/DeviceDTO.java index d3edc5e..62a77b3 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/dto/DeviceDTO.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/dto/DeviceDTO.java @@ -1,11 +1,13 @@ package org.dromara.sample.manage.model.dto; +import cn.hutool.json.JSONObject; import io.swagger.v3.oas.annotations.media.Schema; import org.dromara.common.sdk.cloudapi.device.ControlSourceEnum; import org.dromara.common.sdk.cloudapi.device.DeviceDomainEnum; import org.dromara.common.sdk.cloudapi.device.DeviceSubTypeEnum; import org.dromara.common.sdk.cloudapi.device.DeviceTypeEnum; import org.dromara.common.sdk.cloudapi.tsa.DeviceIconUrl; +import org.dromara.sample.manage.domain.ManageDevicePayloadCustom; import org.dromara.sample.manage.model.entity.DeviceProEntity; import org.dromara.sample.manage.model.enums.DeviceFirmwareStatusEnum; @@ -117,4 +119,9 @@ public class DeviceDTO { private Long pushDeptId; + + private boolean spiritsmellFlag;//灵嗅设备状态: + private ManageDevicePayloadCustom payloadSpiritsmell;//灵嗅设备挂载: + + private JSONObject osdData;//redis中的osd数据 } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/enums/PropertySetFieldEnum.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/enums/PropertySetFieldEnum.java index 94dab47..4007bef 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/enums/PropertySetFieldEnum.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/enums/PropertySetFieldEnum.java @@ -27,15 +27,15 @@ public enum PropertySetFieldEnum { // EXIT_WAYLINE_WHEN_RC_LOST(PropertySetEnum.EXIT_WAYLINE_WHEN_RC_LOST, .class), // -// THERMAL_CURRENT_PALETTE_STYLE(PropertySetEnum.THERMAL_CURRENT_PALETTE_STYLE, .class), + THERMAL_CURRENT_PALETTE_STYLE(PropertySetEnum.THERMAL_CURRENT_PALETTE_STYLE, ThermalCurrentPaletteStyleReceiver.class), // -// THERMAL_GAIN_MODE(PropertySetEnum.THERMAL_GAIN_MODE, .class), + THERMAL_GAIN_MODE(PropertySetEnum.THERMAL_GAIN_MODE, ThermalGaiModeReceiver.class), // -// THERMAL_ISOTHERM_STATE(PropertySetEnum.THERMAL_ISOTHERM_STATE, .class), + THERMAL_ISOTHERM_STATE(PropertySetEnum.THERMAL_ISOTHERM_STATE, ThermalIsothermStateReceiver.class), // -// THERMAL_ISOTHERM_UPPER_LIMIT(PropertySetEnum.THERMAL_ISOTHERM_UPPER_LIMIT, .class), + THERMAL_ISOTHERM_UPPER_LIMIT(PropertySetEnum.THERMAL_ISOTHERM_UPPER_LIMIT, ThermalIsothermUpperLimitReceiver.class), // -// THERMAL_ISOTHERM_LOWER_LIMIT(PropertySetEnum.THERMAL_ISOTHERM_LOWER_LIMIT, .class), + THERMAL_ISOTHERM_LOWER_LIMIT(PropertySetEnum.THERMAL_ISOTHERM_LOWER_LIMIT, ThermalIsothermLowerLimitReceiver.class), ; diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/param/DeviceSubscribeParam.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/param/DeviceSubscribeParam.java new file mode 100644 index 0000000..7f837e9 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/param/DeviceSubscribeParam.java @@ -0,0 +1,17 @@ +package org.dromara.sample.manage.model.param; + +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.Data; +import org.springframework.web.bind.annotation.RequestParam; + +@Data +public class DeviceSubscribeParam { + + @JsonProperty("action") + private String action; + @JsonProperty("token") + private String token; + @JsonProperty("dock_sn") + private String dockSn; + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalCurrentPaletteStyleReceiver.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalCurrentPaletteStyleReceiver.java new file mode 100644 index 0000000..b78b974 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalCurrentPaletteStyleReceiver.java @@ -0,0 +1,41 @@ +package org.dromara.sample.manage.model.receiver; + +import com.fasterxml.jackson.annotation.JsonValue; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.dromara.common.sdk.cloudapi.device.OsdDockDrone; +import org.dromara.common.sdk.cloudapi.device.PayloadIndex; +import org.dromara.common.sdk.cloudapi.device.ThermalPaletteStyleEnum; +import org.dromara.common.sdk.cloudapi.property.ThermalCurrentPaletteStyleSet; + +import java.util.Map; +import java.util.Objects; + +/** + * @author sean.zhou + * @date 2021/11/18 + * @version 0.1 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ThermalCurrentPaletteStyleReceiver extends BasicDeviceProperty { + + private String payloadIndex; + + private int thermalCurrentPaletteStyle; + + @Override + public boolean valid() { + return Objects.nonNull(payloadIndex) && Objects.nonNull(thermalCurrentPaletteStyle); + } + + @Override + public boolean canPublish(OsdDockDrone osd) { + return true; + } + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalGaiModeReceiver.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalGaiModeReceiver.java new file mode 100644 index 0000000..7eb6fdc --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalGaiModeReceiver.java @@ -0,0 +1,36 @@ +package org.dromara.sample.manage.model.receiver; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.dromara.common.sdk.cloudapi.device.OsdDockDrone; + +import java.util.Objects; + +/** + * @author sean.zhou + * @date 2021/11/18 + * @version 0.1 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ThermalGaiModeReceiver extends BasicDeviceProperty { + + private String payloadIndex; + + private int thermalGainMde; + + @Override + public boolean valid() { + return Objects.nonNull(payloadIndex) && Objects.nonNull(thermalGainMde); + } + + @Override + public boolean canPublish(OsdDockDrone osd) { + return true; + } + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermLowerLimitReceiver.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermLowerLimitReceiver.java new file mode 100644 index 0000000..f171bad --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermLowerLimitReceiver.java @@ -0,0 +1,36 @@ +package org.dromara.sample.manage.model.receiver; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.dromara.common.sdk.cloudapi.device.OsdDockDrone; + +import java.util.Objects; + +/** + * @author sean.zhou + * @date 2021/11/18 + * @version 0.1 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ThermalIsothermLowerLimitReceiver extends BasicDeviceProperty { + + private String payloadIndex; + + private int thermalIsothermLowerLimit; + + @Override + public boolean valid() { + return Objects.nonNull(payloadIndex) && Objects.nonNull(thermalIsothermLowerLimit); + } + + @Override + public boolean canPublish(OsdDockDrone osd) { + return true; + } + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermStateReceiver.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermStateReceiver.java new file mode 100644 index 0000000..d657528 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermStateReceiver.java @@ -0,0 +1,36 @@ +package org.dromara.sample.manage.model.receiver; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.dromara.common.sdk.cloudapi.device.OsdDockDrone; + +import java.util.Objects; + +/** + * @author sean.zhou + * @date 2021/11/18 + * @version 0.1 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ThermalIsothermStateReceiver extends BasicDeviceProperty { + + private String payloadIndex; + + private int thermalIsothermState; + + @Override + public boolean valid() { + return Objects.nonNull(payloadIndex) && Objects.nonNull(thermalIsothermState); + } + + @Override + public boolean canPublish(OsdDockDrone osd) { + return true; + } + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermUpperLimitReceiver.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermUpperLimitReceiver.java new file mode 100644 index 0000000..e9ad205 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/model/receiver/ThermalIsothermUpperLimitReceiver.java @@ -0,0 +1,36 @@ +package org.dromara.sample.manage.model.receiver; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import org.dromara.common.sdk.cloudapi.device.OsdDockDrone; + +import java.util.Objects; + +/** + * @author sean.zhou + * @date 2021/11/18 + * @version 0.1 + */ +@EqualsAndHashCode(callSuper = true) +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ThermalIsothermUpperLimitReceiver extends BasicDeviceProperty { + + private String payloadIndex; + + private int thermalIsothermUpperLimit; + + @Override + public boolean valid() { + return Objects.nonNull(payloadIndex) && Objects.nonNull(thermalIsothermUpperLimit); + } + + @Override + public boolean canPublish(OsdDockDrone osd) { + return true; + } + +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceProService.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceProService.java index 6e6c321..d644a00 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceProService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceProService.java @@ -2,24 +2,13 @@ package org.dromara.sample.manage.service; import cn.hutool.core.lang.Dict; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.fasterxml.jackson.databind.JsonNode; -import org.apache.ibatis.annotations.Param; -import org.dromara.common.sdk.cloudapi.device.ControlSourceEnum; -import org.dromara.common.sdk.cloudapi.device.DeviceOsdHost; -import org.dromara.common.sdk.cloudapi.device.DockModeCodeEnum; -import org.dromara.common.sdk.cloudapi.device.DroneModeCodeEnum; -import org.dromara.common.sdk.common.HttpResultResponse; import org.dromara.common.sdk.common.PaginationData; -import org.dromara.common.sdk.config.version.GatewayManager; -import org.dromara.common.websocket.dto.BizCodeEnum; import org.dromara.sample.manage.model.dto.*; import org.dromara.sample.manage.model.entity.DeviceProEntity; import org.dromara.sample.manage.model.entity.DeviceProUserEntity; -import org.dromara.sample.manage.model.param.DeviceQueryParam; -import java.util.Collection; import java.util.List; -import java.util.Optional; +import java.util.Map; /** * @author sean.zhou @@ -36,7 +25,9 @@ public interface IDeviceProService { Boolean updateDevicePro(DeviceProEntity deviceProEntity); - Boolean updateDeviceProUser(List userEntity,Integer proId); + Boolean updateDeviceProUser(List userEntity, Integer proId); + + Boolean updateDeviceProUserNew(List> userEntity, Integer proId); Boolean updateDevice(Dict dict); @@ -56,4 +47,7 @@ public interface IDeviceProService { List listUserGroup(); + Boolean initProRedisCache(); + + } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceRedisService.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceRedisService.java index 3e78f12..6d783c4 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceRedisService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceRedisService.java @@ -1,10 +1,12 @@ package org.dromara.sample.manage.service; +import cn.hutool.json.JSONObject; import org.dromara.common.sdk.cloudapi.device.OsdDockDrone; import org.dromara.common.sdk.cloudapi.device.VideoId; import org.dromara.common.sdk.cloudapi.firmware.OtaProgress; import org.dromara.sample.component.mqtt.model.EventsReceiver; import org.dromara.sample.manage.model.dto.DeviceDTO; +import org.dromara.sample.wayline.domain.bo.WaylineJobAtmosphereBo; import java.util.List; import java.util.Optional; @@ -135,4 +137,14 @@ public interface IDeviceRedisService { Optional getDeviceVideo(String sn, Object data); Boolean delDeviceVideo(String sn); + + void setDeviceSpiritSmellOnline(String deviceSn, WaylineJobAtmosphereBo data); + + boolean checkDeviceSpiritSmell(String deviceSn); + + Optional getDeviceSpiritSmellOnline(String deviceSn); + + void pushDeviceSpiritSmellList(String deviceSn, WaylineJobAtmosphereBo jobAtmosphere); + + JSONObject getDevicesOsdList(String type); } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceService.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceService.java index 80e69e1..0067570 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IDeviceService.java @@ -167,6 +167,8 @@ public interface IDeviceService { */ int devicePropertySet(String workspaceId, String dockSn, JsonNode param); + int devicePropertySetData(String workspaceId, String dockSn, JsonNode param); + /** * Check the working status of the dock. * @param dockSn diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IManageDevicePayloadCustomService.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IManageDevicePayloadCustomService.java new file mode 100644 index 0000000..ac1dde8 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/IManageDevicePayloadCustomService.java @@ -0,0 +1,68 @@ +package org.dromara.sample.manage.service; + +import org.dromara.sample.manage.domain.vo.ManageDevicePayloadCustomVo; +import org.dromara.sample.manage.domain.bo.ManageDevicePayloadCustomBo; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; + +import java.util.Collection; +import java.util.List; + +/** + * 设备自定义/第三方载荷信息Service接口 + * + * @author szs + * @date 2025-06-18 + */ +public interface IManageDevicePayloadCustomService { + + /** + * 查询设备自定义/第三方载荷信息 + * + * @param id 主键 + * @return 设备自定义/第三方载荷信息 + */ + ManageDevicePayloadCustomVo queryById(Long id); + + /** + * 分页查询设备自定义/第三方载荷信息列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 设备自定义/第三方载荷信息分页列表 + */ + TableDataInfo queryPageList(ManageDevicePayloadCustomBo bo, PageQuery pageQuery); + + /** + * 查询符合条件的设备自定义/第三方载荷信息列表 + * + * @param bo 查询条件 + * @return 设备自定义/第三方载荷信息列表 + */ + List queryList(ManageDevicePayloadCustomBo bo); + + /** + * 新增设备自定义/第三方载荷信息 + * + * @param bo 设备自定义/第三方载荷信息 + * @return 是否新增成功 + */ + Boolean insertByBo(ManageDevicePayloadCustomBo bo); + + /** + * 修改设备自定义/第三方载荷信息 + * + * @param bo 设备自定义/第三方载荷信息 + * @return 是否修改成功 + */ + Boolean updateByBo(ManageDevicePayloadCustomBo bo); + + /** + * 校验并批量删除设备自定义/第三方载荷信息信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + Boolean deleteWithValidByIds(Collection ids, Boolean isValid); +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceProServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceProServiceImpl.java index fcec254..ea23938 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceProServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceProServiceImpl.java @@ -1,73 +1,36 @@ package org.dromara.sample.manage.service.impl; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.convert.impl.BeanConverter; import cn.hutool.core.lang.Dict; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; -import org.apache.ibatis.executor.BatchResult; -import org.dromara.common.core.constant.Constants; import org.dromara.common.core.exception.ServiceException; import org.dromara.common.redis.utils.RedisOpsUtils; import org.dromara.common.redis.utils.RedisUtils; import org.dromara.common.satoken.utils.LoginHelper; -import org.dromara.common.sdk.cloudapi.device.*; -import org.dromara.common.sdk.cloudapi.firmware.*; -import org.dromara.common.sdk.cloudapi.firmware.api.AbstractFirmwareService; -import org.dromara.common.sdk.cloudapi.property.api.AbstractPropertyService; -import org.dromara.common.sdk.cloudapi.tsa.DeviceIconUrl; -import org.dromara.common.sdk.cloudapi.tsa.TopologyDeviceModel; import org.dromara.common.sdk.common.*; -import org.dromara.common.sdk.config.version.GatewayManager; -import org.dromara.common.sdk.exception.CloudSDKException; -import org.dromara.common.sdk.mqtt.IMqttTopicService; -import org.dromara.common.sdk.mqtt.MqttGatewayPublish; -import org.dromara.common.sdk.mqtt.events.EventsSubscribe; -import org.dromara.common.sdk.mqtt.osd.OsdSubscribe; -import org.dromara.common.sdk.mqtt.property.PropertySetReplyResultEnum; -import org.dromara.common.sdk.mqtt.property.PropertySetSubscribe; -import org.dromara.common.sdk.mqtt.requests.RequestsSubscribe; -import org.dromara.common.sdk.mqtt.services.ServicesReplyData; -import org.dromara.common.sdk.mqtt.services.ServicesSubscribe; -import org.dromara.common.sdk.mqtt.services.TopicServicesResponse; -import org.dromara.common.sdk.mqtt.state.StateSubscribe; -import org.dromara.common.sdk.mqtt.status.StatusSubscribe; -import org.dromara.common.tenant.helper.TenantHelper; -import org.dromara.common.websocket.dto.BizCodeEnum; -import org.dromara.sample.common.error.CommonErrorEnum; -import org.dromara.sample.component.mqtt.model.EventsReceiver; -import org.dromara.sample.control.model.enums.DroneAuthorityEnum; +import org.dromara.sample.feign.RemoteSystemFeign; import org.dromara.sample.manage.mapper.IDeviceMapper; import org.dromara.sample.manage.mapper.IDeviceProMapper; import org.dromara.sample.manage.mapper.IDeviceProUserMapper; -import org.dromara.sample.manage.mapper.IDeviceQrtzMapper; import org.dromara.sample.manage.model.dto.*; import org.dromara.sample.manage.model.entity.DeviceEntity; import org.dromara.sample.manage.model.entity.DeviceProEntity; import org.dromara.sample.manage.model.entity.DeviceProUserEntity; -import org.dromara.sample.manage.model.entity.DeviceQrtzDateEntity; -import org.dromara.sample.manage.model.enums.DeviceFirmwareStatusEnum; -import org.dromara.sample.manage.model.enums.PropertySetFieldEnum; -import org.dromara.sample.manage.model.enums.UserTypeEnum; -import org.dromara.sample.manage.model.param.DeviceQueryParam; -import org.dromara.sample.manage.model.receiver.BasicDeviceProperty; import org.dromara.sample.manage.service.*; -import org.dromara.sample.websocket.service.IWebSocketMessageService; -import org.dromara.system.api.domain.vo.RemoteUserVo; import org.dromara.system.api.model.LoginUser; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import org.springframework.util.CollectionUtils; -import org.springframework.util.StringUtils; -import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; @@ -90,6 +53,9 @@ public class DeviceProServiceImpl implements IDeviceProService { @Autowired private IDeviceProUserMapper deviceProUserMapper; + @Autowired + RemoteSystemFeign remoteSystemFeign; + @Override public PaginationData listDeviceProEntityMap(Page page, DeviceProDTO deviceProDTO) { @@ -127,8 +93,7 @@ public class DeviceProServiceImpl implements IDeviceProService { } @Override - @Transactional(rollbackFor = Exception.class) - public Boolean updateDeviceProUser(List userEntity,Integer proId) { + public Boolean updateDeviceProUser(List userEntity, Integer proId) { try { List proUserEntityList = deviceProUserMapper.selectList(new LambdaQueryWrapper().eq(DeviceProUserEntity::getDeviceProId, proId)); @@ -142,6 +107,51 @@ public class DeviceProServiceImpl implements IDeviceProService { deviceProUserMapper.insert(different); } + //更新设备组redis缓存 + Boolean flag = updateDeviceProCache("update",null); + + return true; + } catch (ServiceException e) { + log.error(e.getMessage(),e); + return false; + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public Boolean updateDeviceProUserNew(List> userEntity, Integer proId) { + try { + List> resultList = remoteSystemFeign.listTargetTypeByUser(userEntity); + + //构建DeviceProUserEntity集合 + List userEntityList = new ArrayList<>(); + + resultList.forEach(resultMap -> { + DeviceProUserEntity deviceProUserEntity = new DeviceProUserEntity(); + deviceProUserEntity.setDeviceProId(proId); + deviceProUserEntity.setUserId(Long.valueOf(resultMap.get("userId") + "")); + deviceProUserEntity.setUserName(resultMap.get("userName") + ""); + deviceProUserEntity.setNickName(resultMap.get("nickName") + ""); + + userEntityList.add(deviceProUserEntity); + }); + + + List proUserEntityList = deviceProUserMapper.selectList(new LambdaQueryWrapper().eq(DeviceProUserEntity::getDeviceProId, proId)); + + List different = userEntityList.stream() + .filter(user -> proUserEntityList.stream().noneMatch(u -> u.getUserId().equals(user.getUserId()))) + .toList(); + + + if (ObjectUtil.isNotEmpty(different)){ + //添加新的项目组成员 + deviceProUserMapper.insert(different); + } + + //更新设备组redis缓存 + Boolean flag = updateDeviceProCache("update",null); + return true; } catch (ServiceException e) { log.error(e.getMessage(),e); @@ -149,6 +159,67 @@ public class DeviceProServiceImpl implements IDeviceProService { } } + /** + * 更新设备组人员缓存 + * @return + */ + private Boolean updateDeviceProCache(String operateType,Long proUserId) { + + try { + // -------------------------------------- redis缓存 --------------------------------------------------- + //更新redis缓存 + //1、如何存储redis 人员 项目组id device_pro:userId -> List proIdList + // device_pro: + //查询所有的用户-设备组信息 + List proUserList = deviceProUserMapper.selectList(new LambdaQueryWrapper<>()); + + //分组 + Map> proUserMap = proUserList.stream() + .collect(Collectors.groupingBy( + DeviceProUserEntity::getUserId, // 按 userId 分组 + Collectors.mapping(DeviceProUserEntity::getDeviceProId, Collectors.toList()) // 收集每个 userId 对应的 DeviceProId 列表 + )); + + + //如果是删除操作 + if (operateType.equalsIgnoreCase("delete")){ + if (!proUserMap.containsKey(proUserId)){ + if (RedisUtils.hasKey("device_pro:" + proUserId)){ + RedisUtils.deleteObject("device_pro:" + proUserId); + } + } + } + + + //更新redis设备组信息 + proUserMap.keySet().forEach(userId -> { + //获取最新的用户设备组信息 + List currentProId = proUserMap.get(userId); + + List cacheList = RedisUtils.getCacheList("device_pro:" + userId); + + log.info("设备组缓存:{}",cacheList); + + //删除这个用户的设备组信息 + if (RedisUtils.hasKey("device_pro:" + userId)){ + RedisUtils.deleteObject("device_pro:" + userId); + + } + + //更新设备组信息 + RedisUtils.setCacheList("device_pro:" + userId, currentProId); + + }); + // -------------------------------------- redis缓存 --------------------------------------------------- + + return true; + } catch (Exception e) { + log.error(e.getMessage(),e); + return false; + } + + } + /** * 绑定设备的项目组 * @param dict @@ -183,6 +254,15 @@ public class DeviceProServiceImpl implements IDeviceProService { */ @Override public List listDeviceGroup(Long userId) { + try { + List userIds = RedisUtils.getCacheList("device_pro:" + userId); +// List collect = RedisOpsUtils.listGetAll("device_pro:" + userId); +// List userIds = collect.stream().map(item -> (Integer) item).collect(Collectors.toList()); + if (CollUtil.isNotEmpty(userIds)) {return userIds;}//从缓存直接读取 + } catch (Exception e) { + System.out.println("找不到pro用户" + "device_pro" + userId); + } + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(DeviceProUserEntity::getUserId,userId); List proUserEntityList = deviceProUserMapper.selectList(wrapper); @@ -265,7 +345,15 @@ public class DeviceProServiceImpl implements IDeviceProService { LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); wrapper.eq(DeviceProUserEntity::getDeviceProId,proId); wrapper.eq(DeviceProUserEntity::getId,proUserId); - return deviceProUserMapper.delete(wrapper) > 0; + + DeviceProUserEntity deviceProUserEntity = deviceProUserMapper.selectById(proUserId); + + int flag = deviceProUserMapper.delete(wrapper); + + //更新缓存 + updateDeviceProCache("delete",deviceProUserEntity.getUserId()); + + return flag > 0; } @Override @@ -286,6 +374,12 @@ public class DeviceProServiceImpl implements IDeviceProService { return ListUtil.empty(); } + @Override + public Boolean initProRedisCache() { + return this.updateDeviceProCache("init",null); + } + + @Override public Boolean saveAndUpdate(DeviceProEntity entity) { boolean flag = true; diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceRedisServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceRedisServiceImpl.java index 74c57e0..f57fe34 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceRedisServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceRedisServiceImpl.java @@ -1,8 +1,14 @@ package org.dromara.sample.manage.service.impl; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONArray; +import cn.hutool.json.JSONObject; import org.dromara.common.redis.config.RedisConst; import org.dromara.common.redis.utils.RedisOpsUtils; import org.dromara.common.redis.utils.RedisUtils; +import org.dromara.common.sdk.cloudapi.device.DockDronePayload; +import org.dromara.common.sdk.cloudapi.device.OsdDock; import org.dromara.common.sdk.cloudapi.device.OsdDockDrone; import org.dromara.common.sdk.cloudapi.device.VideoId; import org.dromara.common.sdk.cloudapi.firmware.OtaProgress; @@ -10,6 +16,7 @@ import org.dromara.sample.component.mqtt.model.EventsReceiver; import org.dromara.sample.manage.model.dto.DeviceDTO; import org.dromara.sample.manage.service.ICapacityCameraService; import org.dromara.sample.manage.service.IDeviceRedisService; +import org.dromara.sample.wayline.domain.bo.WaylineJobAtmosphereBo; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -41,6 +48,125 @@ public class DeviceRedisServiceImpl implements IDeviceRedisService { return Optional.ofNullable((DeviceDTO) RedisOpsUtils.get(RedisConst.DEVICE_ONLINE_PREFIX + sn)); } + @Override + public JSONObject getDevicesOsdList(String type) { + JSONObject resJsonObject = new JSONObject(); //机场 droneInDock + Set osdKeys = RedisOpsUtils.getAllKeys(RedisConst.OSD_PREFIX+"*"); + for (String osdKey : osdKeys) { + Object osdObj = RedisOpsUtils.get(osdKey); + + if(StrUtil.equals(type,"dock") && osdObj instanceof OsdDockDrone ){continue;} + if(StrUtil.equals(type,"drone") && osdObj instanceof OsdDock){continue;} + + //处理机场数据 + /** + * { + * "droneChargeState": { + * "state": false, + * "capacityPercent": 90 + * }, + * "latitude": 34.64393, + * "longitude": 116.82873, + * "height": 37.8021, + * "modeCode": 0 + * } + */ + if(osdObj instanceof OsdDock ){ //org.plough.sdk.cloudapi.device.OsdDock + + OsdDock dock = (OsdDock) osdObj; +// OsdDockVo osdDockVo = new OsdDockVo(); +// BeanUtil.copyProperties(dock, osdDockVo); + + JSONObject item = new JSONObject(); + item.put("droneChargeState", dock.getDroneChargeState()); + item.put("latitude", dock.getLatitude()); + item.put("longitude", dock.getLongitude()); + item.put("height", dock.getHeight()); + item.put("modeCode", dock.getModeCode()); + resJsonObject.put(osdKey.replaceFirst(RedisConst.OSD_PREFIX,""), item); + + //处理无人机数据 + /** + * { + * "attitudeHead": -177, + * "attitudePitch": 0.9, + * "attitudeRoll": -0.8, + * "battery": { + * "capacityPercent": 89, + * "landingPower": 8, + * "remainFlightTime": 0, + * "returnHomePower": 25 + * }, + * "height": 63.853302, + * "latitude": 34.19659, + * "longitude": 117.0838, + * "modeCode": 5, + * "trackId": "48f03cfa-4c61-4cff-8388-faac69605426", + * "payload": [ + * { + * "payloadIndex": "81-0-0", + * "gimbalPitch": 0, + * "gimbalRoll": 0, + * "gimbalYaw": -177.15698 + * } + * ] + * } + */ +// }else if(osdObj.getClass().getName().equals("org.plough.sdk.cloudapi.device.OsdDockDrone") ){ //org.plough.sdk.cloudapi.device.OsdDockDrone + }else if(osdObj instanceof OsdDockDrone){ //org.plough.sdk.cloudapi.device.OsdDockDrone + + OsdDockDrone dockDrone = (OsdDockDrone) osdObj; +// OsdDockDroneVo dockDroneVo = new OsdDockDroneVo(); +// BeanUtil.copyProperties(dockDrone, dockDroneVo); + + JSONObject item = new JSONObject(); + item.put("attitudeHead", dockDrone.getAttitudeHead()); + item.put("attitudePitch", dockDrone.getAttitudePitch()); + item.put("attitudeRoll", dockDrone.getAttitudeRoll()); + if (dockDrone.getBattery() != null) { + JSONObject battery = new JSONObject(); + battery.put("capacityPercent", dockDrone.getBattery().getCapacityPercent()); + battery.put("landingPower", dockDrone.getBattery().getLandingPower()); + battery.put("remainFlightTime", dockDrone.getBattery().getRemainFlightTime()); + battery.put("returnHomePower", dockDrone.getBattery().getReturnHomePower()); + item.put("battery", battery); + } + item.put("height", dockDrone.getHeight()); + item.put("latitude", dockDrone.getLatitude()); + item.put("longitude", dockDrone.getLongitude()); + item.put("modeCode", dockDrone.getModeCode()); + item.put("trackId", dockDrone.getTrackId()); + // payload(只保留4个字段) + if (dockDrone.getPayloads() != null && !dockDrone.getPayloads().isEmpty()) { + JSONArray payloadArray = new JSONArray(); + for (DockDronePayload payload : dockDrone.getPayloads()) { + JSONObject payloadObj = new JSONObject(); + payloadObj.put("payloadIndex", payload.getPayloadIndex()); + payloadObj.put("gimbalPitch", payload.getGimbalPitch()); + payloadObj.put("gimbalRoll", payload.getGimbalRoll()); + payloadObj.put("gimbalYaw", payload.getGimbalYaw()); + payloadArray.add(payloadObj); + } + item.put("payload", payloadArray); + } + resJsonObject.put(osdKey.replaceFirst(RedisConst.OSD_PREFIX, ""), item); + } + } + return resJsonObject; + } + + + @Override + public Optional getDeviceSpiritSmellOnline(String deviceSn) { + return Optional.ofNullable((WaylineJobAtmosphereBo) RedisOpsUtils.get(RedisConst.DEVICE_SPIRITSMELL_PREFIX + deviceSn)); + } + + @Override + public void pushDeviceSpiritSmellList(String deviceSn, WaylineJobAtmosphereBo jobAtmosphere) { + RedisOpsUtils.listRPush(RedisConst.DEVICE_SPIRITSMELL_LIST_PREFIX + deviceSn,jobAtmosphere); +// RedisOpsUtils.setWithExpire(RedisConst.DEVICE_SPIRITSMELL_PREFIX + deviceSn, data, 30); + } + @Override public void setDeviceOnline(DeviceDTO device) { RedisOpsUtils.setWithExpire(RedisConst.DEVICE_ONLINE_PREFIX + device.getDeviceSn(), device, RedisConst.DEVICE_ALIVE_SECOND); @@ -51,6 +177,20 @@ public class DeviceRedisServiceImpl implements IDeviceRedisService { return RedisOpsUtils.del(RedisConst.DEVICE_ONLINE_PREFIX + sn); } + @Override + public void setDeviceSpiritSmellOnline(String deviceSn, WaylineJobAtmosphereBo data) { + RedisOpsUtils.setWithExpire(RedisConst.DEVICE_SPIRITSMELL_PREFIX + deviceSn, data, 30); + } + + @Override + public boolean checkDeviceSpiritSmell(String deviceSn) { + return RedisOpsUtils.checkExist(RedisConst.DEVICE_SPIRITSMELL_PREFIX + deviceSn); +// && +// RedisOpsUtils.getExpire(RedisConst.DEVICE_SPIRITSMELL_PREFIX + deviceSn) > 0 ; +// BooleanUtil.toBoolean(RedisOpsUtils.get(RedisConst.DEVICE_SPIRITSMELL_PREFIX + deviceSn).toString()); + } + + @Override public void setDeviceOsd(String sn, Object data) { RedisOpsUtils.setWithExpire(RedisConst.OSD_PREFIX + sn, data, RedisConst.DEVICE_ALIVE_SECOND); diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceServiceImpl.java index bda7cef..0f8c56d 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/DeviceServiceImpl.java @@ -1,5 +1,7 @@ package org.dromara.sample.manage.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; @@ -32,8 +34,10 @@ import org.dromara.common.websocket.dto.BizCodeEnum; import org.dromara.sample.common.error.CommonErrorEnum; import org.dromara.sample.component.mqtt.model.EventsReceiver; import org.dromara.sample.control.model.enums.DroneAuthorityEnum; +import org.dromara.sample.manage.domain.ManageDevicePayloadCustom; import org.dromara.sample.manage.mapper.IDeviceMapper; import org.dromara.sample.manage.mapper.IDeviceProMapper; +import org.dromara.sample.manage.mapper.ManageDevicePayloadCustomMapper; import org.dromara.sample.manage.model.dto.*; import org.dromara.sample.manage.model.entity.DeviceEntity; import org.dromara.sample.manage.model.entity.DeviceProEntity; @@ -61,6 +65,7 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import java.util.stream.Collectors; +import java.util.stream.Stream; import static org.dromara.common.core.utils.StringUtils.DASH; import static org.dromara.common.core.utils.StringUtils.SLASH; @@ -139,6 +144,9 @@ public class DeviceServiceImpl implements IDeviceService { @Autowired private IDeviceProMapper deviceProMapper; + @Autowired + private ManageDevicePayloadCustomMapper manageDevicePayloadCustomMapper; + @Autowired private IDeviceProService deviceProService; @@ -264,6 +272,21 @@ public class DeviceServiceImpl implements IDeviceService { deviceRedisService.checkDeviceOnline(gateway.getDeviceSn())) .forEach(this::spliceDeviceTopo); + //验证第三方挂载状态(灵嗅) + List deviceSnList = devicesList.stream().map(DeviceDTO::getDeviceSn).collect(Collectors.toList()); + LambdaQueryWrapper payloadCustomMapper = new LambdaQueryWrapper<>(); + payloadCustomMapper.in(CollUtil.isNotEmpty(deviceSnList),ManageDevicePayloadCustom::getDockSn, deviceSnList); + List payloadCustomList = manageDevicePayloadCustomMapper.selectList(payloadCustomMapper); + for (DeviceDTO deviceDTO : devicesList) { + ManageDevicePayloadCustom spiritsmellV2 = payloadCustomList.stream().filter(item -> + ObjectUtil.equals(item.getDockSn(), deviceDTO.getDeviceSn()) && + ObjectUtil.equals(item.getPayloadName(), "spiritsmellV2")).findFirst().orElse(null); +// long spiritsmellV2Count = payloadCustomList.stream().filter(item -> +// ObjectUtil.equals(item.getDockSn(), deviceDTO.getDeviceSn()) && +// ObjectUtil.equals(item.getPayloadName(), "spiritsmellV2")).count(); + deviceDTO.setPayloadSpiritsmell(spiritsmellV2); + } + return devicesList; } @@ -271,6 +294,7 @@ public class DeviceServiceImpl implements IDeviceService { public void spliceDeviceTopo(DeviceDTO gateway) { gateway.setStatus(deviceRedisService.checkDeviceOnline(gateway.getDeviceSn())); + gateway.setSpiritsmellFlag(deviceRedisService.checkDeviceSpiritSmell(gateway.getDeviceSn()));//验证是否有灵嗅在线 // sub device if (!StringUtils.hasText(gateway.getChildDeviceSn())) { @@ -693,6 +717,39 @@ public class DeviceServiceImpl implements IDeviceService { return result.getResult(); } + + @Override + public int devicePropertySetData(String workspaceId, String dockSn, JsonNode param) { + String property = param.fieldNames().next(); + PropertySetFieldEnum propertyEnum = PropertySetFieldEnum.find(property); + + Optional dockOpt = deviceRedisService.getDeviceOnline(dockSn); + if (dockOpt.isEmpty()) { + throw new RuntimeException("Dock处于脱机状态。"); + } + String childSn = dockOpt.get().getChildDeviceSn(); + Optional osdOpt = deviceRedisService.getDeviceOsd(childSn, OsdDockDrone.class); + if (osdOpt.isEmpty()) { + throw new RuntimeException("设备处于脱机状态。"); + } + + // Make sure the data is valid. + BasicDeviceProperty basicDeviceProperty = objectMapper.convertValue(param.get(property), propertyEnum.getClazz()); + boolean valid = basicDeviceProperty.valid(); + if (!valid) { + throw new IllegalArgumentException(CommonErrorEnum.ILLEGAL_ARGUMENT.getMessage()); + } + boolean isPublish = basicDeviceProperty.canPublish(osdOpt.get()); + if (!isPublish) { + return PropertySetReplyResultEnum.SUCCESS.getResult(); + } + + BaseModel baseModel = objectMapper.convertValue(param.get(property), propertyEnum.getProperty().getClazz()); + PropertySetReplyResultEnum result = abstractPropertyService.propertySet( + SDKManager.getDeviceSDK(dockSn), propertyEnum.getProperty(), baseModel); + return result.getResult(); + } + @Override public DockModeCodeEnum getDockMode(String dockSn) { return deviceRedisService.getDeviceOsd(dockSn, OsdDock.class) diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/ManageDevicePayloadCustomServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/ManageDevicePayloadCustomServiceImpl.java new file mode 100644 index 0000000..0bc2edb --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/manage/service/impl/ManageDevicePayloadCustomServiceImpl.java @@ -0,0 +1,139 @@ +package org.dromara.sample.manage.service.impl; + +import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StringUtils; +import org.dromara.common.mybatis.core.page.TableDataInfo; +import org.dromara.common.mybatis.core.page.PageQuery; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import lombok.RequiredArgsConstructor; +import org.springframework.stereotype.Service; +import org.dromara.sample.manage.domain.bo.ManageDevicePayloadCustomBo; +import org.dromara.sample.manage.domain.vo.ManageDevicePayloadCustomVo; +import org.dromara.sample.manage.domain.ManageDevicePayloadCustom; +import org.dromara.sample.manage.mapper.ManageDevicePayloadCustomMapper; +import org.dromara.sample.manage.service.IManageDevicePayloadCustomService; + +import java.util.List; +import java.util.Map; +import java.util.Collection; + +/** + * 设备自定义/第三方载荷信息Service业务层处理 + * + * @author szs + * @date 2025-06-18 + */ +@RequiredArgsConstructor +@Service +public class ManageDevicePayloadCustomServiceImpl implements IManageDevicePayloadCustomService { + + private final ManageDevicePayloadCustomMapper baseMapper; + + /** + * 查询设备自定义/第三方载荷信息 + * + * @param id 主键 + * @return 设备自定义/第三方载荷信息 + */ + @Override + public ManageDevicePayloadCustomVo queryById(Long id){ + return baseMapper.selectVoById(id); + } + + /** + * 分页查询设备自定义/第三方载荷信息列表 + * + * @param bo 查询条件 + * @param pageQuery 分页参数 + * @return 设备自定义/第三方载荷信息分页列表 + */ + @Override + public TableDataInfo queryPageList(ManageDevicePayloadCustomBo bo, PageQuery pageQuery) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + Page result = baseMapper.selectVoPage(pageQuery.build(), lqw); + return TableDataInfo.build(result); + } + + /** + * 查询符合条件的设备自定义/第三方载荷信息列表 + * + * @param bo 查询条件 + * @return 设备自定义/第三方载荷信息列表 + */ + @Override + public List queryList(ManageDevicePayloadCustomBo bo) { + LambdaQueryWrapper lqw = buildQueryWrapper(bo); + return baseMapper.selectVoList(lqw); + } + + private LambdaQueryWrapper buildQueryWrapper(ManageDevicePayloadCustomBo bo) { + Map params = bo.getParams(); + LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); + lqw.eq(StringUtils.isNotBlank(bo.getPayloadSn()), ManageDevicePayloadCustom::getPayloadSn, bo.getPayloadSn()); + lqw.like(StringUtils.isNotBlank(bo.getPayloadName()), ManageDevicePayloadCustom::getPayloadName, bo.getPayloadName()); + lqw.eq(StringUtils.isNotBlank(bo.getPayloadType()), ManageDevicePayloadCustom::getPayloadType, bo.getPayloadType()); + lqw.eq(bo.getParentId() != null, ManageDevicePayloadCustom::getParentId, bo.getParentId()); + lqw.eq(StringUtils.isNotBlank(bo.getFirmwareVersion()), ManageDevicePayloadCustom::getFirmwareVersion, bo.getFirmwareVersion()); + lqw.eq(StringUtils.isNotBlank(bo.getDockSn()), ManageDevicePayloadCustom::getDockSn, bo.getDockSn()); + lqw.eq(StringUtils.isNotBlank(bo.getDeviceSn()), ManageDevicePayloadCustom::getDeviceSn, bo.getDeviceSn()); + lqw.eq(StringUtils.isNotBlank(bo.getDroneSn()), ManageDevicePayloadCustom::getDroneSn, bo.getDroneSn()); + lqw.eq(bo.getPayloadIndex() != null, ManageDevicePayloadCustom::getPayloadIndex, bo.getPayloadIndex()); + lqw.eq(bo.getEnableFlag() != null, ManageDevicePayloadCustom::getEnableFlag, bo.getEnableFlag()); + lqw.eq(StringUtils.isNotBlank(bo.getPayloadDesc()), ManageDevicePayloadCustom::getPayloadDesc, bo.getPayloadDesc()); + return lqw; + } + + /** + * 新增设备自定义/第三方载荷信息 + * + * @param bo 设备自定义/第三方载荷信息 + * @return 是否新增成功 + */ + @Override + public Boolean insertByBo(ManageDevicePayloadCustomBo bo) { + ManageDevicePayloadCustom add = MapstructUtils.convert(bo, ManageDevicePayloadCustom.class); + validEntityBeforeSave(add); + boolean flag = baseMapper.insert(add) > 0; + if (flag) { + bo.setId(add.getId()); + } + return flag; + } + + /** + * 修改设备自定义/第三方载荷信息 + * + * @param bo 设备自定义/第三方载荷信息 + * @return 是否修改成功 + */ + @Override + public Boolean updateByBo(ManageDevicePayloadCustomBo bo) { + ManageDevicePayloadCustom update = MapstructUtils.convert(bo, ManageDevicePayloadCustom.class); + validEntityBeforeSave(update); + return baseMapper.updateById(update) > 0; + } + + /** + * 保存前的数据校验 + */ + private void validEntityBeforeSave(ManageDevicePayloadCustom entity){ + //TODO 做一些数据校验,如唯一约束 + } + + /** + * 校验并批量删除设备自定义/第三方载荷信息信息 + * + * @param ids 待删除的主键集合 + * @param isValid 是否进行有效性校验 + * @return 是否删除成功 + */ + @Override + public Boolean deleteWithValidByIds(Collection ids, Boolean isValid) { + if(isValid){ + //TODO 做一些业务上的校验,判断是否需要校验 + } + return baseMapper.deleteByIds(ids) > 0; + } +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java index 905b9fb..edb5495 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/controller/FileController.java @@ -1,21 +1,34 @@ package org.dromara.sample.media.controller; +import cn.hutool.core.util.ObjectUtil; +import com.amazonaws.util.IOUtils; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.servlet.http.HttpServletResponse; +import org.dromara.common.core.exception.ServiceException; +import org.dromara.common.core.utils.file.FileUtils; +import org.dromara.common.oss.core.OssClient; +import org.dromara.common.oss.factory.OssFactory; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.common.sdk.common.HttpResultResponse; import org.dromara.common.sdk.common.PaginationData; import org.dromara.sample.manage.service.IDeviceProService; import org.dromara.sample.media.model.MediaFileDTO; +import org.dromara.sample.media.model.MediaFileEntity; import org.dromara.sample.media.service.IFileService; +import org.dromara.sample.wayline.service.IWaylineJobService; import org.dromara.system.api.model.LoginUser; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.*; -import java.io.IOException; +import java.io.*; import java.net.URL; +import java.net.URLEncoder; import java.util.List; +import java.util.Optional; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; /** * @author sean @@ -30,6 +43,9 @@ public class FileController { @Autowired private IFileService fileService; + @Autowired + private IWaylineJobService waylineJobService; + /** @@ -81,11 +97,68 @@ public class FileController { @RequestParam(name = "type", required = false) Integer type) { PaginationData filesList = fileService.getMediaFilesPaginationByJobId(workspaceId, page, pageSize,jobId,type); for (MediaFileDTO mediaFileDTO :filesList.getList()){ - mediaFileDTO.setUrl(fileService.getObjectUrl(workspaceId, mediaFileDTO.getFileId()).toString()); + mediaFileDTO.setUrl(fileService.getObjectUrl(mediaFileDTO.getObjectKey()).toString()); } return HttpResultResponse.success(filesList); } + + @GetMapping("/{workspace_id}/file/downloadZip/{job_id}") + public void downloadZip( HttpServletResponse response, @PathVariable(name = "workspace_id") String workspaceId, + @PathVariable(name = "job_id") String jobId, @RequestParam(name = "jobName", required = false) String jobName) throws IOException { + List mediaFileDTO = fileService.getFilesByWorkspaceAndJobId(workspaceId, jobId).stream().map(MediaFileDTO::getObjectKey).toList(); + if(mediaFileDTO.size() == 0){ + throw new ServiceException("文件不存在"); + } + OssClient storage = OssFactory.instance("mediafile"); + response.setContentType("application/zip"); + if(ObjectUtil.isNull(jobName)){ + jobName = waylineJobService.getJobByJobId(workspaceId,jobId).get().getJobName(); + } + String encodedJobName = URLEncoder.encode(jobName, "UTF-8"); + response.setHeader("Content-Disposition", "attachment; filename="+encodedJobName+".zip"); + try (ZipOutputStream zipOut = new ZipOutputStream(response.getOutputStream())) { + byte[] buffer = new byte[1024]; + for (String objectKey : mediaFileDTO) { + try (InputStream inputStream = storage.getObjectContent(objectKey)) { + // 创建一个新的 ZIP 条目 + zipOut.putNextEntry(new ZipEntry(objectKey)); + + int len; + // 读取文件内容并写入到 ZIP 输出流 + while ((len = inputStream.read(buffer)) != -1) { + zipOut.write(buffer, 0, len); + } + + // 完成当前条目的写入 + zipOut.closeEntry(); + } catch (IOException e) { + e.printStackTrace(); // 如果有某个文件出错,跳过该文件并继续处理其他文件 + } + } + + zipOut.flush(); + } catch (IOException e) { + e.printStackTrace(); + } + } + + + @GetMapping("/{workspace_id}/file/download/{file_id}") + public void downloadZip( HttpServletResponse response, @PathVariable(name = "workspace_id") String workspaceId, + @PathVariable(name = "file_id") String fileId) throws IOException { + Optional mediaFileDTO = fileService.getObjectByFileId(workspaceId,fileId); + + OssClient storage = OssFactory.instance("mediafile"); + String jobName = waylineJobService.getJobByJobId(workspaceId,mediaFileDTO.get().getJobId()).get().getJobName(); + String[] filePaths = mediaFileDTO.get().getObjectKey().split("\\."); + FileUtils.setAttachmentResponseHeader(response, jobName+"."+filePaths[filePaths.length-1]); + response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE + "; charset=UTF-8"); + long contentLength = storage.download(mediaFileDTO.get().getObjectKey(), response.getOutputStream()); + response.setContentLengthLong(contentLength); + } + + /** * 根据文件id查询图片的偏航角 * @param fileId diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java index 86e0221..f04cfd2 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/IFileService.java @@ -4,9 +4,11 @@ import org.dromara.common.sdk.cloudapi.media.FlightTask; import org.dromara.common.sdk.cloudapi.media.MediaUploadCallbackRequest; import org.dromara.common.sdk.common.PaginationData; import org.dromara.sample.media.model.MediaFileDTO; +import org.dromara.sample.media.model.MediaFileEntity; import java.net.URL; import java.util.List; +import java.util.Optional; /** * @author sean @@ -55,6 +57,10 @@ public interface IFileService { */ URL getObjectUrl(String workspaceId, String fileId); + Optional getObjectByFileId(String workspaceId, String fileId); + + URL getObjectUrl(String objectKey); + /** * Query all media files of a job. * @param workspaceId diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java index 3d0a0b9..f99b84a 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/media/service/impl/FileServiceImpl.java @@ -109,6 +109,7 @@ public class FileServiceImpl implements IFileService { .collect(Collectors.toList()); } + @Override public PaginationData getMediaFilesPaginationByWorkspaceId(String workspaceId, long page, long pageSize,List proIds) { LoginUser loginUser = LoginHelper.getLoginUser(); @@ -139,6 +140,22 @@ public class FileServiceImpl implements IFileService { return storage.getPrivateUrlURL(mediaFileOpt.get().getObjectKey(),3600); } + @Override + public URL getObjectUrl(String objectKey) { + OssClient storage = OssFactory.instance("mediafile"); + return storage.getPrivateUrlURL(objectKey,3600); + } + + + @Override + public Optional getObjectByFileId(String workspaceId, String fileId) { + Optional mediaFileOpt = getMediaByFileId(workspaceId, fileId); + if (mediaFileOpt.isEmpty()) { + throw new IllegalArgumentException("{} 不存在。"); + } + return mediaFileOpt; + } + @Override public List getFilesByWorkspaceAndJobId(String workspaceId, String jobId) { return mapper.selectList(new LambdaQueryWrapper() diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobAtmosphereController.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobAtmosphereController.java index 2fe9863..03ad6ab 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobAtmosphereController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobAtmosphereController.java @@ -1,8 +1,13 @@ package org.dromara.sample.wayline.controller; +import java.util.ArrayList; +import java.util.Date; import java.util.List; import java.util.Optional; +import cn.hutool.core.date.DateTime; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.ObjectUtil; import lombok.RequiredArgsConstructor; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.constraints.*; @@ -51,6 +56,43 @@ public class WaylineJobAtmosphereController extends BaseController { return waylineJobAtmosphereService.queryPageList(bo, pageQuery); } + /** + * 查询灵嗅记录 waylineJobId / dockSn + * @param bo + * @return + */ + @SaCheckPermission("sample:WaylineJobAtmosphere:list") + @GetMapping("/listQuery") + public List listQuery(WaylineJobAtmosphereBo bo) { + return waylineJobAtmosphereService.queryList(bo); + } + + + /** + * 根据时间查询记录 day / dayTime + * @param bo + * @return + */ + @SaCheckPermission("sample:WaylineJobAtmosphere:list") + @GetMapping("/listTime") + public List listTime(WaylineJobAtmosphereBo bo) { + List dayList = new ArrayList<>(); + //没传开始-结束时间 默认查今天数据 + if (ObjectUtil.isEmpty(bo.getDayStart()) || ObjectUtil.isEmpty(bo.getDayEnd())) { + Date currentDate = new Date(); + DateTime dayStart = DateUtil.beginOfDay(currentDate); + DateTime dayEnd = DateUtil.endOfDay(currentDate); + dayList = waylineJobAtmosphereService.selectByDateRange(bo.getDockSn(), dayStart, dayEnd); + } else if (ObjectUtil.isNotEmpty(bo.getDayStart()) || ObjectUtil.isNotEmpty(bo.getDayEnd())) { + DateTime dayStart = DateUtil.date(bo.getDayStart()); + DateTime dayEnd = DateUtil.date(bo.getDayEnd()); + dayList = waylineJobAtmosphereService.selectByDateRange(bo.getDockSn(), dayStart, dayEnd); + } + return dayList; + } + + + /** 演示数据返回前台 **/ @GetMapping("/list/demo") public List demoList(WaylineJobAtmosphereBo bo, PageQuery pageQuery) { List demoList= waylineJobAtmosphereService.demoList(bo); diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java index 7edd719..8d38c39 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/controller/WaylineJobController.java @@ -19,10 +19,7 @@ import org.dromara.sample.wayline.model.enums.WaylineTaskStatusEnum; import org.dromara.sample.wayline.model.entity.WaylineFileEntity; import org.dromara.sample.wayline.model.param.CreateJobParam; import org.dromara.sample.wayline.model.param.UpdateJobParam; -import org.dromara.sample.wayline.service.IFlightTaskService; -import org.dromara.sample.wayline.service.IWaylineFileService; -import org.dromara.sample.wayline.service.IWaylineJobService; -import org.dromara.sample.wayline.service.IWaylineRedisService; +import org.dromara.sample.wayline.service.*; import org.dromara.sample.wayline.service.IWaylineRedisService; import org.dromara.sample.wayline.service.impl.WaylineFileServiceImpl; import org.dromara.system.api.model.LoginUser; @@ -89,11 +86,44 @@ public class WaylineJobController { @PathVariable(name = "workspace_id") String workspaceId, @RequestParam(name = "proIds" , required = false) List proIds, @RequestParam(name = "fileId" , required = false) String fileId, - @RequestParam(name = "name" , required = false) String name) { - PaginationData data = waylineJobService.getJobsByWorkspaceId(workspaceId, page, pageSize,fileId,proIds,name); + @RequestParam(name = "name" , required = false) String name, + @RequestParam(name = "mediaCount" , required = false) Integer mediaCount) { + PaginationData data = waylineJobService.getJobsByWorkspaceId(workspaceId, page, pageSize,fileId,proIds,name,mediaCount); + return HttpResultResponse.success(data); + } + + /** 灵嗅航线-分页查询 **/ + @GetMapping("/{workspace_id}/jobsSpiritSmellPage") + @Operation(summary = "查询工作区中的所有作业。。", description = "查询工作区中的所有作业。") + public HttpResultResponse> getJobsSpiritSmellPage( + @RequestParam(name = "pageNum", defaultValue = "1") Long page, + @RequestParam(name = "pageSize", defaultValue = "10") Long pageSize, + @PathVariable(name = "workspace_id") String workspaceId, + @RequestParam(name = "proIds" , required = false) List proIds, + @RequestParam(name = "fileId" , required = false) String fileId, + @RequestParam(name = "name" , required = false) String name, + @RequestParam(name = "dockSn" , required = false) String dockSn + ) { + PaginationData data = waylineJobService.getJobsSpiritSmellPageByWorkspaceId(workspaceId,page, pageSize,fileId,proIds,name,dockSn); + return HttpResultResponse.success(data); + } + + /** 灵嗅航线-全量查询-单个设备下查询 **/ + @GetMapping("/{workspace_id}/jobsSpiritSmell") + @Operation(summary = "查询工作区中的所有作业。。", description = "查询工作区中的所有作业。") + public HttpResultResponse> getJobsSpiritSmell( + @PathVariable(name = "workspace_id") String workspaceId, + @RequestParam(name = "proIds" , required = false) List proIds, + @RequestParam(name = "fileId" , required = false) String fileId, + @RequestParam(name = "name" , required = false) String name, + @RequestParam(name = "dockSn" , required = false) String dockSn + ) { + List data = waylineJobService.getJobsSpiritSmellByWorkspaceId(workspaceId,fileId,proIds,name,dockSn); return HttpResultResponse.success(data); } + + /** * Send the command to cancel the jobs. * @param jobIds diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/WaylineJobAtmosphere.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/WaylineJobAtmosphere.java index 0e9d70d..3c93ca2 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/WaylineJobAtmosphere.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/WaylineJobAtmosphere.java @@ -122,6 +122,24 @@ public class WaylineJobAtmosphere implements Serializable { @TableField(value = "update_time", fill = FieldFill.INSERT_UPDATE) private Date updateTime; + //灵嗅扩展数据------ + @TableField("mission_open_status") + private Boolean missionOpenStatus;//任务打开状态 + + @TableField("timestamp") + private Long timestamp;//时间戳 + + @TableField("relative_altitude") + private Float relativeAltitude;//相对高度 + + @TableField("data_recovery_flag") + private Boolean dataRecoveryFlag;//数据恢复标识 + + + + + + } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/bo/WaylineJobAtmosphereBo.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/bo/WaylineJobAtmosphereBo.java index b7c25a2..2371aa7 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/bo/WaylineJobAtmosphereBo.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/bo/WaylineJobAtmosphereBo.java @@ -1,6 +1,7 @@ package org.dromara.sample.wayline.domain.bo; import cn.hutool.json.JSONObject; +import com.fasterxml.jackson.annotation.JsonFormat; import org.dromara.sample.wayline.domain.WaylineJobAtmosphere; import org.dromara.common.mybatis.core.domain.BaseEntity; import org.dromara.common.core.validate.AddGroup; @@ -10,6 +11,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import jakarta.validation.constraints.*; import java.util.Date; +import java.util.List; /** * 无人机任务-空气质量业务对象 wayline_job_atmosphere @@ -32,6 +34,7 @@ public class WaylineJobAtmosphereBo extends BaseEntity { */ // @NotNull(message = "无人机任务ID不能为空", groups = { AddGroup.class, EditGroup.class }) private Long waylineJobId; + private List waylineJobIds; /** * 任务UUID @@ -93,6 +96,7 @@ public class WaylineJobAtmosphereBo extends BaseEntity { */ // @NotBlank(message = "负载设备序列号不能为空", groups = { AddGroup.class, EditGroup.class }) private String serial; + private String payloadType;//负载类型 spiritsmellV2 / spiritsmellV2_1 /** * 数据序列号 @@ -148,6 +152,7 @@ public class WaylineJobAtmosphereBo extends BaseEntity { * 空气质量数据 */ private String airData; + private JSONObject airDataJson; /** * 错误码 @@ -174,5 +179,16 @@ public class WaylineJobAtmosphereBo extends BaseEntity { */ private Long proId; + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date dayStart; + + @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss") + private Date dayEnd; + + //灵嗅扩展数据------ + private Boolean missionOpenStatus; + private Long timestamp; + private Float relativeAltitude; + private Boolean dataRecoveryFlag; } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/vo/WaylineJobAtmosphereVo.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/vo/WaylineJobAtmosphereVo.java index 0ff451a..371ac58 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/vo/WaylineJobAtmosphereVo.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/domain/vo/WaylineJobAtmosphereVo.java @@ -206,5 +206,19 @@ public class WaylineJobAtmosphereVo implements Serializable { @ExcelProperty(value = "proID") private Long proId; + //灵嗅扩展数据------ + @ExcelProperty(value = "任务打开状态") + private Boolean missionOpenStatus; + + @ExcelProperty(value = "时间戳") + private Long timestamp; + + @ExcelProperty(value = "相对高度") + private Float relativeAltitude; + + @ExcelProperty(value = "数据恢复标识") + private Boolean dataRecoveryFlag; + + } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/mapper/WaylineJobAtmosphereMapper.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/mapper/WaylineJobAtmosphereMapper.java index d52158f..9f1fd99 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/mapper/WaylineJobAtmosphereMapper.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/mapper/WaylineJobAtmosphereMapper.java @@ -1,9 +1,12 @@ package org.dromara.sample.wayline.mapper; +import org.apache.ibatis.annotations.Param; import org.dromara.sample.wayline.domain.WaylineJobAtmosphere; import org.dromara.sample.wayline.domain.vo.WaylineJobAtmosphereVo; import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; +import java.util.List; + /** * 无人机任务-空气质量Mapper接口 * @@ -12,4 +15,7 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus; */ public interface WaylineJobAtmosphereMapper extends BaseMapperPlus { + List selectSpiritSmellWayLineJobIds(@Param("dockSn") String dockSn); + + List selectDistinctWaylineFileId(); } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/dto/WaylineJobDTO.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/dto/WaylineJobDTO.java index 7d97e73..4f416d2 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/dto/WaylineJobDTO.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/dto/WaylineJobDTO.java @@ -8,6 +8,7 @@ import org.dromara.common.sdk.cloudapi.wayline.OutOfControlActionEnum; import org.dromara.common.sdk.cloudapi.wayline.ProgressExtBreakPoint; import org.dromara.common.sdk.cloudapi.wayline.TaskTypeEnum; import org.dromara.common.sdk.cloudapi.wayline.WaylineTypeEnum; +import org.dromara.sample.wayline.domain.vo.WaylineJobAtmosphereVo; import java.time.LocalDateTime; import java.util.List; @@ -79,4 +80,6 @@ public class WaylineJobDTO { private ProgressExtBreakPoint breakPoint; private List proIds; + + private List waylineJobAtmosphereVoList; } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java index eada478..a99588f 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/model/entity/WaylineJobEntity.java @@ -97,4 +97,8 @@ public class WaylineJobEntity implements Serializable { @TableField("pro_id") private Integer proId; + + + @TableField("dock_name") + private String dockName; } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobAtmosphereService.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobAtmosphereService.java index 7085f40..f4d49a5 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobAtmosphereService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobAtmosphereService.java @@ -1,5 +1,6 @@ package org.dromara.sample.wayline.service; +import cn.hutool.core.date.DateTime; import cn.hutool.json.JSONObject; import org.dromara.sample.wayline.domain.vo.WaylineJobAtmosphereVo; import org.dromara.sample.wayline.domain.bo.WaylineJobAtmosphereBo; @@ -71,4 +72,10 @@ public interface IWaylineJobAtmosphereService { void handleAdd(WaylineJobDTO waylineJobDTO, JSONObject json); List demoList(WaylineJobAtmosphereBo bo); + + List selectSpiritSmellWayLineJobIdsByDockSn(String dockSn); + + List selectByDateRange(String dockSn, DateTime dayStart, DateTime dayEnd); + + List selectSpiritSmellWayLineJobIds(String dockSn); } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java index 36e4064..a15bb22 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/IWaylineJobService.java @@ -28,7 +28,7 @@ public interface IWaylineJobService { * @param endTime The time the job ended. * @return */ - Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime, Integer proId); + Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime, Integer proId,String dockName); /** * Create a sub-task based on the information of the parent task. @@ -71,7 +71,9 @@ public interface IWaylineJobService { * @param pageSize * @return */ - PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name); + PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name,Integer mediaCount); + + /** * Query the wayline execution status of the dock. @@ -89,4 +91,9 @@ public interface IWaylineJobService { List getMediaFileDTO(String jobId, String fileType); WaylineJobDTO getJobByDockSn(String dockSn); + + /**获取灵嗅数据**/ + List getJobsSpiritSmellByWorkspaceId(String workspaceId, String fileId, List proIds, String name, String dockSn); + /**获取灵嗅数据-分页**/ + PaginationData getJobsSpiritSmellPageByWorkspaceId(String workspaceId, Long page, Long pageSize, String fileId, List proIds, String name, String dockSn); } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java index cc9b9d9..b7638b7 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/FlightTaskServiceImpl.java @@ -248,7 +248,7 @@ public class FlightTaskServiceImpl extends AbstractWaylineService implements IFl if(deviceOnline.get().getProId() == null){ throw new SQLException("项目组不存在"); } - Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, loginUser.getUsername(), new Date(beginTime), new Date(endTime),deviceOnline.get().getProId()); + Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, loginUser.getUsername(), new Date(beginTime), new Date(endTime),deviceOnline.get().getProId(),deviceOnline.get().getNickname()); if (waylineJobOpt.isEmpty()) { throw new SQLException("无法创建路线作业。"); } @@ -286,7 +286,7 @@ public class FlightTaskServiceImpl extends AbstractWaylineService implements IFl if(deviceOnline.get().getProId() == null){ throw new SQLException("项目组不存在"); } - Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, username, new Date(beginTime), new Date(endTime),deviceOnline.get().getProId()); + Optional waylineJobOpt = waylineJobService.createWaylineJob(param, workspaceId, username, new Date(beginTime), new Date(endTime),deviceOnline.get().getProId(),deviceOnline.get().getNickname()); if (waylineJobOpt.isEmpty()) { throw new SQLException("无法创建路线作业。"); } @@ -342,6 +342,7 @@ public class FlightTaskServiceImpl extends AbstractWaylineService implements IFl if (waylineFile.isEmpty()) { throw new SQLException("路线文件不存在。"); } + waylineJob.setWaylineName(waylineFile.get().getName()); // get file url URL url = waylineFileService.getObjectUrl(waylineJob.getWorkspaceId(), waylineFile.get().getId()); diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineFileServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineFileServiceImpl.java index 68fb04d..2136ead 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineFileServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineFileServiceImpl.java @@ -1,5 +1,6 @@ package org.dromara.sample.wayline.service.impl; +import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.crypto.digest.MD5; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -33,6 +34,7 @@ import org.dromara.sample.manage.service.IDeviceProService; import org.dromara.sample.manage.service.IDeviceRedisService; import org.dromara.sample.wayline.mapper.IAudioFileMapper; import org.dromara.sample.wayline.mapper.IWaylineFileMapper; +import org.dromara.sample.wayline.mapper.WaylineJobAtmosphereMapper; import org.dromara.sample.wayline.model.dto.KmzFileProperties; import org.dromara.sample.wayline.model.dto.WaylineFileDTO; import org.dromara.sample.wayline.model.entity.AudioFileEntity; @@ -87,6 +89,9 @@ public class WaylineFileServiceImpl implements IWaylineFileService { @Autowired private IDeviceRedisService deviceRedisService; + @Autowired + private WaylineJobAtmosphereMapper waylineJobAtmosphereMapper; + @Override public PaginationData getWaylinesByParam(String workspaceId, GetWaylineListRequest param,List proIds) { @@ -94,6 +99,10 @@ public class WaylineFileServiceImpl implements IWaylineFileService { if(proIds == null){ proIds = deviceProService.listDeviceGroup(loginUser.getUserId()); } + if(BooleanUtil.isTrue(param.getSpiritSmellFlag())){ //灵嗅航线过滤wayLineFileIds + param.setSpiritSmellWaylineFileIds(waylineJobAtmosphereMapper.selectDistinctWaylineFileId()); + } + // Paging Query List finalProIds = proIds; Page page = mapper.selectPage( @@ -122,6 +131,9 @@ public class WaylineFileServiceImpl implements IWaylineFileService { .and(ObjectUtil.isAllNotEmpty(proIds), wrapper -> { wrapper.in(WaylineFileEntity::getProId, finalProIds); }) + .and(BooleanUtil.isTrue(param.getSpiritSmellFlag()), wrapper -> { + wrapper.in(WaylineFileEntity::getWaylineId,param.getSpiritSmellWaylineFileIds()); + }) .like(Objects.nonNull(param.getKey()), WaylineFileEntity::getName, param.getKey()) // There is a risk of SQL injection .last(Objects.nonNull(param.getOrderBy()), " order by " + param.getOrderBy().toString())); diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobAtmosphereServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobAtmosphereServiceImpl.java index 3c91f8a..b9a48b9 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobAtmosphereServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobAtmosphereServiceImpl.java @@ -1,9 +1,12 @@ package org.dromara.sample.wayline.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.date.DateTime; import cn.hutool.core.util.ObjectUtil; import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import org.dromara.common.core.utils.MapstructUtils; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.core.utils.StringUtils; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.mybatis.core.page.PageQuery; @@ -22,6 +25,7 @@ import org.dromara.sample.wayline.service.IWaylineJobAtmosphereService; import java.util.List; import java.util.Map; import java.util.Collection; +import java.util.stream.Collectors; /** * 无人机任务-空气质量Service业务层处理 @@ -83,6 +87,7 @@ public class WaylineJobAtmosphereServiceImpl implements IWaylineJobAtmosphereSer Map params = bo.getParams(); LambdaQueryWrapper lqw = Wrappers.lambdaQuery(); lqw.eq(bo.getWaylineJobId() != null, WaylineJobAtmosphere::getWaylineJobId, bo.getWaylineJobId()); + lqw.in(CollUtil.isNotEmpty(bo.getWaylineJobIds()), WaylineJobAtmosphere::getWaylineJobId, bo.getWaylineJobIds()); lqw.eq(StringUtils.isNotBlank(bo.getJobId()), WaylineJobAtmosphere::getJobId, bo.getJobId()); lqw.like(StringUtils.isNotBlank(bo.getName()), WaylineJobAtmosphere::getName, bo.getName()); lqw.eq(StringUtils.isNotBlank(bo.getFileId()), WaylineJobAtmosphere::getFileId, bo.getFileId()); @@ -185,4 +190,28 @@ public class WaylineJobAtmosphereServiceImpl implements IWaylineJobAtmosphereSer } return waylineJobAtmosphereVos; } + + @Override + public List selectSpiritSmellWayLineJobIdsByDockSn(String dockSn) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.select(WaylineJobAtmosphere::getWaylineJobId); + wrapper.eq(WaylineJobAtmosphere::getDockSn,dockSn); + List waylineJobAtmosphereVoList = baseMapper.selectVoList(wrapper); + List waylineJobIds = waylineJobAtmosphereVoList.stream().map(WaylineJobAtmosphereVo::getWaylineJobId).distinct().collect(Collectors.toList()); + return waylineJobIds; + } + + @Override + public List selectByDateRange(String dockSn, DateTime dayStart, DateTime dayEnd) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.between(WaylineJobAtmosphere::getCreateTime, dayStart, dayEnd); + wrapper.eq(ObjectUtil.isNotEmpty(dockSn),WaylineJobAtmosphere::getDockSn,dockSn); //传值了再查询 + List waylineJobAtmosphereVoList = baseMapper.selectVoList(wrapper); + return waylineJobAtmosphereVoList; + } + + @Override + public List selectSpiritSmellWayLineJobIds(String dockSn) { + return baseMapper.selectSpiritSmellWayLineJobIds(dockSn); + } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java index f3786e7..b501974 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/wayline/service/impl/WaylineJobServiceImpl.java @@ -1,6 +1,10 @@ package org.dromara.sample.wayline.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.json.JSONUtil; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; @@ -25,12 +29,15 @@ import org.dromara.sample.manage.service.IDeviceService; import org.dromara.sample.media.model.MediaFileCountDTO; import org.dromara.sample.media.model.MediaFileDTO; import org.dromara.sample.media.service.IFileService; +import org.dromara.sample.wayline.domain.bo.WaylineJobAtmosphereBo; +import org.dromara.sample.wayline.domain.vo.WaylineJobAtmosphereVo; import org.dromara.sample.wayline.mapper.IWaylineJobMapper; import org.dromara.sample.wayline.model.dto.WaylineJobDTO; import org.dromara.sample.wayline.model.entity.WaylineJobEntity; import org.dromara.sample.wayline.model.enums.WaylineJobStatusEnum; import org.dromara.sample.wayline.model.param.CreateJobParam; import org.dromara.sample.wayline.service.IWaylineFileService; +import org.dromara.sample.wayline.service.IWaylineJobAtmosphereService; import org.dromara.sample.wayline.service.IWaylineJobService; import org.dromara.sample.wayline.service.IWaylineRedisService; import com.fasterxml.jackson.databind.ObjectMapper; @@ -83,6 +90,9 @@ public class WaylineJobServiceImpl implements IWaylineJobService { @Autowired private IDeviceProService deviceProService; + @Autowired + private IWaylineJobAtmosphereService waylineJobAtmosphereService; + private Optional insertWaylineJob(WaylineJobEntity jobEntity) { int id = mapper.insert(jobEntity); if (id <= 0) { @@ -92,7 +102,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { } @Override - public Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime,Integer proId) { + public Optional createWaylineJob(CreateJobParam param, String workspaceId, String username, Date beginTime, Date endTime,Integer proId,String dockName) { if (Objects.isNull(param)) { return Optional.empty(); } @@ -116,6 +126,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { .breakPoint(param.getBreakPoint()) .jobType(param.getJobType().getType()) .proId(proId) + .dockName(dockName) .build(); return insertWaylineJob(jobEntity); @@ -175,7 +186,7 @@ public class WaylineJobServiceImpl implements IWaylineJobService { } @Override - public PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name) { + public PaginationData getJobsByWorkspaceId(String workspaceId, long page, long pageSize,String fileId,List proIds,String name,Integer mediaCount) { LoginUser loginUser = LoginHelper.getLoginUser(); if(ObjectUtil.isAllEmpty(proIds)){ proIds = deviceProService.listDeviceGroup(loginUser.getUserId()); @@ -185,6 +196,9 @@ public class WaylineJobServiceImpl implements IWaylineJobService { if(ObjectUtil.isNotEmpty(fileId)) { waylineJobEntityLambdaQueryWrapper.eq(WaylineJobEntity::getFileId, fileId); } + if(ObjectUtil.isNotEmpty(mediaCount)) { + waylineJobEntityLambdaQueryWrapper.ge(WaylineJobEntity::getMediaCount, mediaCount); + } waylineJobEntityLambdaQueryWrapper.in(ObjectUtil.isAllNotEmpty(proIds),WaylineJobEntity::getProId,proIds); if(ObjectUtil.isNotEmpty(name)){ waylineJobEntityLambdaQueryWrapper.and(wrapper ->{ @@ -202,6 +216,103 @@ public class WaylineJobServiceImpl implements IWaylineJobService { return new PaginationData(records, new Pagination(pageData.getCurrent(), pageData.getSize(), pageData.getTotal())); } + + @Override + public List getJobsSpiritSmellByWorkspaceId(String workspaceId, String fileId, List proIds, String name, String dockSn) { + LoginUser loginUser = LoginHelper.getLoginUser(); + if(ObjectUtil.isAllEmpty(proIds)){ + proIds = deviceProService.listDeviceGroup(loginUser.getUserId()); + } + LambdaQueryWrapper waylineJobEntityLambdaQueryWrapper = new LambdaQueryWrapper<>(); + waylineJobEntityLambdaQueryWrapper.eq(WaylineJobEntity::getWorkspaceId, workspaceId); + if(ObjectUtil.isNotEmpty(fileId)) { + waylineJobEntityLambdaQueryWrapper.eq(WaylineJobEntity::getFileId, fileId); + } + waylineJobEntityLambdaQueryWrapper.in(ObjectUtil.isAllNotEmpty(proIds),WaylineJobEntity::getProId,proIds); +// if(ObjectUtil.isNotEmpty(name)){ +// waylineJobEntityLambdaQueryWrapper.and(wrapper ->{ +// wrapper.like(WaylineJobEntity::getName, name).or().like(WaylineJobEntity::getWaylineName, name); +// }); +// }; + if(ObjectUtil.isNotEmpty(dockSn)){//找指定设备的航线 //灵嗅数据过滤 + List waylineJobIds = waylineJobAtmosphereService.selectSpiritSmellWayLineJobIds(dockSn); + waylineJobEntityLambdaQueryWrapper.in(WaylineJobEntity::getId,waylineJobIds); + }else{//找全部有灵嗅数据的航线 + List waylineJobIds = waylineJobAtmosphereService.selectSpiritSmellWayLineJobIds(null); + waylineJobEntityLambdaQueryWrapper.in(WaylineJobEntity::getId,waylineJobIds); + } + + waylineJobEntityLambdaQueryWrapper.orderByDesc(WaylineJobEntity::getId); + List waylineJobEntitieList = mapper.selectList(waylineJobEntityLambdaQueryWrapper); + List records = waylineJobEntitieList + .stream() + .map(this::entity2Dto) + .collect(Collectors.toList()); + + //拼接灵嗅数据 + /* List waylineJobIds = records.stream().map(WaylineJobDTO::getId).collect(Collectors.toList()); + if(CollUtil.isNotEmpty(waylineJobIds)){ + WaylineJobAtmosphereBo bo = new WaylineJobAtmosphereBo(); + bo.setWaylineJobIds(waylineJobIds); + List waylineJobAtmosphereVoList = waylineJobAtmosphereService.queryList(bo); + for (WaylineJobDTO record : records) { + List collect = waylineJobAtmosphereVoList.stream().filter(item -> item.getWaylineJobId().equals(record.getId().longValue())).collect(Collectors.toList()); +// collect.stream().forEach(item -> {item.setAirDataJson( JSONUtil.parseObj(item.getAirData())); }); + record.setWaylineJobAtmosphereVoList(collect); + } + }*/ + + return records; + } + + @Override + public PaginationData getJobsSpiritSmellPageByWorkspaceId(String workspaceId, Long page, Long pageSize, String fileId, List proIds, String name, String dockSn) { + + LoginUser loginUser = LoginHelper.getLoginUser(); + if(ObjectUtil.isAllEmpty(proIds)){ + proIds = deviceProService.listDeviceGroup(loginUser.getUserId()); + } + LambdaQueryWrapper waylineJobEntityLambdaQueryWrapper = new LambdaQueryWrapper<>(); + waylineJobEntityLambdaQueryWrapper.eq(WaylineJobEntity::getWorkspaceId, workspaceId); + if(ObjectUtil.isNotEmpty(fileId)) { + waylineJobEntityLambdaQueryWrapper.eq(WaylineJobEntity::getFileId, fileId); + } + waylineJobEntityLambdaQueryWrapper.in(ObjectUtil.isAllNotEmpty(proIds),WaylineJobEntity::getProId,proIds); +// if(ObjectUtil.isNotEmpty(name)){ +// waylineJobEntityLambdaQueryWrapper.and(wrapper ->{ +// wrapper.like(WaylineJobEntity::getName, name).or().like(WaylineJobEntity::getWaylineName, name); +// }); +// }; + if(ObjectUtil.isNotEmpty(dockSn)){//找指定设备的航线 //灵嗅数据过滤 + List waylineJobIds = waylineJobAtmosphereService.selectSpiritSmellWayLineJobIds(dockSn); + waylineJobEntityLambdaQueryWrapper.in(WaylineJobEntity::getId,waylineJobIds); + }else{//找全部有灵嗅数据的航线 + List waylineJobIds = waylineJobAtmosphereService.selectSpiritSmellWayLineJobIds(null); + waylineJobEntityLambdaQueryWrapper.in(WaylineJobEntity::getId,waylineJobIds); + } + + waylineJobEntityLambdaQueryWrapper.orderByDesc(WaylineJobEntity::getId); + Page pageData = mapper.selectPage(new Page(page, pageSize),waylineJobEntityLambdaQueryWrapper); + List records = pageData.getRecords() + .stream().map(this::entity2Dto) + .collect(Collectors.toList()); + + //拼接灵嗅数据 + /* List waylineJobIds = records.stream().map(WaylineJobDTO::getId).collect(Collectors.toList()); + if(CollUtil.isNotEmpty(waylineJobIds)){ + WaylineJobAtmosphereBo bo = new WaylineJobAtmosphereBo(); + bo.setWaylineJobIds(waylineJobIds); + List waylineJobAtmosphereVoList = waylineJobAtmosphereService.queryList(bo); + for (WaylineJobDTO record : records) { + List collect = waylineJobAtmosphereVoList.stream().filter(item -> item.getWaylineJobId().equals(record.getId().longValue())).collect(Collectors.toList()); + // collect.stream().forEach(item -> {item.setAirDataJson( JSONUtil.parseObj(item.getAirData())); }); + record.setWaylineJobAtmosphereVoList(collect); + } + }*/ + return new PaginationData(records, new Pagination(pageData.getCurrent(), pageData.getSize(), pageData.getTotal())); + } + + private WaylineJobEntity dto2Entity(WaylineJobDTO dto) { WaylineJobEntity.WaylineJobEntityBuilder builder = WaylineJobEntity.builder(); if (dto == null) { @@ -297,11 +408,12 @@ public class WaylineJobServiceImpl implements IWaylineJobService { .jobId(entity.getJobId()) .jobName(entity.getName()) .fileId(entity.getFileId()) - .fileName(waylineFileService.getWaylineByWaylineId(entity.getWorkspaceId(), entity.getFileId()) - .orElse(new GetWaylineListResponse()).getName()) + .fileName(entity.getWaylineName()) + // .orElse(new GetWaylineListResponse()).getName()) .dockSn(entity.getDockSn()) - .dockName(deviceService.getDeviceBySn(entity.getDockSn()) - .orElse(DeviceDTO.builder().build()).getNickname()) + .dockName(entity.getDockName()) +// .dockName(deviceService.getDeviceBySn(entity.getDockSn()) +// .orElse(DeviceDTO.builder().build()).getNickname()) .username(entity.getUsername()) .workspaceId(entity.getWorkspaceId()) .status(WaylineJobStatusEnum.IN_PROGRESS.getVal() == entity.getStatus() && @@ -348,17 +460,17 @@ public class WaylineJobServiceImpl implements IWaylineJobService { .uploading(RedisOpsUtils.checkExist(key) && entity.getJobId().equals(((MediaFileCountDTO)RedisOpsUtils.get(key)).getJobId())); return builder.build(); } - - int uploadedSize = fileService.getFilesByWorkspaceAndJobId(entity.getWorkspaceId(), entity.getJobId()).size(); - // All media for this job have been uploaded. - if (uploadedSize >= entity.getMediaCount()) { - return builder.uploadedCount(uploadedSize).build(); - } - RedisOpsUtils.hashSet(countKey, entity.getJobId(), - MediaFileCountDTO.builder() - .jobId(entity.getJobId()) - .mediaCount(entity.getMediaCount()) - .uploadedCount(uploadedSize).build()); +// +// int uploadedSize = fileService.getFilesByWorkspaceAndJobId(entity.getWorkspaceId(), entity.getJobId()).size(); +// //All media for this job have been uploaded. +// if (uploadedSize >= entity.getMediaCount()) { +// return builder.uploadedCount(uploadedSize).build(); +// } +// RedisOpsUtils.hashSet(countKey, entity.getJobId(), +// MediaFileCountDTO.builder() +// .jobId(entity.getJobId()) +// .mediaCount(entity.getMediaCount()) +// .build()); return builder.build(); } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketFactory.java b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketFactory.java index 23a04ab..45b4b38 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketFactory.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketFactory.java @@ -20,8 +20,11 @@ public class MyWebSocketFactory extends WebSocketDefaultFactory { @Autowired private IWebSocketManageService webSocketManageService; + @Autowired + private WebSocketSubscriptionManager websocketSubscriptionManager; + @Override public WebSocketHandler decorate(WebSocketHandler handler) { - return new MyWebSocketHandler(handler, webSocketManageService); + return new MyWebSocketHandler(handler, webSocketManageService, websocketSubscriptionManager); } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketHandler.java b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketHandler.java index 1a1b1c1..49945fe 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketHandler.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/MyWebSocketHandler.java @@ -1,6 +1,8 @@ package org.dromara.sample.websocket.config; import cn.hutool.core.bean.BeanUtil; +import cn.hutool.json.JSONObject; +import cn.hutool.json.JSONUtil; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.constant.CacheConstants; import org.dromara.common.redis.utils.RedisUtils; @@ -28,16 +30,26 @@ import static org.dromara.common.satoken.utils.LoginHelper.LOGIN_USER_KEY; @Slf4j public class MyWebSocketHandler extends WebSocketDefaultHandler { - private IWebSocketManageService webSocketManageService; + private final IWebSocketManageService webSocketManageService; - MyWebSocketHandler(WebSocketHandler delegate, IWebSocketManageService webSocketManageService) { + private final WebSocketSubscriptionManager websocketSubscriptionManager; + + public MyWebSocketHandler(WebSocketHandler delegate, + IWebSocketManageService webSocketManageService, + WebSocketSubscriptionManager websocketSubscriptionManager) { super(delegate); this.webSocketManageService = webSocketManageService; + this.websocketSubscriptionManager = websocketSubscriptionManager; } @Override public void afterConnectionEstablished(WebSocketSession session) throws Exception { + // 从 URL Query 中解析 token + String query = session.getUri().getQuery(); // e.g. "Authorization=Bearer abc...&clientid=xxx" + String token = parseTokenFromQuery(query); + session.getAttributes().put("token", token); + Object cacheObject = RedisUtils.getCacheObject("000000:online_tokens:" + session.getUri().toString().substring(session.getUri().toString().indexOf("%20") + 3, session.getUri().toString().indexOf("&"))); SysUserOnline sysUserOnline = BeanUtil.copyProperties(cacheObject, SysUserOnline.class); if (StringUtils.hasText(sysUserOnline.getUserName())) { @@ -61,9 +73,70 @@ public class MyWebSocketHandler extends WebSocketDefaultHandler { } + + /** + * 前台触发连接 + * // 建好 ws 连接之后 + * ws.send(JSON.stringify({ + * action: "subscribe", + * bizCode: "SPIRIT_SMELL" + * })); + * + * // 页面关闭或切换时 + * ws.send(JSON.stringify({ + * action: "unsubscribe", + * bizCode: "SPIRIT_SMELL" + * })); + * + * @throws Exception + */ @Override - public void handleMessage(WebSocketSession session, WebSocketMessage message) throws Exception { - log.debug("received message: {}", message.getPayload()); + public void handleMessage(WebSocketSession rawSession, WebSocketMessage wsMsg) throws Exception { +// log.debug("received message: {}", message.getPayload()); + + String payload = wsMsg.getPayload().toString(); + if(!JSONUtil.isTypeJSON(payload)){ + System.out.println(payload); + return; + } + System.out.println(payload); + + JSONObject json = JSONUtil.parseObj(payload); + String action = json.getStr("action"); // subscribe/unsubscribe +// String bizCode = json.getStr("bizCode"); + String dockSn = json.getStr("dockSn"); + String token = (String) rawSession.getAttributes().get("token"); + // 还可以带 workspaceId/userType 等,按需扩展 + + /* MyConcurrentWebSocketSession session = new MyConcurrentWebSocketSession(rawSession); + + if ("subscribe".equals(action)) { +// websocketSubscriptionManager.subscribe(bizCode, dockSn, token, session); +// websocketSubscriptionManager.subscribe( dockSn, token, session); + websocketSubscriptionManager.subscribe(token,dockSn,session); + } + else if ("unsubscribe".equals(action)) { +// websocketSubscriptionManager.unsubscribe(bizCode, dockSn, token, session.getId()); +// websocketSubscriptionManager.unsubscribe( dockSn, token, session.getId()); + websocketSubscriptionManager.unsubscribe( token,dockSn,session.getId()); + } + else { + log.warn("Unknown WS action: {}", action); + }*/ + } + + private String parseTokenFromQuery(String query) { + // 简单解析:找到 Authorization=Bearer XXX + for (String part : query.split("&")) { + if (part.startsWith("Authorization=")) { + String v = part.substring("Authorization=".length()); + if (v.startsWith("Bearer ")) { + return v.substring("Bearer ".length()); + } + return v; + } + } + return null; } } diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/WebSocketSubscriptionManager.java b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/WebSocketSubscriptionManager.java new file mode 100644 index 0000000..3cf36e9 --- /dev/null +++ b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/config/WebSocketSubscriptionManager.java @@ -0,0 +1,104 @@ +package org.dromara.sample.websocket.config; + +import org.dromara.common.redis.config.RedisConst; +import org.dromara.common.redis.utils.RedisOpsUtils; +import org.springframework.stereotype.Component; + +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; + +@Component +public class WebSocketSubscriptionManager { + + /** + * 存储结构: + * key = bizCode + ":" + dockSn + * 内部Map = token -> (sessionId -> session) + */ +// private final ConcurrentHashMap> > subs = new ConcurrentHashMap<>(); + + // token -> Set + private final ConcurrentHashMap> tokenToDockSet = new ConcurrentHashMap<>(); + // token -> sessionId -> session + private final ConcurrentHashMap> tokenSessions = new ConcurrentHashMap<>(); + + + + private String buildOuterKey(String bizCode, String dockSn) { + return bizCode + ":" + dockSn; + } + + /** 订阅设备 */ + public void subscribe(String token, String dockSn, MyConcurrentWebSocketSession session) { +// 保存用户到redis,案例数据: ,超时:30分钟 + String key = RedisConst.DEVICE_ONLINE_USER_PREFIX + token; + RedisOpsUtils.setWithExpire(key, dockSn ,RedisConst.ONLINE_REDIS_USER_ALIVE_SECOND); + +// tokenToDockSet.computeIfAbsent(token, k -> ConcurrentHashMap.newKeySet()).add(dockSn); +// tokenSessions.computeIfAbsent(key, k -> new ConcurrentHashMap<>()).put(session.getId(), session); + } + + + /** 取消订阅设备 */ + public void unsubscribe(String token, String dockSn, String sessionId) { + + RedisOpsUtils.del(RedisConst.DEVICE_ONLINE_USER_PREFIX+token); + +// Set docks = tokenToDockSet.get(token); +// if (docks != null) { +// docks.remove(dockSn); +// if (docks.isEmpty()) { +// tokenToDockSet.remove(token); +// } +// } +// +// var sessionMap = tokenSessions.get(token); +// if (sessionMap != null) { +// sessionMap.remove(sessionId); +// if (sessionMap.isEmpty()) { +// tokenSessions.remove(token); +// } +// } + } + + /** 获取所有订阅了该 dockSn 的用户的 session */ + public Collection getSessionsForDock(String dockSn) { + List result = new ArrayList<>(); + for (Map.Entry> entry : tokenToDockSet.entrySet()) { + String token = entry.getKey(); + Set dockSnSet = entry.getValue(); + if (dockSnSet.contains(dockSn)) { + var sessionMap = tokenSessions.get(token); + if (sessionMap != null) { + result.addAll(sessionMap.values()); + } + } + } + return result; + } + + + // bizCode -> sessionId -> MyConcurrentWebSocketSession +// private final ConcurrentHashMap> subs = new ConcurrentHashMap<>(); + +// /** 订阅 */ +// public void subscribe(String bizCode, MyConcurrentWebSocketSession session) { +// subs.computeIfAbsent(bizCode, k -> new ConcurrentHashMap<>()) +// .put(session.getId(), session); +// } +// +// /** 取消订阅 */ +// public void unsubscribe(String bizCode, String sessionId) { +// var map = subs.get(bizCode); +// if (map != null) { +// map.remove(sessionId); +// if (map.isEmpty()) subs.remove(bizCode); +// } +// } +// +// /** 获取所有对该 bizCode 感兴趣的 sessions */ +// public Collection getSubscribers(String bizCode) { +// var map = subs.get(bizCode); +// return map == null ? Collections.emptyList() : map.values(); +// } +} diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/IWebSocketMessageService.java b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/IWebSocketMessageService.java index 6811db1..445595c 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/IWebSocketMessageService.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/IWebSocketMessageService.java @@ -27,6 +27,8 @@ public interface IWebSocketMessageService { */ void sendBatch(Collection sessions, WebSocketMessageResponse message); + void sendBatchBySessions(Collection sessions, String bizCode, Object data); + void sendBatch(String workspaceId, Integer userType, String bizCode, Object data); void sendBatch(String workspaceId, String bizCode, Object data); diff --git a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/impl/WebSocketMessageServiceImpl.java b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/impl/WebSocketMessageServiceImpl.java index 437d579..19cb1bf 100644 --- a/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/impl/WebSocketMessageServiceImpl.java +++ b/dk-modules/sample/src/main/java/org/dromara/sample/websocket/service/impl/WebSocketMessageServiceImpl.java @@ -1,19 +1,33 @@ package org.dromara.sample.websocket.service.impl; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.json.JSONUtil; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; +import org.dromara.common.redis.config.RedisConst; +import org.dromara.common.redis.utils.RedisOpsUtils; import org.dromara.common.websocket.dto.WebSocketMessageResponse; import org.dromara.sample.websocket.config.MyConcurrentWebSocketSession; +import org.dromara.sample.websocket.config.WebSocketSubscriptionManager; import org.dromara.sample.websocket.service.IWebSocketManageService; import org.dromara.sample.websocket.service.IWebSocketMessageService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.util.StringUtils; import org.springframework.web.socket.TextMessage; +import org.springframework.web.socket.handler.WebSocketSessionDecorator; import java.io.IOException; +import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.hutool.jwt.JWTUtil.parseToken; /** * @author sean.zhou @@ -29,12 +43,12 @@ public class WebSocketMessageServiceImpl implements IWebSocketMessageService { @Autowired private IWebSocketManageService webSocketManageService; + @Autowired + private WebSocketSubscriptionManager webSocketSubscriptionManager; @Override public void sendMessage(MyConcurrentWebSocketSession session, WebSocketMessageResponse message) { - if (session == null) { - return; - } + if (session == null) {return;} try { if (!session.isOpen()) { @@ -43,7 +57,6 @@ public class WebSocketMessageServiceImpl implements IWebSocketMessageService { return; } - session.sendMessage(new TextMessage(mapper.writeValueAsBytes(message))); } catch (IOException e) { log.info("Failed to publish the message. {}", message.toString()); @@ -51,23 +64,68 @@ public class WebSocketMessageServiceImpl implements IWebSocketMessageService { } } + /** 核心调用 **/ @Override public void sendBatch(Collection sessions, WebSocketMessageResponse message) { - if (sessions.isEmpty()) { - return; - } + if (sessions.isEmpty()) {return;} try { - TextMessage data = new TextMessage(mapper.writeValueAsBytes(message)); +// System.out.println(data.getPayload()); + String targetDockSn = extractDockSn(message.getData());//获取sn码 +// if (StrUtil.isBlank(targetDockSn)) { //消息体中不包含 dockSn 可拦截 +// return; +// } + + //查redis在线用户 + String onlineUserPrefix = RedisConst.DEVICE_ONLINE_USER_PREFIX ; +// Set allKeys = RedisOpsUtils.getAllKeys(keyPrefix); +// allKeys = allKeys.stream() +// .map(key -> StrUtil.subAfter(key, keyPrefix, false)) +// .filter(StrUtil::isNotBlank) // 排除 null 或 空字符串 +// .collect(Collectors.toSet()); for (MyConcurrentWebSocketSession session : sessions) { if (!session.isOpen()) { session.close(); - log.debug("This session is closed."); - return; +// log.debug("This session is closed."); +// return; + continue; + } +// session.sendMessage(data);//数据发送 //关闭数据 + + String token = parseTokenFromQuery(session.getUri().getQuery()); +// System.out.println("tok"+token); +// String newToken = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOiJzeXNfdXNlcjoxIiwicm5TdHIiOiJMVUoxUGUzczNMVGNndHkzTVI1SFRRV3NUcjdWamlsSSIsImNsaWVudGlkIjoiZTVjZDdlNDg5MWJmOTVkMWQxOTIwNmNlMjRhN2IzMmUiLCJ0ZW5hbnRJZCI6IjAwMDAwMCIsInVzZXJJZCI6MSwidXNlck5hbWUiOiJhZG1pbiIsImRlcHRJZCI6MiwiZGVwdE5hbWUiOiLmsZ_oi4_nnIEiLCJkZXB0Q2F0ZWdvcnkiOiIifQ.5SX070r1cmmQGbEmd9MMD88XnLDJ8wPJ5LvddJ3cn_Y"; +// System.out.println(ObjectUtil.equals(token,newToken)); + + if (StrUtil.isBlank(token)) { continue;} + + String key = onlineUserPrefix + token; + String snStr = (String)RedisOpsUtils.get(key); + if (StrUtil.isEmpty(snStr)) {continue;} + + String[] snSplit = snStr.split(","); +// CollUtil.contains(Arrays.asList(snSplit),targetDockSn); + +// if(ObjectUtil.isNotEmpty(snStr) && ObjectUtil.equals(sn, targetDockSn)){ + if(ObjectUtil.isNotEmpty(snStr) && Arrays.asList(snSplit).contains(targetDockSn) ){ +// if(ObjectUtil.isNotEmpty(sn)){ + session.sendMessage(data);//数据发送 } - session.sendMessage(data); + +// boolean keyExist = RedisOpsUtils.checkExist(keyPrefix + ":" + token); +// if (keyExist) { +// Object o = RedisOpsUtils.get(keyPrefix + ":" + token); +// } + + + //在线用户token里有当前用户,发送消息 +// String query = session.getUri().getQuery(); // Authorization=Bearer abgffgx.... +// String token = parseTokenFromQuery(query); +// if(CollUtil.contains(allKeys, token)){ +// session.sendMessage(data);//数据发送 +// } } } catch (IOException e) { @@ -77,11 +135,65 @@ public class WebSocketMessageServiceImpl implements IWebSocketMessageService { } } + @Override + public void sendBatchBySessions(Collection sessions, String bizCode, Object data) { + WebSocketMessageResponse response = new WebSocketMessageResponse<>() + .setBizCode(bizCode) + .setTimestamp(System.currentTimeMillis()) + .setData(Objects.requireNonNullElse(data, "")); + sendBatch(sessions, response); + } + + + private String extractDockSn(Object data) { + try { + // 假设DTO 都有 getSn() 方法 + Method method = data.getClass().getMethod("getSn"); + Object sn = method.invoke(data); + return sn == null ? null : sn.toString(); + } catch (Exception e) { + return null; + } + } + @Override public void sendBatch(String workspaceId, Integer userType, String bizCode, Object data) { if (!StringUtils.hasText(workspaceId)) { throw new RuntimeException("工作区ID不存在。"); } + +// // 1. 优先尝试基于订阅投递 +// String dockSn = extractDockSn(data); +// if (dockSn != null) { +// Collection subs = +// webSocketSubscriptionManager.getSubscribers(bizCode, dockSn); +// if (!subs.isEmpty()) { +// // 精准投递给订阅者 +// this.sendBatchBySessions(subs, bizCode, data); +// return; +// } +// } + + //2. 全部发送 + + /* String dockSn = extractDockSn(data); //获取设备sn码 + System.out.println("dockSn: "+ dockSn); + if (dockSn != null) { + Collection subs = webSocketSubscriptionManager.getSessionsForDock(dockSn); +// subs.stream().map() + String collect = subs.stream().map(WebSocketSessionDecorator::getId).collect(Collectors.joining(",")); + if (!subs.isEmpty()) { + System.out.println("订阅数:" + subs.size() + " collect: "+ collect); + + this.sendBatch(subs, new WebSocketMessageResponse<>() + .setData(Objects.requireNonNullElse(data, "")) + .setTimestamp(System.currentTimeMillis()) + .setBizCode(bizCode)); + return; + } + }*/ + + //旧群发 Collection sessions = Objects.isNull(userType) ? webSocketManageService.getValueWithWorkspace(workspaceId) : webSocketManageService.getValueWithWorkspaceAndUserType(workspaceId, userType); @@ -96,4 +208,18 @@ public class WebSocketMessageServiceImpl implements IWebSocketMessageService { public void sendBatch(String workspaceId, String bizCode, Object data) { this.sendBatch(workspaceId, null, bizCode, data); } + + private String parseTokenFromQuery(String query) { + // 简单解析:找到 Authorization=Bearer XXX + for (String part : query.split("&")) { + if (part.startsWith("Authorization=")) { + String v = part.substring("Authorization=".length()); + if (v.startsWith("Bearer ")) { + return v.substring("Bearer ".length()); + } + return v; + } + } + return null; + } } diff --git a/dk-modules/sample/src/main/resources/mapper/ManageDevicePayloadCustomMapper.xml b/dk-modules/sample/src/main/resources/mapper/ManageDevicePayloadCustomMapper.xml new file mode 100644 index 0000000..7f5f825 --- /dev/null +++ b/dk-modules/sample/src/main/resources/mapper/ManageDevicePayloadCustomMapper.xml @@ -0,0 +1,7 @@ + + + + + diff --git a/dk-modules/sample/src/main/resources/mapper/WaylineJobAtmosphereMapper.xml b/dk-modules/sample/src/main/resources/mapper/WaylineJobAtmosphereMapper.xml index 537db7b..473480d 100644 --- a/dk-modules/sample/src/main/resources/mapper/WaylineJobAtmosphereMapper.xml +++ b/dk-modules/sample/src/main/resources/mapper/WaylineJobAtmosphereMapper.xml @@ -4,4 +4,19 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> + + + + + + diff --git a/dk-modules/sample/src/main/resources/mapper/WaylineJobMapper.xml b/dk-modules/sample/src/main/resources/mapper/WaylineJobMapper.xml new file mode 100644 index 0000000..a301af7 --- /dev/null +++ b/dk-modules/sample/src/main/resources/mapper/WaylineJobMapper.xml @@ -0,0 +1,23 @@ + + + + + + + + diff --git a/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java b/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java index 41334c7..28f2436 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java +++ b/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysDepartBoundaryController.java @@ -1,12 +1,15 @@ package org.dromara.system.controller.system; +import cn.dev33.satoken.annotation.SaCheckPermission; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.dromara.common.core.domain.R; import org.dromara.common.idempotent.annotation.RepeatSubmit; +import org.dromara.common.log.annotation.Log; +import org.dromara.common.log.enums.BusinessType; import org.dromara.common.mybatis.core.page.PageQuery; import org.dromara.common.mybatis.core.page.TableDataInfo; import org.dromara.common.web.core.BaseController; @@ -38,8 +41,8 @@ public class SysDepartBoundaryController extends BaseController { */ @Operation(summary ="查询部门的地理位置",description = "查询部门的地理位置") @GetMapping(value = "/listJson") - public R> listJson(SysDepartBoundary departBoundary) { - List listJson = departBoundaryService.listJson(departBoundary); + public R listJson(SysDepartBoundary departBoundary) { + String listJson = departBoundaryService.listJson(departBoundary); return R.ok("查询成功!",listJson); } /** @@ -71,6 +74,7 @@ public class SysDepartBoundaryController extends BaseController { * @return */ @RepeatSubmit() + @Log(title = "导入部门区域", businessType = BusinessType.IMPORT) @Operation(summary ="新增部门区域",description = "新增部门区域(areaType: 0:市级 1:区级(县) 2:镇级(街道) 3:村级)") @RequestMapping(value = "/{areaType}/{parentId}/upload", method = RequestMethod.POST) public R uploadShpFile(@RequestParam("file") MultipartFile file, @@ -100,6 +104,8 @@ public class SysDepartBoundaryController extends BaseController { * @param id * @return */ + @SaCheckPermission("system:boundary:delete") + @Log(title = "删除部门区域", businessType = BusinessType.DELETE) @Operation(summary ="删除部门区域",description = "删除部门区域") @RequestMapping(value = "/delete", method = RequestMethod.DELETE) public R deleteDepartBoundary(@RequestParam(name = "id") String id) { diff --git a/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysUserController.java b/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysUserController.java index 365b7dc..da371fd 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysUserController.java +++ b/dk-modules/system/src/main/java/org/dromara/system/controller/system/SysUserController.java @@ -37,6 +37,7 @@ import org.springframework.web.multipart.MultipartFile; import java.util.ArrayList; import java.util.List; +import java.util.Map; /** * 用户信息 @@ -334,4 +335,14 @@ public class SysUserController extends BaseController { return R.ok(userService.selectUserListByDept(deptId)); } + /** + * 用于设备组添加成员,根据目标值类型查询 + * @param params + * @return + */ + @GetMapping("/list/target") + public List> listTargetTypeByUser(List> params){ + return userService.listTargetTypeByUser(params); + } + } diff --git a/dk-modules/system/src/main/java/org/dromara/system/domain/bo/SysDepartBoundaryBo.java b/dk-modules/system/src/main/java/org/dromara/system/domain/bo/SysDepartBoundaryBo.java index 45516f3..54ce3ea 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/domain/bo/SysDepartBoundaryBo.java +++ b/dk-modules/system/src/main/java/org/dromara/system/domain/bo/SysDepartBoundaryBo.java @@ -7,27 +7,24 @@ import lombok.Getter; @Data public class SysDepartBoundaryBo { - private String departId; - /** - * 区域类别 1是市级 2是区级 + * 部门id */ - private AreaType areaType; - - private String landCategoriesJson; - + private String deptId; - @AllArgsConstructor - @Getter - public enum AreaType { - - Municipal("1","市级"), - - DistrictLevel("2","区级"); + /** + * 部门名称 + */ + private String deptName; - private String code; + /** + * 区域类别 areaType: 0:市级 1:区级(县) 2:镇级(街道) 3:村级 + */ + private Integer areaType; - private String desc; + /** + * 区域矢量数据 + */ + private String landCategoriesJson; - } } diff --git a/dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteSubmailConfigServiceImpl.java b/dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteSubmailConfigServiceImpl.java index f982ce3..8cc1c5e 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteSubmailConfigServiceImpl.java +++ b/dk-modules/system/src/main/java/org/dromara/system/dubbo/RemoteSubmailConfigServiceImpl.java @@ -60,7 +60,7 @@ public class RemoteSubmailConfigServiceImpl implements RemoteSubmailConfigServic Long deptId = Convert.toLong(map.get("deptId")); List sysUserVos = userService.selectUserListByDept(Convert.toLong(deptId)); Set phones = sysUserVos.stream().filter(u -> u.getNoticeType() == 1 && StrUtil.isNotEmpty(u.getPhonenumber())).map(SysUserVo::getPhonenumber).collect(Collectors.toSet()); - sysSubmailConfigService.sendPhone(code,phones, JSON.toJSONString(map)); + sysSubmailConfigService.sendPhone(code,phones, JSON.toJSONString(map),null); } } @@ -74,7 +74,7 @@ public class RemoteSubmailConfigServiceImpl implements RemoteSubmailConfigServic * @param noticeMap */ @Override - public void remoteSendUser(String code, List userIds, Map noticeMap) { + public void remoteSendUser(String code, List userIds, Map noticeMap,String project) { userIds.forEach(userId -> { SysUserVo sysUserVo = userService.selectUserById(userId); @@ -83,7 +83,7 @@ public class RemoteSubmailConfigServiceImpl implements RemoteSubmailConfigServic Set phones = new HashSet<>(); phones.add(sysUserVo.getPhonenumber()); - sysSubmailConfigService.sendPhone(code,phones, JSON.toJSONString(noticeMap)); + sysSubmailConfigService.sendPhone(code,phones, JSON.toJSONString(noticeMap),project); } }); diff --git a/dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java b/dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java index e075336..f0535fe 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java +++ b/dk-modules/system/src/main/java/org/dromara/system/mapper/SysDepartBoundaryMapper.java @@ -24,7 +24,7 @@ public interface SysDepartBoundaryMapper extends BaseMapper { void saveBatchBoundary(@Param("list") List boundaryList); - String listJson(@Param("deptId") String deptId); + String listJson(@Param("list") List deptIdList); List listDepartBoundaryByLngAndLat(@Param("lng") Double lng,@Param("lat") Double lat); } diff --git a/dk-modules/system/src/main/java/org/dromara/system/mapper/SysUserMapper.java b/dk-modules/system/src/main/java/org/dromara/system/mapper/SysUserMapper.java index 537c71e..bfc56a3 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/mapper/SysUserMapper.java +++ b/dk-modules/system/src/main/java/org/dromara/system/mapper/SysUserMapper.java @@ -92,9 +92,7 @@ public interface SysUserMapper extends BaseMapperPlus { }) int updateById(@Param(Constants.ENTITY) SysUser user); - @DataPermission({ - @DataColumn(key = "deptName", value = "dept_id") - }) + List selectFlwByIds(@Param(Constants.WRAPPER) Wrapper queryWrapper); List allList(@Param("param") SysUserBo user); diff --git a/dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java b/dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java index 74be76c..c3324d7 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java +++ b/dk-modules/system/src/main/java/org/dromara/system/service/ISysDepartBoundaryService.java @@ -28,7 +28,7 @@ public interface ISysDepartBoundaryService extends IService{ boolean addDepartBoundary(SysDepartBoundary departBoundary); - List listJson(SysDepartBoundary departBoundary); + String listJson(SysDepartBoundary departBoundary); List listDepartBoundaryByLngAndLat(Double lng, Double lat); diff --git a/dk-modules/system/src/main/java/org/dromara/system/service/ISysDeptService.java b/dk-modules/system/src/main/java/org/dromara/system/service/ISysDeptService.java index b259af1..85ade78 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/service/ISysDeptService.java +++ b/dk-modules/system/src/main/java/org/dromara/system/service/ISysDeptService.java @@ -162,4 +162,12 @@ public interface ISysDeptService { SysDept addBoundaryDept(SysDeptBo sysDeptBo); List listTreeDeptByChild(Long deptId); + + /** + * 根据当前部门查询下一级 + * @param deptId + * @return + */ + List selectSecondByParentId(Long deptId); + } diff --git a/dk-modules/system/src/main/java/org/dromara/system/service/ISysSubmailConfigService.java b/dk-modules/system/src/main/java/org/dromara/system/service/ISysSubmailConfigService.java index 01a7223..d54a742 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/service/ISysSubmailConfigService.java +++ b/dk-modules/system/src/main/java/org/dromara/system/service/ISysSubmailConfigService.java @@ -72,7 +72,7 @@ public interface ISysSubmailConfigService { R cmdSend(String code, String multiParam); - R sendPhone(String code,Setphones, String multiParam); + R sendPhone(String code,Setphones, String multiParam,String project); String submailSendUtil(SysSubmailConfigBo bo, List configUserVoList); String submailSendPhone(SysSubmailConfigBo bo, Set phones); diff --git a/dk-modules/system/src/main/java/org/dromara/system/service/ISysUserService.java b/dk-modules/system/src/main/java/org/dromara/system/service/ISysUserService.java index 2d0e9e0..839016b 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/service/ISysUserService.java +++ b/dk-modules/system/src/main/java/org/dromara/system/service/ISysUserService.java @@ -7,6 +7,7 @@ import org.dromara.system.domain.vo.SysUserExportVo; import org.dromara.system.domain.vo.SysUserVo; import java.util.List; +import java.util.Map; /** * 用户 业务层 @@ -280,4 +281,11 @@ public interface ISysUserService { List selectFlwByIds(List userIds, Long deptId); List allList(SysUserBo user); + + /** + * 用于设备组添加成员,根据目标值类型查询 + * @param params + * @return + */ + List> listTargetTypeByUser(List> params); } diff --git a/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysDepartBoundaryServiceImpl.java b/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysDepartBoundaryServiceImpl.java index 32888c0..f4aebdd 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysDepartBoundaryServiceImpl.java +++ b/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysDepartBoundaryServiceImpl.java @@ -1,12 +1,15 @@ package org.dromara.system.service.impl; import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; import lombok.RequiredArgsConstructor; import org.apache.dubbo.config.annotation.DubboReference; +import org.dromara.common.core.utils.StreamUtils; import org.dromara.common.satoken.utils.LoginHelper; import org.dromara.system.api.domain.vo.RemoteDeptVo; import org.dromara.system.domain.SysDepartBoundary; @@ -215,23 +218,20 @@ public class SysDepartBoundaryServiceImpl extends ServiceImpl listJson(SysDepartBoundary departBoundary) { - if(ObjectUtil.isEmpty(departBoundary.getDeptId())){ - throw new ServiceException("部门【id】不存在"); - } + public String listJson(SysDepartBoundary departBoundary) { + + //获取当前人所属部门 + Long deptId = LoginHelper.getDeptId(); + + + //根据当前所属部门id查询下级部门,获取部门所属区域 + List deptVoList = deptService.selectSecondByParentId(deptId); + + List secondDeptIdList = StreamUtils.toList(deptVoList, SysDeptVo::getDeptId); - SysDepartBoundaryBo child = new SysDepartBoundaryBo(); - child.setDepartId(String.valueOf(departBoundary.getDeptId())); - child.setAreaType(SysDepartBoundaryBo.AreaType.DistrictLevel); - child.setLandCategoriesJson(this.baseMapper.listJson(String.valueOf(departBoundary.getDeptId()))); + return this.baseMapper.listJson(secondDeptIdList.stream().distinct().toList()); - SysDeptVo sysDeptVo = deptService.getByParentId(String.valueOf(departBoundary.getDeptId())); - SysDepartBoundaryBo parent = new SysDepartBoundaryBo(); - parent.setDepartId(String.valueOf(sysDeptVo.getDeptId())); - parent.setAreaType(SysDepartBoundaryBo.AreaType.Municipal); - parent.setLandCategoriesJson(this.baseMapper.listJson(String.valueOf(sysDeptVo.getDeptId()))); - return List.of(child,parent); } /** @@ -249,7 +249,7 @@ public class SysDepartBoundaryServiceImpl extends ServiceImpl selectSecondByParentId(Long deptId) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(SysDept::getParentId, deptId); + wrapper.eq(SysDept::getStatus, UserConstants.DEPT_NORMAL); + + List deptVoList = this.baseMapper.selectVoList(wrapper); + + if (ObjectUtil.isEmpty(deptVoList)) { + return List.of(); + } + + return deptVoList; + } + } diff --git a/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysSubmailConfigServiceImpl.java b/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysSubmailConfigServiceImpl.java index 5bed240..ca963b7 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysSubmailConfigServiceImpl.java +++ b/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysSubmailConfigServiceImpl.java @@ -3,6 +3,7 @@ package org.dromara.system.service.impl; import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.bean.copier.CopyOptions; import cn.hutool.core.util.BooleanUtil; +import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.hutool.json.JSONArray; @@ -187,7 +188,7 @@ public class SysSubmailConfigServiceImpl implements ISysSubmailConfigService { } @Override - public R sendPhone(String code, Set phones, String multiParam) { + public R sendPhone(String code, Set phones, String multiParam,String project) { //找到生效配置 SysSubmailConfigBo bo = new SysSubmailConfigBo(); bo.setCode(code); @@ -197,6 +198,11 @@ public class SysSubmailConfigServiceImpl implements ISysSubmailConfigService { } SysSubmailConfigVo firstConfigVo = sysSubmailConfigVoTempList.get(0); + //如果模版不为空则使用传过来的模版 + if (ObjectUtil.isNotEmpty(project)){ + firstConfigVo.setProject(project); + } + BeanUtil.copyProperties(firstConfigVo,bo); bo.setMultiParam(multiParam); diff --git a/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java b/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java index 54b5d6a..1602daf 100644 --- a/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java +++ b/dk-modules/system/src/main/java/org/dromara/system/service/impl/SysUserServiceImpl.java @@ -37,9 +37,8 @@ import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; -import java.util.ArrayList; -import java.util.List; -import java.util.Map; +import java.util.*; +import java.util.stream.Collectors; /** * 用户 业务层处理 @@ -613,6 +612,85 @@ public class SysUserServiceImpl implements ISysUserService { return baseMapper.allList(user); } + /** + * 用于设备组添加成员,根据目标值类型查询 + * @param params + * @return + */ + @Override + public List> listTargetTypeByUser(List> params) { + //1、定义返回值 + List> result = new ArrayList<>(); + + //2、根据传过来的集合中的目标值类型分组 + Map>> targetMap = params.stream().collect(Collectors.groupingBy(p -> Integer.valueOf(p.get("targetType") + ""))); + + //3、根据目标值的遍历 + targetMap.keySet().forEach(targetType -> { + + List currentUserList = new ArrayList<>(); + + //4、获取相应目标类型的目标值集合 + List> targetMapList = targetMap.get(targetType); + + //5、如果为空则结束当前循环 + if (ObjectUtil.isEmpty(targetMapList)) { + return; + } + + //不为空再根据集合中的目标值转换成long集合 + List targetKeyList = targetMapList.stream().map(p -> Long.valueOf(p.get("targetKey") + "")).distinct().toList(); + + //根据目标值类型找到对应的解析方法 + switch (targetType) { + case 1: + currentUserList= this.baseMapper.selectList(new LambdaQueryWrapper().in(SysUser::getUserId, targetKeyList)); + + break; + case 2: + //角色 + List userRoleIds = Optional.ofNullable(userRoleMapper.selectList( + new LambdaQueryWrapper() + .in(SysUserRole::getRoleId, targetKeyList))) + .orElse(List.of()) + .stream() + .map(SysUserRole::getUserId) + .filter(Objects::nonNull) + .distinct() + .toList(); + + currentUserList = this.baseMapper.selectList(new LambdaQueryWrapper().in(SysUser::getDeptId, userRoleIds)); + + break; + case 3: + //部门 + currentUserList = this.baseMapper.selectList(new LambdaQueryWrapper().in(SysUser::getDeptId, targetKeyList)); + + break; + default: + break; + } + + //拿到目标值获取的信息进行构建返回格式 + currentUserList.forEach(sysUser -> { + Map userMap = new HashMap<>(); + //用户 + userMap.put("userId",sysUser.getUserId()); + userMap.put("userName",sysUser.getUserName()); + userMap.put("nickName",sysUser.getNickName()); + + //防止重复存入 + if (result.stream().noneMatch(p-> Long.valueOf(p.get("userId") + "").equals(sysUser.getUserId()))) { + result.add(userMap); + } + }); + + }); + + + return result; + } + /** * 通过用户ID查询用户账户 * diff --git a/dk-modules/system/src/main/resources/mapper/system/SysDepartBoundaryMapper.xml b/dk-modules/system/src/main/resources/mapper/system/SysDepartBoundaryMapper.xml index 9c87bd2..1877558 100644 --- a/dk-modules/system/src/main/resources/mapper/system/SysDepartBoundaryMapper.xml +++ b/dk-modules/system/src/main/resources/mapper/system/SysDepartBoundaryMapper.xml @@ -154,7 +154,8 @@ 'deptId', l.dept_id, 'deptName', l.dept_name, 'name', l.name_path, - 'community_name', l.name_path + 'community_name', l.name_path, + 'areaType',l.area_type ), 'geometry', ST_AsGeoJSON(l.boundary) @@ -167,7 +168,10 @@ sys_depart_boundary l LEFT JOIN sys_dept d ON l.dept_id = d.dept_id WHERE - d.dept_id = #{deptId} + d.dept_id in + + #{item} +