rts-sim-testing-service/third_party/cidc_modbus/cidc_modbus.go

136 lines
3.7 KiB
Go

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/service"
"joylink.club/iot/service/proto"
"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), make([]byte, len(qcs.Qbs)), make([]byte, 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) *proto.ModbusConfig {
return &proto.ModbusConfig{
Url: config.Url,
UnitId: config.UnitId,
Endianness: config.Endianness,
Interval: config.Interval,
Timeout: config.Timeout,
Mapping: convertToModbusDcMapping(config.Mapping),
}
}
func convertToModbusDcMapping(modbusDcMapping []config.ModbusDcMapping) []*proto.ModbusDcMapping {
res := make([]*proto.ModbusDcMapping, 0)
for _, mdm := range modbusDcMapping {
res = append(res, &proto.ModbusDcMapping{
Function: mdm.Function,
Addr: mdm.Addr,
Quantity: mdm.Quantity,
WriteStrategy: mdm.WriteStrategy,
Type: mdm.Type,
Start: mdm.Start,
})
}
return res
}