package controllers import ( "bytes" "encoding/base64" "encoding/json" "fmt" "image" "io/ioutil" "os" "path/filepath" "sort" "strconv" "strings" "unsafe" "vamicro/camera-common/models" commonSv "vamicro/camera-common/service" service2 "vamicro/saas-service/service" scs "vamicro/scene-service/controllers" "basic.com/pubsub/protomsg.git" "basic.com/valib/bhomeclient.git" "basic.com/valib/bhomedbapi.git" "basic.com/valib/go-aiot.git/aiotProto/aiot" "basic.com/valib/logger.git" //"vamicro/camera-common/service/uniquelCoordinate" "vamicro/camera-common/vo" "vamicro/config" "vamicro/extend/util" "vamicro/gb28181-service/cache" gbModels "vamicro/gb28181-service/models" "vamicro/gb28181-service/service" ) type Gb28181Controller struct { } // @Summary 获取所有摄像机列表及信息 // @Description "获取所有摄像机列表及信息" // @Produce json // @Tags gb28181 // @Param cameraName query string false "摄像机名称" // @Param runType query string false "0:全部,1:分析,2:监控,3:联动" // @Param cameraId query string false "摄像机id" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/showAll [get] func (gbc Gb28181Controller) GetAllCameras(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { cameraName := c.Query("cameraName") cameraType, _ := strconv.Atoi(c.Query("runType")) cameraId := c.Query("cameraId") areaId := c.Query("areaId") var cam models.Camera lkMap := make(map[string]string) linkWhere := "" if cameraType == 3 { //查联动 var crApi bhomedbapi.CameraRuleApi lb, lkList := crApi.FindAllCameraLink() if !lb { return &bhomeclient.Reply{Msg: "查询联动配置失败"} } if len(lkList) == 0 { return &bhomeclient.Reply{Success: true, Data: []struct{}{}} } for _, lc := range lkList { cArr := strings.Split(lc.CameraIds, ",") for _, lcId := range cArr { if _, ok := lkMap[lcId]; !ok { lkMap[lcId] = lcId } } } for k := range lkMap { linkWhere += "'" + k + "'," } linkWhere = strings.TrimRight(linkWhere, ",") } cams, err := cam.FindAllByServer("", cameraName, cameraType, cameraId, areaId, linkWhere) if err != nil { return &bhomeclient.Reply{Msg: err.Error()} } else { return &bhomeclient.Reply{Success: true, Data: cams} } } // @Summary 更新摄像机 // @Description "用于更新摄像机操作" // @Accept json // @Produce json // @Tags gb28181 // @Param cam body vo.CameraEditVo true "id:摄像机id default:cid0 (string), areaid:摄像机关联区域id default:1 (int), name:摄像机名字 default:Testname(string) 必填; 其他参数可配 " // @Success 200 {string} json "{"code":200, success:true, msg:"请求处理成功", data:"修改后的摄像机信息"}" // @Failure 500 {string} json "{"code":500, success:false msg:"null",data:"错误信息内容"}" // @Router /data/api-v/gb28181/camera/update [put] func (gbc Gb28181Controller) CameraUpdate(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var camVo vo.CameraEditVo err := c.BindJSON(&camVo) if err != nil { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } logger.Debug("update sensors:", camVo.Sensors) var sv commonSv.CameraService if b, e := sv.CameraUpdate(camVo); b { sv := service.NewGb28181Service(h.Bk) sv.AddDbChangeMsg(protomsg.DbAction_Update) return &bhomeclient.Reply{Success: true, Data: camVo.Copy2Camera()} } else { return &bhomeclient.Reply{Success: false, Msg: e.Error()} } } // @Summary 显示摄像机 // @Description "显示摄像机" // @Produce json // @Tags gb28181 // @Param cid path string true "摄像机id" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"", data:""}" // @Router /data/api-v/gb28181/camera/show [get] func (gbc Gb28181Controller) CameraSel(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var cam models.Camera cid := c.Query("cid") rows, err := cam.SelectById(cid) if err != nil { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } if rows == 0 { return &bhomeclient.Reply{Success: false, Msg: "没有记录"} } m := util.Struct2Map(cam) var sor models.Sensor sensors, _ := sor.FindByCameraId(cid) if sensors != nil { m["sensors"] = sensors } else { m["sensors"] = []models.Sensor{} } //摄像机分辨率 dRe0 := models.Resolution{ Width: 0, Height: 0, } dRe1 := models.Resolution{ Width: 1920, Height: 1080, } dRe2 := models.Resolution{ Width: 2688, Height: 1520, } m["resolutions"] = []models.Resolution{dRe0, dRe1, dRe2} //处理摄像机的状态 var crApi bhomedbapi.CameraRuleApi if cam.RunType == models.TYPE_RUNTYPE_POLL || cam.RunType == models.TYPE_RUNTYPE_REALTIME { if crApi.ExistRunningTask(cam.Id) { if cam.IsRunning { m["status"] = models.Camera_Status_Doing } else { m["status"] = models.Camera_Status_Wait } } else { m["status"] = models.Camera_Status_NoRule } } else { m["status"] = models.Camera_Status_Err } if cam.RunServerId != "" { if cam.RunServerId == config.Server.AnalyServerId { lc, e := cache.GetServerInfo() if e == nil { m["runServerName"] = lc.ServerName } } else { //属于其他服务器 var cluApi bhomedbapi.ClusterApi flag, info := cluApi.FindCluster() if flag && info.ClusterId != "" && len(info.Nodes) > 0 { for _, n := range info.Nodes { if cam.RunServerId == n.NodeId { m["runServerName"] = n.NodeName break } } } } } return &bhomeclient.Reply{Success: true, Data: m} } // @Summary 显示gb28181树形结构 // @Description 显示gb28181树形结构 // @Produce json // @Tags 国标目录树 // @Param parentId query string true "区域的id" // @Param searchType query int true "查询类型(0:全部,1:分析摄像机,2:监控摄像机, 3:联动摄像机)" // @Param cameraName query string false "摄像机名称" // @Success 200 {string} json "{"code":200, msg:"目录结构数据"}" // @Failure 500 {string} json "{"code":500, msg:"返回错误信息"}" // @Router /data/api-v/gb28181/tree [get] func (gbc Gb28181Controller) CameraGb28181Tree(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var aram models.Area var searchType = 0 var err error parentId := c.Query("parentId") if parentId == "" { parentId = "0" } searchTypeStr := c.Query("searchType") cameraName := c.Query("cameraName") treeType := models.TYPE_GB28181_TREE //国标树 isPlatformStr := c.Query("isPlatform") isPlatform, _ := strconv.Atoi(isPlatformStr) //单机获取本机摄像机,平台获取所有摄像机 if searchTypeStr != "" { searchType, err = strconv.Atoi(searchTypeStr) if err != nil { logger.Debug("err:", err) return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } } areas, err := aram.Find(parentId, cameraName, util.FiledbyStuct(models.TreeNode{}), treeType) if err != nil { logger.Debug("area.Find err:", err) return &bhomeclient.Reply{Success: false, Msg: err.Error()} } lkMap := make(map[string]string) linkWhere := "" if searchType == 3 { //查联动 var crApi bhomedbapi.CameraRuleApi lb, lkList := crApi.FindAllCameraLink() if !lb { return &bhomeclient.Reply{Msg: "查询联动配置失败"} } if len(lkList) == 0 { return &bhomeclient.Reply{Success: true, Data: []struct{}{}} } for _, lc := range lkList { cArr := strings.Split(lc.CameraIds, ",") for _, lcId := range cArr { if _, ok := lkMap[lcId]; !ok { lkMap[lcId] = lcId } } } for k := range lkMap { linkWhere += "'" + k + "'," } linkWhere = strings.TrimRight(linkWhere, ",") } var cam models.Camera cams, err := cam.Find(searchType, cameraName, models.TYPE_GB28181_CAMERA, isPlatform, linkWhere) //查国标摄像机 if err != nil { logger.Debug("cam.Find err:", err) return &bhomeclient.Reply{Success: false, Msg: err.Error()} } var totalCams models.CamTreeNodeList totalCams = cams sort.Sort(totalCams) rAreas := models.RecursiveArea(areas, cams, searchType) allRules, e2 := cache.GetCameraRules() ruleM := make(map[string]protomsg.CameraAndRules) if e2 == nil && allRules != nil { for _, r := range allRules { if r.CameraInfo != nil { ruleM[r.CameraInfo.Id] = r } } } var totalAreas models.AreaList totalAreas = rAreas sort.Sort(totalAreas) arr := menuFormat(totalAreas, parentId, totalCams, treeType, ruleM) for _, camE := range totalCams { if camE.Areaid == "0" { isRunnig := false isAI := false camera := models.Camera{} rows, e := camera.SelectById(camE.Id) if rows > 0 && e == nil { isRunnig = camera.IsRunning if crInfo, ok := ruleM[camera.Id]; ok && crInfo.Rules != nil && len(crInfo.Rules) > 0 && (camera.RunType == models.TYPE_RUNTYPE_POLL || camera.RunType == models.TYPE_RUNTYPE_REALTIME) { isAI = true } //if camera.RunType == models.TYPE_RUNTYPE_POLL || camera.RunType == models.TYPE_RUNTYPE_REALTIME { // isAI = true //} } arr = append(arr, models.TreeMenu{ Id: camE.Id, Type: "4", Name: camE.Name, IsRunning: isRunnig, IsAI: isAI, Rtsp: camE.Rtsp, CameraType: treeType, }) } } return &bhomeclient.Reply{Success: true, Data: arr} } // 将区域和摄像机数组转换目录树形结构 func menuFormat(dbArr []models.Area, parentId string, dbCams []models.CameraTreeNode, treeType int, ruleM map[string]protomsg.CameraAndRules) []models.TreeMenu { var arr []models.TreeMenu for _, area := range dbArr { if parentId == area.Parentid { tmp := models.TreeMenu{} tmp.Id = area.Id tmp.Type = "MENU" tmp.Name = area.Name sontmp := menuFormat(dbArr, area.Id, dbCams, treeType, ruleM) tmp.Areanodes = sontmp for _, val := range dbCams { if val.Areaid == area.Id { camtmp := models.TreeMenu{} camtmp.Id = val.Id camtmp.Name = val.Name camtmp.Type = "4" isRunnig := false isAI := false camera := models.Camera{} rows, e := camera.SelectById(val.Id) if rows > 0 && e == nil { isRunnig = camera.IsRunning if crInfo, ok := ruleM[camera.Id]; ok && crInfo.Rules != nil && len(crInfo.Rules) > 0 && (camera.RunType == models.TYPE_RUNTYPE_POLL || camera.RunType == models.TYPE_RUNTYPE_REALTIME) { isAI = true } //if camera.RunType == models.TYPE_RUNTYPE_POLL || camera.RunType == models.TYPE_RUNTYPE_REALTIME { // isAI = true //} } camtmp.IsAI = isAI camtmp.IsRunning = isRunnig camtmp.Rtsp = val.Rtsp camtmp.CameraType = treeType tmp.Areanodes = append(tmp.Areanodes, camtmp) } } arr = append(arr, tmp) } } return arr } // @Summary 刷新Gb28181平台树 // @Description 刷新Gb28181平台树 // @Produce json // @Tags 国标目录树 // @Param id formData string false "国标平台id" // @Success 200 {string} json "{"code":200, data:"",msg:"请求成功", success:true}" // @Failure 200 {string} json "{"code":500, data:"",msg:"请求失败", success:false}" // @Router /data/api-v/gb28181/treeRefresh [post] func (gbc Gb28181Controller) Gb28181TreeRefresh(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { id := c.PostForm("id") sv := service.NewGb28181Service(h.Bk) if b, d := sv.RefreshById(id); b { return &bhomeclient.Reply{Success: true, Msg: "刷新成功", Data: d} } else { return &bhomeclient.Reply{Success: false, Msg: "刷新失败"} } } // @Summary 获取国标资源 // @Description 获取国标资源 // @Produce json // @Tags 国标资源 // @Success 200 {string} json "{"code":200, data:"",msg:"请求成功", success:true}" // @Failure 200 {string} json "{"code":500, data:"",msg:"请求失败", success:false}" // @Router /data/api-v/gb28181/getAllChannel [post] func (gbc Gb28181Controller) GetAllChannel(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { sv := service.NewGb28181Service(h.Bk) if b, d := sv.RefreshAllChannel(); b { return &bhomeclient.Reply{Success: true, Msg: "刷新成功", Data: d} } else { return &bhomeclient.Reply{Success: false, Msg: "刷新失败"} } } // @Summary 删除Gb28181平台 // @Description 删除Gb28181平台 // @Produce json // @Tags 国标目录树 // @Success 200 {string} json "{"code":200, data:"",msg:"请求成功", success:true}" // @Failure 200 {string} json "{"code":500, data:"",msg:"请求失败", success:false}" // @Router /data/api-v/gb28181/treeDelete [post] func (gbc Gb28181Controller) Gb28181TreeDelete(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { sv := service.NewGb28181Service(h.Bk) if sv.Delete() { return &bhomeclient.Reply{Success: true, Msg: "删除成功"} } else { return &bhomeclient.Reply{Success: false, Msg: "删除失败"} } } // @Summary 获取国标区域列表 // @Description 获取国标区域列表 // @Produce json // @Tags gb28181 // @Param parentId query int true "parentId" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:"成功信息"}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:"错误信息内容"}" // @Router /data/api-v/gb28181/findAreaByParentId [get] func (gbc Gb28181Controller) FindAreaByParentId(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { parentIdStr := c.Query("parentId") if parentIdStr == "" { parentIdStr = "0" } parentId, err := strconv.Atoi(parentIdStr) if err != nil { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } var gbaE gbModels.GbCodeArea list, _ := gbaE.FindByParentId(parentId) if list == nil { list = []gbModels.GbCodeArea{} } return &bhomeclient.Reply{Success: true, Data: list} } // @Summary 生成新的国标id // @Description 生成新的国标id // @Produce json // @Tags gb28181 // @Param code query string true "行政区域编码" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:"成功信息"}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:"错误信息内容"}" // @Router /data/api-v/gb28181/newGbId [get] func (gbc Gb28181Controller) NewGbId(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { areaCode := c.Query("code") if areaCode == "" { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } //生成新的国标id,生成规则:系统编码 =中心编码(8位) + 行业编码(2) + 类型编码(11-13位) + 序号(最后7位) //1.code为6位行政区划编码,后面需要接2位的基层接入单位编号 if len(areaCode) >= 6 { areaCode = areaCode[:6] } areaCode = areaCode + "00" newGbCode := areaCode //2.行业编码,第9、10位 //00 社会治安路面接入 //01 社会治安社区接入 //02 社会治安内部接入 //03 社会治安其他接入 //04 交通路面接入 //05 交通卡口接入 //06 交通内部接入 //07 交通其他接入 //08 城市管理接入 //09 卫生环保接入 //10 商检海关接入 //11 教育部门接入 newGbCode += "01" //设备或用户的具体类型,其中的前端设备包含公安系统和非公安系统的前端设备, //终端用户包含公安系统和非公安系统的终端用户。由3位数字组成,即20位国标编码中的第11、12、13位。 //3.设备或用户的具体类型,第11、12、13位 //111 DVR编码 //112 视频服务器编码 //113 编码器编码 //114 解码器编码 //115 视频切换矩阵编码 //116 音频切换矩阵编码 //117 报警控制器编码 //118 网络视频录像机(NVR)编码 //130 混合硬盘录像机(HVR)编码 //119~130 扩展的前端主设备类型 //131 摄像机编码 //132 网络摄像机(IPC)编码 //133 显示器编码 //134 报警输入设备编码(如红外、烟感、门禁等报警设备) //135 报警输出设备编码(如警灯、警铃等设备) //136 语音输入设备编码 //137 语音输出设备 //138 移动传输设备编码 newGbCode += "112" //4. 14位为网络标识 (0、1、2、3、4为监控报警专网,5为公安信息网,6为政务网,7为Internet网, // 8为社会资源接入网,9为预留) newGbCode += "1" //5.序号指设备或用户的序号。由6位数字组成,即20位国标编码中的15-20位。 newGbCode += "000001" logger.Debug("newGbCode:", newGbCode) return &bhomeclient.Reply{Success: true, Data: newGbCode} } // @Summary GB28181设置查询 // @Description GB28181设置信息查询 // @Accept json // @Produce json // @Tags gb28181 // @Success 200 {string} json "{"code":200, msg:"目录结构数据", success:true}" // @Failure 500 {string} json "{"code":500, msg:"返回错误信息", success:false}" // @Router /data/api-v/gb28181/configShow [GET] func (gbc Gb28181Controller) Gb28181ConfigShow(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var conf gbModels.Gb28181Config conf.Select() proId := "" cityId := "" zoneId := "" if conf.PublicId != "" && len(conf.PublicId) > 6 { confAreaId := conf.PublicId[:6] var tmpArea gbModels.GbCodeArea tId, _ := strconv.Atoi(confAreaId) rows, _ := tmpArea.SelectById(tId) if rows > 0 { if tmpArea.Level == 3 { zoneId = confAreaId cityId = strconv.Itoa(tmpArea.ParentId) var cityArea gbModels.GbCodeArea crows, _ := cityArea.SelectById(tmpArea.ParentId) if crows > 0 { proId = strconv.Itoa(cityArea.ParentId) } } else if tmpArea.Level == 2 { cityId = confAreaId proId = strconv.Itoa(tmpArea.ParentId) } else if tmpArea.Level == 1 { proId = confAreaId } } } m := util.Struct2Map(conf) m["proId"] = proId m["cityId"] = cityId m["zoneId"] = zoneId return &bhomeclient.Reply{Success: true, Data: m} } // @Summary GB28181设置信息修改 // @Description GB28181设置修改 // @Accept json // @Produce json // @Tags gb28181 // @Param config body models.Gb28181Config true "GB28181设置数据" // @Success 200 {string} json "{"code":200, msg:"目录结构数据", success:true}" // @Failure 500 {string} json "{"code":500, msg:"返回错误信息", success:false}" // @Router /data/api-v/gb28181/configEdit [POST] func (gbc Gb28181Controller) Gb28181ConfigEdit(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var reqCon gbModels.Gb28181Config // 前台数据绑定 if err := c.BindJSON(&reqCon); err != nil { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } logger.Debug("gbConfig:", reqCon) sv := service.NewGb28181Service(h.Bk) if sv.Edit(reqCon) { return &bhomeclient.Reply{Success: true, Msg: "保存成功"} } else { return &bhomeclient.Reply{Success: false, Msg: "保存失败"} } } type Gb28181config struct { GbConfig gbModels.Gb28181Config `json:"gbConfig"` } func (gbc Gb28181Controller) SaasGb28181ConfigEdit(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var reqCon Gb28181config // 前台数据绑定 if err := c.BindJSON(&reqCon); err != nil { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } logger.Debug("gbConfig:", reqCon) sv := service.NewGb28181Service(h.Bk) if sv.Edit(reqCon.GbConfig) { return &bhomeclient.Reply{Success: true, Msg: "保存成功"} } else { return &bhomeclient.Reply{Success: false, Msg: "保存失败"} } } // @Security ApiKeyAuth // @Summary 获取国标下级接入平台列表 // @Description 获取国标下级接入平台列表 // @Produce json // @Tags gb28181 // @Success 200 {string} json "{"code":200, success:true, msg:"", data:"成功信息"}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:"错误信息内容"}" // @Router /data/api-v/gb28181/getAllSubServer [get] func (gbc Gb28181Controller) GetAllSubServer(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { sv := service.NewGb28181Service(h.Bk) b, d := sv.GetAllSubServer() if b { return &bhomeclient.Reply{Success: true, Data: d} } else { return &bhomeclient.Reply{Msg: "获取失败"} } } func (gbc Gb28181Controller) GetGb28181VssTable(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { sv := service.NewGb28181Service(h.Bk) data := sv.GetGb28181VssTable() return &bhomeclient.Reply{Success: true, Data: data} } type SaveMenus struct { Menus []service.GbTreeMenu `json:"checkedMenus"` } func (gbc Gb28181Controller) SaveGb28181CamTree(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var reqBody SaveMenus if err := c.BindJSON(&reqBody); err != nil { return &bhomeclient.Reply{Msg: "参数有误"} } sv := service.NewGb28181Service(h.Bk) if b, err := sv.SaveGb28181CamTree(reqBody.Menus); b { return &bhomeclient.Reply{Success: true, Msg: "保存成功"} } else { return &bhomeclient.Reply{Msg: "保存失败:" + err.Error()} } } // @Summary 获取运行类型获取摄像机列表 // @Description 获取运行类型获取摄像机列表 // @Produce json // @Tags gb28181 // @Param runType query int true "0:查轮询,1:查实时" // @Param cameraName query string false "查询条件" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/getCamerasByRunType [get] func (gbc Gb28181Controller) GetCamerasByRunType(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { runTypeStr := c.Query("runType") cameraName := c.Query("cameraName") logger.Debug("runType:", runTypeStr) logger.Debug("cameraName:", cameraName) runType, err := strconv.Atoi(runTypeStr) if err != nil || (runType != 0 && runType != 1) { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } var sv commonSv.CameraService list, err := sv.GetCamerasByRunType(runType, cameraName) if err != nil { return &bhomeclient.Reply{Success: false, Msg: err.Error()} } else { return &bhomeclient.Reply{Success: true, Data: list} } } // @Summary 切换摄像机运行实时或轮询的开关 // @Description 切换摄像机运行实时或轮询的开关 // @Produce json // @Tags gb28181 // @Param cameraId formData string true "摄像机id" // @Param runEnable formData bool true "开启:true,关闭:false" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/updateRunEnable [post] func (gbc Gb28181Controller) UpdateRunEnable(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { cameraId := c.PostForm("cameraId") enableStr := c.PostForm("runEnable") runEnable, _ := strconv.ParseBool(enableStr) if cameraId == "" { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } var sv commonSv.CameraService if sv.UpdateRunEnable(cameraId, runEnable) { sv := service.NewGb28181Service(h.Bk) sv.AddDbChangeMsg(protomsg.DbAction_Update) return &bhomeclient.Reply{Success: true, Msg: "更新成功"} } else { return &bhomeclient.Reply{Success: false, Msg: "更新失败"} } } // @Summary 摄像机轮询和实时状态切换 // @Description 摄像机轮询和实时状态切换 // @Produce json // @Tags gb28181 // @Param changeRunBody body vo.CameraChangeRunVo true "参数结构体,0:实时切轮询,1:轮询切实时" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/changeRunType [post] func (gbc Gb28181Controller) ChangeRunType(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var ccrVo vo.CameraChangeRunVo if err := c.BindJSON(&ccrVo); err != nil { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } var sv commonSv.CameraService if sv.ChangeRunType(ccrVo) { sv := service.NewGb28181Service(h.Bk) sv.AddDbChangeMsg(protomsg.DbAction_Update) return &bhomeclient.Reply{Success: true, Msg: "更新成功"} } else { return &bhomeclient.Reply{Success: false, Msg: "更新失败"} } } // @Summary 摄像机is_running状态切换 // @Description 摄像机is_running状态切换 // @Produce json // @Tags gb28181 // @Param cameraId formData string true "摄像机id" // @Param is_running formData bool true "解码中:true,停止解码:false" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/updateIsRunningState [post] func (gbc Gb28181Controller) UpdateIsRunningState(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { cameraId := c.PostForm("cameraId") isRunningStr := c.PostForm("isRunning") isRunning, _ := strconv.ParseBool(isRunningStr) if cameraId == "" { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } var sv commonSv.CameraService if sv.UpdateIsRunningState(cameraId, isRunning) { sv := service.NewGb28181Service(h.Bk) sv.AddDbChangeMsg(protomsg.DbAction_Update) return &bhomeclient.Reply{Success: true, Msg: "更新成功"} } else { return &bhomeclient.Reply{Success: false, Msg: "更新失败"} } } type IsRunningArg struct { CameraIds []string `json:"cameraIds"` } // @Router /data/api-v/gb28181/camera/updateIsRunningAll [post] func (gbc Gb28181Controller) UpdateIsRunningAll(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var reqBody IsRunningArg c.BindJSON(&reqBody) logger.Debug("UpdateIsRunningAll cameraId:", reqBody.CameraIds) var sv commonSv.CameraService if sv.UpdateIsRunningAll(reqBody.CameraIds) { sv := service.NewGb28181Service(h.Bk) sv.AddDbChangeMsg(protomsg.DbAction_Update) return &bhomeclient.Reply{Success: true, Msg: "更新成功"} } else { return &bhomeclient.Reply{Success: false, Msg: "更新失败"} } } // @Summary 更新摄像机快照 // @Description 更新摄像机快照 // @Produce json // @Tags gb28181 // @Param cameraId formData string true "摄像机id" // @Param snapshot formData string true "快照地址" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/updateSnapshotUrl [post] func (gbc Gb28181Controller) UpdateSnapshot(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { cameraId := c.Query("cameraId") logger.Debug("cameraId:", cameraId) if cameraId == "" { return &bhomeclient.Reply{Msg: "参数有误"} } var csv commonSv.CameraService flag, camInfo := csv.GetById(cameraId) if !flag { return &bhomeclient.Reply{Msg: "获取摄像机失败"} } ////////////////////////////////////////////////// /* 将capture的图片保存在本地 因为网页请求时有5s超时,在此期间很可能拿不到图片 */ const baseMapDir = "./gb28181BaseMapDir/" baseMapFile := baseMapDir + cameraId rep := &bhomeclient.Reply{Msg: "未查找到预存的图片"} if _, base64Str, _ := service.UpdateCapture(camInfo.Type, camInfo.Rtsp, "", camInfo.Name); len(base64Str) > 0 { rep = &bhomeclient.Reply{ Success: true, Msg: "从本地[cameraBaseMapDir]获取图片base64", Data: map[string]string{ "cameraId": cameraId, "snapshotUrl": "", "base64": base64Str, }, } _, err := os.Stat(baseMapDir) if os.IsNotExist(err) { if err := os.MkdirAll(baseMapDir, 0755); err != nil { logger.Debug("======>> 未获取到图片文件夹") fmt.Println("======>> 未获取到图片文件夹") } logger.Debug("======>> create basemap directory") fmt.Println("======>> create basemap directory") } tmp := (*[2]uintptr)(unsafe.Pointer(&base64Str)) tmp2 := [3]uintptr{tmp[0], tmp[1], tmp[1]} b64 := *(*[]byte)(unsafe.Pointer(&tmp2)) if err := ioutil.WriteFile(baseMapFile, b64, 0644); err != nil { logger.Debug("======>> WriteFile Image BaseMap Failed") fmt.Println("======>> WriteFile Image BaseMap Failed") } } else { // 首先查找是否存在此照片 found := false filepath.Walk(baseMapDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if !info.IsDir() && info.Name() == cameraId { found = true return nil } return nil }) if found { if image, err := ioutil.ReadFile(baseMapFile); err == nil { logger.Debug("======>> 获取图片,发送回去") fmt.Println("======>> 获取图片,发送回去") rep = &bhomeclient.Reply{ Success: true, Msg: "从本地[cameraBaseMapDir]获取图片base64", Data: map[string]string{ "cameraId": cameraId, "snapshotUrl": "", "base64": *(*string)(unsafe.Pointer(&image)), }, } } } } return rep /* 将capture的图片保存在本地 因为网页请求时有5s超时,在此期间很可能拿不到图片 */ ////////////////////////////////////////////////////////// var sysApi bhomedbapi.SysSetApi sb, sysconf := sysApi.GetServerInfo() if !sb || sysconf.WebPicIp == "" { return &bhomeclient.Reply{Msg: "未获取到图片服务器ip"} } weedfsUri := "http://" + sysconf.WebPicIp + ":" + strconv.Itoa(int(sysconf.WebPicPort)) + "/submit?collection=" + sysconf.ServerId + "-persistent" filename, base64Str, err := service.UpdateCapture(camInfo.Type, camInfo.Rtsp, weedfsUri, camInfo.Name) if err != nil { logger.Debug("UpdateSnapshotUrl.err:", err) if base64Str != "" { //上传到图片服务器失败 return &bhomeclient.Reply{Msg: "上传失败,返回base64", Data: map[string]string{ "cameraId": cameraId, "snapshotUrl": "", "base64": base64Str, }} } else { return &bhomeclient.Reply{Msg: "更新失败"} } } if csv.UpdateSnapshot(cameraId, filename) { return &bhomeclient.Reply{Success: true, Msg: "更新成功", Data: map[string]string{ "cameraId": cameraId, "snapshotUrl": filename, "base64": base64Str, }} } else { return &bhomeclient.Reply{Msg: "更新失败"} } } // @Security ApiKeyAuth // @Summary 获取国标摄像机底图,不存储,返回base64 // @Description 获取国标摄像机底图,不存储,返回base64 // @Produce json // @Tags 摄像机 // @Param id query string true "摄像机id" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/capture [get] func (gbc Gb28181Controller) Capture(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { id := c.Query("id") if id == "" { return &bhomeclient.Reply{Msg: "参数有误"} } b, err := service.CaptureBase64(id) if err != nil { return &bhomeclient.Reply{Msg: err.Error()} } strBase64 := base64.StdEncoding.EncodeToString(b) return &bhomeclient.Reply{Success: true, Data: strBase64} } func (gbc Gb28181Controller) TreeSelected(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { sv := service.NewGb28181Service(h.Bk) tree := sv.GetGbCurrentTree() return &bhomeclient.Reply{Success: true, Data: tree} } // @Summary 在地图上获取摄像机列表 // @Description 在地图上获取摄像机列表 // @Produce json // @Tags gb28181 // @Param quryArg body vo.CameraQueryVo true "摄像机列表查询" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/findOnMap [post] func (gbc Gb28181Controller) FindOnMap(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var searchArg vo.CameraQueryVo err := c.BindJSON(&searchArg) if err != nil { return &bhomeclient.Reply{Msg: "参数有误"} } logger.Debug("isOnMap:", searchArg.IsOnMap) logger.Debug("floorStr:", searchArg.Floor) logger.Debug("cameraName:", searchArg.CameraName) var cam models.Camera cams, err := cam.FindBy(searchArg.IsOnMap, searchArg.Floor, searchArg.CameraName) if err != nil { return &bhomeclient.Reply{Msg: "查询失败"} } return &bhomeclient.Reply{Success: true, Data: cams} } // @Summary 更新摄像机地图位置 // @Description 更新摄像机地图位置 // @Produce json // @Tags gb28181 // @Param posArg body vo.CameraPosVo true "摄像机位置更新参数" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/updatePos [post] func (gbc Gb28181Controller) UpdatePos(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var arg vo.CameraPosVo err := c.BindJSON(&arg) if err != nil || arg.Id == "" { return &bhomeclient.Reply{Msg: "参数有误"} } var cam models.Camera if cam.UpdatePos(arg.Id, arg.Floor, arg.Longitude, arg.Latitude) { return &bhomeclient.Reply{Success: true, Msg: "更新成功"} } else { return &bhomeclient.Reply{Msg: "更新失败"} } } // @Summary 获取集群中各节点的摄像机 // @Description 获取集群中各节点的摄像机 // @Produce json // @Tags gb28181 // @Param searchType query int true "查询类型(0:全部,1:分析摄像机,2:监控摄像机, 3:联动摄像机)" // @Param cameraName query string false "摄像机名称" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/nodeCamera [get] func (gbc Gb28181Controller) NodeCamera(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { searchType, _ := strconv.Atoi(c.Query("searchType")) camName := c.Query("cameraName") var camE models.Camera lkMap := make(map[string]string) linkWhere := "" if searchType == 3 { //查联动 var crApi bhomedbapi.CameraRuleApi lb, lkList := crApi.FindAllCameraLink() if !lb { return &bhomeclient.Reply{Msg: "查询联动配置失败"} } if len(lkList) == 0 { return &bhomeclient.Reply{Success: true, Data: []struct{}{}} } for _, lc := range lkList { cArr := strings.Split(lc.CameraIds, ",") for _, lcId := range cArr { if _, ok := lkMap[lcId]; !ok { lkMap[lcId] = lcId } } } for k := range lkMap { linkWhere += "'" + k + "'," } linkWhere = strings.TrimRight(linkWhere, ",") } allCams, _ := camE.FindAllByServer("", camName, searchType, "", "", linkWhere) result := make([]models.TreeMenu, 0) var clusterApi bhomedbapi.ClusterApi b, ci := clusterApi.FindCluster() if b { if ci.Nodes != nil && len(ci.Nodes) > 0 { for _, n := range ci.Nodes { result = append(result, models.TreeMenu{ Id: n.NodeId, Name: n.NodeName, Type: "MENU", Areanodes: getCamsByNodeId(allCams, n.NodeId), }) } } } return &bhomeclient.Reply{Success: true, Data: result} } func getCamsByNodeId(cams []models.Camera, nodeId string) []models.TreeMenu { arr := make([]models.TreeMenu, 0) if cams != nil { var camRuleApi bhomedbapi.CameraRuleApi for _, c := range cams { if c.RunServerId == nodeId { isRunnig := false isAI := false camera := models.Camera{} rows, e := camera.SelectById(c.Id) if rows > 0 && e == nil { isRunnig = camera.IsRunning isAI = camRuleApi.ExistRunningTask(c.Id) && (camera.RunType == models.TYPE_RUNTYPE_POLL || camera.RunType == models.TYPE_RUNTYPE_REALTIME) } arr = append(arr, models.TreeMenu{ Id: c.Id, Type: "4", Name: c.Name, IsAI: isAI, //是否AI摄像机 IsRunning: isRunnig, Rtsp: c.Rtsp, CameraType: -1, }) } } } return arr } // @Summary 获取摄像机的坐标标定信息 // @Description 获取摄像机的坐标标定信息 // @Produce json // @Tags gb28181 // @Param cameraId query string true "摄像机id" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/coord [get] func (gbc Gb28181Controller) Coord(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { cameraId := c.Query("cameraId") if cameraId == "" { return &bhomeclient.Reply{Msg: "参数有误"} } logger.Debug("coord cameraId:", cameraId) var camE models.Camera rows, err := camE.SelectById(cameraId) if err == nil && rows > 0 { var snapShotUrl = "" if camE.SnapshotUrl == "" { var sysApi bhomedbapi.SysSetApi sb, sysconf := sysApi.GetServerInfo() if !sb || sysconf.WebPicIp == "" { return &bhomeclient.Reply{Msg: "未获取到图片服务器ip"} } weedfsUri := "http://" + sysconf.WebPicIp + ":" + strconv.Itoa(int(sysconf.WebPicPort)) + "/submit?collection=" + sysconf.ServerId + "-persistent" //没有底图需要先刷新底图 snapUrl, _, err := service.UpdateCapture(camE.Type, camE.Rtsp, weedfsUri, camE.Name) if err != nil { return &bhomeclient.Reply{Msg: err.Error()} } snapShotUrl = snapUrl } else { snapShotUrl = camE.SnapshotUrl } if !strings.HasPrefix(snapShotUrl, "http://") { snapShotUrl = "http://" + snapShotUrl } result := vo.CoordTransShow{ Coords: make([]vo.CoordTrans, 0), PanoramaCoords: make([]vo.CPoint, 0), } if camE.CoordTransform == "" { return &bhomeclient.Reply{Success: true, Data: result} } else { var coords []vo.CoordTrans err := json.Unmarshal([]byte(camE.CoordTransform), &coords) if err != nil { logger.Debug("unmarshal CoordTransform err:", err) return &bhomeclient.Reply{Msg: "坐标转换失败"} } result.Coords = coords } bts, dE := util.DownLoad(snapShotUrl) if dE != nil { return &bhomeclient.Reply{Msg: "获取摄像机底图失败"} } reader := bytes.NewReader(bts) im, _, err := image.DecodeConfig(reader) if err != nil { return &bhomeclient.Reply{Msg: "获取底图分辨率宽高失败"} } w := im.Width h := im.Height logger.Debug("coord w:", w, "h", h) /*args, e := json.Marshal(map[string]interface{}{ "coordTrans": result.Coords, "w": w, "h": h, }) if e != nil { return &bhomeclient.Reply{Msg:e.Error()} } panoCoordStr := uniquelCoordinate.TransCoord(string(args)) if panoCoordStr != "" { logger.Debug("panoCoordStr:", panoCoordStr) var cresult vo.CCoordResult err = json.Unmarshal([]byte(panoCoordStr), &cresult) if err != nil { logger.Debug("将panoCoordStr 转化为CCoordResult失败,err:", err) result.PanoramaCoords = make([]vo.CPoint, 0) } else { result.PanoramaCoords = cresult.Result } }*/ return &bhomeclient.Reply{Success: true, Data: result} } else { return &bhomeclient.Reply{Msg: "摄像机查询失败"} } } // @Summary 更新摄像机的坐标标定信息 // @Description 更新摄像机的坐标标定信息 // @Produce json // @Tags gb28181 // @Param reqBody body vo.CoordSetVo true "摄像机坐标转换参数" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/camera/updateCoord [post] func (gbc Gb28181Controller) UpdateCoord(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var reqBody vo.CoordSetVo err := c.BindJSON(&reqBody) if err != nil || reqBody.CameraId == "" { return &bhomeclient.Reply{Msg: "参数有误"} } //有时候会出现x0和y0相同,但是x1和y1不一样的bug m := make(map[string]vo.CoordTrans) newList := make([]vo.CoordTrans, 0) for _, ct := range reqBody.Coords { k := strconv.Itoa(ct.X0) + ":" + strconv.Itoa(ct.Y0) if _, exist := m[k]; !exist { newList = append(newList, ct) m[k] = ct } } reqBody.Coords = newList //去除重复的 bts, err := json.Marshal(reqBody.Coords) if err != nil { return &bhomeclient.Reply{Msg: "坐标转换失败"} } var camE models.Camera if camE.UpdateCoordTrans(reqBody.CameraId, string(bts)) { return &bhomeclient.Reply{Success: true, Msg: "更新成功"} } else { return &bhomeclient.Reply{Msg: "更新失败"} } } // @Summary 获取要同步的摄像机信息数据 // @Description 获取要同步的摄像机信息数据 // @Produce json // @Tags camera // @Param reqBody body vo.CoordSetVo true "" // @Success 200 {string} json "{"code":200, success:true, msg:"", data:""}" // @Failure 500 {string} json "{"code":500, success:false, msg:"",data:""}" // @Router /data/api-v/gb28181/GetSyncCameraData [post] func (gbc Gb28181Controller) GetSyncCameraData(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { // 获取设备相继信息 var camS commonSv.CameraService camera, err := camS.GetSyncCamera() if err != nil { return &bhomeclient.Reply{Success: false, Msg: "获取摄像机信息失败", Data: camera} } return &bhomeclient.Reply{Success: true, Msg: "获取成功", Data: camera} } func (gbc Gb28181Controller) SaveNotExistOrUpdate(h *bhomeclient.WrapperHandler, c *bhomeclient.Request) *bhomeclient.Reply { var reqBody scs.SyncCameraAndArea if e := c.BindJSON(&reqBody); e != nil { return &bhomeclient.Reply{Success: false, Msg: "参数有误"} } var err error tx := models.GetDB().Begin() defer func() { if err != nil && tx != nil { logger.Error("SaveNotExistOrUpdate rollback err:", err) tx.Rollback() } }() sv := commonSv.CameraService{} for _, cam := range reqBody.Cams { if err = sv.SaveNotExistOrUpdate(tx, cam); err != nil { logger.Error("SaveNotExistOrUpdate err:", err) return &bhomeclient.Reply{Msg: err.Error()} } } if err = sv.SaveOrUpdateAreas(tx, reqBody.Areas, reqBody.CamAndArea); err != nil { logger.Error("SaveOrUpdateAreas err:", err) return &bhomeclient.Reply{Msg: err.Error()} } tx.Commit() gsv := service.NewGb28181Service(h.Bk) gsv.AddDbChangeMsg(protomsg.DbAction_Update) _, _ = service2.DoBusReq("/data/api-v/saas/syncCamera", config.Server.AnalyServerId, aiot.RequestMethod_Post, aiot.RequestContentType_ApplicationJson, map[string]interface{}{}) return &bhomeclient.Reply{Success: true, Msg: "保存成功"} }