diff --git a/component/train.go b/component/train.go index 9df1b4c..1388eb3 100644 --- a/component/train.go +++ b/component/train.go @@ -3,7 +3,6 @@ package component import ( "fmt" "joylink.club/ecs" - "log/slog" ) // TrainPositionInfo 列车当前位置信息 @@ -31,14 +30,14 @@ func (t *TrainPositionInfo) ToString() string { type TrainBaliseTelegram struct { BaliseId string //应答器ID Telegram []byte //一个应答器同一时刻只有一条报文处于激活有效状态 - sent bool //true-已经向车载ATP发送过 + Up bool //列车经过应答器时的运行方向 } -func NewTrainBaliseTelegram(baliseId string, telegram []byte) *TrainBaliseTelegram { +func NewTrainBaliseTelegram(up bool, baliseId string, telegram []byte) *TrainBaliseTelegram { return &TrainBaliseTelegram{ BaliseId: baliseId, Telegram: telegram, - sent: false, + Up: up, } } @@ -53,9 +52,14 @@ type TrainBtm struct { //天线此时是否在应答器上方 AboveBalise bool //列车在运行方向顺序扫描到的应答器 - ScannedBalise *TrainBaliseTelegram + //避免丢失 + scannedBalises chan *TrainBaliseTelegram //最近经过的应答器id - viaBaliseId string + lastTelegram *TrainBaliseTelegram +} + +func NewTrainBtm() *TrainBtm { + return &TrainBtm{scannedBalises: make(chan *TrainBaliseTelegram, 16)} } // 应答器计数器加1,[0,255] @@ -74,31 +78,33 @@ func (t *TrainBtm) baliseMessageCounterAdd1() { } } -// SetBaliseTelegramHadSentAndGet 获取未发送的应答器报文并标记已发送 -// 通过Canet发送应答器报文时调用该方法来获取要发送的报文 -func (t *TrainBtm) SetBaliseTelegramHadSentAndGet() *TrainBaliseTelegram { - if t.ScannedBalise != nil && !t.ScannedBalise.sent { - t.ScannedBalise.sent = true - return t.ScannedBalise +func (t *TrainBtm) FindScannedBalises() <-chan *TrainBaliseTelegram { + if len(t.scannedBalises) > 0 { + return t.scannedBalises + } else { + return nil } - return nil } // Scanning BTM通过车载应答器天线接收到应答器报文 -func (t *TrainBtm) Scanning(aboveBalise bool, aboveBaliseId string, telegram *TrainBaliseTelegram) { - t.AboveBalise = aboveBalise - //BTM此时在一个新的应答器上方 - if t.AboveBalise && t.viaBaliseId != aboveBaliseId { - t.viaBaliseId = aboveBaliseId - t.baliseCounterAdd1() - slog.Debug(fmt.Sprintf("列车经过应答器上方,应答器:[%s]", t.viaBaliseId)) +func (t *TrainBtm) Scanning(aboveBalise bool, telegram *TrainBaliseTelegram) { + //新报文 + isNewTbt := telegram != nil && (t.lastTelegram == nil || t.lastTelegram.Up != telegram.Up || t.lastTelegram.BaliseId != telegram.BaliseId) + if isNewTbt { + t.lastTelegram = telegram } // - if telegram == nil { - return + if isNewTbt { + t.scannedBalises <- telegram + t.baliseMessageCounterAdd1() + } + // + t.AboveBalise = aboveBalise + //BTM此时在一个新的应答器上方 + if t.AboveBalise || isNewTbt { + t.baliseCounterAdd1() + //slog.Debug(fmt.Sprintf("列车经过应答器上方,应答器:[%s]", t.viaBaliseId)) } - t.ScannedBalise = telegram - t.baliseMessageCounterAdd1() } var ( diff --git a/entity/train.go b/entity/train.go index 0a3f1e7..81f4849 100644 --- a/entity/train.go +++ b/entity/train.go @@ -18,7 +18,7 @@ func NewTrainWithBtmEntity(w ecs.World, trainId string) *ecs.Entry { te := w.Entry(w.Create(component.UidType, component.TrainPositionInfoType, component.TrainBtmType)) component.UidType.SetValue(te, component.Uid{Id: trainId}) component.TrainPositionInfoType.Set(te, &component.TrainPositionInfo{}) - component.TrainBtmType.Set(te, &component.TrainBtm{}) + component.TrainBtmType.Set(te, component.NewTrainBtm()) data.EntityMap[trainId] = te return te } diff --git a/fi/train.go b/fi/train.go index 70bc718..1ea0740 100644 --- a/fi/train.go +++ b/fi/train.go @@ -107,22 +107,21 @@ func TrainBalisePowerAmplifierSwitch(w ecs.World, turnOn bool) error { return result.Err } -// BaliseTelegramForSend 获取当前与CANET关联的列车的用于发送的应答器报文 -// 会修改应答器报文状态为已发送 -func BaliseTelegramForSend(w ecs.World) (*component.TrainBaliseTelegram, error) { - result := <-ecs.Request[*component.TrainBaliseTelegram](w, func() ecs.Result[*component.TrainBaliseTelegram] { +// GetScannedBaliseTelegram 获取扫描到的应答器报文 +func GetScannedBaliseTelegram(w ecs.World) (<-chan *component.TrainBaliseTelegram, error) { + result := <-ecs.Request[<-chan *component.TrainBaliseTelegram](w, func() ecs.Result[<-chan *component.TrainBaliseTelegram] { //获取当前关联CANET设备的列车 canetTrain := findCanetTrain(w) if canetTrain == nil { - return ecs.NewResult[*component.TrainBaliseTelegram](nil, fmt.Errorf("系统中当前不存在与CANET设备关联的列车实体")) + return ecs.NewResult[<-chan *component.TrainBaliseTelegram](nil, fmt.Errorf("系统中当前不存在与CANET设备关联的列车实体")) } // train := component.TrainBtmType.Get(canetTrain) - tbt := train.SetBaliseTelegramHadSentAndGet() + tbt := train.FindScannedBalises() if tbt != nil { return ecs.NewOkResult(tbt) } else { - return ecs.NewResult[*component.TrainBaliseTelegram](nil, fmt.Errorf("此刻没有要发送的应答器报文")) + return ecs.NewResult[<-chan *component.TrainBaliseTelegram](nil, fmt.Errorf("此刻没有要发送的应答器报文")) } }) return result.Val, result.Err diff --git a/sys/device_sys/balise_detection.go b/sys/device_sys/balise_detection.go index 47b73d8..59df1f3 100644 --- a/sys/device_sys/balise_detection.go +++ b/sys/device_sys/balise_detection.go @@ -38,17 +38,17 @@ func (s *BaliseDetectSystem) DetectBalise(w ecs.World, trainEntry *ecs.Entry, la } for _, detectedBalise := range tt { //列车应答器天线扫描到应答器,获取应答器报文发送给BTM - tbt := s.findBaliseTelegram(wd, detectedBalise) + tbt := s.findBaliseTelegram(wd, r.up, detectedBalise) if tbt != nil { tbts = append(tbts, tbt) } } } if len(tbts) <= 0 { - btm.Scanning(aboveBalise, "", nil) + btm.Scanning(aboveBalise, nil) } else { for _, tbt := range tbts { - btm.Scanning(true, tbt.BaliseId, tbt) + btm.Scanning(true, tbt) } } } @@ -121,7 +121,7 @@ func (s *BaliseDetectSystem) headMoveRanges(wd *component.WorldData, last *Train } // 获取应答器激活的有效报文 -func (s *BaliseDetectSystem) findBaliseTelegram(wd *component.WorldData, detectedBalise *repository.Transponder) *component.TrainBaliseTelegram { +func (s *BaliseDetectSystem) findBaliseTelegram(wd *component.WorldData, up bool, detectedBalise *repository.Transponder) *component.TrainBaliseTelegram { if detectedBalise == nil { return nil } @@ -133,7 +133,7 @@ func (s *BaliseDetectSystem) findBaliseTelegram(wd *component.WorldData, detecte baliseState.ValidTelegram = []byte{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12} // if len(baliseState.ValidTelegram) > 0 { - return component.NewTrainBaliseTelegram(detectedBalise.Id(), baliseState.ValidTelegram) + return component.NewTrainBaliseTelegram(up, detectedBalise.Id(), baliseState.ValidTelegram) } } else { slog.Warn(fmt.Sprintf("应答器[%s]实体不存在", detectedBalise.Id()))