package api import ( "context" "fmt" "gb-cms/common" "gb-cms/dao" "gb-cms/log" "gb-cms/stack" "math" "net/http" "strconv" "strings" "time" ) func (api *ApiServer) OnDeviceList(q *QueryDeviceChannel, _ http.ResponseWriter, r *http.Request) (interface{}, error) { // 分页参数 if q.Limit < 1 { q.Limit = 10 } var status string if "" == q.Online { } else if "true" == q.Online { status = "ON" } else if "false" == q.Online { status = "OFF" } if "desc" != q.Order { q.Order = "asc" } devices, total, err := dao.Device.QueryDevices((q.Start/q.Limit)+1, q.Limit, status, q.Keyword, q.Order) if err != nil { log.Sugar.Errorf("查询设备列表失败 err: %s", err.Error()) return nil, err } response := struct { DeviceCount int DeviceList_ []LiveGBSDevice `json:"DeviceList"` }{ DeviceCount: total, } // livgbs设备离线后的最后心跳时间, 涉及到是否显示非法设备的批量删除按钮 offlineTime := time.Date(1, time.January, 1, 0, 0, 0, 0, time.UTC).Format("2006-01-02 15:04:05") for _, device := range devices { // 更新正在查询通道的进度 var catalogProgress string data := stack.UniqueTaskManager.Find(stack.GenerateCatalogTaskID(device.GetID())) if data != nil { catalogSize := data.(*stack.CatalogProgress) if catalogSize.TotalSize > 0 { catalogProgress = fmt.Sprintf("%d/%d", catalogSize.RecvSize, catalogSize.TotalSize) } } var lastKeealiveTime string if device.Online() { lastKeealiveTime = device.LastHeartbeat.Format("2006-01-02 15:04:05") } else { lastKeealiveTime = offlineTime } if device.CatalogInterval < 1 { device.CatalogInterval = dao.DefaultCatalogInterval } response.DeviceList_ = append(response.DeviceList_, LiveGBSDevice{ AlarmSubscribe: device.AlarmSubscribe, // 报警订阅 CatalogInterval: device.CatalogInterval, // 目录刷新时间 CatalogProgress: catalogProgress, CatalogSubscribe: device.CatalogSubscribe, // 目录订阅 ChannelCount: device.ChannelsTotal, ChannelOverLoad: false, Charset: "GB2312", CivilCodeFirst: false, CommandTransport: device.Transport, ContactIP: "", CreatedAt: device.CreatedAt.Format("2006-01-02 15:04:05"), CustomName: "", DropChannelType: "", GBVer: "", ID: device.GetID(), KeepOriginalTree: false, LastKeepaliveAt: lastKeealiveTime, LastRegisterAt: device.RegisterTime.Format("2006-01-02 15:04:05"), Latitude: 0, Longitude: 0, //Manufacturer: device.Manufacturer, Manufacturer: device.UserAgent, MediaTransport: device.Setup.Transport(), MediaTransportMode: device.Setup.String(), Name: device.Name, Online: device.Online(), PTZSubscribe: false, // PTZ订阅2022 Password: "", PositionSubscribe: device.PositionSubscribe, // 位置订阅 RecordCenter: false, RecordIndistinct: false, RecvStreamIP: "", RemoteIP: device.RemoteIP, RemotePort: device.RemotePort, RemoteRegion: "", SMSGroupID: "", SMSID: "", StreamMode: "", SubscribeInterval: 0, Type: "GB", UpdatedAt: device.UpdatedAt.Format("2006-01-02 15:04:05"), }) } return &response, nil } func (api *ApiServer) OnChannelList(q *QueryDeviceChannel, _ http.ResponseWriter, r *http.Request) (interface{}, error) { // 分页参数 if q.Limit < 1 { q.Limit = 10 } var deviceName string if q.DeviceID != "" { device, err := dao.Device.QueryDevice(q.DeviceID) if err != nil { log.Sugar.Errorf("查询设备失败 err: %s", err.Error()) return nil, err } deviceName = device.Name } var status string if "" == q.Online { } else if "true" == q.Online { status = "ON" } else if "false" == q.Online { status = "OFF" } if "desc" != q.Order { q.Order = "asc" } channels, total, err := dao.Channel.QueryChannels(q.DeviceID, q.GroupID, (q.Start/q.Limit)+1, q.Limit, status, q.Keyword, q.Order, q.Sort, q.ChannelType == "dir") if err != nil { log.Sugar.Errorf("查询通道列表失败 err: %s", err.Error()) return nil, err } response := ChannelListResult{ ChannelCount: total, } index := q.Start + 1 response.ChannelList = ChannelModels2LiveGBSChannels(index, channels, deviceName) return &response, nil } func (api *ApiServer) OnRecordList(v *QueryRecordParams, _ http.ResponseWriter, _ *http.Request) (interface{}, error) { log.Sugar.Debugf("查询录像列表 %v", *v) model, _ := dao.Device.QueryDevice(v.DeviceID) if model == nil || !model.Online() { log.Sugar.Errorf("查询录像列表失败, 设备离线 device: %s", v.DeviceID) return nil, fmt.Errorf("设备离线") } device := &stack.Device{DeviceModel: model} sn := stack.GetSN() err := device.QueryRecord(v.ChannelID, v.StartTime, v.EndTime, sn, "all") if err != nil { log.Sugar.Errorf("发送查询录像请求失败 err: %s", err.Error()) return nil, err } // 设置查询超时时长 timeout := int(math.Max(math.Min(5, float64(v.Timeout)), 60)) withTimeout, cancelFunc := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second) var recordList []stack.RecordInfo stack.SNManager.AddEvent(sn, func(data interface{}) { response := data.(*stack.QueryRecordInfoResponse) if len(response.DeviceList.Devices) > 0 { recordList = append(recordList, response.DeviceList.Devices...) } // 所有记录响应完毕 if len(recordList) >= response.SumNum { cancelFunc() } }) select { case _ = <-withTimeout.Done(): break } response := struct { DeviceID string Name string RecordList []struct { DeviceID string EndTime string FileSize uint64 Name string Secrecy string StartTime string Type string } SumNum int `json:"sumNum"` }{ DeviceID: v.DeviceID, Name: model.Name, SumNum: len(recordList), } for _, record := range recordList { log.Sugar.Infof("查询录像列表 %v", record) response.RecordList = append(response.RecordList, struct { DeviceID string EndTime string FileSize uint64 Name string Secrecy string StartTime string Type string }{ DeviceID: record.DeviceID, EndTime: record.EndTime, FileSize: record.FileSize, Name: record.Name, Secrecy: record.Secrecy, StartTime: record.StartTime, Type: record.Type, }) } return &response, nil } func (api *ApiServer) OnDeviceMediaTransportSet(req *SetMediaTransportReq, _ http.ResponseWriter, _ *http.Request) (interface{}, error) { var setupType common.SetupType if "udp" == strings.ToLower(req.MediaTransport) { setupType = common.SetupTypeUDP } else if "passive" == strings.ToLower(req.MediaTransportMode) { setupType = common.SetupTypePassive } else if "active" == strings.ToLower(req.MediaTransportMode) { setupType = common.SetupTypeActive } else { return nil, fmt.Errorf("media_transport_mode error") } err := dao.Device.UpdateMediaTransport(req.DeviceID, setupType) if err != nil { return nil, err } return "OK", nil } func (api *ApiServer) OnCatalogQuery(params *QueryDeviceChannel, _ http.ResponseWriter, _ *http.Request) (interface{}, error) { deviceModel, err := dao.Device.QueryDevice(params.DeviceID) if err != nil { return nil, err } if deviceModel == nil { return nil, fmt.Errorf("not found device") } list, err := (&stack.Device{DeviceModel: deviceModel}).QueryCatalog(15) if err != nil { return nil, err } response := struct { ChannelCount int `json:"ChannelCount"` ChannelList []*dao.ChannelModel `json:"ChannelList"` }{ ChannelCount: len(list), ChannelList: list, } return &response, nil } func (api *ApiServer) OnDeviceTree(q *QueryDeviceChannel, _ http.ResponseWriter, _ *http.Request) (interface{}, error) { var response []*LiveGBSDeviceTree // 查询所有设备 if q.DeviceID == "" && q.PCode == "" { devices, err := dao.Device.LoadDevices() if err != nil { return nil, err } for _, model := range devices { count, _ := dao.Channel.QueryChanelCount(model.DeviceID, true) deviceCount, _ := dao.Channel.QueryChanelCount(model.DeviceID, false) onlineCount, _ := dao.Channel.QueryOnlineChanelCount(model.DeviceID, false) response = append(response, &LiveGBSDeviceTree{Code: "", Custom: false, CustomID: "", CustomName: "", ID: model.DeviceID, Latitude: 0, Longitude: 0, Manufacturer: model.Manufacturer, Name: model.Name, OnlineSubCount: onlineCount, Parental: true, PtzType: 0, Serial: model.DeviceID, Status: model.Status.String(), SubCount: count, SubCountDevice: deviceCount}) } } else { // 查询设备下的某个目录的所有通道 if q.PCode == "" { q.PCode = q.DeviceID } channels, _, _ := dao.Channel.QueryChannels(q.DeviceID, q.PCode, -1, 0, "", "", "asc", "", false) for _, channel := range channels { id := channel.RootID + ":" + channel.DeviceID latitude, _ := strconv.ParseFloat(channel.Latitude, 10) longitude, _ := strconv.ParseFloat(channel.Longitude, 10) var deviceCount int var onlineCount int if channel.SubCount > 0 { deviceCount, _ = dao.Channel.QuerySubChannelCount(channel.RootID, channel.DeviceID, false) onlineCount, _ = dao.Channel.QueryOnlineSubChannelCount(channel.RootID, channel.DeviceID, false) } response = append(response, &LiveGBSDeviceTree{Code: channel.DeviceID, Custom: false, CustomID: "", CustomName: "", ID: id, Latitude: latitude, Longitude: longitude, Manufacturer: channel.Manufacturer, Name: channel.Name, OnlineSubCount: onlineCount, Parental: false, PtzType: 0, Serial: channel.RootID, Status: channel.Status.String(), SubCount: channel.SubCount, SubCountDevice: deviceCount}) } } return &response, nil } func (api *ApiServer) OnDeviceRemove(q *DeleteDevice, _ http.ResponseWriter, _ *http.Request) (interface{}, error) { var err error if q.IP != "" { // 删除IP下的所有设备 err = dao.Device.DeleteDevicesByIP(q.IP) } else if q.UA != "" { // 删除UA下的所有设备 err = dao.Device.DeleteDevicesByUA(q.UA) } else { // 删除单个设备 err = dao.Device.DeleteDevice(q.DeviceID) } if err != nil { return nil, err } else if q.Forbid { if q.IP != "" { // 拉黑IP err = dao.Blacklist.SaveIP(q.IP) } else if q.UA != "" { // 拉黑UA err = dao.Blacklist.SaveUA(q.UA) } } return "OK", nil } func (api *ApiServer) OnDeviceInfoSet(params *DeviceInfo, w http.ResponseWriter, req *http.Request) (interface{}, error) { model, err := dao.Device.QueryDevice(params.DeviceID) if err != nil { return nil, err } device := stack.Device{DeviceModel: model} // 更新的字段和值 conditions := make(map[string]interface{}, 0) // 刷新目录间隔 if params.CatalogInterval != model.CatalogInterval && params.CatalogInterval != dao.DefaultCatalogInterval && params.CatalogInterval >= 60 { conditions["catalog_interval"] = params.CatalogInterval } if model.CatalogSubscribe != params.CatalogSubscribe { conditions["catalog_subscribe"] = params.CatalogSubscribe // 开启目录订阅 if params.CatalogSubscribe { _ = device.SubscribeCatalog() } else { // 取消目录订阅 device.UnsubscribeCatalog() } } if model.PositionSubscribe != params.PositionSubscribe { conditions["position_subscribe"] = params.PositionSubscribe // 开启位置订阅 if params.PositionSubscribe { _ = device.SubscribePosition() } else { // 取消位置订阅 device.UnsubscribePosition() } } if model.AlarmSubscribe != params.AlarmSubscribe { conditions["alarm_subscribe"] = params.AlarmSubscribe // 开启报警订阅 if params.AlarmSubscribe { _ = device.SubscribeAlarm() } else { // 取消报警订阅 device.UnsubscribeAlarm() } } // 更新设备信息 if len(conditions) > 0 { if err = dao.Device.UpdateDevice(params.DeviceID, conditions); err != nil { return nil, err } } return "OK", nil } func (api *ApiServer) OnPTZControl(v *QueryRecordParams, _ http.ResponseWriter, _ *http.Request) (interface{}, error) { log.Sugar.Debugf("PTZ控制 %v", *v) model, _ := dao.Device.QueryDevice(v.DeviceID) if model == nil || !model.Online() { log.Sugar.Errorf("PTZ控制失败, 设备离线 device: %s", v.DeviceID) return nil, fmt.Errorf("设备离线") } device := &stack.Device{DeviceModel: model} device.ControlPTZ(v.Command, v.ChannelID) return "OK", nil }