【增加IBP盘对象映射】【半实物协议增加阻力等信息】

This commit is contained in:
weizhihong 2023-10-16 14:52:58 +08:00
parent b698316777
commit ac5e8f843b
7 changed files with 222 additions and 16 deletions

View File

@ -57,7 +57,7 @@ func init() {
}
trainState := sta.(*state.TrainState)
// 给半实物仿真发送速度
vobc.SendTrainSpeedTask(math.Abs(float64(info.Speed * 36)))
vobc.SendTrainSpeedTask(convertVobc(info))
// 更新列车状态
memory.UpdateTrainState(simulation, convert(info, trainState, simulation))
}
@ -207,6 +207,21 @@ func convert(info *dynamics.TrainInfo, sta *state.TrainState, simulation *memory
return sta
}
// 转换成Vobc发送参数
func convertVobc(info *dynamics.TrainInfo) *vobc.SendTrainInfo {
param := &vobc.SendTrainInfo{
Speed: uint16(math.Abs(float64(info.Speed * 36))),
Upslope: info.UpSlope,
Slope: uint16(info.Slope),
Acceleration: uint16(info.Acceleration * 100),
TotalResistance: uint16(info.TotalResistance / 10),
AirResistance: uint16(info.AirResistance / 10),
SlopeResistance: uint16(info.SlopeResistance / 10),
CurveResistance: uint16(info.CurveResistance / 10),
}
return param
}
func dynamicsRun(verifySimulation *memory.VerifySimulation) {
_ = dynamics.Run(func() []*dynamics.TurnoutInfo {
stateSlice := memory.GetAllTurnoutState(verifySimulation)

View File

@ -19,12 +19,14 @@ import (
var (
giTypeMap sync.Map
giNameMap sync.Map
giDataMap sync.Map
)
// 将发布的地图数据放入内存中
func PublishMapVerifyStructure(graphic *model.PublishedGi) {
giTypeMap.Store(graphic.ID, graphicData.PictureType(graphic.Type))
giNameMap.Store(graphic.Name, graphic.ID)
var message proto.Message
switch graphicData.PictureType(graphic.Type) {
case graphicData.PictureType_StationLayout:
@ -92,6 +94,22 @@ func QueryEcsLinkByDeviceInfo(repo *repository.Repository, mapId int32, id strin
}
}
func getStorageIBPMapData(mapCode string) *graphicData.IBPGraphicStorage {
// 处理关联的IBP盘信息
if mapCode == "" {
return nil
}
ibpId, ok := giNameMap.Load(mapCode)
if !ok {
return nil
}
ibpMapData, ok := giDataMap.Load(ibpId)
if !ok {
return nil
}
return ibpMapData.(*graphicData.IBPGraphicStorage)
}
// 根据物理区段上的偏移量基于区段A端找到所在link的linkId与偏移量
func sectionMapToEcsLink(repo *repository.Repository, id string, offset int64, runDirection bool) (int32, int64, bool, bool, int64) {
section := repo.FindPhysicalSection(id)

View File

@ -2,7 +2,6 @@ package memory
import (
"fmt"
"strconv"
"sync"
"joylink.club/bj-rtsts-server/ats/verify/protos/graphicData"
@ -161,21 +160,16 @@ func initStationUid(data *graphicData.RtssGraphicStorage) *stationUidStructure {
Uid: GenerateElementUid(city, lineId, nil, s.Code),
}
// 处理关联的IBP盘信息
if s.RefIbpMapCode == "" {
continue
}
ibpId, _ := strconv.Atoi(s.RefIbpMapCode)
ibpMapData, ok := giDataMap.Load(ibpId)
if !ok {
continue
}
initIBPUid(gus, city, lineId, s, ibpMapData.(*graphicData.IBPGraphicStorage))
initIBPUid(gus, city, lineId, s, getStorageIBPMapData(s.RefIbpMapCode))
}
return gus
}
// 处理IBP盘信息
func initIBPUid(gus *stationUidStructure, city, lineId string, station *graphicData.Station, data *graphicData.IBPGraphicStorage) {
if data == nil {
return
}
// 设备所属组合
refMap := make(map[string]string)
for _, r := range data.IbpRelatedDevices {
@ -196,24 +190,28 @@ func initIBPUid(gus *stationUidStructure, city, lineId string, station *graphicD
for _, d := range data.IbpButtons { // ibp按钮
uidMap[d.Common.Id] = &elementIdStructure{
CommonId: d.Common.Id,
Code: d.Code,
Uid: GenerateElementUid(city, lineId, []string{station.Code}, getCode(d.Common.Id, d.Code)),
}
}
for _, d := range data.IbpKeys { // ibp钥匙
uidMap[d.Common.Id] = &elementIdStructure{
CommonId: d.Common.Id,
Code: d.Code,
Uid: GenerateElementUid(city, lineId, []string{station.Code}, getCode(d.Common.Id, d.Code)),
}
}
for _, d := range data.IbpAlarms { // ibp报警器
uidMap[d.Common.Id] = &elementIdStructure{
CommonId: d.Common.Id,
Code: d.Code,
Uid: GenerateElementUid(city, lineId, []string{station.Code}, getCode(d.Common.Id, d.Code)),
}
}
for _, d := range data.IbpLights { // ibp指示灯
uidMap[d.Common.Id] = &elementIdStructure{
CommonId: d.Common.Id,
Code: d.Code,
Uid: GenerateElementUid(city, lineId, []string{station.Code}, getCode(d.Common.Id, d.Code)),
}
}

View File

@ -2,6 +2,7 @@ package memory
import (
"fmt"
"log/slog"
"sort"
"strconv"
"strings"
@ -213,6 +214,10 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *graphicD
for _, signal := range repo.Signals {
signalMap[signal.Id] = signal
}
stationMap := make(map[string]*proto.Station)
for _, station := range repo.Stations {
stationMap[station.Id] = station
}
for _, relationship := range relayGi.DeviceRelateRelayList {
switch relationship.DeviceType {
case graphicData.RelatedRef_Turnout:
@ -253,6 +258,24 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *graphicD
ComponentIds: componentIds,
})
}
case graphicData.RelatedRef_station:
station := stationMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
if station == nil {
continue
}
for _, group := range relationship.Combinationtypes {
d := &proto.ElectronicGroup{Code: group.Code}
for _, relayId := range group.RefRelays {
if uidsMap.RelayIds[relayId] == nil {
continue
}
d.Components = append(d.Components, &proto.ElectronicComponent{
Id: uidsMap.RelayIds[relayId].Uid,
DeviceType: proto.DeviceType_DeviceType_Relay,
})
}
station.ElectronicGroup = append(station.ElectronicGroup, d)
}
}
}
}
@ -410,6 +433,133 @@ func fillProtoRepository(repo *proto.Repository, storage *graphicData.RtssGraphi
SameTrend: data.SameTrend,
})
}
// 初始化站场图按钮
for _, data := range storage.EsbButtons {
repo.Buttons = append(repo.Buttons, &proto.Button{
Id: uidsMap.ButtonIds[data.Common.Id].Uid,
Code: data.Code,
ButtonType: proto.Button_Reset_Press,
})
}
// 车站关联关系
relateMap := make(map[string]*graphicData.StationRelateDevice)
for _, data := range storage.StationRelateDeviceList {
relateMap[data.Code] = data
}
// 处理车站信息
for _, data := range storage.Stations {
station := &proto.Station{
Id: uidsMap.StationIds[data.Common.Id].Uid,
Code: data.Code,
}
// 关联车站的设备
refs, ok := relateMap[data.Code]
if ok {
for _, c := range refs.Combinationtypes {
group := &proto.ElectronicGroup{Code: c.Code}
for _, d := range c.RefDevices {
var comp *proto.ElectronicComponent
if uidsMap.ButtonIds[d] != nil { // 目前只处理按钮
comp = &proto.ElectronicComponent{
Id: uidsMap.ButtonIds[d].Uid,
DeviceType: proto.DeviceType_DeviceType_Button,
}
} else {
continue
}
group.Components = append(group.Components, comp)
}
station.ElectronicGroup = append(station.ElectronicGroup, group)
}
}
// 处理车站关联IBP的设备
handlerIBPDeviceToStation(uidsMap, station, repo, data.RefIbpMapCode)
repo.Stations = append(repo.Stations, station)
}
}
// 将IBP的设备关联到车站中
func handlerIBPDeviceToStation(uidsMap *stationUidStructure, station *proto.Station, repo *proto.Repository, ibpMap string) {
storage := getStorageIBPMapData(ibpMap)
if storage == nil {
return
}
ibpIdMap := uidsMap.IBPIds[station.Code] // 车站对应的UID集合
typeMap := make(map[string]proto.DeviceType) // 对应的设备类型
for _, data := range storage.IbpButtons { // 处理按钮
buttonType := proto.Button_NO_Reset_Press
if data.IsSelfReset {
buttonType = proto.Button_Reset_Press
}
b := &proto.Button{
Id: ibpIdMap[data.Common.Id].Uid,
Code: data.Code,
ButtonType: buttonType,
}
typeMap[data.Common.Id] = proto.DeviceType_DeviceType_Button
repo.Buttons = append(repo.Buttons, b)
}
for _, data := range storage.IbpKeys { // 钥匙
b := &proto.Button{
Id: ibpIdMap[data.Common.Id].Uid,
Code: data.Code,
ButtonType: proto.Button_Key_Knob,
}
typeMap[data.Common.Id] = proto.DeviceType_DeviceType_Button
repo.Buttons = append(repo.Buttons, b)
}
for _, data := range storage.IbpAlarms { // 报警器
b := &proto.Alarm{
Id: ibpIdMap[data.Common.Id].Uid,
Code: data.Code,
}
typeMap[data.Common.Id] = proto.DeviceType_DeviceType_Alarm
repo.Alarms = append(repo.Alarms, b)
}
for _, data := range storage.IbpLights { // 指示灯
b := &proto.Light{
Id: ibpIdMap[data.Common.Id].Uid,
Code: data.Code,
Aspect: converIbpLightAspect(data.Color),
}
typeMap[data.Common.Id] = proto.DeviceType_DeviceType_Light
repo.Lights = append(repo.Lights, b)
}
// 组信息
for _, data := range storage.IbpRelatedDevices {
for _, c := range data.Combinationtypes {
group := &proto.ElectronicGroup{Code: c.Code}
for _, d := range c.RefDevices {
deviceType, ok := typeMap[d]
if !ok {
slog.Debug("IBP组合类型类型不确定id:%s", d)
continue
}
group.Components = append(group.Components, &proto.ElectronicComponent{
Id: ibpIdMap[d].Uid,
DeviceType: deviceType,
})
}
station.ElectronicGroup = append(station.ElectronicGroup, group)
}
}
}
// 将IBP的灯颜色转换成repo灯颜色
func converIbpLightAspect(color graphicData.IbpLight_IbpLightColor) proto.Light_LightAspect {
switch color {
case graphicData.IbpLight_white:
return proto.Light_B
case graphicData.IbpLight_red:
return proto.Light_H
case graphicData.IbpLight_green:
return proto.Light_L
case graphicData.IbpLight_blue:
return proto.Light_A
default:
panic(&dto.ErrorDto{Code: dto.ArgumentParseError, Message: "未知的灯颜色类型" + color.String()})
}
}
func converCheckPointUid(data *proto.CheckPoint, uidsMap *stationUidStructure) *proto.CheckPoint {

View File

@ -208,4 +208,5 @@ gorm.io/driver/clickhouse v0.5.0/go.mod h1:cIKAlFw+IVK75g0bDcm0M9qRA4EAgsn23Si+z
gorm.io/driver/postgres v1.4.5/go.mod h1:GKNQYSJ14qvWkvPwXljMGehpKrhlDNsqYRr5HnYGncg=
gorm.io/driver/sqlite v1.4.3/go.mod h1:0Aq3iPO+v9ZKbcdiz8gLWRw5VOPcBOPUQJFLq5e2ecI=
gorm.io/driver/sqlserver v1.4.1/go.mod h1:DJ4P+MeZbc5rvY58PnmN1Lnyvb5gw5NPzGshHDnJLig=
honnef.co/go/tools v0.0.1-2020.1.4 h1:UoveltGrhghAA7ePc+e+QYDHXrBps2PqFZiHkGR/xK8=
sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8=

View File

@ -113,16 +113,13 @@ func RunUdpServer() {
}
// 发送列车速度到VOBC
func SendTrainSpeedTask(speed float64) error {
func SendTrainSpeedTask(trainInfo *SendTrainInfo) error {
if running {
return nil
}
mutex.Lock()
defer mutex.Unlock()
trainInfo := &SendTrainInfo{
LifeSignal: sendTrainLifeSignal,
Speed: uint16(speed),
}
trainInfo.LifeSignal = sendTrainLifeSignal
err := sendVobcMsg(encoderVobcTrainInfo(trainInfo))
if err != nil {
slog.Error("发送Vobc信息失败", err)
@ -167,5 +164,18 @@ func encoderVobcTrainInfo(info *SendTrainInfo) []byte {
var data []byte
data = binary.BigEndian.AppendUint16(data, info.LifeSignal)
data = binary.BigEndian.AppendUint16(data, info.Speed)
if info.Upslope {
data = append(data, 1<<7)
} else {
data = append(data, 0)
}
// 中间预留一位
data = append(data, 0)
data = binary.BigEndian.AppendUint16(data, info.Acceleration) // 加速度 100 = 1 m/s*s
data = binary.BigEndian.AppendUint16(data, info.TotalResistance) // 实际运行阻力 100 = 1KN
data = binary.BigEndian.AppendUint16(data, info.AirResistance) // 空气阻力 100 = 1KN
data = binary.BigEndian.AppendUint16(data, info.SlopeResistance) // 坡道阻力 100 = 1KN
data = binary.BigEndian.AppendUint16(data, info.CurveResistance) // 曲线阻力 100 = 1KN
data = binary.BigEndian.AppendUint16(data, info.Slope) // 坡度值 1= 1‰
return data
}

View File

@ -96,4 +96,18 @@ type SendTrainInfo struct {
LifeSignal uint16
// 列车速度 10=1km/h
Speed uint16
// 上坡
Upslope bool
// 坡度值 1= 1‰
Slope uint16
// 加速度 100 = 1 m/s*s
Acceleration uint16
// 实际运行阻力 100 = 1KN
TotalResistance uint16
// 空气阻力 100 = 1KN
AirResistance uint16
// 坡道阻力 100 = 1KN
SlopeResistance uint16
// 曲线阻力 100 = 1KN
CurveResistance uint16
}