package cidcmodbus import ( "fmt" "log/slog" "time" "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/ts/simulation/wayside/memory" "joylink.club/iot/dto" "joylink.club/iot/service" "joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/entity" ) // 联锁驱采Modbus服务 type CidcModbusService interface { Stop() } var serviceManage = &cidcModbusServiceManage{} type cidcModbusServiceManage struct { services []*cidcModbusService } func (m *cidcModbusServiceManage) Stop() { for _, s := range m.services { s.Stop() } m.services = nil } func Stop() { serviceManage.Stop() } func Start(vs *memory.VerifySimulation) error { for _, cmc := range vs.GetCidcModbusConfig() { if cmc.Open { cms, err := newCidcModbusService(vs, &cmc) if err != nil { return err } serviceManage.services = append(serviceManage.services, cms) } } return nil } type cidcModbusService struct { vs *memory.VerifySimulation // 仿真对象 modbusConfig *config.CidcModbusConfig // modbus驱采配置 ecsUid string // 联锁集中站uid qcms service.IotQcMappingService // modbus驱采映射服务 } func (s *cidcModbusService) update() { wd := entity.GetWorldData(s.vs.World) qce := wd.FindQcEntityByEcsId(s.ecsUid) if qce == nil { panic(fmt.Sprintf("联锁驱采Modbus服务查询状态失败,仿真不存在集中站联锁: %s", s.ecsUid)) } qcs := component.CiQcStateType.Get(qce) if qcs == nil { panic(fmt.Sprintf("联锁驱采Modbus服务查询状态失败,集中站联锁驱采状态不存在: %s", s.ecsUid)) } // 写采集数据 err := s.qcms.WriteCjBytes(qcs.Cbs) if err != nil { slog.Error("联锁驱采Modbus服务写采集数据失败", err) } // 读驱动数据 qs := s.qcms.GetQdBytes() qcs.Qbs = qs } // Stop implements CidcModbusService. func (s *cidcModbusService) Stop() { s.qcms.Stop() } func newCidcModbusService(vs *memory.VerifySimulation, modbusConfig *config.CidcModbusConfig) (*cidcModbusService, error) { station := vs.Repo.FindStationByStationName(modbusConfig.Ecs) if station == nil { return nil, fmt.Errorf("联锁驱采Modbus服务创建失败,未找到联锁集中站: %s", modbusConfig.Ecs) } ecsId := station.Id() // 获取 wd := entity.GetWorldData(vs.World) qce := wd.FindQcEntityByEcsId(ecsId) if qce == nil { return nil, fmt.Errorf("联锁驱采Modbus服务创建失败,仿真不存在集中站联锁: %s", ecsId) } qcs := component.CiQcStateType.Get(qce) qcms, err := service.NewModbusQcService(converToModbusDcConfig(modbusConfig, len(qcs.Qbs), len(qcs.Cbs))) if err != nil { return nil, fmt.Errorf("联锁驱采Modbus服务创建失败: %s", err) } cms := &cidcModbusService{ vs: vs, modbusConfig: modbusConfig, ecsUid: ecsId, qcms: qcms, } // 注册驱采数据仿真更新 qcms.RegisterQcDataHandleScheduleTask(cms.update, time.Millisecond*time.Duration(modbusConfig.Interval)) return cms, nil } func converToModbusDcConfig(config *config.CidcModbusConfig, qdl, cjl int) *dto.ModbusConfig { return &dto.ModbusConfig{ Url: config.Url, UnitId: config.UnitId, Endianness: config.Endianness, Interval: config.Interval, Timeout: config.Timeout, Qdl: uint32(qdl), Cjl: uint32(cjl), Mapping: convertToModbusDcMapping(config.Mapping), } } func convertToModbusDcMapping(modbusDcMapping []config.ModbusDcMapping) []*dto.ModbusDcMapping { res := make([]*dto.ModbusDcMapping, 0) for _, mdm := range modbusDcMapping { res = append(res, &dto.ModbusDcMapping{ Function: mdm.Function, Addr: mdm.Addr, Quantity: mdm.Quantity, Type: mdm.Type, Start: mdm.Start, }) } return res }