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 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 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 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 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 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 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 findFence(String key,String gid,String name){ Result result=new Result(); Map 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 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> findByAreaName(String keyword){ Map 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 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> findAroundPOI(GdAroundDto gdAroundDto){ Result result=new Result(); Map 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 pageInfo=new PageInfo<>(); pageInfo.setPageNum(gdAroundDto.getPage()); pageInfo.setPageSize(gdAroundDto.getOffset()); List 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 list = (List) 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> aroundPOI = findAroundPOI(gdAroundDto); PageInfo data = aroundPOI.getData(); System.out.println(data.getTotal()); List list = data.getList(); for (GdAroundResDto gdAroundResDto : list) { System.out.println(gdAroundResDto.getName()+" "+gdAroundResDto.getType()); } } }