Explorar o código

坐标位置转化

luoyangwei hai 1 ano
pai
achega
52465107b7

+ 1 - 0
config/local.yml

@@ -14,6 +14,7 @@ storage:
 amap:
     key: "a4952dd01d3f605ce2af33e61031f365"
     url: "http://apilocate.amap.com/position"
+    convert_url: "https://restapi.amap.com/v3/assistant/coordinate/convert"
 
 log:
     # level 日志等级

+ 1 - 0
config/test.yml

@@ -14,6 +14,7 @@ storage:
 amap:
     key: "a4952dd01d3f605ce2af33e61031f365"
     url: "http://apilocate.amap.com/position"
+    convert_url: "https://restapi.amap.com/v3/assistant/coordinate/convert"
 
 
 log:

+ 5 - 5
internal/handler/location_header.go

@@ -31,17 +31,17 @@ func NewLocationHeader(
 }
 
 func (h *LocationHeader) Post(c fiber.Ctx) error {
-	log := log.With().Str("requestId", requestid.FromContext(c)).Logger()
+	l := log.With().Str("requestId", requestid.FromContext(c)).Logger()
 
 	var request v1.PostLocationRequest
 	if err := c.Bind().Body(&request); err != nil {
-		log.Error().Err(err).Msg("绑定请求体失败")
+		l.Error().Err(err).Msg("绑定请求体失败")
 		return fiber.ErrBadRequest
 	}
 
 	var err error
 	var response *v1.PostLocationResponse
-	log.Info().Any("request", request).Int32("accessType", request.AccessType).Msg("正在定位")
+	l.Info().Any("request", request).Int32("accessType", request.AccessType).Msg("正在定位")
 	if request.AccessType == gpcLocationType {
 		response, err = h.gpsService.Request(h.WrapFiberContext(c), &request)
 	} else {
@@ -49,9 +49,9 @@ func (h *LocationHeader) Post(c fiber.Ctx) error {
 	}
 
 	if err != nil {
-		log.Error().Err(err).Msg("定位失败")
+		l.Error().Err(err).Msg("定位失败")
 		return err
 	}
-	log.Info().Any("response", response).Int32("accessType", request.AccessType).Msg("定位完成")
+	l.Info().Any("response", response).Int32("accessType", request.AccessType).Msg("定位完成")
 	return c.JSON(response)
 }

+ 11 - 11
internal/service/amap_service.go

@@ -62,7 +62,7 @@ type amapResult struct {
 
 func (s *AMapService) Request(ctx context.Context, request *v1.PostLocationRequest) (*v1.PostLocationResponse, error) {
 	requestId := requestid.FromContext(ctx.Value("fiberCtx").(fiber.Ctx))
-	log := log.With().Str("requestId", requestId).Logger()
+	l := log.With().Str("requestId", requestId).Logger()
 
 	var err error
 	var result amapResult
@@ -73,15 +73,15 @@ func (s *AMapService) Request(ctx context.Context, request *v1.PostLocationReque
 	}
 
 	// Encode the request parameters into a URL
-	var url string
-	if url, err = s.queryEncode(request); err != nil {
+	var encodeUrl string
+	if encodeUrl, err = s.queryEncode(request); err != nil {
 		return nil, err
 	}
 
 	// Request to amap api interface
 	// read and retrieve after interface return
 	var bytes []byte
-	if bytes, err = s.send(ctx, url); err != nil {
+	if bytes, err = s.send(ctx, encodeUrl); err != nil {
 		return nil, err
 	}
 
@@ -92,7 +92,7 @@ func (s *AMapService) Request(ctx context.Context, request *v1.PostLocationReque
 
 	// Determine whether the request is successful
 	if !isSuccessful(&result) {
-		log.Error().Stack().Msg("amap request is not successful")
+		l.Error().Stack().Msg("amap request is not successful")
 		return nil, fiber.NewError(v1.ErrAMAPLocationFailed.Code, result.Info)
 	}
 
@@ -103,7 +103,7 @@ func (s *AMapService) Request(ctx context.Context, request *v1.PostLocationReque
 		return nil, eris.Wrapf(err, "error select by previous")
 	}
 	if isInvalidPosition {
-		log.Warn().Str("now", result.Result.Location).Msgf("定位命中距离算法判断, 丢弃点位")
+		l.Warn().Str("now", result.Result.Location).Msgf("定位命中距离算法判断, 丢弃点位")
 		return nil, v1.ErrAMAPLocationFailed
 	}
 
@@ -122,9 +122,9 @@ func (s *AMapService) Request(ctx context.Context, request *v1.PostLocationReque
 	positionTime := time.UnixMilli(request.PositionTime)
 
 	// 数据写入数据库
-	if err := s.mapLocationModel.Insert(ctx, &model.MapLocationModel{
+	if err = s.mapLocationModel.Insert(ctx, &model.MapLocationModel{
 		ExtID:        request.ID,
-		Request:      conv.String(url),
+		Request:      conv.String(encodeUrl),
 		InfoCode:     int32(infoCode),
 		Info:         result.Info,
 		Result:       conv.String(resultStr),
@@ -196,9 +196,9 @@ func (s *AMapService) queryEncode(request *v1.PostLocationRequest) (string, erro
 		query.Add(key, fmt.Sprintf("%v", val))
 	}
 
-	url, _ := url.QueryUnescape(query.Encode())
-	url = fmt.Sprintf("%s?%s", s.conf.GetString("amap.url"), url)
-	return url, nil
+	unescapeUrl, _ := url.QueryUnescape(query.Encode())
+	unescapeUrl = fmt.Sprintf("%s?%s", s.conf.GetString("amap.url"), unescapeUrl)
+	return unescapeUrl, nil
 }
 
 // isSuccessful Determine whether the request is successful

+ 3 - 2
internal/service/gps_service.go

@@ -30,9 +30,10 @@ func NewGpsService(conf *viper.Viper, mapLocationModel *model.MapLocationModel,
 
 func (s *GpsService) Request(ctx context.Context, request *v1.PostLocationRequest) (*v1.PostLocationResponse, error) {
 	requestId := requestid.FromContext(ctx.Value("fiberCtx").(fiber.Ctx))
-	log := log.With().Str("requestId", requestId).Logger()
+	l := log.With().Str("requestId", requestId).Logger()
 
 	location := request.Lon + "," + request.Lat
+	location = s.locationService.convertGpsPoint(ctx, location)
 
 	// 距离算法判断是否丢弃点位
 	// 跟上一次的点位作比较, 如果点位的移动速度超过了 trainSpeed 阈值, 我们需要丢弃这个点位
@@ -41,7 +42,7 @@ func (s *GpsService) Request(ctx context.Context, request *v1.PostLocationReques
 		return nil, eris.Wrapf(err, "error select by previous")
 	}
 	if isInvalidPosition {
-		log.Warn().Str("now", location).Msgf("定位命中距离算法判断, 丢弃点位")
+		l.Warn().Str("now", location).Msgf("定位命中距离算法判断, 丢弃点位")
 		return nil, v1.ErrAMAPLocationFailed
 	}
 

+ 52 - 3
internal/service/location_service.go

@@ -2,7 +2,12 @@ package service
 
 import (
 	"context"
+	"fmt"
+	"github.com/bytedance/sonic"
+	"io"
 	"math"
+	"net/http"
+	"net/url"
 	"strconv"
 	"strings"
 	"time"
@@ -33,11 +38,11 @@ func NewLocationService(conf *viper.Viper, mapLocationModel *model.MapLocationMo
 // 同一个用户在短时间内多次请求, 如果有这类情况直接返回同一结果
 func (s *LocationService) rateLimiter(ctx context.Context, request *v1.PostLocationRequest) (*v1.PostLocationResponse, bool) {
 	requestId := requestid.FromContext(ctx.Value("fiberCtx").(fiber.Ctx))
-	log := log.With().Str("requestId", requestId).Logger()
+	l := log.With().Str("requestId", requestId).Logger()
 
 	mapLocation, err := s.mapLocationModel.SelectByDuration(ctx, request.ID, 60*time.Second)
 	if err != nil {
-		log.Error().Stack().Err(eris.Wrap(err, "select by duration")).
+		l.Error().Stack().Err(eris.Wrap(err, "select by duration")).
 			Msg("flooding select by duration error")
 		return nil, false
 	}
@@ -46,7 +51,7 @@ func (s *LocationService) rateLimiter(ctx context.Context, request *v1.PostLocat
 		return nil, false
 	}
 
-	log.Warn().Msgf("定位命中 Flooding")
+	l.Warn().Msgf("定位命中 Flooding")
 	return &v1.PostLocationResponse{
 		Type:      1,
 		PointType: mapLocation.PointType,
@@ -77,6 +82,50 @@ func haversine(lat1, lng1, lat2, lng2 float64) float64 {
 	return dist * radius / 1000
 }
 
+func (s *LocationService) convertGpsPoint(ctx context.Context, locations string) string {
+	requestId := requestid.FromContext(ctx.Value("fiberCtx").(fiber.Ctx))
+	l := log.With().Str("requestId", requestId).Logger()
+
+	var query = url.Values{"key": []string{s.conf.GetString("amap.key")}}
+	query.Add("locations", locations)
+	query.Add("coordsys", "gps")
+	query.Add("output", "json")
+
+	unescapeUrl, _ := url.QueryUnescape(query.Encode())
+	unescapeUrl = fmt.Sprintf("%s?%s", s.conf.GetString("amap.convert_url"), unescapeUrl)
+
+	// Request to amap
+	res, err := http.Get(unescapeUrl)
+	if err != nil {
+		l.Error().Err(err).Msg("amap http get error")
+		return locations
+	}
+
+	// Incorrect situation
+	if res.StatusCode != http.StatusOK {
+		l.Error().Msgf("amap http status code is not 200, status code: %d", res.StatusCode)
+		return locations
+	}
+
+	var result map[string]interface{}
+	respBytes, err := io.ReadAll(res.Body)
+	if err != nil {
+		l.Error().Err(err).Msg("amap read all error")
+		return locations
+	}
+	if err = sonic.Unmarshal(respBytes, &result); err != nil {
+		return locations
+	}
+
+	// Determine whether the request is successful
+	var status = result["status"].(string)
+	if status != amapSuccessfulStatus {
+		l.Error().Stack().Msg("amap request is not successful")
+		return locations
+	}
+	return result["locations"].(string)
+}
+
 // previousPositionDiff 距离算法判断是否丢弃点位
 // true: 丢弃点位, false: 不丢弃
 func (s *LocationService) previousPositionDiff(ctx context.Context, request *v1.PostLocationRequest, location string, positionTime int64) (bool, error) {