mirror of
https://github.com/lkmio/gb-cms.git
synced 2025-10-25 08:30:55 +08:00
feat: 支持查询子目录通道列表
This commit is contained in:
3
api.go
3
api.go
@@ -91,6 +91,7 @@ type PageQuery struct {
|
||||
type PageQueryChannel struct {
|
||||
PageQuery
|
||||
DeviceID string `json:"device_id"`
|
||||
GroupID string `json:"group_id"`
|
||||
}
|
||||
|
||||
var apiServer *ApiServer
|
||||
@@ -483,7 +484,7 @@ func (api *ApiServer) OnChannelList(v *PageQueryChannel, w http.ResponseWriter,
|
||||
v.PageSize = &defaultPageSize
|
||||
}
|
||||
|
||||
channels, total, err := ChannelDao.QueryChannels(v.DeviceID, *v.PageNumber, *v.PageSize)
|
||||
channels, total, err := ChannelDao.QueryChannels(v.DeviceID, v.GroupID, *v.PageNumber, *v.PageSize)
|
||||
if err != nil {
|
||||
Sugar.Errorf("查询通道列表失败 err: %s", err.Error())
|
||||
return nil, err
|
||||
|
||||
@@ -1,28 +1,32 @@
|
||||
package main
|
||||
|
||||
import "gorm.io/gorm"
|
||||
import (
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
type DaoChannel interface {
|
||||
SaveChannel(deviceId string, channel *Channel) error
|
||||
SaveChannel(channel *Channel) error
|
||||
|
||||
UpdateChannelStatus(deviceId, channelId, status string) error
|
||||
|
||||
QueryChannel(deviceId string, channelId string) (*Channel, error)
|
||||
|
||||
QueryChannels(deviceId string, page, size int) ([]*Channel, int, error)
|
||||
QueryChannels(deviceId, groupId, string, page, size int) ([]*Channel, int, error)
|
||||
|
||||
QueryChanelCount(deviceId string) (int, error)
|
||||
|
||||
QueryOnlineChanelCount(deviceId string) (int, error)
|
||||
|
||||
QueryChannelByTypeCode(codecs ...int) ([]*Channel, error)
|
||||
}
|
||||
|
||||
type daoChannel struct {
|
||||
}
|
||||
|
||||
func (d *daoChannel) SaveChannel(deviceId string, channel *Channel) error {
|
||||
func (d *daoChannel) SaveChannel(channel *Channel) error {
|
||||
return DBTransaction(func(tx *gorm.DB) error {
|
||||
var old Channel
|
||||
if db.Select("id").Where("parent_id =? and device_id =?", deviceId, channel.DeviceID).Take(&old).Error == nil {
|
||||
if db.Select("id").Where("root_id =? and device_id =?", channel.RootID, channel.DeviceID).Take(&old).Error == nil {
|
||||
channel.ID = old.ID
|
||||
}
|
||||
return tx.Save(channel).Error
|
||||
@@ -30,27 +34,33 @@ func (d *daoChannel) SaveChannel(deviceId string, channel *Channel) error {
|
||||
}
|
||||
|
||||
func (d *daoChannel) UpdateChannelStatus(deviceId, channelId, status string) error {
|
||||
return db.Model(&Channel{}).Where("parent_id =? and device_id =?", deviceId, channelId).Update("status", status).Error
|
||||
return db.Model(&Channel{}).Where("root_id =? and device_id =?", deviceId, channelId).Update("status", status).Error
|
||||
}
|
||||
|
||||
func (d *daoChannel) QueryChannel(deviceId string, channelId string) (*Channel, error) {
|
||||
var channel Channel
|
||||
tx := db.Where("parent_id =? and device_id =?", deviceId, channelId).Take(&channel)
|
||||
tx := db.Where("root_id =? and device_id =?", deviceId, channelId).Take(&channel)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
return &channel, nil
|
||||
}
|
||||
|
||||
func (d *daoChannel) QueryChannels(deviceId string, page, size int) ([]*Channel, int, error) {
|
||||
func (d *daoChannel) QueryChannels(deviceId, groupId string, page, size int) ([]*Channel, int, error) {
|
||||
conditions := map[string]interface{}{}
|
||||
conditions["root_id"] = deviceId
|
||||
if groupId != "" {
|
||||
conditions["group_id"] = groupId
|
||||
}
|
||||
|
||||
var channels []*Channel
|
||||
tx := db.Limit(size).Offset((page-1)*size).Where("parent_id =?", deviceId).Find(&channels)
|
||||
tx := db.Limit(size).Offset((page - 1) * size).Where(conditions).Find(&channels)
|
||||
if tx.Error != nil {
|
||||
return nil, 0, tx.Error
|
||||
}
|
||||
|
||||
var total int64
|
||||
tx = db.Model(&Channel{}).Where("parent_id =?", deviceId).Count(&total)
|
||||
tx = db.Model(&Channel{}).Select("id").Where(conditions).Count(&total)
|
||||
if tx.Error != nil {
|
||||
return nil, 0, tx.Error
|
||||
}
|
||||
@@ -60,7 +70,7 @@ func (d *daoChannel) QueryChannels(deviceId string, page, size int) ([]*Channel,
|
||||
|
||||
func (d *daoChannel) QueryChanelCount(deviceId string) (int, error) {
|
||||
var total int64
|
||||
tx := db.Model(&Channel{}).Where("parent_id =?", deviceId).Count(&total)
|
||||
tx := db.Model(&Channel{}).Where("root_id =?", deviceId).Count(&total)
|
||||
if tx.Error != nil {
|
||||
return 0, tx.Error
|
||||
}
|
||||
@@ -69,9 +79,19 @@ func (d *daoChannel) QueryChanelCount(deviceId string) (int, error) {
|
||||
|
||||
func (d *daoChannel) QueryOnlineChanelCount(deviceId string) (int, error) {
|
||||
var total int64
|
||||
tx := db.Model(&Channel{}).Where("parent_id =? and status =?", deviceId, "ON").Count(&total)
|
||||
tx := db.Model(&Channel{}).Where("root_id =? and status =?", deviceId, "ON").Count(&total)
|
||||
if tx.Error != nil {
|
||||
return 0, tx.Error
|
||||
}
|
||||
|
||||
return int(total), nil
|
||||
}
|
||||
|
||||
func (d *daoChannel) QueryChannelByTypeCode(codecs ...int) ([]*Channel, error) {
|
||||
var channels []*Channel
|
||||
tx := db.Where("type_code in ?", codecs).Find(&channels)
|
||||
if tx.Error != nil {
|
||||
return nil, tx.Error
|
||||
}
|
||||
return channels, nil
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ type DaoDevice interface {
|
||||
UpdateDeviceInfo(deviceId string, device *Device) error
|
||||
|
||||
UpdateOfflineDevices(deviceIds []string) error
|
||||
|
||||
ExistDevice(deviceId string) bool
|
||||
}
|
||||
|
||||
type daoDevice struct {
|
||||
@@ -66,7 +68,20 @@ func (d *daoDevice) SaveDevice(device *Device) error {
|
||||
|
||||
func (d *daoDevice) UpdateDeviceInfo(deviceId string, device *Device) error {
|
||||
return DBTransaction(func(tx *gorm.DB) error {
|
||||
return tx.Model(&Device{}).Select("Manufacturer", "Model", "Firmware", "Name").Where("device_id =?", deviceId).Updates(*device).Error
|
||||
var condition = make(map[string]interface{})
|
||||
if device.Manufacturer != "" {
|
||||
condition["manufacturer"] = device.Manufacturer
|
||||
}
|
||||
if device.Model != "" {
|
||||
condition["model"] = device.Model
|
||||
}
|
||||
if device.Firmware != "" {
|
||||
condition["firmware"] = device.Firmware
|
||||
}
|
||||
if device.Name != "" {
|
||||
condition["name"] = device.Name
|
||||
}
|
||||
return tx.Model(&Device{}).Where("device_id =?", deviceId).Updates(condition).Error
|
||||
})
|
||||
}
|
||||
|
||||
@@ -127,3 +142,13 @@ func (d *daoDevice) UpdateOfflineDevices(deviceIds []string) error {
|
||||
return tx.Model(&Device{}).Where("device_id in ?", deviceIds).Update("status", OFF).Error
|
||||
})
|
||||
}
|
||||
|
||||
func (d *daoDevice) ExistDevice(deviceId string) bool {
|
||||
var device Device
|
||||
tx := db.Select("id").Where("device_id =?", deviceId).Take(&device)
|
||||
if tx.Error != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/lkmio/avformat/utils"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
@@ -60,6 +62,7 @@ func (e *EventHandler) OnKeepAlive(id string, addr string) bool {
|
||||
}
|
||||
|
||||
func (e *EventHandler) OnCatalog(device string, response *CatalogResponse) {
|
||||
utils.Assert(device == response.DeviceID)
|
||||
for _, channel := range response.DeviceList.Devices {
|
||||
// 状态转为大写
|
||||
channel.Status = OnlineStatus(strings.ToUpper(channel.Status.String()))
|
||||
@@ -69,7 +72,33 @@ func (e *EventHandler) OnCatalog(device string, response *CatalogResponse) {
|
||||
channel.Status = ON
|
||||
}
|
||||
|
||||
if err := ChannelDao.SaveChannel(device, channel); err != nil {
|
||||
// 下级设备的系统ID, 更新DeviceInfo
|
||||
if channel.DeviceID == device && DeviceDao.ExistDevice(device) {
|
||||
_ = DeviceDao.UpdateDeviceInfo(device, &Device{
|
||||
Manufacturer: channel.Manufacturer,
|
||||
Model: channel.Model,
|
||||
Name: channel.Name,
|
||||
})
|
||||
}
|
||||
|
||||
typeCode := GetTypeCode(channel.DeviceID)
|
||||
if typeCode == "" {
|
||||
Sugar.Errorf("保存通道时, 获取设备类型失败 device: %s", channel.DeviceID)
|
||||
}
|
||||
|
||||
var groupId string
|
||||
if channel.ParentID != "" {
|
||||
layers := strings.Split(channel.ParentID, "/")
|
||||
groupId = layers[len(layers)-1]
|
||||
} else if channel.BusinessGroupID != "" {
|
||||
groupId = channel.BusinessGroupID
|
||||
}
|
||||
|
||||
code, _ := strconv.Atoi(typeCode)
|
||||
channel.RootID = device
|
||||
channel.TypeCode = code
|
||||
channel.GroupID = groupId
|
||||
if err := ChannelDao.SaveChannel(channel); err != nil {
|
||||
Sugar.Infof("保存通道到数据库失败 err: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
58
xml.go
58
xml.go
@@ -15,30 +15,40 @@ type GBModel struct {
|
||||
|
||||
type Channel struct {
|
||||
GBModel
|
||||
DeviceID string `json:"device_id" xml:"DeviceID" gorm:"index"`
|
||||
Name string `json:"name" xml:"Name,omitempty"`
|
||||
Manufacturer string `json:"manufacturer" xml:"Manufacturer,omitempty"`
|
||||
Model string `json:"model" xml:"Model,omitempty"`
|
||||
Owner string `json:"owner" xml:"Owner,omitempty"`
|
||||
CivilCode string `json:"civil_code" xml:"CivilCode,omitempty"`
|
||||
Block string `json:"block" xml:"Block,omitempty"`
|
||||
Address string `json:"address" xml:"Address,omitempty"`
|
||||
Parental string `json:"parental" xml:"Parental,omitempty"`
|
||||
ParentID string `json:"parent_id" xml:"ParentID,omitempty" gorm:"index"`
|
||||
SafetyWay string `json:"safety_way" xml:"SafetyWay,omitempty"`
|
||||
RegisterWay string `json:"register_way" xml:"RegisterWay,omitempty"`
|
||||
CertNum string `json:"cert_num" xml:"CertNum,omitempty"`
|
||||
Certifiable string `json:"certifiable" xml:"Certifiable,omitempty"`
|
||||
ErrCode string `json:"err_code" xml:"ErrCode,omitempty"`
|
||||
EndTime string `json:"end_time" xml:"EndTime,omitempty"`
|
||||
Secrecy string `json:"secrecy" xml:"Secrecy,omitempty"`
|
||||
IPAddress string `json:"ip_address" xml:"IPAddress,omitempty"`
|
||||
Port string `json:"port" xml:"Port,omitempty"`
|
||||
Password string `json:"password" xml:"Password,omitempty"`
|
||||
Status OnlineStatus `json:"status" xml:"Status,omitempty"`
|
||||
Longitude string `json:"longitude" xml:"Longitude,omitempty"`
|
||||
Latitude string `json:"latitude" xml:"Latitude,omitempty"`
|
||||
SetupType SetupType `json:"setup_type,omitempty"`
|
||||
|
||||
// RootID 是设备的根ID, 用于查询设备的所有通道.
|
||||
RootID string `json:"-" xml:"-" gorm:"index"` // 根设备ID
|
||||
TypeCode int `json:"-" xml:"-" gorm:"index"` // 设备类型编码
|
||||
|
||||
// 所在组ID. 扩展的数据库字段, 方便查询某个目录下的设备列表.
|
||||
// 如果ParentID不为空, ParentID作为组ID, 如果ParentID为空, BusinessGroupID作为组ID.
|
||||
GroupID string `json:"-" xml:"-" gorm:"index"`
|
||||
|
||||
DeviceID string `json:"device_id" xml:"DeviceID" gorm:"index"`
|
||||
Name string `json:"name" xml:"Name,omitempty"`
|
||||
Manufacturer string `json:"manufacturer" xml:"Manufacturer,omitempty"`
|
||||
Model string `json:"model" xml:"Model,omitempty"`
|
||||
Owner string `json:"owner" xml:"Owner,omitempty"`
|
||||
CivilCode string `json:"civil_code" xml:"CivilCode,omitempty"`
|
||||
Block string `json:"block" xml:"Block,omitempty"`
|
||||
Address string `json:"address" xml:"Address,omitempty"`
|
||||
Parental string `json:"parental" xml:"Parental,omitempty"`
|
||||
ParentID string `json:"parent_id" xml:"ParentID,omitempty" gorm:"index"` // 父设备ID/系统ID/虚拟目录ID
|
||||
BusinessGroupID string `json:"-" xml:"BusinessGroupID,omitempty" gorm:"index"`
|
||||
SafetyWay string `json:"safety_way" xml:"SafetyWay,omitempty"`
|
||||
RegisterWay string `json:"register_way" xml:"RegisterWay,omitempty"`
|
||||
CertNum string `json:"cert_num" xml:"CertNum,omitempty"`
|
||||
Certifiable string `json:"certifiable" xml:"Certifiable,omitempty"`
|
||||
ErrCode string `json:"err_code" xml:"ErrCode,omitempty"`
|
||||
EndTime string `json:"end_time" xml:"EndTime,omitempty"`
|
||||
Secrecy string `json:"secrecy" xml:"Secrecy,omitempty"`
|
||||
IPAddress string `json:"ip_address" xml:"IPAddress,omitempty"`
|
||||
Port string `json:"port" xml:"Port,omitempty"`
|
||||
Password string `json:"password" xml:"Password,omitempty"`
|
||||
Status OnlineStatus `json:"status" xml:"Status,omitempty"`
|
||||
Longitude string `json:"longitude" xml:"Longitude,omitempty"`
|
||||
Latitude string `json:"latitude" xml:"Latitude,omitempty"`
|
||||
SetupType SetupType `json:"setup_type,omitempty"`
|
||||
}
|
||||
|
||||
func (d *Channel) Online() bool {
|
||||
|
||||
40
xml_test.go
40
xml_test.go
@@ -1,11 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestDecodeXML(t *testing.T) {
|
||||
//var catalogBodyFos *os.File
|
||||
//if catalogBodyFos == nil {
|
||||
// file, err := os.OpenFile("./catalog.raw", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0644)
|
||||
// if err != nil {
|
||||
// panic(err)
|
||||
// }
|
||||
// catalogBodyFos = file
|
||||
//}
|
||||
//
|
||||
//bytes := make([]byte, 4)
|
||||
//binary.BigEndian.PutUint32(bytes, uint32(len(body)))
|
||||
//if _, err := catalogBodyFos.Write(bytes); err != nil {
|
||||
// panic(err)
|
||||
//} else if _, err = catalogBodyFos.Write([]byte(body)); err != nil {
|
||||
// panic(err)
|
||||
//}
|
||||
|
||||
t.Run("save_channels", func(t *testing.T) {
|
||||
file, err := os.ReadFile("./catalog.raw")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
handler := EventHandler{}
|
||||
for i := 0; i < len(file); {
|
||||
size := binary.BigEndian.Uint32(file[i:])
|
||||
i += 4
|
||||
body := file[i : i+int(size)]
|
||||
i += int(size)
|
||||
catalogResponse := &CatalogResponse{}
|
||||
err = DecodeXML(body, catalogResponse)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
handler.OnCatalog(catalogResponse.DeviceID, catalogResponse)
|
||||
}
|
||||
})
|
||||
|
||||
//str := "3c3f786d6c2076657273696f6e3d22312e30223f3e0d0a3c51756572793e0d0a3c436d64547970653e446576696365496e666f3c2f436d64547970653e0d0a3c534e3e323c2f534e3e0d0a3c44657669636549443e33343032303030303030313332303030303030313c2f44657669636549443e0d0a3c2f51756572793e0d0a"
|
||||
str := "3c3f786d6c2076657273696f6e3d22312e302220656e636f64696e673d22474232333132223f3e0d0a3c526573706f6e73653e0d0a3c436d64547970653e436174616c6f673c2f436d64547970653e0d0a3c534e3e313c2f534e3e0d0a3c44657669636549443e33343032303030303030313332303030303030313c2f44657669636549443e0d0a3c53756d4e756d3e313c2f53756d4e756d3e0d0a3c4465766963654c697374204e756d3d2231223e0d0a3c4974656d3e0d0a3c44657669636549443e33343032303030303030313331303030303030313c2f44657669636549443e0d0a3c4e616d653e47423238313831436c69656e743c2f4e616d653e0d0a3c4d616e7566616374757265723e48616958696e3c2f4d616e7566616374757265723e0d0a3c4d6f64656c3e474232383138315f416e64726f69643c2f4d6f64656c3e0d0a3c4f776e65723e4f776e65723c2f4f776e65723e0d0a3c416464726573733e416464726573733c2f416464726573733e0d0a3c506172656e74616c3e303c2f506172656e74616c3e0d0a3c506172656e7449443e33343032303030303030313332303030303030313c2f506172656e7449443e0d0a3c5361666574795761793e303c2f5361666574795761793e0d0a3c52656769737465725761793e313c2f52656769737465725761793e0d0a3c536563726563793e303c2f536563726563793e0d0a3c5374617475733e4f4e3c2f5374617475733e0d0a3c2f4974656d3e0d0a3c2f4465766963654c6973743e0d0a3c2f526573706f6e73653e0d0a"
|
||||
data, err := hex.DecodeString(str)
|
||||
|
||||
Reference in New Issue
Block a user