20260307:地图规范化

This commit is contained in:
George 2026-03-07 22:36:25 +08:00
parent c707b0018c
commit 41543cc5a5
10 changed files with 200 additions and 78 deletions

View File

@ -155,3 +155,6 @@ swagger:
enabled: true # 是否开启swagger
pathMapping: /dev-api # 请求前缀
# 地图配置
map:
provider: baidu

View File

@ -153,3 +153,7 @@ logging:
swagger:
enabled: true # 是否开启swagger
pathMapping: /prod-api # 请求前缀
# 地图配置
map:
provider: baidu

View File

@ -29,8 +29,8 @@ public class ForestExampleController {
@GetMapping("/amap/location2")
public Map amapLocation2(@RequestParam BigDecimal longitude, @RequestParam BigDecimal latitude) {
Coordinate coordinate = new Coordinate(
longitude.toEngineeringString(),
latitude.toEngineeringString());
new BigDecimal(longitude.toEngineeringString()),
new BigDecimal(latitude.toEngineeringString()));
Map result = amap.getLocation(coordinate);
return result;
}
@ -38,8 +38,8 @@ public class ForestExampleController {
@GetMapping("/amap/location3")
public Map amapLocation3(@RequestParam BigDecimal longitude, @RequestParam BigDecimal latitude) {
Coordinate coordinate = new Coordinate(
longitude.toEngineeringString(),
latitude.toEngineeringString());
new BigDecimal(longitude.toEngineeringString()),
new BigDecimal(latitude.toEngineeringString()));
Map result = amap.getLocationByCoordinate(coordinate);
return result;
}

View File

@ -0,0 +1,62 @@
package com.fastbee.http.map;
import com.alibaba.fastjson2.JSONObject;
import com.fastbee.common.constant.Constants;
import com.fastbee.common.exception.ServerException;
import com.fastbee.common.utils.http.HttpUtils;
import com.fastbee.http.model.Coordinate;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
/**
* @description: 百度地图API接口服务
*
* @author Sumuxi
* @date 2026/3/7
*/
@Slf4j
@Service("baiduLocationService")
public class BaiduLocationService implements LocationService {
@Value("${other.baidu_ak}")
private String baiduAK;
interface API {
String BAIDU_URL = "http://api.map.baidu.com";
String geocoding = "/geocoding/v3/";
}
/**
* 根据结构化地址获取地理编码(即经纬度)
* 地理编码服务提供将结构化地址数据(如:北京市海淀区上地十街十号)转换为对应坐标点(经纬度)功能。
* @param address 地址
* @return 经纬度对象
*/
@Override
public Coordinate getCoordinateByAddress(String address) {
String baseUri = API.BAIDU_URL + API.geocoding;
address = StringUtils.isEmpty(address) ? "湖南省长沙市岳麓区" : address;
String encodedAddress;
try {
encodedAddress = URLEncoder.encode(address, StandardCharsets.UTF_8.toString());
} catch (UnsupportedEncodingException e) {
throw new ServerException(100001, "地理编码异常");
}
String baiduResponse = HttpUtils.sendGet(baseUri, "address=" + encodedAddress + "&output=json&ak=" + baiduAK, Constants.UTF8);
if (!StringUtils.isEmpty(baiduResponse)) {
JSONObject baiduObject = JSONObject.parseObject(baiduResponse);
JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location");
log.info("设置经度:{},设置纬度:{}", location.getBigDecimal("lng"), location.getBigDecimal("lat"));
return new Coordinate(location.getBigDecimal("lng"), location.getBigDecimal("lat"));
}
return null;
}
}

View File

@ -0,0 +1,26 @@
package com.fastbee.http.map;
import com.fastbee.http.model.Coordinate;
/**
* @description: 地理位置服务接口
*
* @author Sumuxi
* @date 2026/3/7
*/
public interface LocationService {
/**
* 根据地址获取经纬度坐标
* @param address 详细地址
* @return 经纬度对象
*/
Coordinate getCoordinateByAddress(String address);
/**
* 根据经纬度获取详细地址
* @param coordinate 经纬度
* @return 详细地址信息
*/
//AddressInfo getAddressByCoordinate(Coordinate coordinate);
}

View File

@ -0,0 +1,40 @@
package com.fastbee.http.map;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @description: 地图工厂
*
* @author Sumuxi
* @date 2026/3/7
*/
@Component
public class LocationServiceFactory {
@Resource
private LocationService baiduLocationService;
// @Resource
// private LocationService gaodeLocationService;
// 从配置文件读取当前使用的服务商
@Value("${map.provider:baidu}")
private String provider;
/**
* 获取当前配置的 LocationService 实例
* @return 具体服务实现
*/
public LocationService getLocationService() {
// if ("gaode".equalsIgnoreCase(provider)) {
// return gaodeLocationService;
// } else if ("tencent".equalsIgnoreCase(provider)) {
// return tencentLocationService;
// }
// 默认返回百度
return baiduLocationService;
}
}

View File

@ -1,34 +1,30 @@
package com.fastbee.http.model;
package com.fastbee.http.model;/**
* @description: 地理位置坐标
* @author Sumuxi
* @date 2026/3/7
*/
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author gongjun
* @since 2016-06-01
* @description: 地理位置坐标
*
* @author Sumuxi
* @date 2026/3/7
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Coordinate {
private String longitude;
@ApiModelProperty("经度")
private BigDecimal longitude;
private String latitude;
public Coordinate(String longitude, String latitude) {
this.longitude = longitude;
this.latitude = latitude;
}
public String getLongitude() {
return longitude;
}
public void setLongitude(String longitude) {
this.longitude = longitude;
}
public String getLatitude() {
return latitude;
}
public void setLatitude(String latitude) {
this.latitude = latitude;
}
@ApiModelProperty("纬度")
private BigDecimal latitude;
}

View File

@ -1,7 +1,6 @@
package com.fastbee.iot.service.impl;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
@ -28,6 +27,9 @@ import com.fastbee.common.utils.StringUtils;
import com.fastbee.common.utils.http.HttpUtils;
import com.fastbee.common.utils.ip.IpUtils;
import com.fastbee.common.utils.json.JsonUtils;
import com.fastbee.http.map.LocationService;
import com.fastbee.http.map.LocationServiceFactory;
import com.fastbee.http.model.Coordinate;
import com.fastbee.iot.cache.IDeviceCache;
import com.fastbee.iot.cache.ITSLCache;
import com.fastbee.iot.cache.ITSLValueCache;
@ -57,7 +59,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.cache.annotation.Caching;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Lazy;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
@ -65,11 +66,7 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import javax.annotation.Resource;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@ -90,8 +87,6 @@ public class DeviceServiceImpl implements IDeviceService {
private static final Logger log = LoggerFactory.getLogger(DeviceServiceImpl.class);
@Value("${server.broker.port}")
private Long brokerPort;
@Value("${other.baidu_ak}")
private String baiduAK;
@Autowired
private ITSLCache itslCache;
@Autowired
@ -130,6 +125,9 @@ public class DeviceServiceImpl implements IDeviceService {
@Lazy
private IDataRepairService dataRepairService;
@Resource
private LocationServiceFactory locationServiceFactory;
@Resource
private EventLogMapper eventLogMapper;
@Resource
@ -371,11 +369,11 @@ public class DeviceServiceImpl implements IDeviceService {
}
Long[] shareSceneIds = null;
List<DeviceShare> deviceShares = deviceShareService.selectDeviceShareByDeviceId(deviceId);
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(deviceShares)) {
if (!CollectionUtils.isEmpty(deviceShares)) {
List<Long> userIdList = deviceShares.stream().map(DeviceShare::getUserId).collect(Collectors.toList());
userIdSceneList.addAll(userIdList);
}
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(userIdSceneList)) {
if (!CollectionUtils.isEmpty(userIdSceneList)) {
shareSceneIds = sceneDeviceMapper.listSceneIdByDeviceIdAndUserId(device.getSerialNumber(), userIdSceneList);
}
if (isGeneralUser) {
@ -847,7 +845,7 @@ public class DeviceServiceImpl implements IDeviceService {
} else {
serialNumberList = list.stream().map(DeviceShortOutput::getSerialNumber).collect(Collectors.toList());
}
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(serialNumberList)) {
if (!CollectionUtils.isEmpty(serialNumberList)) {
List<DeviceAlertCount> alist = alertLogService.selectDeviceAlertCount(serialNumberList);
for (DeviceAlertCount item : alist) {
list.stream()
@ -1126,8 +1124,8 @@ public class DeviceServiceImpl implements IDeviceService {
}
}
} else if (DeviceType.GATEWAY.getCode() == device.getDeviceType()) {
LambdaQueryWrapper<ProductSubGateway> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(ProductSubGateway::getGwProductId, product.getProductId());
// LambdaQueryWrapper<ProductSubGateway> queryWrapper = new LambdaQueryWrapper<>();
// queryWrapper.eq(ProductSubGateway::getGwProductId, product.getProductId());
// 处理子设备添加和子设备轮询
ProductSubGateway productSubGateway = new ProductSubGateway();
productSubGateway.setGwProductId(product.getProductId());
@ -1138,9 +1136,9 @@ public class DeviceServiceImpl implements IDeviceService {
productSubGatewayList.sort(Comparator.comparing(ProductSubGatewayVO::getSlaveId));
List<Long> subProductIdList = productSubGatewayList.stream().map(ProductSubGatewayVO::getSubProductId)
.collect(Collectors.toList());
LambdaQueryWrapper<ProductModbusJob> queryWrapper1 = new LambdaQueryWrapper<>();
queryWrapper1.in(ProductModbusJob::getProductId, subProductIdList);
List<ProductModbusJob> productModbusJobList = productModbusJobMapper.selectList(queryWrapper1);
LambdaQueryWrapper<ProductModbusJob> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.in(ProductModbusJob::getProductId, subProductIdList);
List<ProductModbusJob> productModbusJobList = productModbusJobMapper.selectList(queryWrapper);
Map<Long, List<ProductModbusJob>> productModbusJobMap = productModbusJobList.stream()
.collect(Collectors.groupingBy(ProductModbusJob::getProductId));
// 新增子设备、绑定子设备、子设备生成轮询
@ -1171,7 +1169,7 @@ public class DeviceServiceImpl implements IDeviceService {
subGatewayMapper.insertGateway(subGateway);
List<ProductModbusJob> productModbusList = productModbusJobMap
.get(productSubGatewayVO.getSubProductId());
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(productModbusList)) {
if (!CollectionUtils.isEmpty(productModbusList)) {
for (ProductModbusJob productModbusJob : productModbusList) {
ModbusJob modbusJob = new ModbusJob();
modbusJob.setJobName(productModbusJob.getJobName());
@ -1590,36 +1588,18 @@ public class DeviceServiceImpl implements IDeviceService {
if (!StringUtils.isEmpty(rspStr)) {
JSONObject obj = JSONObject.parseObject(rspStr);
device.setNetworkAddress(obj.getString("addr"));
System.out.println(device.getSerialNumber() + "- 设置地址:" + obj.getString("addr"));
log.info("{}- 设置地址:{}", device.getSerialNumber(), obj.getString("addr"));
// 查询经纬度
setLatitudeAndLongitude(obj.getString("city"), device);
LocationService service = locationServiceFactory.getLocationService();
Coordinate coordinate = service.getCoordinateByAddress(obj.getString("city"));
device.setLongitude(coordinate.getLongitude());
device.setLatitude(coordinate.getLatitude());
}
} catch (Exception e) {
log.error(e.getMessage());
}
}
/**
* 设置经纬度
*
* @param city
*/
private void setLatitudeAndLongitude(String city, Device device) throws UnsupportedEncodingException {
String BAIDU_URL = "http://api.map.baidu.com/geocoding/v3/";
city = StrUtil.isEmpty(city) ? "湖南省长沙市岳麓区" : city;
String encodedAddress = URLEncoder.encode(city, StandardCharsets.UTF_8.toString());
String baiduResponse = HttpUtils.sendGet(BAIDU_URL, "address=" + encodedAddress + "&output=json&ak=" + baiduAK,
Constants.UTF8);
if (!StringUtils.isEmpty(baiduResponse)) {
JSONObject baiduObject = JSONObject.parseObject(baiduResponse);
JSONObject location = baiduObject.getJSONObject("result").getJSONObject("location");
device.setLongitude(location.getBigDecimal("lng"));
device.setLatitude(location.getBigDecimal("lat"));
System.out.println(device.getSerialNumber() + "- 设置经度:" + location.getBigDecimal("lng") + ",设置纬度:"
+ location.getBigDecimal("lat"));
}
}
/**
* 根据产品ID获取产品下所有编号
*
@ -1652,7 +1632,7 @@ public class DeviceServiceImpl implements IDeviceService {
List<String> serialNumberList = deviceImportVOList.stream().map(DeviceImportVO::getSerialNumber)
.collect(Collectors.toList());
List<String> oldSerialNumberList = deviceMapper.checkExistBySerialNumbers(serialNumberList);
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(oldSerialNumberList)) {
if (!CollectionUtils.isEmpty(oldSerialNumberList)) {
return "以下设备编号(" + JSON.toJSONString(oldSerialNumberList) + ")已存在,请修改后重试";
}
List<Device> deviceList = new ArrayList<>();
@ -1705,7 +1685,7 @@ public class DeviceServiceImpl implements IDeviceService {
List<String> serialNumberList = deviceAssignmentVOS.stream().map(DeviceAssignmentVO::getSerialNumber)
.collect(Collectors.toList());
List<String> oldSerialNumberList = deviceMapper.checkExistBySerialNumbers(serialNumberList);
if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(oldSerialNumberList)) {
if (!CollectionUtils.isEmpty(oldSerialNumberList)) {
return "以下设备编号(" + JSON.toJSONString(oldSerialNumberList) + ")已存在,请修改后重试";
}
SysDept sysDept = sysDeptMapper.selectDeptById(deptId);

View File

@ -129,8 +129,8 @@ public class ProductServiceImpl implements IProductService {
@Transactional
public AjaxResult deleteProductByProductIds(Long[] productIds) {
// 删除物模型JSON缓存
for (int i = 0; i < productIds.length; i++) {
String key = RedisKeyBuilder.buildTSLCacheKey(productIds[i]);
for (Long productId : productIds) {
String key = RedisKeyBuilder.buildTSLCacheKey(productId);
redisCache.deleteObject(key);
}
// 产品下不能有固件

View File

@ -21,9 +21,20 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
</sql>
<select id="selectListVO" resultType="com.fastbee.iot.model.gateWay.ProductSubGatewayVO">
select ps.id, ps.gw_product_id, ps.sub_product_id, ps.slave_id, ps.create_by, ps.create_time, ps.update_by, ps.update_time, ps.remark, ps.create_time,
p.product_name subProductName, p.location_way subLocationWay
from iot_product_sub_gateway ps left join iot_product p on ps.sub_product_id = p.product_id
select ps.id,
ps.gw_product_id,
ps.sub_product_id,
ps.slave_id,
ps.create_by,
ps.create_time,
ps.update_by,
ps.update_time,
ps.remark,
ps.create_time,
p.product_name subProductName,
p.location_way subLocationWay
from iot_product_sub_gateway ps
left join iot_product p on ps.sub_product_id = p.product_id
where ps.gw_product_id = #{gwProductId}
order by create_time
</select>