定位区域判断更新,更加准确
This commit is contained in:
parent
8534e08033
commit
578adc465c
|
@ -24,6 +24,7 @@ import org.locationtech.jts.io.WKTWriter;
|
||||||
import org.opengis.feature.simple.SimpleFeature;
|
import org.opengis.feature.simple.SimpleFeature;
|
||||||
import org.opengis.feature.simple.SimpleFeatureType;
|
import org.opengis.feature.simple.SimpleFeatureType;
|
||||||
import org.opengis.referencing.operation.MathTransform;
|
import org.opengis.referencing.operation.MathTransform;
|
||||||
|
import org.locationtech.jts.operation.distance.DistanceOp;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
@ -243,52 +244,38 @@ public class GeoUtils {
|
||||||
double toleranceValue = tolerance == null ? 0 : tolerance.doubleValue();
|
double toleranceValue = tolerance == null ? 0 : tolerance.doubleValue();
|
||||||
|
|
||||||
GeometryFactory geometryFactory = new GeometryFactory();
|
GeometryFactory geometryFactory = new GeometryFactory();
|
||||||
Coordinate coordinate = new Coordinate(lon, lat);
|
Point point = geometryFactory.createPoint(new Coordinate(lon, lat));
|
||||||
Point point = geometryFactory.createPoint(coordinate);
|
|
||||||
|
|
||||||
if (polygon != null && polygon.contains(point)) {
|
if (polygon != null && polygon.contains(point)) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
// 获取多边形的外边界
|
// 计算点到多边形的最短距离,若在误差范围内,则认为在多边形内
|
||||||
Coordinate[] coordinates = polygon.getCoordinates();
|
double distance = calculateMinDistanceToPolygon(polygon, lon, lat);
|
||||||
for (Coordinate coord : coordinates) {
|
return distance <= toleranceValue;
|
||||||
double distance = calculateDistance(lat, lon, coord.y, coord.x);
|
|
||||||
if (distance <= toleranceValue) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判断一个点是否在一个缩短后的圆形区域内
|
* 判断一个点是否在缩短后的区域内
|
||||||
* */
|
* */
|
||||||
public static boolean isInPolygonWithShorten(BigDecimal longitude, BigDecimal latitude, Geometry polygon, BigDecimal shortenDistance) {
|
public static boolean isInPolygonWithShorten(BigDecimal longitude, BigDecimal latitude, Geometry polygon, BigDecimal shortenDistance) {
|
||||||
if (longitude == null || latitude == null || polygon == null ) {
|
if (longitude == null || latitude == null || polygon == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
double lon = longitude.doubleValue();
|
double lon = longitude.doubleValue();
|
||||||
double lat = latitude.doubleValue();
|
double lat = latitude.doubleValue();
|
||||||
double shortenDistanceValue = shortenDistance == null ? 0 : shortenDistance.doubleValue();
|
double shortenDistanceValue = shortenDistance == null ? 0 : shortenDistance.doubleValue();
|
||||||
GeometryFactory geometryFactory = new GeometryFactory();
|
|
||||||
Coordinate coordinate = new Coordinate(lon, lat);
|
Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(lon, lat));
|
||||||
Point point = geometryFactory.createPoint(coordinate);
|
|
||||||
|
|
||||||
if (polygon.contains(point)) {
|
if (polygon.contains(point)) {
|
||||||
// 获取多边形的外边界
|
// 计算点到多边形边界的最短距离
|
||||||
Coordinate[] coordinates = polygon.getCoordinates();
|
double minDistance = calculateMinDistanceToPolygon(polygon, lon, lat);
|
||||||
for (Coordinate coord : coordinates) {
|
// 如果最短距离小于缩短距离,则认为点在缩短区域外
|
||||||
double distance = calculateDistance(lat, lon, coord.y, coord.x);
|
return minDistance > shortenDistanceValue;
|
||||||
if (shortenDistanceValue >= distance) {
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将角度转换为弧度
|
// 将角度转换为弧度
|
||||||
private static double deg2rad(double deg) {
|
private static double deg2rad(double deg) {
|
||||||
|
@ -346,34 +333,65 @@ public class GeoUtils {
|
||||||
return EARTH_RADIUS * c; // 距离(米)
|
return EARTH_RADIUS * c; // 距离(米)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 判获取到最近一个运营区
|
* 计算给定点到多边形的最短距离(单位:米)
|
||||||
* */
|
*/
|
||||||
public static boolean getNearestOperatingArea (String longitude, String latitude, List<Geometry> polygon) {
|
public static double calculateMinDistanceToPolygon(Geometry polygon, double lon, double lat) {
|
||||||
double lon = Double.parseDouble(longitude);
|
Point point = GEOMETRY_FACTORY.createPoint(new Coordinate(lon, lat));
|
||||||
double lat = Double.parseDouble(latitude);
|
|
||||||
|
|
||||||
GeometryFactory geometryFactory = new GeometryFactory();
|
// 获取多边形的边界
|
||||||
Coordinate coordinate = new Coordinate(lon, lat);
|
Geometry boundary = polygon.getBoundary();
|
||||||
Point point = geometryFactory.createPoint(coordinate);
|
Coordinate[] coordinates = boundary.getCoordinates();
|
||||||
|
|
||||||
for (Geometry geometry : polygon) {
|
double minDistance = Double.MAX_VALUE;
|
||||||
if (geometry.contains(point)) {
|
|
||||||
return true;
|
|
||||||
}else{
|
|
||||||
|
|
||||||
|
// 遍历多边形的每条边
|
||||||
|
for (int i = 0; i < coordinates.length - 1; i++) {
|
||||||
|
Coordinate c1 = coordinates[i];
|
||||||
|
Coordinate c2 = coordinates[i + 1];
|
||||||
|
|
||||||
|
// 计算点到线段的最短距离
|
||||||
|
double distance = calculateDistanceToSegment(lat, lon, c1.y, c1.x, c2.y, c2.x);
|
||||||
|
minDistance = Math.min(minDistance, distance);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return minDistance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 计算给定点到多边形的最短距离
|
* 计算点到线段的最短距离(单位:米)
|
||||||
* */
|
*/
|
||||||
public double calculateMinDistanceToPolygon(Geometry polygon, double lon, double lat) {
|
private static double calculateDistanceToSegment(double lat, double lon,
|
||||||
Coordinate coord = new Coordinate(lon, lat);
|
double lat1, double lon1,
|
||||||
Point point = new GeometryFactory().createPoint(coord);
|
double lat2, double lon2) {
|
||||||
return polygon.distance(point); // 返回给定点到多边形的最短距离
|
// 计算点到线段两端点的距离
|
||||||
|
double d1 = calculateDistance(lat, lon, lat1, lon1);
|
||||||
|
double d2 = calculateDistance(lat, lon, lat2, lon2);
|
||||||
|
double lineLength = calculateDistance(lat1, lon1, lat2, lon2);
|
||||||
|
|
||||||
|
// 如果线段长度接近0,返回到端点的距离
|
||||||
|
if (lineLength < 0.000001) {
|
||||||
|
return Math.min(d1, d2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算点到线段的投影是否在线段上
|
||||||
|
double t = ((lat - lat1) * (lat2 - lat1) + (lon - lon1) * (lon2 - lon1)) /
|
||||||
|
((lat2 - lat1) * (lat2 - lat1) + (lon2 - lon1) * (lon2 - lon1));
|
||||||
|
|
||||||
|
if (t < 0) {
|
||||||
|
return d1; // 最近点是第一个端点
|
||||||
|
}
|
||||||
|
if (t > 1) {
|
||||||
|
return d2; // 最近点是第二个端点
|
||||||
|
}
|
||||||
|
|
||||||
|
// 计算投影点的坐标
|
||||||
|
double projLat = lat1 + t * (lat2 - lat1);
|
||||||
|
double projLon = lon1 + t * (lon2 - lon1);
|
||||||
|
|
||||||
|
// 返回点到投影点的距离
|
||||||
|
return calculateDistance(lat, lon, projLat, projLon);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
package com.ruoyi.bst.area.domain.vo;
|
||||||
|
|
||||||
|
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 定位所属区域信息
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
public class LocationAreaVO {
|
||||||
|
|
||||||
|
// 是否在运营区内
|
||||||
|
private Boolean isInArea;
|
||||||
|
|
||||||
|
// 是否在运营区最小内边界
|
||||||
|
private Boolean isInAreaMin;
|
||||||
|
|
||||||
|
// 是否在运营区最大外边界
|
||||||
|
private Boolean isInAreaMax;
|
||||||
|
|
||||||
|
// 是否在禁行区内
|
||||||
|
private Boolean isInNoRidingArea;
|
||||||
|
|
||||||
|
// 位于的禁行区
|
||||||
|
private AreaSubVO inNoRidingArea;
|
||||||
|
|
||||||
|
// 是否靠近禁行区
|
||||||
|
private Boolean isNearNoRidingArea;
|
||||||
|
|
||||||
|
// 靠近的禁行区
|
||||||
|
private AreaSubVO nearNoRidingArea;
|
||||||
|
}
|
|
@ -1,10 +1,12 @@
|
||||||
package com.ruoyi.bst.area.service;
|
package com.ruoyi.bst.area.service;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import com.ruoyi.bst.area.domain.Area;
|
import com.ruoyi.bst.area.domain.Area;
|
||||||
import com.ruoyi.bst.area.domain.AreaQuery;
|
import com.ruoyi.bst.area.domain.AreaQuery;
|
||||||
import com.ruoyi.bst.area.domain.AreaVO;
|
import com.ruoyi.bst.area.domain.AreaVO;
|
||||||
|
import com.ruoyi.bst.area.domain.vo.LocationAreaVO;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 运营区Service接口
|
* 运营区Service接口
|
||||||
|
@ -83,4 +85,13 @@ public interface AreaService
|
||||||
*/
|
*/
|
||||||
public List<AreaVO> selectSimpleList(AreaQuery query);
|
public List<AreaVO> selectSimpleList(AreaQuery query);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 查询定位所属区域信息
|
||||||
|
* @param lon 经度
|
||||||
|
* @param lat 纬度
|
||||||
|
* @param areaId 运营区ID
|
||||||
|
* @return 定位所属区域信息
|
||||||
|
*/
|
||||||
|
public LocationAreaVO selectLocationArea(BigDecimal lon, BigDecimal lat, Long areaId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.ruoyi.bst.area.service.impl;
|
package com.ruoyi.bst.area.service.impl;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.locationtech.jts.geom.Geometry;
|
import org.locationtech.jts.geom.Geometry;
|
||||||
|
@ -10,8 +11,12 @@ import com.github.pagehelper.PageHelper;
|
||||||
import com.ruoyi.bst.area.domain.Area;
|
import com.ruoyi.bst.area.domain.Area;
|
||||||
import com.ruoyi.bst.area.domain.AreaQuery;
|
import com.ruoyi.bst.area.domain.AreaQuery;
|
||||||
import com.ruoyi.bst.area.domain.AreaVO;
|
import com.ruoyi.bst.area.domain.AreaVO;
|
||||||
|
import com.ruoyi.bst.area.domain.vo.LocationAreaVO;
|
||||||
import com.ruoyi.bst.area.mapper.AreaMapper;
|
import com.ruoyi.bst.area.mapper.AreaMapper;
|
||||||
import com.ruoyi.bst.area.service.AreaService;
|
import com.ruoyi.bst.area.service.AreaService;
|
||||||
|
import com.ruoyi.bst.area.utils.AreaUtil;
|
||||||
|
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
|
||||||
|
import com.ruoyi.bst.areaSub.service.AreaSubService;
|
||||||
import com.ruoyi.common.utils.DateUtils;
|
import com.ruoyi.common.utils.DateUtils;
|
||||||
import com.ruoyi.common.utils.collection.CollectionUtils;
|
import com.ruoyi.common.utils.collection.CollectionUtils;
|
||||||
import com.ruoyi.common.utils.map.GeoUtils;
|
import com.ruoyi.common.utils.map.GeoUtils;
|
||||||
|
@ -31,6 +36,9 @@ public class AreaServiceImpl implements AreaService
|
||||||
@Autowired
|
@Autowired
|
||||||
private AreaMapper areaMapper;
|
private AreaMapper areaMapper;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AreaSubService areaSubService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 查询运营区
|
* 查询运营区
|
||||||
*
|
*
|
||||||
|
@ -150,4 +158,20 @@ public class AreaServiceImpl implements AreaService
|
||||||
return areaMapper.logicDel(ids);
|
return areaMapper.logicDel(ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LocationAreaVO selectLocationArea(BigDecimal lon, BigDecimal lat, Long areaId) {
|
||||||
|
if (lon == null || lat == null || areaId == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 查询运营区
|
||||||
|
AreaVO area = this.selectAreaById(areaId);
|
||||||
|
if (area == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 查询运营区内的禁行区
|
||||||
|
List<AreaSubVO> noRidingList = areaSubService.selectNoRidingListByAreaId(areaId);
|
||||||
|
|
||||||
|
return AreaUtil.getLocationArea(lon, lat, area, noRidingList);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,23 +1,27 @@
|
||||||
package com.ruoyi.bst.area.utils;
|
package com.ruoyi.bst.area.utils;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.locationtech.jts.geom.Geometry;
|
import org.locationtech.jts.geom.Geometry;
|
||||||
|
|
||||||
import com.ruoyi.bst.area.domain.Area;
|
import com.ruoyi.bst.area.domain.Area;
|
||||||
import com.ruoyi.bst.area.domain.AreaVO;
|
import com.ruoyi.bst.area.domain.AreaVO;
|
||||||
|
import com.ruoyi.bst.area.domain.vo.LocationAreaVO;
|
||||||
|
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
|
||||||
|
import com.ruoyi.bst.areaSub.utils.AreaSubUtil;
|
||||||
import com.ruoyi.common.utils.map.GeoUtils;
|
import com.ruoyi.common.utils.map.GeoUtils;
|
||||||
|
|
||||||
public class AreaUtil {
|
public class AreaUtil {
|
||||||
|
|
||||||
|
|
||||||
// 是否在运营区内
|
// 是否在运营区内(0误差)
|
||||||
public static boolean isInArea(Area area, BigDecimal longitude, BigDecimal latitude) {
|
public static boolean isInArea(Area area, BigDecimal longitude, BigDecimal latitude) {
|
||||||
Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
|
Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
|
||||||
if (geometry == null) {
|
if (geometry == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, area.getOutageDistance());
|
return GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, BigDecimal.ZERO);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 是否在运营区最小内边界
|
// 是否在运营区最小内边界
|
||||||
|
@ -44,4 +48,35 @@ public class AreaUtil {
|
||||||
return GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, area.getOutageDistance());
|
return GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, area.getOutageDistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static LocationAreaVO getLocationArea(BigDecimal lon, BigDecimal lat, AreaVO area, List<AreaSubVO> noRidingList) {
|
||||||
|
if (lon == null || lat == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LocationAreaVO vo = new LocationAreaVO();
|
||||||
|
|
||||||
|
// 是否在运营区内
|
||||||
|
vo.setIsInArea(AreaUtil.isInArea(area, lon, lat));
|
||||||
|
|
||||||
|
// 是否在运营区最小内边界
|
||||||
|
vo.setIsInAreaMin(AreaUtil.isInAreaMin(area, lon, lat));
|
||||||
|
|
||||||
|
// 是否在运营区最大外边界
|
||||||
|
vo.setIsInAreaMax(AreaUtil.isInAreaMax(area, lon, lat));
|
||||||
|
|
||||||
|
// 是否在禁行区内
|
||||||
|
AreaSubVO inNoRidingArea = AreaSubUtil.getInAreaSub(noRidingList, lon, lat, area.getError());
|
||||||
|
vo.setInNoRidingArea(inNoRidingArea);
|
||||||
|
vo.setIsInNoRidingArea(inNoRidingArea != null);
|
||||||
|
|
||||||
|
// 靠近运营区边界时的播报距离
|
||||||
|
BigDecimal boundaryDistance = area.getBoundaryDistance();
|
||||||
|
// 是否在禁行区内
|
||||||
|
AreaSubVO nearAreaSub = AreaSubUtil.getNearAreaSub(noRidingList, lon, lat, area.getError(), boundaryDistance);
|
||||||
|
vo.setNearNoRidingArea(nearAreaSub);
|
||||||
|
vo.setIsNearNoRidingArea(nearAreaSub != null);
|
||||||
|
|
||||||
|
return vo;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,24 +47,33 @@ public class AreaSubUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 获取靠近的区域
|
* 获取靠近的区域,而非是在区域内
|
||||||
* @param areaSubList 区域列表
|
* @param areaSubList 区域列表
|
||||||
* @param longitude 经度
|
* @param longitude 经度
|
||||||
* @param latitude 纬度
|
* @param latitude 纬度
|
||||||
* @param error 误差
|
* @param distance 靠近多少
|
||||||
* @return 靠近的区域
|
* @return 靠近的区域
|
||||||
*/
|
*/
|
||||||
public static AreaSubVO getNearAreaSub(List<AreaSubVO> areaSubList, BigDecimal longitude, BigDecimal latitude, BigDecimal error) {
|
public static AreaSubVO getNearAreaSub(List<AreaSubVO> areaSubList, BigDecimal longitude, BigDecimal latitude, BigDecimal areaError, BigDecimal distance) {
|
||||||
if (CollectionUtils.isEmptyElement(areaSubList)) {
|
if (CollectionUtils.isEmptyElement(areaSubList)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
BigDecimal tolerance = BigDecimal.ZERO; // 误差距离
|
||||||
|
if (areaError != null) {
|
||||||
|
tolerance = areaError;
|
||||||
|
}
|
||||||
for (AreaSubVO area : areaSubList) {
|
for (AreaSubVO area : areaSubList) {
|
||||||
Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
|
Geometry geometry = GeoUtils.fromWkt(area.getBoundary());
|
||||||
if (geometry == null) {
|
if (geometry == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
boolean inCircle = GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, error);
|
if (area.getError() != null) {
|
||||||
if (inCircle) {
|
tolerance = area.getError();
|
||||||
|
}
|
||||||
|
boolean inMax = GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, distance); // 在外侧误差范围内
|
||||||
|
boolean inCircle = GeoUtils.isInPolygonWithTolerance(longitude, latitude, geometry, tolerance); // 在内部
|
||||||
|
// 不在内部,但在外侧误差范围内,视为靠近
|
||||||
|
if (!inCircle && inMax) {
|
||||||
return area;
|
return area;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -230,7 +230,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
|
||||||
</insert>
|
</insert>
|
||||||
|
|
||||||
<update id="updateDevice" parameterType="Device">
|
<update id="updateDevice" parameterType="Device">
|
||||||
update bst_device
|
update bst_device bd
|
||||||
<trim prefix="SET" suffixOverrides=",">
|
<trim prefix="SET" suffixOverrides=",">
|
||||||
<include refid="updateColumns"/>
|
<include refid="updateColumns"/>
|
||||||
</trim>
|
</trim>
|
||||||
|
|
|
@ -163,6 +163,7 @@ public class OrderValidatorImpl implements OrderValidator{
|
||||||
ServiceUtil.assertion(!DeviceStatus.canUse().contains(device.getStatus()), "ID为%s的车辆当前状态不可使用", device.getId());
|
ServiceUtil.assertion(!DeviceStatus.canUse().contains(device.getStatus()), "ID为%s的车辆当前状态不可使用", device.getId());
|
||||||
ServiceUtil.assertion(MathUtils.smallerThan(device.getRemainingPower(), device.getAreaUndercharge()), "ID为%s的车辆电量不足%s%%,暂时无法使用", device.getId(), device.getAreaUndercharge());
|
ServiceUtil.assertion(MathUtils.smallerThan(device.getRemainingPower(), device.getAreaUndercharge()), "ID为%s的车辆电量不足%s%%,暂时无法使用", device.getId(), device.getAreaUndercharge());
|
||||||
ServiceUtil.assertion(OrderStatus.PROCESSING.getCode().equals(device.getOrderStatus()), "ID为%s的车辆当前有正在进行的订单,无法使用", device.getId());
|
ServiceUtil.assertion(OrderStatus.PROCESSING.getCode().equals(device.getOrderStatus()), "ID为%s的车辆当前有正在进行的订单,无法使用", device.getId());
|
||||||
|
ServiceUtil.assertion(device.getAreaId() == null, "当前车辆未绑定运营区,无法使用");
|
||||||
|
|
||||||
// 设备能否在该订单上使用(换车)
|
// 设备能否在该订单上使用(换车)
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
|
|
|
@ -154,10 +154,10 @@ public class OrderUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 通过设备定位获取是否在运营区
|
// 通过设备定位获取是否在运营区
|
||||||
boolean deviceInArea = AreaUtil.isInArea(area, device.getLongitude(), device.getLatitude()); // 是否在运营区
|
boolean deviceInArea = AreaUtil.isInAreaMax(area, device.getLongitude(), device.getLatitude()); // 是否在运营区
|
||||||
vo.setDeviceInArea(deviceInArea);
|
vo.setDeviceInArea(deviceInArea);
|
||||||
// 通过手机定位获取是否在运营区
|
// 通过手机定位获取是否在运营区
|
||||||
boolean mobileInArea = AreaUtil.isInArea(area, lon, lat); // 是否在运营区
|
boolean mobileInArea = AreaUtil.isInAreaMax(area, lon, lat); // 是否在运营区
|
||||||
vo.setMobileInArea(mobileInArea);
|
vo.setMobileInArea(mobileInArea);
|
||||||
// 是否在运营区
|
// 是否在运营区
|
||||||
boolean inArea = deviceInArea || mobileInArea;
|
boolean inArea = deviceInArea || mobileInArea;
|
||||||
|
|
|
@ -1,24 +1,23 @@
|
||||||
package com.ruoyi.iot.service.impl;
|
package com.ruoyi.iot.service.impl;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
|
||||||
import java.time.Duration;
|
import java.time.Duration;
|
||||||
import java.time.LocalDateTime;
|
import java.time.LocalDateTime;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import com.ruoyi.bst.device.domain.enums.DeviceUnLockType;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
import com.ruoyi.bst.area.domain.AreaVO;
|
import com.ruoyi.bst.area.domain.AreaVO;
|
||||||
|
import com.ruoyi.bst.area.domain.vo.LocationAreaVO;
|
||||||
import com.ruoyi.bst.area.service.AreaService;
|
import com.ruoyi.bst.area.service.AreaService;
|
||||||
import com.ruoyi.bst.area.utils.AreaUtil;
|
import com.ruoyi.bst.area.utils.AreaUtil;
|
||||||
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
|
import com.ruoyi.bst.areaSub.domain.AreaSubVO;
|
||||||
import com.ruoyi.bst.areaSub.service.AreaSubService;
|
import com.ruoyi.bst.areaSub.service.AreaSubService;
|
||||||
import com.ruoyi.bst.areaSub.utils.AreaSubUtil;
|
|
||||||
import com.ruoyi.bst.device.domain.DeviceVO;
|
import com.ruoyi.bst.device.domain.DeviceVO;
|
||||||
import com.ruoyi.bst.device.domain.enums.DeviceLockStatus;
|
import com.ruoyi.bst.device.domain.enums.DeviceLockStatus;
|
||||||
import com.ruoyi.bst.device.domain.enums.DeviceStatus;
|
import com.ruoyi.bst.device.domain.enums.DeviceStatus;
|
||||||
|
import com.ruoyi.bst.device.domain.enums.DeviceUnLockType;
|
||||||
import com.ruoyi.bst.device.service.DeviceIotService;
|
import com.ruoyi.bst.device.service.DeviceIotService;
|
||||||
import com.ruoyi.bst.device.service.DeviceService;
|
import com.ruoyi.bst.device.service.DeviceService;
|
||||||
import com.ruoyi.bst.device.utils.DeviceUtil;
|
import com.ruoyi.bst.device.utils.DeviceUtil;
|
||||||
|
@ -152,14 +151,17 @@ public class IotReceiveServiceImpl implements IotReceiveService {
|
||||||
boolean isOpen = DeviceLockStatus.OPEN.getCode().equals(device.getLockStatus()); // 是否开锁
|
boolean isOpen = DeviceLockStatus.OPEN.getCode().equals(device.getLockStatus()); // 是否开锁
|
||||||
boolean isQLocked = DeviceStatus.Q_LOCKED.getCode().equals(device.getStatus()); // 是否强制断电
|
boolean isQLocked = DeviceStatus.Q_LOCKED.getCode().equals(device.getStatus()); // 是否强制断电
|
||||||
|
|
||||||
// 是否在运营区最大外边界
|
|
||||||
boolean isInAreaMax = AreaUtil.isInAreaMax(area, device.getLongitude(), device.getLatitude());
|
|
||||||
// 是否在禁行区内
|
|
||||||
AreaSubVO inAreaSub = AreaSubUtil.getInAreaSub(noRidingList, device.getLongitude(), device.getLatitude(), area.getError());
|
|
||||||
boolean isInNoRidingArea = inAreaSub != null;
|
|
||||||
// 是否有正在使用的订单
|
// 是否有正在使用的订单
|
||||||
boolean hasOrder = device.getOrderDeviceId() != null && OrderDeviceStatus.USING.getCode().equals(device.getOrderDeviceStatus());
|
boolean hasOrder = device.getOrderDeviceId() != null && OrderDeviceStatus.USING.getCode().equals(device.getOrderDeviceStatus());
|
||||||
|
|
||||||
|
// 获取车辆位置信息
|
||||||
|
LocationAreaVO locationArea = AreaUtil.getLocationArea(device.getLongitude(), device.getLatitude(), area, noRidingList);
|
||||||
|
boolean isInArea = locationArea.getIsInArea() != null && locationArea.getIsInArea();
|
||||||
|
boolean isInAreaMin = locationArea.getIsInAreaMin() != null && locationArea.getIsInAreaMin();
|
||||||
|
boolean isInAreaMax = locationArea.getIsInAreaMax() != null && locationArea.getIsInAreaMax();
|
||||||
|
boolean isInNoRidingArea = locationArea.getIsInNoRidingArea() != null && locationArea.getIsInNoRidingArea();
|
||||||
|
boolean isNearNoRidingArea = locationArea.getIsNearNoRidingArea() != null && locationArea.getIsNearNoRidingArea();
|
||||||
|
|
||||||
// 在运营区内,并且不在禁行区内,并且车辆为强制断电状态,为车辆上电
|
// 在运营区内,并且不在禁行区内,并且车辆为强制断电状态,为车辆上电
|
||||||
if (isInAreaMax && !isInNoRidingArea && isQLocked && !isOpen && hasOrder) {
|
if (isInAreaMax && !isInNoRidingArea && isQLocked && !isOpen && hasOrder) {
|
||||||
deviceIotService.unlock(device, DeviceUnLockType.BACK_AREA, "重新返回运营区上电", false);
|
deviceIotService.unlock(device, DeviceUnLockType.BACK_AREA, "重新返回运营区上电", false);
|
||||||
|
@ -176,9 +178,8 @@ public class IotReceiveServiceImpl implements IotReceiveService {
|
||||||
deviceIotService.qLock(device, "超出运营区外边界最大值,强制断电", false);
|
deviceIotService.qLock(device, "超出运营区外边界最大值,强制断电", false);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
boolean isInArea = AreaUtil.isInArea(area, device.getLongitude(), device.getLatitude()); // 是否在运营区内
|
|
||||||
boolean isInAreaMin = AreaUtil.isInAreaMin(area, device.getLongitude(), device.getLatitude()); // 是否在运营区最小内边界
|
|
||||||
// 一次警告
|
// 一次警告
|
||||||
|
log.info("车辆MAC:{},定位:{},{}。是否在运营区内:{},是否在运营区最小内边界:{},是否在运营区最大外边界:{}", device.getMac(), device.getLongitude(), device.getLatitude(), isInArea, isInAreaMin, isInAreaMax);
|
||||||
if (isInArea && !isInAreaMin) {
|
if (isInArea && !isInAreaMin) {
|
||||||
deviceIotService.play(device, IotConstants.PLAY_BOUNDARY_NEAR, "靠近运营区内边界");
|
deviceIotService.play(device, IotConstants.PLAY_BOUNDARY_NEAR, "靠近运营区内边界");
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -199,10 +200,7 @@ public class IotReceiveServiceImpl implements IotReceiveService {
|
||||||
}
|
}
|
||||||
|
|
||||||
// 靠近禁行区,播报语音警告
|
// 靠近禁行区,播报语音警告
|
||||||
BigDecimal boundaryDistance = area.getBoundaryDistance();// 靠近运营区边界时的播报距离
|
if (isNearNoRidingArea) {
|
||||||
AreaSubVO nearAreaSub = AreaSubUtil.getNearAreaSub(noRidingList, device.getLongitude(), device.getLatitude(), boundaryDistance);
|
|
||||||
boolean isNearyNoRidingArea = nearAreaSub != null;
|
|
||||||
if (isNearyNoRidingArea) {
|
|
||||||
deviceIotService.play(device, IotConstants.PLAY_BOUNDARY_NEAR, "靠近禁行区");
|
deviceIotService.play(device, IotConstants.PLAY_BOUNDARY_NEAR, "靠近禁行区");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.ruoyi.web.bst;
|
package com.ruoyi.web.bst;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
@ -156,4 +157,17 @@ public class AreaController extends BaseController
|
||||||
}
|
}
|
||||||
return toAjax(areaService.logicDel(ids));
|
return toAjax(areaService.logicDel(ids));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取定位所属区域信息(Debug)
|
||||||
|
* @param lon 经度
|
||||||
|
* @param lat 纬度
|
||||||
|
* @param areaId 运营区ID
|
||||||
|
* @return 定位所属区域信息
|
||||||
|
*/
|
||||||
|
@PreAuthorize("@ss.hasPermi('bst:area:locationArea')")
|
||||||
|
@GetMapping("/locationArea")
|
||||||
|
public AjaxResult locationArea(BigDecimal lon, BigDecimal lat, Long areaId) {
|
||||||
|
return success(areaService.selectLocationArea(lon, lat, areaId));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user