rts-sim-testing-service/ts/simulation/wayside/memory/wayside_memory_transponder.go

198 lines
6.9 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package memory
import (
"encoding/hex"
"fmt"
"strings"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/dto/data_proto"
"joylink.club/bj-rtsts-server/sys_error"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/component/component_data"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto"
"joylink.club/rtsssimulation/util/number"
"sort"
)
// BalisePositionModify 应答器移位
func BalisePositionModify(simulation *VerifySimulation, req *dto.BaliseMoveReqDto) *sys_error.BusinessError {
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
transponder := simulation.Repo.FindTransponder(uid)
if transponder == nil {
return sys_error.New(fmt.Sprintf("未找到[mapId:%d id:%d]的应答器", req.MapId, req.BaliseId))
}
//将请求参数中的公里标转为rtss仿真所用的公里标
km := &proto.Kilometer{
Value: req.Km.Kilometer,
CoordinateSystem: req.Km.CoordinateSystem,
}
if req.Km.Direction == data_proto.KilometerSystem_LEFT {
km.Direction = proto.Direction_LEFT
} else if req.Km.Direction == data_proto.KilometerSystem_RIGHT {
km.Direction = proto.Direction_RIGHT
} else {
panic(fmt.Sprintf("未知的公里标方向[%d]", req.Km.Direction))
}
//将应答器所在Link的两端公里标转为请求参数中公里标的坐标系
link := transponder.LinkPosition().Link()
akm, err := repository.ConvertKilometer(simulation.Repo, link.AKm(), km.CoordinateSystem)
if err != nil {
panic(sys_error.New("应答器所在Link的起点公里标转换失败"))
}
bkm, err := repository.ConvertKilometer(simulation.Repo, link.BKm(), km.CoordinateSystem)
if err != nil {
panic(sys_error.New("应答器所在Link的终点公里标转换失败"))
}
//筛选出Link上所有的应答器并按公里标大小排序
var transponders []*repository.Transponder
for _, device := range link.Devices() {
t, ok := device.(*repository.Transponder)
if ok {
transponders = append(transponders, t)
}
}
sort.Slice(transponders, func(i, j int) bool {
aT := transponders[i]
bT := transponders[j]
aTKm, err := repository.ConvertKilometer(simulation.Repo, aT.Km(), km.CoordinateSystem)
if err != nil {
panic(sys_error.New(fmt.Sprintf("应答器[id:%s]公里标转换失败", aT.Id())))
}
bTKm, err := repository.ConvertKilometer(simulation.Repo, bT.Km(), km.CoordinateSystem)
if err != nil {
panic(sys_error.New(fmt.Sprintf("应答器[id:%s]公里标转换失败", bT.Id())))
}
return aTKm.Value < bTKm.Value
})
//确保请求的公里标没有超出Link范围且在相邻的应答器之间
var minKm *proto.Kilometer
var maxKm *proto.Kilometer
if akm.Value < bkm.Value {
minKm = akm
maxKm = bkm
} else {
minKm = bkm
maxKm = akm
}
for i, t := range transponders {
if t == transponder {
if i > 0 {
minKm, err = repository.ConvertKilometer(simulation.Repo, transponders[i-1].Km(), km.CoordinateSystem)
}
if i < len(transponders)-1 {
maxKm, err = repository.ConvertKilometer(simulation.Repo, transponders[i+1].Km(), km.CoordinateSystem)
}
}
}
//更新应答器公里标和Link位置
entry, _ := entity.GetEntityByUid(simulation.World, uid)
if km.Value <= minKm.Value || km.Value >= maxKm.Value {
return sys_error.New("位置设置错误,必须在相邻的应答器/道岔/轨道边界之间")
}
component.KmType.Set(entry, km)
offset := number.Abs(km.Value - akm.Value)
component.LinkPositionType.Set(entry, &component_data.LinkPosition{
LinkId: link.Id(),
Offset: offset,
})
return nil
}
// BalisePositionReset 应答器复位
func BalisePositionReset(simulation *VerifySimulation, req *dto.BaliseReqDto) error {
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
balise := simulation.Repo.FindTransponder(uid)
if balise == nil {
return sys_error.New(fmt.Sprintf("未找到[mapId:%d id:%d]的应答器", req.MapId, req.BaliseId))
}
return balisePositionReset(simulation, balise)
}
func balisePositionReset(simulation *VerifySimulation, balise *repository.Transponder) error {
entry, _ := entity.GetEntityByUid(simulation.World, balise.Id())
component.KmType.Set(entry, balise.Km())
component.LinkPositionType.SetValue(entry, component_data.LinkPosition{
LinkId: balise.LinkPosition().Link().Id(),
Offset: balise.LinkPosition().Offset(),
})
return nil
}
// BaliseTelegramModify 修改应答器报文
func BaliseTelegramModify(simulation *VerifySimulation, req *dto.BaliseModifyTelegramReqDto) error {
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
entry, ok := entity.GetEntityByUid(simulation.World, uid)
if !ok {
return sys_error.New(fmt.Sprintf("没有[mapId:%d id:%d]的应答器", req.MapId, req.BaliseId))
}
fixedTelegramLen := 256
if len(req.FixedTelegram) != fixedTelegramLen {
return sys_error.New(fmt.Sprintf("固定报文长度必须为[%d]", fixedTelegramLen))
}
fixedUserTelegramLen := 208
if len(req.FixedUserTelegram) != fixedUserTelegramLen {
return sys_error.New(fmt.Sprintf("固定用户报文长度必须为[%d]", fixedUserTelegramLen))
}
ft, err := hex.DecodeString(req.FixedTelegram)
if err != nil {
return sys_error.New("固定报文解析出错", err)
}
fut, err := hex.DecodeString(req.FixedUserTelegram)
if err != nil {
return sys_error.New("固定用户报文解析出错", err)
}
component.BaliseFixedTelegramType.SetValue(entry, component.BaliseState{
Telegram: ft,
UserTelegram: fut,
})
return nil
}
// BaliseTelegramReset 重置应答器报文
func BaliseTelegramReset(simulation *VerifySimulation, req *dto.BaliseReqDto) error {
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
worldData := entity.GetWorldData(simulation.World)
balise := worldData.Repo.FindTransponder(uid)
if balise == nil {
return sys_error.New(fmt.Sprintf("未找到[mapId:%d id:%d]的应答器", req.MapId, req.BaliseId))
}
return baliseTelegramReset(simulation, balise)
}
func baliseTelegramReset(simulation *VerifySimulation, balise *repository.Transponder) error {
entry, _ := entity.GetEntityByUid(simulation.World, balise.Id())
component.BaliseFixedTelegramType.SetValue(entry, component.BaliseState{
Telegram: balise.FixedTelegram(),
})
return nil
}
// BaliseReset 重置应答器所有状态
func BaliseReset(simulation *VerifySimulation) error {
var errs []error
for _, balise := range simulation.Repo.ResponderList() {
err := baliseTelegramReset(simulation, balise)
if err != nil {
errs = append(errs, err)
}
err = balisePositionReset(simulation, balise)
if err != nil {
errs = append(errs, err)
}
}
if len(errs) > 0 {
var userMsg []string
for _, err := range errs {
be, ok := err.(*sys_error.BusinessError)
if ok {
userMsg = append(userMsg, be.UserMsg)
}
}
return sys_error.New(strings.Join(userMsg, "\n"))
}
return nil
}