package main import ( "fmt" "sync" "github.com/sirupsen/logrus" "lc/common/protocol" ) type ModelInfo struct { TID uint16 Flag int } type Device interface { Start() Stop() UpdateInfo(devinfo protocol.DevInfo) GetDevInfo() *protocol.DevInfo UpdateModel(tid uint16, flag int) } func CreateDevice(t uint8, devinfo *protocol.DevInfo) Device { var device Device switch t { case 0: device = NewModbusRtu(devinfo) case 1: device = NewConcentrator(devinfo) case 2: device = NewYmLampController(devinfo) default: logrus.Errorf("AddDevices:不支持的协议的设备:mode=%d", t) } return device } var _onceGetDeviceMgr sync.Once var _singleSerialMgr *DeviceMgr func GetDeviceMgr() *DeviceMgr { _onceGetDeviceMgr.Do(func() { _singleSerialMgr = &DeviceMgr{mapDevice: make(map[string]Device)} }) return _singleSerialMgr } type DeviceMgr struct { mu sync.Mutex mapDevice map[string]Device } func validateDevInfos(devinfos []protocol.DevInfo) error { for i := range devinfos { v := &devinfos[i] if v.DevCode == "" { return fmt.Errorf("DevCode 不能为空") } if v.TID == 0 { return fmt.Errorf("设备[%s]的 TID 不能为 0,请指定正确的物模型ID", v.DevCode) } if v.ProtocolType > 2 { return fmt.Errorf("设备[%s]的 ProtocolType=%d 不支持,仅支持 0(ModbusRTU) 1(Zigbee) 2(裕明485)", v.DevCode, v.ProtocolType) } // 同批次内 DevCode 唯一性 for j := i + 1; j < len(devinfos); j++ { if v.DevCode == devinfos[j].DevCode { return fmt.Errorf("同一文件中 DevCode=%s 重复", v.DevCode) } } // 同批次内同一 Code 下 DevID 冲突检测 for j := i + 1; j < len(devinfos); j++ { if v.Code == devinfos[j].Code && v.DevID == devinfos[j].DevID { return fmt.Errorf("同一串口[Code=%d]下 DevID=%d 冲突(设备 %s 和 %s)", v.Code, v.DevID, v.DevCode, devinfos[j].DevCode) } } } return nil } func (o *DeviceMgr) checkDevIDConflict(v *protocol.DevInfo) error { for _, exist := range o.mapDevice { ei := exist.GetDevInfo() if ei.Code == v.Code && ei.DevID == v.DevID && ei.DevCode != v.DevCode { return fmt.Errorf("串口[Code=%d]下 DevID=%d 已被设备[%s]占用,设备[%s]不能使用相同地址", v.Code, v.DevID, ei.DevCode, v.DevCode) } } return nil } // AddDevices 新增 func (o *DeviceMgr) AddDevices(devinfos []protocol.DevInfo) { if err := validateDevInfos(devinfos); err != nil { logrus.Errorf("AddDevices: 配置校验失败: %v", err) return } o.mu.Lock() defer o.mu.Unlock() for _, v := range devinfos { if _, ok := o.mapDevice[v.DevCode]; ok { logrus.Errorf("AddDevices:已添加该设备,不可重复添加:devcode=%s", v.DevCode) continue } if err := o.checkDevIDConflict(&v); err != nil { logrus.Errorf("AddDevices: %v", err) continue } di := v if device := CreateDevice(v.ProtocolType, &di); device != nil { device.Start() o.mapDevice[v.DevCode] = device } } } // RemoveDevice 删除 func (o *DeviceMgr) RemoveDevice(devcode string) { o.mu.Lock() defer o.mu.Unlock() if device, ok := o.mapDevice[devcode]; ok { device.Stop() delete(o.mapDevice, devcode) } } // UpdateDevices 新增或修改 func (o *DeviceMgr) UpdateDevices(code uint8, devinfos []protocol.DevInfo) { if len(devinfos) > 0 { if err := validateDevInfos(devinfos); err != nil { logrus.Errorf("UpdateDevices: 配置校验失败: %v", err) return } } //先遍历devinfos mapDevinfos := make(map[string]*protocol.DevInfo) for _, v := range devinfos { mapDevinfos[v.DevCode] = &v } o.mu.Lock() defer o.mu.Unlock() if len(devinfos) == 0 { for k, v := range o.mapDevice { if v.GetDevInfo().Code == code { v.Stop() delete(o.mapDevice, k) } } return } //先删除不再用的设备 for k, v := range o.mapDevice { if v.GetDevInfo().Code != code { continue } if _, ok := mapDevinfos[k]; !ok { v.Stop() delete(o.mapDevice, k) } } //再添加新的设备或更新设备 for _, v := range devinfos { if device, ok := o.mapDevice[v.DevCode]; ok { old := device.GetDevInfo() if v.ProtocolType == old.ProtocolType { //设备类型没变 device.UpdateInfo(v) //更新设备信息 if v.TID != old.TID { //更新物模型信息 device.UpdateModel(v.TID, 3) } continue } else { device.Stop() delete(o.mapDevice, v.DevCode) } } else { if err := o.checkDevIDConflict(&v); err != nil { logrus.Errorf("UpdateDevices: %v", err) continue } } if device := CreateDevice(v.ProtocolType, &v); device != nil { device.Start() o.mapDevice[v.DevCode] = device } } } // GetDevice 查询 func (o *DeviceMgr) GetDevice(devcode string) Device { o.mu.Lock() defer o.mu.Unlock() if device, ok := o.mapDevice[devcode]; ok { return device } return nil } // StopDevice 停止 func (o *DeviceMgr) StopDevice(devcode string) { o.mu.Lock() defer o.mu.Unlock() if device, ok := o.mapDevice[devcode]; ok { device.Stop() delete(o.mapDevice, devcode) } } // StopAllDevice 停止所有 func (o *DeviceMgr) StopAllDevice() { o.mu.Lock() defer o.mu.Unlock() for k, v := range o.mapDevice { v.Stop() delete(o.mapDevice, k) } } // UpdateModel 更新模型 func (o *DeviceMgr) UpdateModel(tid uint16, flag int) { o.mu.Lock() defer o.mu.Unlock() for _, v := range o.mapDevice { v.UpdateModel(tid, flag) } }