Sfoglia il codice sorgente

无人机数据接收存储

Memory_LG 1 mese fa
parent
commit
bf7601dd11

+ 5 - 0
pom.xml

@@ -125,6 +125,11 @@
             <version>5.8.24</version>
         </dependency>
 
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-test</artifactId>
+        </dependency>
+
     </dependencies>
 
     <build>

+ 53 - 1
src/main/java/com/sooka/sponest/event/centereventteventcatalogue/controller/AlarmEventController.java

@@ -1,12 +1,17 @@
 package com.sooka.sponest.event.centereventteventcatalogue.controller;
 
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.ruoyi.common.core.domain.R;
 import com.ruoyi.common.core.utils.StringUtils;
+import com.ruoyi.common.core.web.controller.BaseController;
+import com.ruoyi.common.core.web.domain.AjaxResult;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.dahua.DaHuaFireEventVO;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.dahua.DaHuaOtherEventVO;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.haikang.HaiKangEventVo;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.tower.TowerEventVo;
+import com.sooka.sponest.event.centereventteventcatalogue.domain.vo.DroneVO;
 import com.sooka.sponest.event.centereventteventcatalogue.service.AlarmEventService;
 import com.sooka.sponest.event.centereventtreportmessage.domain.CentereventTReportmessage;
 import com.sooka.sponest.event.centereventtreportmessage.service.ICentereventTReportmessageService;
@@ -20,13 +25,15 @@ 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 com.sooka.sponest.event.utils.URLToJSONConverter;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 @Api(tags = "海康")
 @RestController
 @RequestMapping("AlarmEventController")
-public class AlarmEventController {
+public class AlarmEventController extends BaseController {
 
     protected final Logger logger = LoggerFactory.getLogger(this.getClass());
 
@@ -203,4 +210,49 @@ public class AlarmEventController {
         }
         return R.ok();
     }
+
+    /**
+     * 无人机上报
+     */
+    /*
+     * {"data":
+     * [{
+     *  "timeStamp":0,                                                                      //时间戳
+     *  "altitude":0.0,                                                                     //海拔高度
+     *  "alarmType":"Sleep",                                                                //隐患类型
+     *  "createTime":1742354657000,                                                         //隐患时间
+     *  "photoPath":"https://47.93.50.30:443/media/dji-photos/wayline/1742354657053.JPG",   //隐患图片地址
+     *  "latitude":38.185382,                                                               //隐患纬度
+     *  "photoId":518,                                                                      //隐患图片id
+     *  "longitude":107.487296322                                                           //隐患经度
+     *  }]
+     * }
+     */
+    @PostMapping("/droneReport")
+    public AjaxResult droneReport(@RequestBody String jsonStr) {
+        if (StringUtils.isEmpty(jsonStr)) {
+            logger.error("参数为空");
+            return AjaxResult.error("参数为空");
+        }
+        logger.info("无人机数据: {}", jsonStr);
+
+        try {
+            JSONObject jsonObject = JSON.parseObject(URLToJSONConverter.convertURLToJSON(jsonStr));
+            JSONArray dataArray = jsonObject.getJSONArray("data");
+
+            if (dataArray == null || dataArray.isEmpty()) {
+                logger.error("数据格式异常: 缺少data数组");
+                return AjaxResult.error("数据格式异常");
+            }
+
+            List<DroneVO> droneArray = dataArray.stream()
+                    .map(data -> JSON.parseObject(data.toString(), DroneVO.class))
+                    .collect(Collectors.toList());
+
+            return toAjax(alarmEventService.insertDroneEvent(droneArray));
+        } catch (Exception e) {
+            logger.error("数据处理失败: {}", e.getMessage());
+            return AjaxResult.error("处理失败: " + e.getMessage());
+        }
+    }
 }

+ 63 - 0
src/main/java/com/sooka/sponest/event/centereventteventcatalogue/domain/vo/DroneVO.java

@@ -0,0 +1,63 @@
+package com.sooka.sponest.event.centereventteventcatalogue.domain.vo;
+
+import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.*;
+import org.apache.ibatis.type.Alias;
+
+import java.util.Date;
+
+@Setter
+@Getter
+@NoArgsConstructor
+@AllArgsConstructor
+@ToString
+@Alias("droneVo")
+public class DroneVO {
+
+    /**
+     * 数据id
+     */
+    private String id;
+    /**
+     * 时间戳
+     */
+    private Long timeStamp;
+    /**
+     * 海拔高度
+     */
+    private Double altitude;
+    /**
+     * 隐患类型
+     */
+    private String alarmType;
+    /**
+     * 隐患时间
+     */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
+    private Date createTime;
+    /**
+     * 隐患图片地址
+     */
+    private String photoPath;
+    /**
+     * 隐患纬度
+     */
+    private String latitude;
+    /**
+     * 隐患经度
+     */
+    private String longitude;
+    /**
+     * 隐患图片id
+     */
+    private Integer photoId;
+    /**
+     * 图片名称
+     */
+    private String photoName;
+    /**
+     * 本地图片路径
+     */
+    private String localPath;
+
+}

+ 9 - 0
src/main/java/com/sooka/sponest/event/centereventteventcatalogue/mapper/AlarmEventMapper.java

@@ -0,0 +1,9 @@
+package com.sooka.sponest.event.centereventteventcatalogue.mapper;
+
+import com.sooka.sponest.event.centereventteventcatalogue.domain.vo.DroneVO;
+
+import java.util.List;
+
+public interface AlarmEventMapper {
+    int insertDrone(List<DroneVO> alarmData);
+}

+ 5 - 0
src/main/java/com/sooka/sponest/event/centereventteventcatalogue/service/AlarmEventService.java

@@ -8,6 +8,9 @@ import com.sooka.sponest.event.centereventteventcatalogue.domain.haikang.EventsV
 import com.sooka.sponest.event.centereventteventcatalogue.domain.haikang.HaiKangEventVo;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.sensor.SensorEventVo;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.tower.TowerEventVo;
+import com.sooka.sponest.event.centereventteventcatalogue.domain.vo.DroneVO;
+
+import java.util.List;
 
 public interface AlarmEventService {
 
@@ -39,4 +42,6 @@ public interface AlarmEventService {
 
     // 住建事件
     String insertHousingConstructionEvent(SensorEventVo sensorEventVo);
+
+    int insertDroneEvent(List<DroneVO> droneArray);
 }

+ 27 - 0
src/main/java/com/sooka/sponest/event/centereventteventcatalogue/service/impl/AlarmEventServiceImpl.java

@@ -9,6 +9,7 @@ import com.ruoyi.common.core.utils.SpringUtils;
 import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.common.core.utils.uuid.IdUtils;
 import com.ruoyi.system.api.RemoteDeptService;
+import com.ruoyi.system.api.RemoteFileService;
 import com.ruoyi.system.api.domain.SysDept;
 import com.sooka.sponest.event.centereventtdeptevent.domain.CentereventDeptEvent;
 import com.sooka.sponest.event.centereventtdeptevent.service.ICentereventDeptEventService;
@@ -19,6 +20,8 @@ import com.sooka.sponest.event.centereventteventcatalogue.domain.haikang.EventsV
 import com.sooka.sponest.event.centereventteventcatalogue.domain.haikang.HaiKangEventVo;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.sensor.SensorEventVo;
 import com.sooka.sponest.event.centereventteventcatalogue.domain.tower.TowerEventVo;
+import com.sooka.sponest.event.centereventteventcatalogue.domain.vo.DroneVO;
+import com.sooka.sponest.event.centereventteventcatalogue.mapper.AlarmEventMapper;
 import com.sooka.sponest.event.centereventteventcatalogue.service.AlarmEventService;
 import com.sooka.sponest.event.centereventteventcatalogue.service.ICentereventTEventcatalogueService;
 import com.sooka.sponest.event.centereventteventtype.domain.CentereventTEventtype;
@@ -28,6 +31,7 @@ import com.sooka.sponest.event.centereventtfirelog.service.ICentereventTFireLogS
 import com.sooka.sponest.event.remoteapi.RemoteDataService;
 import com.sooka.sponest.event.remoteapi.domain.CenterdataTAttach;
 import com.sooka.sponest.event.utils.GWHttpUtilsTest65;
+import com.sooka.sponest.event.utils.NetworkImageToMultipartFile;
 import com.sooka.sponest.event.utils.RemoteApiUtil;
 import com.sooka.sponest.monitor.api.RemoteMonitorService;
 import com.sooka.sponest.monitor.api.domain.CenterdataTAidevicedept;
@@ -47,6 +51,7 @@ import org.springframework.web.client.RestTemplate;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.List;
+import java.util.Optional;
 
 import static com.ruoyi.common.core.utils.DateUtils.YYYY_MM_DD_HH_MM_SS;
 import static com.sooka.sponest.event.utils.EventConstants.*;
@@ -71,6 +76,12 @@ public class AlarmEventServiceImpl implements AlarmEventService {
     @Autowired
     private ICentereventTEventtypeService centereventTEventtypeService;
 
+    @Autowired
+    private RemoteFileService fileService;
+
+    @Autowired
+    private AlarmEventMapper alarmEventMapper;
+
     @Value("${sooka.dahuaservice.detail}")
     private String detailUrl;
 
@@ -673,4 +684,20 @@ public class AlarmEventServiceImpl implements AlarmEventService {
         this.insertEventLog(centereventTEventcatalogue);
         return centereventTEventcatalogue.getEventCode() + "_" + eventtype.getEventTypeName();
     }
+
+
+    @Override
+    public int insertDroneEvent(List<DroneVO> alarmData) {
+        alarmData.parallelStream().forEach(item -> {
+            item.setId(IdUtils.simpleUUID());
+            try {
+                Optional.ofNullable(NetworkImageToMultipartFile.downloadImageToMultipartFile(item.getPhotoPath()))
+                        .map(multipartFile -> fileService.upload(multipartFile).getData())
+                        .ifPresent(data -> item.setLocalPath(data.getUrl()));
+            } catch (Exception e) {
+                logger.error("Failed to process image for item {}: {}", item.getId(), e.getMessage());
+            }
+        });
+        return alarmEventMapper.insertDrone(alarmData);
+    }
 }

+ 112 - 0
src/main/java/com/sooka/sponest/event/utils/NetworkImageToMultipartFile.java

@@ -0,0 +1,112 @@
+package com.sooka.sponest.event.utils;
+
+import org.springframework.mock.web.MockMultipartFile;
+import org.springframework.web.multipart.MultipartFile;
+
+import javax.net.ssl.*;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.cert.X509Certificate;
+
+public class NetworkImageToMultipartFile {
+
+    /**
+     * 从网络路径下载图片并转换为 MultipartFile
+     * @param imageUrl 图片的网络路径
+     * @return MultipartFile 对象
+     */
+    public static MultipartFile downloadImageToMultipartFile(String imageUrl) {
+        try {
+            // 禁用 SSL 证书验证(仅适用于开发环境)
+            disableSSLVerification();
+
+            // 打开连接
+            URL url = new URL(imageUrl);
+            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
+            connection.setRequestMethod("GET");
+
+            int responseCode = connection.getResponseCode();
+            if (responseCode == HttpURLConnection.HTTP_OK) {
+                // 获取输入流
+                InputStream inputStream = connection.getInputStream();
+
+                // 获取文件名(从 URL 中提取)
+                String fileName = imageUrl.substring(imageUrl.lastIndexOf('/') + 1);
+
+                // 创建 MockMultipartFile
+                MultipartFile multipartFile = new MockMultipartFile(
+                        fileName, // 文件名
+                        fileName, // 原始文件名
+                        "image/jpeg", // 文件内容类型
+                        inputStream // 输入流
+                );
+
+                // 关闭输入流
+                inputStream.close();
+
+                return multipartFile;
+            } else {
+                System.out.println("Failed to download image. Server responded with code: " + responseCode);
+            }
+        } catch (IOException e) {
+            e.printStackTrace();
+            System.out.println("Error downloading image: " + e.getMessage());
+        } catch (NoSuchAlgorithmException | KeyManagementException e) {
+            e.printStackTrace();
+            System.out.println("Error disabling SSL verification: " + e.getMessage());
+        }
+        return null;
+    }
+
+    /**
+     * 禁用 SSL 证书验证(仅适用于开发环境)
+     */
+    public static void disableSSLVerification() throws NoSuchAlgorithmException, KeyManagementException {
+        // 创建一个信任所有证书的 TrustManager
+        TrustManager[] trustAllCerts = new TrustManager[]{
+                new X509TrustManager() {
+                    public X509Certificate[] getAcceptedIssuers() {
+                        return null;
+                    }
+
+                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
+                    }
+
+                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
+                    }
+                }
+        };
+
+        // 安装全局的信任管理器
+        SSLContext sc = SSLContext.getInstance("SSL");
+        sc.init(null, trustAllCerts, new java.security.SecureRandom());
+        HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
+
+        // 创建一个 HostnameVerifier,跳过主机名验证
+        HostnameVerifier allHostsValid = new HostnameVerifier() {
+            public boolean verify(String hostname, SSLSession session) {
+                return true;
+            }
+        };
+
+        HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
+    }
+
+    public static void main(String[] args) {
+        String imageUrl = "https://47.93.50.30:443/media/dji-photos/wayline/1742354657053.JPG";
+
+        // 下载图片并转换为 MultipartFile
+        MultipartFile multipartFile = downloadImageToMultipartFile(imageUrl);
+
+        if (multipartFile != null) {
+            System.out.println("File Name: " + multipartFile.getOriginalFilename());
+            System.out.println("File Size: " + multipartFile.getSize() + " bytes");
+        } else {
+            System.out.println("Failed to convert image to MultipartFile.");
+        }
+    }
+}

+ 48 - 0
src/main/java/com/sooka/sponest/event/utils/URLToJSONConverter.java

@@ -0,0 +1,48 @@
+package com.sooka.sponest.event.utils;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+public class URLToJSONConverter {
+
+    /**
+     * 将 URL 编码的字符串转换为格式化的 JSON 字符串
+     * @param encodedData URL 编码的字符串
+     * @return 格式化的 JSON 字符串
+     */
+    public static String convertURLToJSON(String encodedData) {
+        try {
+            // 解码 URL 编码的字符串
+            String decodedData = URLDecoder.decode(encodedData, "UTF-8");
+
+            // 去掉等号(如果存在)
+            if (decodedData.endsWith("=")) {
+                decodedData = decodedData.substring(0, decodedData.length() - 1);
+            }
+
+            // 将字符串解析为 JSON 对象
+            JSONObject jsonObject = JSON.parseObject(decodedData);
+
+            // 格式化 JSON 输出
+            return jsonObject.toJSONString();
+        } catch (UnsupportedEncodingException e) {
+            e.printStackTrace();
+            return "Error: UnsupportedEncodingException";
+        } catch (Exception e) {
+            e.printStackTrace();
+            return "Error: Invalid input format";
+        }
+    }
+
+    public static void main(String[] args) {
+        // 示例 URL 编码的 JSON 数据
+        String encodedData = "%7B%22data%22%3A%5B%7B%22alarmType%22%3A%22Sleep%22%2C%22altitude%22%3A0.0%2C%22createTime%22%3A1742354657000%2C%22latitude%22%3A38.185382%2C%22longitude%22%3A107.487296322%2C%22photoId%22%3A518%2C%22photoPath%22%3A%22https%3A%2F%2F47.93.50.30%3A443%2Fmedia%2Fdji-photos%2Fwayline%2F1742354657053.JPG%22%2C%22timeStamp%22%3A0%7D%5D%7D";
+
+        // 调用方法并打印结果
+        String result = convertURLToJSON(encodedData);
+        System.out.println(result);
+    }
+}

+ 28 - 0
src/main/resources/mapper/centereventteventcatalogue/AlarmEventMapper.xml

@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.sooka.sponest.event.centereventteventcatalogue.mapper.AlarmEventMapper">
+    <resultMap id="resultDroneMapper" type="droneVo">
+        <id column="id" jdbcType="VARCHAR" property="id"/>
+        <result column="time_stamp" jdbcType="VARCHAR" property="timeStamp"/>
+        <result column="altitude" jdbcType="VARCHAR" property="altitude"/>
+        <result column="alarm_type" jdbcType="VARCHAR" property="alarmType"/>
+        <result column="create_time" jdbcType="VARCHAR" property="createTime"/>
+        <result column="photo_path" jdbcType="VARCHAR" property="photoPath"/>
+        <result column="latitude" jdbcType="VARCHAR" property="latitude"/>
+        <result column="longitude" jdbcType="VARCHAR" property="longitude"/>
+        <result column="photo_id" jdbcType="VARCHAR" property="photoId"/>
+        <result column="photo_name" jdbcType="VARCHAR" property="photoName"/>
+        <result column="local_path" jdbcType="VARCHAR" property="localPath"/>
+    </resultMap>
+
+    <insert id="insertDrone" parameterType="list">
+        insert into centerevent_t_drone
+        (id, time_stamp, altitude, alarm_type, create_time, photo_path, latitude, longitude, photo_id, photo_name, local_path)
+        values
+        <foreach collection="list" item="item" index="index" separator=",">
+            (#{item.id}, #{item.timeStamp}, #{item.altitude}, #{item.alarmType}, #{item.createTime}, #{item.photoPath}, #{item.latitude}, #{item.longitude}, #{item.photoId}, #{item.photoName}, #{item.localPath})
+        </foreach>
+    </insert>
+</mapper>