+autonavi.BatchWalkingDistance

This commit is contained in:
gazebo
2019-10-18 12:02:14 +08:00
parent ef90a430ac
commit 629aa20fea
3 changed files with 162 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
package autonavi
import (
"bytes"
"crypto/md5"
"fmt"
"net/http"
@@ -12,8 +13,12 @@ import (
)
const (
signKey = "sig"
prodURL = "https://restapi.amap.com/v3"
signKey = "sig"
prodURL = "https://restapi.amap.com"
prodURLv3 = "/v3"
prodURLFullv3 = prodURL + prodURLv3
batchAPIStr = "batch"
)
const (
@@ -196,6 +201,16 @@ type RegeoCodeInfo struct {
Roads []*RoadInfo `json:"roads"`
}
type tBatchAPIParams struct {
APIStr string
APIParams map[string]interface{}
}
type tBatchAPIResponse struct {
Result ResponseResult
Err error
}
func New(key string, config ...*platformapi.APIConfig) *API {
curConfig := platformapi.DefAPIConfig
if len(config) > 0 {
@@ -236,7 +251,7 @@ func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal Re
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(prodURL, apiStr, params2), nil)
request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(prodURLFullv3, apiStr, params2), nil)
return request
},
a.config,
@@ -262,6 +277,74 @@ func (a *API) AccessAPI(apiStr string, params map[string]interface{}) (retVal Re
return retVal, err
}
func (a *API) BatchAccessAPI(apiList []*tBatchAPIParams) (retVal []*tBatchAPIResponse, err error) {
if len(apiList) == 0 {
return nil, nil
}
var ops []map[string]interface{}
for _, v := range apiList {
params2 := utils.MergeMaps(utils.Params2Map("key", a.key, "output", "json"), v.APIParams)
params2[signKey] = a.signParams(params2)
op := make(map[string]interface{})
op["url"] = utils.GenerateGetURL(prodURLv3, v.APIStr, params2)
ops = append(ops, op)
}
params2 := map[string]interface{}{
"ops": ops,
}
err = platformapi.AccessPlatformAPIWithRetry(a.client,
func() *http.Request {
request, _ := http.NewRequest(http.MethodGet, utils.GenerateGetURL(prodURLFullv3, batchAPIStr, utils.Params2Map("key", a.key)),
bytes.NewReader(utils.MustMarshal(params2)))
request.Header.Set("charset", "UTF-8")
request.Header.Set("Content-Type", "application/json")
return request
},
a.config,
func(response *http.Response, bodyStr string, jsonResult1 map[string]interface{}) (errLevel string, err error) {
if jsonResult1 == nil {
return platformapi.ErrLevelRecoverableErr, fmt.Errorf("mapData is nil")
}
if resultList, ok := jsonResult1[platformapi.KeyData].([]interface{}); ok {
for _, v := range resultList {
jsonResult1 := v.(map[string]interface{})
status := int(utils.ForceInterface2Int64(jsonResult1["status"]))
if status == http.StatusOK {
jsonResult1 := v.(map[string]interface{})["body"].(map[string]interface{})
var retVal2 map[string]interface{}
var err2 error
status := jsonResult1["status"].(string)
if status == StatusCodeSuccess {
retVal2 = jsonResult1
} else {
infoCode := jsonResult1["infocode"].(string)
err2 = utils.NewErrorCode(jsonResult1["info"].(string), infoCode)
}
retVal = append(retVal, &tBatchAPIResponse{
Result: retVal2,
Err: err2,
})
}
}
errLevel = platformapi.ErrLevelSuccess
} else {
infoCode := jsonResult1["infocode"].(string)
err = utils.NewErrorCode(jsonResult1["info"].(string), infoCode)
if _, ok := exceedLimitCodes[infoCode]; ok {
errLevel = platformapi.ErrLevelExceedLimit
} else if _, ok := canRetryCodes[infoCode]; ok {
errLevel = platformapi.ErrLevelRecoverableErr
} else {
errLevel = platformapi.ErrLevelCodeIsNotOK
}
}
return errLevel, err
})
return retVal, err
}
// 为了方便调用者编码,如果失败,也会返回未转换的原始值
func (a *API) CoordinateConvert(lng, lat float64, coordsys string) (retLng, retLat float64, err error) {
// outCoords, err := a.BatchCoordinateConvert([]*Coordinate{
@@ -484,3 +567,29 @@ func (a *API) WalkingDistance(lng1, lat1, lng2, lat2 float64) (distance float64)
}
return distance
}
func (a *API) BatchWalkingDistance(srcLng, srcLat float64, destCoords []*Coordinate) (distanceList []float64, err error) {
var reqList []*tBatchAPIParams
for _, v := range destCoords {
reqList = append(reqList, &tBatchAPIParams{
APIStr: "direction/walking",
APIParams: map[string]interface{}{
"origin": coordinate2String(srcLng, srcLat),
"destination": coordinate2String(v.Lng, v.Lat),
},
})
}
resultList, err := a.BatchAccessAPI(reqList)
if err == nil {
for _, v := range resultList {
distance := float64(9527123)
if v.Err == nil {
if paths, _ := v.Result["route"].(map[string]interface{})["paths"].([]interface{}); len(paths) > 0 {
distance = utils.Interface2Float64WithDefault(paths[0].(map[string]interface{})["distance"], 0)
}
}
distanceList = append(distanceList, distance)
}
}
return distanceList, err
}

View File

@@ -112,3 +112,40 @@ func TestGeoCodeRegeo(t *testing.T) {
}
t.Log(utils.Format4Output(result, false))
}
func TestBatchWalkingDistance(t *testing.T) {
result, err := autonaviAPI.BatchWalkingDistance(104.052756, 30.685203, []*Coordinate{
&Coordinate{
Lng: 104.052756,
Lat: 30.687203,
},
&Coordinate{
Lng: 104.032756,
Lat: 30.685203,
},
&Coordinate{
Lng: 104.032756,
Lat: 30.685203,
},
&Coordinate{
Lng: 104.032756,
Lat: 30.685203,
},
&Coordinate{
Lng: 104.032756,
Lat: 30.685203,
},
&Coordinate{
Lng: 104.032756,
Lat: 30.685203,
},
&Coordinate{
Lng: 104.032756,
Lat: 30.685203,
},
})
if err != nil {
t.Fatal(err)
}
t.Log(utils.Format4Output(result, false))
}

View File

@@ -24,6 +24,7 @@ const (
DefMaxRecoverableRetryCount = 1 // 可恢复类错误(一般指网络错),最大重试次数
KeyTrackInfo = "TrackInfo"
KeyData = "fakeData"
)
type APIRetryConfig struct {
@@ -147,6 +148,7 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
}
var (
errLevel string
bodyGeneral interface{}
bodyMap map[string]interface{}
parseJSONErr error
)
@@ -155,15 +157,23 @@ func AccessPlatformAPIWithRetry(client *http.Client, handleRequest func() *http.
baseapi.SugarLogger.Errorf("AccessPlatformAPIWithRetry:%s ioutil.ReadAll failed, url:%v, request:%v, error:%v", trackInfo, request.URL, getClonedData(request.URL, savedBuf), err)
errLevel = ErrLevelRecoverableErr // 读取数据错误,或数据格式错误认为是偶发情况,重试
} else {
if err = utils.TryUnmarshalUseNumber(bodyData, &bodyMap); err != nil {
if err = utils.TryUnmarshalUseNumber(bodyData, &bodyGeneral); err != nil {
parseJSONErr = err
err = nil // 尝试忽略解析成json错
} else {
baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry:%s url:%v, response:%s", trackInfo, request.URL, utils.Format4Output(bodyMap, true))
baseapi.SugarLogger.Debugf("AccessPlatformAPIWithRetry:%s url:%v, response:%s", trackInfo, request.URL, utils.Format4Output(bodyGeneral, true))
}
// 临时处理返回值居然不是map的情况
if bodyMap2, ok := bodyGeneral.(map[string]interface{}); ok {
bodyMap = bodyMap2
} else {
bodyMap = map[string]interface{}{
KeyData: bodyGeneral,
}
}
errLevel, err = handleResponse(response, string(bodyData), bodyMap)
if err != nil && parseJSONErr != nil {
const maxOutputLen = 200
const maxOutputLen = 2000
bodyDataLen := len(bodyData)
bodyData2 := bodyData
if bodyDataLen > maxOutputLen {