From 3182e867c12d73bd4c75182459d3b9fae670653c Mon Sep 17 00:00:00 2001 From: thesai <1021828630@qq.com> Date: Wed, 31 Jul 2024 17:08:53 +0800 Subject: [PATCH] =?UTF-8?q?[=E9=87=8D=E5=86=99]=E8=AE=A1=E8=BD=B4=E7=9A=84?= =?UTF-8?q?=E7=BB=84=E4=BB=B6=E3=80=81=E5=AE=9E=E4=BD=93=E3=80=81=E7=B3=BB?= =?UTF-8?q?=E7=BB=9F=E3=80=81=E9=A2=84=E5=A4=8D=E4=BD=8D/=E5=A4=8D?= =?UTF-8?q?=E4=BD=8D=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- component/axle_section.go | 229 ++++++++-------- component/train.go | 10 + entity/axle_section.go | 73 ++--- entity/balise.go | 5 +- fi/axle_section.go | 120 +++++++++ fi/section.go | 400 ++++++++++++---------------- repository/check_point.go | 8 +- repository/link.go | 14 +- repository/model.go | 7 + repository/repository_manager.go | 17 +- repository/signal.go | 22 +- repository/transponder.go | 6 +- sys/bind.go | 5 +- sys/device_sys/axle_section.go | 57 ++++ sys/device_sys/fadc_axle_device.go | 197 +++++++------- sys/device_sys/section_detection.go | 110 ++++---- 16 files changed, 694 insertions(+), 586 deletions(-) create mode 100644 fi/axle_section.go create mode 100644 sys/device_sys/axle_section.go diff --git a/component/axle_section.go b/component/axle_section.go index 62383b3..60b7a31 100644 --- a/component/axle_section.go +++ b/component/axle_section.go @@ -1,113 +1,134 @@ package component -import ( - "fmt" - "joylink.club/ecs" -) - -//计轴设备,管理联锁集中站内的所有计轴区段 -//计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态 -//计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态 -// -//当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。 -//当RAC,RJO,RJT任意一个不为0时,终止发送复零/预复零命令。 +import "joylink.club/ecs" 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 } -// PhysicalSectionState 物理区段 -type PhysicalSectionState struct { - //true-占用,false-出清 - Occ bool -} - -// 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 { - 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 - } -} +////计轴设备,管理联锁集中站内的所有计轴区段 +////计轴直接复位:计轴的轮对计数清零,区段转换为空闲状态 +////计轴预复位:将计轴的轮对计数清零,但是区段不会立即变成空闲区段,而是处于一种“占用”状态,在压道车通过之后确认区段空闲且计轴正常后,区段转换为空闲状态 +//// +////当CI系统给计轴设备发送计轴直接复零/预复零命令时,连续发送一定时间(具体发送时间调试后确定)的复零/预复零命令。 +////当RAC,RJO,RJT任意一个不为0时,终止发送复零/预复零命令。 +// +//var ( +// PhysicalSectionCircuitType = ecs.NewComponentType[PhysicalSectionCircuit]() +//) +// +//type PhysicalSectionCircuit struct { +// GJ *ecs.Entry +//} +// +//// PhysicalSectionState 物理区段 +//type PhysicalSectionState struct { +// //true-占用,false-出清 +// Occ bool +//} +// +//// 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 { +// 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 +// } +//} diff --git a/component/train.go b/component/train.go index b3a91c2..6be013c 100644 --- a/component/train.go +++ b/component/train.go @@ -12,6 +12,7 @@ type TrainPositionInfo struct { Up bool //列车长度 mm Len int64 + //列车所在轨道link HeadLink string //列车所在link偏移量(mm) @@ -20,6 +21,15 @@ type TrainPositionInfo struct { TailLink string //列车所在link偏移量(mm) TailLinkOffset int64 + + //车头所在物理区段 + HeadSectionId string + //车头所在物理区段偏移量 + HeadSectionOffset uint32 + //车尾所在物理区段 + TailSectionId string + //车尾所在物理区段偏移量 + TailSectionOffset uint32 } func (t *TrainPositionInfo) ToString() string { diff --git a/entity/axle_section.go b/entity/axle_section.go index 21a7255..543cbc4 100644 --- a/entity/axle_section.go +++ b/entity/axle_section.go @@ -1,75 +1,34 @@ package entity import ( - "fmt" "joylink.club/ecs" "joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/repository" - "strings" "unsafe" ) -func newAxleManageDevice(w ecs.World, data *component.WorldData, centralizedStation string) *ecs.Entry { - entry := w.Entry(w.Create(component.AxleManageDeviceType)) - component.AxleManageDeviceType.Set(entry, component.NewAxleManageDevice(centralizedStation)) - data.AxleManageDeviceEntities = append(data.AxleManageDeviceEntities, entry) - return entry -} +var AxleSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.AxleSectionTag, component.AxleManagerType} // LoadAxlePhysicalSections 加载计轴区段 func LoadAxlePhysicalSections(w ecs.World) error { - data := GetWorldData(w) - sections := data.Repo.PhysicalSectionList() + wd := GetWorldData(w) + sections := wd.Repo.PhysicalSectionList() for _, section := range sections { - if is, se := section.IsAxleSection(); se == nil && is { - if len(strings.TrimSpace(section.CentralizedStation())) == 0 { - return fmt.Errorf("区段[%s]未设置所属集中站", section.Id()) - } - 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() { - if ec.Code() == "GJ" { - relay := ec.(*repository.Relay) - gjEntry := NewRelayEntity(w, relay, worldData.EntityMap) - circuit := &component.PhysicalSectionCircuit{GJ: gjEntry} - entry.AddComponent(component.PhysicalSectionCircuitType, unsafe.Pointer(circuit)) + if is, err := section.IsAxleSection(); err == nil && is { + entry := w.Entry(w.Create(AxleSectionBaseComponentTypes...)) + component.UidType.SetValue(entry, component.Uid{Id: section.Id()}) + for _, group := range section.ComponentGroups() { + for _, ec := range group.Components() { + if ec.Code() == "GJ" { + relay := ec.(*repository.Relay) + gjEntry := NewRelayEntity(w, relay, wd.EntityMap) + circuit := &component.AxleSectionCircuit{GJ: gjEntry} + entry.AddComponent(component.AxleSectionCircuitType, unsafe.Pointer(circuit)) + } } } + wd.EntityMap[section.Id()] = entry } - worldData.EntityMap[uid] = entry } - return entry + return nil } diff --git a/entity/balise.go b/entity/balise.go index 7c753aa..1b117a8 100644 --- a/entity/balise.go +++ b/entity/balise.go @@ -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() { entry.AddComponent(component.BaliseVariableTelegramType) } + linkPosition := td.LinkPosition() component.LinkPositionType.SetValue(entry, component_data.LinkPosition{ - LinkId: td.LinkPosition().Link().Id(), - Offset: td.LinkPosition().Offset(), + LinkId: linkPosition.Link().Id(), + Offset: linkPosition.Offset(), }) component.KmType.Set(entry, td.Km()) worldData.EntityMap[uid] = entry diff --git a/fi/axle_section.go b/fi/axle_section.go new file mode 100644 index 0000000..2596c84 --- /dev/null +++ b/fi/axle_section.go @@ -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 +} diff --git a/fi/section.go b/fi/section.go index 1193eb7..1f9fe53 100644 --- a/fi/section.go +++ b/fi/section.go @@ -1,239 +1,173 @@ package fi -import ( - "fmt" - "strings" - - "joylink.club/ecs" - "joylink.club/rtsssimulation/component" - "joylink.club/rtsssimulation/entity" -) - -// AxleSectionDrstDrive 计轴直接复位操作 // -// 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 -} - -// AxleSectionPdrstDrive 计轴预复位操作 +//import ( +// "fmt" +// "strings" // -// 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)) - // } - // } - // - 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 区段故障占用设置 +// "joylink.club/ecs" +// "joylink.club/rtsssimulation/component" +// "joylink.club/rtsssimulation/entity" +//) // -// set : true - 设置故障占用;false - 取消故障占用 -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.AxleSectionFaultTag) { - sectionEntry.AddComponent(component.AxleSectionFaultTag) - } - } else { //计轴故障取消 - if sectionEntry.HasComponent(component.AxleSectionFaultTag) { - sectionEntry.RemoveComponent(component.AxleSectionFaultTag) - } - } - // - return ecs.NewOkEmptyResult() - }) - return r.Err -} - -// AxleSectionTrainDrive 计轴区段内车进入出清设置 +//// AxleSectionDrstDrive 计轴直接复位操作 +//// +//// 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()) // -// 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 -} +// 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-取消 +//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)) +// // } +// // } +// // +// 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 - 取消故障占用 +//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.AxleSectionFaultTag) { +// sectionEntry.AddComponent(component.AxleSectionFaultTag) +// } +// } else { //计轴故障取消 +// if sectionEntry.HasComponent(component.AxleSectionFaultTag) { +// sectionEntry.RemoveComponent(component.AxleSectionFaultTag) +// } +// } +// // +// 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 +//} diff --git a/repository/check_point.go b/repository/check_point.go index 40a2aa0..be3edc0 100644 --- a/repository/check_point.go +++ b/repository/check_point.go @@ -9,7 +9,7 @@ type CheckPoint struct { km *proto.Kilometer pointType proto.CheckPointType //检测点类型 devicePorts []DevicePort //检测点关联的设备及其端口 - linkPosition *LinkPosition + linkPosition LinkPosition } 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) { c.devicePorts = append(c.devicePorts, devicePort) } -func (c *CheckPoint) bindLinkPosition(position *LinkPosition) { +func (c *CheckPoint) bindLinkPosition(position LinkPosition) { c.linkPosition = position } diff --git a/repository/link.go b/repository/link.go index 40f0c47..2d15113 100644 --- a/repository/link.go +++ b/repository/link.go @@ -18,8 +18,8 @@ type Link struct { aKm *proto.Kilometer bKm *proto.Kilometer - //Link上的模型((非区段边界)检测点、应答器、信号机) - devices []Identity + //按偏移量小到大排序的、此Link上的模型((非区段边界)检测点、应答器、信号机) + devices []LinkPositionDevice ////Link关联的模型,包含LinkNode //devicePositions []*DeviceLinkPosition @@ -59,7 +59,7 @@ func (l *Link) BRelation() *TurnoutPort { return l.bRelation } -func (l *Link) Devices() []Identity { +func (l *Link) Devices() []LinkPositionDevice { 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 { l.devices = append(l.devices, device) } @@ -138,15 +138,15 @@ type LinkPosition struct { func NewLinkPosition(link *Link, offset int64) *LinkPosition { return &LinkPosition{link: link, offset: offset} } -func (l *LinkPosition) Link() *Link { +func (l LinkPosition) Link() *Link { return l.link } -func (l *LinkPosition) Offset() int64 { +func (l LinkPosition) Offset() int64 { return l.offset } -func (l *LinkPosition) String() string { +func (l LinkPosition) String() string { return fmt.Sprintf("[LinkPosition:{%s-%d]", l.link.Id(), l.offset) } diff --git a/repository/model.go b/repository/model.go index 4e0c6ed..0ba8b41 100644 --- a/repository/model.go +++ b/repository/model.go @@ -22,6 +22,13 @@ func (m identity) Type() proto.DeviceType { return m.deviceType } +// LinkPositionDevice 有link位置的设备 +type LinkPositionDevice interface { + Identity + LinkPosition() LinkPosition + bindLinkPosition(position LinkPosition) +} + //////////////////////////system中使用/////////////////////////////////// // IRelayCRole 获取继电器在具体电路中的角色(组合类型、功能名称) diff --git a/repository/repository_manager.go b/repository/repository_manager.go index 25dda0d..acb4bc0 100644 --- a/repository/repository_manager.go +++ b/repository/repository_manager.go @@ -836,6 +836,10 @@ func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer if visitedModelMap[device.Id()] { continue } + linkPositionDevice, ok := device.(LinkPositionDevice) + if !ok { + return fmt.Errorf("device [%s:%s] not implements LinkPositionDevice", device.Id(), device.Type().String()) + } km := findModelKm(device) if km == nil || km.CoordinateSystem == "" { continue @@ -845,19 +849,12 @@ func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer return err } offset := int64(math.Abs(float64(convertedKm.Value - startKm.Value))) - linkPosition := &LinkPosition{ + linkPosition := LinkPosition{ link: link, offset: offset, } - switch device.Type() { - case proto.DeviceType_DeviceType_CheckPoint: - 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) + linkPositionDevice.bindLinkPosition(linkPosition) + link.bindDevices(linkPositionDevice) } return nil } diff --git a/repository/signal.go b/repository/signal.go index 8ab2135..e85b9d0 100644 --- a/repository/signal.go +++ b/repository/signal.go @@ -8,7 +8,7 @@ type Signal struct { km *proto.Kilometer //section *PhysicalSection //turnoutPort TurnoutPort - linkPosition *LinkPosition + linkPosition LinkPosition //信号机电路系统电子元器件 componentGroups []*ElectronicComponentGroup 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 { return s.componentGroups } + func (s *Signal) Code() string { return s.code } func (s *Signal) Model() proto.Signal_Model { return s.model } + +func (s *Signal) LinkPosition() LinkPosition { + return s.linkPosition +} + +func (s *Signal) bindLinkPosition(position LinkPosition) { + s.linkPosition = position +} diff --git a/repository/transponder.go b/repository/transponder.go index 4cd196c..a429b4c 100644 --- a/repository/transponder.go +++ b/repository/transponder.go @@ -8,7 +8,7 @@ type Transponder struct { km *proto.Kilometer //section *PhysicalSection //turnoutPort TurnoutPort - linkPosition *LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取 + linkPosition LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取 fixedTelegram []byte //应答器固定报文 fixedUserTelegram []byte //应答器固定用户报文 baliseType proto.Transponder_Type //应答器类型 @@ -38,10 +38,10 @@ func (t *Transponder) FixedTelegram() []byte { func (t *Transponder) FixedUserTelegram() []byte { return t.fixedUserTelegram } -func (t *Transponder) bindLinkPosition(position *LinkPosition) { +func (t *Transponder) bindLinkPosition(position LinkPosition) { t.linkPosition = position } -func (t *Transponder) LinkPosition() *LinkPosition { +func (t *Transponder) LinkPosition() LinkPosition { return t.linkPosition } diff --git a/sys/bind.go b/sys/bind.go index b936c1e..0a7dd73 100644 --- a/sys/bind.go +++ b/sys/bind.go @@ -39,8 +39,9 @@ func BindSystem(w ecs.World) { circuit_sys.NewIBPSys(), device_sys.NewAlarmSys(), //物理区段 - device_sys.NewFaDcAxleDeviceSystem(), - device_sys.NewSectionDetectSystem(), + //device_sys.NewFaDcAxleDeviceSystem(), + //device_sys.NewSectionDetectSystem(), + device_sys.NewAxleSectionSystem(), //应答器 device_sys.NewBaliseSystem(), //电机 diff --git a/sys/device_sys/axle_section.go b/sys/device_sys/axle_section.go new file mode 100644 index 0000000..ebafec9 --- /dev/null +++ b/sys/device_sys/axle_section.go @@ -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 + } + }) +} diff --git a/sys/device_sys/fadc_axle_device.go b/sys/device_sys/fadc_axle_device.go index fe243ee..2e897d0 100644 --- a/sys/device_sys/fadc_axle_device.go +++ b/sys/device_sys/fadc_axle_device.go @@ -1,100 +1,101 @@ 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) - s.calculateHf(sectionFault, axleSectionEntry, sectionState, axleDevice, axleRuntime) - s.calculateDrst(axleSectionEntry, sectionState, axleDevice, axleRuntime) - s.calculatePdrst(axleSectionEntry, sectionState, axleDevice, axleRuntime) - s.calculateSectionState(sectionFault, sectionState, axleDevice, axleRuntime) - if axleSectionEntry.HasComponent(component.PhysicalSectionCircuitType) { - sectionCircuit := component.PhysicalSectionCircuitType.Get(axleSectionEntry) - relayDrive := component.RelayDriveType.Get(sectionCircuit.GJ) - relayDrive.Td = !sectionState.Occ - } - - if "北京_12_酒仙桥_15G" == axleSectionId && false { - sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) - slog.Info(axleSectionId, - "Drst", axleRuntime.Drst, - "Pdrst", axleRuntime.Pdrst, - "DoingPdrst", axleRuntime.DoingPdrst, - "Rac", axleRuntime.Rac, - "Rjo", axleRuntime.Rjo, - "Rjt", axleRuntime.Rjt, - "SectionFault", sectionFault, - "Occ", sectionState.Occ, - "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) calculateDrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) { - isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) - if axleRuntime.Drst && !axleRuntime.Rjo && !axleRuntime.Rjt && isFault { //直接复位且没有拒绝原因 - axleDevice.UpdateCount(0) - axleDevice.ResetCountPulse() - 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 // 技术原因拒绝复位 -} +// +//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) +// s.calculateHf(sectionFault, axleSectionEntry, sectionState, axleDevice, axleRuntime) +// s.calculateDrst(axleSectionEntry, sectionState, axleDevice, axleRuntime) +// s.calculatePdrst(axleSectionEntry, sectionState, axleDevice, axleRuntime) +// s.calculateSectionState(sectionFault, sectionState, axleDevice, axleRuntime) +// if axleSectionEntry.HasComponent(component.PhysicalSectionCircuitType) { +// sectionCircuit := component.PhysicalSectionCircuitType.Get(axleSectionEntry) +// relayDrive := component.RelayDriveType.Get(sectionCircuit.GJ) +// relayDrive.Td = !sectionState.Occ +// } +// +// if "北京_12_酒仙桥_15G" == axleSectionId && false { +// sectionFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) +// slog.Info(axleSectionId, +// "Drst", axleRuntime.Drst, +// "PDRST", axleRuntime.Pdrst, +// "DoingPdrst", axleRuntime.DoingPdrst, +// "RAC", axleRuntime.Rac, +// "RJO", axleRuntime.Rjo, +// "RJT", axleRuntime.Rjt, +// "SectionFault", sectionFault, +// "Occ", sectionState.Occ, +// "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) calculateDrst(axleSectionEntry *ecs.Entry, sectionState *component.PhysicalSectionState, axleDevice *component.AxlePhysicalSection, axleRuntime *component.AxleDeviceRuntime) { +// isFault := axleSectionEntry.HasComponent(component.AxleSectionFaultTag) +// if axleRuntime.Drst && !axleRuntime.Rjo && !axleRuntime.Rjt && isFault { //直接复位且没有拒绝原因 +// axleDevice.UpdateCount(0) +// axleDevice.ResetCountPulse() +// 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 // 技术原因拒绝复位 +//} diff --git a/sys/device_sys/section_detection.go b/sys/device_sys/section_detection.go index a623f3f..5002af3 100644 --- a/sys/device_sys/section_detection.go +++ b/sys/device_sys/section_detection.go @@ -2,68 +2,67 @@ package device_sys import ( "fmt" - "log/slog" - "strings" - "joylink.club/ecs" - "joylink.club/ecs/filter" "joylink.club/rtsssimulation/component" "joylink.club/rtsssimulation/entity" "joylink.club/rtsssimulation/repository" "joylink.club/rtsssimulation/repository/model/proto" + "log/slog" + "strings" ) -// SectionDetectSystem 区段检测系统 -type SectionDetectSystem struct { - trainQuery *ecs.Query - axleSectionQuery *ecs.Query -} +//// SectionDetectSystem 区段检测系统 +//type SectionDetectSystem struct { +// trainQuery *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 { wd := entity.GetWorldData(w) curLink := wd.Repo.FindLink(tp.HeadLink) @@ -80,8 +79,7 @@ func DoSearchTrainOccupiedSections(w ecs.World, tp *component.TrainPositionInfo) return stp.trainSections() } -///////////////////////////////////////////////////////////////////// - +// ///////////////////////////////////////////////////////////////////// type stpContext struct { w ecs.World trainLen int64 //列车长度