增加禁飞区
This commit is contained in:
parent
139e2eff46
commit
61ca367330
|
|
@ -8,6 +8,9 @@ package com.multictrl.common.constant;
|
||||||
*/
|
*/
|
||||||
public interface BusinessConstant {
|
public interface BusinessConstant {
|
||||||
|
|
||||||
|
String WEB_EVENT_TOPIC = "thing/product/%s/web_event";
|
||||||
|
String NOFLY_ZONE_METHOD = "nofly_zone";
|
||||||
|
|
||||||
//********************************* minio *********************************//
|
//********************************* minio *********************************//
|
||||||
String ROUTE_IMG_BUCKET = "route-images";//航线图片桶
|
String ROUTE_IMG_BUCKET = "route-images";//航线图片桶
|
||||||
String ROUTE_KMZ_BUCKET = "route-kmz";//航线桶
|
String ROUTE_KMZ_BUCKET = "route-kmz";//航线桶
|
||||||
|
|
@ -83,6 +86,10 @@ public interface BusinessConstant {
|
||||||
String UAV_LIGHT_INDEX = "uav_light_index_";
|
String UAV_LIGHT_INDEX = "uav_light_index_";
|
||||||
String UAV_MODE_CODE = "uav_mode_code_";
|
String UAV_MODE_CODE = "uav_mode_code_";
|
||||||
|
|
||||||
|
//********************************* other cache key *********************************//
|
||||||
|
String DOCK_NOFLY_ZONE = "dock_nofly_zone_";
|
||||||
|
String DOCK_NOFLY_ZONE_TRIGGER_SIGN = "dock_nofly_zone_trigger_sign_";
|
||||||
|
|
||||||
//********************************* other *********************************//
|
//********************************* other *********************************//
|
||||||
String HTTP_PROTOCOL = "http://";
|
String HTTP_PROTOCOL = "http://";
|
||||||
String HTTPS_PROTOCOL = "https://";
|
String HTTPS_PROTOCOL = "https://";
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,97 @@
|
||||||
|
package com.multictrl.modules.business.controller;
|
||||||
|
|
||||||
|
import com.multictrl.common.annotation.ApiOrder;
|
||||||
|
import com.multictrl.common.annotation.LogOperation;
|
||||||
|
import com.multictrl.common.constant.Constant;
|
||||||
|
import com.multictrl.common.page.PageData;
|
||||||
|
import com.multictrl.common.utils.Result;
|
||||||
|
import com.multictrl.common.validator.AssertUtils;
|
||||||
|
import com.multictrl.common.validator.ValidatorUtils;
|
||||||
|
import com.multictrl.common.validator.group.AddGroup;
|
||||||
|
import com.multictrl.common.validator.group.UpdateGroup;
|
||||||
|
import com.multictrl.modules.business.dto.NoflyZoneDTO;
|
||||||
|
import com.multictrl.modules.business.service.NoflyZoneService;
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.shiro.authz.annotation.RequiresPermissions;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameter;
|
||||||
|
import io.swagger.v3.oas.annotations.Parameters;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁飞区
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-09
|
||||||
|
*/
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("business/noflyzone")
|
||||||
|
@Tag(name = "禁飞区")
|
||||||
|
@ApiOrder(22)
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class NoflyZoneController {
|
||||||
|
private final NoflyZoneService noflyZoneService;
|
||||||
|
|
||||||
|
@GetMapping("page")
|
||||||
|
@Operation(summary = "分页")
|
||||||
|
@Parameters({
|
||||||
|
@Parameter(name = Constant.PAGE, description = "当前页码,从1开始"),
|
||||||
|
@Parameter(name = Constant.LIMIT, description = "每页显示记录数"),
|
||||||
|
@Parameter(name = "name", description = "名称")
|
||||||
|
})
|
||||||
|
@RequiresPermissions("bus:noflyzone:page")
|
||||||
|
public Result<PageData<NoflyZoneDTO>> page(@Parameter(hidden = true) @RequestParam Map<String, Object> params) {
|
||||||
|
PageData<NoflyZoneDTO> page = noflyZoneService.pageList(params);
|
||||||
|
|
||||||
|
return new Result<PageData<NoflyZoneDTO>>().ok(page);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping
|
||||||
|
@Operation(summary = "保存")
|
||||||
|
@LogOperation("保存")
|
||||||
|
@RequiresPermissions("bus:noflyzone:save")
|
||||||
|
public Result<Object> save(@RequestBody NoflyZoneDTO dto) {
|
||||||
|
//效验数据
|
||||||
|
ValidatorUtils.validateEntity(dto, AddGroup.class);
|
||||||
|
noflyZoneService.saveNoFlying(dto);
|
||||||
|
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PutMapping
|
||||||
|
@Operation(summary = "修改")
|
||||||
|
@LogOperation("修改")
|
||||||
|
@RequiresPermissions("bus:noflyzone:update")
|
||||||
|
public Result<Object> update(@RequestBody NoflyZoneDTO dto) {
|
||||||
|
//效验数据
|
||||||
|
ValidatorUtils.validateEntity(dto, UpdateGroup.class);
|
||||||
|
noflyZoneService.update(dto);
|
||||||
|
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@DeleteMapping
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@LogOperation("删除")
|
||||||
|
@RequiresPermissions("bus:noflyzone:delete")
|
||||||
|
public Result<Object> delete(@RequestBody Long[] ids) {
|
||||||
|
//效验数据
|
||||||
|
AssertUtils.isArrayEmpty(ids, "id");
|
||||||
|
noflyZoneService.delete(ids);
|
||||||
|
|
||||||
|
return new Result<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@GetMapping("/getNoFlying")
|
||||||
|
@Operation(summary = "获取机库禁飞区", description = "返回机库所属组织以及上级组织设置的禁飞区")
|
||||||
|
public Result<List<NoflyZoneDTO>> getNoFlying(@RequestParam String dockSn) {
|
||||||
|
List<NoflyZoneDTO> list = noflyZoneService.getNoFlyZoneByDockSn(dockSn);
|
||||||
|
|
||||||
|
return new Result<List<NoflyZoneDTO>>().ok(list);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
package com.multictrl.modules.business.dao;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.multictrl.common.dao.BaseDao;
|
||||||
|
import com.multictrl.modules.business.dto.NoflyZoneDTO;
|
||||||
|
import com.multictrl.modules.business.entity.NoflyZoneEntity;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁飞区
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-09
|
||||||
|
*/
|
||||||
|
@Mapper
|
||||||
|
public interface NoflyZoneDao extends BaseDao<NoflyZoneEntity> {
|
||||||
|
|
||||||
|
//分页列表
|
||||||
|
IPage<NoflyZoneDTO> pageList(IPage<NoflyZoneEntity> page, @Param("ew") QueryWrapper<NoflyZoneEntity> ew);
|
||||||
|
|
||||||
|
//新增禁飞区
|
||||||
|
void saveNoFlyZone(NoflyZoneEntity noflyZoneEntity);
|
||||||
|
|
||||||
|
//查询禁飞区
|
||||||
|
List<NoflyZoneDTO> getNoFlyZoneList(@Param("ew") QueryWrapper<NoflyZoneEntity> ew);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.multictrl.modules.business.dto;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import com.multictrl.common.validator.group.AddGroup;
|
||||||
|
import com.multictrl.common.validator.group.UpdateGroup;
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import jakarta.validation.constraints.*;
|
||||||
|
import jakarta.validation.groups.Default;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.io.Serial;
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁飞区
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-09
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Schema(name = "禁飞区")
|
||||||
|
public class NoflyZoneDTO implements Serializable {
|
||||||
|
@Serial
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Null(message = "标识必须为空", groups = {AddGroup.class})
|
||||||
|
@NotNull(message = "标识不能为空", groups = {UpdateGroup.class})
|
||||||
|
@Schema(description = "标识")
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
@Schema(description = "名称")
|
||||||
|
@NotBlank(message = "名称不能为空", groups = {AddGroup.class, UpdateGroup.class})
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
@NotBlank(message = "是否开启不能为空", groups = {AddGroup.class, UpdateGroup.class})
|
||||||
|
@Schema(description = "是否开启 1开启 0未开启")
|
||||||
|
private String status;
|
||||||
|
|
||||||
|
@Schema(description = "范围")
|
||||||
|
@NotEmpty(message = "范围不能为空", groups = {AddGroup.class})
|
||||||
|
@Size(min = 2, max = 2, message = "范围数据错误", groups = {AddGroup.class})
|
||||||
|
private List<List<@Valid point>> extent;
|
||||||
|
|
||||||
|
@Schema(description = "时间")
|
||||||
|
@JsonProperty(access = JsonProperty.Access.READ_ONLY)
|
||||||
|
private Date createDate;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String deptName;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
private String userName;
|
||||||
|
|
||||||
|
@Schema(hidden = true)
|
||||||
|
@JsonIgnore
|
||||||
|
private String extentWkt;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
@Data
|
||||||
|
public static class point {
|
||||||
|
|
||||||
|
@NotNull(message = "经度不能为空", groups = {AddGroup.class})
|
||||||
|
@Schema(description = "经度")
|
||||||
|
private Double lng;
|
||||||
|
|
||||||
|
@NotNull(message = "纬度不能为空", groups = {AddGroup.class})
|
||||||
|
@Schema(description = "纬度")
|
||||||
|
private Double lat;
|
||||||
|
|
||||||
|
@NotNull(message = "海拔高度不能为空", groups = {AddGroup.class})
|
||||||
|
@Schema(description = "海拔高度")
|
||||||
|
private Double height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.multictrl.modules.business.entity;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.multictrl.common.entity.BaseEntity;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.EqualsAndHashCode;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁飞区
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-09
|
||||||
|
*/
|
||||||
|
@EqualsAndHashCode(callSuper = true)
|
||||||
|
@Data
|
||||||
|
@TableName("bus_nofly_zone")
|
||||||
|
public class NoflyZoneEntity extends BaseEntity {
|
||||||
|
/**
|
||||||
|
* 名称
|
||||||
|
*/
|
||||||
|
private String name;
|
||||||
|
/**
|
||||||
|
* 是否开启 1开启 0未开启
|
||||||
|
*/
|
||||||
|
private String status;
|
||||||
|
/**
|
||||||
|
* 范围
|
||||||
|
*/
|
||||||
|
private String extent;
|
||||||
|
/**
|
||||||
|
* 部门标识
|
||||||
|
*/
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private Long deptId;
|
||||||
|
}
|
||||||
|
|
@ -7,10 +7,10 @@ import com.multictrl.common.constant.BusinessConstant;
|
||||||
import com.multictrl.common.constant.DockMode;
|
import com.multictrl.common.constant.DockMode;
|
||||||
import com.multictrl.common.utils.CacheUtils;
|
import com.multictrl.common.utils.CacheUtils;
|
||||||
import com.multictrl.common.utils.JsonUtils;
|
import com.multictrl.common.utils.JsonUtils;
|
||||||
|
import com.multictrl.modules.business.dto.NoflyZoneDTO;
|
||||||
|
import com.multictrl.modules.business.influxdb.FlightLog;
|
||||||
import com.multictrl.modules.business.influxdb.UavReport;
|
import com.multictrl.modules.business.influxdb.UavReport;
|
||||||
import com.multictrl.modules.business.service.DockService;
|
import com.multictrl.modules.business.service.*;
|
||||||
import com.multictrl.modules.business.service.FlightTaskService;
|
|
||||||
import com.multictrl.modules.business.service.InfluxService;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
@ -18,6 +18,9 @@ import org.springframework.stereotype.Component;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* osd设备属性定频上报0.5HZ
|
* osd设备属性定频上报0.5HZ
|
||||||
|
|
@ -33,6 +36,9 @@ public class OsdHandler implements MessageHandler {
|
||||||
private final InfluxService influxService;
|
private final InfluxService influxService;
|
||||||
private final FlightTaskService flightTaskService;
|
private final FlightTaskService flightTaskService;
|
||||||
private final DockService dockService;
|
private final DockService dockService;
|
||||||
|
private final DJIBaseService djiBaseService;
|
||||||
|
private final MqttPushService mqttPushService;
|
||||||
|
private final NoflyZoneService noflyZoneService;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void handleMessage(String topic, String payload, String gateway) {
|
public void handleMessage(String topic, String payload, String gateway) {
|
||||||
|
|
@ -59,13 +65,13 @@ public class OsdHandler implements MessageHandler {
|
||||||
}
|
}
|
||||||
//刚从“任务中”切到“空闲“,说明架次结束入库了
|
//刚从“任务中”切到“空闲“,说明架次结束入库了
|
||||||
if (modeCode == DockMode.IDLE.getCode()
|
if (modeCode == DockMode.IDLE.getCode()
|
||||||
&& CacheUtils.get(BusinessConstant.DOCK_IN_WORK + dockSn) != null) {
|
&& CacheUtils.get(BusinessConstant.DOCK_IN_WORK + dockSn) != null) {
|
||||||
CacheUtils.delete(BusinessConstant.DOCK_IN_WORK + dockSn);
|
CacheUtils.delete(BusinessConstant.DOCK_IN_WORK + dockSn);
|
||||||
log.debug("{}机库架次飞行完成,取消DRC心跳", dockSn);
|
log.debug("{}机库架次飞行完成,取消DRC心跳", dockSn);
|
||||||
List<String> list = Optional.ofNullable(CacheUtils.get(BusinessConstant.DRC_HEART_BEAT_SN))
|
List<String> list = Optional.ofNullable(CacheUtils.get(BusinessConstant.DRC_HEART_BEAT_SN))
|
||||||
.filter(obj -> obj instanceof List)
|
.filter(obj -> obj instanceof List)
|
||||||
.map(obj -> (List<String>) obj)
|
.map(obj -> (List<String>) obj)
|
||||||
.orElse(Collections.emptyList());
|
.orElse(Collections.emptyList());
|
||||||
if (CollUtil.isNotEmpty(list)) {
|
if (CollUtil.isNotEmpty(list)) {
|
||||||
list.remove(dockSn);
|
list.remove(dockSn);
|
||||||
}
|
}
|
||||||
|
|
@ -87,9 +93,9 @@ public class OsdHandler implements MessageHandler {
|
||||||
String latitude = data.getStr("latitude");
|
String latitude = data.getStr("latitude");
|
||||||
String longitude = data.getStr("longitude");
|
String longitude = data.getStr("longitude");
|
||||||
if (latitude != null && longitude != null && !GPS_ZERO.equals(latitude) && !GPS_ZERO.equals(
|
if (latitude != null && longitude != null && !GPS_ZERO.equals(latitude) && !GPS_ZERO.equals(
|
||||||
longitude)) {
|
longitude)) {
|
||||||
String payload_index = data.getJSONArray("cameras") != null ?
|
String payload_index = data.getJSONArray("cameras") != null ?
|
||||||
data.getJSONArray("cameras").getJSONObject(0).getStr("payload_index") : null;
|
data.getJSONArray("cameras").getJSONObject(0).getStr("payload_index") : null;
|
||||||
//获取电池电量,如果单电池则把 a赋值给b
|
//获取电池电量,如果单电池则把 a赋值给b
|
||||||
int capacity_percent_a;
|
int capacity_percent_a;
|
||||||
int capacity_percent_b;
|
int capacity_percent_b;
|
||||||
|
|
@ -102,53 +108,160 @@ public class OsdHandler implements MessageHandler {
|
||||||
}
|
}
|
||||||
|
|
||||||
UavReport uavReport = UavReport.builder()
|
UavReport uavReport = UavReport.builder()
|
||||||
.dockSn(dockSn)
|
.dockSn(dockSn)
|
||||||
.obstacle_avoidance_horizon(data.getJSONObject("obstacle_avoidance").getInt("horizon"))
|
.obstacle_avoidance_horizon(data.getJSONObject("obstacle_avoidance").getInt("horizon"))
|
||||||
.obstacle_avoidance_upside(data.getJSONObject("obstacle_avoidance").getInt("upside"))
|
.obstacle_avoidance_upside(data.getJSONObject("obstacle_avoidance").getInt("upside"))
|
||||||
.obstacle_avoidance_downside(data.getJSONObject("obstacle_avoidance").getInt("downside"))
|
.obstacle_avoidance_downside(data.getJSONObject("obstacle_avoidance").getInt("downside"))
|
||||||
.is_near_area_limit(data.getInt("is_near_area_limit"))
|
.is_near_area_limit(data.getInt("is_near_area_limit"))
|
||||||
.is_near_height_limit(data.getInt("is_near_height_limit"))
|
.is_near_height_limit(data.getInt("is_near_height_limit"))
|
||||||
.payload_index(payload_index)
|
.payload_index(payload_index)
|
||||||
.gimbal_pitch(
|
.gimbal_pitch(
|
||||||
payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_pitch") : null)
|
payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_pitch") : null)
|
||||||
.gimbal_roll(
|
.gimbal_roll(
|
||||||
payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_roll") : null)
|
payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_roll") : null)
|
||||||
.gimbal_yaw(
|
.gimbal_yaw(
|
||||||
payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_yaw") : null)
|
payload_index != null ? data.getJSONObject(payload_index).getDouble("gimbal_yaw") : null)
|
||||||
.zoom_factor(
|
.zoom_factor(
|
||||||
payload_index != null ? data.getJSONObject(payload_index).getDouble("zoom_factor") : null)
|
payload_index != null ? data.getJSONObject(payload_index).getDouble("zoom_factor") : null)
|
||||||
.track_id(data.getStr("track_id"))
|
.track_id(data.getStr("track_id"))
|
||||||
.position_state_is_fixed(data.getJSONObject("position_state").getInt("is_fixed"))
|
.position_state_is_fixed(data.getJSONObject("position_state").getInt("is_fixed"))
|
||||||
.position_state_is_quality(data.getJSONObject("position_state").getInt("quality"))
|
.position_state_is_quality(data.getJSONObject("position_state").getInt("quality"))
|
||||||
.position_state_is_gps_number(data.getJSONObject("position_state").getInt("gps_number"))
|
.position_state_is_gps_number(data.getJSONObject("position_state").getInt("gps_number"))
|
||||||
.position_state_is_rtk_number(data.getJSONObject("position_state").getInt("rtk_number"))
|
.position_state_is_rtk_number(data.getJSONObject("position_state").getInt("rtk_number"))
|
||||||
.battery_capacity_percent(data.getJSONObject("battery").getInt("capacity_percent"))
|
.battery_capacity_percent(data.getJSONObject("battery").getInt("capacity_percent"))
|
||||||
.battery_remain_flight_time(data.getJSONObject("battery").getInt("remain_flight_time"))
|
.battery_remain_flight_time(data.getJSONObject("battery").getInt("remain_flight_time"))
|
||||||
.battery_return_home_power(data.getJSONObject("battery").getInt("return_home_power"))
|
.battery_return_home_power(data.getJSONObject("battery").getInt("return_home_power"))
|
||||||
.battery_landing_power(data.getJSONObject("battery").getInt("landing_power"))
|
.battery_landing_power(data.getJSONObject("battery").getInt("landing_power"))
|
||||||
.battery_capacity_percent_a(capacity_percent_a)
|
.battery_capacity_percent_a(capacity_percent_a)
|
||||||
.battery_capacity_percent_b(capacity_percent_b)
|
.battery_capacity_percent_b(capacity_percent_b)
|
||||||
.wind_direction(data.getInt("wind_direction"))
|
.wind_direction(data.getInt("wind_direction"))
|
||||||
.wind_speed(data.getDouble("wind_speed"))
|
.wind_speed(data.getDouble("wind_speed"))
|
||||||
.home_distance(data.getDouble("home_distance"))
|
.home_distance(data.getDouble("home_distance"))
|
||||||
//state上报
|
//state上报
|
||||||
// .home_latitude(data.getDouble("home_latitude"))
|
// .home_latitude(data.getDouble("home_latitude"))
|
||||||
// .home_longitude(data.getDouble("home_longitude"))
|
// .home_longitude(data.getDouble("home_longitude"))
|
||||||
.attitude_head(data.getInt("attitude_head"))
|
.attitude_head(data.getInt("attitude_head"))
|
||||||
.attitude_roll(data.getDouble("attitude_roll"))
|
.attitude_roll(data.getDouble("attitude_roll"))
|
||||||
.attitude_pitch(data.getDouble("attitude_pitch"))
|
.attitude_pitch(data.getDouble("attitude_pitch"))
|
||||||
.elevation(data.getDouble("elevation"))
|
.elevation(data.getDouble("elevation"))
|
||||||
.height(data.getDouble("height"))
|
.height(data.getDouble("height"))
|
||||||
.latitude(data.getDouble("latitude"))
|
.latitude(data.getDouble("latitude"))
|
||||||
.longitude(data.getDouble("longitude"))
|
.longitude(data.getDouble("longitude"))
|
||||||
.vertical_speed(data.getDouble("vertical_speed"))
|
.vertical_speed(data.getDouble("vertical_speed"))
|
||||||
.horizontal_speed(data.getDouble("horizontal_speed"))
|
.horizontal_speed(data.getDouble("horizontal_speed"))
|
||||||
.build();
|
.build();
|
||||||
influxService.addRecord(uavReport);
|
influxService.addRecord(uavReport);
|
||||||
|
|
||||||
|
//禁飞区校验
|
||||||
|
Double height = data.getDouble("height");
|
||||||
|
NoflyZoneDTO.point point = new NoflyZoneDTO.point(uavReport.getLongitude(), uavReport.getLatitude(), height);
|
||||||
|
judgingNoFlyZone(dockSn, point, mode);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log.debug("osd --> payload解析失败,解析后为null");
|
log.debug("osd --> payload解析失败,解析后为null");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//禁飞区限制
|
||||||
|
// 允许触发返航的飞行模式集合
|
||||||
|
//"3":"手动飞行","4":"自动起飞","5":"航线飞行","16":"虚拟摇杆状态","17":"指令飞行"
|
||||||
|
private static final Set<Integer> ALLOWED_MODE_CODES = Set.of(3, 4, 5, 16, 17);
|
||||||
|
// 按设备隔离的计数器(线程安全)
|
||||||
|
private final ConcurrentHashMap<String, AtomicInteger> counterMap = new ConcurrentHashMap<>();
|
||||||
|
// 单线程执行器(若需提高并发,可调整线程数或使用同步)
|
||||||
|
private final ExecutorService executor = new ThreadPoolExecutor(1, 1, 0L,
|
||||||
|
TimeUnit.MILLISECONDS, new ArrayBlockingQueue<>(100));
|
||||||
|
|
||||||
|
private void judgingNoFlyZone(String dockSn, NoflyZoneDTO.point point, Integer modeCode) {
|
||||||
|
// 1. 模式过滤(快速失败)
|
||||||
|
if (!ALLOWED_MODE_CODES.contains(modeCode)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 2. 按设备自增计数器,判断是否需要校验(每3次上报校验一次)
|
||||||
|
AtomicInteger deviceCounter = counterMap.computeIfAbsent(dockSn, k -> new AtomicInteger(0));
|
||||||
|
int count = deviceCounter.incrementAndGet();
|
||||||
|
if (count % 3 != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 3. 获取禁飞区列表
|
||||||
|
Object obj = CacheUtils.get(BusinessConstant.DOCK_NOFLY_ZONE + dockSn);
|
||||||
|
if (!(obj instanceof List)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<NoflyZoneDTO> noFlyZoneList = (List<NoflyZoneDTO>) obj;
|
||||||
|
// 4. 遍历禁飞区,检查是否已触发返航
|
||||||
|
String triggerKey = BusinessConstant.DOCK_NOFLY_ZONE_TRIGGER_SIGN + dockSn;
|
||||||
|
for (NoflyZoneDTO dto : noFlyZoneList) {
|
||||||
|
// 先判断是否已在触发中(快速路径)
|
||||||
|
if (CacheUtils.get(triggerKey) != null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 执行点是否在禁飞区内
|
||||||
|
if (noflyZoneService.isInNoFlyZone(dto.getExtent(), point)) {
|
||||||
|
// 原子设置触发标记,防止并发重复触发
|
||||||
|
if (trySetTrigger(triggerKey)) {
|
||||||
|
// 异步执行返航任务
|
||||||
|
CompletableFuture.runAsync(() -> executeReturnHome(dockSn, dto), executor);
|
||||||
|
}
|
||||||
|
// 只要命中一个禁飞区就停止遍历
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 原子设置触发标记(使用缓存框架的 putIfAbsent 或本地锁)
|
||||||
|
* 返回 true 表示当前线程成功设置,false 表示已被其他线程设置
|
||||||
|
*/
|
||||||
|
private boolean trySetTrigger(String key) {
|
||||||
|
synchronized (this) {
|
||||||
|
if (CacheUtils.get(key) == null) {
|
||||||
|
CacheUtils.set(key, true, 1000 * 60);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 执行返航并推送状态(抽离重复逻辑)
|
||||||
|
*/
|
||||||
|
private void executeReturnHome(String dockSn, NoflyZoneDTO dto) {
|
||||||
|
String zoneName = dto.getName();
|
||||||
|
// 1. 发送进入禁飞区通知(type=0)
|
||||||
|
logAndPush(dockSn, zoneName, 0, "飞机进入禁飞区,强制返航");
|
||||||
|
|
||||||
|
try {
|
||||||
|
// 2. 执行返航指令
|
||||||
|
djiBaseService.executeAndReturnResult(dockSn, "return_home");
|
||||||
|
// 3. 发送成功通知(type=1)
|
||||||
|
logAndPush(dockSn, zoneName, 1, "飞机进入禁飞区,强制返航成功");
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 记录异常堆栈,便于排查
|
||||||
|
log.error("返航失败,dockSn={}, zone={}", dockSn, zoneName, e);
|
||||||
|
// 4. 发送失败通知(type=2)
|
||||||
|
logAndPush(dockSn, zoneName, 2, "飞机进入禁飞区,强制返航失败,请手动返航");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一记录飞行日志并推送 MQTT 消息
|
||||||
|
*/
|
||||||
|
private void logAndPush(String dockSn, String zoneName, int type, String msg) {
|
||||||
|
// 记录 InfluxDB 日志
|
||||||
|
FlightLog flightLog = new FlightLog();
|
||||||
|
flightLog.setDockSn(dockSn);
|
||||||
|
flightLog.setLevel(2);
|
||||||
|
flightLog.setMessage(msg);
|
||||||
|
influxService.addRecord(flightLog);
|
||||||
|
|
||||||
|
// 推送 MQTT 事件
|
||||||
|
JSONObject data = new JSONObject();
|
||||||
|
data.set("name", zoneName);
|
||||||
|
data.set("type", type);
|
||||||
|
data.set("msg", msg);
|
||||||
|
JSONObject payload = djiBaseService.getPayload(BusinessConstant.NOFLY_ZONE_METHOD, data);
|
||||||
|
mqttPushService.pushMessageByClient1(BusinessConstant.WEB_EVENT_TOPIC.formatted(dockSn), payload.toString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.multictrl.modules.business.service;
|
||||||
|
|
||||||
|
import com.multictrl.common.page.PageData;
|
||||||
|
import com.multictrl.common.service.CrudService;
|
||||||
|
import com.multictrl.modules.business.dto.NoflyZoneDTO;
|
||||||
|
import com.multictrl.modules.business.entity.NoflyZoneEntity;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁飞区
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-09
|
||||||
|
*/
|
||||||
|
public interface NoflyZoneService extends CrudService<NoflyZoneEntity, NoflyZoneDTO> {
|
||||||
|
|
||||||
|
//分页列表
|
||||||
|
PageData<NoflyZoneDTO> pageList(Map<String, Object> params);
|
||||||
|
|
||||||
|
//新增禁飞区
|
||||||
|
void saveNoFlying(NoflyZoneDTO noflyZone);
|
||||||
|
|
||||||
|
//修改禁飞区
|
||||||
|
void updateNoFlying(NoflyZoneDTO noflyZone);
|
||||||
|
|
||||||
|
//获取机库禁飞区
|
||||||
|
List<NoflyZoneDTO> getNoFlyZoneByDockSn(String dockSn);
|
||||||
|
|
||||||
|
//判断是否在禁飞区内
|
||||||
|
Boolean isInNoFlyZone(List<List<NoflyZoneDTO.point>> noFlyZone, NoflyZoneDTO.point point);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,253 @@
|
||||||
|
package com.multictrl.modules.business.service.impl;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||||
|
import com.multictrl.common.constant.BusinessConstant;
|
||||||
|
import com.multictrl.common.exception.RenException;
|
||||||
|
import com.multictrl.common.page.PageData;
|
||||||
|
import com.multictrl.common.service.impl.CrudServiceImpl;
|
||||||
|
import com.multictrl.common.utils.CacheUtils;
|
||||||
|
import com.multictrl.modules.business.dao.NoflyZoneDao;
|
||||||
|
import com.multictrl.modules.business.dto.NoflyZoneDTO;
|
||||||
|
import com.multictrl.modules.business.entity.DockEntity;
|
||||||
|
import com.multictrl.modules.business.entity.NoflyZoneEntity;
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import com.multictrl.modules.business.service.DockService;
|
||||||
|
import com.multictrl.modules.business.service.NoflyZoneService;
|
||||||
|
import com.multictrl.modules.sys.entity.SysDeptEntity;
|
||||||
|
import com.multictrl.modules.sys.service.SysDeptService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 禁飞区
|
||||||
|
*
|
||||||
|
* @author Sdy
|
||||||
|
* @since 1.0.0 2026-06-09
|
||||||
|
*/
|
||||||
|
@Service
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class NoflyZoneServiceImpl extends CrudServiceImpl<NoflyZoneDao, NoflyZoneEntity, NoflyZoneDTO> implements NoflyZoneService {
|
||||||
|
private final DockService dockService;
|
||||||
|
private final SysDeptService deptService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public QueryWrapper<NoflyZoneEntity> getWrapper(Map<String, Object> params) {
|
||||||
|
String name = (String) params.get("f.name");
|
||||||
|
|
||||||
|
QueryWrapper<NoflyZoneEntity> wrapper = new QueryWrapper<>();
|
||||||
|
wrapper.like(StrUtil.isNotBlank(name), "f.name", name);
|
||||||
|
wrapper.orderByDesc("f.create_date");
|
||||||
|
|
||||||
|
return wrapper;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public PageData<NoflyZoneDTO> pageList(Map<String, Object> params) {
|
||||||
|
IPage<NoflyZoneDTO> page = baseDao.pageList(getPage(params, null, false), getWrapper(params));
|
||||||
|
for (NoflyZoneDTO record : page.getRecords()) {
|
||||||
|
String extentWkt = record.getExtentWkt();
|
||||||
|
List<List<NoflyZoneDTO.point>> lists = parseMultipolygonZ(extentWkt);
|
||||||
|
record.setExtent(lists);
|
||||||
|
}
|
||||||
|
return getPageData(page, currentDtoClass());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void saveNoFlying(NoflyZoneDTO noflyZone) {
|
||||||
|
NoflyZoneEntity entity = new NoflyZoneEntity();
|
||||||
|
entity.setName(noflyZone.getName());
|
||||||
|
entity.setStatus(noflyZone.getStatus());
|
||||||
|
StringBuilder extent = new StringBuilder("'MULTIPOLYGON Z (");
|
||||||
|
List<List<NoflyZoneDTO.point>> lists = noflyZone.getExtent();
|
||||||
|
for (List<NoflyZoneDTO.point> list : lists) {
|
||||||
|
if (list.size() < 3) {
|
||||||
|
throw new RenException("无效的面");
|
||||||
|
}
|
||||||
|
NoflyZoneDTO.point first = list.get(0);
|
||||||
|
StringBuilder sb = new StringBuilder("((");
|
||||||
|
for (NoflyZoneDTO.point point : list) {
|
||||||
|
sb.append(point.getLng()).append(" ").append(point.getLat()).append(" ").append(point.getHeight()).append(",");
|
||||||
|
}
|
||||||
|
sb.append(first.getLng()).append(" ").append(first.getLat()).append(" ").append(first.getHeight()).append("))");
|
||||||
|
extent.append(sb).append(",");
|
||||||
|
}
|
||||||
|
extent.deleteCharAt(extent.length() - 1);
|
||||||
|
extent.append(")'");
|
||||||
|
entity.setExtent(extent.toString());
|
||||||
|
baseDao.saveNoFlyZone(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateNoFlying(NoflyZoneDTO noflyZone) {
|
||||||
|
update(null, new UpdateWrapper<NoflyZoneEntity>()
|
||||||
|
.eq("id", noflyZone.getId())
|
||||||
|
.set(StringUtils.isNotBlank(noflyZone.getStatus()), "status", noflyZone.getStatus())
|
||||||
|
.set(StringUtils.isNotBlank(noflyZone.getName()), "name", noflyZone.getName()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<NoflyZoneDTO> getNoFlyZoneByDockSn(String dockSn) {
|
||||||
|
DockEntity dockEntity = dockService.getDao().selectOne(new QueryWrapper<DockEntity>().eq("dock_sn", dockSn));
|
||||||
|
if (dockEntity == null) {
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
SysDeptEntity deptEntity = deptService.selectById(dockEntity.getDeptId());
|
||||||
|
List<Long> deptIds = new ArrayList<>();
|
||||||
|
deptIds.add(dockEntity.getDeptId());
|
||||||
|
if (StringUtils.isNotBlank(deptEntity.getPids())) {
|
||||||
|
Arrays.stream(deptEntity.getPids().split(","))
|
||||||
|
.filter(StringUtils::isNotBlank)
|
||||||
|
.map(Long::parseLong)
|
||||||
|
.forEach(deptIds::add);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<NoflyZoneDTO> list = baseDao.getNoFlyZoneList(new QueryWrapper<NoflyZoneEntity>()
|
||||||
|
.eq("f.status", "1").and(v ->
|
||||||
|
v.in("f.dept_id", deptIds).or().isNull("f.dept_id")));
|
||||||
|
|
||||||
|
list.forEach(dto -> dto.setExtent(parseMultipolygonZ(dto.getExtentWkt())));
|
||||||
|
|
||||||
|
CacheUtils.set(BusinessConstant.DOCK_NOFLY_ZONE + dockSn, list);
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean isInNoFlyZone(List<List<NoflyZoneDTO.point>> noFlyZone, NoflyZoneDTO.point point) {
|
||||||
|
if (noFlyZone.size() != 2 || noFlyZone.get(0).size() < 3 || noFlyZone.get(1).size() < 3) {
|
||||||
|
throw new IllegalArgumentException("立方体必须由两个多边形面构成,每个面至少3个点");
|
||||||
|
}
|
||||||
|
|
||||||
|
List<NoflyZoneDTO.point> bottomFace = noFlyZone.get(0);
|
||||||
|
List<NoflyZoneDTO.point> topFace = noFlyZone.get(1);
|
||||||
|
|
||||||
|
// 检查高度是否在立方体范围内
|
||||||
|
double minHeight = Math.min(bottomFace.get(0).getHeight(), topFace.get(0).getHeight());
|
||||||
|
double maxHeight = Math.max(bottomFace.get(0).getHeight(), topFace.get(0).getHeight());
|
||||||
|
|
||||||
|
if (point.getHeight() < minHeight || point.getHeight() > maxHeight) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查点是否在底面多边形内
|
||||||
|
boolean inBottomFace = isPointInPolygon(bottomFace, point);
|
||||||
|
|
||||||
|
// 检查点是否在顶面多边形内
|
||||||
|
boolean inTopFace = isPointInPolygon(topFace, point);
|
||||||
|
|
||||||
|
// 如果点在底面或顶面多边形内,则它在立方体内
|
||||||
|
return inBottomFace || inTopFace;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析MULTIPOLYGON Z字符串
|
||||||
|
*
|
||||||
|
* @param multipolygonZ MULTIPOLYGON Z格式的字符串
|
||||||
|
* @return 解析后的范围数据
|
||||||
|
*/
|
||||||
|
private List<List<NoflyZoneDTO.point>> parseMultipolygonZ(String multipolygonZ) {
|
||||||
|
List<List<NoflyZoneDTO.point>> result = new ArrayList<>();
|
||||||
|
|
||||||
|
// 使用正则表达式匹配多边形数据
|
||||||
|
Pattern pattern = Pattern.compile("\\(\\(([^)]+)\\)\\)");
|
||||||
|
Matcher matcher = pattern.matcher(multipolygonZ);
|
||||||
|
|
||||||
|
while (matcher.find()) {
|
||||||
|
String polygonData = matcher.group(1);
|
||||||
|
List<NoflyZoneDTO.point> polygon = parsePolygon(polygonData);
|
||||||
|
result.add(polygon);
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析单个多边形数据
|
||||||
|
*
|
||||||
|
* @param polygonData 多边形数据字符串
|
||||||
|
* @return 多边形点列表
|
||||||
|
*/
|
||||||
|
private List<NoflyZoneDTO.point> parsePolygon(String polygonData) {
|
||||||
|
List<NoflyZoneDTO.point> points = new ArrayList<>();
|
||||||
|
String[] coordinates = polygonData.split(",");
|
||||||
|
|
||||||
|
for (String coord : coordinates) {
|
||||||
|
NoflyZoneDTO.point point = parseCoordinate(coord.trim());
|
||||||
|
if (point != null) {
|
||||||
|
points.add(point);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 去除最后一个点(如果它与第一个点相同,WKT格式多边形首尾闭合)
|
||||||
|
if (points.size() > 1) {
|
||||||
|
NoflyZoneDTO.point first = points.get(0);
|
||||||
|
NoflyZoneDTO.point last = points.get(points.size() - 1);
|
||||||
|
if (first.getLng().equals(last.getLng())
|
||||||
|
&& first.getLat().equals(last.getLat())
|
||||||
|
&& first.getHeight().equals(last.getHeight())) {
|
||||||
|
points.remove(points.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return points;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解析单个坐标点
|
||||||
|
*
|
||||||
|
* @param coordinate 坐标字符串
|
||||||
|
* @return 点对象,解析失败返回null
|
||||||
|
*/
|
||||||
|
private NoflyZoneDTO.point parseCoordinate(String coordinate) {
|
||||||
|
// 使用正则表达式匹配三个浮点数
|
||||||
|
Pattern pattern = Pattern.compile("([\\d.]+)\\s+([\\d.]+)\\s+([\\d.]+)");
|
||||||
|
Matcher matcher = pattern.matcher(coordinate);
|
||||||
|
if (matcher.find()) {
|
||||||
|
return new NoflyZoneDTO.point(
|
||||||
|
Double.parseDouble(matcher.group(1)),
|
||||||
|
Double.parseDouble(matcher.group(2)),
|
||||||
|
Double.parseDouble(matcher.group(3))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 判断点是否在多边形内(射线法 Ray Casting)
|
||||||
|
* <p>
|
||||||
|
* 将3D多边形投影到2D平面(经纬度),忽略高度,
|
||||||
|
* 使用射线法判断点是否落在多边形内部。
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param polygon 多边形顶点列表
|
||||||
|
* @param point 要检查的点
|
||||||
|
* @return 如果点在多边形内返回true,否则返回false
|
||||||
|
*/
|
||||||
|
private boolean isPointInPolygon(List<NoflyZoneDTO.point> polygon, NoflyZoneDTO.point point) {
|
||||||
|
int n = polygon.size();
|
||||||
|
if (n < 3) return false;
|
||||||
|
|
||||||
|
double px = point.getLng();
|
||||||
|
double py = point.getLat();
|
||||||
|
boolean inside = false;
|
||||||
|
|
||||||
|
for (int i = 0, j = n - 1; i < n; j = i++) {
|
||||||
|
double xi = polygon.get(i).getLng(), yi = polygon.get(i).getLat();
|
||||||
|
double xj = polygon.get(j).getLng(), yj = polygon.get(j).getLat();
|
||||||
|
|
||||||
|
if (((yi > py) != (yj > py)) &&
|
||||||
|
(px < (xj - xi) * (py - yi) / (yj - yi) + xi)) {
|
||||||
|
inside = !inside;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return inside;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
<?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.multictrl.modules.business.dao.NoflyZoneDao">
|
||||||
|
<resultMap type="com.multictrl.modules.business.entity.NoflyZoneEntity" id="busNoflyZoneMap">
|
||||||
|
<result property="id" column="id"/>
|
||||||
|
<result property="name" column="name"/>
|
||||||
|
<result property="status" column="status"/>
|
||||||
|
<result property="extent" column="extent"/>
|
||||||
|
<result property="deptId" column="dept_id"/>
|
||||||
|
<result property="creator" column="creator"/>
|
||||||
|
<result property="createDate" column="create_date"/>
|
||||||
|
</resultMap>
|
||||||
|
|
||||||
|
<select id="pageList" resultType="com.multictrl.modules.business.dto.NoflyZoneDTO">
|
||||||
|
SELECT
|
||||||
|
f.id,
|
||||||
|
f."name",
|
||||||
|
ST_AsText(f.extent) AS extent_wkt,
|
||||||
|
f.create_date,
|
||||||
|
u.real_name user_name,
|
||||||
|
d.name dept_name,
|
||||||
|
f.status
|
||||||
|
FROM bus_nofly_zone f
|
||||||
|
left join sys_user u on f.creator = u.id
|
||||||
|
left join sys_dept d on f.dept_id = d.id
|
||||||
|
${ew.customSqlSegment}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="saveNoFlyZone">
|
||||||
|
INSERT INTO bus_nofly_zone (id, name, extent, dept_id, creator, create_date, status)
|
||||||
|
VALUES (#{id}, #{name}, ST_GeomFromText(${extent}, 4326), #{deptId}, #{creator}, #{createDate}, #{status})
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<select id="getNoFlyZoneList" resultType="com.multictrl.modules.business.dto.NoflyZoneDTO">
|
||||||
|
SELECT f.id,
|
||||||
|
f."name",
|
||||||
|
ST_AsText(f.extent) AS extent_wkt,
|
||||||
|
f.create_date,
|
||||||
|
u.real_name user_name,
|
||||||
|
d.name dept_name,
|
||||||
|
f.status
|
||||||
|
FROM bus_nofly_zone f
|
||||||
|
left join sys_user u on f.creator = u.id
|
||||||
|
left join sys_dept d on f.dept_id = d.id
|
||||||
|
${ew.customSqlSegment}
|
||||||
|
</select>
|
||||||
|
</mapper>
|
||||||
|
|
@ -2264,3 +2264,34 @@ VALUES (2063906540177379330, 2063906301022359553, '妙算', 'MIAO_SUAN', '', 1,
|
||||||
'2026-06-08 16:50:39.364', 1067246875800000001, '2026-06-08 16:52:08.349',
|
'2026-06-08 16:50:39.364', 1067246875800000001, '2026-06-08 16:52:08.349',
|
||||||
'source-material/miao_suan.png');
|
'source-material/miao_suan.png');
|
||||||
|
|
||||||
|
CREATE
|
||||||
|
EXTENSION IF NOT EXISTS postgis;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS "public"."bus_nofly_zone";
|
||||||
|
CREATE TABLE "public"."bus_nofly_zone"
|
||||||
|
(
|
||||||
|
"id" int8 NOT NULL,
|
||||||
|
"name" varchar(255) COLLATE "pg_catalog"."default" NOT NULL,
|
||||||
|
"status" char(1) COLLATE "pg_catalog"."default",
|
||||||
|
"extent" "public"."geography" NOT NULL,
|
||||||
|
"dept_id" int8,
|
||||||
|
"creator" int8,
|
||||||
|
"create_date" timestamp(6)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_nofly_zone"."extent" IS '范围';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_nofly_zone"."dept_id" IS '部门标识';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_nofly_zone"."name" IS '名称';
|
||||||
|
COMMENT
|
||||||
|
ON COLUMN "public"."bus_nofly_zone"."status" IS '是否开启 1开启 0未开启';
|
||||||
|
COMMENT
|
||||||
|
ON TABLE "public"."bus_nofly_zone" IS '禁飞区';
|
||||||
|
|
||||||
|
-- ----------------------------
|
||||||
|
-- Primary Key structure for table bus_nofly_zone
|
||||||
|
-- ----------------------------
|
||||||
|
ALTER TABLE "public"."bus_nofly_zone"
|
||||||
|
ADD CONSTRAINT "uav_no_flying_pkey" PRIMARY KEY ("id");
|
||||||
Loading…
Reference in New Issue