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

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 { //var (
//计轴区段内车轴数 // PhysicalSectionCircuitType = ecs.NewComponentType[PhysicalSectionCircuit]()
Count int //)
//记录Count变化波形 //
countPulse uint8 //type PhysicalSectionCircuit struct {
} // GJ *ecs.Entry
type AxleDeviceRuntime struct { //}
//true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。 //
Rac bool //// PhysicalSectionState 物理区段
//true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。 //type PhysicalSectionState struct {
Rjo bool // //true-占用false-出清
//true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等 // Occ bool
Rjt bool //}
//true-计轴直接复位 //
//计轴的轮对计数清零,区段转换为空闲状态 //// AxlePhysicalSection 计轴物理区段
Drst bool //type AxlePhysicalSection struct {
//true-计轴预复位 // //计轴区段内车轴数
//将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态 // Count int
Pdrst bool // //记录Count变化波形
//true-计轴系统正在执行直接预复位操作 // countPulse uint8
DoingPdrst bool //}
} //type AxleDeviceRuntime struct {
// //true-计轴复位反馈,表示计轴设备已收到CI系统发送的直接复零/预复零命令。
func NewAxleDeviceRuntime() *AxleDeviceRuntime { // RAC bool
return &AxleDeviceRuntime{} // //true-运营原因拒绝计轴复位,如区段空闲时下发复位命令;或车轮压住传感器时收到复位命令。
} // RJO bool
// //true-技术原因拒绝计轴复位,主要指计轴相关设备故障时收到复位命令如车轮传感器的导线断开、AEB之间的通信故障等
// AxleManageDevice 计轴管理设备 // RJT bool
type AxleManageDevice struct { // //true-计轴直接复位
CentralizedStation string //所属集中站编号code // //计轴的轮对计数清零,区段转换为空闲状态
Adrs map[string]*AxleDeviceRuntime //key-sectionId // Drst bool
} // //true-计轴预复位
// //将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态
func (d *AxleManageDevice) FindAdr(sectionId string) *AxleDeviceRuntime { // PDRST bool
return d.Adrs[sectionId] // //true-计轴系统正在执行直接预复位操作
} // DoingPdrst bool
func NewAxleManageDevice(centralizedStation string) *AxleManageDevice { //}
return &AxleManageDevice{CentralizedStation: centralizedStation, Adrs: make(map[string]*AxleDeviceRuntime)} //
} //func NewAxleDeviceRuntime() *AxleDeviceRuntime {
// return &AxleDeviceRuntime{}
var ( //}
PhysicalSectionStateType = ecs.NewComponentType[PhysicalSectionState]() //
AxlePhysicalSectionType = ecs.NewComponentType[AxlePhysicalSection]() //// AxleManageDevice 计轴管理设备
AxleSectionFaultTag = ecs.NewTag() //type AxleManageDevice struct {
AxleManageDeviceType = ecs.NewComponentType[AxleManageDevice]() // CentralizedStation string //所属集中站编号code
) // Adrs map[string]*AxleDeviceRuntime //key-sectionId
//}
/////////////////////////////AxlePhysicalSection///////////////////////////////// //
//func (d *AxleManageDevice) FindAdr(sectionId string) *AxleDeviceRuntime {
func NewAxlePhysicalSection() *AxlePhysicalSection { // return d.Adrs[sectionId]
return &AxlePhysicalSection{Count: 0, countPulse: 0} //}
} //func NewAxleManageDevice(centralizedStation string) *AxleManageDevice {
func (c *AxlePhysicalSection) UpdateCount(count int) { // return &AxleManageDevice{CentralizedStation: centralizedStation, Adrs: make(map[string]*AxleDeviceRuntime)}
cp := to1(c.Count) //}
np := to1(count) //
// //var (
if cp != np { // PhysicalSectionStateType = ecs.NewComponentType[PhysicalSectionState]()
c.countPulse <<= 1 // AxlePhysicalSectionType = ecs.NewComponentType[AxlePhysicalSection]()
if np > 0 { // AxleSectionFaultTag = ecs.NewTag()
c.countPulse |= np // AxleManageDeviceType = ecs.NewComponentType[AxleManageDevice]()
} //)
} //
c.Count = count ///////////////////////////////AxlePhysicalSection/////////////////////////////////
} //
func (c *AxlePhysicalSection) ResetCountPulse() { //func NewAxlePhysicalSection() *AxlePhysicalSection {
c.countPulse = 0x00 // return &AxlePhysicalSection{Count: 0, countPulse: 0}
} //}
func (c *AxlePhysicalSection) ShowCountWave() string { //func (c *AxlePhysicalSection) UpdateCount(count int) {
return fmt.Sprintf("%08b", c.countPulse) // cp := to1(c.Count)
} // np := to1(count)
// //
// IsCount010Pulse true-车进入计轴区段后出清计轴区段 // if cp != np {
func (c *AxlePhysicalSection) IsCount010Pulse() bool { // c.countPulse <<= 1
return c.countPulse&0x01 == 0 && c.countPulse&0x02 > 0 && c.countPulse&0x04 == 0 // if np > 0 {
} // c.countPulse |= np
// }
// 归1 // }
func to1(c int) uint8 { // c.Count = count
if c > 0 { //}
return 0x01 //func (c *AxlePhysicalSection) ResetCountPulse() {
} else { // c.countPulse = 0x00
return 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)
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
}
// AxleSectionPdrstDrive 计轴预复位操作
// //
// set : true-设置false-取消 // "joylink.club/ecs"
func AxleSectionPdrstDrive(w ecs.World, sectionId string, set bool) error { // "joylink.club/rtsssimulation/component"
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] { // "joylink.club/rtsssimulation/entity"
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, 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
}
// AxleSectionFaultOccDrive 区段故障占用设置
// //
// set : true - 设置故障占用false - 取消故障占用 //// AxleSectionDrstDrive 计轴直接复位操作
func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error { ////
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] { //// set : true-设置false-取消
wd := entity.GetWorldData(w) //func AxleSectionDrstDrive(w ecs.World, sectionId string, set bool) error {
sectionModel := wd.Repo.FindPhysicalSection(sectionId) // r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
if sectionModel == nil { // wd := entity.GetWorldData(w)
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId)) // //
} // sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// // if sectionModel == nil {
sectionEntry := wd.EntityMap[sectionId] // return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
if sectionEntry == nil { // }
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId)) // // if set {
} // // axleSectionEntry := wd.EntityMap[sectionId]
if set { //计轴故障设置 // // if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
if !sectionEntry.HasComponent(component.AxleSectionFaultTag) { // // return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
sectionEntry.AddComponent(component.AxleSectionFaultTag) // // }
} // // }
} else { //计轴故障取消 // //
if sectionEntry.HasComponent(component.AxleSectionFaultTag) { // faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
sectionEntry.RemoveComponent(component.AxleSectionFaultTag)
}
}
//
return ecs.NewOkEmptyResult()
})
return r.Err
}
// AxleSectionTrainDrive 计轴区段内车进入出清设置
// //
// trainIn : true - 计轴区段内有车false-计轴区段出清 // if faDcAxleDeviceEntry == nil {
func AxleSectionTrainDrive(w ecs.World, sectionId string, trainIn bool) error { // return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] { // }
wd := entity.GetWorldData(w) // faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
sectionModel := wd.Repo.FindPhysicalSection(sectionId) // axleRuntime := faDcAxleDevice.FindAdr(sectionId)
if sectionModel == nil { // if axleRuntime == nil {
return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId)) // return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
} // }
// // axleRuntime.Drst = set
sectionEntry := wd.EntityMap[sectionId] // //
if sectionEntry == nil { // return ecs.NewOkEmptyResult()
return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId)) // })
} // return r.Err
axleDevice := component.AxlePhysicalSectionType.Get(sectionEntry) //}
if trainIn { //
axleDevice.UpdateCount(1) //// AxleSectionPdrstDrive 计轴预复位操作
} else { ////
axleDevice.UpdateCount(0) //// set : true-设置false-取消
} //func AxleSectionPdrstDrive(w ecs.World, sectionId string, set bool) error {
// // r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
return ecs.NewOkEmptyResult() // wd := entity.GetWorldData(w)
}) // sectionModel := wd.Repo.FindPhysicalSection(sectionId)
return r.Err // if sectionModel == nil {
} // return ecs.NewErrResult(fmt.Errorf("区段模型[%s]不存实体", sectionId))
// }
// FindAxleSectionsStatus 获取计轴区段的相关状态 // // if set {
func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) { // // axleSectionEntry := wd.EntityMap[sectionId]
r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] { // // if !axleSectionEntry.HasComponent(component.AxleSectionFaultTag) {
wd := entity.GetWorldData(w) // // return ecs.NewErrResult(fmt.Errorf("区段[%s]非故障占用,无法进行复位操作", sectionId))
var msg []*AxleSectionState // // }
var esb = strings.Builder{} //收集未找到的区段的id // // }
for _, sectionId := range sectionIds { // //
find := false // faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
sectionModel := wd.Repo.FindPhysicalSection(sectionId) //
if sectionModel != nil { // if faDcAxleDeviceEntry == nil {
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation()) // return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]实体不存在", sectionModel.CentralizedStation()))
if faDcAxleDeviceEntry != nil { // }
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry) // faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
axleDevice := faDcAxleDevice.FindAdr(sectionId) // axleRuntime, ok := faDcAxleDevice.Adrs[sectionId]
if axleDevice != nil { // if !ok {
sectionEntry, _ := entity.GetEntityByUid(w, sectionId) // return ecs.NewErrResult(fmt.Errorf("计轴管理设备[%s]中不存在区段[%s]的计轴设备", sectionModel.CentralizedStation(), sectionId))
if sectionEntry != nil { // }
if sectionEntry.HasComponent(component.AxlePhysicalSectionType) { //计轴物理区段实体 // axleRuntime.Pdrst = set
as := &AxleSectionState{} // //
state := component.PhysicalSectionStateType.Get(sectionEntry) // return ecs.NewOkEmptyResult()
as.Id = component.UidType.Get(sectionEntry).Id // })
as.Clr = !state.Occ // return r.Err
as.Occ = state.Occ //}
as.Rac = axleDevice.Rac //
as.Rjt = axleDevice.Rjt //// AxleSectionFaultOccDrive 区段故障占用设置
as.Rjo = axleDevice.Rjo ////
// //// set : true - 设置故障占用false - 取消故障占用
msg = append(msg, as) //func AxleSectionFaultOccDrive(w ecs.World, sectionId string, set bool) error {
find = true // 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 !find { // sectionEntry := wd.EntityMap[sectionId]
esb.WriteString(fmt.Sprintf("%s,", sectionId)) // if sectionEntry == nil {
} // return ecs.NewErrResult(fmt.Errorf("区段[%s]实体不存在", sectionId))
} //for // }
if esb.Len() > 0 { // if set { //计轴故障设置
return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String())) // if !sectionEntry.HasComponent(component.AxleSectionFaultTag) {
} else { // sectionEntry.AddComponent(component.AxleSectionFaultTag)
return ecs.NewResult(msg, nil) // }
} // } else { //计轴故障取消
}) // if sectionEntry.HasComponent(component.AxleSectionFaultTag) {
return r.Val, r.Err // sectionEntry.RemoveComponent(component.AxleSectionFaultTag)
} // }
// }
type AxleSectionState struct { // //
//uid // return ecs.NewOkEmptyResult()
Id string // })
//0-bit7 计轴出清 // return r.Err
Clr bool //}
//0-bit6 计轴占用 //
Occ bool //// FindAxleSectionsStatus 获取计轴区段的相关状态
//1-bit6 计轴复位反馈 //func FindAxleSectionsStatus(w ecs.World, sectionIds []string) ([]*AxleSectionState, error) {
Rac bool // r := <-ecs.Request[[]*AxleSectionState](w, func() ecs.Result[[]*AxleSectionState] {
//1-bit5 运营原因拒绝计轴复位 // wd := entity.GetWorldData(w)
Rjo bool // var msg []*AxleSectionState
//1-bit4 技术原因拒绝计轴复位 // var esb = strings.Builder{} //收集未找到的区段的id
Rjt bool // for _, sectionId := range sectionIds {
} // find := false
// sectionModel := wd.Repo.FindPhysicalSection(sectionId)
// AxleSectionRstDrive 复位(直接复位、预复位) // if sectionModel != nil {
func AxleSectionRstDrive(w ecs.World, cmds []*AxleSectionCmd) error { // faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
r := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] { // if faDcAxleDeviceEntry != nil {
wd := entity.GetWorldData(w) // faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
var esb = strings.Builder{} //收集未找到的区段的id // axleDevice := faDcAxleDevice.FindAdr(sectionId)
find := false // if axleDevice != nil {
for _, cmd := range cmds { // sectionEntry, _ := entity.GetEntityByUid(w, sectionId)
sectionId := cmd.SectionId // if sectionEntry != nil {
sectionModel := wd.Repo.FindPhysicalSection(sectionId) // if sectionEntry.HasComponent(component.AxlePhysicalSectionType) { //计轴物理区段实体
if sectionModel != nil { // as := &AxleSectionState{}
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation()) // state := component.PhysicalSectionStateType.Get(sectionEntry)
if faDcAxleDeviceEntry != nil { // as.Id = component.UidType.Get(sectionEntry).Id
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry) // as.Clr = !state.Occ
axleRuntime := faDcAxleDevice.FindAdr(sectionId) // as.Occ = state.Occ
if axleRuntime != nil { // as.Rac = axleDevice.Rac
axleRuntime.Pdrst = cmd.Pdrst // as.Rjt = axleDevice.Rjt
axleRuntime.Drst = cmd.Drst // as.Rjo = axleDevice.Rjo
find = true // //
} // msg = append(msg, as)
} // find = true
} // }
if !find { // }
esb.WriteString(fmt.Sprintf("%s,", sectionId)) // }
} // }
} //for // }
if esb.Len() > 0 { // //
return ecs.NewErrResult(fmt.Errorf("计轴区段复位操作,失败列表[%s]", esb.String())) // if !find {
} else { // esb.WriteString(fmt.Sprintf("%s,", sectionId))
return ecs.NewOkEmptyResult() // }
} // } //for
}) // if esb.Len() > 0 {
return r.Err // return ecs.NewResult(msg, fmt.Errorf("区段非计轴区段或计轴区段状态不存在:[%s]", esb.String()))
} // } else {
// return ecs.NewResult(msg, nil)
type AxleSectionCmd struct { // }
SectionId string // })
Drst bool // return r.Val, r.Err
Pdrst bool //}
} //
//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

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