diff --git a/.gitignore b/.gitignore index 28f7412..55c1137 100644 --- a/.gitignore +++ b/.gitignore @@ -37,3 +37,4 @@ buildNumber.properties # https://github.com/takari/maven-wrapper#usage-without-binary-jar .mvn/wrapper/maven-wrapper.jar +.idea/ diff --git a/common/pom.xml b/common/pom.xml index da33fe6..bf993ba 100644 --- a/common/pom.xml +++ b/common/pom.xml @@ -96,6 +96,12 @@ jakarta.servlet jakarta.servlet-api + + com.google.code.gson + gson + 2.10.1 + + \ No newline at end of file diff --git a/common/src/main/java/com/jiagutech/ams/model/DeptItem.java b/common/src/main/java/com/jiagutech/ams/model/DeptItem.java index cd10bd3..665907b 100644 --- a/common/src/main/java/com/jiagutech/ams/model/DeptItem.java +++ b/common/src/main/java/com/jiagutech/ams/model/DeptItem.java @@ -14,8 +14,9 @@ import lombok.Data; @Data public class DeptItem { @JsonSerialize(using = ToStringSerializer.class) - private String deptId; + private Long deptId; private String deptName; + @JsonSerialize(using = ToStringSerializer.class) private Long managerId; private String managerName; private String managerPhone; diff --git a/common/src/main/java/com/jiagutech/ams/model/LoginUser.java b/common/src/main/java/com/jiagutech/ams/model/LoginUser.java index 528421d..ae7770c 100644 --- a/common/src/main/java/com/jiagutech/ams/model/LoginUser.java +++ b/common/src/main/java/com/jiagutech/ams/model/LoginUser.java @@ -1,6 +1,8 @@ package com.jiagutech.ams.model; import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import com.jiagutech.ams.model.dto.DeptDTO; import com.jiagutech.ams.model.dto.RoleDTO; import lombok.Data; @@ -28,6 +30,7 @@ public class LoginUser implements Serializable { /** * 用户ID */ + @JsonSerialize(using = ToStringSerializer.class) private Long userId; /** diff --git a/common/src/main/java/com/jiagutech/ams/model/common/PageResult.java b/common/src/main/java/com/jiagutech/ams/model/common/PageResult.java index 699875e..26172b3 100644 --- a/common/src/main/java/com/jiagutech/ams/model/common/PageResult.java +++ b/common/src/main/java/com/jiagutech/ams/model/common/PageResult.java @@ -26,7 +26,7 @@ public class PageResult { pageResult.setTotal(total); pageResult.setPageSize(pageSize); pageResult.setPageNum(pageNum); - pageResult.setPages(total % pageSize == 0 ? total / pageSize : total / pageSize + 1); + pageResult.setPages(total==0||pageSize==0?0:total % pageSize == 0 ? total / pageSize : total / pageSize + 1); pageResult.setRecords(records); return pageResult; } diff --git a/common/src/main/java/com/jiagutech/ams/model/dto/DeptDTO.java b/common/src/main/java/com/jiagutech/ams/model/dto/DeptDTO.java index 1401435..1ba0159 100644 --- a/common/src/main/java/com/jiagutech/ams/model/dto/DeptDTO.java +++ b/common/src/main/java/com/jiagutech/ams/model/dto/DeptDTO.java @@ -1,6 +1,8 @@ package com.jiagutech.ams.model.dto; import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; import java.io.Serializable; @@ -16,7 +18,7 @@ import java.io.Serializable; @TableName("ams_dept") public class DeptDTO implements Serializable { private static final long serialVersionUID = 1L; - + @JsonSerialize(using = ToStringSerializer.class) private Long id; private String name; } diff --git a/common/src/main/java/com/jiagutech/ams/model/dto/RoleDTO.java b/common/src/main/java/com/jiagutech/ams/model/dto/RoleDTO.java index 0d0a160..f797021 100644 --- a/common/src/main/java/com/jiagutech/ams/model/dto/RoleDTO.java +++ b/common/src/main/java/com/jiagutech/ams/model/dto/RoleDTO.java @@ -2,6 +2,8 @@ package com.jiagutech.ams.model.dto; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; import lombok.Data; import java.io.Serializable; @@ -18,6 +20,7 @@ import java.io.Serializable; public class RoleDTO implements Serializable { private static final long serialVersionUID = 1L; @TableId + @JsonSerialize(using = ToStringSerializer.class) private Long id; private String name; diff --git a/common/src/main/java/com/jiagutech/ams/model/dto/UserDTO.java b/common/src/main/java/com/jiagutech/ams/model/dto/UserDTO.java index e6b7518..e744c10 100644 --- a/common/src/main/java/com/jiagutech/ams/model/dto/UserDTO.java +++ b/common/src/main/java/com/jiagutech/ams/model/dto/UserDTO.java @@ -24,5 +24,6 @@ public class UserDTO { private Integer delFlag = 0; private Long regionCode; private String regionPath; + private String regionName; } \ No newline at end of file diff --git a/pom.xml b/pom.xml index 25dbbbd..91416b8 100644 --- a/pom.xml +++ b/pom.xml @@ -55,6 +55,13 @@ true + + zyg + + zyg + info + + prod diff --git a/social/pom.xml b/social/pom.xml index 47f2452..86abdc9 100644 --- a/social/pom.xml +++ b/social/pom.xml @@ -17,27 +17,7 @@ UTF-8 - - - dev - - - dev - info - - - - true - - - - prod - - prod - info - - - + com.jiagutech @@ -83,6 +63,22 @@ org.apache.poi poi-ooxml + + org.springframework.boot + spring-boot-starter-amqp + + + + org.mapstruct + mapstruct + 1.5.5.Final + + + org.mapstruct + mapstruct-processor + 1.5.5.Final + compile + com.alibaba easyexcel @@ -93,5 +89,16 @@ + + org.locationtech.jts + jts-core + 1.18.1 + + + org.locationtech.proj4j + proj4j + 1.1.3 + + \ No newline at end of file diff --git a/social/src/main/java/com/jiagutech/ams/controller/DeviceController.java b/social/src/main/java/com/jiagutech/ams/controller/DeviceController.java index 71c01ee..7f3b308 100644 --- a/social/src/main/java/com/jiagutech/ams/controller/DeviceController.java +++ b/social/src/main/java/com/jiagutech/ams/controller/DeviceController.java @@ -1,16 +1,17 @@ package com.jiagutech.ams.controller; import cn.dev33.satoken.annotation.SaCheckRole; +import com.jiagutech.ams.model.common.PageRequest; +import com.jiagutech.ams.model.common.PageResult; import com.jiagutech.ams.model.common.R; +import com.jiagutech.ams.model.dto.DeviceDTO; +import com.jiagutech.ams.model.request.JobPageRequest; import com.jiagutech.ams.model.response.DeviceInfo; import com.jiagutech.ams.service.DeviceService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import lombok.RequiredArgsConstructor; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RequestParam; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; import java.util.List; @@ -39,4 +40,11 @@ public class DeviceController { return R.ok(deviceService.onlineAndRound(maxLng, maxLat, minLng, minLat)); } + + @Operation(summary = "设备列表") + @PostMapping("/page") + @SaCheckRole("manager") + public R> page(@RequestBody PageRequest pageRequest) { + return R.ok(deviceService.page(pageRequest)); + } } diff --git a/social/src/main/java/com/jiagutech/ams/controller/JobController.java b/social/src/main/java/com/jiagutech/ams/controller/JobController.java index 2e71f43..9f6f81d 100644 --- a/social/src/main/java/com/jiagutech/ams/controller/JobController.java +++ b/social/src/main/java/com/jiagutech/ams/controller/JobController.java @@ -3,10 +3,13 @@ package com.jiagutech.ams.controller; import cn.dev33.satoken.annotation.SaCheckRole; import cn.dev33.satoken.annotation.SaMode; import cn.hutool.core.collection.CollectionUtil; +import com.jiagutech.ams.model.TrackImageVO; +import com.jiagutech.ams.model.TrackItem; import com.jiagutech.ams.model.common.PageRequest; import com.jiagutech.ams.model.common.PageResult; import com.jiagutech.ams.model.common.R; import com.jiagutech.ams.model.dto.JobTypeDTO; +import com.jiagutech.ams.model.dto.TrackImageDTO; import com.jiagutech.ams.model.request.JobCreateRequest; import com.jiagutech.ams.model.request.JobPageRequest; import com.jiagutech.ams.model.response.JobCreateResponse; @@ -40,6 +43,7 @@ public class JobController { public R> getJobTypes() { return R.ok(jobService.getJobTypes()); } + @Operation(summary = "创建作业记录") @PostMapping("/start") @SaCheckRole("machinist") @@ -50,13 +54,13 @@ public class JobController { @Operation(summary = "更新作业状态") @SaCheckRole(value = {"machinist", "admin"}, mode = SaMode.OR) @PutMapping("/status") - public R updateJobStatus(@RequestParam("jobId") Long jobId, @RequestParam("status") Integer status) { - jobService.updateJobStatus(jobId, status); + public R updateJobStatus(@RequestParam("jobId") String jobId, @RequestParam("status") Integer status) { + jobService.updateJobStatus(Long.parseLong(jobId), status); return R.ok(); } @Operation(summary = "分页获取作业列表") - @SaCheckRole(value = {"machinist","gov","manager"}, mode = SaMode.OR) + @SaCheckRole(value = {"machinist", "gov", "manager"}, mode = SaMode.OR) @PostMapping("/page") public R> getPages(@RequestBody PageRequest pageRequest) { return R.ok(jobService.getPages(pageRequest)); @@ -72,12 +76,28 @@ public class JobController { @PostMapping("/export") @Operation(summary = "导出作业记录") - public void exportJobs(@RequestBody(required = false) JobPageRequest jobPageRequest, HttpServletResponse response){ + public void exportJobs(@RequestBody(required = false) JobPageRequest jobPageRequest, HttpServletResponse response) { jobService.exportJobs(jobPageRequest, response); } + @PostMapping("/exportByFarmer") @Operation(summary = "导出作业记录") - public void exportByFarmer(@RequestBody(required = false) JobPageRequest jobPageRequest, HttpServletResponse response){ + public void exportByFarmer(@RequestBody(required = false) JobPageRequest jobPageRequest, HttpServletResponse response) { jobService.exportByFarmer(jobPageRequest, response); } + + @GetMapping("/tracks/{jobId}") + @Operation(summary = "获取作业轨迹列表") + public R> getTrackList(@PathVariable("jobId") Long jobId) { + return R.ok(jobService.getTrackList(jobId)); + } + + @Operation(summary = "上传作业图片") + @PostMapping("/jobImage") + public R uploadJobImages(@RequestBody TrackImageVO trackImageVO) { + jobService.saveJobImages(trackImageVO); + return R.ok(); + } + + } diff --git a/social/src/main/java/com/jiagutech/ams/mapper/DeviceMapper.java b/social/src/main/java/com/jiagutech/ams/mapper/DeviceMapper.java index 4da3a85..4db59b3 100644 --- a/social/src/main/java/com/jiagutech/ams/mapper/DeviceMapper.java +++ b/social/src/main/java/com/jiagutech/ams/mapper/DeviceMapper.java @@ -1,10 +1,12 @@ package com.jiagutech.ams.mapper; +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jiagutech.ams.model.dto.DeviceDTO; import com.jiagutech.ams.model.response.DeviceInfo; import java.util.List; -public interface DeviceMapper { +public interface DeviceMapper extends BaseMapper { List queryDeviceList(Long detpId); diff --git a/social/src/main/java/com/jiagutech/ams/mapper/JobMapper.java b/social/src/main/java/com/jiagutech/ams/mapper/JobMapper.java index d25a9fb..d6786fe 100644 --- a/social/src/main/java/com/jiagutech/ams/mapper/JobMapper.java +++ b/social/src/main/java/com/jiagutech/ams/mapper/JobMapper.java @@ -1,6 +1,5 @@ package com.jiagutech.ams.mapper; -import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.mapper.BaseMapper; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; diff --git a/social/src/main/java/com/jiagutech/ams/mapper/SortieMapper.java b/social/src/main/java/com/jiagutech/ams/mapper/SortieMapper.java new file mode 100644 index 0000000..d7c3263 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/mapper/SortieMapper.java @@ -0,0 +1,8 @@ +package com.jiagutech.ams.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jiagutech.ams.model.dto.SortieDTO; + +public interface SortieMapper extends BaseMapper { + +} diff --git a/social/src/main/java/com/jiagutech/ams/mapper/TrackImageMapper.java b/social/src/main/java/com/jiagutech/ams/mapper/TrackImageMapper.java new file mode 100644 index 0000000..0339df6 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/mapper/TrackImageMapper.java @@ -0,0 +1,7 @@ +package com.jiagutech.ams.mapper; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.jiagutech.ams.model.dto.TrackImageDTO; + +public interface TrackImageMapper extends BaseMapper { +} diff --git a/social/src/main/java/com/jiagutech/ams/model/JobMapping.java b/social/src/main/java/com/jiagutech/ams/model/JobMapping.java index fcc11b8..3e11179 100644 --- a/social/src/main/java/com/jiagutech/ams/model/JobMapping.java +++ b/social/src/main/java/com/jiagutech/ams/model/JobMapping.java @@ -3,9 +3,13 @@ package com.jiagutech.ams.model; import com.jiagutech.ams.model.dto.JobDTO; import com.jiagutech.ams.model.request.JobCreateRequest; import com.jiagutech.ams.model.response.JobCreateResponse; +import com.jiagutech.ams.model.response.JobItem; +import com.jiagutech.ams.model.response.JobPolyItem; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; +import java.util.List; + @Mapper public interface JobMapping { JobMapping INSTANCE = Mappers.getMapper(JobMapping.class); @@ -13,4 +17,8 @@ public interface JobMapping { JobDTO jobCreateToJobDTO(JobCreateRequest job); JobCreateResponse jobDTOToJobCreateResponse(JobDTO job); + + JobPolyItem jobItemToJobPolyItem(JobItem job); + + List jobItemListToJobPolyItemList(List jobList); } diff --git a/social/src/main/java/com/jiagutech/ams/model/Locus.java b/social/src/main/java/com/jiagutech/ams/model/Locus.java new file mode 100644 index 0000000..4ba7cad --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/Locus.java @@ -0,0 +1,32 @@ +package com.jiagutech.ams.model; + +import lombok.Data; + +import java.io.Serializable; + +@Data +public class Locus implements Serializable { + + // 设备Id + private String vehicleId; + // 时间戳 + private Long timestamp; + + private Long recordTime; + // 纬度,最多保留7位小数(CGCS2000 坐标系) + private Double lat; + // 经度,最多保留7位小数(CGCS2000 坐标系) + private Double lng; + // 状态[1位数字](0=不工作,1=工作,3=合格) + private Integer status; + // 幅宽(米)[浮点数,最多保留两位小数] + private Double breadth; + // 速度(千米/小时)[浮点数,最多保留一位小数] + private Double velocity; + // 耕深(厘米)[浮点数,最多保留一位小数] + private Double deep; + // 流量(脉冲值)[浮点数,最多保留一位小数] + private Double flow; + // 播种速度 粒/s生成对应的实体类 + private Double seeding; +} \ No newline at end of file diff --git a/social/src/main/java/com/jiagutech/ams/model/SortieMapping.java b/social/src/main/java/com/jiagutech/ams/model/SortieMapping.java new file mode 100644 index 0000000..920f762 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/SortieMapping.java @@ -0,0 +1,25 @@ +package com.jiagutech.ams.model; + +import com.jiagutech.ams.model.dto.SortieDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface SortieMapping { + SortieMapping INSTANCE = Mappers.getMapper(SortieMapping.class); + + @Mappings( + value = { + @Mapping(target = "workArea", source = "sprayArea"), + @Mapping(target = "latitude", source = "lat0"), + @Mapping(target = "longitude", source = "lng0"), + @Mapping(target = "startAt", source = "startTime"), + @Mapping(target = "endAt", source = "endTime"), + @Mapping(target = "vehicleId", source = "droneId"), + + }) + SortieDTO convertToSortieDTOByUavSortie(UavSortie uavSortie); + +} diff --git a/social/src/main/java/com/jiagutech/ams/model/TrackImageVO.java b/social/src/main/java/com/jiagutech/ams/model/TrackImageVO.java new file mode 100644 index 0000000..00b8955 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/TrackImageVO.java @@ -0,0 +1,30 @@ +package com.jiagutech.ams.model; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @ClassName TrackImageDTO + * @author: zhangyeguang + * @create: 2024-09-09 14:12 + * @Version 1.0 + * @description: + **/ +@Data +public class TrackImageVO { + + private Long id; + + private Long deviceId; + + private Long timestamp; + + private Double lat; + + private Double lng; + + private String vehicleId; + + private String imageUrl; + +} diff --git a/social/src/main/java/com/jiagutech/ams/model/TrackItem.java b/social/src/main/java/com/jiagutech/ams/model/TrackItem.java new file mode 100644 index 0000000..1820674 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/TrackItem.java @@ -0,0 +1,32 @@ +package com.jiagutech.ams.model; + +import lombok.Data; + +/** + * @ClassName TrackItem + * @author: zhangyeguang + * @create: 2024-09-09 12:00 + * @Version 1.0 + * @description: + **/ +@Data +public class TrackItem { + + private Long timestamp; + + private Double lat; + + private Double lng; + + private Float velocity; + + private Float deep; + + private Float flow; + + private Float seeding; + + private String imageUrl; + + +} diff --git a/social/src/main/java/com/jiagutech/ams/model/TrackMapping.java b/social/src/main/java/com/jiagutech/ams/model/TrackMapping.java new file mode 100644 index 0000000..4713eb4 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/TrackMapping.java @@ -0,0 +1,24 @@ +package com.jiagutech.ams.model; + +import com.jiagutech.ams.model.dto.TrackImageDTO; +import org.mapstruct.Mapper; +import org.mapstruct.Mapping; +import org.mapstruct.Mappings; +import org.mapstruct.factory.Mappers; + +@Mapper +public interface TrackMapping { + + TrackMapping INSTANCE = Mappers.getMapper(TrackMapping.class); + + @Mappings(value = { + @Mapping(target = "boxNum", source = "vehicleId"), + @Mapping(target = "ts", source = "timestamp"), + + }) + TrackImageDTO convertToTrackImageDTOByVO(TrackImageVO trackImage); + + + TrackItem convertToTrackItemByLocus(Locus track); + +} diff --git a/social/src/main/java/com/jiagutech/ams/model/UavSortie.java b/social/src/main/java/com/jiagutech/ams/model/UavSortie.java new file mode 100644 index 0000000..ef54e4a --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/UavSortie.java @@ -0,0 +1,68 @@ +package com.jiagutech.ams.model; + + +import lombok.Data; + +@Data +public class UavSortie implements java.io.Serializable { + private static final long serialVersionUID = 1L; + + /** + * 飞机ID + */ + private String droneId; + + + /** + * 起飞时间(毫秒时间戳) + */ + private Long startTime; + + /** + * 降落时间(毫秒时间戳) + */ + private Long endTime; + + /** + * 行政区划分编码(如:江苏省 南京市 浦口区:320111) + */ + private Integer regionCode; + + + private Double lat0; + private Double lng0; + + private Long flightTime; + + /** + * + */ + private Float sprayArea; + + /** + * 喷洒容量 + */ + private Float sprayQuantity; + + // 达标面积(亩) + private Float qualifiedWorkArea; + + // 重复作业面积(亩) + private Float repeatWorkArea; + + // 耕深(厘米) + private Float avgDeep; + + // 合格率 + private Float qualifiedRate; + // 行驶里程(米) + private Float distance; + + // 作业类型,编码见附表1 + private Long module; + // 总流量(单位:L) + private Float sumFlow; + // 总播种量 (单位:粒) + private Integer seedingNumber; + +} diff --git a/social/src/main/java/com/jiagutech/ams/model/dto/SortieDTO.java b/social/src/main/java/com/jiagutech/ams/model/dto/SortieDTO.java new file mode 100644 index 0000000..4e3f760 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/dto/SortieDTO.java @@ -0,0 +1,50 @@ +package com.jiagutech.ams.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @ClassName SoriteDTO + * @author: zhangyeguang + * @create: 2024-09-09 10:02 + * @Version 1.0 + * @description: + **/ +@Data +@TableName("sortie_store") +public class SortieDTO { + + @TableId + private Long Id; + + private Long startAt; + + private Long endAt; + + private String vehicleId; + + private Double longitude; + + private Double latitude; + + private Float workArea; + + private Float RepeatWorkArea; + + private Float qualifiedWorkArea; + + private Float avgDeep; + + private Float qualifiedRate; + + private Float distance; + + private Long module; + + private Float sumFlow; + + private Integer seedingNumber; + +} diff --git a/social/src/main/java/com/jiagutech/ams/model/dto/TrackImageDTO.java b/social/src/main/java/com/jiagutech/ams/model/dto/TrackImageDTO.java new file mode 100644 index 0000000..34887b2 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/dto/TrackImageDTO.java @@ -0,0 +1,31 @@ +package com.jiagutech.ams.model.dto; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +/** + * @ClassName TrackImageDTO + * @author: zhangyeguang + * @create: 2024-09-09 14:12 + * @Version 1.0 + * @description: + **/ +@Data +@TableName("track_image") +public class TrackImageDTO { + + private Long id; + + private Long deviceId; + + private Long ts; + + private Double lat; + + private Double lng; + + private String boxNum; + + private String imageUrl; + +} diff --git a/social/src/main/java/com/jiagutech/ams/model/request/JobCreateRequest.java b/social/src/main/java/com/jiagutech/ams/model/request/JobCreateRequest.java index 5f99215..97e4eeb 100644 --- a/social/src/main/java/com/jiagutech/ams/model/request/JobCreateRequest.java +++ b/social/src/main/java/com/jiagutech/ams/model/request/JobCreateRequest.java @@ -1,5 +1,6 @@ package com.jiagutech.ams.model.request; +import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.NumberDeserializers; import com.jiagutech.ams.utils.StringToLongDeserializer; @@ -31,6 +32,7 @@ public class JobCreateRequest { /** * 区域 */ + @JsonIgnore private long regionCode; /** * 设备ID diff --git a/social/src/main/java/com/jiagutech/ams/model/response/JobItem.java b/social/src/main/java/com/jiagutech/ams/model/response/JobItem.java index e25b67e..4ccd8a5 100644 --- a/social/src/main/java/com/jiagutech/ams/model/response/JobItem.java +++ b/social/src/main/java/com/jiagutech/ams/model/response/JobItem.java @@ -17,15 +17,21 @@ import lombok.Data; public class JobItem { @ExcelIgnore @JsonSerialize(using = ToStringSerializer.class) - private Long jobId; - @ExcelIgnore private Long operatorId; + @ExcelIgnore + @JsonSerialize(using = ToStringSerializer.class) + private Long jobId; @ExcelProperty(value = "机手") private String operatorName; + @ExcelProperty(value = "机手手机号") + private String operatorPhone; @ExcelIgnore + @JsonSerialize(using = ToStringSerializer.class) private Long farmerId; @ExcelProperty(value = "农户") private String farmerName; + @ExcelProperty(value = "农户手机号") + private String farmerPhone; @ExcelIgnore private Long startTime; @ExcelIgnore @@ -44,11 +50,14 @@ public class JobItem { @ExcelProperty(value = "作业类型") private String typeName; @ExcelIgnore + @JsonSerialize(using = ToStringSerializer.class) private Long deviceId; @ExcelIgnore private long deptId; @ExcelProperty(value = "合作社") private String deptName; + @ExcelProperty(value = "作业地区") + private String regionName; } diff --git a/social/src/main/java/com/jiagutech/ams/model/response/JobPolyItem.java b/social/src/main/java/com/jiagutech/ams/model/response/JobPolyItem.java new file mode 100644 index 0000000..26d89ea --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/model/response/JobPolyItem.java @@ -0,0 +1,40 @@ +package com.jiagutech.ams.model.response; + +import com.alibaba.excel.annotation.ExcelIgnore; +import com.alibaba.excel.annotation.ExcelProperty; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; +import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; +import lombok.Data; + +/** + * @ClassName JobItem + * @author: zhangyeguang + * @create: 2024-09-02 15:18 + * @Version 1.0 + * @description: + **/ +@Data +public class JobPolyItem { + + @ExcelProperty(value = "农户") + private String farmerName; + @ExcelProperty(value = "农户手机号") + private String farmerPhone; + + + @ExcelProperty(value = "开始作业时间") + private String startTimeStr; + + @ExcelProperty(value = "作业总面积") + private Float area; + + @ExcelProperty(value = "作业类型") + private String typeName; + + @ExcelProperty(value = "合作社") + private String deptName; + @ExcelProperty(value = "作业地区") + private String regionName; + + +} diff --git a/social/src/main/java/com/jiagutech/ams/rest/CenterRestClient.java b/social/src/main/java/com/jiagutech/ams/rest/CenterRestClient.java deleted file mode 100644 index 6052e1b..0000000 --- a/social/src/main/java/com/jiagutech/ams/rest/CenterRestClient.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.jiagutech.ams.rest; - -import lombok.RequiredArgsConstructor; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; -import org.springframework.web.client.RestTemplate; - -/** - * @ClassName CenterClient - * @author: zhangyeguang - * @create: 2024-09-03 16:32 - * @Version 1.0 - * @description: - **/ -@Component -@Slf4j -@RequiredArgsConstructor -public class CenterRestClient { - private final RestTemplate restTemplate; - - - -} diff --git a/social/src/main/java/com/jiagutech/ams/rest/TrackRestClient.java b/social/src/main/java/com/jiagutech/ams/rest/TrackRestClient.java new file mode 100644 index 0000000..ec25e06 --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/rest/TrackRestClient.java @@ -0,0 +1,44 @@ +package com.jiagutech.ams.rest; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.TypeReference; +import com.jiagutech.ams.model.Locus; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestTemplate; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @ClassName CenterClient + * @author: zhangyeguang + * @create: 2024-09-03 16:32 + * @Version 1.0 + * @description: + **/ +@Component +@Slf4j +@RequiredArgsConstructor +public class TrackRestClient { + private final RestTemplate restTemplate; + + + @Value("${center-track.client.url}") + private String CenterTrackUrl; + + + public List getTractorByDroneIdAndTime(String droneid, Long startTime, Long endTime) { + Map map = new HashMap<>(); + map.put("droneid", droneid); + map.put("startTime", startTime); + map.put("endTime", endTime); + String res = restTemplate.getForObject(CenterTrackUrl + "?droneid={droneid}&start={startTime}&end={endTime}", String.class, map); + return JSON.parseObject(res, new TypeReference>() {}); + } + + +} diff --git a/social/src/main/java/com/jiagutech/ams/service/DeviceService.java b/social/src/main/java/com/jiagutech/ams/service/DeviceService.java index a5c2c76..02a246f 100644 --- a/social/src/main/java/com/jiagutech/ams/service/DeviceService.java +++ b/social/src/main/java/com/jiagutech/ams/service/DeviceService.java @@ -1,9 +1,14 @@ package com.jiagutech.ams.service; +import com.jiagutech.ams.model.common.PageRequest; +import com.jiagutech.ams.model.common.PageResult; +import com.jiagutech.ams.model.dto.DeviceDTO; import com.jiagutech.ams.model.response.DeviceInfo; import java.util.List; public interface DeviceService { List onlineAndRound(double maxLng, double maxLat, double minLng, double minLat); + + PageResult page(PageRequest pageRequest); } diff --git a/social/src/main/java/com/jiagutech/ams/service/DeviceServiceImpl.java b/social/src/main/java/com/jiagutech/ams/service/DeviceServiceImpl.java index 3a33c84..64f3e9b 100644 --- a/social/src/main/java/com/jiagutech/ams/service/DeviceServiceImpl.java +++ b/social/src/main/java/com/jiagutech/ams/service/DeviceServiceImpl.java @@ -4,12 +4,19 @@ import cn.dev33.satoken.annotation.SaCheckLogin; import cn.dev33.satoken.annotation.SaCheckRole; import cn.dev33.satoken.stp.StpUtil; import com.alibaba.fastjson2.JSON; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.CollectionUtils; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.jiagutech.ams.constant.UserConstants; import com.jiagutech.ams.mapper.DeviceMapper; import com.jiagutech.ams.model.LoginUser; import com.jiagutech.ams.model.TrackDataJG; +import com.jiagutech.ams.model.common.PageRequest; +import com.jiagutech.ams.model.common.PageResult; +import com.jiagutech.ams.model.dto.DeviceDTO; import com.jiagutech.ams.model.response.DeviceInfo; +import com.jiagutech.ams.model.response.JobItem; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.data.redis.core.StringRedisTemplate; @@ -65,4 +72,14 @@ public class DeviceServiceImpl implements DeviceService { } return deviceInfos; } + + @Override + public PageResult page(PageRequest pageRequest) { + Page page = new Page(pageRequest.getPageNum(), pageRequest.getPageSize()); + QueryWrapper queryWrapper = Wrappers.query(); + LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser()); + queryWrapper.eq("dept_id",loginUser.getDept().getId()); + Page result = deviceMapper.selectPage(page, queryWrapper); + return PageResult.of((int) result.getTotal(), (int) pageRequest.getPageSize(), (int) result.getCurrent(), result.getRecords()); + } } diff --git a/social/src/main/java/com/jiagutech/ams/service/JobService.java b/social/src/main/java/com/jiagutech/ams/service/JobService.java index af01a06..d694a91 100644 --- a/social/src/main/java/com/jiagutech/ams/service/JobService.java +++ b/social/src/main/java/com/jiagutech/ams/service/JobService.java @@ -1,8 +1,11 @@ package com.jiagutech.ams.service; +import com.jiagutech.ams.model.TrackImageVO; +import com.jiagutech.ams.model.TrackItem; import com.jiagutech.ams.model.common.PageRequest; import com.jiagutech.ams.model.common.PageResult; import com.jiagutech.ams.model.dto.JobTypeDTO; +import com.jiagutech.ams.model.dto.TrackImageDTO; import com.jiagutech.ams.model.request.JobCreateRequest; import com.jiagutech.ams.model.request.JobPageRequest; import com.jiagutech.ams.model.response.JobCreateResponse; @@ -25,4 +28,8 @@ public interface JobService { void exportJobs(JobPageRequest jobPageRequest, HttpServletResponse response); void exportByFarmer(JobPageRequest jobPageRequest, HttpServletResponse response); + + List getTrackList(Long jobId); + + void saveJobImages(TrackImageVO trackImageDTO); } diff --git a/social/src/main/java/com/jiagutech/ams/service/JobServiceImpl.java b/social/src/main/java/com/jiagutech/ams/service/JobServiceImpl.java index f0ead06..d8bec23 100644 --- a/social/src/main/java/com/jiagutech/ams/service/JobServiceImpl.java +++ b/social/src/main/java/com/jiagutech/ams/service/JobServiceImpl.java @@ -2,7 +2,7 @@ package com.jiagutech.ams.service; import cn.dev33.satoken.stp.StpUtil; import cn.hutool.core.collection.CollectionUtil; -import com.alibaba.excel.EasyExcel; +import cn.hutool.core.util.ObjectUtil; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.Wrappers; @@ -10,32 +10,23 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.jiagutech.ams.constant.UserConstants; import com.jiagutech.ams.exception.BizCode; import com.jiagutech.ams.exception.BusinessException; -import com.jiagutech.ams.mapper.JobMapper; -import com.jiagutech.ams.mapper.JobTypeMapper; -import com.jiagutech.ams.mapper.RegionMapper; -import com.jiagutech.ams.mapper.UserMapper; -import com.jiagutech.ams.model.JobMapping; -import com.jiagutech.ams.model.LoginUser; +import com.jiagutech.ams.mapper.*; +import com.jiagutech.ams.model.*; import com.jiagutech.ams.model.common.PageRequest; import com.jiagutech.ams.model.common.PageResult; -import com.jiagutech.ams.model.dto.JobDTO; -import com.jiagutech.ams.model.dto.JobTypeDTO; -import com.jiagutech.ams.model.dto.RegionDTO; -import com.jiagutech.ams.model.dto.RoleDTO; +import com.jiagutech.ams.model.dto.*; import com.jiagutech.ams.model.request.JobCreateRequest; import com.jiagutech.ams.model.request.JobPageRequest; import com.jiagutech.ams.model.response.JobCreateResponse; import com.jiagutech.ams.model.response.JobItem; +import com.jiagutech.ams.model.response.JobPolyItem; +import com.jiagutech.ams.rest.TrackRestClient; import com.jiagutech.ams.utils.ExcelUtil; import jakarta.servlet.http.HttpServletResponse; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; -import org.apache.poi.util.StringUtil; import org.springframework.stereotype.Service; -import java.io.IOException; -import java.io.UnsupportedEncodingException; -import java.net.URLEncoder; import java.util.ArrayList; import java.util.List; import java.util.function.Predicate; @@ -52,12 +43,20 @@ import java.util.stream.Collectors; @Service @RequiredArgsConstructor public class JobServiceImpl implements JobService { + private final JobMapper jobMapper; + private final UserMapper userMapper; - private final RegionMapper regionMapper; + + private final DeviceMapper deviceMapper; private final JobTypeMapper jobTypeMapper; + private final TrackRestClient trackRestClient; + + private final TrackImageMapper trackImageMapper; + + @Override public JobCreateResponse createJob(JobCreateRequest jobCreateRequest) { LoginUser loginUser = StpUtil.getSession().get(UserConstants.SYS_SESSION, new LoginUser()); @@ -83,6 +82,7 @@ public class JobServiceImpl implements JobService { } + @Override public PageResult getPages(PageRequest pageRequest) { JobPageRequest requestParam = pageRequest.getRequest(); @@ -117,9 +117,44 @@ public class JobServiceImpl implements JobService { public void exportByFarmer(JobPageRequest jobPageRequest, HttpServletResponse response) { QueryWrapper queryWrapper = buildQueryWrapper(jobPageRequest); List jobItems = jobMapper.jobListCountByFarmer(queryWrapper); - ExcelUtil.exportExcel(jobItems, "作业记录", JobItem.class, response); + List jobPolyItems = JobMapping.INSTANCE.jobItemListToJobPolyItemList(jobItems); + ExcelUtil.exportExcel(jobPolyItems, "作业记录", JobPolyItem.class, response); + } + + + @Override + public List getTrackList(Long jobId) { + if (jobId != null) { + JobDTO job = jobMapper.selectById(jobId); + DeviceDTO deviceDTO = deviceMapper.selectById(job.getDeviceId()); + List locusList = trackRestClient.getTractorByDroneIdAndTime(deviceDTO.getBoxNum(), job.getStartTime(), job.getEndTime()); + QueryWrapper query = Wrappers.query(); + List trackImageDTOS = trackImageMapper.selectList( + query.eq("device_id", job.getDeviceId()) + .between("ts", job.getStartTime(), job.getEndTime()) + ); + List trackItems = new ArrayList<>(locusList.size()); + for (Locus locus : locusList) { + TrackItem trackItem = TrackMapping.INSTANCE.convertToTrackItemByLocus(locus); + trackItem.setImageUrl(trackImageDTOS.stream().filter(t -> t.getTs() == locus.getTimestamp()).findFirst().map(t -> t.getImageUrl()).orElse(null)); + trackItems.add(trackItem); + } + return trackItems; + } + return List.of(); } + @Override + public void saveJobImages(TrackImageVO trackImageVO) { + TrackImageDTO trackImageDTO = TrackMapping.INSTANCE.convertToTrackImageDTOByVO(trackImageVO); + QueryWrapper query = Wrappers.query(); + DeviceDTO deviceDTO = deviceMapper.selectOne(query.eq("box_num", trackImageDTO.getBoxNum())); + if (ObjectUtil.isNotEmpty(deviceDTO)) { + trackImageDTO.setDeviceId(deviceDTO.getId()); + trackImageMapper.insert(trackImageDTO); + } + + } private QueryWrapper buildQueryWrapper(JobPageRequest requestParam) { diff --git a/social/src/main/java/com/jiagutech/ams/service/SortieService.java b/social/src/main/java/com/jiagutech/ams/service/SortieService.java new file mode 100644 index 0000000..148428d --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/service/SortieService.java @@ -0,0 +1,59 @@ +package com.jiagutech.ams.service; + +import cn.hutool.core.util.ObjectUtil; +import com.alibaba.fastjson2.JSON; +import com.baomidou.mybatisplus.core.toolkit.Wrappers; +import com.jiagutech.ams.mapper.DeviceMapper; +import com.jiagutech.ams.mapper.SortieMapper; +import com.jiagutech.ams.model.SortieMapping; +import com.jiagutech.ams.model.UavSortie; +import com.jiagutech.ams.model.dto.SortieDTO; +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.amqp.rabbit.annotation.RabbitListener; +import org.springframework.stereotype.Component; + +/** + * @ClassName SortieService + * @author: zhangyeguang + * @create: 2024-09-09 09:32 + * @Version 1.0 + * @description: + **/ +@Slf4j +@Component +@RequiredArgsConstructor +public class SortieService { + + private final SortieMapper sortieMapper; + + @RabbitListener(queues = "queue_amssortie_social") + public void receiveMessage(String message) { + log.info("receiveMessage: {}", message); + try { + UavSortie uavSortie = JSON.parseObject(message, UavSortie.class); + SortieDTO sortieDTO = SortieMapping.INSTANCE.convertToSortieDTOByUavSortie(uavSortie); + SortieDTO hasSorties = sortieMapper.selectOne(Wrappers.lambdaQuery(SortieDTO.class).eq(SortieDTO::getVehicleId, uavSortie.getStartTime())); + if (ObjectUtil.isNotEmpty(sortieDTO)) { + if (ObjectUtil.isNotEmpty(hasSorties)) { + sortieDTO.setId(hasSorties.getId()); + sortieMapper.updateById(sortieDTO); + return; + } + sortieMapper.insert(sortieDTO); + } + } catch (Exception e) { + log.error("receiveMessage error", e); + } + + } +// QueryWrapper queryWrapper = Wrappers.query(); +// DeviceDTO deviceDTO = deviceMapper.selectOne(queryWrapper.eq("device_id", sortieDTO.getVehicleId())); +// if (ObjectUtil.isNotEmpty(deviceDTO)) { +// Long DeviceId = deviceDTO.getId(); +// +// } + + +} + diff --git a/social/src/main/java/com/jiagutech/ams/utils/FlightTrackerUtils.java b/social/src/main/java/com/jiagutech/ams/utils/FlightTrackerUtils.java new file mode 100644 index 0000000..2fb483f --- /dev/null +++ b/social/src/main/java/com/jiagutech/ams/utils/FlightTrackerUtils.java @@ -0,0 +1,368 @@ +package com.jiagutech.ams.utils; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; + +import org.locationtech.jts.geom.*; +import org.locationtech.proj4j.BasicCoordinateTransform; +import org.locationtech.proj4j.CRSFactory; +import org.locationtech.proj4j.CoordinateReferenceSystem; +import org.locationtech.proj4j.ProjCoordinate; + + +import java.io.FileReader; +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.ArrayList; +import java.util.List; + +public class FlightTrackerUtils { + + private static final double DEG_TO_RAD = Math.PI / 180; + private static final double RAD_TO_DEG = 180 / Math.PI; + // 架次最小轨迹点数量 + private static final double MIN_POINT_COUNT = 10; + // 架次最小轨迹点密度 + private static final double MIN_POINT_DENSITY = 1; + // 架次轨迹最大速度 dm/s + private static final double MAX_SPEED = 100; + // 架次轨迹最大间隔距离 单位:米 + private static final double MAX_DISTANCE = 100; + // 架次轨迹最大时间间隔 单位:秒 + private static final double MAX_DURATION = 90; + + public static class PointTemp { + LocalDateTime timestamp; + double lat; + double lon; + + int spd; + + public PointTemp(LocalDateTime timestamp, double lat, double lon, int spd) { + this.timestamp = timestamp; + this.lat = lat; + this.lon = lon; + this.spd = spd; + } + } + + public static class SortieTemp{ + long startTime; + long endTime; + double area; + long duration; + String startGeom; + + + public long getDuration() { + return (endTime - startTime) / 1000; + } + + public long getStartTime() { + return startTime; + } + + public long getEndTime() { + return endTime; + } + + public double getArea() { + return area; + } + + public String getStartGeom() { + return startGeom; + } + + public String toJson(){ + ObjectMapper mapper = new ObjectMapper(); + try { + return mapper.writeValueAsString(this); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + return null; + } + + } + + public static double haversineDistance(double lat1, double lon1, double lat2, double lon2) { + GeometryFactory geometryFactory = new GeometryFactory(); + + Coordinate coord1 = fromLatLngToPoint(lat1, lon1); + Coordinate coord2 = fromLatLngToPoint(lat2, lon2); + + Point point1 = geometryFactory.createPoint(coord1); + Point point2 = geometryFactory.createPoint(coord2); + + return point1.distance(point2); + } + + public static List> readAndProcessFlightData(String filePath) throws IOException { + List points = new ArrayList<>(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + try (CSVParser parser = CSVParser.parse(new FileReader(filePath), CSVFormat.DEFAULT.withHeader())) { + for (CSVRecord record : parser) { + LocalDateTime timestamp = LocalDateTime.parse(record.get("ts"), formatter); + double lat = Double.parseDouble(record.get("lat")); + double lon = Double.parseDouble(record.get("lon")); + int spd = Integer.parseInt(record.get("spd")); + points.add(new PointTemp(timestamp, lat, lon, spd)); + } + } + points = removeStationaryPoints(points,0.5); + List> segments = new ArrayList<>(); + List currentSegment = new ArrayList<>(); + for (int i = 0; i < points.size() - 1; i++) { + PointTemp p1 = points.get(i); + PointTemp p2 = points.get(i + 1); + double distance = haversineDistance(p1.lat, p1.lon, p2.lat, p2.lon); + long timeDifference = java.time.Duration.between(p1.timestamp, p2.timestamp).getSeconds(); +// double speed = distance / timeDifference; + + if (p1.spd <= MAX_SPEED) { + if (distance <= MAX_DISTANCE && timeDifference <= MAX_DURATION) { + currentSegment.add(p1); + } else { + currentSegment.add(p1); + segments.add(currentSegment); + currentSegment = new ArrayList<>(); + } + } + } + currentSegment.add(points.get(points.size() - 1)); + segments.add(currentSegment); + + return segments; + } + + public static List> readAndProcessFlightData(List points) { + points = removeStationaryPoints(points,0.5); + List> segments = new ArrayList<>(); + List currentSegment = new ArrayList<>(); + for (int i = 0; i < points.size() - 1; i++) { + PointTemp p1 = points.get(i); + PointTemp p2 = points.get(i + 1); + double distance = haversineDistance(p1.lat, p1.lon, p2.lat, p2.lon); + long timeDifference = java.time.Duration.between(p1.timestamp, p2.timestamp).getSeconds(); +// double speed = distance / timeDifference; + + if (p1.spd <= MAX_SPEED) { + if (distance <= 100 && timeDifference <= 90) { + currentSegment.add(p1); + } else { + currentSegment.add(p1); + segments.add(currentSegment); + currentSegment = new ArrayList<>(); + } + } + } + currentSegment.add(points.get(points.size() - 1)); + segments.add(currentSegment); + + return segments; + } + + public static Coordinate fromLatLngToPoint(double lat, double lng) { + double x = lng * 20037508.34 / 180; + double y = Math.log(Math.tan((90 + lat) * DEG_TO_RAD / 2)) / DEG_TO_RAD; + y = y * 20037508.34 / 180; + return new Coordinate(x, y); + } + +// public static double calculateArea(List points) { +// if (points.size() < 3) { +// return 0; +// } +// +// GeometryFactory geometryFactory = new GeometryFactory(); +// Coordinate[] coordinates = new Coordinate[points.size() + 1]; +// +// for (int i = 0; i < points.size(); i++) { +// PointTemp point = points.get(i); +// coordinates[i] = fromLatLngToPoint(point.lat, point.lon); +// } +// coordinates[points.size()] = coordinates[0]; +// +// Polygon polygon = geometryFactory.createPolygon(coordinates); +// double area = polygon.getArea(); +// +// return area * 0.0001; // Convert to mu (亩) +// } + + public static double calculateArea(List points) { + if (points.size() < 3) { + return 0; + } + + GeometryFactory geometryFactory = new GeometryFactory(); + Coordinate[] coordinates = new Coordinate[points.size() + 1]; + + for (int i = 0; i < points.size(); i++) { + PointTemp point = points.get(i); + ProjCoordinate projCoord = fromLatLngToUTM(point.lat, point.lon); + coordinates[i] = new Coordinate(projCoord.x, projCoord.y); + } + coordinates[points.size()] = coordinates[0]; + + LinearRing shell = geometryFactory.createLinearRing(coordinates); + Polygon polygon = geometryFactory.createPolygon(shell); + + double area = polygon.getArea(); + + return area * 0.0015; // Convert to mu (亩) + } + + public static List removeStationaryPoints(List points, double threshold) { + List filteredPoints = new ArrayList<>(); + filteredPoints.add(points.get(0)); + + for (int i = 1; i < points.size(); i++) { + PointTemp previousPoint = points.get(i - 1); + PointTemp currentPoint = points.get(i); + + double distance = haversineDistance(previousPoint.lat, previousPoint.lon, currentPoint.lat, currentPoint.lon); + + if (distance >= threshold) { + filteredPoints.add(currentPoint); + } + } + + return filteredPoints; + } + +// public static Point toScreenCoordinates(PointTemp point, double minLat, double maxLat, double minLon, double maxLon, int width, int height) { +// int x = (int) ((point.lon - minLon) / (maxLon - minLon) * width); +// int y = (int) ((maxLat - point.lat) / (maxLat - minLat) * height); +// return new Point(x, y); +// } + +// public static void saveTrajectoryToImage(List group, String filename) { +// int width = 800; +// int height = 600; +// +// // 计算最小和最大经纬度 +// double minLat = Double.MAX_VALUE; +// double maxLat = Double.MIN_VALUE; +// double minLon = Double.MAX_VALUE; +// double maxLon = Double.MIN_VALUE; +// for (PointTemp point : group) { +// minLat = Math.min(minLat, point.lat); +// maxLat = Math.max(maxLat, point.lat); +// minLon = Math.min(minLon, point.lon); +// maxLon = Math.max(maxLon, point.lon); +// +// } +// +// // 创建 BufferedImage +// BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); +// Graphics2D g = image.createGraphics(); +// +// // 设置背景和轨迹颜色 +// g.setColor(Color.WHITE); +// g.fillRect(0, 0, width, height); +// g.setColor(Color.BLUE); +// +// // 绘制轨迹 +// for (int i = 0; i < group.size() - 1; i++) { +// PointTemp point1 = group.get(i); +// PointTemp point2 = group.get(i + 1); +// Point screenPoint1 = toScreenCoordinates(point1, minLat, maxLat, minLon, maxLon, width, height); +// Point screenPoint2 = toScreenCoordinates(point2, minLat, maxLat, minLon, maxLon, width, height); +// g.drawLine(screenPoint1.x, screenPoint1.y, screenPoint2.x, screenPoint2.y); +// } +// +// +// // 保存图像为 PNG 文件 +// try { +// File pngFile = new File(filename); +//// pngFile.deleteOnExit(); +// +// ImageIO.write(image, "png", pngFile); +// } catch (IOException e) { +// System.out.printf("保存图像文件失败: %s", e.getMessage()); +// e.printStackTrace(); +// } +// } + public static ProjCoordinate fromLatLngToUTM(double lat, double lon) { + CRSFactory crsFactory = new CRSFactory(); + CoordinateReferenceSystem wgs84 = crsFactory.createFromName("EPSG:4326"); + CoordinateReferenceSystem utm = crsFactory.createFromName("EPSG:32633"); // Choose the appropriate UTM zone + + BasicCoordinateTransform transform = new BasicCoordinateTransform(wgs84, utm); + + ProjCoordinate srcCoord = new ProjCoordinate(lon, lat); + ProjCoordinate dstCoord = new ProjCoordinate(); + + transform.transform(srcCoord, dstCoord); + + return dstCoord; + } + + public static List getPointsTempFromCsv(String path) throws Exception { + List points = new ArrayList<>(); + DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"); + + try (CSVParser parser = CSVParser.parse(new FileReader(path), CSVFormat.DEFAULT.withHeader())) { + for (CSVRecord record : parser) { + LocalDateTime timestamp = LocalDateTime.parse(record.get("ts"), formatter); + double lat = Double.parseDouble(record.get("lat")); + double lon = Double.parseDouble(record.get("lon")); + int spd = Integer.parseInt(record.get("spd")); + points.add(new PointTemp(timestamp, lat, lon, spd)); + } + } + return points; + } + + public static List pointToSortie(List points){ + List sorties = new ArrayList<>(); + List> segments = readAndProcessFlightData(points); + for (int i = 0; i < segments.size(); i++) { + double area = calculateArea(segments.get(i)); + if (segments.get(i).size() < MIN_POINT_COUNT || segments.get(i).size() / area < MIN_POINT_DENSITY){ + continue; + } + SortieTemp sortieTemp = new SortieTemp(); + sortieTemp.startTime = segments.get(i).get(0).timestamp.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + sortieTemp.endTime = segments.get(i).get(segments.get(i).size()-1).timestamp.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); + sortieTemp.area = area; + sortieTemp.startGeom = segments.get(i).get(0).lat+" "+segments.get(i).get(0).lon; + sorties.add(sortieTemp); + } + return sorties; + } + + public static void main(String[] args) throws Exception { + String filePath = "/Users/leesans/Documents/03_Source/jiagu/test/sorties/src/main/java/org/example/test0319.csv"; + + // List> segments = readAndProcessFlightData(filePath); +// for (int i = 0; i < segments.size(); i++) { +// double area = calculateArea(segments.get(i)); +// if (segments.get(i).size() < 30 || segments.get(i).size() / area < 1){ +// continue; +// } +// SortieTemp sortieTemp = new SortieTemp(); +// sortieTemp.startTime = segments.get(i).get(0).timestamp.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); +// sortieTemp.endTime = segments.get(i).get(segments.get(i).size()-1).timestamp.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli(); +// sortieTemp.area = area; +// saveTrajectoryToImage(segments.get(i), String.format("/Users/leesans/Documents/03_Source/jiagu/test/output/segment-%d.png", i + 1)); +// System.out.printf("Segment %d size: %d area: %.2f mu density: %.2f first timestamp: %s end timestamp: %s%n", i + 1, +// segments.get(i).size(), area, segments.get(i).size() / area, segments.get(i).get(0).timestamp, +// segments.get(i).get(segments.get(i).size()-1).timestamp); +// System.out.println(sortieTemp.toJson()); +// } + List points = getPointsTempFromCsv(filePath); + List sorties = pointToSortie(points); + for (int i = 0; i < sorties.size(); i++) { + System.out.println(sorties.get(i).toJson()); + } + } +} + diff --git a/social/src/main/resources/mapper/JobMapper.xml b/social/src/main/resources/mapper/JobMapper.xml index 8939b7f..941bead 100644 --- a/social/src/main/resources/mapper/JobMapper.xml +++ b/social/src/main/resources/mapper/JobMapper.xml @@ -12,8 +12,11 @@ j.operator_id, FROM_UNIXTIME(j.start_time/1000,'%Y-%m-%d %H:%i:%s') as start_time_str, u1.nick_name as operator_name, + u1.phone as operator_phone, j.farmer_id, u2.nick_name as farmer_name, + u2.phone as farmer_phone, + u2.region_name , j.job_type, t.name as type_name, d.id as dept_id, @@ -23,8 +26,6 @@ left join ams_dept d on j.dept_id=d.id left join ams_user u1 on j.operator_id = u1.id left join ams_user u2 on j.farmer_id = u2.id - - + + + \ No newline at end of file diff --git a/social/src/main/resources/mapper/RegionMapper.xml b/social/src/main/resources/mapper/RegionMapper.xml index 3aa30da..accff1c 100644 --- a/social/src/main/resources/mapper/RegionMapper.xml +++ b/social/src/main/resources/mapper/RegionMapper.xml @@ -41,7 +41,7 @@ ) SELECT GROUP_CONCAT(region_code ORDER BY level SEPARATOR '->') AS region_code, - GROUP_CONCAT(region_name ORDER BY level SEPARATOR '->') AS regionName + GROUP_CONCAT(region_name ORDER BY level SEPARATOR '-') AS regionName from cte \ No newline at end of file diff --git a/social/src/main/resources/mapper/SortieMapper.xml b/social/src/main/resources/mapper/SortieMapper.xml new file mode 100644 index 0000000..2ee1ae2 --- /dev/null +++ b/social/src/main/resources/mapper/SortieMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/social/src/main/resources/mapper/TrackImageMapper.xml b/social/src/main/resources/mapper/TrackImageMapper.xml new file mode 100644 index 0000000..94fb2b4 --- /dev/null +++ b/social/src/main/resources/mapper/TrackImageMapper.xml @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/system/pom.xml b/system/pom.xml index d901bea..e3f0c39 100644 --- a/system/pom.xml +++ b/system/pom.xml @@ -18,15 +18,18 @@ - - org.springframework.boot - spring-boot-starter-web - + com.jiagutech common 1.0.0-SNAPSHOT + + org.springframework.boot + spring-boot-starter-web + + + cn.hutool diff --git a/system/src/main/java/com/jiagutech/ams/model/UserMapping.java b/system/src/main/java/com/jiagutech/ams/model/UserMapping.java index 2705596..9b63d3d 100644 --- a/system/src/main/java/com/jiagutech/ams/model/UserMapping.java +++ b/system/src/main/java/com/jiagutech/ams/model/UserMapping.java @@ -3,6 +3,7 @@ package com.jiagutech.ams.model; import com.jiagutech.ams.model.dto.UserDTO; import com.jiagutech.ams.model.request.UserRequest; import org.mapstruct.Mapper; +import org.mapstruct.Mapping; import org.mapstruct.factory.Mappers; /** @@ -17,6 +18,7 @@ public interface UserMapping { UserMapping INSTANCE = Mappers.getMapper(UserMapping.class); + @Mapping(source = "userId", target = "id") UserDTO userToUserDTO(UserRequest user); LoginUser userDTOToLoginUser(UserDTO userDTO); diff --git a/system/src/main/java/com/jiagutech/ams/model/request/UserRequest.java b/system/src/main/java/com/jiagutech/ams/model/request/UserRequest.java index 06a1d16..cc8eb36 100644 --- a/system/src/main/java/com/jiagutech/ams/model/request/UserRequest.java +++ b/system/src/main/java/com/jiagutech/ams/model/request/UserRequest.java @@ -20,7 +20,6 @@ public class UserRequest { /** * 用户ID */ - @JsonIgnore private Long userId; /** diff --git a/system/src/main/java/com/jiagutech/ams/service/UserServiceImpl.java b/system/src/main/java/com/jiagutech/ams/service/UserServiceImpl.java index d451c3c..0a90717 100644 --- a/system/src/main/java/com/jiagutech/ams/service/UserServiceImpl.java +++ b/system/src/main/java/com/jiagutech/ams/service/UserServiceImpl.java @@ -94,6 +94,7 @@ public class UserServiceImpl implements UserService { RegionVO completeRegionInfo = regionMapper.getCompleteRegionInfo(userDTO.getRegionCode()); if (completeRegionInfo != null) { userDTO.setRegionPath(completeRegionInfo.getRegionCode()); + userDTO.setRegionName(completeRegionInfo.getRegionName()); } } userMapper.insert(userDTO); diff --git a/web/pom.xml b/web/pom.xml index d94e045..18d83f9 100644 --- a/web/pom.xml +++ b/web/pom.xml @@ -1,102 +1,158 @@ - 4.0.0 - - com.jiagutech - ams-social - ${revision} - + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + 4.0.0 + + com.jiagutech + ams-social + ${revision} + - web + web - - 17 - 17 - UTF-8 - + + 17 + 17 + UTF-8 + - - - dev - - - dev - info - - - - true - - - - prod - - prod - info - - - - - - com.jiagutech - system - 1.0.0-SNAPSHOT - - - com.jiagutech - social - 1.0.0-SNAPSHOT - - - org.springframework.boot - spring-boot-starter-data-jdbc - - - mysql - mysql-connector-java - - - org.springdoc - springdoc-openapi-starter-webmvc-ui + + + dev + + + dev + info + + + + true + + + + zyg + + zyg + info + + + + prod + + prod + info + + + + + + com.jiagutech + system + 1.0.0-SNAPSHOT + + + com.jiagutech + social + 1.0.0-SNAPSHOT + + + org.springframework.boot + spring-boot-starter-data-jdbc + + + mysql + mysql-connector-java + + + org.springdoc + springdoc-openapi-starter-webmvc-ui - - - org.springdoc - springdoc-openapi-starter-webmvc-api - - - org.apache.commons - commons-pool2 - 2.12.0 - - - cn.dev33 - sa-token-spring-boot3-starter - + + + org.springdoc + springdoc-openapi-starter-webmvc-api + + + org.apache.commons + commons-pool2 + 2.12.0 + + + cn.dev33 + sa-token-spring-boot3-starter + - - cn.dev33 - sa-token-redis - - - + + cn.dev33 + sa-token-redis + + + + org.mapstruct + mapstruct + 1.5.3.Final + + + org.springframework.amqp + spring-rabbit + + + org.springframework.amqp + spring-amqp + + + + + + src/main/resources + true + + application.yml + application-${profiles.active}.yml + *.xml + + + + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.1 + + 17 + 17 + + + org.mapstruct + mapstruct-processor + 1.5.3.Final + + + + org.projectlombok + lombok + ${lombok.version} + + + + + + + - - - org.springframework.boot - spring-boot-maven-plugin - ${spring-boot.version} - - - - repackage - - - - - - \ No newline at end of file diff --git a/web/src/main/java/com/jiagutech/ams/common/RabbitConfig.java b/web/src/main/java/com/jiagutech/ams/common/RabbitConfig.java new file mode 100644 index 0000000..27e4cb5 --- /dev/null +++ b/web/src/main/java/com/jiagutech/ams/common/RabbitConfig.java @@ -0,0 +1,40 @@ +package com.jiagutech.ams.common; + +import org.springframework.amqp.core.*; +import org.springframework.amqp.rabbit.connection.ConnectionFactory; +import org.springframework.amqp.rabbit.core.RabbitTemplate; +import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter; +import org.springframework.amqp.support.converter.SimpleMessageConverter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @ClassName RabbitConfig + * @author: zhangyeguang + * @create: 2024-09-10 09:58 + * @Version 1.0 + * @description: + **/ +@Configuration +public class RabbitConfig { + public static final String EXCHANGE_NAME = "topic.exchange"; + public static final String QUEUE_FARM_SORTIE = "queue_amssortie_social"; + + @Bean + public Exchange exchange() { + //durable(true) 持久化,mq重启之后交换机还在 + return ExchangeBuilder.topicExchange(EXCHANGE_NAME).durable(true).build(); + } + + @Bean(QUEUE_FARM_SORTIE) + public Queue farmsortieQueue() { + return new Queue(QUEUE_FARM_SORTIE); + } + + + @Bean + public Binding bindingFarmSortie() { + return BindingBuilder.bind(farmsortieQueue()).to(exchange()).with("#.farmsortie").noargs(); + } + +} diff --git a/web/src/main/resources/application-dev.yml b/web/src/main/resources/application-dev.yml new file mode 100644 index 0000000..b5a103f --- /dev/null +++ b/web/src/main/resources/application-dev.yml @@ -0,0 +1,27 @@ + +spring: + datasource: + # url: jdbc:mysql://192.168.10.111:23306/ams_social?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true + # username: root + # password: 123456 + url: jdbc:mysql://101.34.243.138:7306/ams_social?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true + username: ams + password: ams@1234 + + data: + redis: + host: 192.168.10.111 + port: 6379 + database: 10 + rabbitmq: + host: 192.168.10.111 + port: 5672 + username: admin + password: admin + + + +center-track: + client: + url: http://localhost:11003/iot/farm/track + diff --git a/web/src/main/resources/application-zyg.yml b/web/src/main/resources/application-zyg.yml new file mode 100644 index 0000000..49998fb --- /dev/null +++ b/web/src/main/resources/application-zyg.yml @@ -0,0 +1,26 @@ + +spring: + datasource: + url: jdbc:mysql://101.34.243.138:7306/ams_social?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true + username: ams + password: ams@1234 + + data: + redis: + host: 101.34.243.138 + port: 7379 + database: 10 + # password: 123456 + + rabbitmq: + host: 192.168.10.111 + port: 5672 + username: admin + password: admin + + + +center-track: + client: + url: http://localhost:8080/iot/mTrack + diff --git a/web/src/main/resources/application.yml b/web/src/main/resources/application.yml index fee8d7b..fe88ed2 100644 --- a/web/src/main/resources/application.yml +++ b/web/src/main/resources/application.yml @@ -1,19 +1,14 @@ server: - port: 8180 - + port: 8181 spring: + profiles: + active: @profiles.active@ application: name: ams-social datasource: type: com.zaxxer.hikari.HikariDataSource driver-class-name: com.mysql.cj.jdbc.Driver - # url: jdbc:mysql://192.168.10.111:23306/ams_social?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true - # username: root - # password: 123456 - url: jdbc:mysql://101.34.243.138:7306/ams_social?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true&allowPublicKeyRetrieval=true - username: ams - password: ams@1234 hikari: # 最大连接池数量 maxPoolSize: 20 @@ -31,25 +26,24 @@ spring: keepaliveTime: 30000 data: redis: - host: 192.168.10.111 - port: 6379 - database: 10 - # host: 101.34.243.138 - # port: 7379 - # database: 10 - # # password: 123456 timeout: 10s - # password: tent_zyg@1234 lettuce: pool: # 连接池最大连接数 - max-active: 200 + max-active: 100 # 连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: 3000ms # 连接池中的最大空闲连接 - max-idle: 100 + max-idle: 50 # 连接池中的最小空闲连接 min-idle: 10 + rabbitmq: + + listener: + simple: + concurrency: 2 + + mybatis-plus: @@ -61,6 +55,7 @@ mybatis-plus: global-config: db-config: id-type: assign_id + banner: false sa-token: @@ -73,7 +68,7 @@ sa-token: is-share: false # jwt秘钥 jwt-secret-key: abcdefghijklmnopqrstuvwxyz - is-print: true + is-print: false is-log: false http: @@ -84,8 +79,11 @@ http: read-timeout: 5000 + logging: level: root: INFO com.jiagutech.ams.mapper: DEBUG - +springdoc: + api-docs: + enabled: true