package service import ( "encoding/json" "errors" "fmt" "strconv" "strings" "vamicro/camera-common/models" "vamicro/camera-common/pub" "vamicro/camera-common/vo" "vamicro/config" "vamicro/extend/util" "basic.com/pubsub/protomsg.git" "basic.com/valib/bhomedbapi.git" "basic.com/valib/logger.git" "github.com/jinzhu/gorm" uuid "github.com/satori/go.uuid" ) type CameraService struct { } func (sv CameraService) CameraAdd(camVo vo.CameraEditVo) (bool, models.Camera, error) { cam := camVo.Copy2Camera() //2020-11-04 验证rtsp地址在本机是 b, _ := IsRtspExist(camVo.Rtsp) if b { return false, cam, errors.New("rtsp地址冲突,本机已存在此rtsp摄像机") } if strings.HasPrefix(cam.Rtsp, "rtsp://") { encodeRtsp, err := util.EncodeRTSPPassword(cam.Rtsp) if err != nil { return false, cam, errors.New("rtsp地址格式错误") } else { fmt.Println("encodertstp,", encodeRtsp) cam.Rtsp = encodeRtsp } } var sysApi bhomedbapi.SysSetApi flag, sysconf := sysApi.GetServerInfo() var realMax = 16 if flag && sysconf.RealMax > 0 { realMax = int(sysconf.RealMax) } var err error tx := models.GetDB().Begin() defer func() { if err != nil && tx != nil { tx.Rollback() } }() cam.Type = models.TYPE_LOCAL_CAMERA // 本地摄像机 var areaE models.Area if camVo.AreaId != "0" { if _, err = areaE.SelectbyId(camVo.AreaId); err != nil { return false, cam, err } } cam.Id = uuid.NewV4().String() cam.RunServerId = config.Server.AnalyServerId if camVo.RunType != models.TYPE_RUNTYPE_VIDEO && camVo.RunType != models.TYPE_RUNTYPE_POLL && camVo.RunType != models.TYPE_RUNTYPE_REALTIME { cam.RunType = models.TYPE_RUNTYPE_VIDEO } else { cam.RunType = camVo.RunType } if cam.RunType == models.TYPE_RUNTYPE_REALTIME { //实时需要判断实时数量 realList, e := cam.GetCamerasByRunType(models.TYPE_RUNTYPE_REALTIME, "") if e != nil || len(realList) >= realMax { return false, cam, e } } cam.RunEnable = true cam.Floor = models.Default_Layer //添加摄像机的时候不应该指定RunServerId,在哪台服务器上配了任务,RunServerId就是对应的那台服务器 if err = tx.Table("cameras").Create(&cam).Error; err != nil { return false, cam, err } if err = tx.Table("camera_area").Create(&models.CameraArea{Cameraid: cam.Id, Areaid: camVo.AreaId}).Error; err != nil { return false, cam, err } //处理传感器 if len(camVo.Sensors) > 0 { for _, sor := range camVo.Sensors { var sorE models.Sensor exist := sorE.Exist(sor.Ip, sor.Port) sorId := "" if exist { sorId = sorE.Id } else { sor.Id = uuid.NewV4().String() if err = tx.Table(sor.TableName()).Create(&sor).Error; err != nil { return false, cam, err } sorId = sor.Id } if err = tx.Exec("insert into camera_sensor(camera_id, sensor_id) select '" + cam.Id + "','" + sorId + "' where not exists (select 1 from camera_sensor where camera_id='" + cam.Id + "' and sensor_id='" + sorId + "')").Error; err != nil { return false, cam, err } } } tx.Commit() camBytes, _ := json.Marshal(cam) sv.addDbChangeMsg(protomsg.TableChanged_T_Camera, cam.Id, protomsg.DbAction_Insert, string(camBytes)) dbMsg := protomsg.DbChangeMessage{ Table: protomsg.TableChanged_T_CameraPolygon, Id: cam.Id, Action: protomsg.DbAction_Insert, Info: string(""), } pub.AddDbMessage(&dbMsg) return true, cam, nil } // 判断rtsp在本机的摄像机列表中是否重复,集群内可以重复 func IsRtspExist(rtsp string) (bool, []models.Camera) { if !config.Server.RtspUnique { return false, nil } var camE models.Camera cams, _ := camE.FindByRtsp(rtsp) if cams != nil { found := false var sameArr []models.Camera for _, c := range cams { if c.RunServerId == config.Server.AnalyServerId { found = true sameArr = append(sameArr, c) } } return found, sameArr } return false, nil } func (sv CameraService) GetById(cameraId string) (bool, models.Camera) { var camE models.Camera rows, err := camE.SelectById(cameraId) if err == nil && rows > 0 { return true, camE } else { return false, models.Camera{} } } func (sv CameraService) CameraUpdate(camVo vo.CameraEditVo) (bool, error) { cam := camVo.Copy2Camera() b, sameArr := IsRtspExist(cam.Rtsp) if b { if len(sameArr) > 1 || (len(sameArr) == 1 && sameArr[0].Id != cam.Id) { return false, errors.New("rtsp地址冲突,本机已存在此rtsp摄像机") } } if strings.HasPrefix(cam.Rtsp, "rtsp://") { encodeRtsp, err := util.EncodeRTSPPassword(cam.Rtsp) if err != nil { return false, errors.New("rtsp地址格式错误") } else { fmt.Println("encodertstp,", encodeRtsp) cam.Rtsp = encodeRtsp } } var sysApi bhomedbapi.SysSetApi flag, sysconf := sysApi.GetServerInfo() var realMax = 16 if flag && sysconf.RealMax > 0 { realMax = int(sysconf.RealMax) } var camTmp models.Camera rows, err := camTmp.SelectById(cam.Id) if err != nil || rows == 0 { return false, errors.New("查询摄像机失败") } cam.Floor = camTmp.Floor if camTmp.RunServerId == "" { //未设置过run_server_id,此种情况是国标摄像机第一次保存,会选择目标服务器的id cam.RunServerId = config.Server.AnalyServerId //此摄像机归属到本台分析服务器 //if cam.RunServerId == "" { // return false //} } else { cam.RunServerId = camTmp.RunServerId //虽然国标摄像机集群内共享,但是更新时不会修改归属 } //过滤非法数据 if cam.RunType != models.TYPE_RUNTYPE_VIDEO && cam.RunType != models.TYPE_RUNTYPE_POLL && cam.RunType != models.TYPE_RUNTYPE_REALTIME { cam.RunType = models.TYPE_RUNTYPE_VIDEO } if cam.RunType == models.TYPE_RUNTYPE_REALTIME { if camTmp.RunType != models.TYPE_RUNTYPE_REALTIME { //由非实时到实时的切换时,需要判断当前的实时数量 realList, e := cam.GetCamerasByRunType(models.TYPE_RUNTYPE_REALTIME, "") if e != nil || len(realList) >= realMax { return false, errors.New("实时数量已达到上限") } } } //处理传感器 var camSensor models.CameraSensor if !camSensor.DeleteByCamId(camVo.Id) { logger.Debug("cameraSensor deleteByCameraId fail") return false, errors.New("传感器删除失败") } if camVo.Sensors != nil && len(camVo.Sensors) > 0 { for _, sor := range camVo.Sensors { var sorE models.Sensor exist := sorE.Exist(sor.Ip, sor.Port) sorId := "" if exist { sorId = sorE.Id if err = models.GetDB().Table(sor.TableName()).Where("id=?", sorId).Update(&sor).Error; err != nil { return false, err } } else { sor.Id = uuid.NewV4().String() if err = models.GetDB().Table(sor.TableName()).Create(&sor).Error; err != nil { return false, err } sorId = sor.Id } if err = models.GetDB().Exec("insert into camera_sensor(camera_id, sensor_id) select '" + cam.Id + "','" + sorId + "' where not exists (select 1 from camera_sensor where camera_id='" + camVo.Id + "' and sensor_id='" + sorId + "')").Error; err != nil { return false, err } } } cam.IsRunning = camTmp.IsRunning cam.Type = camTmp.Type err = cam.Update() if err != nil { return false, err } camBytes, _ := json.Marshal(cam) sv.addDbChangeMsg(protomsg.TableChanged_T_Camera, cam.Id, protomsg.DbAction_Update, string(camBytes)) return true, nil } func (sv CameraService) GetCamerasByRunType(runType int, cameraName string) (cams []vo.CamSensorVo, err error) { //指定当前机器为过滤条件 var cameraE models.Camera list, err := cameraE.GetCamerasByRunType(runType, cameraName) logger.Debug("GetCamerasByRunType len(list):", len(list), " err:", err) if err != nil { return nil, err } var crApi bhomedbapi.CameraRuleApi var sensorE models.Sensor for _, cam := range list { //判断每一个摄像机是否有可运行的任务和规则 if crApi.ExistRunningTask(cam.Id) { sensors, _ := sensorE.FindByCameraId(cam.Id) var camSor vo.CamSensorVo camSor.Camera = cam if sensors != nil { camSor.Sensors = sensors } else { camSor.Sensors = []models.Sensor{} } cams = append(cams, camSor) } } return cams, nil } func (sv CameraService) UpdateIsRunningState(id string, isRunning bool) bool { var cameraE models.Camera return cameraE.UpdateIsRunningState(id, isRunning) } func (sv CameraService) UpdateIsRunningAll(camIds []string) bool { var cameraE models.Camera return cameraE.UpdateIsRunningAll(camIds) } func (sv CameraService) UpdateRunEnable(cameraId string, runEnable bool) bool { var cameraE models.Camera return cameraE.UpdateRunEnable(cameraId, runEnable) } // 1.判断本地摄像机的实时数量 // 2.判断是否安装有国标,以及国标实时摄像机的数量 func (sv CameraService) ChangeRunType(ccrVo vo.CameraChangeRunVo) bool { logger.Debug("ChangeRunType params:", ccrVo) var sysApi bhomedbapi.SysSetApi flag, sysconf := sysApi.GetServerInfo() var realMax = 16 if flag && sysconf.RealMax > 0 { realMax = int(sysconf.RealMax) } var err error tx := models.GetDB().Begin() defer func() { if err != nil && tx != nil { tx.Rollback() } }() for _, cameraId := range ccrVo.CameraIds { var camE models.Camera rows, e := camE.SelectById(cameraId) if e == nil && rows > 0 { if ccrVo.RunType == models.TYPE_RUNTYPE_REALTIME { //非实时向实时切换 if camE.RunType != models.TYPE_RUNTYPE_REALTIME { realList, e := camE.GetCamerasByRunType(models.TYPE_RUNTYPE_REALTIME, "") if e != nil || len(realList) >= realMax { logger.Warn("realTime cameras limit " + strconv.Itoa(realMax)) return false } } else { continue } } sql := fmt.Sprintf("update cameras set run_type=%d, is_running=0 where id='%s'", ccrVo.RunType, cameraId) if camE.RunServerId == "" { sql = fmt.Sprintf("update cameras set run_type=%d, run_server_id='%s', is_running=0 where id='%s'", ccrVo.RunType, config.Server.AnalyServerId, cameraId) } logger.Debug(sql) if err = tx.Exec(sql).Error; err != nil { logger.Warn(err) return false } } else { logger.Warn("find camera by id failure, id:", cameraId, " err:", e, " row:", rows) } } tx.Commit() cIds := strings.Join(ccrVo.CameraIds, ",") sv.addDbChangeMsg(protomsg.TableChanged_T_Camera, cIds, protomsg.DbAction_Update, "") //var pollConfSv PollConfigService //pollConfSv.ResetChannelCount() return true } func (sv CameraService) UpdateSnapshot(cameraId string, snapshot string) bool { var cameraE models.Camera return cameraE.UpdateSnapshot(cameraId, snapshot) } // 通过摄像机id获取在哪台服务器上运行 func GetRunServerName(cameraId string) string { var runServerName = "" var camTmp models.Camera rows, _ := camTmp.SelectById(cameraId) if rows > 0 { var syssetApi bhomedbapi.SysSetApi fb, localConf := syssetApi.GetServerInfo() if fb { if camTmp.RunServerId == localConf.ServerId { //归属本台服务器 runServerName = localConf.ServerName } else { //属于其他服务器 var clusterApi bhomedbapi.ClusterApi flag, cInfo := clusterApi.FindCluster() if flag { if cInfo.Nodes != nil { for _, n := range cInfo.Nodes { if n.Id == camTmp.RunServerId { runServerName = n.NodeName break } } } } } } } return runServerName } func (sv CameraService) addDbChangeMsg(tChanged protomsg.TableChanged, id string, action protomsg.DbAction, info string) { dbMsg := protomsg.DbChangeMessage{ Table: tChanged, Id: id, Action: action, Info: info, } pub.AddDbMessage(&dbMsg) } // 获取摄像机数据 func (sv CameraService) GetSyncCamera() (vo.SyncCameraResult, error) { res := vo.SyncCameraResult{} // 摄像机信息 var camM models.Camera camList, err := camM.FindAll() if err != nil { logger.Error("fail to find camera list", err) return res, err } res.Cameras = camList // 区域 var areaM models.Area areaList, err := areaM.FindAll() if err != nil { logger.Error("fail to find area list", err) return res, err } res.Area = areaList // 摄像机关联区域 var camAreaM models.CameraArea camAreaList, err := camAreaM.FindAll() if err != nil { logger.Error("fail to find camera area list", err) return res, err } res.CameraArea = camAreaList logger.Debug("camera", res) return res, nil } // 获取同步传感器信息 func (sv CameraService) GetSyncSensor() (vo.SyncSensorResult, error) { res := vo.SyncSensorResult{} // 传感器 var sensorM models.Sensor sensorList, err := sensorM.FindAll() if err != nil { logger.Error("fail to find sensor list", err) return res, err } res.Sensor = sensorList // 摄像机传感器 var csM models.CameraSensor csList, err := csM.FindAll() if err != nil { logger.Error("fail to find camera sensor list", err) return res, err } res.CameraSensor = csList return res, nil } func (sv CameraService) SaveNotExistOrUpdate(tx *gorm.DB, cam models.Camera) error { b, sameArr := IsRtspExist(cam.Rtsp) if b { if len(sameArr) > 1 || (len(sameArr) == 1 && sameArr[0].Id != cam.Id) { return errors.New("rtsp地址冲突,本机已存在此rtsp摄像机") } } cam.RunServerId = config.Server.AnalyServerId var sysApi bhomedbapi.SysSetApi flag, sysconf := sysApi.GetServerInfo() var realMax = 16 if flag && sysconf.RealMax > 0 { realMax = int(sysconf.RealMax) } var camTmp models.Camera rows, _ := camTmp.SelectById(cam.Id) if rows == 0 { if err := tx.Table(cam.TableName()).Create(&cam).Error; err != nil { return err } } else { cam.Floor = camTmp.Floor if camTmp.RunServerId == "" { //未设置过run_server_id,此种情况是国标摄像机第一次保存,会选择目标服务器的id cam.RunServerId = config.Server.AnalyServerId //此摄像机归属到本台分析服务器 //if cam.RunServerId == "" { // return false //} } else { cam.RunServerId = camTmp.RunServerId //虽然国标摄像机集群内共享,但是更新时不会修改归属 } //过滤非法数据 if cam.RunType != models.TYPE_RUNTYPE_VIDEO && cam.RunType != models.TYPE_RUNTYPE_POLL && cam.RunType != models.TYPE_RUNTYPE_REALTIME { cam.RunType = models.TYPE_RUNTYPE_VIDEO } if cam.RunType == models.TYPE_RUNTYPE_REALTIME { if camTmp.RunType != models.TYPE_RUNTYPE_REALTIME { //由非实时到实时的切换时,需要判断当前的实时数量 realList, e := cam.GetCamerasByRunType(models.TYPE_RUNTYPE_REALTIME, "") if e != nil || len(realList) >= realMax { return errors.New("实时数量已达到上限") } } } //处理传感器 //var camSensor models.CameraSensor //if !camSensor.DeleteByCamId(cam.Id) { // logger.Debug("cameraSensor deleteByCameraId fail") // return errors.New("传感器删除失败") //} //if camVo.Sensors != nil && len(camVo.Sensors) > 0 { // for _, sor := range camVo.Sensors { // var sorE models.Sensor // exist := sorE.Exist(sor.Ip, sor.Port) // sorId := "" // if exist { // sorId = sorE.Id // if err = models.GetDB().Table(sor.TableName()).Where("id=?", sorId).Update(&sor).Error; err != nil { // return false, err // } // } else { // sor.Id = uuid.NewV4().String() // if err = models.GetDB().Table(sor.TableName()).Create(&sor).Error; err != nil { // return false, err // } // sorId = sor.Id // } // if err = models.GetDB().Exec("insert into camera_sensor(camera_id, sensor_id) select '" + cam.Id + "','" + sorId + "' where not exists (select 1 from camera_sensor where camera_id='" + camVo.Id + "' and sensor_id='" + sorId + "')").Error; err != nil { // return false, err // } // } //} cam.IsRunning = camTmp.IsRunning cam.Type = camTmp.Type if err := tx.Table(cam.TableName()).Save(&cam).Error; err != nil { return err } } return nil } func (sv CameraService) SaveOrUpdateAreas(tx *gorm.DB, areas []models.Area, cas []models.CameraArea) error { for _, a := range areas { tmp := a var count int if err := tx.Table(a.TableName()).Where("id=?", a.Id).Count(&count).Error; err != nil { return err } if count == 0 { if err := tx.Table(tmp.TableName()).Create(&tmp).Error; err != nil { return err } } else { if err := tx.Table(tmp.TableName()).Save(&tmp).Error; err != nil { return err } } } for _, ca := range cas { var count int if err := tx.Table(ca.TableName()).Where("cameraId=? and areaId=?", ca.Cameraid, ca.Areaid).Count(&count).Error; err != nil { return err } if count == 0 { tmp := models.CameraArea{ Cameraid: ca.Cameraid, Areaid: ca.Areaid, } if err := tx.Table(tmp.TableName()).Create(&tmp).Error; err != nil { return err } } } return nil }