package com.xzx.gc.common.utils.gdmap;
|
|
import cn.hutool.core.bean.BeanUtil;
|
import cn.hutool.core.collection.CollUtil;
|
import cn.hutool.core.convert.Convert;
|
import cn.hutool.core.util.RandomUtil;
|
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.http.HttpUtil;
|
import cn.hutool.json.JSONArray;
|
import cn.hutool.json.JSONObject;
|
import cn.hutool.json.JSONUtil;
|
import com.github.pagehelper.PageInfo;
|
import com.xzx.gc.common.Result;
|
import com.xzx.gc.common.constant.Constants;
|
import com.xzx.gc.common.dto.gdmap.*;
|
import com.xzx.gc.common.utils.BusinessUtil;
|
import com.xzx.gc.entity.AddressInfo;
|
import com.xzx.gc.model.dto.GdAreaDto;
|
import lombok.experimental.UtilityClass;
|
import lombok.extern.slf4j.Slf4j;
|
|
import java.util.ArrayList;
|
import java.util.HashMap;
|
import java.util.List;
|
import java.util.Map;
|
|
@UtilityClass
|
@Slf4j
|
public class GdMapUtil {
|
|
|
//逆地理编码URL
|
private static final String REVERSE_GEOCODING="https://restapi.amap.com/v3/geocode/regeo";
|
//地理编码URL
|
private static final String GEOCODING="https://restapi.amap.com/v3/geocode/geo";
|
//电子围栏
|
private static final String FENCE_URL="https://restapi.amap.com/v4/geofence/meta?key=";
|
private static final String FENCE_STATUS_URL="https://restapi.amap.com/v4/geofence/status";
|
//poi
|
private static final String POI_URL="https://restapi.amap.com/v3/place/text";
|
//行政区域查询
|
private static final String ACODE_URL="https://restapi.amap.com/v3/config/district";
|
//周边搜索
|
private static final String AROUND_URL="https://restapi.amap.com/v3/place/around";
|
|
//小区POI
|
public static final String HOUSE_POI="120300";
|
|
|
/**
|
* 地理编码:将地址转成经纬度
|
*/
|
public Result getLocationByAddress( GdGEODto gdReverseGEODto){
|
Result result=new Result();
|
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(gdReverseGEODto);
|
String s = HttpUtil.get(GEOCODING, stringObjectMap);
|
JSONObject jsonObject = JSONUtil.parseObj(s);
|
if(Constants.FAIL.equals(jsonObject.getStr("status"))){
|
result.setCode(-1);
|
result.setMsg(jsonObject.getStr("info"));
|
log.error("地理编码失败,原因:{},key:{}",result.getMsg(),gdReverseGEODto.getKey());
|
}else{
|
JSONArray regeocode = jsonObject.getJSONArray("geocodes");
|
if(regeocode!=null&®eocode.size()>0){
|
JSONObject jsonObject1= (JSONObject) regeocode.get(0);
|
String location = jsonObject1.getStr("location");
|
result.setData(location);
|
}
|
log.info("地理编码成功,结果:{}",result.getData());
|
}
|
return result;
|
}
|
|
/**
|
* 批量查询
|
* @param gdReverseGEODto
|
* @return
|
*/
|
public Result getBatchAreaInfo(GdReverseGEODto gdReverseGEODto){
|
Result result=new Result();
|
gdReverseGEODto.setBatch(true);
|
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(gdReverseGEODto);
|
String s;
|
try {
|
s = HttpUtil.get(REVERSE_GEOCODING, stringObjectMap);
|
} catch (Exception e) {
|
log.error("逆地理编码失败,原因:{},key:{}",e.getMessage(),gdReverseGEODto.getKey());
|
return Result.error(-1,"获取位置失败");
|
}
|
JSONObject jsonObject = JSONUtil.parseObj(s);
|
if(Constants.FAIL.equals(jsonObject.getStr("status"))){
|
result.setCode(-1);
|
result.setMsg(jsonObject.getStr("info"));
|
log.error("逆地理编码失败,原因:{},key:{}",result.getMsg(),gdReverseGEODto.getKey());
|
}else{
|
JSONArray regeocodes = jsonObject.getJSONArray("regeocodes");
|
result.setData(regeocodes);
|
|
}
|
return result;
|
}
|
/**
|
* 逆地理编码:将经纬度转换为详细结构化的地址,且返回附近周边的POI、AOI信息。
|
* @param gdReverseGEODto 逆编码实体
|
* @param level 层级 1查询省 2 查询市 3查询区信息 0查询所有
|
*/
|
public Result getAreaInfo(GdReverseGEODto gdReverseGEODto, int level){
|
Result result=new Result();
|
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(gdReverseGEODto);
|
String s = null;
|
try {
|
s = HttpUtil.get(REVERSE_GEOCODING, stringObjectMap);
|
} catch (Exception e) {
|
log.error("逆地理编码失败,原因:{},key:{}",e.getMessage(),gdReverseGEODto.getKey());
|
return Result.error(-1,"获取位置失败");
|
}
|
JSONObject jsonObject = JSONUtil.parseObj(s);
|
if(Constants.FAIL.equals(jsonObject.getStr("status"))){
|
result.setCode(-1);
|
result.setMsg(jsonObject.getStr("info"));
|
log.error("逆地理编码失败,原因:{},key:{}",result.getMsg(),gdReverseGEODto.getKey());
|
}else{
|
JSONObject regeocode = jsonObject.getJSONObject("regeocode");
|
//结构化地址信息包括:省份+城市+区县+城镇+乡村+街道+门牌号码
|
String address = regeocode.getStr("formatted_address");
|
JSONObject addressComponent = regeocode.getJSONObject("addressComponent");
|
String district = addressComponent.getStr("district");
|
String city = addressComponent.getStr("city");
|
String province = addressComponent.getStr("province");
|
String citycode = addressComponent.getStr("citycode");
|
String adcode = addressComponent.getStr("adcode");
|
if(Convert.toInt(3)==level){
|
result.setData(district);
|
}else if(Convert.toInt(2)==level){
|
result.setData(city);
|
}else if(Convert.toInt(1)==level){
|
result.setData(province);
|
}else {
|
AddressInfo addressInfo=new AddressInfo();
|
addressInfo.setProvinceName(province);
|
addressInfo.setTownshipName(district);
|
addressInfo.setCityName(city);
|
addressInfo.setCitycode(citycode);
|
addressInfo.setAdcode(adcode);
|
addressInfo.setFormatAddress(address);
|
addressInfo.setLongitude(gdReverseGEODto.getLocation().split(",")[0]);
|
addressInfo.setLatitude(gdReverseGEODto.getLocation().split(",")[1]);
|
result.setData(addressInfo);
|
}
|
// log.info("逆地理编码成功,结果:{}",result.getData());
|
}
|
return result;
|
}
|
|
/**
|
* 根据关键字搜索
|
*/
|
public AddressInfo getLocationByPOI(GdPOIDto gdPOIDto,AddressInfo addressInfo){
|
if(StrUtil.isNotBlank(addressInfo.getAdcode())){
|
gdPOIDto.setCity(addressInfo.getAdcode());
|
}else if(StrUtil.isNotBlank(addressInfo.getCitycode())){
|
gdPOIDto.setCity(addressInfo.getCitycode());
|
}else if(StrUtil.isNotBlank(addressInfo.getCityName())){
|
gdPOIDto.setCity(addressInfo.getCityName());
|
}else{
|
gdPOIDto.setCity(Constants.CHANGSHA_CODE);
|
}
|
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(gdPOIDto);
|
String s = null;
|
try {
|
s = HttpUtil.get(POI_URL, stringObjectMap);
|
} catch (Exception e) {
|
log.error("地理关键字搜索失败,原因:{},key:{}",e.getMessage(),gdPOIDto.getKey());
|
return addressInfo;
|
}
|
JSONObject jsonObject = JSONUtil.parseObj(s);
|
if(Constants.FAIL.equals(jsonObject.getStr("status"))){
|
String msg=jsonObject.getStr("info");
|
log.error("地理关键字搜索失败,原因:{},key:{}",msg,gdPOIDto.getKey());
|
}else{
|
JSONArray regeocode = jsonObject.getJSONArray("pois");
|
if(regeocode!=null&®eocode.size()>0){
|
JSONObject jsonObject1= (JSONObject) regeocode.get(0);
|
String data = jsonObject1.getStr("location");
|
if(StrUtil.isNotBlank(data)) {
|
// String[] split = data.split(",");
|
// addressInfo.setLongitude( NumberUtil.roundStr(split[0],6,RoundingMode.DOWN));
|
// addressInfo.setLatitude( NumberUtil.roundStr(split[1],6,RoundingMode.DOWN));
|
}
|
String pcode = jsonObject1.getStr("pcode");
|
addressInfo.setPcode(pcode);
|
String pname =jsonObject1.getStr("pname");
|
addressInfo.setProvinceName(pname);
|
String citycode =jsonObject1.getStr("citycode");
|
addressInfo.setCitycode(citycode);
|
String cityname =jsonObject1.getStr("cityname");
|
addressInfo.setCityName(cityname);
|
String adcode = jsonObject1.getStr("adcode");
|
addressInfo.setAdcode(adcode);
|
String adname = jsonObject1.getStr("adname");
|
adname=new BusinessUtil().changeArea(adname);
|
addressInfo.setTownshipName(adname);
|
log.info("地理关键字搜索成功,关键字:{},结果:{}",gdPOIDto.getKeywords(),jsonObject1);
|
}else {
|
log.error("地理关键字搜索失败,:{}",gdPOIDto.getKeywords());
|
}
|
|
}
|
return addressInfo;
|
}
|
|
|
/**
|
* 创建围栏
|
* @param createFenceDto
|
* @return
|
*/
|
public Result<String> createFence(String key,CreateFenceDto createFenceDto){
|
Result result=new Result();
|
String post = HttpUtil.post(FENCE_URL+key, JSONUtil.toJsonStr(createFenceDto));
|
JSONObject jsonObject = JSONUtil.parseObj(post);
|
Integer errcode = jsonObject.getInt("errcode");
|
String errmsg = jsonObject.getStr("errmsg");
|
if(errcode.intValue()==0){
|
JSONObject data = jsonObject.getJSONObject("data");
|
String status = data.getStr("status");
|
String message = data.getStr("message");
|
if(Constants.DEL_NOT_FLAG== Convert.toInt(status)){
|
String gid = data.getStr("gid");
|
result.setData(gid);
|
result.setCode(0);
|
log.info("电子围栏创建成功,ID:{}",gid);
|
}else{
|
result.setCode(Convert.toInt(status));
|
result.setMsg(message);
|
log.error("电子围栏创建失败,原因:{}",message);
|
}
|
}else{
|
result.setCode(errcode);
|
result.setMsg(errmsg);
|
log.error("电子围栏创建失败,原因:{}",errmsg);
|
}
|
return result;
|
}
|
|
|
/**
|
* 更新围栏
|
* @param createFenceDto
|
* @return
|
*/
|
public Result<String> updateFence(CreateFenceDto createFenceDto,String key,String gid){
|
Result result=new Result();
|
String post = HttpUtil.post(FENCE_URL+key+"&gid="+gid+"&method=patch", JSONUtil.toJsonStr(createFenceDto));
|
JSONObject jsonObject = JSONUtil.parseObj(post);
|
Integer errcode = jsonObject.getInt("errcode");
|
String errmsg = jsonObject.getStr("errmsg");
|
if(errcode.intValue()==0){
|
JSONObject data = jsonObject.getJSONObject("data");
|
String status = data.getStr("status");
|
String message = data.getStr("message");
|
if(Constants.DEL_NOT_FLAG== Convert.toInt(status)){
|
result.setCode(0);
|
result.setData(gid);
|
log.info("电子围栏更新成功,ID:{}",gid);
|
|
}else{
|
result.setCode(Convert.toInt(status));
|
result.setMsg(message);
|
log.error("电子围栏更新失败,原因:{}",message);
|
}
|
}else{
|
result.setCode(errcode);
|
result.setMsg(errmsg);
|
log.error("电子围栏更新失败,原因:{}",errmsg);
|
}
|
return result;
|
}
|
|
|
/**
|
* 根据id或名字(非中文)查询围栏 都不传 则查询所有
|
* @param name 围栏名字
|
* @param gid 围栏Id
|
* @return
|
*/
|
public Result<JSONArray> findFence(String key,String gid,String name){
|
Result result=new Result();
|
Map<String,Object> map=new HashMap<>();
|
if(StrUtil.isNotBlank(gid)) {
|
map.put("gid",gid);
|
}else{
|
map.put("name", name);
|
}
|
String post = HttpUtil.get(FENCE_URL+key,map);
|
JSONObject jsonObject = JSONUtil.parseObj(post);
|
Integer errcode = jsonObject.getInt("errcode");
|
String errmsg = jsonObject.getStr("errmsg");
|
if(errcode.intValue()==0){
|
//成功
|
JSONObject data = jsonObject.getJSONObject("data");
|
//围栏ID
|
JSONArray jsonArray = data.getJSONArray("rs_list");
|
if(jsonArray.size()>0) {
|
for (Object o : jsonArray) {
|
JSONObject jsonObject1 = JSONUtil.parseObj(o);
|
String relGid = jsonObject1.getStr("gid");
|
String relName = jsonObject1.getStr("name");
|
String points = jsonObject1.getStr("points");
|
log.info("电子围栏查询成功,名字:{},gid:{}", relName,relGid);
|
}
|
result.setData(jsonArray);
|
result.setCode(0);
|
}else{
|
result.setCode(-1);
|
log.info("电子围栏不存在,名字:{},gid:{}", name,gid);
|
}
|
}else{
|
result.setCode(errcode);
|
result.setMsg(errmsg);
|
log.error("电子围栏查询失败,原因:{},key:{}",errmsg,key);
|
}
|
return result;
|
}
|
|
|
/**
|
* 查询设备是否存在围栏内
|
* @param location 数据为坐标数据和坐标产生的时间戳数据,至少包含一个坐标对和时间戳。
|
*
|
* 1、传入1个点时,直接判断交互关系。
|
*
|
* 2、当传入多个点时,可以通过前后时间判断动态交互关系。
|
*
|
* 格式: x1,y1,unix_ts1;x2,y2,unix_ts2
|
*
|
* 动态交互判断方法:第一个点作为当前时间的点,然后从其余点中选出在当前点之前10s~1小时范围内的最早点,用这两个时间点的位置判断设备与围栏的动态交互关系。若数据无效交互关系默认返回leave。
|
*
|
* @param diu 设备唯一标识符,作为记录依据,不影响判断结果。Android设备一般使用imei号码,iOS一般使用idfv号,其余设备可根据业务自定义。
|
* 大于13位小于16位(13<diu<16)
|
* @return
|
*/
|
public Result isInFence(String location,String diu,String key){
|
Result result=new Result();
|
Map<String,Object> map=new HashMap<>();
|
map.put("key",key);
|
map.put("locations",location);
|
map.put("diu",diu);
|
String post = HttpUtil.get(FENCE_STATUS_URL,map);
|
JSONObject jsonObject = JSONUtil.parseObj(post);
|
Integer errcode = jsonObject.getInt("errcode");
|
String errmsg = jsonObject.getStr("errmsg");
|
if(errcode.intValue()==0){
|
//成功
|
JSONObject data = jsonObject.getJSONObject("data");
|
Integer status = data.getInt("status");
|
String message = data.getStr("message");
|
if(Constants.DEL_NOT_FLAG== Convert.toInt(status)){
|
//围栏ID
|
JSONArray jsonArray = data.getJSONArray("fencing_event_list");
|
//围栏距离设备的距离,没有命中围栏时返回。单位:米
|
Double nearestFenceDistance = data.getDouble("nearest_fence_distance");
|
String nearestFenceGid = data.getStr("nearest_fence_gid");
|
if (jsonArray.size() > 0) {
|
for (Object o : jsonArray) {
|
JSONObject jsonObject1 = JSONUtil.parseObj(jsonArray.get(0));
|
String client_status = jsonObject1.getStr("client_status");
|
JSONObject fenceInfo = jsonObject1.getJSONObject("fence_info");
|
String fenceGid = fenceInfo.getStr("fence_gid");
|
String fenceName = fenceInfo.getStr("fence_name");
|
if ("in".equals(client_status)) {
|
result.setCode(0);
|
result.setData(fenceGid);
|
log.debug("电子围栏监控成功,状态:{},命中的围栏ID:{},围栏名称:{}", client_status,fenceGid,fenceName);
|
break;
|
} else {
|
result.setCode(-1);
|
}
|
}
|
} else {
|
result.setCode(-1);
|
log.debug("电子围栏未监控到此设备,坐标:{},最近的围栏:{},相差:{} 米", location,nearestFenceGid,nearestFenceDistance);
|
}
|
}else{
|
result.setCode(status);
|
result.setMsg(message);
|
log.error("电子围栏监控失败,原因:{},key:{}", message,key);
|
}
|
}else{
|
result.setCode(errcode);
|
result.setMsg(errmsg);
|
log.error("电子围栏监控失败,原因:{},key:{}",errmsg,key);
|
}
|
return result;
|
}
|
/**
|
* 删除围栏
|
* @param gid
|
* @return
|
*/
|
public Result deleteFence(String key,String gid){
|
Result result=new Result();
|
String post = HttpUtil.post(FENCE_URL+key+"&gid="+gid+"&method=delete", "{}");
|
JSONObject jsonObject = JSONUtil.parseObj(post);
|
Integer errcode = jsonObject.getInt("errcode");
|
String errmsg = jsonObject.getStr("errmsg");
|
if(errcode.intValue()==0){
|
//成功
|
JSONObject data = jsonObject.getJSONObject("data");
|
String message = data.getStr("message");
|
String status = data.getStr("status");
|
if(Constants.DEL_NOT_FLAG== Convert.toInt(status)){
|
result.setCode(0);
|
log.info("电子围栏删除成功,ID:{}",gid);
|
}else{
|
result.setCode(Convert.toInt(status));
|
result.setMsg(message);
|
log.error("电子围栏删除失败,原因:{}",message);
|
}
|
}else{
|
result.setCode(errcode);
|
result.setMsg(errmsg);
|
log.error("电子围栏删除失败,原因:{}",errmsg);
|
}
|
return result;
|
}
|
|
|
/**
|
* 获取设备标识 15位 Android设备一般使用imei号码,iOS一般使用idfv号
|
* @param diu
|
* @return
|
*/
|
public String getDiu(String diu){
|
if(StrUtil.isBlank(diu)){
|
return RandomUtil.randomString(15);
|
}else {
|
if (diu.length() > 15) {
|
return StrUtil.subWithLength(diu, 0, 15);
|
} else if(diu.length()<15){
|
return StrUtil.fill(diu, Convert.toChar("0"), 15, false);
|
}else{
|
return diu;
|
}
|
}
|
}
|
|
|
/**
|
* 行政区域查询
|
* @param keyword
|
* @return
|
*/
|
public Result<List<GdAreaDto>> findByAreaName(String keyword){
|
Map<String,Object> map=new HashMap<>();
|
map.put("key",Constants.GD_MAP_KEY);
|
map.put("keywords",keyword);
|
map.put("subdistrict",0);
|
String result = HttpUtil.get(ACODE_URL,map);
|
JSONObject jsonObject = JSONUtil.parseObj(result);
|
Integer status = jsonObject.getInt("status");
|
String info = jsonObject.getStr("info");
|
List<GdAreaDto> list=CollUtil.newArrayList();
|
if(1==status.intValue()){
|
JSONArray districts = jsonObject.getJSONArray("districts");
|
if(districts.size()>0){
|
for (Object district : districts) {
|
JSONObject jsonObject1 = JSONUtil.parseObj(district);
|
String citycode = jsonObject1.getStr("citycode");
|
String adcode = jsonObject1.getStr("adcode");
|
GdAreaDto gdAreaDto=new GdAreaDto();
|
gdAreaDto.setAdcode(adcode);
|
gdAreaDto.setCitycode(citycode);
|
gdAreaDto.setName(keyword);
|
list.add(gdAreaDto);
|
}
|
}
|
return Result.success(list);
|
}else {
|
return Result.error("行政区域查询失败:"+info);
|
}
|
}
|
|
|
/**120302
|
* 查找周边
|
*/
|
public Result<PageInfo<GdAroundResDto>> findAroundPOI(GdAroundDto gdAroundDto){
|
Result result=new Result();
|
Map<String, Object> stringObjectMap = BeanUtil.beanToMap(gdAroundDto);
|
String s = HttpUtil.get(AROUND_URL, stringObjectMap);
|
JSONObject jsonObject = JSONUtil.parseObj(s);
|
if(Constants.FAIL.equals(jsonObject.getStr("status"))){
|
result.setCode(-1);
|
result.setMsg(jsonObject.getStr("info"));
|
log.error("搜索周边POI失败,原因:{},key:{}",result.getMsg(),gdAroundDto.getKey());
|
}else{
|
PageInfo<GdAroundResDto> pageInfo=new PageInfo<>();
|
pageInfo.setPageNum(gdAroundDto.getPage());
|
pageInfo.setPageSize(gdAroundDto.getOffset());
|
List<GdAroundResDto> list=new ArrayList<>();
|
JSONArray regeocode = jsonObject.getJSONArray("pois");
|
int count = jsonObject.getInt("count");
|
pageInfo.setTotal(count);
|
if(regeocode!=null&®eocode.size()>0){
|
for (Object o : regeocode) {
|
JSONObject jsonObject1= (JSONObject)o;
|
GdAroundResDto gdAroundResDto = BeanUtil.toBean(jsonObject1, GdAroundResDto.class);
|
list.add(gdAroundResDto);
|
}
|
pageInfo.setList(list);
|
}
|
result.setData(pageInfo);
|
log.info("搜索周边POI成功,结果:{}",result.getData());
|
}
|
return result;
|
}
|
|
public static void main(String[] args) {
|
// String gid="c5489f7f-ba0b-4b09-9e78-a447fc135db3";
|
// Result fence = GdMapUtil.findFence("b591ccdeaab2372d14dde1b0f1eed361", gid, null);
|
// if(fence.getCode()==0) {
|
// JSONArray data = (JSONArray) fence.getData();
|
// JSONObject jsonObject1 = JSONUtil.parseObj(data.get(0));
|
// //围栏所在地区adcode
|
// String adcode = jsonObject1.getStr("adcode");
|
// System.out.println(adcode);
|
// }
|
|
// Result result = findByAreaName("朝阳区");
|
// List<GdAreaDto> list = (List<GdAreaDto>) result.getData();
|
// System.out.println(list.size());
|
|
GdAroundDto gdAroundDto =new GdAroundDto();
|
gdAroundDto.setLocation("112.943809,28.132178");
|
gdAroundDto.setTypes("120300");
|
gdAroundDto.setExtensions("base");
|
// gdAroundDto.setPage(2);
|
// gdAroundDto.setOffset(25);
|
// gdAroundDto.setKeywords("西雅韵");
|
Result<PageInfo<GdAroundResDto>> aroundPOI = findAroundPOI(gdAroundDto);
|
PageInfo<GdAroundResDto> data = aroundPOI.getData();
|
System.out.println(data.getTotal());
|
List<GdAroundResDto> list = data.getList();
|
for (GdAroundResDto gdAroundResDto : list) {
|
System.out.println(gdAroundResDto.getName()+" "+gdAroundResDto.getType());
|
}
|
|
}
|
|
}
|