[重写]计轴的组件、实体、系统、预复位/复位逻辑

This commit is contained in:
thesai 2024-07-31 17:08:53 +08:00
parent 8c6bfb2aee
commit 3182e867c1
16 changed files with 694 additions and 586 deletions

View File

@ -1,113 +1,134 @@
package component package component
import ( import "joylink.club/ecs"
"fmt"
"joylink.club/ecs"
)
//计轴设备,管理联锁集中站内的所有计轴区段
//计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态
//计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
//
//当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。
//当RACRJORJT任意一个不为0时终止发送复零/预复零命令。
var ( var (
PhysicalSectionCircuitType = ecs.NewComponentType[PhysicalSectionCircuit]() AxleSectionTag = ecs.NewTag()
AxleSectionCircuitType = ecs.NewComponentType[AxleSectionCircuit]()
AxleManagerType = ecs.NewComponentType[AxleManager]()
) )
var AxleSectionForceOccupied = ecs.NewTag() //区段强制占用(故障占用)
type PhysicalSectionCircuit struct { // AxleManager 计轴管理器。我自己起的名字,计轴逻辑的载体
type AxleManager struct {
Count int //轴数(简化版)。目前此轴数计数只与区段上有无列车有关,故障占用等状态不会影响此计数
Occupied bool //占用
PDRST bool //预复位
//RAC bool //计轴复位反馈。主要指计轴设备发送给CI系统的直接复零/预复零命令反馈表示计轴设备已收到CI系统发送的直接复零/预复零命令。
//RJO bool //运营原因拒绝直接复位/预复位。如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
//RJT bool //技术原因拒绝直接复位/预复位。主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等。
}
// AxleSectionCircuit 计轴区段电路
type AxleSectionCircuit struct {
GJ *ecs.Entry GJ *ecs.Entry
} }
// PhysicalSectionState 物理区段 ////计轴设备,管理联锁集中站内的所有计轴区段
type PhysicalSectionState struct { ////计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态
//true-占用false-出清 ////计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
Occ bool ////
} ////当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。
////当RACRJORJT任意一个不为0时终止发送复零/预复零命令。
// AxlePhysicalSection 计轴物理区段
type AxlePhysicalSection struct {
//计轴区段内车轴数
Count int
//记录Count变化波形
countPulse uint8
}
type AxleDeviceRuntime struct {
//true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。
Rac bool
//true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
Rjo bool
//true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等
Rjt bool
//true-计轴直接复位
//计轴的轮对计数清零,区段转换为空闲状态
Drst bool
//true-计轴预复位
//将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
Pdrst bool
//true-计轴系统正在执行直接预复位操作
DoingPdrst bool
}
func NewAxleDeviceRuntime() *AxleDeviceRuntime {
return &AxleDeviceRuntime{}
}
// AxleManageDevice 计轴管理设备
type AxleManageDevice struct {
CentralizedStation string //所属集中站编号code
Adrs map[string]*AxleDeviceRuntime //key-sectionId
}
func (d *AxleManageDevice) FindAdr(sectionId string) *AxleDeviceRuntime {
return d.Adrs[sectionId]
}
func NewAxleManageDevice(centralizedStation string) *AxleManageDevice {
return &AxleManageDevice{CentralizedStation: centralizedStation, Adrs: make(map[string]*AxleDeviceRuntime)}
}
var (
PhysicalSectionStateType = ecs.NewComponentType[PhysicalSectionState]()
AxlePhysicalSectionType = ecs.NewComponentType[AxlePhysicalSection]()
AxleSectionFaultTag = ecs.NewTag()
AxleManageDeviceType = ecs.NewComponentType[AxleManageDevice]()
)
/////////////////////////////AxlePhysicalSection/////////////////////////////////
func NewAxlePhysicalSection() *AxlePhysicalSection {
return &AxlePhysicalSection{Count: 0, countPulse: 0}
}
func (c *AxlePhysicalSection) UpdateCount(count int) {
cp := to1(c.Count)
np := to1(count)
// //
if cp != np { //var (
c.countPulse <<= 1 // PhysicalSectionCircuitType = ecs.NewComponentType[PhysicalSectionCircuit]()
if np > 0 { //)
c.countPulse |= np //
} //type PhysicalSectionCircuit struct {
} // GJ *ecs.Entry
c.Count = count //}
} //
func (c *AxlePhysicalSection) ResetCountPulse() { //// PhysicalSectionState 物理区段
c.countPulse = 0x00 //type PhysicalSectionState struct {
} // //true-占用false-出清
func (c *AxlePhysicalSection) ShowCountWave() string { // Occ bool
return fmt.Sprintf("%08b", c.countPulse) //}
} //
//// AxlePhysicalSection 计轴物理区段
// IsCount010Pulse true-车进入计轴区段后出清计轴区段 //type AxlePhysicalSection struct {
func (c *AxlePhysicalSection) IsCount010Pulse() bool { // //计轴区段内车轴数
return c.countPulse&0x01 == 0 && c.countPulse&0x02 > 0 && c.countPulse&0x04 == 0 // Count int
} // //记录Count变化波形
// countPulse uint8
// 归1 //}
func to1(c int) uint8 { //type AxleDeviceRuntime struct {
if c > 0 { // //true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。
return 0x01 // RAC bool
} else { // //true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
return 0x00 // RJO bool
} // //true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等
} // RJT bool
// //true-计轴直接复位
// //计轴的轮对计数清零,区段转换为空闲状态
// Drst bool
// //true-计轴预复位
// //将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
// PDRST bool
// //true-计轴系统正在执行直接预复位操作
// DoingPdrst bool
//}
//
//func NewAxleDeviceRuntime() *AxleDeviceRuntime {
// return &AxleDeviceRuntime{}
//}
//
//// AxleManageDevice 计轴管理设备
//type AxleManageDevice struct {
// CentralizedStation string //所属集中站编号code
// Adrs map[string]*AxleDeviceRuntime //key-sectionId
//}
//
//func (d *AxleManageDevice) FindAdr(sectionId string) *AxleDeviceRuntime {
// return d.Adrs[sectionId]
//}
//func NewAxleManageDevice(centralizedStation string) *AxleManageDevice {
// return &AxleManageDevice{CentralizedStation: centralizedStation, Adrs: make(map[string]*AxleDeviceRuntime)}
//}
//
//var (
// PhysicalSectionStateType = ecs.NewComponentType[PhysicalSectionState]()
// AxlePhysicalSectionType = ecs.NewComponentType[AxlePhysicalSection]()
// AxleSectionFaultTag = ecs.NewTag()
// AxleManageDeviceType = ecs.NewComponentType[AxleManageDevice]()
//)
//
///////////////////////////////AxlePhysicalSection/////////////////////////////////
//
//func NewAxlePhysicalSection() *AxlePhysicalSection {
// return &AxlePhysicalSection{Count: 0, countPulse: 0}
//}
//func (c *AxlePhysicalSection) UpdateCount(count int) {
// cp := to1(c.Count)
// np := to1(count)
// //
// if cp != np {
// c.countPulse <<= 1
// if np > 0 {
// c.countPulse |= np
// }
// }
// c.Count = count
//}
//func (c *AxlePhysicalSection) ResetCountPulse() {
// c.countPulse = 0x00
//}
//func (c *AxlePhysicalSection) ShowCountWave() string {
// return fmt.Sprintf("%08b", c.countPulse)
//}
//
//// IsCount010Pulse true-车进入计轴区段后出清计轴区段
//func (c *AxlePhysicalSection) IsCount010Pulse() bool {
// return c.countPulse&0x01 == 0 && c.countPulse&0x02 > 0 && c.countPulse&0x04 == 0
//}
//
//// 归1
//func to1(c int) uint8 {
// if c > 0 {
// return 0x01
// } else {
// return 0x00
// }
//}

View File

@ -12,6 +12,7 @@ type TrainPositionInfo struct {
Up bool Up bool
//列车长度 mm //列车长度 mm
Len int64 Len int64
//列车所在轨道link //列车所在轨道link
HeadLink string HeadLink string
//列车所在link偏移量mm //列车所在link偏移量mm
@ -20,6 +21,15 @@ type TrainPositionInfo struct {
TailLink string TailLink string
//列车所在link偏移量mm //列车所在link偏移量mm
TailLinkOffset int64 TailLinkOffset int64
//车头所在物理区段
HeadSectionId string
//车头所在物理区段偏移量
HeadSectionOffset uint32
//车尾所在物理区段
TailSectionId string
//车尾所在物理区段偏移量
TailSectionOffset uint32
} }
func (t *TrainPositionInfo) ToString() string { func (t *TrainPositionInfo) ToString() string {

View File

@ -1,75 +1,34 @@
package entity package entity
import ( import (
"fmt"
"joylink.club/ecs" "joylink.club/ecs"
"joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository" "joylink.club/rtsssimulation/repository"
"strings"
"unsafe" "unsafe"
) )
func newAxleManageDevice(w ecs.World, data *component.WorldData, centralizedStation string) *ecs.Entry { var AxleSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.AxleSectionTag, component.AxleManagerType}
entry := w.Entry(w.Create(component.AxleManageDeviceType))
component.AxleManageDeviceType.Set(entry, component.NewAxleManageDevice(centralizedStation))
data.AxleManageDeviceEntities = append(data.AxleManageDeviceEntities, entry)
return entry
}
// LoadAxlePhysicalSections 加载计轴区段 // LoadAxlePhysicalSections 加载计轴区段
func LoadAxlePhysicalSections(w ecs.World) error { func LoadAxlePhysicalSections(w ecs.World) error {
data := GetWorldData(w) wd := GetWorldData(w)
sections := data.Repo.PhysicalSectionList() sections := wd.Repo.PhysicalSectionList()
for _, section := range sections { for _, section := range sections {
if is, se := section.IsAxleSection(); se == nil && is { if is, err := section.IsAxleSection(); err == nil && is {
if len(strings.TrimSpace(section.CentralizedStation())) == 0 { entry := w.Entry(w.Create(AxleSectionBaseComponentTypes...))
return fmt.Errorf("区段[%s]未设置所属集中站", section.Id()) component.UidType.SetValue(entry, component.Uid{Id: section.Id()})
} for _, group := range section.ComponentGroups() {
amdEntry := FindAxleManageDevice(data, section.CentralizedStation())
if amdEntry == nil {
amdEntry = newAxleManageDevice(w, data, section.CentralizedStation())
}
amd := component.AxleManageDeviceType.Get(amdEntry)
//
createAxleSectionEntity(w, section, data)
//
amd.Adrs[section.Id()] = component.NewAxleDeviceRuntime()
}
}
return nil
}
func FindAxleManageDevice(data *component.WorldData, centralizedStation string) *ecs.Entry {
for _, entry := range data.AxleManageDeviceEntities {
amd := component.AxleManageDeviceType.Get(entry)
if amd != nil && amd.CentralizedStation == centralizedStation {
return entry
}
}
return nil
}
// 计轴区段实体
func createAxleSectionEntity(w ecs.World, axleSection *repository.PhysicalSection, worldData *component.WorldData) *ecs.Entry {
uid := axleSection.Id()
entry, ok := worldData.EntityMap[uid]
if !ok {
entry = w.Entry(w.Create(component.UidType, component.PhysicalSectionStateType, component.AxlePhysicalSectionType))
//
component.UidType.SetValue(entry, component.Uid{Id: uid})
component.PhysicalSectionStateType.Set(entry, &component.PhysicalSectionState{Occ: false})
component.AxlePhysicalSectionType.Set(entry, component.NewAxlePhysicalSection())
//
for _, group := range axleSection.ComponentGroups() {
for _, ec := range group.Components() { for _, ec := range group.Components() {
if ec.Code() == "GJ" { if ec.Code() == "GJ" {
relay := ec.(*repository.Relay) relay := ec.(*repository.Relay)
gjEntry := NewRelayEntity(w, relay, worldData.EntityMap) gjEntry := NewRelayEntity(w, relay, wd.EntityMap)
circuit := &component.PhysicalSectionCircuit{GJ: gjEntry} circuit := &component.AxleSectionCircuit{GJ: gjEntry}
entry.AddComponent(component.PhysicalSectionCircuitType, unsafe.Pointer(circuit)) entry.AddComponent(component.AxleSectionCircuitType, unsafe.Pointer(circuit))
} }
} }
} }
worldData.EntityMap[uid] = entry wd.EntityMap[section.Id()] = entry
} }
return entry }
return nil
} }

View File

@ -47,9 +47,10 @@ func newBaliseEntity(w ecs.World, td *repository.Transponder, worldData *compone
if proto.Transponder_IB == td.BaliseType() || proto.Transponder_VB == td.BaliseType() { if proto.Transponder_IB == td.BaliseType() || proto.Transponder_VB == td.BaliseType() {
entry.AddComponent(component.BaliseVariableTelegramType) entry.AddComponent(component.BaliseVariableTelegramType)
} }
linkPosition := td.LinkPosition()
component.LinkPositionType.SetValue(entry, component_data.LinkPosition{ component.LinkPositionType.SetValue(entry, component_data.LinkPosition{
LinkId: td.LinkPosition().Link().Id(), LinkId: linkPosition.Link().Id(),
Offset: td.LinkPosition().Offset(), Offset: linkPosition.Offset(),
}) })
component.KmType.Set(entry, td.Km()) component.KmType.Set(entry, td.Km())
worldData.EntityMap[uid] = entry worldData.EntityMap[uid] = entry

120
fi/axle_section.go Normal file
View File

@ -0,0 +1,120 @@
package fi
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"strings"
)
// AxleSectionFaultOccDrive 区段故障占用设置
func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
sectionEntry := wd.EntityMap[sectionId]
if sectionEntry == nil {
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
}
if set { //计轴故障设置
if !sectionEntry.HasComponent(component.AxleSectionForceOccupied) {
sectionEntry.AddComponent(component.AxleSectionForceOccupied)
}
} else { //计轴故障取消
if sectionEntry.HasComponent(component.AxleSectionForceOccupied) {
sectionEntry.RemoveComponent(component.AxleSectionForceOccupied)
}
}
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionDrstDrive 直接复位
func AxleSectionDrstDrive(w ecs.World, sectionId string) (*AxleSectionState, error) {
r := <-ecs.Request[*AxleSectionState](w, func() ecs.Result[*AxleSectionState] {
wd := entity.GetWorldData(w)
entry := wd.EntityMap[sectionId]
if entry == nil {
return ecs.NewResult[*AxleSectionState](nil, fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleManager := component.AxleManagerType.Get(entry)
state := &AxleSectionState{}
if axleManager.Count != 0 {
state.Rjo = true
} else {
entry.RemoveComponent(component.AxleSectionForceOccupied)
state.Rac = true
}
return ecs.NewOkResult(state)
})
return r.Val, r.Err
}
// AxleSectionPdrstDrive 预复位
func AxleSectionPdrstDrive(w ecs.World, sectionId string) (*AxleSectionState, error) {
r := <-ecs.Request[*AxleSectionState](w, func() ecs.Result[*AxleSectionState] {
wd := entity.GetWorldData(w)
entry := wd.EntityMap[sectionId]
if entry == nil {
return ecs.NewResult[*AxleSectionState](nil, fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleManager := component.AxleManagerType.Get(entry)
state := &AxleSectionState{}
if axleManager.Count != 0 {
state.Rjo = true
} else {
state.Rac = true
}
return ecs.NewOkResult(state)
})
return r.Val, r.Err
}
// FindAxleSectionsStatus 获取计轴区段的相关状态
func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) {
r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] {
wd := entity.GetWorldData(w)
var msg []*AxleSectionState
var esb = strings.Builder{} //收集未找到的区段的id
for _, sectionId := range sectionIds {
entry := wd.EntityMap[sectionId]
if entry == nil {
esb.WriteString(fmt.Sprintf("%s,", sectionId))
continue
}
axleManager := component.AxleManagerType.Get(entry)
msg = append(msg, &AxleSectionState{
Id: sectionId,
Clr: !axleManager.Occupied,
Occ: axleManager.Occupied,
})
}
if esb.Len() > 0 {
return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String()))
} else {
return ecs.NewResult(msg, nil)
}
})
return r.Val, r.Err
}
type AxleSectionState struct {
//uid
Id string
//0-bit7 计轴出清
Clr bool
//0-bit6 计轴占用
Occ bool
//1-bit6 计轴复位反馈
Rac bool
//1-bit5 运营原因拒绝计轴复位
Rjo bool
//1-bit4 技术原因拒绝计轴复位
Rjt bool
}

View File

@ -1,239 +1,173 @@
package fi package fi
import (
"fmt"
"strings"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// AxleSectionDrstDrive 计轴直接复位操作
// //
// set : true-设置false-取消 //import (
func AxleSectionDrstDrive(w ecs.World, sectionId string, set bool) error { // "fmt"
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] { // "strings"
wd := entity.GetWorldData(w)
// //
sectionModel := wd.Repo.FindPhysicalSection(sectionId) // "joylink.club/ecs"
if sectionModel == nil { // "joylink.club/rtsssimulation/component"
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId)) // "joylink.club/rtsssimulation/entity"
} //)
// if set { //
// axleSectionEntry := wd.EntityMap[sectionId] //// AxleSectionDrstDrive 计轴直接复位操作
// if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) { ////
// return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId)) //// set : true-设置false-取消
//func AxleSectionDrstDrive(w ecs.World, sectionId string, set bool) error {
// r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
// wd := entity.GetWorldData(w)
// //
// sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// if sectionModel == nil {
// return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
// } // }
// // if set {
// // axleSectionEntry := wd.EntityMap[sectionId]
// // if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// // return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
// // }
// // }
// //
// faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
//
// if faDcAxleDeviceEntry == nil {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
// }
// faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
// axleRuntime := faDcAxleDevice.FindAdr(sectionId)
// if axleRuntime == nil {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
// }
// axleRuntime.Drst = set
// //
// return ecs.NewOkEmptyResult()
// })
// return r.Err
//} //}
// //
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation()) //// AxleSectionPdrstDrive 计轴预复位操作
////
if faDcAxleDeviceEntry == nil { //// set : true-设置false-取消
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation())) //func AxleSectionPdrstDrive(w ecs.World, sectionId string, set bool) error {
} // r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry) // wd := entity.GetWorldData(w)
axleRuntime := faDcAxleDevice.FindAdr(sectionId) // sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if axleRuntime == nil { // if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId)) // return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
axleRuntime.Drst = set
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionPdrstDrive 计轴预复位操作
//
// set : true-设置false-取消
func AxleSectionPdrstDrive(w ecs.World, sectionId string, set bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
// if set {
// axleSectionEntry := wd.EntityMap[sectionId]
// if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
// } // }
// // if set {
// // axleSectionEntry := wd.EntityMap[sectionId]
// // if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// // return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
// // }
// // }
// //
// faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
//
// if faDcAxleDeviceEntry == nil {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
// }
// faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
// axleRuntime, ok := faDcAxleDevice.Adrs[sectionId]
// if !ok {
// return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
// }
// axleRuntime.Pdrst = set
// //
// return ecs.NewOkEmptyResult()
// })
// return r.Err
//} //}
// //
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation()) //// AxleSectionFaultOccDrive 区段故障占用设置
////
if faDcAxleDeviceEntry == nil { //// set : true - 设置故障占用false - 取消故障占用
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation())) //func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
} // r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry) // wd := entity.GetWorldData(w)
axleRuntime, ok := faDcAxleDevice.Adrs[sectionId] // sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if !ok { // if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId)) // return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
} // }
axleRuntime.Pdrst = set // //
// sectionEntry := wd.EntityMap[sectionId]
// if sectionEntry == nil {
// return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
// }
// if set { //计轴故障设置
// if !sectionEntry.HasComponent(component.AxleSectionFaultTag) {
// sectionEntry.AddComponent(component.AxleSectionFaultTag)
// }
// } else { //计轴故障取消
// if sectionEntry.HasComponent(component.AxleSectionFaultTag) {
// sectionEntry.RemoveComponent(component.AxleSectionFaultTag)
// }
// }
// //
// return ecs.NewOkEmptyResult()
// })
// return r.Err
//}
// //
return ecs.NewOkEmptyResult() //// FindAxleSectionsStatus 获取计轴区段的相关状态
}) //func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) {
return r.Err // r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] {
} // wd := entity.GetWorldData(w)
// var msg []*AxleSectionState
// AxleSectionFaultOccDrive 区段故障占用设置 // var esb = strings.Builder{} //收集未找到的区段的id
// for _, sectionId := range sectionIds {
// find := false
// sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// if sectionModel != nil {
// faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
// if faDcAxleDeviceEntry != nil {
// faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
// axleDevice := faDcAxleDevice.FindAdr(sectionId)
// if axleDevice != nil {
// sectionEntry, _ := entity.GetEntityByUid(w, sectionId)
// if sectionEntry != nil {
// if sectionEntry.HasComponent(component.AxlePhysicalSectionType) { //计轴物理区段实体
// as := &AxleSectionState{}
// state := component.PhysicalSectionStateType.Get(sectionEntry)
// as.Id = component.UidType.Get(sectionEntry).Id
// as.Clr = !state.Occ
// as.Occ = state.Occ
// as.Rac = axleDevice.Rac
// as.Rjt = axleDevice.Rjt
// as.Rjo = axleDevice.Rjo
// //
// msg = append(msg, as)
// find = true
// }
// }
// }
// }
// }
// //
// if !find {
// esb.WriteString(fmt.Sprintf("%s,", sectionId))
// }
// } //for
// if esb.Len() > 0 {
// return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String()))
// } else {
// return ecs.NewResult(msg, nil)
// }
// })
// return r.Val, r.Err
//}
// //
// set : true - 设置故障占用false - 取消故障占用 //type AxleSectionState struct {
func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error { // //uid
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] { // Id string
wd := entity.GetWorldData(w) // //0-bit7 计轴出清
sectionModel := wd.Repo.FindPhysicalSection(sectionId) // Clr bool
if sectionModel == nil { // //0-bit6 计轴占用
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId)) // Occ bool
} // //1-bit6 计轴复位反馈
// // Rac bool
sectionEntry := wd.EntityMap[sectionId] // //1-bit5 运营原因拒绝计轴复位
if sectionEntry == nil { // Rjo bool
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId)) // //1-bit4 技术原因拒绝计轴复位
} // Rjt bool
if set { //计轴故障设置 //}
if !sectionEntry.HasComponent(component.AxleSectionFaultTag) {
sectionEntry.AddComponent(component.AxleSectionFaultTag)
}
} else { //计轴故障取消
if sectionEntry.HasComponent(component.AxleSectionFaultTag) {
sectionEntry.RemoveComponent(component.AxleSectionFaultTag)
}
}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionTrainDrive 计轴区段内车进入出清设置
//
// trainIn : true - 计轴区段内有车false-计轴区段出清
func AxleSectionTrainDrive(w ecs.World, sectionId string, trainIn bool) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
}
//
sectionEntry := wd.EntityMap[sectionId]
if sectionEntry == nil {
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
}
axleDevice := component.AxlePhysicalSectionType.Get(sectionEntry)
if trainIn {
axleDevice.UpdateCount(1)
} else {
axleDevice.UpdateCount(0)
}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// FindAxleSectionsStatus 获取计轴区段的相关状态
func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) {
r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] {
wd := entity.GetWorldData(w)
var msg []*AxleSectionState
var esb = strings.Builder{} //收集未找到的区段的id
for _, sectionId := range sectionIds {
find := false
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel != nil {
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
if faDcAxleDeviceEntry != nil {
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleDevice := faDcAxleDevice.FindAdr(sectionId)
if axleDevice != nil {
sectionEntry, _ := entity.GetEntityByUid(w, sectionId)
if sectionEntry != nil {
if sectionEntry.HasComponent(component.AxlePhysicalSectionType) { //计轴物理区段实体
as := &AxleSectionState{}
state := component.PhysicalSectionStateType.Get(sectionEntry)
as.Id = component.UidType.Get(sectionEntry).Id
as.Clr = !state.Occ
as.Occ = state.Occ
as.Rac = axleDevice.Rac
as.Rjt = axleDevice.Rjt
as.Rjo = axleDevice.Rjo
//
msg = append(msg, as)
find = true
}
}
}
}
}
//
if !find {
esb.WriteString(fmt.Sprintf("%s,", sectionId))
}
} //for
if esb.Len() > 0 {
return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String()))
} else {
return ecs.NewResult(msg, nil)
}
})
return r.Val, r.Err
}
type AxleSectionState struct {
//uid
Id string
//0-bit7 计轴出清
Clr bool
//0-bit6 计轴占用
Occ bool
//1-bit6 计轴复位反馈
Rac bool
//1-bit5 运营原因拒绝计轴复位
Rjo bool
//1-bit4 技术原因拒绝计轴复位
Rjt bool
}
// AxleSectionRstDrive 复位(直接复位、预复位)
func AxleSectionRstDrive(w ecs.World, cmds []*AxleSectionCmd) error {
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
var esb = strings.Builder{} //收集未找到的区段的id
find := false
for _, cmd := range cmds {
sectionId := cmd.SectionId
sectionModel := wd.Repo.FindPhysicalSection(sectionId)
if sectionModel != nil {
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
if faDcAxleDeviceEntry != nil {
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleRuntime := faDcAxleDevice.FindAdr(sectionId)
if axleRuntime != nil {
axleRuntime.Pdrst = cmd.Pdrst
axleRuntime.Drst = cmd.Drst
find = true
}
}
}
if !find {
esb.WriteString(fmt.Sprintf("%s,", sectionId))
}
} //for
if esb.Len() > 0 {
return ecs.NewErrResult(fmt.Errorf("计轴区段复位操作,失败列表[%s]", esb.String()))
} else {
return ecs.NewOkEmptyResult()
}
})
return r.Err
}
type AxleSectionCmd struct {
SectionId string
Drst bool
Pdrst bool
}

View File

@ -9,7 +9,7 @@ type CheckPoint struct {
km *proto.Kilometer km *proto.Kilometer
pointType proto.CheckPointType //检测点类型 pointType proto.CheckPointType //检测点类型
devicePorts []DevicePort //检测点关联的设备及其端口 devicePorts []DevicePort //检测点关联的设备及其端口
linkPosition *LinkPosition linkPosition LinkPosition
} }
func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointType) *CheckPoint { func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointType) *CheckPoint {
@ -20,10 +20,14 @@ func NewCheckPoint(id string, km *proto.Kilometer, pointType proto.CheckPointTyp
} }
} }
func (c *CheckPoint) LinkPosition() LinkPosition {
return c.linkPosition
}
func (c *CheckPoint) bindDevicePort(devicePort DevicePort) { func (c *CheckPoint) bindDevicePort(devicePort DevicePort) {
c.devicePorts = append(c.devicePorts, devicePort) c.devicePorts = append(c.devicePorts, devicePort)
} }
func (c *CheckPoint) bindLinkPosition(position *LinkPosition) { func (c *CheckPoint) bindLinkPosition(position LinkPosition) {
c.linkPosition = position c.linkPosition = position
} }

View File

@ -18,8 +18,8 @@ type Link struct {
aKm *proto.Kilometer aKm *proto.Kilometer
bKm *proto.Kilometer bKm *proto.Kilometer
//Link上的模型非区段边界检测点、应答器、信号机 //按偏移量小到大排序的、此Link上的模型非区段边界检测点、应答器、信号机
devices []Identity devices []LinkPositionDevice
////Link关联的模型包含LinkNode ////Link关联的模型包含LinkNode
//devicePositions []*DeviceLinkPosition //devicePositions []*DeviceLinkPosition
@ -59,7 +59,7 @@ func (l *Link) BRelation() *TurnoutPort {
return l.bRelation return l.bRelation
} }
func (l *Link) Devices() []Identity { func (l *Link) Devices() []LinkPositionDevice {
return l.devices return l.devices
} }
@ -102,7 +102,7 @@ func (l *Link) bindKm(km *proto.Kilometer, port proto.Port) {
} }
} }
func (l *Link) bindDevices(devices ...Identity) { func (l *Link) bindDevices(devices ...LinkPositionDevice) {
for _, device := range devices { for _, device := range devices {
l.devices = append(l.devices, device) l.devices = append(l.devices, device)
} }
@ -138,15 +138,15 @@ type LinkPosition struct {
func NewLinkPosition(link *Link, offset int64) *LinkPosition { func NewLinkPosition(link *Link, offset int64) *LinkPosition {
return &LinkPosition{link: link, offset: offset} return &LinkPosition{link: link, offset: offset}
} }
func (l *LinkPosition) Link() *Link { func (l LinkPosition) Link() *Link {
return l.link return l.link
} }
func (l *LinkPosition) Offset() int64 { func (l LinkPosition) Offset() int64 {
return l.offset return l.offset
} }
func (l *LinkPosition) String() string { func (l LinkPosition) String() string {
return fmt.Sprintf("[LinkPosition:{%s-%d]", l.link.Id(), l.offset) return fmt.Sprintf("[LinkPosition:{%s-%d]", l.link.Id(), l.offset)
} }

View File

@ -22,6 +22,13 @@ func (m identity) Type() proto.DeviceType {
return m.deviceType return m.deviceType
} }
// LinkPositionDevice 有link位置的设备
type LinkPositionDevice interface {
Identity
LinkPosition() LinkPosition
bindLinkPosition(position LinkPosition)
}
//////////////////////////system中使用/////////////////////////////////// //////////////////////////system中使用///////////////////////////////////
// IRelayCRole 获取继电器在具体电路中的角色(组合类型、功能名称) // IRelayCRole 获取继电器在具体电路中的角色(组合类型、功能名称)

View File

@ -836,6 +836,10 @@ func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer
if visitedModelMap[device.Id()] { if visitedModelMap[device.Id()] {
continue continue
} }
linkPositionDevice, ok := device.(LinkPositionDevice)
if !ok {
return fmt.Errorf("device [%s:%s] not implements LinkPositionDevice", device.Id(), device.Type().String())
}
km := findModelKm(device) km := findModelKm(device)
if km == nil || km.CoordinateSystem == "" { if km == nil || km.CoordinateSystem == "" {
continue continue
@ -845,19 +849,12 @@ func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer
return err return err
} }
offset := int64(math.Abs(float64(convertedKm.Value - startKm.Value))) offset := int64(math.Abs(float64(convertedKm.Value - startKm.Value)))
linkPosition := &LinkPosition{ linkPosition := LinkPosition{
link: link, link: link,
offset: offset, offset: offset,
} }
switch device.Type() { linkPositionDevice.bindLinkPosition(linkPosition)
case proto.DeviceType_DeviceType_CheckPoint: link.bindDevices(linkPositionDevice)
device.(*CheckPoint).bindLinkPosition(linkPosition)
case proto.DeviceType_DeviceType_Signal:
device.(*Signal).bindLinkPosition(linkPosition)
case proto.DeviceType_DeviceType_Transponder:
device.(*Transponder).bindLinkPosition(linkPosition)
}
link.bindDevices(device)
} }
return nil return nil
} }

View File

@ -8,7 +8,7 @@ type Signal struct {
km *proto.Kilometer km *proto.Kilometer
//section *PhysicalSection //section *PhysicalSection
//turnoutPort TurnoutPort //turnoutPort TurnoutPort
linkPosition *LinkPosition linkPosition LinkPosition
//信号机电路系统电子元器件 //信号机电路系统电子元器件
componentGroups []*ElectronicComponentGroup componentGroups []*ElectronicComponentGroup
model proto.Signal_Model model proto.Signal_Model
@ -23,23 +23,21 @@ func NewSignal(id string, km *proto.Kilometer, code string, model proto.Signal_M
} }
} }
func (s *Signal) bindLinkPosition(position *LinkPosition) {
s.linkPosition = position
}
// func (s *Signal) bindSection(section *PhysicalSection) {
// s.section = section
// }
//
// func (s *Signal) bindTurnoutPort(tp TurnoutPort) {
// s.turnoutPort = tp
// }
func (s *Signal) RelayGroups() []*ElectronicComponentGroup { func (s *Signal) RelayGroups() []*ElectronicComponentGroup {
return s.componentGroups return s.componentGroups
} }
func (s *Signal) Code() string { func (s *Signal) Code() string {
return s.code return s.code
} }
func (s *Signal) Model() proto.Signal_Model { func (s *Signal) Model() proto.Signal_Model {
return s.model return s.model
} }
func (s *Signal) LinkPosition() LinkPosition {
return s.linkPosition
}
func (s *Signal) bindLinkPosition(position LinkPosition) {
s.linkPosition = position
}

View File

@ -8,7 +8,7 @@ type Transponder struct {
km *proto.Kilometer km *proto.Kilometer
//section *PhysicalSection //section *PhysicalSection
//turnoutPort TurnoutPort //turnoutPort TurnoutPort
linkPosition *LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取 linkPosition LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取
fixedTelegram []byte //应答器固定报文 fixedTelegram []byte //应答器固定报文
fixedUserTelegram []byte //应答器固定用户报文 fixedUserTelegram []byte //应答器固定用户报文
baliseType proto.Transponder_Type //应答器类型 baliseType proto.Transponder_Type //应答器类型
@ -38,10 +38,10 @@ func (t *Transponder) FixedTelegram() []byte {
func (t *Transponder) FixedUserTelegram() []byte { func (t *Transponder) FixedUserTelegram() []byte {
return t.fixedUserTelegram return t.fixedUserTelegram
} }
func (t *Transponder) bindLinkPosition(position *LinkPosition) { func (t *Transponder) bindLinkPosition(position LinkPosition) {
t.linkPosition = position t.linkPosition = position
} }
func (t *Transponder) LinkPosition() *LinkPosition { func (t *Transponder) LinkPosition() LinkPosition {
return t.linkPosition return t.linkPosition
} }

View File

@ -39,8 +39,9 @@ func BindSystem(w ecs.World) {
circuit_sys.NewIBPSys(), circuit_sys.NewIBPSys(),
device_sys.NewAlarmSys(), device_sys.NewAlarmSys(),
//物理区段 //物理区段
device_sys.NewFaDcAxleDeviceSystem(), //device_sys.NewFaDcAxleDeviceSystem(),
device_sys.NewSectionDetectSystem(), //device_sys.NewSectionDetectSystem(),
device_sys.NewAxleSectionSystem(),
//应答器 //应答器
device_sys.NewBaliseSystem(), device_sys.NewBaliseSystem(),
//电机 //电机

View File

@ -0,0 +1,57 @@
package device_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
)
type AxleSectionSystem struct {
trainQuery *ecs.Query //简化列车经过计轴时的计轴逻辑,后续有需要了再拆出去
axleSectionQuery *ecs.Query
}
func NewAxleSectionSystem() *AxleSectionSystem {
return &AxleSectionSystem{
trainQuery: ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType)),
axleSectionQuery: ecs.NewQuery(filter.Contains(component.UidType, component.AxleSectionTag, component.AxleManagerType)),
}
}
// Update
// 预复位逻辑:目前仅在区段上无车且占用时,才能成功设置预复位/复位,也就是说,区段会有【强制占用】状态且无车。
// 那么当预复位设置成功之后等待一次区段计数从非0变成0清除预复位和【强制占用】状态
func (s *AxleSectionSystem) Update(w ecs.World) {
sectionTrainCountMap := make(map[string]int)
s.trainQuery.Each(w, func(entry *donburi.Entry) {
trainPositionInfo := component.TrainPositionInfoType.Get(entry)
sectionIds := DoSearchTrainOccupiedSections(w, trainPositionInfo)
for _, id := range sectionIds {
sectionTrainCountMap[id]++
}
})
s.axleSectionQuery.Each(w, func(entry *donburi.Entry) {
sectionId := component.UidType.Get(entry).Id
axleManager := component.AxleManagerType.Get(entry)
count := axleManager.Count
axleManager.Count = sectionTrainCountMap[sectionId]
//预复位逻辑。
if axleManager.PDRST && count != 0 && axleManager.Count == 0 {
axleManager.PDRST = false
entry.RemoveComponent(component.AxleSectionForceOccupied)
}
//区段占用判定
var gj *ecs.Entry
if entry.HasComponent(component.AxleSectionCircuitType) {
gj = component.AxleSectionCircuitType.Get(entry).GJ
}
occupied := axleManager.Count != 0 || entry.HasComponent(component.AxleSectionForceOccupied)
if gj != nil {
component.RelayDriveType.Get(entry).Td = !occupied
axleManager.Occupied = !component.BitStateType.Get(gj).Val
} else {
axleManager.Occupied = occupied
}
})
}

View File

@ -1,100 +1,101 @@
package device_sys package device_sys
import (
"log/slog"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// FaDcAxleDeviceSystem FaDc计轴设备管理器系统
type FaDcAxleDeviceSystem struct {
query *ecs.Query
}
func NewFaDcAxleDeviceSystem() *FaDcAxleDeviceSystem {
return &FaDcAxleDeviceSystem{
query: ecs.NewQuery(filter.Contains(component.AxleManageDeviceType)),
}
}
func (s *FaDcAxleDeviceSystem) Update(w ecs.World) {
data := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
faDcDevice := component.AxleManageDeviceType.Get(entry)
for axleSectionId, axleRuntime := range faDcDevice.Adrs {
axleSectionEntry := data.EntityMap[axleSectionId]
sectionState := component.PhysicalSectionStateType.Get(axleSectionEntry)
axleDevice := component.AxlePhysicalSectionType.Get(axleSectionEntry)
// //
sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) //import (
s.calculateHf(sectionFault, axleSectionEntry, sectionState, axleDevice, axleRuntime) // "log/slog"
s.calculateDrst(axleSectionEntry, sectionState, axleDevice, axleRuntime) //
s.calculatePdrst(axleSectionEntry, sectionState, axleDevice, axleRuntime) // "joylink.club/ecs"
s.calculateSectionState(sectionFault, sectionState, axleDevice, axleRuntime) // "joylink.club/ecs/filter"
if axleSectionEntry.HasComponent(component.PhysicalSectionCircuitType) { // "joylink.club/rtsssimulation/component"
sectionCircuit := component.PhysicalSectionCircuitType.Get(axleSectionEntry) // "joylink.club/rtsssimulation/entity"
relayDrive := component.RelayDriveType.Get(sectionCircuit.GJ) //)
relayDrive.Td = !sectionState.Occ //
} //// FaDcAxleDeviceSystem FaDc计轴设备管理器系统
//type FaDcAxleDeviceSystem struct {
if "北京_12_酒仙桥_15G" == axleSectionId && false { // query *ecs.Query
sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) //}
slog.Info(axleSectionId, //
"Drst", axleRuntime.Drst, //func NewFaDcAxleDeviceSystem() *FaDcAxleDeviceSystem {
"Pdrst", axleRuntime.Pdrst, // return &FaDcAxleDeviceSystem{
"DoingPdrst", axleRuntime.DoingPdrst, // query: ecs.NewQuery(filter.Contains(component.AxleManageDeviceType)),
"Rac", axleRuntime.Rac, // }
"Rjo", axleRuntime.Rjo, //}
"Rjt", axleRuntime.Rjt, //func (s *FaDcAxleDeviceSystem) Update(w ecs.World) {
"SectionFault", sectionFault, // data := entity.GetWorldData(w)
"Occ", sectionState.Occ, // s.query.Each(w, func(entry *ecs.Entry) {
"Count", axleDevice.Count, // faDcDevice := component.AxleManageDeviceType.Get(entry)
"Wave", axleDevice.ShowCountWave()) // for axleSectionId, axleRuntime := range faDcDevice.Adrs {
} // axleSectionEntry := data.EntityMap[axleSectionId]
} // sectionState := component.PhysicalSectionStateType.Get(axleSectionEntry)
}) // axleDevice := component.AxlePhysicalSectionType.Get(axleSectionEntry)
} // //
// sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
// 计算计轴区段状态 // s.calculateHf(sectionFault, axleSectionEntry, sectionState, axleDevice, axleRuntime)
func (s *FaDcAxleDeviceSystem) calculateSectionState(sectionFault bool, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) { // s.calculateDrst(axleSectionEntry, sectionState, axleDevice, axleRuntime)
sectionState.Occ = axleDevice.Count > 0 || sectionFault // s.calculatePdrst(axleSectionEntry, sectionState, axleDevice, axleRuntime)
} // s.calculateSectionState(sectionFault, sectionState, axleDevice, axleRuntime)
// if axleSectionEntry.HasComponent(component.PhysicalSectionCircuitType) {
// 计轴直接复位 // sectionCircuit := component.PhysicalSectionCircuitType.Get(axleSectionEntry)
func (s *FaDcAxleDeviceSystem) calculateDrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) { // relayDrive := component.RelayDriveType.Get(sectionCircuit.GJ)
isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) // relayDrive.Td = !sectionState.Occ
if axleRuntime.Drst && !axleRuntime.Rjo && !axleRuntime.Rjt && isFault { //直接复位且没有拒绝原因 // }
axleDevice.UpdateCount(0) //
axleDevice.ResetCountPulse() // if "北京_12_酒仙桥_15G" == axleSectionId && false {
axleRuntime.DoingPdrst = false // sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
//清除故障 // slog.Info(axleSectionId,
if axleSectionEntry.HasComponent(component.AxleSectionFaultTag) { // "Drst", axleRuntime.Drst,
axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag) // "PDRST", axleRuntime.Pdrst,
} // "DoingPdrst", axleRuntime.DoingPdrst,
} // "RAC", axleRuntime.Rac,
} // "RJO", axleRuntime.Rjo,
// "RJT", axleRuntime.Rjt,
// 计轴预复位 // "SectionFault", sectionFault,
func (s *FaDcAxleDeviceSystem) calculatePdrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) { // "Occ", sectionState.Occ,
isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) // "Count", axleDevice.Count,
if axleRuntime.Pdrst && !axleRuntime.Rjo && !axleRuntime.Rjt && !axleRuntime.DoingPdrst && isFault { //预复位且没有拒绝原因 // "Wave", axleDevice.ShowCountWave())
axleDevice.UpdateCount(0) // }
axleDevice.ResetCountPulse() // }
axleRuntime.DoingPdrst = true // })
} //}
//压道车通过该计轴区段,完成计轴预复位 //
if axleRuntime.DoingPdrst && isFault && axleDevice.IsCount010Pulse() { //// 计算计轴区段状态
axleRuntime.DoingPdrst = false //func (s *FaDcAxleDeviceSystem) calculateSectionState(sectionFault bool, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
//清除故障 // sectionState.Occ = axleDevice.Count > 0 || sectionFault
axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag) //}
} //
} //// 计轴直接复位
//func (s *FaDcAxleDeviceSystem) calculateDrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
// 复位回复运算 // isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
func (s *FaDcAxleDeviceSystem) calculateHf(sectionFault bool, axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) { // if axleRuntime.Drst && !axleRuntime.Rjo && !axleRuntime.Rjt && isFault { //直接复位且没有拒绝原因
axleRuntime.Rac = axleRuntime.Drst || axleRuntime.Pdrst // axleDevice.UpdateCount(0)
axleRuntime.Rjo = axleRuntime.Rac && !sectionState.Occ && !axleRuntime.DoingPdrst //空闲拒绝复位(排除预复位过程中) // axleDevice.ResetCountPulse()
axleRuntime.Rjt = false // 技术原因拒绝复位 // axleRuntime.DoingPdrst = false
} // //清除故障
// if axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
// axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag)
// }
// }
//}
//
//// 计轴预复位
//func (s *FaDcAxleDeviceSystem) calculatePdrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
// isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag)
// if axleRuntime.Pdrst && !axleRuntime.Rjo && !axleRuntime.Rjt && !axleRuntime.DoingPdrst && isFault { //预复位且没有拒绝原因
// axleDevice.UpdateCount(0)
// axleDevice.ResetCountPulse()
// axleRuntime.DoingPdrst = true
// }
// //压道车通过该计轴区段,完成计轴预复位
// if axleRuntime.DoingPdrst && isFault && axleDevice.IsCount010Pulse() {
// axleRuntime.DoingPdrst = false
// //清除故障
// axleSectionEntry.RemoveComponent(component.AxleSectionFaultTag)
// }
//}
//
//// 复位回复运算
//func (s *FaDcAxleDeviceSystem) calculateHf(sectionFault bool, axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) {
// axleRuntime.Rac = axleRuntime.Drst || axleRuntime.Pdrst
// axleRuntime.Rjo = axleRuntime.Rac && !sectionState.Occ && !axleRuntime.DoingPdrst //空闲拒绝复位(排除预复位过程中)
// axleRuntime.Rjt = false // 技术原因拒绝复位
//}

View File

@ -2,68 +2,67 @@ package device_sys
import ( import (
"fmt" "fmt"
"log/slog"
"strings"
"joylink.club/ecs" "joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity" "joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/repository" "joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto" "joylink.club/rtsssimulation/repository/model/proto"
"log/slog"
"strings"
) )
// SectionDetectSystem 区段检测系统 //// SectionDetectSystem 区段检测系统
type SectionDetectSystem struct { //type SectionDetectSystem struct {
trainQuery *ecs.Query // trainQuery *ecs.Query
axleSectionQuery *ecs.Query // axleSectionQuery *ecs.Query
} //}
//
//func NewSectionDetectSystem() *SectionDetectSystem {
// return &SectionDetectSystem{trainQuery: ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType)),
// axleSectionQuery: ecs.NewQuery(filter.Contains(component.UidType, component.AxlePhysicalSectionType))}
//}
//func (s *SectionDetectSystem) Update(w ecs.World) {
// //key-sectionId,统计区段上有车的情况
// sectionTrainMap := make(map[string]*trainCount)
// //所有列车
// s.trainQuery.Each(w, func(entry *ecs.Entry) {
// tp := component.TrainPositionInfoType.Get(entry)
// //fmt.Println("============>>>>>>列车位置信息:", tp.ToString())
// trainSectionIds := DoSearchTrainOccupiedSections(w, tp)
// //fmt.Println("============>>>>>>列车所在物理区段:", trainSectionIds)
// for _, sectionId := range trainSectionIds { //车所在区段
// tc, find := sectionTrainMap[sectionId]
// if !find {
// tc = newTrainCount()
// sectionTrainMap[sectionId] = tc
// }
// tc.add()
// }
// })
// //计轴区段
// s.axleSectionQuery.Each(w, func(entry *ecs.Entry) {
// axleSectionId := component.UidType.Get(entry).Id
// axleSection := component.AxlePhysicalSectionType.Get(entry)
// tc, find := sectionTrainMap[axleSectionId]
// if find {
// axleSection.UpdateCount(int(tc.count))
// } else {
// axleSection.UpdateCount(0)
// }
// })
//}
//
//type trainCount struct {
// count int8
//}
//
//func newTrainCount() *trainCount {
// return &trainCount{count: 0}
//}
//func (c *trainCount) add() {
// c.count++
//}
func NewSectionDetectSystem() *SectionDetectSystem {
return &SectionDetectSystem{trainQuery: ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType)),
axleSectionQuery: ecs.NewQuery(filter.Contains(component.UidType, component.AxlePhysicalSectionType))}
}
func (s *SectionDetectSystem) Update(w ecs.World) {
//key-sectionId,统计区段上有车的情况
sectionTrainMap := make(map[string]*trainCount)
//所有列车
s.trainQuery.Each(w, func(entry *ecs.Entry) {
tp := component.TrainPositionInfoType.Get(entry)
//fmt.Println("============>>>>>>列车位置信息:", tp.ToString())
trainSectionIds := DoSearchTrainOccupiedSections(w, tp)
//fmt.Println("============>>>>>>列车所在物理区段:", trainSectionIds)
for _, sectionId := range trainSectionIds { //车所在区段
tc, find := sectionTrainMap[sectionId]
if !find {
tc = newTrainCount()
sectionTrainMap[sectionId] = tc
}
tc.add()
}
})
//计轴区段
s.axleSectionQuery.Each(w, func(entry *ecs.Entry) {
axleSectionId := component.UidType.Get(entry).Id
axleSection := component.AxlePhysicalSectionType.Get(entry)
tc, find := sectionTrainMap[axleSectionId]
if find {
axleSection.UpdateCount(int(tc.count))
} else {
axleSection.UpdateCount(0)
}
})
}
type trainCount struct {
count int8
}
func newTrainCount() *trainCount {
return &trainCount{count: 0}
}
func (c *trainCount) add() {
c.count++
}
func DoSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo) []string { func DoSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo) []string {
wd := entity.GetWorldData(w) wd := entity.GetWorldData(w)
curLink := wd.Repo.FindLink(tp.HeadLink) curLink := wd.Repo.FindLink(tp.HeadLink)
@ -80,8 +79,7 @@ func DoSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo)
return stp.trainSections() return stp.trainSections()
} }
///////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////
type stpContext struct { type stpContext struct {
w ecs.World w ecs.World
trainLen int64 //列车长度 trainLen int64 //列车长度