2024-01-08 17:45:24 +08:00
|
|
|
|
package memory
|
|
|
|
|
|
|
|
|
|
import (
|
2024-01-16 13:44:28 +08:00
|
|
|
|
"encoding/hex"
|
2024-01-08 17:45:24 +08:00
|
|
|
|
"fmt"
|
2024-01-24 17:45:16 +08:00
|
|
|
|
"joylink.club/ecs"
|
2024-01-11 10:24:56 +08:00
|
|
|
|
"strings"
|
2024-01-10 11:17:32 +08:00
|
|
|
|
|
2024-01-08 17:45:24 +08:00
|
|
|
|
"joylink.club/bj-rtsts-server/dto"
|
2024-01-11 10:24:56 +08:00
|
|
|
|
"joylink.club/bj-rtsts-server/dto/data_proto"
|
2024-01-08 17:45:24 +08:00
|
|
|
|
"joylink.club/bj-rtsts-server/sys_error"
|
|
|
|
|
"joylink.club/rtsssimulation/component"
|
2024-01-10 11:17:32 +08:00
|
|
|
|
"joylink.club/rtsssimulation/component/component_data"
|
2024-01-08 17:45:24 +08:00
|
|
|
|
"joylink.club/rtsssimulation/entity"
|
2024-01-10 14:06:01 +08:00
|
|
|
|
"joylink.club/rtsssimulation/repository"
|
|
|
|
|
"joylink.club/rtsssimulation/repository/model/proto"
|
|
|
|
|
"joylink.club/rtsssimulation/util/number"
|
|
|
|
|
"sort"
|
2024-01-08 17:45:24 +08:00
|
|
|
|
)
|
|
|
|
|
|
2024-01-10 14:06:01 +08:00
|
|
|
|
// BalisePositionModify 应答器移位
|
2024-01-11 13:55:19 +08:00
|
|
|
|
func BalisePositionModify(simulation *VerifySimulation, req *dto.BaliseMoveReqDto) *sys_error.BusinessError {
|
2024-01-11 10:24:56 +08:00
|
|
|
|
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
|
2024-01-10 14:06:01 +08:00
|
|
|
|
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,
|
|
|
|
|
}
|
2024-01-11 10:24:56 +08:00
|
|
|
|
if req.Km.Direction == data_proto.KilometerSystem_LEFT {
|
2024-01-10 14:06:01 +08:00
|
|
|
|
km.Direction = proto.Direction_LEFT
|
2024-01-11 10:24:56 +08:00
|
|
|
|
} else if req.Km.Direction == data_proto.KilometerSystem_RIGHT {
|
2024-01-10 14:06:01 +08:00
|
|
|
|
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)
|
2024-01-11 13:55:19 +08:00
|
|
|
|
if km.Value <= minKm.Value || km.Value >= maxKm.Value {
|
2024-01-18 10:08:55 +08:00
|
|
|
|
return sys_error.New("位置设置错误,必须在相邻的应答器/道岔/轨道边界之间")
|
2024-01-10 14:06:01 +08:00
|
|
|
|
}
|
|
|
|
|
component.KmType.Set(entry, km)
|
|
|
|
|
offset := number.Abs(km.Value - akm.Value)
|
2024-01-10 14:17:15 +08:00
|
|
|
|
component.LinkPositionType.Set(entry, &component_data.LinkPosition{
|
2024-01-10 14:06:01 +08:00
|
|
|
|
LinkId: link.Id(),
|
|
|
|
|
Offset: offset,
|
|
|
|
|
})
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BalisePositionReset 应答器复位
|
2024-01-24 17:45:16 +08:00
|
|
|
|
func BalisePositionReset(simulation *VerifySimulation, req *dto.BaliseReqDto) *sys_error.BusinessError {
|
2024-01-11 10:24:56 +08:00
|
|
|
|
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
|
|
|
|
|
balise := simulation.Repo.FindTransponder(uid)
|
|
|
|
|
if balise == nil {
|
2024-01-10 14:06:01 +08:00
|
|
|
|
return sys_error.New(fmt.Sprintf("未找到[mapId:%d id:%d]的应答器", req.MapId, req.BaliseId))
|
2024-01-08 17:45:24 +08:00
|
|
|
|
}
|
2024-01-11 10:24:56 +08:00
|
|
|
|
return balisePositionReset(simulation, balise)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-24 17:45:16 +08:00
|
|
|
|
func balisePositionReset(simulation *VerifySimulation, balise *repository.Transponder) *sys_error.BusinessError {
|
2024-01-11 10:24:56 +08:00
|
|
|
|
entry, _ := entity.GetEntityByUid(simulation.World, balise.Id())
|
|
|
|
|
component.KmType.Set(entry, balise.Km())
|
2024-01-10 14:17:15 +08:00
|
|
|
|
component.LinkPositionType.SetValue(entry, component_data.LinkPosition{
|
2024-01-11 10:24:56 +08:00
|
|
|
|
LinkId: balise.LinkPosition().Link().Id(),
|
|
|
|
|
Offset: balise.LinkPosition().Offset(),
|
2024-01-10 14:06:01 +08:00
|
|
|
|
})
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaliseTelegramModify 修改应答器报文
|
2024-01-24 17:45:16 +08:00
|
|
|
|
func BaliseTelegramModify(simulation *VerifySimulation, req *dto.BaliseModifyTelegramReqDto) *sys_error.BusinessError {
|
2024-01-11 10:24:56 +08:00
|
|
|
|
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
|
2024-01-10 14:06:01 +08:00
|
|
|
|
entry, ok := entity.GetEntityByUid(simulation.World, uid)
|
|
|
|
|
if !ok {
|
|
|
|
|
return sys_error.New(fmt.Sprintf("没有[mapId:%d id:%d]的应答器", req.MapId, req.BaliseId))
|
2024-01-08 17:45:24 +08:00
|
|
|
|
}
|
2024-01-22 11:06:30 +08:00
|
|
|
|
fixedTelegramLen := 256
|
|
|
|
|
if len(req.FixedTelegram) != fixedTelegramLen {
|
|
|
|
|
return sys_error.New(fmt.Sprintf("固定报文长度必须为[%d]", fixedTelegramLen))
|
2024-01-16 13:44:28 +08:00
|
|
|
|
}
|
2024-01-22 11:06:30 +08:00
|
|
|
|
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)
|
2024-01-16 13:44:28 +08:00
|
|
|
|
if err != nil {
|
2024-01-22 11:06:30 +08:00
|
|
|
|
return sys_error.New("固定用户报文解析出错", err)
|
2024-01-16 13:44:28 +08:00
|
|
|
|
}
|
2024-01-24 17:45:16 +08:00
|
|
|
|
vt, err := hex.DecodeString(req.VariableTelegram)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return sys_error.New("可变报文解析出错", err)
|
|
|
|
|
}
|
|
|
|
|
vut, err := hex.DecodeString(req.VariableUserTelegram)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return sys_error.New("可变用户报文解析出错", err)
|
|
|
|
|
}
|
|
|
|
|
return sendEcsRequest(simulation.World, func() error {
|
|
|
|
|
component.BaliseFixedTelegramType.SetValue(entry, component.BaliseState{
|
|
|
|
|
Telegram: ft,
|
|
|
|
|
UserTelegram: fut,
|
|
|
|
|
})
|
|
|
|
|
if entry.HasComponent(component.BaliseVariableTelegramType) {
|
|
|
|
|
component.BaliseVariableTelegramType.SetValue(entry, component.BaliseState{
|
|
|
|
|
Telegram: vt,
|
|
|
|
|
UserTelegram: vut,
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
return nil
|
2024-01-22 11:06:30 +08:00
|
|
|
|
})
|
2024-01-10 14:06:01 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// BaliseTelegramReset 重置应答器报文
|
2024-01-24 17:45:16 +08:00
|
|
|
|
func BaliseTelegramReset(simulation *VerifySimulation, req *dto.BaliseReqDto) *sys_error.BusinessError {
|
2024-01-11 10:24:56 +08:00
|
|
|
|
uid := QueryMapUidMapByType(req.MapId, &data_proto.Transponder{})[req.BaliseId].Uid
|
2024-01-10 14:06:01 +08:00
|
|
|
|
worldData := entity.GetWorldData(simulation.World)
|
2024-01-11 10:24:56 +08:00
|
|
|
|
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)
|
|
|
|
|
}
|
|
|
|
|
|
2024-01-24 17:45:16 +08:00
|
|
|
|
func baliseTelegramReset(simulation *VerifySimulation, balise *repository.Transponder) *sys_error.BusinessError {
|
2024-01-11 10:24:56 +08:00
|
|
|
|
entry, _ := entity.GetEntityByUid(simulation.World, balise.Id())
|
2024-01-24 17:45:16 +08:00
|
|
|
|
return sendEcsRequest(simulation.World, func() error {
|
|
|
|
|
component.BaliseFixedTelegramType.SetValue(entry, component.BaliseState{
|
|
|
|
|
Telegram: balise.FixedTelegram(),
|
|
|
|
|
UserTelegram: balise.FixedUserTelegram(),
|
|
|
|
|
})
|
|
|
|
|
if entry.HasComponent(component.BaliseVariableTelegramType) {
|
|
|
|
|
component.BaliseVariableTelegramType.SetValue(entry, component.BaliseState{})
|
|
|
|
|
}
|
|
|
|
|
return nil
|
2024-01-08 17:45:24 +08:00
|
|
|
|
})
|
|
|
|
|
}
|
2024-01-10 14:06:01 +08:00
|
|
|
|
|
|
|
|
|
// BaliseReset 重置应答器所有状态
|
2024-01-24 17:45:16 +08:00
|
|
|
|
func BaliseReset(simulation *VerifySimulation) *sys_error.BusinessError {
|
2024-01-11 10:24:56 +08:00
|
|
|
|
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)
|
|
|
|
|
}
|
2024-01-10 14:06:01 +08:00
|
|
|
|
}
|
2024-01-11 10:24:56 +08:00
|
|
|
|
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
|
2024-01-10 14:06:01 +08:00
|
|
|
|
}
|
2024-01-24 17:45:16 +08:00
|
|
|
|
|
|
|
|
|
func sendEcsRequest(w ecs.World, handler func() error) *sys_error.BusinessError {
|
|
|
|
|
result := <-ecs.Request(w, func() ecs.Result[ecs.EmptyType] {
|
|
|
|
|
err := handler()
|
|
|
|
|
if err != nil {
|
|
|
|
|
return ecs.NewErrResult(err)
|
|
|
|
|
}
|
|
|
|
|
return ecs.NewOkEmptyResult()
|
|
|
|
|
})
|
|
|
|
|
if result.Err != nil {
|
|
|
|
|
return sys_error.New("仿真世界请求执行失败", result.Err)
|
|
|
|
|
}
|
|
|
|
|
return nil
|
|
|
|
|
}
|