203 lines
4.9 KiB
Go
203 lines
4.9 KiB
Go
package service
|
||
|
||
import (
|
||
"fmt"
|
||
"sync"
|
||
|
||
"github.com/ossrs/srs-sip/pkg/models"
|
||
)
|
||
|
||
type DeviceInfo struct {
|
||
DeviceID string `json:"device_id"`
|
||
SourceAddr string `json:"source_addr"`
|
||
NetworkType string `json:"network_type"`
|
||
ChannelMap sync.Map `json:"-"`
|
||
}
|
||
|
||
type deviceManager struct {
|
||
devices sync.Map
|
||
}
|
||
|
||
var instance *deviceManager
|
||
var once sync.Once
|
||
|
||
func GetDeviceManager() *deviceManager {
|
||
once.Do(func() {
|
||
instance = &deviceManager{
|
||
devices: sync.Map{},
|
||
}
|
||
})
|
||
return instance
|
||
}
|
||
|
||
func (dm *deviceManager) AddDevice(id string, info *DeviceInfo) {
|
||
channel := models.ChannelInfo{
|
||
DeviceID: id,
|
||
ParentID: id,
|
||
Name: id,
|
||
Status: models.ChannelStatus("ON"),
|
||
}
|
||
info.ChannelMap.Store(channel.DeviceID, channel)
|
||
dm.devices.Store(id, info)
|
||
}
|
||
|
||
func (dm *deviceManager) RemoveDevice(id string) {
|
||
dm.devices.Delete(id)
|
||
}
|
||
|
||
func (dm *deviceManager) GetDevices() []*DeviceInfo {
|
||
list := make([]*DeviceInfo, 0)
|
||
dm.devices.Range(func(key, value interface{}) bool {
|
||
list = append(list, value.(*DeviceInfo))
|
||
return true
|
||
})
|
||
return list
|
||
}
|
||
|
||
func (dm *deviceManager) GetDevice(id string) (*DeviceInfo, bool) {
|
||
v, ok := dm.devices.Load(id)
|
||
if !ok {
|
||
return nil, false
|
||
}
|
||
return v.(*DeviceInfo), true
|
||
}
|
||
|
||
// ChannelParser defines interface for different manufacturer's channel parsing
|
||
type ChannelParser interface {
|
||
ParseChannels(list ...models.ChannelInfo) ([]models.ChannelInfo, error)
|
||
}
|
||
|
||
// channelParserRegistry manages registration and lookup of manufacturer-specific parsers
|
||
type channelParserRegistry struct {
|
||
parsers map[string]ChannelParser
|
||
mu sync.RWMutex
|
||
}
|
||
|
||
var (
|
||
parserRegistry = &channelParserRegistry{
|
||
parsers: make(map[string]ChannelParser),
|
||
}
|
||
)
|
||
|
||
// RegisterParser registers a parser for a specific manufacturer
|
||
func (r *channelParserRegistry) RegisterParser(manufacturer string, parser ChannelParser) {
|
||
r.mu.Lock()
|
||
defer r.mu.Unlock()
|
||
r.parsers[manufacturer] = parser
|
||
}
|
||
|
||
// GetParser retrieves parser for a specific manufacturer
|
||
func (r *channelParserRegistry) GetParser(manufacturer string) (ChannelParser, bool) {
|
||
r.mu.RLock()
|
||
defer r.mu.RUnlock()
|
||
parser, ok := r.parsers[manufacturer]
|
||
return parser, ok
|
||
}
|
||
|
||
// UpdateChannels updates device channel information
|
||
func (dm *deviceManager) UpdateChannels(deviceID string, list ...models.ChannelInfo) error {
|
||
device, ok := dm.GetDevice(deviceID)
|
||
if !ok {
|
||
return fmt.Errorf("device not found: %s", deviceID)
|
||
}
|
||
|
||
// clear ChannelMap
|
||
device.ChannelMap.Range(func(key, value interface{}) bool {
|
||
device.ChannelMap.Delete(key)
|
||
return true
|
||
})
|
||
|
||
parser, ok := parserRegistry.GetParser(list[0].Manufacturer)
|
||
if !ok {
|
||
return fmt.Errorf("no parser found for manufacturer: %s", list[0].Manufacturer)
|
||
}
|
||
|
||
channels, err := parser.ParseChannels(list...)
|
||
if err != nil {
|
||
return fmt.Errorf("failed to parse channels: %v", err)
|
||
}
|
||
|
||
for _, channel := range channels {
|
||
device.ChannelMap.Store(channel.DeviceID, channel)
|
||
}
|
||
dm.devices.Store(deviceID, device)
|
||
return nil
|
||
}
|
||
|
||
func (dm *deviceManager) ApiGetChannelByDeviceId(deviceID string) []models.ChannelInfo {
|
||
device, ok := dm.GetDevice(deviceID)
|
||
if !ok {
|
||
return nil
|
||
}
|
||
|
||
channels := make([]models.ChannelInfo, 0)
|
||
device.ChannelMap.Range(func(key, value interface{}) bool {
|
||
channels = append(channels, value.(models.ChannelInfo))
|
||
return true
|
||
})
|
||
return channels
|
||
}
|
||
|
||
func (dm *deviceManager) GetAllVideoChannels() []models.ChannelInfo {
|
||
channels := make([]models.ChannelInfo, 0)
|
||
dm.devices.Range(func(key, value interface{}) bool {
|
||
device := value.(*DeviceInfo)
|
||
device.ChannelMap.Range(func(key, value interface{}) bool {
|
||
channels = append(channels, value.(models.ChannelInfo))
|
||
return true
|
||
})
|
||
return true
|
||
})
|
||
return channels
|
||
}
|
||
|
||
func (dm *deviceManager) GetDeviceInfoByChannel(channelID string) (*DeviceInfo, bool) {
|
||
var device *DeviceInfo
|
||
found := false
|
||
dm.devices.Range(func(key, value interface{}) bool {
|
||
d := value.(*DeviceInfo)
|
||
_, ok := d.ChannelMap.Load(channelID)
|
||
if ok {
|
||
device = d
|
||
found = true
|
||
return false
|
||
}
|
||
return true
|
||
})
|
||
return device, found
|
||
}
|
||
|
||
// Hikvision channel parser implementation
|
||
type HikvisionParser struct{}
|
||
|
||
func (p *HikvisionParser) ParseChannels(list ...models.ChannelInfo) ([]models.ChannelInfo, error) {
|
||
return list, nil
|
||
}
|
||
|
||
// Dahua channel parser implementation
|
||
type DahuaParser struct{}
|
||
|
||
func (p *DahuaParser) ParseChannels(list ...models.ChannelInfo) ([]models.ChannelInfo, error) {
|
||
return list, nil
|
||
}
|
||
|
||
// Uniview channel parser implementation
|
||
type UniviewParser struct{}
|
||
|
||
func (p *UniviewParser) ParseChannels(list ...models.ChannelInfo) ([]models.ChannelInfo, error) {
|
||
videoChannels := make([]models.ChannelInfo, 0)
|
||
for _, channel := range list {
|
||
// 只有Parental为1的通道,才是视频通道
|
||
if channel.Parental == 1 {
|
||
videoChannels = append(videoChannels, channel)
|
||
}
|
||
}
|
||
return videoChannels, nil
|
||
}
|
||
|
||
func init() {
|
||
parserRegistry.RegisterParser("Hikvision", &HikvisionParser{})
|
||
parserRegistry.RegisterParser("DAHUA", &DahuaParser{})
|
||
parserRegistry.RegisterParser("UNIVIEW", &UniviewParser{})
|
||
}
|