瀏覽代碼

Merge branch 'dev' of http://106.52.134.22:3000/terry/iot_manager_service into dev

longan 2 年之前
父節點
當前提交
0fcfbe0302

+ 2 - 1
.gitignore

@@ -2,4 +2,5 @@
 log
 .idea
 go.sum
-main_demo.go
+main_demo.go
+/demo/

+ 239 - 0
app/operation/controller/captureController.go

@@ -0,0 +1,239 @@
+package controller
+
+import (
+	"github.com/gin-gonic/gin"
+	"iot_manager_service/app/middleware"
+	"iot_manager_service/app/operation/model"
+	"iot_manager_service/app/operation/service"
+	"iot_manager_service/util/common"
+	"net/http"
+	"strconv"
+)
+
+// Capture 抓拍单元
+var Capture = new(captureCtl)
+
+type captureCtl struct{}
+
+// CountList 取车流量 月日
+func (c captureCtl) CountList(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	err = nil
+	if req.QueryType == "day" {
+		records, err = service.CaptureService.GetDayVehicleTotal(claims.TenantId, req)
+	} else {
+		records, err = service.CaptureService.GetMonthVehicleTotal(claims.TenantId, req)
+	}
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// SuggestSpeed 取抓拍单元 方位
+func (c captureCtl) SuggestSpeed(ctx *gin.Context) {
+	captureId, err := strconv.Atoi(ctx.Query("captureId"))
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var records interface{}
+	records, err = service.CaptureService.GetSuggestSpeed(claims.TenantId, captureId)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// AreaList 归属地统计 list
+func (c captureCtl) AreaList(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	records, err = service.CaptureAreaService.GetAreaList(claims.TenantId, req)
+
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// AreaTypeList 归属地统计 line图表
+func (c captureCtl) AreaTypeList(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	records, err = service.CaptureAreaService.GetAreaTypeList(claims.TenantId, req)
+
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// VehicleTypeEx 车型 列表 查询
+func (c captureCtl) VehicleTypeEx(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	err = nil
+	records, err = service.CaptureVehicleTypeExService.GetVehicleList(claims.TenantId, req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// VehicleTypeList 车型 line线图数据
+func (c captureCtl) VehicleTypeList(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	err = nil
+	records, err = service.CaptureVehicleTypeExService.GetVehicleTypeList(claims.TenantId, req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// SpeedList 车速统计
+func (c captureCtl) SpeedList(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	records, err = service.CaptureSpeedService.GetList(claims.TenantId, req)
+
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// OverSpeedRecord 超速明细
+func (c captureCtl) OverSpeedRecord(ctx *gin.Context) {
+	var req model.RequestCaptureOverSpeed
+	_ = ctx.ShouldBindQuery(&req)
+	var records interface{}
+	records, err := service.CaptureSpeedService.GetOverSpeedRecord(req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// OverSpeedRecordSync 同步超速明细记录
+func (c captureCtl) OverSpeedRecordSync(ctx *gin.Context) {
+	var req model.RequestCaptureFilter
+	_ = ctx.ShouldBindQuery(&req)
+	go func() {
+		service.CaptureSpeedService.SyncOverSpeedRecord(req.StartTime, req.EndTime)
+	}()
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, nil))
+}
+
+// PeriodsList 时段统计
+func (c captureCtl) PeriodsList(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	records, err := service.CapturePeriodsService.GetPeriodsList(claims.TenantId, req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// CarrecordCount 货车统计
+func (c captureCtl) CarrecordCount(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCarRecordCountFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	err = nil
+	records, err = service.CaptureCarRecordService.GetCarRecordCount(claims.TenantId, req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}
+
+// ReportList 报表统计
+func (c captureCtl) ReportList(ctx *gin.Context) {
+	value, _ := ctx.Get(middleware.Authorization)
+	claims := value.(*middleware.Claims)
+	var req model.RequestCaptureReportFilter
+	err := ctx.ShouldBindQuery(&req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	var records interface{}
+	err = nil
+	records, err = service.CaptureReportService.GetList(claims.TenantId, req)
+	if err != nil {
+		ctx.JSON(http.StatusOK, err)
+		return
+	}
+	ctx.JSON(http.StatusOK, common.SuccessResponse(common.Succeeded, records))
+}

app/operation/dao/AlarmDao.go → app/operation/dao/alarmDao.go


+ 55 - 0
app/operation/dao/captureOverSpeedDao.go

@@ -0,0 +1,55 @@
+package dao
+
+import (
+	"errors"
+	"gorm.io/gorm"
+	"iot_manager_service/app/operation/model"
+	"iot_manager_service/util/common"
+)
+
+type CaptureOverSpeed struct {
+	ID        int         `gorm:"comment:ID" json:"id"`
+	CaptureSn string      `gorm:"comment:抓拍单元SN" json:"code"`
+	Time      common.Time `gorm:"comment:抓拍时间;type:datetime" json:"time"`
+	Vtype     int         `gorm:"comment:车类型" json:"vtype"`
+	Plate     string      `gorm:"comment:车牌号" json:"plate"`
+	Speed     int         `gorm:"comment:速度" json:"speed"`
+	Sflag     int         `gorm:"comment:速度比率" json:"sflag"`
+}
+
+func (c CaptureOverSpeed) TableName() string {
+	return "data_capture_over_speed"
+}
+
+// GetMaxIdAndUpDateTime 得到最大同步 ID
+func (c CaptureOverSpeed) GetMaxIdAndUpDateTime() (int64, string) {
+	var captureOverSpeed CaptureOverSpeed
+	err := Db.Debug().Model(&c).Last(&captureOverSpeed).Error
+	if err != nil {
+		return 0, ""
+	}
+	return int64(captureOverSpeed.ID), captureOverSpeed.Time.String()
+}
+
+// BatchCreate 批量插入
+func (c CaptureOverSpeed) BatchCreate(his []CaptureOverSpeed) error {
+	return Db.Debug().Model(&c).CreateInBatches(his, 1000).Error
+}
+
+// Gets 记录列表
+func (c CaptureOverSpeed) Gets(captureSn string, req model.RequestCaptureOverSpeed) ([]CaptureOverSpeed, int64, error) {
+	//fmt.Printf("size = %v \n", size)
+	//fmt.Printf("current = %v \n", current)
+	var list []CaptureOverSpeed
+	db := Db.Debug().Model(&c).Where(&CaptureOverSpeed{CaptureSn: captureSn})
+	db.Where("time between ? and ?", req.StartTime+" 00:00:00", req.EndTime+" 23:59:59")
+	var count int64
+	db.Count(&count)
+	db = db.Scopes(common.Paginate(req.Current, req.Size))
+	err := db.Order("id desc").Find(&list).Error
+	if errors.Is(err, gorm.ErrRecordNotFound) {
+		err = nil
+	}
+	//fmt.Printf("count = %v", count)
+	return list, count, err
+}

+ 3 - 1
app/operation/dao/common.go

@@ -10,7 +10,9 @@ var Db *gorm.DB
 
 func InitDB(db *gorm.DB) {
 	Db = db
-	models := []common.TableModelAuto{}
+	models := []common.TableModelAuto{
+		{&CaptureOverSpeed{}, "超速车牌数据明细"},
+	}
 	for _, val := range models {
 		//fmt.Println(val.Model)
 		err := Db.Set("gorm:table_options", "comment '"+val.Comment+"'").AutoMigrate(val.Model)

+ 197 - 0
app/operation/edge_service/forCaptureItsService.go

@@ -0,0 +1,197 @@
+package edge_service
+
+import (
+	"encoding/json"
+	"fmt"
+	"io/ioutil"
+	"iot_manager_service/config"
+	"net/http"
+	url2 "net/url"
+	"strings"
+	"time"
+)
+
+// CaptureIts 获取设备能耗数据
+type ForCaptureIts struct{}
+
+// CaptureItsReq 请求参数
+type ForCaptureItsReq struct {
+	Codes []string `json:"codes"` //抓拍单元 capture_sn列表
+	Types []int    `json:"types"` //vtype 车型
+	Start string   `json:"start"`
+	End   string   `json:"end"`
+	Flag  int      `json:"flag"` //0按日 1按月
+}
+
+// ForCaptureItsRes 返回数据
+type ForCaptureItsRes struct {
+	Code int                 `json:"code"`
+	Msg  string              `json:"msg"`
+	Data []ForCaptureItsData `json:"data"`
+}
+type ForCaptureItsData struct {
+	Code  string `json:"code"`  //抓拍单元 capture_sn
+	Time  string `json:"time"`  //时间 2022-05-01  ||2022-05
+	Flag  int    `json:"flag"`  //0:日数据,1:月数据,2:小时数据
+	Sflag int    `json:"sflag"` //车速区间时:
+	Total int    `json:"total"` //数量
+
+	Province string `json:"province"` //归属地时-用到的省
+	City     string `json:"city"`     //归属地时-用到的城市
+
+	Vtype int    `json:"vtype"` //车型统计
+	Plate string `json:"plate"` //车牌记录-车牌
+	Speed int    `json:"speed"` //车牌记录-车速
+}
+
+// VehicleTotal 统计日 月 车流量 数据
+func (f ForCaptureIts) VehicleTotal(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/vehicletotal"
+	return f.pubPost(reqPostData, api)
+}
+
+// Province 归属地省统计
+func (f ForCaptureIts) Province(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/province"
+	return f.pubPost(reqPostData, api)
+}
+
+// City 归属地城市统计
+func (f ForCaptureIts) City(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/provincecity"
+	return f.pubPost(reqPostData, api)
+}
+
+// Vehicletypeex 车型统计
+func (f ForCaptureIts) Vehicletypeex(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/vehicletypeex"
+	return f.pubPost(reqPostData, api)
+}
+
+// Vehiclespeedtotal 车速区间统计 日月
+func (f ForCaptureIts) VehicleSpeedTotal(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/vehiclespeedtotal"
+	return f.pubPost(reqPostData, api)
+}
+
+// Vehicleoverspeedtotal 车速超速区间统计
+func (f ForCaptureIts) VehicleOverSpeedTotal(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/vehicleoverspeedtotal"
+	return f.pubPost(reqPostData, api)
+}
+
+// VehicleHourTotal 小时统计数据
+func (f ForCaptureIts) VehicleHourTotal(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/vehiclehourtotal"
+	return f.pubPost(reqPostData, api)
+}
+
+// Vehicleplate 同步车牌记录
+func (f ForCaptureIts) Vehicleplate(reqPostData ForCaptureItsReq) ([]ForCaptureItsData, error) {
+	api := "/data/v1/its/vehicleplate"
+	return f.pubPost(reqPostData, api)
+}
+
+//公用 post请求
+func (f ForCaptureIts) pubPost(reqPostData ForCaptureItsReq, api string) ([]ForCaptureItsData, error) {
+	cfg := config.Instance()
+	api = cfg.Foreign.IotEdgeUrl + api
+	//fmt.Printf("api = %v \n", api)
+	if !strings.Contains(reqPostData.Start, ":") {
+		reqPostData.Start = reqPostData.Start + " 00:00:00"
+		reqPostData.End = reqPostData.End + " 23:59:59"
+	}
+	//fmt.Printf("reqPostData = %v \n", reqPostData)
+	method := "POST"
+	client := &http.Client{}
+	marshal, _ := json.Marshal(reqPostData)
+	req, err := http.NewRequest(method, api, strings.NewReader(string(marshal)))
+
+	if err != nil {
+		return nil, err
+	}
+	res, err := client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer res.Body.Close()
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return nil, err
+	}
+	//fmt.Printf("body = %v", string(body))
+	result := ForCaptureItsRes{}
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		return nil, err
+	}
+	if result.Code != 0 {
+		panic(result.Msg)
+	}
+	//fmt.Printf("result.Data = %v", result.Data)
+	return result.Data, nil
+}
+
+// SyncOverSpeedRecordData 同步超速车牌数据结构
+type SyncOverSpeedRecordData struct {
+	ID    int    `json:"id"`
+	Code  string `json:"code"`
+	Time  string `json:"time"`
+	Vtype int    `json:"vtype"`
+	Plate string `json:"plate"`
+	Speed int    `json:"speed"`
+	Flag  int    `json:"flag"`
+}
+
+//同步超速车牌号返回数据
+type syncOverSpeedRecordDataRes struct {
+	Code int                       `json:"code"`
+	Msg  string                    `json:"msg"`
+	Data []SyncOverSpeedRecordData `json:"data"`
+}
+
+func (r *ForCaptureIts) SyncOverSpeedRecord(maxId int64, maxUpDateTime string, start, end string) ([]SyncOverSpeedRecordData, error) {
+	maxId += 1
+	if maxUpDateTime == "" {
+		maxUpDateTime = time.Now().AddDate(-1, 0, 0).Format("2006-01-02 15:04:05")
+	}
+	cfg := config.Instance()
+	api := cfg.Foreign.IotEdgeUrl + "/data/v1/its/overspeed/sync"
+	url := fmt.Sprintf("%v?id=%d&start=%v&end=%v", api, maxId, url2.QueryEscape(maxUpDateTime), url2.QueryEscape(time.Now().Format("2006-01-02 15:04:05")))
+	if start != "" {
+		parse, err := time.Parse("2006-01-02", start)
+		if err != nil {
+			parse = time.Now().AddDate(-1, 0, 0)
+		}
+		startStr := parse.Format("2006-01-02 15:04:05")
+		url = fmt.Sprintf("%v?id=%d&start=%v&end=%v", api, maxId, url2.QueryEscape(startStr), url2.QueryEscape(time.Now().Format("2006-01-02 15:04:05")))
+	}
+	//fmt.Printf("url = %v", url)
+	method := "GET"
+	client := &http.Client{}
+	req, err := http.NewRequest(method, url, nil)
+
+	if err != nil {
+		return nil, err
+	}
+	res, err := client.Do(req)
+	if err != nil {
+		return nil, err
+	}
+	defer res.Body.Close()
+	body, err := ioutil.ReadAll(res.Body)
+	if err != nil {
+		return nil, err
+	}
+	//fmt.Printf("body = %v", string(body))
+	result := syncOverSpeedRecordDataRes{}
+	err = json.Unmarshal(body, &result)
+	if err != nil {
+		return nil, err
+	}
+	if result.Code != 0 {
+		panic(result.Msg)
+	}
+	//fmt.Printf("result.Data = %v", result.Data)
+	return result.Data, nil
+}

app/operation/model/Alarm.go → app/operation/model/alarm.go


+ 136 - 0
app/operation/model/capture.go

@@ -0,0 +1,136 @@
+package model
+
+import "sort"
+
+type RequestCaptureFilter struct {
+	StartTime string `form:"queryStartDate"`
+	EndTime   string `form:"queryEndDate"`
+	QueryType string `form:"queryType"` //类型 month月 day日
+	CaptureId int    `form:"captureId"` //抓拍单元
+	Type      int    `form:"type"`      //归属地时,区分查看城市 1=省份 2=城市
+}
+
+type ResponseCaptureVehicleTotal struct {
+	CountTime string `json:"countTime"` //统一时间
+	CountT    int    `json:"countT"`    //总报警
+}
+
+type ResponseCaptureSuggestSpeed struct {
+	ID               int    `json:"id"`
+	CaptureDirection int    `json:"captureDirection"` //方向
+	WayName          string `json:"wayName"`          //名称
+}
+
+type TmpCapture struct {
+	Name  string `json:"name"`
+	Value int    `json:"value"`
+}
+
+type TypeList struct {
+	Name1   string `json:"name1"`
+	Name2   string `json:"name2"`
+	Name3   string `json:"name3"`
+	Name4   string `json:"name4"`
+	Name5   string `json:"name5"`
+	Name6   string `json:"name6"`
+	Name7   string `json:"name7"`
+	Name8   string `json:"name8"`
+	Name9   string `json:"name9"`
+	Name10  string `json:"name10"`
+	Name11  string `json:"name11"`
+	Value1  int    `json:"value1"`
+	Value2  int    `json:"value2"`
+	Value3  int    `json:"value3"`
+	Value4  int    `json:"value4"`
+	Value5  int    `json:"value5"`
+	Value6  int    `json:"value6"`
+	Value7  int    `json:"value7"`
+	Value8  int    `json:"value8"`
+	Value9  int    `json:"value9"`
+	Value10 int    `json:"value10"`
+	Value11 int    `json:"value11"`
+}
+type TmpCaptures struct {
+	TmpCapturesData []TmpCapture
+	CountTime       string `json:"time"`
+	TypeList
+}
+
+type IntSlice []TmpCapture
+
+func (p IntSlice) Len() int           { return len(p) }
+func (p IntSlice) Less(i, j int) bool { return p[i].Value < p[j].Value }
+func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+//渲染出10个前10的数据
+func ViewData(tmp TmpCaptures) TmpCaptures {
+	tmpNew := tmp
+	for i, datum := range tmpNew.TmpCapturesData {
+		switch i + 1 {
+		case 1:
+			tmpNew.Name1 = datum.Name
+			tmpNew.Value1 = datum.Value
+		case 2:
+			tmpNew.Name2 = datum.Name
+			tmpNew.Value2 = datum.Value
+		case 3:
+			tmpNew.Name3 = datum.Name
+			tmpNew.Value3 = datum.Value
+		case 4:
+			tmpNew.Name4 = datum.Name
+			tmpNew.Value4 = datum.Value
+		case 5:
+			tmpNew.Name5 = datum.Name
+			tmpNew.Value5 = datum.Value
+		case 6:
+			tmpNew.Name6 = datum.Name
+			tmpNew.Value6 = datum.Value
+		case 7:
+			tmpNew.Name7 = datum.Name
+			tmpNew.Value7 = datum.Value
+		case 8:
+			tmpNew.Name8 = datum.Name
+			tmpNew.Value8 = datum.Value
+		case 9:
+			tmpNew.Name9 = datum.Name
+			tmpNew.Value9 = datum.Value
+		case 10:
+			tmpNew.Name10 = datum.Name
+			tmpNew.Value10 = datum.Value
+		case 11:
+			tmpNew.Name11 = datum.Name
+			tmpNew.Value11 = datum.Value
+		}
+	}
+	return tmpNew
+}
+
+//排序功能
+func RankByWordCount(wordFrequencies map[string]int) PairList {
+	pl := make(PairList, len(wordFrequencies))
+	i := 0
+	for k, v := range wordFrequencies {
+		pl[i] = TmpCapture{k, v}
+		i++
+	}
+	//从小到大排序
+	//sort.Sort(pl)
+	//从大到小排序
+	sort.Sort(sort.Reverse(pl))
+	return pl
+}
+
+type PairList []TmpCapture
+
+func (p PairList) Len() int           { return len(p) }
+func (p PairList) Less(i, j int) bool { return p[i].Value < p[j].Value }
+func (p PairList) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }
+
+func IsContain(items []string, item string) bool {
+	for _, eachItem := range items {
+		if eachItem == item {
+			return true
+		}
+	}
+	return false
+}

+ 25 - 0
app/operation/model/captureCarRecord.go

@@ -0,0 +1,25 @@
+package model
+
+type ResponseCarRecordCount struct {
+	NowDate string `json:"nowDate"` //当前返回时间
+	CountN  int    `json:"countN"`  //大型货车
+	CountT  int    `json:"countT"`  //中型货车
+}
+type ResponseCarModelCount struct {
+	TotalCountN int `json:"totalCountN"` //大型货车 总数量
+	TotalCountT int `json:"totalCountT"` //中型货车 总数量
+}
+
+type ResponseCarRecordAll struct {
+	CarRecordCount []ResponseCarRecordCount `json:"carRecordCount"` //汇总line图
+	CarModelCount  ResponseCarModelCount    `json:"carModelCount"`  //车型总数量
+	Details        interface{}              `json:"details"`        //下方车牌明细
+}
+
+type RequestCarRecordCountFilter struct {
+	StartTime string `form:"startTime"`
+	EndTime   string `form:"endTime"`
+	QueryType string `form:"queryType"` //类型 month月 day日
+	CaptureId int    `form:"captureId"` //抓拍单元
+	CarModel  int    `form:"carModel"`  //2大型 1中型 0全部
+}

+ 6 - 0
app/operation/model/capturePeriods.go

@@ -0,0 +1,6 @@
+package model
+
+type ResponseCapturePeriods struct {
+	Hours  string `json:"hours"`  //时
+	CountT int    `json:"countT"` //总报警
+}

+ 23 - 0
app/operation/model/captureReport.go

@@ -0,0 +1,23 @@
+package model
+
+type RequestCaptureReportFilter struct {
+	StartTime string `form:"startTime"`
+	EndTime   string `form:"endTime"`
+	CaptureId int    `form:"captureId"` //抓拍单元
+	QueryType int    `form:"queryType"` //1小时统计 2日统计 3月统计
+}
+
+type ResponseCaptureReport struct {
+	CountTime string `json:"time"`    //时间
+	Value1    int    `json:"value1"`  //小型货车
+	Value2    int    `json:"value2"`  //中型货车
+	Value3    int    `json:"value3"`  //大型货车
+	Value4    int    `json:"value4"`  //特大货车
+	Value5    int    `json:"value5"`  //箱式货车
+	Value6    int    `json:"value6"`  //轻型客车
+	Value7    int    `json:"value7"`  //大客车
+	Value8    int    `json:"value8"`  //汽车小计
+	Value9    int    `json:"value9"`  //摩托车
+	Value10   int    `json:"value10"` //拖拉机
+	AllTotal  int    `json:"value11"` //总计
+}

+ 34 - 0
app/operation/model/captureSpeed.go

@@ -0,0 +1,34 @@
+package model
+
+type ResponseCaptureSpeed struct {
+	CountTime string `json:"countTime"` //统一时间
+	V1        int    `json:"v1"`
+	V2        int    `json:"v2"`
+	V3        int    `json:"v3"`
+	V4        int    `json:"v4"`
+	V5        int    `json:"v5"`
+	V6        int    `json:"v6"`
+	V7        int    `json:"v7"`
+
+	V11 int `json:"v11"`
+	V13 int `json:"v13"`
+	V14 int `json:"v14"`
+	V15 int `json:"v15"`
+	V16 int `json:"v16"`
+}
+
+type RequestCaptureOverSpeed struct {
+	StartTime string `form:"queryStartDate"`
+	EndTime   string `form:"queryEndDate"`
+	CaptureId int    `form:"captureId"` //抓拍单元
+	Current   int    `form:"current"`   //当前分页
+	Size      int    `form:"size"`      //每页数量
+}
+
+type ResponseCaptureOverSpeedRecord struct {
+	Records interface{} `json:"records"` //记录列表
+	Current int         `json:"current"` //当前分页
+	Size    int         `json:"size"`    //每页数量
+	Total   int64       `json:"total"`   //总数
+	Pages   int         `json:"pages"`   //总页数
+}

app/operation/service/AlarmService.go → app/operation/service/alarmService.go


+ 164 - 0
app/operation/service/captureAreaService.go

@@ -0,0 +1,164 @@
+package service
+
+import (
+	"iot_manager_service/app/device/dao"
+	"iot_manager_service/app/operation/edge_service"
+	"iot_manager_service/app/operation/model"
+	"iot_manager_service/util/common"
+)
+
+// CaptureAreaService 归属地统计
+var CaptureAreaService = new(captureAreaService)
+
+type captureAreaService struct{}
+
+// GetAreaList 得到下方前10的详细数据 list
+func (s captureAreaService) GetAreaList(tenantId int, req model.RequestCaptureFilter) (interface{}, error) {
+	//得到边缘数据
+	flag, forData, err := s.getData(tenantId, req)
+
+	//得到排名前10的省或城市
+	getTop10 := s.getTop10(forData, req.Type)
+	var topArr []string
+	for _, area := range getTop10 {
+		topArr = append(topArr, area.Name)
+	}
+
+	//将所有省份或城市 数据组装成 map {time:[{Name:"xxx", Value:11}]}
+	mdata := make(map[string][]model.TmpCapture)
+	for _, datum := range forData {
+		time := datum.Time
+		if flag == 1 {
+			time += "-01"
+		}
+		name := datum.City
+		if req.Type == 1 {
+			name = datum.Province
+		}
+		mm := model.TmpCapture{
+			Name:  name,
+			Value: datum.Total,
+		}
+		mdata[time] = append(mdata[time], mm)
+	}
+
+	//时间范围内的月份或天的明细列表
+	var countTimes []string
+	if flag == 1 {
+		countTimes = common.GetTimeMonths(req.StartTime, req.EndTime) //时间范围 月
+	} else {
+		countTimes = common.GetTimeDays(req.StartTime, req.EndTime) //时间范围 天
+	}
+
+	//每日|每月 前10的数据 组装
+	var list []model.TmpCaptures
+	for _, countTime := range countTimes {
+		//得到总排名前10的,当天|当月 数据
+		var tmpsData []model.TmpCapture
+		for _, area := range getTop10 {
+			value := mdata[countTime]
+			val := 0
+			for _, i := range value {
+				if area.Name == i.Name {
+					val += i.Value
+				}
+				i.Value = 0
+			}
+			tmpsData = append(tmpsData, model.TmpCapture{
+				Name:  area.Name,
+				Value: val,
+			})
+		}
+		//按日期 组装 前10名的每天或每月数据
+		list = append(list, model.TmpCaptures{
+			CountTime:       countTime,
+			TmpCapturesData: tmpsData,
+		})
+	}
+
+	//按前端要求的格式,组装数据
+	var list2 []model.TmpCaptures
+	for _, areas := range list {
+		data := model.ViewData(areas)
+		if len(data.TmpCapturesData) > 0 {
+			list2 = append(list2, data)
+		}
+	}
+	if err != nil {
+		return nil, err
+	}
+	return list2, nil
+}
+
+// GetAreaTypeList 前10的地区 和 数量 line 图表
+func (s captureAreaService) GetAreaTypeList(tenantId int, req model.RequestCaptureFilter) (interface{}, error) {
+	//得到全部数据
+	_, forData, err := s.getData(tenantId, req)
+
+	// 得到排名前10的省或城市
+	getTop10 := s.getTop10(forData, req.Type)
+	var tmp model.TmpCaptures
+	tmp.TmpCapturesData = getTop10
+
+	//按前端要求的格式,组装数据
+	data := model.ViewData(tmp)
+	return data, err
+}
+
+//得到边缘接口 时间范围数据
+func (s captureAreaService) getData(tenantId int, req model.RequestCaptureFilter) (int, []edge_service.ForCaptureItsData, error) {
+	//区分按月或按日
+	flag := 0
+	if req.QueryType == "month" {
+		flag = 1
+	}
+
+	//查出抓拍单元sn
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+
+	forCaptureIts := edge_service.ForCaptureIts{}
+	var forData []edge_service.ForCaptureItsData
+	var err error
+	if req.Type == 1 { //按省
+		forData, err = forCaptureIts.Province(edge_service.ForCaptureItsReq{
+			Codes: codes,
+			Start: req.StartTime,
+			End:   req.EndTime,
+			Flag:  flag,
+		})
+	} else { //按城市
+		forData, err = forCaptureIts.City(edge_service.ForCaptureItsReq{
+			Codes: codes,
+			Start: req.StartTime,
+			End:   req.EndTime,
+			Flag:  flag,
+		})
+	}
+	return flag, forData, err
+}
+
+//得到 前10
+func (s captureAreaService) getTop10(data []edge_service.ForCaptureItsData, typeInt int) model.PairList {
+	//拼全部数据
+	allData := make(map[string]int)
+	for _, datum := range data {
+		if typeInt == 1 {
+			allData[datum.Province] += datum.Total
+		} else {
+			allData[datum.City] += datum.Total
+		}
+	}
+	//对数据排序
+	top10Data := model.RankByWordCount(allData)
+	//取前10
+	if len(top10Data) >= 10 {
+		top10Data = top10Data[:10]
+	}
+	return top10Data
+}

+ 80 - 0
app/operation/service/captureCarRecordService.go

@@ -0,0 +1,80 @@
+package service
+
+import (
+	"iot_manager_service/app/device/dao"
+	"iot_manager_service/app/operation/edge_service"
+	"iot_manager_service/app/operation/model"
+	"iot_manager_service/util/common"
+	"strconv"
+)
+
+// CaptureCarRecordService 货车记录
+var CaptureCarRecordService = new(captureCarRecordService)
+
+type captureCarRecordService struct{}
+
+var (
+	MediumTruckVType int = 26 //中型货车
+	BigTruckVType    int = 17 //大型货车
+)
+
+func (s captureCarRecordService) GetCarRecordCount(tenantId int, req model.RequestCarRecordCountFilter) (*model.ResponseCarRecordAll, error) {
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+	forCaptureIts := edge_service.ForCaptureIts{}
+	vtypes := []int{MediumTruckVType, BigTruckVType}
+	if req.CarModel == 1 {
+		vtypes = []int{MediumTruckVType}
+	} else if req.CarModel == 2 {
+		vtypes = []int{BigTruckVType}
+	}
+	forData, err := forCaptureIts.Vehicleplate(
+		edge_service.ForCaptureItsReq{
+			Types: vtypes, //中型货车 大货车
+			Codes: codes,
+			Start: req.StartTime,
+			End:   req.EndTime,
+		})
+	if err != nil {
+		return nil, err
+	}
+	var countTimes []string
+	if req.QueryType == "month" {
+		countTimes = common.GetTimeMonths(req.StartTime, req.EndTime) //时间范围 月
+	} else {
+		countTimes = common.GetTimeDays(req.StartTime, req.EndTime) //时间范围 天
+	}
+	data := make(map[string]int)
+	for _, datum := range forData {
+		key := string(datum.Time[:10])
+		if req.QueryType == "month" {
+			key = string(datum.Time[:7]) + "-01"
+		}
+		vtype := strconv.Itoa(datum.Vtype)
+		data[key+vtype] += 1
+	}
+	var list []model.ResponseCarRecordCount
+	var totalCountN, totalCountT int
+	for _, countTime := range countTimes {
+		key := countTime
+		vtype26 := strconv.Itoa(MediumTruckVType)
+		vtype17 := strconv.Itoa(BigTruckVType)
+		list = append(list, model.ResponseCarRecordCount{
+			NowDate: countTime,
+			CountN:  data[key+vtype17],
+			CountT:  data[key+vtype26],
+		})
+		totalCountN += data[key+vtype17]
+		totalCountT += data[key+vtype26]
+	}
+	return &model.ResponseCarRecordAll{
+		CarRecordCount: list,
+		CarModelCount:  model.ResponseCarModelCount{totalCountN, totalCountT},
+		Details:        forData,
+	}, nil
+}

+ 56 - 0
app/operation/service/capturePeriodsService.go

@@ -0,0 +1,56 @@
+package service
+
+import (
+	"iot_manager_service/app/device/dao"
+	"iot_manager_service/app/operation/edge_service"
+	"iot_manager_service/app/operation/model"
+	"strconv"
+)
+
+// CapturePeriodsService 时段统计
+var CapturePeriodsService = new(capturePeriodsService)
+
+type capturePeriodsService struct{}
+
+func (s capturePeriodsService) GetPeriodsList(tenantId int, req model.RequestCaptureFilter) (interface{}, error) {
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+	forCaptureIts := edge_service.ForCaptureIts{}
+	forData, err := forCaptureIts.VehicleHourTotal(edge_service.ForCaptureItsReq{
+		Codes: codes,
+		Start: req.StartTime,
+		End:   req.EndTime,
+	})
+	if err != nil {
+		return nil, err
+	}
+	var hours []string
+	for i := 0; i < 24; i++ {
+		ii := strconv.Itoa(i)
+		if len(ii) < 2 {
+			ii = "0" + ii
+		}
+		hours = append(hours, ii)
+	}
+	datas := make(map[string]int)
+	for _, datum := range forData {
+		timeStr := datum.Time
+		hour := timeStr[11:13]
+		_, ok := datas[(hour)]
+		if ok {
+			datas[(hour)] += datum.Total
+		} else {
+			datas[(hour)] = 0
+		}
+	}
+	var list []model.ResponseCapturePeriods
+	for _, hour := range hours {
+		list = append(list, model.ResponseCapturePeriods{Hours: hour, CountT: datas[hour]})
+	}
+	return list, nil
+}

+ 104 - 0
app/operation/service/captureReportService.go

@@ -0,0 +1,104 @@
+package service
+
+import (
+	"iot_manager_service/app/device/dao"
+	"iot_manager_service/app/operation/edge_service"
+	"iot_manager_service/app/operation/model"
+	"iot_manager_service/util/common"
+	"strconv"
+)
+
+// CaptureReportService 报表统计
+var CaptureReportService = new(captureReportService)
+
+type captureReportService struct{}
+
+func (s captureReportService) GetList(tenantId int, req model.RequestCaptureReportFilter) ([]model.ResponseCaptureReport, error) {
+	var list []model.ResponseCaptureReport
+	//按日期  或 时段把每个类型的汇总 展示 出来
+	flag, record, err := s.getData(tenantId, req)
+	nlist := make(map[string]int)
+	allTypes := []int{14, 26, 17, 10, 33, 25, 146, 8, 9}
+	qcTypes := []int{14, 26, 17, 10, 33, 25, 146}
+	allTotal := make(map[string]int)
+	value8Total := make(map[string]int)
+	for _, data := range record {
+		key := data.Time[:10]
+		if flag == 2 {
+			key = data.Time[11:13]
+		}
+		vtype := strconv.Itoa(data.Vtype)
+		nlist[key+vtype] += data.Total
+		if common.InIntArr(data.Vtype, qcTypes) {
+			value8Total[key] += data.Total
+		}
+		if common.InIntArr(data.Vtype, allTypes) {
+			allTotal[key] += data.Total
+		}
+	}
+	var countTimes []string
+	if flag == 0 {
+		//日
+		countTimes = common.GetTimeDays(req.StartTime, req.EndTime) //时间范围 天
+	} else if flag == 2 {
+		for i := 0; i < 24; i++ {
+			ii := strconv.Itoa(i)
+			if len(ii) < 2 {
+				ii = "0" + ii
+			}
+			countTimes = append(countTimes, ii)
+		}
+	}
+	//fmt.Printf("nlist = %v \n", nlist)
+	//fmt.Printf("countTimes = %v \n", countTimes)
+	//	types := []int{14, 26, 17, 10, 33, 25, 146, 8, 9}
+	for _, countTime := range countTimes {
+		list = append(list, model.ResponseCaptureReport{
+			CountTime: countTime,
+			Value1:    nlist[countTime+"14"],
+			Value2:    nlist[countTime+"26"],
+			Value3:    nlist[countTime+"17"],
+			Value4:    nlist[countTime+"10"],
+			Value5:    nlist[countTime+"33"],
+			Value6:    nlist[countTime+"25"],
+			Value7:    nlist[countTime+"146"],
+			Value8:    value8Total[countTime],
+			Value9:    nlist[countTime+"8"],
+			Value10:   nlist[countTime+"9"],
+			AllTotal:  allTotal[countTime],
+		})
+	}
+	return list, err
+}
+
+//得到边缘接口 时间范围数据
+func (s captureReportService) getData(tenantId int, req model.RequestCaptureReportFilter) (int, []edge_service.ForCaptureItsData, error) {
+	//区分按月或按日
+	flag := 1 //月
+	if req.QueryType == 1 {
+		flag = 2 //时
+	}
+	if req.QueryType == 2 {
+		flag = 0 //日
+	}
+
+	//查出抓拍单元sn
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+
+	forCaptureIts := edge_service.ForCaptureIts{}
+	var forData []edge_service.ForCaptureItsData
+	var err error
+	forData, err = forCaptureIts.Vehicletypeex(edge_service.ForCaptureItsReq{
+		Codes: codes,
+		Start: req.StartTime,
+		End:   req.EndTime,
+		Flag:  flag,
+	})
+	return flag, forData, err
+}

+ 82 - 0
app/operation/service/captureService.go

@@ -0,0 +1,82 @@
+package service
+
+import (
+	"iot_manager_service/app/device/dao"
+	"iot_manager_service/app/operation/edge_service"
+	"iot_manager_service/app/operation/model"
+	"iot_manager_service/util/common"
+)
+
+// CaptureService 车流统计
+var CaptureService = new(captureService)
+
+type captureService struct{}
+
+// GetDayVehicleTotal 车流统计 日
+func (s captureService) GetDayVehicleTotal(tenantId int, req model.RequestCaptureFilter) ([]model.ResponseCaptureVehicleTotal, error) {
+	return s.getVehicleTotalData(0, tenantId, req)
+}
+
+// GetMonthVehicleTotal 车流统计 月
+func (s captureService) GetMonthVehicleTotal(tenantId int, req model.RequestCaptureFilter) ([]model.ResponseCaptureVehicleTotal, error) {
+	return s.getVehicleTotalData(1, tenantId, req)
+}
+
+// 车流统计公用方法
+func (s captureService) getVehicleTotalData(flag int, tenantId int, req model.RequestCaptureFilter) ([]model.ResponseCaptureVehicleTotal, error) {
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+	var list []model.ResponseCaptureVehicleTotal
+	forCaptureIts := edge_service.ForCaptureIts{}
+	forData, err := forCaptureIts.VehicleTotal(edge_service.ForCaptureItsReq{
+		Codes: codes,
+		Start: req.StartTime,
+		End:   req.EndTime,
+		Flag:  flag,
+	})
+	//fmt.Printf("forData = %v \n", forData)
+	var countTimes []string
+	if flag == 1 {
+		countTimes = common.GetTimeMonths(req.StartTime, req.EndTime) //时间范围 月
+	} else {
+		countTimes = common.GetTimeDays(req.StartTime, req.EndTime) //时间范围 天
+	}
+	for _, countTime := range countTimes {
+		var countT int
+		for _, datum := range forData {
+			time := datum.Time
+			if flag == 1 {
+				time += "-01"
+			}
+			if time == countTime {
+				countT = datum.Total
+				continue
+			}
+		}
+		list = append(list, model.ResponseCaptureVehicleTotal{
+			CountTime: countTime,
+			CountT:    countT,
+		})
+	}
+	if err != nil {
+		return nil, err
+	}
+	return list, nil
+}
+
+// GetSuggestSpeed 从数据库查抓拍单元风向
+func (s captureService) GetSuggestSpeed(tenantId int, captureId int) (*dao.CaptureUnit, error) {
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       captureId,
+	}
+	if err := unit.GetDevice(); err != nil {
+		return nil, err
+	}
+	return &unit, nil
+}

+ 181 - 0
app/operation/service/captureSpeedService.go

@@ -0,0 +1,181 @@
+package service
+
+import (
+	"iot_manager_service/app/device/dao"
+	operationDao "iot_manager_service/app/operation/dao"
+	"iot_manager_service/app/operation/edge_service"
+	"iot_manager_service/app/operation/model"
+	"iot_manager_service/util/common"
+	"math"
+	"strconv"
+)
+
+var CaptureSpeedService = new(captureSpeedService)
+
+type captureSpeedService struct{}
+
+// GetList 车速统计
+func (s captureSpeedService) GetList(tenantId int, req model.RequestCaptureFilter) (map[string]interface{}, error) {
+	//sectionSpeed 区间车速数据
+	data := make(map[string]interface{})
+	speed, err := s.getSectionSpeed(tenantId, req)
+	data["sectionSpeed"] = s.viewData(req, speed, "sectionSpeed")
+	//overSpeed //超速数据
+	speed, err = s.getOverSpeed(tenantId, req)
+	data["overSpeed"] = s.viewData(req, speed, "overSpeed")
+	return data, err
+}
+
+// 区间车速数据
+func (s captureSpeedService) getSectionSpeed(tenantId int, req model.RequestCaptureFilter) ([]edge_service.ForCaptureItsData, error) {
+	//区分按月或按日
+	flag := 0
+	if req.QueryType == "month" {
+		flag = 1
+	}
+	//查出抓拍单元sn
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+	forCaptureIts := edge_service.ForCaptureIts{}
+	speedTotal, err := forCaptureIts.VehicleSpeedTotal(edge_service.ForCaptureItsReq{
+		Codes: codes,
+		Start: req.StartTime,
+		End:   req.EndTime,
+		Flag:  flag,
+	})
+	if err != nil {
+		return nil, err
+	}
+	return speedTotal, nil
+}
+
+// 超速数据
+func (s captureSpeedService) getOverSpeed(tenantId int, req model.RequestCaptureFilter) ([]edge_service.ForCaptureItsData, error) {
+	//区分按月或按日
+	flag := 0
+	if req.QueryType == "month" {
+		flag = 1
+	}
+	//查出抓拍单元sn
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+	forCaptureIts := edge_service.ForCaptureIts{}
+	speedTotal, err := forCaptureIts.VehicleOverSpeedTotal(edge_service.ForCaptureItsReq{
+		Codes: codes,
+		Start: req.StartTime,
+		End:   req.EndTime,
+		Flag:  flag,
+	})
+	if err != nil {
+		return nil, err
+	}
+	return speedTotal, nil
+}
+
+// 前端数据格式渲染
+func (s captureSpeedService) viewData(req model.RequestCaptureFilter, speeds []edge_service.ForCaptureItsData, cate string) []model.ResponseCaptureSpeed {
+	//区分按月或按日
+	flag := 0
+	if req.QueryType == "month" {
+		flag = 1
+	}
+	data := make(map[string]int)
+	for _, speed := range speeds {
+		time := speed.Time
+		if flag == 1 {
+			time += "-01"
+		}
+		sflag := strconv.Itoa(speed.Sflag)
+		data[time+"--"+sflag] += speed.Total
+	}
+	//时间范围内的月份或天的明细列表
+	var countTimes []string
+	if flag == 1 {
+		countTimes = common.GetTimeMonths(req.StartTime, req.EndTime) //时间范围 月
+	} else {
+		countTimes = common.GetTimeDays(req.StartTime, req.EndTime) //时间范围 天
+	}
+	var list []model.ResponseCaptureSpeed
+	for _, time := range countTimes {
+		if cate == "sectionSpeed" {
+			list = append(list, model.ResponseCaptureSpeed{
+				CountTime: time,
+				V1:        data[time+"--0"],
+				V2:        data[time+"--1"],
+				V3:        data[time+"--2"],
+				V4:        data[time+"--3"],
+				V5:        data[time+"--4"],
+				V6:        data[time+"--5"],
+				V7:        data[time+"--6"],
+			})
+		} else {
+			list = append(list, model.ResponseCaptureSpeed{
+				CountTime: time,
+				V11:       data[time+"--100"],
+				V13:       data[time+"--101"],
+				V14:       data[time+"--102"],
+				V15:       data[time+"--103"],
+				V16:       data[time+"--104"],
+			})
+		}
+	}
+	return list
+}
+
+// SyncOverSpeedRecord 同步超速车牌记录
+func (s captureSpeedService) SyncOverSpeedRecord(start, end string) error {
+	speed := operationDao.CaptureOverSpeed{}
+	maxId, maxTime := speed.GetMaxIdAndUpDateTime()
+	forCaptureIts := edge_service.ForCaptureIts{}
+	record, err := forCaptureIts.SyncOverSpeedRecord(maxId, maxTime, start, end)
+	if err != nil {
+		return err
+	}
+	var list []operationDao.CaptureOverSpeed
+	for _, data := range record {
+		list = append(list, operationDao.CaptureOverSpeed{
+			ID:        data.ID,
+			CaptureSn: data.Code,
+			Time:      common.Time(common.TimeStringToGoTime(data.Time)),
+			Vtype:     data.Vtype,
+			Plate:     data.Plate,
+			Speed:     data.Speed,
+			Sflag:     data.Flag,
+		})
+	}
+	return speed.BatchCreate(list)
+}
+
+func (s captureSpeedService) GetOverSpeedRecord(req model.RequestCaptureOverSpeed) (*model.ResponseCaptureOverSpeedRecord, error) {
+	//查出抓拍单元sn
+	unit := dao.CaptureUnit{
+		ID: req.CaptureId,
+	}
+	if req.Size <= 0 {
+		req.Size = 10
+	}
+	unit.GetDevice()
+	speed := operationDao.CaptureOverSpeed{}
+	records, total, err := speed.Gets(unit.CaptureSn, req)
+	if err != nil {
+		return nil, err
+	}
+	pages := math.Ceil(float64(total) / float64(req.Size))
+	return &model.ResponseCaptureOverSpeedRecord{
+		Records: records,
+		Current: req.Current,
+		Size:    req.Size,
+		Total:   total,
+		Pages:   int(pages),
+	}, nil
+}

+ 162 - 0
app/operation/service/captureVehicleTypeExService.go

@@ -0,0 +1,162 @@
+package service
+
+import (
+	"iot_manager_service/app/device/dao"
+	"iot_manager_service/app/operation/edge_service"
+	"iot_manager_service/app/operation/model"
+	systemService "iot_manager_service/app/system/service"
+	"iot_manager_service/util/common"
+	"strconv"
+)
+
+// CaptureVehicleTypeExService 车型统计
+var CaptureVehicleTypeExService = new(captureVehicleTypeExService)
+
+type captureVehicleTypeExService struct{}
+
+// GetVehicleList 得到下方前10的详细数据 list
+func (s captureVehicleTypeExService) GetVehicleList(tenantId int, req model.RequestCaptureFilter) (interface{}, error) {
+	//得到边缘数据
+	flag, forData, err := s.getData(tenantId, req)
+
+	//得到排名前10的省或城市
+	getTop10 := s.getTop10(forData, req.Type)
+	var topArr []string
+	for _, Vehicle := range getTop10 {
+		topArr = append(topArr, Vehicle.Name)
+	}
+
+	//将所有省份或城市 数据组装成 map {time:[{Name:"xxx", Value:11}]}
+	mdata := make(map[string][]model.TmpCapture)
+	for _, datum := range forData {
+		time := datum.Time
+		if flag == 1 {
+			time += "-01"
+		}
+		name := s.getVtypeName(datum.Vtype)
+
+		mm := model.TmpCapture{
+			Name:  name,
+			Value: datum.Total,
+		}
+		mdata[time] = append(mdata[time], mm)
+	}
+
+	//时间范围内的月份或天的明细列表
+	var countTimes []string
+	if flag == 1 {
+		countTimes = common.GetTimeMonths(req.StartTime, req.EndTime) //时间范围 月
+	} else {
+		countTimes = common.GetTimeDays(req.StartTime, req.EndTime) //时间范围 天
+	}
+
+	//每日|每月 前10的数据 组装
+	var list []model.TmpCaptures
+	for _, countTime := range countTimes {
+		//得到总排名前10的,当天|当月 数据
+		var tmpsData []model.TmpCapture
+		for _, Vehicle := range getTop10 {
+			value := mdata[countTime]
+			val := 0
+			for _, i := range value {
+				if Vehicle.Name == i.Name {
+					val += i.Value
+				}
+				i.Value = 0
+			}
+			tmpsData = append(tmpsData, model.TmpCapture{
+				Name:  Vehicle.Name,
+				Value: val,
+			})
+		}
+		//按日期 组装 前10名的每天或每月数据
+		list = append(list, model.TmpCaptures{
+			CountTime:       countTime,
+			TmpCapturesData: tmpsData,
+		})
+	}
+
+	//按前端要求的格式,组装数据
+	var list2 []model.TmpCaptures
+	for _, Vehicles := range list {
+		data := model.ViewData(Vehicles)
+		if len(data.TmpCapturesData) > 0 {
+			list2 = append(list2, data)
+		}
+	}
+	if err != nil {
+		return nil, err
+	}
+	return list2, nil
+}
+
+// GetVehicleTypeList 前10的地区 和 数量 line 图表
+func (s captureVehicleTypeExService) GetVehicleTypeList(tenantId int, req model.RequestCaptureFilter) (interface{}, error) {
+	//得到全部数据
+	_, forData, err := s.getData(tenantId, req)
+
+	// 得到排名前10的省或城市
+	getTop10 := s.getTop10(forData, req.Type)
+	var tmp model.TmpCaptures
+	tmp.TmpCapturesData = getTop10
+
+	//按前端要求的格式,组装数据
+	data := model.ViewData(tmp)
+	return data, err
+}
+
+//得到边缘接口 时间范围数据
+func (s captureVehicleTypeExService) getData(tenantId int, req model.RequestCaptureFilter) (int, []edge_service.ForCaptureItsData, error) {
+	//区分按月或按日
+	flag := 0
+	if req.QueryType == "month" {
+		flag = 1
+	}
+
+	//查出抓拍单元sn
+	unit := dao.CaptureUnit{
+		TenantId: tenantId,
+		ID:       req.CaptureId,
+	}
+	unit.GetDevice()
+	var codes []string
+	codes = append(codes, unit.CaptureSn)
+
+	forCaptureIts := edge_service.ForCaptureIts{}
+	var forData []edge_service.ForCaptureItsData
+	var err error
+	forData, err = forCaptureIts.Vehicletypeex(edge_service.ForCaptureItsReq{
+		Codes: codes,
+		Start: req.StartTime,
+		End:   req.EndTime,
+		Flag:  flag,
+	})
+	return flag, forData, err
+}
+
+//得到 前10
+func (s captureVehicleTypeExService) getTop10(data []edge_service.ForCaptureItsData, typeInt int) model.PairList {
+	//拼全部数据
+	allData := make(map[string]int)
+	for _, datum := range data {
+		name := s.getVtypeName(datum.Vtype)
+		allData[name] += datum.Total
+	}
+	//对数据排序
+	top10Data := model.RankByWordCount(allData)
+	//取前10
+	if len(top10Data) >= 10 {
+		top10Data = top10Data[:10]
+	}
+	return top10Data
+}
+
+// getVtypeName 根据车型编号  取字典中的名称
+func (s captureVehicleTypeExService) getVtypeName(vtype int) string {
+	name := strconv.Itoa(vtype)
+	if vtype > 34 {
+		return "其它"
+	}
+	dict := systemService.DictService.GetCacheDict("car_model_type"+name, "car_model_type", vtype)
+	return dict
+}

+ 6 - 1
app/warn/dao/platformAlarmDao.go

@@ -3,6 +3,7 @@ package dao
 import (
 	"errors"
 	"gorm.io/gorm"
+	"gorm.io/gorm/clause"
 	"iot_manager_service/app/warn/model"
 	"iot_manager_service/util/common"
 	"time"
@@ -80,7 +81,11 @@ func (a PlatformAlarm) GetMaxIdAndUpDateTime() (int64, string) {
 }
 
 func (a PlatformAlarm) BatchCreate(his []PlatformAlarm) error {
-	return Db.Debug().CreateInBatches(his, 1000).Error
+	db := Db.Debug()
+	db = db.Clauses(clause.OnConflict{
+		Columns: []clause.Column{{Name: "ID"}}, //  这里的列必须是唯一的,比如主键或是唯一索引
+	})
+	return db.CreateInBatches(his, 1000).Error
 }
 
 func (a PlatformAlarm) Update() error {

+ 1 - 0
app/warn/edge_service/syncAlarmService.go

@@ -35,6 +35,7 @@ type RecordAlarmRecordData struct {
 
 // SyncAlartRecord  同步报警 数据
 func (r *RecordAlarmRecord) SyncAlartRecord(maxId int64, maxUpDateTime string) ([]RecordAlarmRecordData, error) {
+	maxId += 1
 	cfg := config.Instance()
 	api := cfg.Foreign.IotEdgeUrl + "/data/v1/alarm/sync"
 	url := fmt.Sprintf("%v?id=%d&&updatedat=%v", api, maxId, url2.QueryEscape(maxUpDateTime))

+ 2 - 0
go.mod

@@ -14,6 +14,7 @@ require (
 	github.com/robfig/cron v1.2.0
 	github.com/satori/go.uuid v1.2.0
 	github.com/sirupsen/logrus v1.9.0
+	gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
 	gopkg.in/yaml.v2 v2.4.0
 	gorm.io/driver/mysql v1.4.4
 	gorm.io/gorm v1.24.1
@@ -60,5 +61,6 @@ require (
 	golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
 	golang.org/x/text v0.3.7 // indirect
 	google.golang.org/protobuf v1.28.0 // indirect
+	gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
 	gopkg.in/ini.v1 v1.66.6 // indirect
 )

+ 25 - 2
router/router.go

@@ -568,7 +568,7 @@ func InitRouter(engine *gin.Engine) {
 	operationGroup.POST("/energy/list", operation.LightingRate.List)
 	//运营统计-告警统计
 	operationGroup.POST("/alarm/list", operation.Alarm.List)
-
+	//告警管理
 	warnGroup := engine.Group("/api/longchi/alarm")
 	{
 		//告警设置
@@ -604,6 +604,29 @@ func InitRouter(engine *gin.Engine) {
 			businesstacticsGroup.POST("/remove", warn.BusinessTactics.Remove)
 			businesstacticsGroup.POST("/enable-disable", warn.BusinessTactics.Enable)
 		}
-
 	}
+	//智慧交通
+	captureGroup := operationGroup.Group("/capture")
+	{
+		//车流汇总
+		captureGroup.GET("affiliation/count-list", operation.Capture.CountList)
+		captureGroup.POST("speed/getSuggestSpeed", operation.Capture.SuggestSpeed)
+		//归属地统计
+		captureGroup.GET("affiliation/list", operation.Capture.AreaList)
+		captureGroup.GET("affiliation/type-list", operation.Capture.AreaTypeList)
+		//车型统计
+		captureGroup.GET("model/list", operation.Capture.VehicleTypeEx)
+		captureGroup.GET("model/type-list", operation.Capture.VehicleTypeList)
+		//车速统计
+		captureGroup.GET("speed/list", operation.Capture.SpeedList)
+		captureGroup.GET("speed/over-speed-record", operation.Capture.OverSpeedRecord)
+		captureGroup.GET("speed/over-speed-record-sync", operation.Capture.OverSpeedRecordSync)
+		//时段统计
+		captureGroup.GET("periods/list", operation.Capture.PeriodsList)
+		//货车统计
+		captureGroup.GET("carrecord/count", operation.Capture.CarrecordCount)
+		//报表统计
+		captureGroup.GET("report/list", operation.Capture.ReportList)
+	}
+
 }

+ 19 - 18
util/common/common.go

@@ -215,8 +215,11 @@ func TimeStringToGoTime(tm string) time.Time {
 
 // GetTimeDays 时间区间的所有天数
 func GetTimeDays(start_time, stop_time string) []string {
-	tm1, _ := time.Parse("2006-01-02", start_time)
-	tm2, _ := time.Parse("2006-01-02", stop_time)
+	star := []rune(start_time)
+	end := []rune(stop_time)
+	tm1, _ := time.Parse("2006-01-02", string(star[:10]))
+	tm2, _ := time.Parse("2006-01-02", string(end[:10]))
+	//fmt.Printf("star = %v \n", string(star[:10]))
 	sInt := tm1.Unix()
 	eInt := tm2.Unix()
 	var args []string
@@ -230,7 +233,7 @@ func GetTimeDays(start_time, stop_time string) []string {
 	}
 	var days []string
 	for i := 0; i < len(args); i++ {
-		parse, _ := time.Parse("2006-01-02", start_time)
+		parse, _ := time.Parse("2006-01-02", string(star[:10]))
 		date := parse.AddDate(0, 0, i).Format("2006-01-02")
 		days = append(days, date)
 	}
@@ -239,24 +242,13 @@ func GetTimeDays(start_time, stop_time string) []string {
 
 // GetTimeMonths 时间区间的所有月份
 func GetTimeMonths(start_time, stop_time string) []string {
-	tm1, _ := time.Parse("2006-01", start_time)
-	tm2, _ := time.Parse("2006-01", stop_time)
-	sInt := tm1.Unix()
-	eInt := tm2.Unix()
-	var args []string
-	for {
-		sInt += 86400
-		st := time.Unix(sInt, 0).Format("20060102")
-		args = append(args, st)
-		if sInt > eInt {
-			break
-		}
-	}
+	star := []rune(start_time)
+	end := []rune(stop_time)
 	var months []string
 	i := 0
 	for {
-		parse, _ := time.Parse("2006-01-02", start_time)
-		endStr, _ := time.Parse("2006-01-02", stop_time)
+		parse, _ := time.Parse("2006-01", string(star[:7]))
+		endStr, _ := time.Parse("2006-01", string(end[:7]))
 		month := parse.AddDate(0, i, 0).Format("2006-01")
 		month = month + "-01"
 		months = append(months, month)
@@ -281,3 +273,12 @@ func Reverse(s []string) []string {
 	}
 	return s
 }
+
+func InIntArr(target int, str_array []int) bool {
+	for _, element := range str_array {
+		if target == element {
+			return true
+		}
+	}
+	return false
+}