列车控制连接版本记录1

This commit is contained in:
tiger_zhou 2024-08-05 16:32:21 +08:00
parent fc6b51cc24
commit 961b9dc5ff
15 changed files with 1578 additions and 1151 deletions

View File

@ -246,8 +246,9 @@ func addTrain(c *gin.Context) {
Id: fmt.Sprintf("%v", req.TrainId), Id: fmt.Sprintf("%v", req.TrainId),
HeadDeviceId: req.Id, HeadDeviceId: req.Id,
HeadOffset: req.HeadOffset, HeadOffset: req.HeadOffset,
DevicePort: req.DevicePort, //HeadOffset: 93211,
TrainRunUp: req.RunDirection, DevicePort: req.DevicePort,
TrainRunUp: req.RunDirection,
//RunDirection: req.RunDirection, //RunDirection: req.RunDirection,
TrainLength: req.TrainLength, TrainLength: req.TrainLength,
WheelDiameter: req.WheelDiameter, WheelDiameter: req.WheelDiameter,

View File

@ -1,7 +1,6 @@
package main package main
import ( import (
"encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
"github.com/spf13/viper" "github.com/spf13/viper"
@ -79,11 +78,6 @@ func initTrainPc() {
//sendBtm() //sendBtm()
} }
const (
e1 = 0x1e
aa = 0x17
)
func createOrRemoveTrain() { func createOrRemoveTrain() {
msgs := make([]*message.TrainPcSimBaseMessage, 0) msgs := make([]*message.TrainPcSimBaseMessage, 0)
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Data: []byte{0x00}, Type: message.RECIVE_TRAIN_CREATE_REMOVE}) //msgs = append(msgs, &message.TrainPcSimBaseMessage{Data: []byte{0x00}, Type: message.RECIVE_TRAIN_CREATE_REMOVE})
@ -146,45 +140,10 @@ func circleSendTrainMockData() {
time.Sleep(time.Millisecond * 1000) time.Sleep(time.Millisecond * 1000)
} }
} }
func sendBtm() {
source := "eb3305d543eb3211000005ea000000010000082b7989eb321100003573000000010000257ce38eeb3211000005d90000000100002731a483eb3211000005c8000000010000322d6b8aeb32110000356200000001000033976df1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1"
data, _ := hex.DecodeString(source)
trainpcClient.Send(data)
}
func circleSendTrainSpeedPlace() {
for {
data := make([]byte, 0)
data = binary.BigEndian.AppendUint16(data, uint16(2))
//data = binary.BigEndian.AppendUint16(data, uint16(1))
//data = binary.BigEndian.AppendUint16(data, uint16(0))
//data = binary.BigEndian.AppendUint16(data, uint16(0))
//data = binary.BigEndian.AppendUint32(data, uint32(940))
//data = binary.BigEndian.AppendUint32(data, uint32(940))
data = binary.BigEndian.AppendUint32(data, uint32(0))
data = binary.BigEndian.AppendUint32(data, uint32(0))
data = binary.BigEndian.AppendUint32(data, uint32(940))
data = binary.BigEndian.AppendUint32(data, uint32(940))
now := time.Now().UTC()
sec := now.Unix()
data = binary.BigEndian.AppendUint32(data, uint32(27797))
data = binary.BigEndian.AppendUint16(data, uint16(now.UnixMilli()-sec*1000))
ss := "eb011d000200000000000000000000000000000000000017af0299ffff"
data, _ = hex.DecodeString(ss)
//bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
//dataCode := bm.Encode()
//fmt.Println(fmt.Sprintf("发送列车位置信息:%v", hex.EncodeToString(data)))
trainpcClient.Send(data)
//dd := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{3, 0}}
//trainpcClient.Send(dd.Encode())
time.Sleep(time.Millisecond * 80)
}
}
func trainPcDataHandle(n int, data []byte) { func trainPcDataHandle(n int, data []byte) {
hexData := hex.EncodeToString(data[:n]) hexData := hex.EncodeToString(data[:n])
slog.Info(fmt.Sprintf("列车pc仿真接口长度:%v,实际长度:%v,接受数据:%v", len(data), n, hexData)) slog.Info(fmt.Sprintf("列车pc仿真接口长度:%v,实际长度:%v,接受数据:%v", len(data), n, hexData))
//source := "eb3211000005ea000000010000082b7989eb321100003573000000010000257ce38eeb3211000005d90000000100002731a483eb3211000005c8000000010000322d6b8aeb32110000356200000001000033976df1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1"
//data2, _ := hex.DecodeString(source)
//trainpcClient.Send(data2)
} }
func trainPcConnErr(err error) { func trainPcConnErr(err error) {

View File

@ -6,8 +6,8 @@ server:
# 数据源 # 数据源
datasource: datasource:
# 数据库访问url # 数据库访问url
# dsn: root:root@tcp(127.0.0.1:3306)/bj-rtss?charset=utf8mb4&parseTime=true&loc=UTC dsn: root:root@tcp(127.0.0.1:3306)/bj-rtss?charset=utf8mb4&parseTime=true&loc=UTC
dsn: root:joylink0503@tcp(192.168.33.233:3306)/bj-rtss?charset=utf8mb4&parseTime=true&loc=UTC # dsn: root:joylink0503@tcp(192.168.33.233:3306)/bj-rtss?charset=utf8mb4&parseTime=true&loc=UTC
# 日志配置 # 日志配置
logging: logging:
@ -33,7 +33,7 @@ logging:
# 消息配置 # 消息配置
messaging: messaging:
mqtt: mqtt:
# address: tcp://127.0.0.1:1883 address: tcp://127.0.0.1:1883
address: tcp://192.168.33.233:1883 # address: tcp://192.168.33.233:1883
username: rtsts_service username: rtsts_service
password: joylink@0503 password: joylink@0503

View File

@ -3222,8 +3222,8 @@ type Transponder struct {
FixedTelegram string `protobuf:"bytes,11,opt,name=fixedTelegram,proto3" json:"fixedTelegram,omitempty"` //应答器固定报文 FixedTelegram string `protobuf:"bytes,11,opt,name=fixedTelegram,proto3" json:"fixedTelegram,omitempty"` //应答器固定报文
FixedUserTelegram string `protobuf:"bytes,12,opt,name=fixedUserTelegram,proto3" json:"fixedUserTelegram,omitempty"` //应答器固定用户报文 FixedUserTelegram string `protobuf:"bytes,12,opt,name=fixedUserTelegram,proto3" json:"fixedUserTelegram,omitempty"` //应答器固定用户报文
OriginalCode string `protobuf:"bytes,13,opt,name=originalCode,proto3" json:"originalCode,omitempty"` //应答器原编号(厂商提供数据编号) OriginalCode string `protobuf:"bytes,13,opt,name=originalCode,proto3" json:"originalCode,omitempty"` //应答器原编号(厂商提供数据编号)
LeuIndex uint32 `protobuf:"varint,14,opt,name=leuIndex,proto3" json:"leuIndex,omitempty"` //LEU索引 LeuIndex uint32 `protobuf:"varint,14,opt,name=leuIndex,proto3" json:"leuIndex,omitempty"` //应答器所属LEU索引
LeuInsideIndex uint32 `protobuf:"varint,15,opt,name=leuInsideIndex,proto3" json:"leuInsideIndex,omitempty"` // LEU内部索引 LeuInsideIndex uint32 `protobuf:"varint,15,opt,name=leuInsideIndex,proto3" json:"leuInsideIndex,omitempty"` // 应答器在LEU内部索引
} }
func (x *Transponder) Reset() { func (x *Transponder) Reset() {

File diff suppressed because it is too large Load Diff

@ -1 +1 @@
Subproject commit 3182e867c12d73bd4c75182459d3b9fae670653c Subproject commit 5f95106870ba0cc1e75766698c3dbee74c45b39f

@ -1 +1 @@
Subproject commit 0c2a7613104f859e83091d1f6379e6e2fa1990ad Subproject commit fd4d5ee6384611ac8f9002c558e954bb65acdaed

View File

@ -55,33 +55,62 @@ type btmCanetClient struct {
baliseDetector *BaliseDetector baliseDetector *BaliseDetector
} }
func (s *btmCanetClient) GetState() state_proto.BTMState { func (s *btmCanetClient) FindNotSendState() (state_proto.BTMState, bool) {
s.baliseDetector.eqLock.Lock()
defer s.baliseDetector.eqLock.Unlock()
detector := s.baliseDetector detector := s.baliseDetector
for _, info := range detector.eq {
if info != nil && !info.IsSend {
info.IsSend = true
return s.getStateFromDeta(info, uint32(detector.baliseCounter), uint32(detector.messageCounter), detector.aboveBalise), true
}
}
return state_proto.BTMState{}, false
}
/*
func (s *btmCanetClient) GetAllData() {
detector := s.baliseDetector
for _, info := range detector.eq {
slog.Info("获取应答器信息 id:%v,是否发送:%v", info.BaliseId)
}
}
*/
func (s *btmCanetClient) getStateFromDeta(info *BtmAntennaScanningBaliseInfo, bc, mc uint32, aboveBalise bool) state_proto.BTMState {
var telegram string var telegram string
var tel128 string var tel128 string
info := detector.eq[len(detector.eq)-1] var dis int64
var baliseId string
if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 { if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 {
telegram = fmt.Sprintf("%X", info.telegram) telegram = fmt.Sprintf("%X", info.telegram)
tel128 = fmt.Sprintf("%X", info.telegram128) tel128 = fmt.Sprintf("%X", info.telegram128)
dis = info.Distance
baliseId = info.BaliseId
} else { } else {
telegram = strings.Repeat("00", balise_const.UserTelegramByteLen) telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
tel128 = strings.Repeat("00", balise_const.TelegramByteLen) tel128 = strings.Repeat("00", balise_const.TelegramByteLen)
} }
var dis int64
if info != nil {
dis = info.Distance
}
return state_proto.BTMState{ return state_proto.BTMState{
BaliseId: baliseId,
DataSerialNumber: uint32(s.dsn), DataSerialNumber: uint32(s.dsn),
BaliseCount: uint32(detector.baliseCounter), BaliseCount: bc,
MessageCounter: uint32(detector.messageCounter), MessageCounter: mc,
Telegram: telegram, Telegram: telegram,
Telegram128: tel128, Telegram128: tel128,
Distance: dis, Distance: dis,
AboveBalise: detector.aboveBalise, AboveBalise: aboveBalise,
} }
} }
func (s *btmCanetClient) GetState() state_proto.BTMState {
detector := s.baliseDetector
info := detector.eq[len(detector.eq)-1]
return s.getStateFromDeta(info, uint32(detector.baliseCounter), uint32(detector.messageCounter), detector.aboveBalise)
}
type BtmClock struct { type BtmClock struct {
BtmTk uint32 //与ATP系统同步的时间ms BtmTk uint32 //与ATP系统同步的时间ms
@ -100,6 +129,8 @@ type BtmCanetClient interface {
HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state_proto.VobcBtmState, h *TrainHeadPositionInfo) HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state_proto.VobcBtmState, h *TrainHeadPositionInfo)
//获取BTM显示状态 + btm最新的状态 //获取BTM显示状态 + btm最新的状态
GetState() state_proto.BTMState GetState() state_proto.BTMState
//GetAllData()
FindNotSendState() (state_proto.BTMState, bool)
} }
var ( var (
@ -121,7 +152,16 @@ func (s *btmCanetClient) HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state
//slog.Debug(h.String()) //slog.Debug(h.String())
wd := entity.GetWorldData(w) wd := entity.GetWorldData(w)
repo := wd.Repo repo := wd.Repo
s.baliseDetector.detect(wd, repo, h, vobcBtm)
//s.baliseDetector.detect(wd, repo, h, vobcBtm)
h2 := &TrainHeadPositionInfo{
TrainId: h.TrainId,
Up: h.Up,
Link: h.OldLink,
LinkOffset: h.OldLinkOffset,
Speed: h.Speed,
Acceleration: h.Acceleration}
s.baliseDetector.detect2(wd, repo, h, h2, vobcBtm)
} }
func (s *btmCanetClient) Start(bcm BtmCanetManager) { func (s *btmCanetClient) Start(bcm BtmCanetManager) {
s.bcm = bcm s.bcm = bcm
@ -154,6 +194,9 @@ func (s *btmCanetClient) Stop() {
s.udpClient.Close() s.udpClient.Close()
s.udpClient = nil s.udpClient = nil
} }
for d := range s.baliseDetector.eq {
s.baliseDetector.eq[d] = nil
}
} }
func (s *btmCanetClient) handleCanetFrames(cfs []byte) { func (s *btmCanetClient) handleCanetFrames(cfs []byte) {
defer func() { defer func() {

View File

@ -2,12 +2,14 @@ package can_btm
import ( import (
"fmt" "fmt"
uuid2 "github.com/google/uuid"
"joylink.club/bj-rtsts-server/dto/state_proto" "joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/bj-rtsts-server/third_party/btm_vobc" "joylink.club/bj-rtsts-server/third_party/btm_vobc"
"joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/fi" "joylink.club/rtsssimulation/fi"
"joylink.club/rtsssimulation/repository" "joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto" "joylink.club/rtsssimulation/repository/model/proto"
"log/slog"
"math" "math"
"sort" "sort"
"sync" "sync"
@ -28,6 +30,7 @@ type BtmAntennaRunningInfo struct {
} }
const ( const (
//BtmAntennaOffsetHead = int64(1000) //车载BTM天线距车头端点的距离mm
BtmAntennaOffsetHead = int64(1000) //车载BTM天线距车头端点的距离mm BtmAntennaOffsetHead = int64(1000) //车载BTM天线距车头端点的距离mm
) )
@ -46,6 +49,7 @@ type BtmAntennaScanningBaliseInfo struct {
telegram128 []byte //应答器报文 telegram128 []byte //应答器报文
Distance int64 //BTM天线中心到应答器的距离mm Distance int64 //BTM天线中心到应答器的距离mm
BaliseType proto.Transponder_Type //应答器类型 BaliseType proto.Transponder_Type //应答器类型
IsSend bool
} }
// BaliseDetector 车载BTM天线应答器探测器 // BaliseDetector 车载BTM天线应答器探测器
@ -76,6 +80,85 @@ func (t *BaliseDetector) tryRebind(th *TrainHeadPositionInfo) {
} }
} }
func (t *BaliseDetector) detect2(wd *component.WorldData, repo *repository.Repository, th, th2 *TrainHeadPositionInfo, vobcBtm *state_proto.VobcBtmState) {
t.tryRebind(th)
//BTM天线中心点运行信息
curAntennaRi := t.createBtmAntennaRunningInfo(wd, repo, th) //目前车头
curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, th2) //上次车头
var startBalises []*repository.Transponder
var endBalises []*repository.Transponder
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi2.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
//endBalises = t.searchBalisesFromBetweenLinkPosition(repo, !th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset)
/* if th.Up {
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi2.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
endBalises = t.searchBalisesFromBetweenLinkPosition(repo, !th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset)
} else {
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi2.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset)
endBalises = t.searchBalisesFromBetweenLinkPosition(repo, !th.Up, curAntennaRi.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
}*/
balises := make([]*repository.Transponder, 0)
for _, balise := range startBalises {
find := false
for _, transponder := range balises {
if transponder.Id() == balise.Id() {
find = true
break
}
}
if !find {
balises = append(balises, balise)
//slog.Info(fmt.Sprintf("start baliseId:%v,Distance:%v,up:%v", balise.Id(), balise.LinkPosition(), curAntennaRi.Up))
}
}
for _, balise := range endBalises {
find := false
for _, transponder := range balises {
if transponder.Id() == balise.Id() {
find = true
break
}
}
if !find {
//slog.Info(fmt.Sprintf("end baliseId:%v,Distance:%v,up:%v", balise.Id(), balise.LinkPosition(), curAntennaRi.Up))
balises = append(balises, balise)
}
}
if len(balises) > 0 {
balise := balises[0]
baliseInfo := &BtmAntennaScanningBaliseInfo{BaliseId: balise.Id(), BaliseType: balise.BaliseType()}
uuid := uuid2.NewString()
for _, transponder := range balises {
slog.Info(fmt.Sprintf("uid :%v,baliseId:%v,Distance:%v,up:%v", uuid, transponder.Id(), baliseInfo.Distance, curAntennaRi.Up))
}
telegram, utel := t.rcvTelegram(wd, balise.Id())
if t.addExpectedBalise(baliseInfo) {
t.baliseCounterAdd1() //应答器计数器
if len(telegram) > 0 {
baliseInfo.telegram = utel
baliseInfo.telegram128 = telegram
t.baliseMessageCounterAdd1() //报文计数器
}
}
t.aboveBalise = true
} else {
t.aboveBalise = false
}
/* curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, &TrainHeadPositionInfo{TrainId: th.TrainId,
Up: !th.Up,
Link: th.Link,
LinkOffset: th.LinkOffset,
Speed: th.Speed,
Acceleration: th.Acceleration})
curExpect2 := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi2)
if curExpect2 != nil && curExpect2.Distance > 20 {
btm_vobc.Default().UpdateTrainLeave(vobcBtm, curExpect2.BaliseId, curTime.UnixMilli())
}*/
}
func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Repository, th *TrainHeadPositionInfo, vobcBtm *state_proto.VobcBtmState) { func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Repository, th *TrainHeadPositionInfo, vobcBtm *state_proto.VobcBtmState) {
t.tryRebind(th) t.tryRebind(th)
//if !t.powerAmplifierSwitch { //天线功率放大器未开启,不进行探测 //if !t.powerAmplifierSwitch { //天线功率放大器未开启,不进行探测
@ -88,7 +171,9 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
curExpect := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi) curExpect := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi)
if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms
//if curExpect != nil && curExpect.Distance < 80 { //20ms
//slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt) //slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt)
//slog.Info(fmt.Sprintf("baliseId:%v,Distance:%v,up:%v", curExpect.BaliseId, curExpect.Distance, curAntennaRi.Up))
telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId) telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId)
if curExpect.Distance <= 50 { if curExpect.Distance <= 50 {
@ -101,7 +186,6 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
curExpect.telegram = utel curExpect.telegram = utel
curExpect.telegram128 = telegram curExpect.telegram128 = telegram
t.baliseMessageCounterAdd1() //报文计数器 t.baliseMessageCounterAdd1() //报文计数器
} }
} }
//BTM天线即将经过应答器 //BTM天线即将经过应答器
@ -165,10 +249,17 @@ func (t *BaliseDetector) addExpectedBalise(curExpect *BtmAntennaScanningBaliseIn
// } // }
//} //}
//检查是否已经记录过 //检查是否已经记录过
eq := t.eq[len(t.eq)-1]
if eq != nil && eq.BaliseId == curExpect.BaliseId { for _, tt := range t.eq {
return false if tt != nil && tt.BaliseId == curExpect.BaliseId {
return false
}
} }
/* eq := t.eq[len(t.eq)-1]
if eq != nil && eq.BaliseId == curExpect.BaliseId {
return false
}*/
//左移 //左移
for i := 1; i < len(t.eq); i++ { for i := 1; i < len(t.eq); i++ {
t.eq[i-1] = t.eq[i] t.eq[i-1] = t.eq[i]
@ -210,7 +301,9 @@ func (t *BaliseDetector) timeScanNearestBalise(curTime time.Time, wd *component.
curAc := float64(ba.Acceleration) curAc := float64(ba.Acceleration)
s := float64(expectedBalise.Distance) / 1000 s := float64(expectedBalise.Distance) / 1000
st, ok := t.calculateBtmAntennaScanNextBaliseTime(curTime, curV, curAc, s) st, ok := t.calculateBtmAntennaScanNextBaliseTime(curTime, curV, curAc, s)
if ok { if ok {
return &BtmAntennaScanningBaliseInfo{BaliseId: expectedBalise.BaliseId, Time: st, Distance: expectedBalise.Distance, BaliseType: expectedBalise.BaliseType} return &BtmAntennaScanningBaliseInfo{BaliseId: expectedBalise.BaliseId, Time: st, Distance: expectedBalise.Distance, BaliseType: expectedBalise.BaliseType}
} }
} }
@ -284,6 +377,43 @@ func (t *BaliseDetector) findBaliseWillScanByBtmAntenna(wd *component.WorldData,
return nil return nil
} }
func (t *BaliseDetector) searchBalisesFromBetweenLinkPosition(repo *repository.Repository, up bool, linkId string, fromOffset int64, toOffset int64) []*repository.Transponder {
rs := repo.ResponderListByLink(linkId)
balises := make([]*repository.Transponder, 0)
if up {
sort.SliceStable(rs, func(i, j int) bool {
return rs[i].LinkPosition().Offset() < rs[j].LinkPosition().Offset()
})
for _, r := range rs {
if r.LinkPosition().Offset() >= fromOffset && r.LinkPosition().Offset() <= toOffset {
//slog.Info(fmt.Sprintf("up id:%v,offset:%v,from:%v,to:%v", r.Id(), r.LinkPosition().Offset(), fromOffset, toOffset))
balises = append(balises, r)
}
}
} else {
sort.SliceStable(rs, func(i, j int) bool {
return rs[j].LinkPosition().Offset() < rs[i].LinkPosition().Offset()
})
//cha := int64(math.Abs(float64(toOffset - fromOffset)))
for _, r := range rs {
/*if r.LinkPosition().Offset() <= fromOffset && r.LinkPosition().Offset() >= toOffset {
balises = append(balises, r)
}*/
if r.LinkPosition().Offset() <= toOffset {
cha := int64(math.Abs(float64(toOffset - fromOffset)))
cha2 := int64(math.Abs(float64(toOffset - r.LinkPosition().Offset())))
if cha2 <= cha {
balises = append(balises, r)
}
}
}
}
return balises
}
// up-在轨道上的搜索方向 // up-在轨道上的搜索方向
func (t *BaliseDetector) searchBalisesFromLinkPosition(repo *repository.Repository, linkId string, up bool, fromOffset int64) []*repository.Transponder { func (t *BaliseDetector) searchBalisesFromLinkPosition(repo *repository.Repository, linkId string, up bool, fromOffset int64) []*repository.Transponder {
rs := repo.ResponderListByLink(linkId) rs := repo.ResponderListByLink(linkId)
@ -302,6 +432,7 @@ func (t *BaliseDetector) searchBalisesFromLinkPosition(repo *repository.Reposito
return rs[j].LinkPosition().Offset() < rs[i].LinkPosition().Offset() return rs[j].LinkPosition().Offset() < rs[i].LinkPosition().Offset()
}) })
for i, r := range rs { for i, r := range rs {
//slog.Info(fmt.Sprintf("id:%v,offset:%v,from:%v", r.Id(), r.LinkPosition().Offset(), fromOffset))
if r.LinkPosition().Offset() <= fromOffset { if r.LinkPosition().Offset() <= fromOffset {
return rs[i:] return rs[i:]
} }

View File

@ -318,7 +318,7 @@ func (d *dynamics) Stop() {
const ( const (
// 道岔消息发送间隔,单位ms // 道岔消息发送间隔,单位ms
TurnoutMessageSendInterval = 50 TurnoutMessageSendInterval = 50
TrainControlMessageSendInterval = 15 TrainControlMessageSendInterval = 10
) )
var turnoutStateLifeSignal uint16 //道岔消息生命信号 var turnoutStateLifeSignal uint16 //道岔消息生命信号

View File

@ -4,6 +4,7 @@ import (
"bytes" "bytes"
"encoding/binary" "encoding/binary"
"fmt" "fmt"
"math"
"strconv" "strconv"
"time" "time"
) )
@ -121,21 +122,60 @@ func AtpLowPowerByte(d byte) bool {
// 列车速度位置报告 // 列车速度位置报告
type TrainSpeedPlaceReportMsg struct { type TrainSpeedPlaceReportMsg struct {
PulseCount1 uint32 PulseCount1 float32
PulseCount2 uint32 PulseCount2 float32
Pp1 float32
Pp2 float32
HistoryCount float32
Tmp bool
PcCount float32
} }
func (tp *TrainSpeedPlaceReportMsg) ParsePulseCount1(s1, s2 uint32) { func (tp *TrainSpeedPlaceReportMsg) ParsePulseCount1(s1, s2 uint32) {
tp.PulseCount1 += s1 //tp.PulseCount1 += tp.HistoryCount
tp.PulseCount2 += s2 //tp.PulseCount2 += tp.HistoryCount
tp.PulseCount1 += float32(s1) * 200 / math.Pi / 840
tp.PulseCount2 += float32(s2) * 200 / math.Pi / 840
//tp.HistoryCount += s1
} }
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir bool, s1, s2 uint32) []byte { func (tp *TrainSpeedPlaceReportMsg) ParsePulseCut(s1, s2 float32) {
/* if s1 == 0 || s2 == 0 {
tp.PulseCount1 = tp.HistoryCount
tp.PulseCount2 = tp.HistoryCount
return
}*/
tp.HistoryCount += s1
d1 := tp.PulseCount1 - s1
if d1 <= 0 {
d1 = 0
}
d2 := tp.PulseCount1 - s2
if d2 <= 0 {
d2 = 0
}
tp.PulseCount1 = d1
tp.PulseCount2 = d2
}
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir uint16, s1, s2 uint32) []byte {
data := make([]byte, 0) data := make([]byte, 0)
data = binary.BigEndian.AppendUint16(data, uint16(IsTrue(runDir)))
data = binary.BigEndian.AppendUint16(data, runDir)
data = binary.BigEndian.AppendUint32(data, s1) data = binary.BigEndian.AppendUint32(data, s1)
data = binary.BigEndian.AppendUint32(data, s2) data = binary.BigEndian.AppendUint32(data, s2)
data = binary.BigEndian.AppendUint32(data, tp.PulseCount1) //data = binary.BigEndian.AppendUint32(data, math.Float32bits(s1))
data = binary.BigEndian.AppendUint32(data, tp.PulseCount2) //data = binary.BigEndian.AppendUint32(data, math.Float32bits(s2))
tp.PcCount = tp.PulseCount1 * 200 / math.Pi / float32(840)
//data = binary.BigEndian.AppendUint32(data, tp.PcCount)
//data = binary.BigEndian.AppendUint32(data, tp.PcCount)
data = binary.BigEndian.AppendUint32(data, math.Float32bits(tp.PcCount))
data = binary.BigEndian.AppendUint32(data, math.Float32bits(tp.PcCount))
//data = binary.BigEndian.AppendUint32(data, uint32(float32(tp.PulseCount1)*200/math.Pi/840))
//data = binary.BigEndian.AppendUint32(data, uint32(float32(tp.PulseCount2)*200/math.Pi/840))
now := time.Now().UTC() now := time.Now().UTC()
// 将时间转换为毫秒 // 将时间转换为毫秒
millis := now.UnixNano() / int64(time.Millisecond) millis := now.UnixNano() / int64(time.Millisecond)

View File

@ -37,7 +37,7 @@ type TrainPcSim interface {
SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool) SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool)
//发送应答器信息数据 //发送应答器信息数据
SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte) SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte)
SendBaliseData2(train *state_proto.TrainState, msgType byte, data []string)
//发布列车控制的相关事件 //发布列车控制的相关事件
//PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent) //PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent)
@ -51,6 +51,7 @@ type TrainPcSim interface {
ResetPluseCount(sta *state_proto.TrainState) ResetPluseCount(sta *state_proto.TrainState)
//FindAllThirdPartState() []tpapi.ThirdPartyApiService //FindAllThirdPartState() []tpapi.ThirdPartyApiService
DsnAddAndReturn() byte DsnAddAndReturn() byte
ResetPlusePlace(sta *state_proto.TrainState)
} }
type TrainPcSimManage interface { type TrainPcSimManage interface {
@ -137,44 +138,97 @@ func (d *trainPcSimService) findAllThirdPartState() []tpapi.ThirdPartyApiService
return services return services
} }
// 速度(单位mm/s)对应的脉冲数:速度*200/pi/840
// 里程单位mm对应的脉冲总里程*200/pi/840
func pluseCountSpeed(wheelDiameter int32, speedMeter float32) uint32 { func pluseCountSpeed(wheelDiameter int32, speedMeter float32) uint32 {
s1 := speedMeter * 1000 s1 := speedMeter * 1000
pluseCountData := s1 * 200 / math.Pi / float32(wheelDiameter) pluseCountData := s1 * 200 / math.Pi / float32(wheelDiameter)
return uint32(pluseCountData) return uint32(pluseCountData)
} }
func (d *trainPcSimService) ResetPlusePlace(sta *state_proto.TrainState) {
defer initLock.Unlock()
initLock.Lock()
if sd, err := d.findTrainConn(sta); err == nil {
/*if !sd.speedPlace.Tmp {
} else {
sd.speedPlace.Tmp = false
}*/
if sd.speedPlace.Tmp {
//sd.speedPlace.PulseCount1 = sd.speedPlace.HistoryCount
//sd.speedPlace.PulseCount2 = sd.speedPlace.HistoryCount
//sd.speedPlace.Tmp = false
}
//sd.speedPlace.HistoryCount = 0
//slog.Info(fmt.Sprintf(" p1:%v,p2:%v,h:%v", sd.speedPlace.PulseCount1, sd.speedPlace.PulseCount2, sd.speedPlace.HistoryCount))
//sd.speedPlace.Tmp = true
}
}
func (d *trainPcSimService) ResetPluseCount(sta *state_proto.TrainState) { func (d *trainPcSimService) ResetPluseCount(sta *state_proto.TrainState) {
defer initLock.Unlock()
initLock.Lock()
if sd, err := d.findTrainConn(sta); err == nil { if sd, err := d.findTrainConn(sta); err == nil {
sd.speedPlace.PulseCount1 = 0 sd.speedPlace.PulseCount1 = 0
sd.speedPlace.PulseCount2 = 0 sd.speedPlace.PulseCount2 = 0
} }
}
func (d *trainPcSimService) pluseSpeed(sta *state_proto.TrainState) (uint32, float32) {
defer initLock.Unlock()
initLock.Lock()
var sum float32 = 0
pcLen := len(sta.PluseCount.PulseCount3)
if pcLen == 0 {
return 0, 0
}
for _, f := range sta.PluseCount.PulseCount3 {
sum += f
}
d.TrainPluseCountReset(sta)
speed := sum / float32(pcLen)
return pluseCountSpeed(sta.WheelDiameter, speed), speed
} }
func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) { func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
defer initLock.Unlock() defer initLock.Unlock()
initLock.Lock() initLock.Lock()
if sd, err := d.findTrainConn(sta); err == nil {
sd.speedPlace.PulseCount1 += float32(sta.DynamicState.Displacement)
sd.speedPlace.PulseCount2 = sd.speedPlace.PulseCount1
}
if sta.TrainRunUp { if sta.TrainRunUp {
if sta.TrainEndsA.SpeedSensorEnableA { if sta.TrainEndsA.SpeedSensorEnableA {
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, h1) sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, h1)
sta.PluseCount.PulseCount3 = append(sta.PluseCount.PulseCount3, h1)
} }
if sta.TrainEndsA.SpeedSensorEnableB { if sta.TrainEndsA.SpeedSensorEnableB {
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, h2) sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, h2)
sta.PluseCount.PulseCount4 = append(sta.PluseCount.PulseCount3, h2)
} }
} else { } else {
if sta.TrainEndsB.SpeedSensorEnableA { if sta.TrainEndsB.SpeedSensorEnableA {
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, t1) sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, t1)
sta.PluseCount.PulseCount3 = append(sta.PluseCount.PulseCount3, t1)
} }
if sta.TrainEndsB.SpeedSensorEnableB { if sta.TrainEndsB.SpeedSensorEnableB {
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, t2) sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, t2)
sta.PluseCount.PulseCount4 = append(sta.PluseCount.PulseCount3, t2)
} }
} }
} }
func (d *trainPcSimService) TrainPluseCountReset(sta *state_proto.TrainState) { func (d *trainPcSimService) TrainPluseCountReset(sta *state_proto.TrainState) {
defer initLock.Unlock()
initLock.Lock()
sta.PluseCount.PulseCount1 = 0 sta.PluseCount.PulseCount1 = 0
sta.PluseCount.PulseCount2 = 0 sta.PluseCount.PulseCount2 = 0
sta.PluseCount.PulseCount3 = make([]float32, 0)
sta.PluseCount.PulseCount4 = make([]float32, 0)
} }
func (d *trainPcSimService) newCloseAllConn() { func (d *trainPcSimService) newCloseAllConn() {
@ -261,7 +315,6 @@ func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
ctx, ctxFun := context.WithCancel(context.Background()) ctx, ctxFun := context.WithCancel(context.Background())
d.cancleContext = ctxFun d.cancleContext = ctxFun
d.trainPcSimManage = pcSimManage d.trainPcSimManage = pcSimManage
//d.connTrainPcSim(ctx)
go d.sendTrainLocationAndSpeedTask(ctx) go d.sendTrainLocationAndSpeedTask(ctx)
} }
@ -358,20 +411,37 @@ func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
connState = tpapi.ThirdPartyState_Broken connState = tpapi.ThirdPartyState_Broken
} }
trainClient.updateState(connState) trainClient.updateState(connState)
s1, s2 := train.PluseCount.PulseCount1, train.PluseCount.PulseCount2 //s1, s2 := train.PluseCount.PulseCount1, train.PluseCount.PulseCount2
trainClient.speedPlace.ParsePulseCount1(s1, s2) s1, speed := d.pluseSpeed(train)
data := trainClient.speedPlace.Encode(train.TrainRunUp, s1, s2) s2 := s1
/*jjzdBtn := train.Tcc.Buttons["JJZD"]
if jjzdBtn.Passed {
s1 = 0
s2 = 0
}*/
//trainClient.speedPlace.ParsePulseCount1(s1, s2)
//slog.Info(fmt.Sprintf("发送列车up:%v ,s1:%v,s2:%v,c1:%v,c2:%v, h位置消息:%v,eb:%v,tmp:%v", train.TrainRunUp, s1, s2, trainClient.speedPlace.PulseCount2, trainClient.speedPlace.PulseCount1, trainClient.speedPlace.HistoryCount, train.VobcState.EmergencyBrakingStatus, trainClient.speedPlace.Tmp))
//trainClient.speedPlace.PulseCount1 = uint32(train.DynamicState.Displacement)
//trainClient.speedPlace.PulseCount2 = trainClient.speedPlace.PulseCount1
runDir := uint16(2)
if train.Tcc.DirKey.Val == 1 {
runDir = 1
}
data := trainClient.speedPlace.Encode(runDir, s1, s2)
bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data} bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
d.TrainPluseCountReset(train)
dataCode := bm.Encode() dataCode := bm.Encode()
//slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,s1: %v,s2: %v,c2: %v,c2: %v,发送数据:%v", train.Id, s1, s2, trainClient.speedPlace.PulseCount1, trainClient.speedPlace.PulseCount2, hex.EncodeToString(dataCode))) slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,列车速度:%v,计数脉冲: %v,累计里程: %v ,累计脉冲:%v,发送数据:%v", train.Id, speed, s1, trainClient.speedPlace.PulseCount1, trainClient.speedPlace.PcCount, hex.EncodeToString(dataCode)))
err := trainClient.tcpClient.Send(dataCode) err := trainClient.tcpClient.Send(dataCode)
if err != nil { if err != nil {
slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode))) slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode)))
} }
} }
} }
time.Sleep(time.Millisecond * 80) time.Sleep(time.Millisecond * 80)
} }
} }
@ -489,25 +559,6 @@ func (d *trainPcSimService) SendTrainDirection(train *state_proto.TrainState, tr
} }
} }
func (d *trainPcSimService) SendBaliseData2(train *state_proto.TrainState, msgType byte, data []string) {
trainClient, trainDataErr := d.findTrainConn(train)
if trainDataErr != nil {
slog.Error(fmt.Sprintf("发送列车PC仿真应答器信息失败2未找到列车连接trainId%v", train.Id))
return
}
for _, hexData := range data {
dd, _ := hex.DecodeString(hexData)
msg := &message.TrainPcSimBaseMessage{Type: msgType, Data: dd}
da := msg.Encode()
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%X,数据:%v", msgType, hex.EncodeToString(da)))
err := trainClient.tcpClient.Send(da)
if err != nil {
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da)))
}
}
}
func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte) { func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte) {
trainClient, trainDataErr := d.findTrainConn(train) trainClient, trainDataErr := d.findTrainConn(train)
if trainDataErr != nil { if trainDataErr != nil {
@ -519,7 +570,7 @@ func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgTyp
msg.Data = data msg.Data = data
da := msg.Encode() da := msg.Encode()
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%x源数据长度:%v,数据:%v", msgType, len(data), hex.EncodeToString(da))) //slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%x源数据长度:%v,数据:%v", msgType, len(data), hex.EncodeToString(da)))
err := trainClient.tcpClient.Send(da) err := trainClient.tcpClient.Send(da)
if err != nil { if err != nil {
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da))) slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da)))

View File

@ -24,6 +24,9 @@ import (
const ( const (
DEFULAT_TRAIN_LOAD = 160 DEFULAT_TRAIN_LOAD = 160
DEFAULT_BRAKE_FORCE = 19040 DEFAULT_BRAKE_FORCE = 19040
DEFAULT_EB = 13040
//DEFAULT_EB = 25000
//DEFAULT_EB = 19200
) )
func CreateMsgTrainConfig(trainId int, trainLen int64, configTrainData dto.ConfigTrainData) *message.TrainOperationConfig { func CreateMsgTrainConfig(trainId int, trainLen int64, configTrainData dto.ConfigTrainData) *message.TrainOperationConfig {
@ -51,7 +54,7 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
} }
//向动力学发送初始化请求 //向动力学发送初始化请求
trainIndex, _ := strconv.ParseUint(status.Id, 10, 16) trainIndex, _ := strconv.ParseUint(status.Id, 10, 16)
slog.Debug("添加列车", "trainIndex", trainIndex, "HeadDeviceId", status.HeadDeviceId, "HeadOffset", status.HeadOffset) //slog.Debug("添加列车", "trainIndex", trainIndex, "HeadDeviceId", status.HeadDeviceId, "HeadOffset", status.HeadOffset)
// 映射link、偏移量、运行方向 // 映射link、偏移量、运行方向
var uid string var uid string
if status.DevicePort == "" { if status.DevicePort == "" {
@ -326,12 +329,23 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2)) panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2))
} }
//slog.Debug("车尾位置", tailDeviceId, "偏移", tailDeviceOffset, "所在设备端", tailDevicePort) //slog.Debug("车尾位置", tailDeviceId, "偏移", tailDeviceOffset, "所在设备端", tailDevicePort)
updateTrainBtmPosition(vs, info, sta, outLinkId, outLinkOffset)
// 修改world中的列车位置 // 修改world中的列车位置
handleTrainPositionFromDynamic(vs, info, sta, outLinkId, outLinkOffset, tailLinkId, tailLinkOffset) handleTrainPositionFromDynamic(vs, info, sta, outLinkId, outLinkOffset, tailLinkId, tailLinkOffset)
//修改列车激活方向 //修改列车激活方向
updateTrainActiveDirFromDynamic(vs, info, sta, id, port, trainHeadActUp) updateTrainActiveDirFromDynamic(vs, info, sta, id, port, trainHeadActUp)
if sta.OldLinkOffset == 0 {
sta.OldLinkOffset = outLinkOffset
sta.OldLink = outLinkId
}
//slog.Info(fmt.Sprintf("old:%v ,new :%v,--:%v", outLinkOffset, sta.OldLinkOffset, pointTo))
updateTrainBtmPosition(vs, info, sta, outLinkId, outLinkOffset)
//slog.Info(fmt.Sprintf("动力学,当前速度(米/秒):%v,加速度:%v", info.Speed, info.Acceleration))
if sta.OldLink != outLinkId {
sta.OldLink = outLinkId
}
if sta.OldLinkOffset != outLinkOffset {
sta.OldLinkOffset = outLinkOffset
}
sta.HeadDeviceId = vs.GetComIdByUid(id) sta.HeadDeviceId = vs.GetComIdByUid(id)
sta.DevicePort = port sta.DevicePort = port
sta.HeadOffset = offset sta.HeadOffset = offset
@ -365,6 +379,7 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
sta.DynamicState.Acceleration = info.Acceleration sta.DynamicState.Acceleration = info.Acceleration
sta.DynamicState.Displacement = int32(info.Displacement) sta.DynamicState.Displacement = int32(info.Displacement)
//slog.Info(fmt.Sprintf("动力学返回速度:%v,位移:%vtime:%v", info.Speed, info.Displacement, time.Now().UnixMilli()))
pluseCount(sta, info.HeadSpeed1, info.HeadSpeed2, info.TailSpeed1, info.TailSpeed2) pluseCount(sta, info.HeadSpeed1, info.HeadSpeed2, info.TailSpeed1, info.TailSpeed2)
return sta return sta
} }
@ -385,20 +400,41 @@ func updateTrainActiveDirFromDynamic(vs *VerifySimulation, info *message.Dynamic
} }
} }
var tmpArr []uint32
// 根据列车位置修改列车应答器 // 根据列车位置修改列车应答器
func updateTrainBtmPosition(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64) { func updateTrainBtmPosition(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64) {
// 更新BTM中列车位置信息 // 更新BTM中列车位置信息
//isup := sta.TrainActiveDirection == 1
can_btm.Default().HandleTrainHeadPositionInfo(vs.World, sta.VobcBtm, &fi.TrainHeadPositionInfo{ can_btm.Default().HandleTrainHeadPositionInfo(vs.World, sta.VobcBtm, &fi.TrainHeadPositionInfo{
TrainId: sta.Id, TrainId: sta.Id,
Up: info.Up, Up: info.Up,
Link: outLinkId, Link: outLinkId,
LinkOffset: outLinkOffset, LinkOffset: outLinkOffset,
Speed: info.Speed, Speed: info.Speed,
Acceleration: info.Acceleration, Acceleration: info.Acceleration,
OldLinkOffset: sta.OldLinkOffset,
OldLink: sta.OldLink,
}) })
state := can_btm.Default().GetState() state := can_btm.Default().GetState()
//fmt.Println(state.Telegram) /*dd, _ := hex.DecodeString(state.Telegram)
sta.BtmState = &state crc := message.Can_Crc32(dd)
find := false
for _, u := range tmpArr {
if u == crc {
find = true
break
}
}
if !find {
tmpArr = append(tmpArr, crc)
slog.Info(fmt.Sprintf("应答器id:%v ,报文:%v", state.BaliseId, state.Telegram))
}*/
if sta.BtmState == nil || sta.BtmState.BaliseId != state.BaliseId {
sta.BtmState = &state
}
} }
// 根据动力学修改列车位置 // 根据动力学修改列车位置

View File

@ -4,6 +4,7 @@ import (
"encoding/binary" "encoding/binary"
"encoding/hex" "encoding/hex"
"fmt" "fmt"
uuid2 "github.com/google/uuid"
"joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/const/balise_const" "joylink.club/bj-rtsts-server/const/balise_const"
"joylink.club/bj-rtsts-server/dto/data_proto" "joylink.club/bj-rtsts-server/dto/data_proto"
@ -50,13 +51,13 @@ func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
//此处先注释,根据现场调试情况 2024-4-16 //此处先注释,根据现场调试情况 2024-4-16
train_pc_sim.Default().SendTrainDirection(sta, sta.VobcState.DirectionForward, sta.VobcState.DirectionBackward) train_pc_sim.Default().SendTrainDirection(sta, sta.VobcState.DirectionForward, sta.VobcState.DirectionBackward)
} else if ct.ControlType == request_proto.TrainControl_HANDLER { } else if ct.ControlType == request_proto.TrainControl_HANDLER {
if vobc.Tc1Active && vobc.Tc2Active { if !vobc.Tc1Active && !vobc.Tc2Active {
panic(sys_error.New("TC1和TC2都未激活不能搬动牵引制动手柄 ")) panic(sys_error.New("TC1和TC2都未激活不能搬动牵引制动手柄 "))
} }
baseMsg = trainControlHandle(vobc, tcc, ct.Handler, ct.DeviceId, tccGraphicData)
oldTraction := sta.VobcState.TractionForce oldTraction := sta.VobcState.TractionForce
oldBrakeForce := sta.VobcState.BrakeForce oldBrakeForce := sta.VobcState.BrakeForce
isTraction := ct.Handler.Val > 0 //是否制动 isTraction := ct.Handler.Val > 0 //是否制动
baseMsg = trainControlHandle(vobc, tcc, ct.Handler, ct.DeviceId, tccGraphicData)
train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isTraction, sta) train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, isTraction, sta)
} }
if vobc.DirectionForward && vobc.TractionForce == 0 { if vobc.DirectionForward && vobc.TractionForce == 0 {
@ -138,7 +139,8 @@ func controlEBBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_p
tccBtn.Passed = active tccBtn.Passed = active
vobc.EmergencyBrakingStatus = true vobc.EmergencyBrakingStatus = true
vobc.TractionForce = 0 vobc.TractionForce = 0
vobc.BrakeForce = DEFAULT_BRAKE_FORCE vobc.BrakeForce = DEFAULT_EB
vobc.BrakingStatus = true
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 0}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, 1}}} return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 0}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, 1}}}
} }
@ -409,20 +411,21 @@ func trainControlHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.Train
vobc.BrakingStatus = false vobc.BrakingStatus = false
vobc.BrakeForce = 0 vobc.BrakeForce = 0
vobc.MaintainBrakeStatus = false vobc.MaintainBrakeStatus = false
notBreak := byte(0)
var zeroState byte = 0 var zeroState byte = 0
var brakeState byte = 0 var brakeState byte = 0
if request.Val > 0 { if request.Val > 0 {
vobc.TractionStatus = true vobc.TractionStatus = true
vobc.TractionForce = int64(request.Val * 180) vobc.TractionForce = int64(request.Val * 180)
notBreak = 1
} else if request.Val < 0 { } else if request.Val < 0 {
vobc.BrakingStatus = true vobc.BrakingStatus = true
vobc.BrakeForce = int64(-request.Val * 180) vobc.BrakeForce = int64(-request.Val * 180)
vobc.EmergencyBrakingStatus = false vobc.EmergencyBrakingStatus = false
jjzdBtn.Passed = false jjzdBtn.Passed = false
brakeState = 1 brakeState = 0
} else { } else {
zeroState = 1 zeroState = 1
} }
@ -433,7 +436,7 @@ func trainControlHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.Train
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.HANDLE_TO_ZERO, zeroState}}, return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.HANDLE_TO_ZERO, zeroState}},
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, brakeState}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, brakeState}},
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 1}}} {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 1}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, notBreak}}}
} }
func (s *VerifySimulation) GetConnTrain2() []*state_proto.TrainState { func (s *VerifySimulation) GetConnTrain2() []*state_proto.TrainState {
@ -488,17 +491,27 @@ func (s *VerifySimulation) reportTrainMockInitMsg(train *state_proto.TrainState,
initResult := trainInit initResult := trainInit
if vobc.Tc1Active || vobc.Tc2Active { if vobc.Tc1Active || vobc.Tc2Active {
state := message.GetBit(data1, 3) state := message.GetBit(data1, 3)
slog.Info(fmt.Sprintf("接收列车输出数量:%b", data1))
if trainInit { if trainInit {
if data1 == 0 { if data1 == 0 {
tcc.Line12ConnErr = true tcc.Line12ConnErr = true
slog.Warn("接受atp模拟量数据data[4]=0模拟断开")
} }
if state == 0 { if state == 0 {
train_pc_sim.Default().ResetPluseCount(train) //tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 1}})
jjzdBtn := tcc.Buttons[JJZD]
ebTce := controlEBBtn(vobc, true, jjzdBtn)
tce = append(tce, ebTce...)
} else if message.GetBit(data1, 0) == 0 {
//tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}})
//tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, 0}})
//tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{0x38, 0}})
jjzdBtn := tcc.Buttons[JJZD] jjzdBtn := tcc.Buttons[JJZD]
ebTce := controlEBBtn(vobc, true, jjzdBtn) ebTce := controlEBBtn(vobc, true, jjzdBtn)
tce = append(tce, ebTce...) tce = append(tce, ebTce...)
} }
/*else {
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, state}})
}*/
} else { } else {
initResult = true initResult = true
if tcc.LineInitTimeStamp12 <= 0 { if tcc.LineInitTimeStamp12 <= 0 {
@ -535,6 +548,9 @@ func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(train *state_proto.Tra
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc) trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc) trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc) trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
/* if !vobc.EmergencyBrakingStatus {
train_pc_sim.Default().ResetPlusePlace(train)
}*/
return initResult return initResult
} }
@ -674,10 +690,14 @@ func (s *VerifySimulation) TrainPcSimMockInfo(train *state_proto.TrainState, dat
train.VobcState.MockInfo = uint32(mockData) train.VobcState.MockInfo = uint32(mockData)
} }
var sendData []uint32
// 4.4.4. 车载输出BTM查询同步帧报文内容0x04 // 4.4.4. 车载输出BTM查询同步帧报文内容0x04
func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []byte) { func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []byte) {
//time.Sleep(time.Millisecond * 50) //time.Sleep(time.Millisecond * 50)
slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧报文内容:%v", hex.EncodeToString(data))) uuid := uuid2.NewString()
ts := time.Now().UnixMilli()
//slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧uuid:%v,时间:%v, 报文内容:%v", uuid, ts, hex.EncodeToString(data)))
if len(data) < 12 { if len(data) < 12 {
slog.Error("列车btm查询报文长度错误:", len(data)) slog.Error("列车btm查询报文长度错误:", len(data))
return return
@ -687,6 +707,7 @@ func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []b
slog.Warn(fmt.Sprintf("列车暂时未获取到应答器信息,无法进行btm查询列车id:%v", train.Id)) slog.Warn(fmt.Sprintf("列车暂时未获取到应答器信息,无法进行btm查询列车id:%v", train.Id))
return return
} }
notSendBtm, ok := can_btm.Default().FindNotSendState()
trainAtm := message.NewBtmHeadFrame(data) trainAtm := message.NewBtmHeadFrame(data)
atpReq := &message.AtpRequestFrame{} atpReq := &message.AtpRequestFrame{}
@ -697,14 +718,20 @@ func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []b
cl := clock(atpReq) cl := clock(atpReq)
dsn := train_pc_sim.Default().DsnAddAndReturn() dsn := train_pc_sim.Default().DsnAddAndReturn()
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl, dsn) //btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl, dsn)
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, &notSendBtm, atpReq, cl, dsn)
//slog.Info(fmt.Sprintf("id1:%x,id2:%x,id3:%x,id4:%x,resendRequest:%v,reqTime:%v,dsn:%v", trainAtm.CanId.ID1, trainAtm.CanId.ID2, trainAtm.CanId.ID3, trainAtm.CanId.ID4, atpReq.ResendRequest, atpReq.Time, dsn)) //slog.Info(fmt.Sprintf("id1:%x,id2:%x,id3:%x,id4:%x,resendRequest:%v,reqTime:%v,dsn:%v", trainAtm.CanId.ID1, trainAtm.CanId.ID2, trainAtm.CanId.ID3, trainAtm.CanId.ID4, atpReq.ResendRequest, atpReq.Time, dsn))
if atpReq.ResendRequest == 2 { if atpReq.ResendRequest == 2 {
slog.Info(fmt.Sprintf("rrrrrrrrrrrrrrrrr:%v", atpReq.String()))
//重新发送 //重新发送
if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 { //if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 {
dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend) if len(notSendBtm.BaliseTelegramForPcSimResend) > 0 {
slog.Info(fmt.Sprintf("rrrrrrrrrrrrrrrrr111111111:%v", atpReq.String()))
//dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend)
dd, _ := hex.DecodeString(notSendBtm.BaliseTelegramForPcSimResend)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, dd) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, dd)
} else { } else {
slog.Info(fmt.Sprintf("rrrrrrrrrrrrrrrrr2222222222222:%v", atpReq.String()))
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4) timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
timeSyncF.T2 = cl.BtmTk timeSyncF.T2 = cl.BtmTk
timeSyncF.T3 = cl.TkNow() timeSyncF.T3 = cl.TkNow()
@ -714,18 +741,31 @@ func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []b
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
} }
} else { } else {
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4) timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
timeSyncF.T2 = cl.BtmTk timeSyncF.T2 = cl.BtmTk
timeSyncF.T3 = cl.TkNow() timeSyncF.T3 = cl.TkNow()
telCount := strings.Count(train.BtmState.Telegram, "00") //telCount := strings.Count(train.BtmState.Telegram, "00")
if telCount >= balise_const.UserTelegramByteLen { telCount := strings.Count(notSendBtm.Telegram, "00")
//if telCount >= balise_const.UserTelegramByteLen || train.BtmState.IsSend {
if !ok && (notSendBtm.Telegram == "" || telCount >= balise_const.UserTelegramByteLen) {
//slog.Info(fmt.Sprintf("准备发送无数据应答器id:%v", train.BtmState.BaliseId))
queryData := make([]byte, 0) queryData := make([]byte, 0)
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...) queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...) queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData) train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
} else { //train.BtmState.IsSend = true
} else /*if !train.BtmState.IsSend*/
if !notSendBtm.IsSend {
slog.Info(fmt.Sprintf("准备发送应答id:%v,uuid :%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v", notSendBtm.BaliseId, uuid, ts, time.Now().UnixMilli(), notSendBtm.Telegram, notSendBtm.BaliseCount, notSendBtm.MessageCounter))
//slog.Info(fmt.Sprintf("准备发送应答id:%v,uuid :%v,消耗时间:%v , 数据:%v", train.BtmState.BaliseId, uuid, ts-time.Now().UnixMilli(), train.BtmState.Telegram))
/* defer func() {
train.BtmState.IsSend = true
}()*/
//有数据 //有数据
aliseData, _ := hex.DecodeString(train.BtmState.Telegram) //aliseData, _ := hex.DecodeString(train.BtmState.Telegram)
aliseData, _ := hex.DecodeString(notSendBtm.Telegram)
stateRepFrame := btmRepFrame.EncodeBtmAtp() stateRepFrame := btmRepFrame.EncodeBtmAtp()
statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, cl.BtmTk, cl.BtmTk, cl.BtmTk) statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, cl.BtmTk, cl.BtmTk, cl.BtmTk)
if statusDataCfOk { if statusDataCfOk {

View File

@ -52,6 +52,7 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRun
} }
if !e { if !e {
verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig) verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig)
if err != nil { if err != nil {
return "", err return "", err
} }