From 6ae48aee541213d8307ba6f06254c850999b34e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B0=8F=E4=BA=91?= Date: Tue, 10 Feb 2026 15:30:50 +0800 Subject: [PATCH 1/3] xx --- .devops/cleanup_orphaned_aircrafts.sh | 153 ++++++++++++++++++ .devops/cleanup_orphaned_aircrafts.sql | 114 +++++++++++++ a_th_web | 2 +- hyf-backend | 2 +- .../device/api/RemoteAircraftFlyService.java | 19 +++ .../device/api/domain/MachineStateVO.java | 106 ++++++++++++ .../RemoteAircraftFlyFallbackFactory.java | 13 ++ ruoyi-modules/tuoheng-device | 2 +- 8 files changed, 408 insertions(+), 3 deletions(-) create mode 100644 .devops/cleanup_orphaned_aircrafts.sh create mode 100644 .devops/cleanup_orphaned_aircrafts.sql create mode 100644 ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/domain/MachineStateVO.java diff --git a/.devops/cleanup_orphaned_aircrafts.sh b/.devops/cleanup_orphaned_aircrafts.sh new file mode 100644 index 0000000..e46a328 --- /dev/null +++ b/.devops/cleanup_orphaned_aircrafts.sh @@ -0,0 +1,153 @@ +#!/bin/bash +# ============================================================ +# 清理没有关联机场的大疆无人机 +# ============================================================ + +set -e + +echo "==========================================" +echo "清理没有关联机场的大疆无人机" +echo "==========================================" + +# 数据库配置 +DB_CONTAINER="ruoyi-mysql" +DB_USER="root" +DB_PASSWORD="password" +DB_NAME="ry-cloud" + +echo "" +echo "第一步:查询所有大疆无人机(用于确认)" +echo "==========================================" +docker exec ${DB_CONTAINER} mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME} -e " +SELECT + a.aircraft_id, + a.aircraft_name, + d.device_manufacturer, + d.device_sn +FROM device_aircraft a +LEFT JOIN device_device d ON a.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang' +ORDER BY a.aircraft_id; +" + +echo "" +echo "第二步:查询没有关联机场的大疆无人机" +echo "==========================================" +docker exec ${DB_CONTAINER} mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME} -e " +SELECT + a.aircraft_id, + a.aircraft_name, + d.device_manufacturer, + d.device_sn, + d.iot_device_id +FROM device_aircraft a +INNER JOIN device_device d ON a.device_id = d.device_id +LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id +WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL +ORDER BY a.aircraft_id; +" + +echo "" +echo "==========================================" +echo "即将删除以上无人机记录" +echo "请确认是否继续?(y/n)" +read -r confirm + +if [[ ! $confirm =~ ^[Yy]$ ]]; then + echo "操作已取消" + exit 0 +fi + +echo "" +echo "第三步:删除无人机挂载关联表中的记录" +echo "==========================================" +docker exec ${DB_CONTAINER} mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME} -e " +DELETE FROM device_aircraft_payload +WHERE aircraft_id IN ( + SELECT a.aircraft_id + FROM device_aircraft a + INNER JOIN device_device d ON a.device_id = d.device_id + LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id + WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL +); +" + +echo "无人机挂载关联记录删除完成" + +echo "" +echo "第四步:删除机场无人机关联表中的记录" +echo "==========================================" +docker exec ${DB_CONTAINER} mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME} -e " +DELETE FROM device_dock_aircraft +WHERE aircraft_id IN ( + SELECT a.aircraft_id + FROM device_aircraft a + INNER JOIN device_device d ON a.device_id = d.device_id + LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id + WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL +); +" + +echo "机场无人机关联记录删除完成" + +echo "" +echo "第五步:删除无人机表中的记录" +echo "==========================================" +docker exec ${DB_CONTAINER} mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME} -e " +DELETE FROM device_aircraft +WHERE aircraft_id IN ( + SELECT temp.aircraft_id + FROM ( + SELECT a.aircraft_id + FROM device_aircraft a + INNER JOIN device_device d ON a.device_id = d.device_id + LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id + WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL + ) AS temp +); +" + +echo "无人机记录删除完成" + +echo "" +echo "第六步:验证删除结果" +echo "==========================================" +docker exec ${DB_CONTAINER} mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME} -e " +SELECT + a.aircraft_id, + a.aircraft_name, + d.device_manufacturer, + d.device_sn +FROM device_aircraft a +INNER JOIN device_device d ON a.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang' +ORDER BY a.aircraft_id; +" + +echo "" +echo "统计验证:" +echo "==========================================" +docker exec ${DB_CONTAINER} mysql -u${DB_USER} -p${DB_PASSWORD} ${DB_NAME} -e " +SELECT + '大疆无人机总数' AS statistic_name, + COUNT(*) AS count +FROM device_aircraft a +INNER JOIN device_device d ON a.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang' +UNION ALL +SELECT + '大疆机场总数' AS statistic_name, + COUNT(*) AS count +FROM device_dock dock +INNER JOIN device_device d ON dock.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang'; +" + +echo "" +echo "==========================================" +echo "清理完成" +echo "==========================================" diff --git a/.devops/cleanup_orphaned_aircrafts.sql b/.devops/cleanup_orphaned_aircrafts.sql new file mode 100644 index 0000000..9db28ba --- /dev/null +++ b/.devops/cleanup_orphaned_aircrafts.sql @@ -0,0 +1,114 @@ +-- ============================================================ +-- 清理没有关联机场的大疆无人机 +-- ============================================================ +-- 问题:大疆的机场是7个,无人机是10个,有3个无人机没有关联机场 +-- 解决方案:删除没有关联机场的大疆无人机记录 +-- ============================================================ + +-- 第一步:查询所有大疆厂商的无人机(用于确认) +SELECT + a.aircraft_id, + a.aircraft_name, + d.device_manufacturer, + d.device_sn +FROM device_aircraft a +LEFT JOIN device_device d ON a.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang' +ORDER BY a.aircraft_id; + +-- 第二步:查询没有关联机场的大疆无人机 +SELECT + a.aircraft_id, + a.aircraft_name, + d.device_manufacturer, + d.device_sn, + d.iot_device_id +FROM device_aircraft a +INNER JOIN device_device d ON a.device_id = d.device_id +LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id +WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL +ORDER BY a.aircraft_id; + +-- 第三步:确认删除前,再次检查(谨慎操作) +-- 执行此查询后,请确认这些无人机确实需要删除 +SELECT + a.aircraft_id, + a.aircraft_name, + d.device_manufacturer, + d.device_sn, + d.iot_device_id, + '将被删除' AS action +FROM device_aircraft a +INNER JOIN device_device d ON a.device_id = d.device_id +LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id +WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL; + +-- 第四步:删除没有关联机场的大疆无人机(谨慎操作!) +-- 删除顺序: +-- 1. 先删除无人机挂载关联表中的记录 +-- 2. 再删除机场无人机关联表中的记录 +-- 3. 最后删除无人机表中的记录 + +-- 4.1 删除无人机挂载关联表中的记录 +DELETE FROM device_aircraft_payload +WHERE aircraft_id IN ( + SELECT a.aircraft_id + FROM device_aircraft a + INNER JOIN device_device d ON a.device_id = d.device_id + LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id + WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL +); + +-- 4.2 删除机场无人机关联表中的记录(如果有) +DELETE FROM device_dock_aircraft +WHERE aircraft_id IN ( + SELECT a.aircraft_id + FROM device_aircraft a + INNER JOIN device_device d ON a.device_id = d.device_id + LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id + WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL +); + +-- 4.3 删除无人机表中的记录 +DELETE FROM device_aircraft +WHERE aircraft_id IN ( + SELECT temp.aircraft_id + FROM ( + SELECT a.aircraft_id + FROM device_aircraft a + INNER JOIN device_device d ON a.device_id = d.device_id + LEFT JOIN device_dock_aircraft da ON a.aircraft_id = da.aircraft_id + WHERE d.device_manufacturer = 'dajiang' + AND da.id IS NULL + ) AS temp +); + +-- 第五步:验证删除结果 +SELECT + a.aircraft_id, + a.aircraft_name, + d.device_manufacturer, + d.device_sn +FROM device_aircraft a +INNER JOIN device_device d ON a.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang' +ORDER BY a.aircraft_id; + +-- 统计验证 +SELECT + '大疆无人机总数' AS statistic_name, + COUNT(*) AS count +FROM device_aircraft a +INNER JOIN device_device d ON a.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang' +UNION ALL +SELECT + '大疆机场总数' AS statistic_name, + COUNT(*) AS count +FROM device_dock dock +INNER JOIN device_device d ON dock.device_id = d.device_id +WHERE d.device_manufacturer = 'dajiang'; diff --git a/a_th_web b/a_th_web index 00f2797..0a0b974 160000 --- a/a_th_web +++ b/a_th_web @@ -1 +1 @@ -Subproject commit 00f27970aa34f76cdc7cf8673d9809b14fd00a93 +Subproject commit 0a0b9741cca600b27b6ab15905f02ae3d71e29e2 diff --git a/hyf-backend b/hyf-backend index 4a53df8..6f0ac0c 160000 --- a/hyf-backend +++ b/hyf-backend @@ -1 +1 @@ -Subproject commit 4a53df8fb148690175918557131e01729bca871d +Subproject commit 6f0ac0c588c9a1711ddbe833c638206eed4bb3c4 diff --git a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java index fcca8db..d0f6732 100644 --- a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java +++ b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java @@ -7,6 +7,7 @@ import com.ruoyi.device.api.domain.DroneCurrentStatusVO; import com.ruoyi.device.api.domain.DroneFlightControlRequest; import com.ruoyi.device.api.domain.DroneRealtimeInfoVO; import com.ruoyi.device.api.domain.DroneTakeoffResponseVO; +import com.ruoyi.device.api.domain.MachineStateVO; import com.ruoyi.device.api.factory.RemoteAircraftFlyFallbackFactory; import org.springframework.cloud.openfeign.FeignClient; import org.springframework.web.bind.annotation.*; @@ -59,4 +60,22 @@ public interface RemoteAircraftFlyService */ @PostMapping("/drone/takeoff/{dockId}") R takeoff(@PathVariable("dockId") Long dockId, @RequestHeader(SecurityConstants.FROM_SOURCE) String source); + + /** + * 无人机开机接口 + * + * @param sn 机场SN号 + * @return 开机响应 + */ + @PostMapping("/drone/power-on/{sn}") + R powerOn(@PathVariable("sn") String sn); + + /** + * 查询设备状态 + * + * @param sn 设备SN号 + * @return 设备状态信息 + */ + @GetMapping("/drone/machine-state/{sn}") + R getMachineState(@PathVariable("sn") String sn); } \ No newline at end of file diff --git a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/domain/MachineStateVO.java b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/domain/MachineStateVO.java new file mode 100644 index 0000000..c5e91ae --- /dev/null +++ b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/domain/MachineStateVO.java @@ -0,0 +1,106 @@ +package com.ruoyi.device.api.domain; + +import java.io.Serializable; + +/** + * 设备状态视图对象 + * API 层 VO,用于前后端数据交互 + * + * @author ruoyi + * @date 2026-02-10 + */ +public class MachineStateVO implements Serializable +{ + private static final long serialVersionUID = 1L; + + /** 设备SN号 */ + private String sn; + + /** 无人机状态 */ + private String droneState; + + /** 机场状态 */ + private String airportState; + + /** 舱门状态 */ + private String coverState; + + /** DRC状态 */ + private String drcState; + + /** 调试模式状态 */ + private String debugModeState; + + public String getSn() + { + return sn; + } + + public void setSn(String sn) + { + this.sn = sn; + } + + public String getDroneState() + { + return droneState; + } + + public void setDroneState(String droneState) + { + this.droneState = droneState; + } + + public String getAirportState() + { + return airportState; + } + + public void setAirportState(String airportState) + { + this.airportState = airportState; + } + + public String getCoverState() + { + return coverState; + } + + public void setCoverState(String coverState) + { + this.coverState = coverState; + } + + public String getDrcState() + { + return drcState; + } + + public void setDrcState(String drcState) + { + this.drcState = drcState; + } + + public String getDebugModeState() + { + return debugModeState; + } + + public void setDebugModeState(String debugModeState) + { + this.debugModeState = debugModeState; + } + + @Override + public String toString() + { + return "MachineStateVO{" + + "sn='" + sn + '\'' + + ", droneState='" + droneState + '\'' + + ", airportState='" + airportState + '\'' + + ", coverState='" + coverState + '\'' + + ", drcState='" + drcState + '\'' + + ", debugModeState='" + debugModeState + '\'' + + '}'; + } +} \ No newline at end of file diff --git a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java index 30d4adc..9c2cee5 100644 --- a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java +++ b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java @@ -6,6 +6,7 @@ import com.ruoyi.device.api.domain.DroneCurrentStatusVO; import com.ruoyi.device.api.domain.DroneFlightControlRequest; import com.ruoyi.device.api.domain.DroneRealtimeInfoVO; import com.ruoyi.device.api.domain.DroneTakeoffResponseVO; +import com.ruoyi.device.api.domain.MachineStateVO; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.cloud.openfeign.FallbackFactory; @@ -51,6 +52,18 @@ public class RemoteAircraftFlyFallbackFactory implements FallbackFactory powerOn(String sn) + { + return R.fail("无人机开机失败:" + throwable.getMessage()); + } + + @Override + public R getMachineState(String sn) + { + return R.fail("查询设备状态失败:" + throwable.getMessage()); + } }; } } \ No newline at end of file diff --git a/ruoyi-modules/tuoheng-device b/ruoyi-modules/tuoheng-device index 82b6327..2de46a6 160000 --- a/ruoyi-modules/tuoheng-device +++ b/ruoyi-modules/tuoheng-device @@ -1 +1 @@ -Subproject commit 82b63271b71dea00924875ca3f2bd861ac0c8b88 +Subproject commit 2de46a69c31841efcff8f930457dd21e2878d9b0 From d6856ec1c202fde1d564759926b992716c161ef4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B0=8F=E4=BA=91?= Date: Wed, 11 Feb 2026 09:16:06 +0800 Subject: [PATCH 2/3] xx --- .../com/ruoyi/device/api/RemoteAircraftFlyService.java | 9 +++++++++ .../api/factory/RemoteAircraftFlyFallbackFactory.java | 6 ++++++ ruoyi-modules/tuoheng-device | 2 +- 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java index d0f6732..edd213c 100644 --- a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java +++ b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/RemoteAircraftFlyService.java @@ -70,6 +70,15 @@ public interface RemoteAircraftFlyService @PostMapping("/drone/power-on/{sn}") R powerOn(@PathVariable("sn") String sn); + /** + * 无人机关机接口 + * + * @param sn 机场SN号 + * @return 关机响应 + */ + @PostMapping("/drone/power-off/{sn}") + R powerOff(@PathVariable("sn") String sn); + /** * 查询设备状态 * diff --git a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java index 9c2cee5..7609818 100644 --- a/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java +++ b/ruoyi-api/tuoheng-api-device/src/main/java/com/ruoyi/device/api/factory/RemoteAircraftFlyFallbackFactory.java @@ -59,6 +59,12 @@ public class RemoteAircraftFlyFallbackFactory implements FallbackFactory powerOff(String sn) + { + return R.fail("无人机关机失败:" + throwable.getMessage()); + } + @Override public R getMachineState(String sn) { diff --git a/ruoyi-modules/tuoheng-device b/ruoyi-modules/tuoheng-device index 2de46a6..42e6643 160000 --- a/ruoyi-modules/tuoheng-device +++ b/ruoyi-modules/tuoheng-device @@ -1 +1 @@ -Subproject commit 2de46a69c31841efcff8f930457dd21e2878d9b0 +Subproject commit 42e6643b52f62acfdd7c002bbe3b7e809179c861 From c025f161b020cd99b642fe4fec1bd4072dcc6de7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AD=99=E5=B0=8F=E4=BA=91?= Date: Wed, 11 Feb 2026 11:30:57 +0800 Subject: [PATCH 3/3] xx --- docker/a_th_web/conf/nginx.conf | 5 +++++ docker/nginx/conf/nginx.conf | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/docker/a_th_web/conf/nginx.conf b/docker/a_th_web/conf/nginx.conf index 0803216..e528be4 100644 --- a/docker/a_th_web/conf/nginx.conf +++ b/docker/a_th_web/conf/nginx.conf @@ -46,6 +46,11 @@ http { proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://ruoyi-gateway:8080/; + + # 支持长时间命令执行 + proxy_connect_timeout 300s; + proxy_send_timeout 300s; + proxy_read_timeout 300s; } location /minio/ { diff --git a/docker/nginx/conf/nginx.conf b/docker/nginx/conf/nginx.conf index 94056ec..1e1896b 100644 --- a/docker/nginx/conf/nginx.conf +++ b/docker/nginx/conf/nginx.conf @@ -27,6 +27,11 @@ http { proxy_set_header REMOTE-HOST $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://ruoyi-gateway:8080/; + + # 支持长时间命令执行 + proxy_connect_timeout 300s; + proxy_send_timeout 300s; + proxy_read_timeout 300s; } # 避免actuator暴露