Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
5e7897ccf3
@ -1,15 +0,0 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
)
|
||||
|
||||
// 按钮状态组件
|
||||
var ButtonStateComponent = ecs.NewComponentType[cstate.ButtonState]()
|
||||
|
||||
// 按钮操作组件
|
||||
var ButtonPressOperatingComponent = ecs.NewComponentType[cstate.ButtonPressOperating]()
|
||||
|
||||
// 按钮确认组件
|
||||
var ButtonConfirmOperatingComponent = ecs.NewComponentType[cstate.ButtonConfirmOperating]()
|
@ -1,60 +0,0 @@
|
||||
package components
|
||||
|
||||
import (
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
)
|
||||
|
||||
// 系统时钟组件
|
||||
var SystemTimerComponent = ecs.NewComponentType[cstate.SystemTimer]()
|
||||
|
||||
// 模型仓库引用组件,单例
|
||||
var ModelStorageRefComponent = ecs.NewComponentType[cstate.ModelStorageRef]()
|
||||
|
||||
// 身份组件
|
||||
var DeviceIdentityComponent = ecs.NewComponentType[cstate.DeviceIdentity]()
|
||||
|
||||
// 存储屏蔽门标签组件
|
||||
var PsdTagHandlerComponent = ecs.NewComponentType[cstate.EntityTagHandler]()
|
||||
|
||||
// 存储继电器标签组件
|
||||
var RelayTagHandlerComponent = ecs.NewComponentType[cstate.EntityTagHandler]()
|
||||
|
||||
// 可移动设备组件
|
||||
var MovableDeviceStateComponent = ecs.NewComponentType[cstate.MovableDeviceState]()
|
||||
|
||||
// 比率设备组件
|
||||
var PercentageDeviceStateComponent = ecs.NewComponentType[cstate.PercentageDeviceState]()
|
||||
|
||||
// 道岔继电器状态组件
|
||||
var SwitchRelayStateComponent = ecs.NewComponentType[cstate.SwitchRelayState]()
|
||||
|
||||
// 物理区段状态组件
|
||||
var PhysicalSectionStateComponent = ecs.NewComponentType[cstate.PhysicalSectionState]()
|
||||
|
||||
// 信号机状态组件
|
||||
var SignalStateComponent = ecs.NewComponentType[cstate.SignalState]()
|
||||
|
||||
// 站台单侧屏蔽门状态组件
|
||||
var PsdStateComponent = ecs.NewComponentType[cstate.PsdState]()
|
||||
|
||||
// 应答器状态组件
|
||||
var BaliseStateComponent = ecs.NewComponentType[cstate.BaliseState]()
|
||||
|
||||
// 列车状态组件
|
||||
var TrainStateComponent = ecs.NewComponentType[cstate.TrainState]()
|
||||
|
||||
// 两档按钮/旋钮状态组件
|
||||
var TowPositionButtonStateComponent = ecs.NewComponentType[cstate.TowPositionButtonState]()
|
||||
|
||||
// 继电器状态组件
|
||||
var RelayStateComponent = ecs.NewComponentType[cstate.RelayState]()
|
||||
|
||||
// 紧急停车按钮状态组件
|
||||
var EmpStateComponent = ecs.NewComponentType[cstate.EmpState]()
|
||||
|
||||
// 生成标签组件
|
||||
// 用于标记实体便于查找
|
||||
func NewComponentTag() *ecs.ComponentType[struct{}] {
|
||||
return ecs.NewComponentType[struct{}]()
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,54 +0,0 @@
|
||||
package cstate
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/yohamta/donburi/component"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 此文件中为与设备无关的仿真系统自身的状态定义
|
||||
|
||||
// 系统时钟,单例
|
||||
type SystemTimer struct {
|
||||
timer *time.Time
|
||||
}
|
||||
|
||||
// 以指定时间构建
|
||||
func NewSystemTimer(time *time.Time) *SystemTimer {
|
||||
return &SystemTimer{
|
||||
timer: time,
|
||||
}
|
||||
}
|
||||
|
||||
// 重置时间
|
||||
func (me *SystemTimer) ResetTime(time time.Time) {
|
||||
*me.timer = time
|
||||
}
|
||||
|
||||
// 获取当前时间的副本
|
||||
func (me *SystemTimer) Now() time.Time {
|
||||
return *me.timer
|
||||
}
|
||||
|
||||
// tick系统时钟,单位ms
|
||||
func (me *SystemTimer) Tick(tick int) {
|
||||
*me.timer = me.timer.Add(time.Duration(tick) * time.Millisecond)
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
// 实体标签
|
||||
type EntityTag = component.IComponentType
|
||||
|
||||
type EntityTagHandler struct {
|
||||
Tag EntityTag
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
// 模型仓库引用
|
||||
// 用于world内使用,查询模型
|
||||
type ModelStorageRef struct {
|
||||
ModelManager umi.IModelManager
|
||||
}
|
@ -1,156 +0,0 @@
|
||||
package creator
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 仿真world配置
|
||||
type WorldConfig struct {
|
||||
//模型管理器,接收模型仓库管理器实例的指针
|
||||
ModelManager umi.IModelManager
|
||||
//world 系统
|
||||
Systems []ecs.ISystem
|
||||
//world tick
|
||||
Tick int
|
||||
//world 起始时间
|
||||
InitTime time.Time
|
||||
}
|
||||
|
||||
// 初始化仿真world
|
||||
func InitializeWorld(config *WorldConfig) ecs.World {
|
||||
world := ecs.NewWorld(config.Tick)
|
||||
// 初始化系统
|
||||
for _, sys := range config.Systems {
|
||||
world.AddSystem(sys)
|
||||
}
|
||||
// 初始化实体
|
||||
initEntites(config, world)
|
||||
//
|
||||
return world
|
||||
}
|
||||
|
||||
// 初始化实体
|
||||
func initEntites(config *WorldConfig, world ecs.World) {
|
||||
modelStorageRefEntry := CreateModelStorageRefEntity(world)
|
||||
components.ModelStorageRefComponent.Set(modelStorageRefEntry, &cstate.ModelStorageRef{ModelManager: config.ModelManager})
|
||||
//world time
|
||||
worldTime := CreateWorldTimeEntity(world)
|
||||
components.SystemTimerComponent.Set(worldTime, cstate.NewSystemTimer(&config.InitTime))
|
||||
//
|
||||
foreachModels(config.ModelManager, umi.Switch, func(md umi.IDeviceModel) {
|
||||
entry := CreateSwitchEntity(world)
|
||||
components.DeviceIdentityComponent.Set(entry, &cstate.DeviceIdentity{Id: md.GetId()})
|
||||
components.SwitchRelayStateComponent.Set(entry, &cstate.SwitchRelayState{DcJ: false, FcJ: false, DbJ: true, FbJ: false})
|
||||
components.PercentageDeviceStateComponent.Set(entry, &cstate.PercentageDeviceState{Rate: system.SwitchNormalVaule, Target: system.SwitchNormalVaule})
|
||||
components.MovableDeviceStateComponent.Set(entry, &cstate.MovableDeviceState{ToH: false, Speed: 0, Position: system.SwitchNormalVaule})
|
||||
})
|
||||
//
|
||||
foreachModels(config.ModelManager, umi.Signal, func(md umi.IDeviceModel) {
|
||||
entry := CreateSignalEntity(world)
|
||||
components.DeviceIdentityComponent.Set(entry, &cstate.DeviceIdentity{Id: md.GetId()})
|
||||
components.SignalStateComponent.Set(entry, &cstate.SignalState{Display: cstate.SignalAspect_No})
|
||||
})
|
||||
//
|
||||
foreachModels(config.ModelManager, umi.Psd, func(md umi.IDeviceModel) {
|
||||
psdEntry := CreatePsdEntity(world)
|
||||
components.DeviceIdentityComponent.Set(psdEntry, &cstate.DeviceIdentity{Id: md.GetId()})
|
||||
components.PsdStateComponent.Set(psdEntry, &cstate.PsdState{AllClosed: true, AllOpened: false, InterlockReleased: false})
|
||||
//
|
||||
psd := md.(umi.IPsdModel)
|
||||
for _, psdCell := range psd.AllDeviceCells() {
|
||||
cellEntry := CreatePsdCellEntity(world, psdEntry)
|
||||
components.DeviceIdentityComponent.Set(cellEntry, &cstate.DeviceIdentity{Id: psdCell.GetId()})
|
||||
components.PercentageDeviceStateComponent.Set(cellEntry, &cstate.PercentageDeviceState{Rate: system.PsdCellWholeCloseValue, Target: system.PsdCellWholeCloseValue})
|
||||
components.MovableDeviceStateComponent.Set(cellEntry, &cstate.MovableDeviceState{ToH: true, Speed: 0, Position: system.PsdCellWholeCloseValue})
|
||||
}
|
||||
})
|
||||
//
|
||||
foreachModels(config.ModelManager, umi.TowPosButton, func(md umi.IDeviceModel) {
|
||||
entry := CreateTowPosButtonEntity(world)
|
||||
components.DeviceIdentityComponent.Set(entry, &cstate.DeviceIdentity{Id: md.GetId()})
|
||||
components.TowPositionButtonStateComponent.Set(entry, &cstate.TowPositionButtonState{Pos1: false, Pos2: true})
|
||||
})
|
||||
}
|
||||
func foreachModels(modelManager umi.IModelManager, deviceType umi.DeviceType, eachFunc func(deviceModel umi.IDeviceModel)) {
|
||||
for _, model := range modelManager.FindByType(deviceType) {
|
||||
eachFunc(model)
|
||||
}
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 创建模型仓库引用实体
|
||||
func CreateModelStorageRefEntity(w ecs.World) *ecs.Entry {
|
||||
return w.Create(components.ModelStorageRefComponent)
|
||||
}
|
||||
|
||||
// 创建world time 实体
|
||||
func CreateWorldTimeEntity(w ecs.World) *ecs.Entry {
|
||||
return w.Create(components.SystemTimerComponent)
|
||||
}
|
||||
|
||||
// 创建道岔实体
|
||||
func CreateSwitchEntity(w ecs.World) *ecs.Entry {
|
||||
e := w.Create(components.DeviceIdentityComponent, components.SwitchRelayStateComponent, components.PercentageDeviceStateComponent, components.MovableDeviceStateComponent, components.RelayTagHandlerComponent)
|
||||
components.RelayTagHandlerComponent.Set(e, &cstate.EntityTagHandler{Tag: components.NewComponentTag()})
|
||||
return e
|
||||
}
|
||||
|
||||
// 创建信号机实体
|
||||
func CreateSignalEntity(w ecs.World) *ecs.Entry {
|
||||
e := w.Create(components.DeviceIdentityComponent, components.SignalStateComponent, components.RelayTagHandlerComponent)
|
||||
components.RelayTagHandlerComponent.Set(e, &cstate.EntityTagHandler{Tag: components.NewComponentTag()})
|
||||
return e
|
||||
}
|
||||
|
||||
// 创建物理区段实体
|
||||
func CreatePhysicalSectionEntity(w ecs.World) *ecs.Entry {
|
||||
return w.Create(components.DeviceIdentityComponent, components.PhysicalSectionStateComponent)
|
||||
}
|
||||
|
||||
// 创建站台单侧屏蔽门实体
|
||||
func CreatePsdEntity(w ecs.World) *ecs.Entry {
|
||||
e := w.Create(components.DeviceIdentityComponent, components.PsdStateComponent, components.PsdTagHandlerComponent, components.RelayTagHandlerComponent)
|
||||
components.PsdTagHandlerComponent.Set(e, &cstate.EntityTagHandler{Tag: components.NewComponentTag()})
|
||||
components.RelayTagHandlerComponent.Set(e, &cstate.EntityTagHandler{Tag: components.NewComponentTag()})
|
||||
return e
|
||||
}
|
||||
|
||||
// 创建屏蔽门cell实体
|
||||
func CreatePsdCellEntity(w ecs.World, psdEntry *ecs.Entry) *ecs.Entry {
|
||||
return w.Create(components.DeviceIdentityComponent, components.PercentageDeviceStateComponent, components.MovableDeviceStateComponent, components.PsdTagHandlerComponent.Get(psdEntry).Tag)
|
||||
}
|
||||
|
||||
// 创建应答器实体
|
||||
func CreateBaliseEntity(w ecs.World) *ecs.Entry {
|
||||
return w.Create(components.DeviceIdentityComponent, components.BaliseStateComponent)
|
||||
}
|
||||
|
||||
// 创建列车实体
|
||||
func CreateTrainEntity(w ecs.World) *ecs.Entry {
|
||||
return w.Create(components.DeviceIdentityComponent, components.TrainStateComponent)
|
||||
}
|
||||
|
||||
// 创建两档位按钮实体
|
||||
func CreateTowPosButtonEntity(w ecs.World) *ecs.Entry {
|
||||
return w.Create(components.DeviceIdentityComponent, components.TowPositionButtonStateComponent)
|
||||
}
|
||||
|
||||
// 创建继电器实体
|
||||
// deviceEntry: 被继电器控制的设备
|
||||
func CreateRelayEntity(w ecs.World, deviceEntry *ecs.Entry) *ecs.Entry {
|
||||
return w.Create(components.DeviceIdentityComponent, components.RelayStateComponent, components.RelayTagHandlerComponent.Get(deviceEntry).Tag)
|
||||
}
|
||||
|
||||
// 创建紧急停车按钮实体
|
||||
func CreateEmpEntity(w ecs.World) *ecs.Entry {
|
||||
e := w.Create(components.DeviceIdentityComponent, components.EmpStateComponent, components.RelayTagHandlerComponent)
|
||||
components.RelayTagHandlerComponent.Set(e, &cstate.EntityTagHandler{Tag: components.NewComponentTag()})
|
||||
return e
|
||||
}
|
27
entities/common_entity.go
Normal file
27
entities/common_entity.go
Normal file
@ -0,0 +1,27 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
// 创建模型仓库实体
|
||||
func CreateModelStorageEntity(w ecs.World) *ecs.Entry {
|
||||
return w.Create(system.ModelStorageComponent)
|
||||
}
|
||||
|
||||
// 创建继电器实体
|
||||
func CreateRelayEntity(w ecs.World, relayId string) *ecs.Entry {
|
||||
e := w.Create(system.EntityIdentityComponent, system.RelayStateComponent)
|
||||
system.EntityIdentityComponent.Set(e, &system.EntityIdentity{Id: relayId})
|
||||
return e
|
||||
}
|
||||
|
||||
// 创建系统时钟实体
|
||||
func CreateSystemTimerEntity(w ecs.World, systemTime time.Time) *ecs.Entry {
|
||||
e := w.Create(system.SystemTimerComponent)
|
||||
system.SystemTimerComponent.Set(e, system.NewSystemTimer(&systemTime))
|
||||
return e
|
||||
}
|
13
entities/signal_entity.go
Normal file
13
entities/signal_entity.go
Normal file
@ -0,0 +1,13 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
func CreateSignal3XH1Entity(w ecs.World, signalId string) *ecs.Entry {
|
||||
e := w.Create(system.EntityIdentityComponent, system.Signal3XH1StateComponent)
|
||||
system.EntityIdentityComponent.Set(e, &system.EntityIdentity{Id: signalId})
|
||||
system.Signal3XH1StateComponent.Set(e, system.NewSignal3XH1State())
|
||||
return e
|
||||
}
|
24
entities/switch_entity.go
Normal file
24
entities/switch_entity.go
Normal file
@ -0,0 +1,24 @@
|
||||
package entities
|
||||
|
||||
import (
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
// 双机zdj9
|
||||
// 默认定位
|
||||
func CreateSwitch2jzdj9Entity(w ecs.World, switchId string) *ecs.Entry {
|
||||
e := w.Create(system.EntityIdentityComponent, system.Switch2jZdj9StateComponent, system.MovableObject1Component, system.MovableObject2Component)
|
||||
system.EntityIdentityComponent.Set(e, &system.EntityIdentity{Id: switchId})
|
||||
//电路
|
||||
system.Switch2jZdj9StateComponent.Set(e, system.NewSwitch2jZdj9State())
|
||||
//J1
|
||||
j1 := system.NewMovableObject()
|
||||
j1.Value = system.J1Range
|
||||
system.MovableObject1Component.Set(e, j1)
|
||||
//J2
|
||||
j2 := system.NewMovableObject()
|
||||
j2.Value = system.J2Range
|
||||
system.MovableObject2Component.Set(e, j2)
|
||||
return e
|
||||
}
|
@ -1,132 +1,5 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
"joylink.club/rtsssimulation/creator"
|
||||
"joylink.club/rtsssimulation/examples/test1/tmodel"
|
||||
"joylink.club/rtsssimulation/examples/test1/tstorages"
|
||||
"joylink.club/rtsssimulation/operate"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
// 具体共享模型仓库key
|
||||
var StorageKeyXaV1 = tstorages.StorageKey{LineId: "xa-1", Version: "0.1"}
|
||||
|
||||
func main() {
|
||||
initShareModels()
|
||||
// 通过共享仓库生成具体仿真world的模型仓库
|
||||
woldModelStorage := tstorages.ShareStoragesMapper.CreateWorldStorageWithShare(StorageKeyXaV1, initLinkModels())
|
||||
//
|
||||
config := &creator.WorldConfig{
|
||||
ModelManager: woldModelStorage,
|
||||
Tick: 300,
|
||||
InitTime: time.Now(),
|
||||
Systems: []ecs.ISystem{
|
||||
system.NewMovableDeviceSystem(),
|
||||
system.NewPercentageDeviceSystem(),
|
||||
system.NewSwitchSystem(),
|
||||
system.NewPsdSystem(),
|
||||
system.NewTimerSystem(),
|
||||
system.NewDebugSystem()},
|
||||
}
|
||||
world := creator.InitializeWorld(config)
|
||||
//
|
||||
world.StartUp()
|
||||
//
|
||||
time.Sleep(2 * time.Second)
|
||||
//
|
||||
//testPsdOpt(world)
|
||||
//testPsdCellOpt(world)
|
||||
testSwitchTurn(world)
|
||||
//
|
||||
time.Sleep(120 * time.Second)
|
||||
}
|
||||
|
||||
// 构建具体仿真link模型
|
||||
func initLinkModels() *tstorages.ModelStorage {
|
||||
mds := tstorages.NewModelStorage()
|
||||
//
|
||||
link1 := tmodel.NewLinkModel("link1")
|
||||
link2 := tmodel.NewLinkModel("link2")
|
||||
mds.AddModel(link1)
|
||||
mds.AddModel(link2)
|
||||
return mds
|
||||
}
|
||||
|
||||
// 构建模型
|
||||
func initShareModels() {
|
||||
mds := tstorages.NewModelStorage()
|
||||
//
|
||||
signal1 := tmodel.NewSignalModel("signal1")
|
||||
signal2 := tmodel.NewSignalModel("signal2")
|
||||
mds.AddModel(signal1)
|
||||
mds.AddModel(signal2)
|
||||
//
|
||||
switch1 := tmodel.NewSwitchModel("switch1")
|
||||
switch1.TurnTime = 3000
|
||||
switch2 := tmodel.NewSwitchModel("switch2")
|
||||
switch2.TurnTime = 2500
|
||||
mds.AddModel(switch1)
|
||||
mds.AddModel(switch2)
|
||||
//
|
||||
psd1 := tmodel.NewPsdModel("psd1")
|
||||
psd1.MoveTime = 5000
|
||||
psd1Cell1 := tmodel.NewPsdCellModel("psd1Cell1", psd1)
|
||||
psd1Cell2 := tmodel.NewPsdCellModel("psd1Cell2", psd1)
|
||||
psd2 := tmodel.NewPsdModel("psd2")
|
||||
psd2.MoveTime = 6000
|
||||
psd2Cell1 := tmodel.NewPsdCellModel("psd2Cell1", psd2)
|
||||
psd2Cell2 := tmodel.NewPsdCellModel("psd2Cell2", psd2)
|
||||
mds.AddModel(psd1)
|
||||
mds.AddModel(psd1Cell1)
|
||||
mds.AddModel(psd1Cell2)
|
||||
mds.AddModel(psd2)
|
||||
mds.AddModel(psd2Cell1)
|
||||
mds.AddModel(psd2Cell2)
|
||||
//
|
||||
button1 := tmodel.NewTowPosButtonModel("button1")
|
||||
mds.AddModel(button1)
|
||||
//
|
||||
tstorages.ShareStoragesMapper.AddShareModelStorage(StorageKeyXaV1, mds)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
func testPsdOpt(w ecs.World) {
|
||||
operate.FirePsdOperation(w, "psd1", true)
|
||||
time.Sleep(5 * time.Second)
|
||||
operate.FirePsdOperation(w, "psd1", false)
|
||||
}
|
||||
func testPsdCellOpt(w ecs.World) {
|
||||
operate.FirePsdCellOperation(w, "psd1", "psd1Cell1", 0)
|
||||
operate.FirePsdCellOperation(w, "psd1", "psd1Cell2", 0)
|
||||
time.Sleep(10 * time.Second)
|
||||
operate.FirePsdCellOperation(w, "psd1", "psd1Cell1", 100-20)
|
||||
operate.FirePsdCellOperation(w, "psd1", "psd1Cell2", 100)
|
||||
//
|
||||
time.Sleep(10 * time.Second)
|
||||
operate.FirePsdCellOperation(w, "psd2", "psd2Cell1", 0)
|
||||
operate.FirePsdCellOperation(w, "psd2", "psd2Cell2", 0)
|
||||
time.Sleep(10 * time.Second)
|
||||
operate.FirePsdCellOperation(w, "psd2", "psd2Cell1", 100-20)
|
||||
operate.FirePsdCellOperation(w, "psd2", "psd2Cell2", 100)
|
||||
}
|
||||
func testSwitchTurn(w ecs.World) {
|
||||
operate.FireSwitchFcj(w, "switch1")
|
||||
time.Sleep(3 * time.Second)
|
||||
operate.FireSwitchDcj(w, "switch1")
|
||||
|
||||
}
|
||||
func testSignalOpt(w ecs.World) {
|
||||
operate.SetSignalDisplay(w, "siganl1", cstate.SignalAspect_B)
|
||||
}
|
||||
func testButtonOpt(world ecs.World) {
|
||||
operate.FireTowPositionButtonMoving(world, "button1")
|
||||
time.Sleep(3 * time.Second)
|
||||
operate.FireTowPositionButtonArrivedPos1(world, "button1")
|
||||
time.Sleep(3 * time.Second)
|
||||
operate.FireTowPositionButtonArrivedPos2(world, "button1")
|
||||
}
|
||||
|
6
examples/test1/tmodel/relay_model.go
Normal file
6
examples/test1/tmodel/relay_model.go
Normal file
@ -0,0 +1,6 @@
|
||||
package tmodel
|
||||
|
||||
// 继电器模型
|
||||
type RelayModel struct {
|
||||
DeviceModel
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package tmodel
|
||||
|
||||
import (
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
@ -10,10 +9,6 @@ type SignalModel struct {
|
||||
DeviceModel
|
||||
//信号机所在轨道
|
||||
LinkOffset *LinkOffsetRef
|
||||
//信号机类型,出厂已确定,即几个色灯、排列顺序
|
||||
Type cstate.SignalAspect
|
||||
//默认显示信号
|
||||
DefaultDisplay cstate.SignalAspect
|
||||
}
|
||||
|
||||
func NewSignalModel(id string) *SignalModel {
|
||||
|
@ -4,6 +4,16 @@ import (
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 道岔电路系统中的继电器
|
||||
type SwitchRelay struct {
|
||||
//继电器模型
|
||||
Relay umi.IRelayModel
|
||||
//该继电器在该道岔电路系统中的组合类型
|
||||
RelayGroup string
|
||||
//该继电器在该道岔电路系统中的功能名称
|
||||
RelayName string
|
||||
}
|
||||
|
||||
// 道岔
|
||||
type SwitchModel struct {
|
||||
DeviceModel
|
||||
@ -13,19 +23,14 @@ type SwitchModel struct {
|
||||
PortB umi.ILinkRef
|
||||
//道岔C端口连接的轨道
|
||||
PortC umi.ILinkRef
|
||||
//道岔转动需要的时间(从开度0-100的时间),单位ms
|
||||
TurnTime int64
|
||||
//道岔电路系统中的继电器
|
||||
Relays []SwitchRelay
|
||||
}
|
||||
|
||||
func NewSwitchModel(id string) *SwitchModel {
|
||||
return &SwitchModel{DeviceModel: DeviceModel{Id: id, Type: umi.Switch}}
|
||||
}
|
||||
|
||||
// 道岔转动从0-100耗时,单位ms
|
||||
func (me *SwitchModel) TurningTime() int64 {
|
||||
return me.TurnTime
|
||||
}
|
||||
|
||||
// 道岔A端口连接的轨道
|
||||
func (me *SwitchModel) PortALink() umi.ILinkRef {
|
||||
return me.PortA
|
||||
@ -41,6 +46,33 @@ func (me *SwitchModel) PortCLink() umi.ILinkRef {
|
||||
return me.PortC
|
||||
}
|
||||
|
||||
// 根据继电器id获取在具体电路中的电路角色
|
||||
// relayId-继电器id
|
||||
// relayGroup-继电器组合类型
|
||||
// relayName-继电器在电路中的名称
|
||||
// find-true找到,false未找到
|
||||
func (me *SwitchModel) FindCircuitRoleById(relayId string) (relayGroup string, relayName string, find bool) {
|
||||
for _, sr := range me.Relays {
|
||||
id := sr.Relay.(umi.IDeviceModel).GetId()
|
||||
if id == relayId {
|
||||
return sr.RelayGroup, sr.RelayName, true
|
||||
}
|
||||
}
|
||||
return "", "", false
|
||||
}
|
||||
|
||||
// 根据继电器具体电路角色来获取继电器设备模型
|
||||
// relayGroup-继电器组合类型
|
||||
// relayName-继电器在电路中的名称
|
||||
func (me *SwitchModel) FindRelayModelByCRole(relayGroup string, relayName string) umi.IRelayModel {
|
||||
for _, sr := range me.Relays {
|
||||
if sr.RelayGroup == relayGroup && sr.RelayName == relayName {
|
||||
return sr.Relay
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
|
||||
// 道岔端口引用
|
||||
|
@ -1,28 +0,0 @@
|
||||
package operate
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
// 应答器查询
|
||||
var baliseQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.BaliseStateComponent))
|
||||
|
||||
//
|
||||
|
||||
// 发送消息到应答器
|
||||
// 当要清空应答器中报文时,则message=nil
|
||||
func SendMessageToTransponder(world ecs.World, transponderId string, message *cstate.BaliseContent) bool {
|
||||
transponderEntry := system.QueryEntityById(world, baliseQuery, transponderId)
|
||||
//
|
||||
if transponderEntry == nil {
|
||||
return false
|
||||
}
|
||||
//
|
||||
components.BaliseStateComponent.Get(transponderEntry).Content = message
|
||||
//
|
||||
return true
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
package operate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
// 紧急停车按钮查询
|
||||
var empQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.EmpStateComponent))
|
||||
|
||||
func findEmpEntry(world ecs.World, empId string) (*ecs.Entry, error) {
|
||||
empEntry := system.QueryEntityById(world, empQuery, empId)
|
||||
if empEntry == nil {
|
||||
return nil, fmt.Errorf("紧急停车按钮[%s]实体不存在", empId)
|
||||
} else {
|
||||
return empEntry, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 激活紧急停车按钮
|
||||
func FireEmpPressed(world ecs.World, empId string) error {
|
||||
entry, err := findEmpEntry(world, empId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
components.EmpStateComponent.Get(entry).Pressed = true
|
||||
return nil
|
||||
}
|
||||
|
||||
// 复位紧急停车按钮
|
||||
func FireEmpReset(world ecs.World, empId string) error {
|
||||
entry, err := findEmpEntry(world, empId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
components.EmpStateComponent.Get(entry).Pressed = false
|
||||
return nil
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package operate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
// 触发比率设备变动到目标比率
|
||||
// lhDistance: 从L到H的总耗时,单位ms
|
||||
// targetRateValue: 变动的最终目标比率值,[0,100000]
|
||||
func FirePercentageDevice(world ecs.World, deviceEntry *ecs.Entry, lhDistance int64, targetRateValue int64) error {
|
||||
if targetRateValue < system.PercentageRateValueMin || targetRateValue > system.PercentageRateValueMax {
|
||||
return fmt.Errorf("targetRateValue须在[%d,%d]范围内", system.PercentageRateValueMin, system.PercentageRateValueMax)
|
||||
}
|
||||
//
|
||||
id := components.DeviceIdentityComponent.Get(deviceEntry).Id
|
||||
if !deviceEntry.HasComponent(components.PercentageDeviceStateComponent) {
|
||||
return fmt.Errorf("比率设备[%s]实体中没有百分比组件", id)
|
||||
}
|
||||
if !deviceEntry.HasComponent(components.MovableDeviceStateComponent) {
|
||||
return fmt.Errorf("比率设备[%s]实体中没有按速度移动组件", id)
|
||||
}
|
||||
//
|
||||
speed := int32(float64(world.Tick()) * (float64(system.PercentageRateValueMax) / float64(lhDistance)))
|
||||
//
|
||||
percent := components.PercentageDeviceStateComponent.Get(deviceEntry)
|
||||
movable := components.MovableDeviceStateComponent.Get(deviceEntry)
|
||||
//
|
||||
percent.Target = targetRateValue
|
||||
movable.Speed = speed
|
||||
movable.ToH = targetRateValue > percent.Rate
|
||||
//
|
||||
return nil
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package operate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
const (
|
||||
//屏蔽门完全关闭,百分比
|
||||
PsdCellWholeCloseRate int8 = system.PercentageRateMax
|
||||
//屏蔽门完全打开,百分比
|
||||
PsdCellWholeOpenRate int8 = system.PercentageRateMin
|
||||
)
|
||||
|
||||
// 车站单侧屏蔽门互锁解除操作
|
||||
func FirePsdInterlockRelease(world ecs.World, psdId string, lockRelease bool) error {
|
||||
psdEntry, err := findPsdEntry(world, psdId)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
components.PsdStateComponent.Get(psdEntry).InterlockReleased = lockRelease
|
||||
//
|
||||
return nil
|
||||
}
|
||||
|
||||
// 屏蔽门全开
|
||||
func FirePsdWholeOpen(world ecs.World, psdId string) error {
|
||||
return FirePsdOperation(world, psdId, false)
|
||||
}
|
||||
|
||||
// 屏蔽门全关
|
||||
func FirePsdWholeClose(world ecs.World, psdId string) error {
|
||||
return FirePsdOperation(world, psdId, true)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// 车站单侧屏蔽门操作
|
||||
// closeOpt true-关门操作,false-开门操作
|
||||
func FirePsdOperation(world ecs.World, psdId string, closeOpt bool) error {
|
||||
psdEntry, err := findPsdEntry(world, psdId)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
//屏蔽门标签
|
||||
psdTag := components.PsdTagHandlerComponent.Get(psdEntry).Tag
|
||||
psdCellQuery := ecs.NewQuery(filter.Contains(psdTag))
|
||||
var errPercent error = nil
|
||||
psdCellQuery.Each(world, func(psdCellEntry *ecs.Entry) {
|
||||
if errPercent == nil {
|
||||
if closeOpt {
|
||||
errPercent = FirePercentageDevice(world, psdCellEntry, findPsdWholeMoveTime(world, psdId), system.GetRateValue(PsdCellWholeCloseRate))
|
||||
} else {
|
||||
errPercent = FirePercentageDevice(world, psdCellEntry, findPsdWholeMoveTime(world, psdId), system.GetRateValue(PsdCellWholeOpenRate))
|
||||
}
|
||||
}
|
||||
})
|
||||
//
|
||||
return errPercent
|
||||
}
|
||||
|
||||
// 车站单侧屏蔽门单元cell操作
|
||||
// closeRate cell最终关上的百分比,100-完全关上,0-完全未关即完全打开,(0,100)内即半关闭
|
||||
func FirePsdCellOperation(world ecs.World, psdId string, psdCellId string, closeRate int8) error {
|
||||
if closeRate < 0 || closeRate > 100 {
|
||||
return fmt.Errorf("屏蔽门单元操作closeRate(%d)不在[0,100]内", closeRate)
|
||||
}
|
||||
//
|
||||
psdEntry, err := findPsdEntry(world, psdId)
|
||||
if nil != err {
|
||||
return err
|
||||
}
|
||||
//屏蔽门标签
|
||||
psdTag := components.PsdTagHandlerComponent.Get(psdEntry).Tag
|
||||
psdCellQuery := ecs.NewQuery(filter.Contains(psdTag))
|
||||
psdCellEntry := system.QueryEntityById(world, psdCellQuery, psdCellId)
|
||||
if psdCellEntry == nil {
|
||||
return fmt.Errorf("屏蔽门[%s]的单元门[%s]的实体不存在", psdId, psdCellId)
|
||||
}
|
||||
//
|
||||
return FirePercentageDevice(world, psdCellEntry, findPsdWholeMoveTime(world, psdId), system.GetRateValue(closeRate))
|
||||
}
|
||||
|
||||
// 获取屏蔽门实体
|
||||
func findPsdEntry(world ecs.World, psdId string) (*ecs.Entry, error) {
|
||||
psdEntry := system.QueryEntityById(world, system.PsdQuery, psdId)
|
||||
if psdEntry == nil {
|
||||
return nil, fmt.Errorf("屏蔽门[%s]实体不存在", psdId)
|
||||
} else {
|
||||
return psdEntry, nil
|
||||
}
|
||||
}
|
||||
|
||||
// 获取屏蔽门从完全开到完全关所需时间,单位ms
|
||||
func findPsdWholeMoveTime(world ecs.World, psdId string) int64 {
|
||||
psd := system.WorldModelStorage(world).FindById(psdId)
|
||||
psdUmi := psd.(umi.IPsdModel)
|
||||
return psdUmi.MovingTime()
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package operate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
// 信号机显示状态查询
|
||||
var signalQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.SignalStateComponent))
|
||||
|
||||
// 设置某个信号机的显示
|
||||
// 返回值:true-设置成功,false-设置失败
|
||||
func SetSignalDisplay(w ecs.World, signalId string, display cstate.SignalAspect) error {
|
||||
signalEntry, err := findSignalEntry(w, signalId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
//
|
||||
signalState := components.SignalStateComponent.Get(signalEntry)
|
||||
signalState.Display = display
|
||||
//
|
||||
return nil
|
||||
}
|
||||
|
||||
// 获取信号机实体
|
||||
func findSignalEntry(w ecs.World, signalId string) (*ecs.Entry, error) {
|
||||
var signalEntry *ecs.Entry = system.QueryEntityById(w, signalQuery, signalId)
|
||||
if signalEntry != nil {
|
||||
return signalEntry, nil
|
||||
} else {
|
||||
return nil, fmt.Errorf("信号机[%s]的实体不存在", signalId)
|
||||
}
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package operate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
const (
|
||||
//道岔定位
|
||||
SwitchNormalRate int8 = system.PercentageRateMin
|
||||
//道岔反位
|
||||
SwitchReverseRate int8 = system.PercentageRateMax
|
||||
)
|
||||
|
||||
// 道岔定操
|
||||
func FireSwitchDcj(w ecs.World, switchId string) error {
|
||||
return fireSwitchTurn(w, switchId, true)
|
||||
}
|
||||
|
||||
// 道岔反操
|
||||
func FireSwitchFcj(w ecs.World, switchId string) error {
|
||||
return fireSwitchTurn(w, switchId, false)
|
||||
}
|
||||
func fireSwitchTurn(w ecs.World, switchId string, turnNormal bool) error {
|
||||
var switchEntry *ecs.Entry = system.QueryEntityById(w, system.SwitchQuery, switchId)
|
||||
if switchEntry == nil {
|
||||
return fmt.Errorf("道岔[%s]的实体不存在", switchId)
|
||||
}
|
||||
relay := components.SwitchRelayStateComponent.Get(switchEntry)
|
||||
relay.DcJ = turnNormal
|
||||
relay.FcJ = !turnNormal
|
||||
//
|
||||
return nil
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package operate
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/system"
|
||||
)
|
||||
|
||||
var towPosButtonsQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.TowPositionButtonStateComponent))
|
||||
|
||||
// 档位变换过程中指令
|
||||
// 该指令执行后,按钮处于未知状态
|
||||
func FireTowPositionButtonMoving(w ecs.World, buttonId string) error {
|
||||
entry := system.QueryEntityById(w, towPosButtonsQuery, buttonId)
|
||||
if nil == entry {
|
||||
return fmt.Errorf("两档位按钮[%s]实体不存在", buttonId)
|
||||
}
|
||||
//
|
||||
state := components.TowPositionButtonStateComponent.Get(entry)
|
||||
state.Pos1 = false
|
||||
state.Pos2 = false
|
||||
//
|
||||
return nil
|
||||
}
|
||||
|
||||
// 档位变换到达pos1指令
|
||||
// 执行该指令后,按钮处于pos1稳定态
|
||||
func FireTowPositionButtonArrivedPos1(w ecs.World, buttonId string) error {
|
||||
return fireTowPositionButtonArrivedPos(w, buttonId, true)
|
||||
}
|
||||
|
||||
// 档位变换到达pos2指令
|
||||
// 执行该指令后,按钮处于pos2稳定态
|
||||
func FireTowPositionButtonArrivedPos2(w ecs.World, buttonId string) error {
|
||||
return fireTowPositionButtonArrivedPos(w, buttonId, false)
|
||||
}
|
||||
func fireTowPositionButtonArrivedPos(w ecs.World, buttonId string, arrivedPos1 bool) error {
|
||||
entry := system.QueryEntityById(w, towPosButtonsQuery, buttonId)
|
||||
if nil == entry {
|
||||
return fmt.Errorf("两档位按钮[%s]实体不存在", buttonId)
|
||||
}
|
||||
//
|
||||
state := components.TowPositionButtonStateComponent.Get(entry)
|
||||
if arrivedPos1 {
|
||||
state.Pos1 = true
|
||||
state.Pos2 = false
|
||||
} else {
|
||||
state.Pos1 = false
|
||||
state.Pos2 = true
|
||||
}
|
||||
//
|
||||
return nil
|
||||
}
|
20
simulation/config.go
Normal file
20
simulation/config.go
Normal file
@ -0,0 +1,20 @@
|
||||
package simulation
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 仿真world配置
|
||||
type WorldConfig struct {
|
||||
//模型管理器,接收模型仓库管理器实例的指针
|
||||
ModelManager umi.IModelManager
|
||||
//world 系统
|
||||
Systems []ecs.ISystem
|
||||
//world tick
|
||||
Tick int
|
||||
//world 起始时间
|
||||
InitTime time.Time
|
||||
}
|
19
simulation/init.go
Normal file
19
simulation/init.go
Normal file
@ -0,0 +1,19 @@
|
||||
package simulation
|
||||
|
||||
import (
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/entities"
|
||||
)
|
||||
|
||||
// 初始化仿真world
|
||||
func InitializeWorld(config *WorldConfig) ecs.World {
|
||||
world := ecs.NewWorld(config.Tick)
|
||||
// 初始化系统
|
||||
for _, sys := range config.Systems {
|
||||
world.AddSystem(sys)
|
||||
}
|
||||
// 初始化系统时间
|
||||
entities.CreateSystemTimerEntity(world, config.InitTime)
|
||||
//
|
||||
return world
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
)
|
||||
|
||||
// 按钮系统
|
||||
type ButtonSystem struct {
|
||||
}
|
||||
|
||||
// 按钮组件
|
||||
var btnIdCom, btnStaCom, btnPreOperCom, btnConOperCom = components.DeviceIdentityComponent,
|
||||
components.ButtonStateComponent, components.ButtonPressOperatingComponent, components.ButtonConfirmOperatingComponent
|
||||
|
||||
// 查询
|
||||
var btnIdQuery = ecs.NewQuery(filter.Contains(btnIdCom))
|
||||
var btnUpdateQuery = ecs.NewQuery(filter.Contains(btnStaCom, btnPreOperCom, btnConOperCom))
|
||||
|
||||
func NewButtonSystem() *ButtonSystem {
|
||||
return &ButtonSystem{}
|
||||
}
|
||||
|
||||
// 按钮操作
|
||||
func PressDownAndUpButton(w ecs.World, btnId string, down bool) bool {
|
||||
buttonEntry := queryButton(w, btnId)
|
||||
if buttonEntry == nil {
|
||||
return false
|
||||
}
|
||||
t, b := getButtonBaseInfo(btnId)
|
||||
if !buttonEntry.HasComponent(btnPreOperCom) { // 操作组件
|
||||
buttonEntry.AddComponent(btnPreOperCom)
|
||||
}
|
||||
preOper := btnPreOperCom.Get(buttonEntry)
|
||||
preOper.Start, preOper.Down, preOper.NeedConfirm, preOper.OperateTime = true, down, b, t
|
||||
return true
|
||||
}
|
||||
|
||||
// 确认操作
|
||||
func ConfirmButton(w ecs.World, btnId string, confirm bool) bool {
|
||||
buttonEntry := queryButton(w, btnId)
|
||||
if buttonEntry == nil {
|
||||
return false
|
||||
}
|
||||
if !buttonEntry.HasComponent(btnConOperCom) { // 确认组件
|
||||
buttonEntry.AddComponent(btnConOperCom)
|
||||
}
|
||||
conOper := btnConOperCom.Get(buttonEntry)
|
||||
conOper.Confirm, conOper.Cancel = confirm, !confirm
|
||||
return true
|
||||
}
|
||||
|
||||
// 更新按钮状态
|
||||
func (bs *ButtonSystem) Update(w ecs.World) {
|
||||
btnUpdateQuery.Each(w, func(e *ecs.Entry) {
|
||||
if e.HasComponent(btnPreOperCom) {
|
||||
btnPreOper := btnPreOperCom.Get(e)
|
||||
if btnPreOper.Start { // 按钮开始操作
|
||||
if btnPreOper.OperateTime <= 0 { // 按钮操作时间大于0
|
||||
btnPreOper.Start, btnPreOper.OperateTime = false, 0
|
||||
} else {
|
||||
btnPreOper.OperateTime -= int64(w.Tick())
|
||||
if btnPreOper.NeedConfirm {
|
||||
conOper := btnConOperCom.Get(e)
|
||||
if e.HasComponent(btnConOperCom) && (conOper.Cancel || conOper.Confirm) {
|
||||
if conOper.Confirm {
|
||||
btnSta := btnStaCom.Get(e)
|
||||
btnSta.PressDown = btnPreOper.Down
|
||||
}
|
||||
btnPreOper.Start, btnPreOper.OperateTime = false, 0
|
||||
conOper.Cancel, conOper.Confirm = false, false
|
||||
e.RemoveComponent(btnPreOperCom)
|
||||
e.RemoveComponent(btnConOperCom)
|
||||
}
|
||||
} else {
|
||||
btnSta := btnStaCom.Get(e)
|
||||
btnSta.PressDown = btnPreOper.Down
|
||||
btnPreOper.Start, btnPreOper.OperateTime = false, 0
|
||||
e.RemoveComponent(btnPreOperCom)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
e.RemoveComponent(btnPreOperCom)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 查找按钮
|
||||
func queryButton(w ecs.World, btnId string) *ecs.Entry {
|
||||
var buttonEntry *ecs.Entry = nil
|
||||
btnIdQuery.Each(w, func(e *ecs.Entry) {
|
||||
if id := btnIdCom.Get(e).Id; id == btnId {
|
||||
buttonEntry = e
|
||||
}
|
||||
})
|
||||
return buttonEntry
|
||||
}
|
||||
|
||||
// 获取按钮设置信息
|
||||
func getButtonBaseInfo(btnId string) (int64, bool) {
|
||||
return 15, false
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
)
|
||||
|
||||
// 调试时显示一些信息
|
||||
type DebugSystem struct {
|
||||
}
|
||||
|
||||
func NewDebugSystem() *DebugSystem {
|
||||
return &DebugSystem{}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *DebugSystem) Update(w ecs.World) {
|
||||
//debugMovableDevice(w)
|
||||
//debugPsd(w)
|
||||
debugSwitch(w)
|
||||
//debugSignal(w)
|
||||
//debugTowPosButton(w)
|
||||
}
|
||||
|
||||
// 可按速度移动组件
|
||||
func debugMovableDevice(w ecs.World) {
|
||||
query := ecs.NewQuery(filter.Contains(components.PercentageDeviceStateComponent, components.MovableDeviceStateComponent))
|
||||
query.Each(w, func(e *ecs.Entry) {
|
||||
id := components.DeviceIdentityComponent.Get(e).Id
|
||||
if "psd1Cell1" == id {
|
||||
percent := components.PercentageDeviceStateComponent.Get(e)
|
||||
movable := components.MovableDeviceStateComponent.Get(e)
|
||||
fmt.Printf("==>>屏蔽门cell [%s],curRateValue = %d ,targetRateValue = %d , speed = %d position = %d\n", id, percent.Rate, percent.Target, movable.Speed, movable.Position)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 两档位按钮旋钮
|
||||
func debugTowPosButton(w ecs.World) {
|
||||
towPosButtonsQuery := ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.TowPositionButtonStateComponent))
|
||||
towPosButtonsQuery.Each(w, func(e *ecs.Entry) {
|
||||
id := components.DeviceIdentityComponent.Get(e).Id
|
||||
state := components.TowPositionButtonStateComponent.Get(e)
|
||||
switch {
|
||||
case state.Pos1 && !state.Pos2:
|
||||
{
|
||||
fmt.Printf("两档位按钮[%s],处于 一 档稳态\n", id)
|
||||
}
|
||||
case !state.Pos1 && state.Pos2:
|
||||
{
|
||||
fmt.Printf("两档位按钮[%s],处于 二 档稳态\n", id)
|
||||
}
|
||||
case !state.Pos1 && !state.Pos2:
|
||||
{
|
||||
fmt.Printf("两档位按钮[%s],处于未知或变换过程中 ......\n", id)
|
||||
}
|
||||
default:
|
||||
{
|
||||
fmt.Printf("两档位按钮[%s],异常同时处于 一二 档 !!\n", id)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 屏蔽门状态
|
||||
func debugPsd(w ecs.World) {
|
||||
psdQuery := ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.PsdStateComponent, components.PsdTagHandlerComponent))
|
||||
psdQuery.Each(w, func(e *ecs.Entry) {
|
||||
psdId := components.DeviceIdentityComponent.Get(e).Id
|
||||
psdState := components.PsdStateComponent.Get(e)
|
||||
psdTag := components.PsdTagHandlerComponent.Get(e).Tag
|
||||
fmt.Printf("屏蔽门[%s] ,全关=%t ,全开=%t ,互锁解除=%t > ", psdId, psdState.AllClosed, psdState.AllOpened, psdState.InterlockReleased)
|
||||
//
|
||||
psdCellQuery := ecs.NewQuery(filter.Contains(psdTag))
|
||||
psdCellQuery.Each(w, func(e *ecs.Entry) {
|
||||
psdCellId := components.DeviceIdentityComponent.Get(e).Id
|
||||
psdCellPercent := components.PercentageDeviceStateComponent.Get(e)
|
||||
psdCellMovable := components.MovableDeviceStateComponent.Get(e)
|
||||
//
|
||||
fmt.Printf("|| cell[%s] ,closeRate=%d ", psdCellId, GetRate(psdCellPercent.Rate))
|
||||
if psdCellMovable.Speed > 0 {
|
||||
if psdCellMovable.ToH {
|
||||
fmt.Printf("== 关门操作中,移动速率=%d", psdCellMovable.Speed)
|
||||
} else {
|
||||
fmt.Printf("== 开门操作中,移动速率=%d", psdCellMovable.Speed)
|
||||
}
|
||||
}
|
||||
|
||||
})
|
||||
//
|
||||
fmt.Println()
|
||||
})
|
||||
}
|
||||
|
||||
// 显示信号机状态
|
||||
func debugSignal(w ecs.World) {
|
||||
siganlQuery := ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.SignalStateComponent))
|
||||
siganlQuery.Each(w, func(e *ecs.Entry) {
|
||||
id := components.DeviceIdentityComponent.Get(e).Id
|
||||
state := components.SignalStateComponent.Get(e)
|
||||
fmt.Printf("==>>信号机[%s],显示=%d\n", id, state.Display)
|
||||
})
|
||||
}
|
||||
|
||||
// 显示道岔状态
|
||||
func debugSwitch(w ecs.World) {
|
||||
switchesQuery := ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent, components.SwitchRelayStateComponent))
|
||||
switchesQuery.Each(w, func(e *ecs.Entry) {
|
||||
percent := components.PercentageDeviceStateComponent.Get(e)
|
||||
movable := components.MovableDeviceStateComponent.Get(e)
|
||||
id := components.DeviceIdentityComponent.Get(e).Id
|
||||
curRate := GetRate(percent.Rate)
|
||||
j := components.SwitchRelayStateComponent.Get(e)
|
||||
fmt.Printf("道岔 [%s],当前位置百分比 [%d] ,Dcj = %t, Fcj = %t, Dbj = %t ,Fbj = %t ,", id, curRate, j.DcJ, j.FcJ, j.DbJ, j.FbJ)
|
||||
if movable.Speed > 0 {
|
||||
fmt.Printf(" ==> 正在转动,移动速率[%d]", movable.Speed)
|
||||
}
|
||||
fmt.Println()
|
||||
})
|
||||
}
|
@ -1,38 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 紧急停车按钮继电器系统
|
||||
type EmpRelaySystem struct {
|
||||
relaySystem
|
||||
// 紧急停车按钮查询
|
||||
query *ecs.Query
|
||||
}
|
||||
|
||||
func NewEmpRelaySystem() *EmpRelaySystem {
|
||||
return &EmpRelaySystem{
|
||||
relaySystem: relaySystem{relayQuery: make(map[string]*ecs.Query)},
|
||||
query: ecs.NewQuery(filter.Contains(components.EmpStateComponent)),
|
||||
}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *EmpRelaySystem) Update(world ecs.World) {
|
||||
me.query.Each(world, func(empEntry *ecs.Entry) {
|
||||
//key-继电器作用名,value-继电器实体
|
||||
usageRelayMapper := make(map[string]*ecs.Entry)
|
||||
//迭代关联的所有继电器
|
||||
me.getDeviceRelayQuery(empEntry).Each(world, func(empRelayEntry *ecs.Entry) {
|
||||
relayId := components.DeviceIdentityComponent.Get(empRelayEntry).Id
|
||||
relayModel := (WorldModelStorage(world).FindById(relayId)).(umi.IRelayModel)
|
||||
usageRelayMapper[relayModel.UsageName()] = empRelayEntry
|
||||
})
|
||||
//根据具体业务逻辑处理继电器
|
||||
|
||||
})
|
||||
}
|
27
system/event/relay_event.go
Normal file
27
system/event/relay_event.go
Normal file
@ -0,0 +1,27 @@
|
||||
package sysEvent
|
||||
|
||||
import "joylink.club/ecs"
|
||||
|
||||
//继电器动作事件
|
||||
//由继电器实体系统产生,表示继电器吸合落下动作
|
||||
type RelayActionEvent struct {
|
||||
//继电器id
|
||||
Id string
|
||||
//true -吸合
|
||||
Xh bool
|
||||
}
|
||||
|
||||
//继电器状态须改变事件
|
||||
//由电路系统运算发现某个继电器需要改变,则由电路系统产生该事件来通知对应继电器产生对应动作
|
||||
type RelayNeedChangeEvent struct {
|
||||
//继电器id
|
||||
Id string
|
||||
//true -吸合
|
||||
Xh bool
|
||||
}
|
||||
|
||||
//继电器动作事件总线
|
||||
var RelayActionEventBus = ecs.NewEventType[RelayActionEvent]()
|
||||
|
||||
//继电器状态须改变事件总线
|
||||
var RelayNeedChangeEventBus = ecs.NewEventType[RelayNeedChangeEvent]()
|
18
system/event/signal_3xh1_event.go
Normal file
18
system/event/signal_3xh1_event.go
Normal file
@ -0,0 +1,18 @@
|
||||
package sysEvent
|
||||
|
||||
import "joylink.club/ecs"
|
||||
|
||||
//信号机3XH1显示状态变化事件
|
||||
type Signal3XH1AspectChangedEvent struct {
|
||||
//信号机id
|
||||
Id string
|
||||
// 物理黄灯,true-亮
|
||||
U bool
|
||||
// 物理绿灯,true-亮
|
||||
L bool
|
||||
// 物理红灯,true-亮
|
||||
H bool
|
||||
}
|
||||
|
||||
//信号机3XH1显示状态变化事件总线
|
||||
var Signal3XH1AspectChangedEventBus = ecs.NewEventType[Signal3XH1AspectChangedEvent]()
|
@ -1,31 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
)
|
||||
|
||||
// 按速度移动的设备系统
|
||||
// 只负责按速度移动位置,由该组件的观察者负责解释位置
|
||||
type MovableDeviceSystem struct {
|
||||
query *ecs.Query
|
||||
}
|
||||
|
||||
func NewMovableDeviceSystem() *MovableDeviceSystem {
|
||||
return &MovableDeviceSystem{query: ecs.NewQuery(filter.Contains(components.MovableDeviceStateComponent))}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *MovableDeviceSystem) Update(world ecs.World) {
|
||||
me.query.Each(world, func(e *ecs.Entry) {
|
||||
md := components.MovableDeviceStateComponent.Get(e)
|
||||
if md.Speed > 0 {
|
||||
if md.ToH {
|
||||
md.Position += int64(md.Speed)
|
||||
} else {
|
||||
md.Position -= int64(md.Speed)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
75
system/move_system.go
Normal file
75
system/move_system.go
Normal file
@ -0,0 +1,75 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
)
|
||||
|
||||
// 时间维度上移动的物体
|
||||
type MovableObject struct {
|
||||
Value int64
|
||||
//移动方向:0-不动,1-变大,-1 -变小
|
||||
direction int8
|
||||
}
|
||||
|
||||
func NewMovableObject() *MovableObject {
|
||||
return &MovableObject{Value: 0, direction: 0}
|
||||
}
|
||||
|
||||
// 时间维度上移动物体组件
|
||||
var MovableObjectComponent = ecs.NewComponentType[MovableObject]()
|
||||
var MovableObject1Component = ecs.NewComponentType[MovableObject]()
|
||||
var MovableObject2Component = ecs.NewComponentType[MovableObject]()
|
||||
|
||||
type TimeMovableSystem struct {
|
||||
query *ecs.Query
|
||||
}
|
||||
|
||||
func NewTimeMovableSystem() *TimeMovableSystem {
|
||||
return &TimeMovableSystem{
|
||||
query: ecs.NewQuery(filter.Or(filter.Contains(MovableObjectComponent), filter.Contains(MovableObject1Component), filter.Contains(MovableObject2Component))),
|
||||
}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *TimeMovableSystem) Update(w ecs.World) {
|
||||
me.query.Each(w, func(e *ecs.Entry) {
|
||||
|
||||
if e.HasComponent(MovableObjectComponent) {
|
||||
MovableObjectComponent.Get(e).move(w.Tick())
|
||||
}
|
||||
if e.HasComponent(MovableObject1Component) {
|
||||
MovableObject1Component.Get(e).move(w.Tick())
|
||||
}
|
||||
if e.HasComponent(MovableObject2Component) {
|
||||
MovableObject2Component.Get(e).move(w.Tick())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////
|
||||
|
||||
func (me *MovableObject) move(tick int) {
|
||||
if me.direction != 0 {
|
||||
if me.direction > 0 {
|
||||
me.Value += int64(tick)
|
||||
} else {
|
||||
me.Value -= int64(tick)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 暂停
|
||||
func (me *MovableObject) Pause() {
|
||||
me.direction = 0
|
||||
}
|
||||
|
||||
// 前进
|
||||
func (me *MovableObject) Forward() {
|
||||
me.direction = 1
|
||||
}
|
||||
|
||||
// 后退
|
||||
func (me *MovableObject) Retreat() {
|
||||
me.direction = -1
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
)
|
||||
|
||||
type PercentageDeviceSystem struct {
|
||||
query *ecs.Query
|
||||
}
|
||||
|
||||
func NewPercentageDeviceSystem() *PercentageDeviceSystem {
|
||||
return &PercentageDeviceSystem{query: ecs.NewQuery(filter.Contains(components.PercentageDeviceStateComponent, components.MovableDeviceStateComponent))}
|
||||
}
|
||||
|
||||
const (
|
||||
PercentageRateValueMax int64 = 100000
|
||||
PercentageRateValueMin int64 = 0
|
||||
)
|
||||
const (
|
||||
PercentageRateMax int8 = 100
|
||||
PercentageRateMin int8 = 0
|
||||
)
|
||||
|
||||
// world 执行
|
||||
func (me *PercentageDeviceSystem) Update(world ecs.World) {
|
||||
me.query.Each(world, func(e *ecs.Entry) {
|
||||
movable := components.MovableDeviceStateComponent.Get(e)
|
||||
if movable.Speed > 0 {
|
||||
percentage := components.PercentageDeviceStateComponent.Get(e)
|
||||
if movable.ToH {
|
||||
if movable.Position >= percentage.Target {
|
||||
movable.Speed = 0
|
||||
movable.Position = percentage.Target
|
||||
}
|
||||
} else {
|
||||
if movable.Position <= percentage.Target {
|
||||
movable.Speed = 0
|
||||
movable.Position = percentage.Target
|
||||
}
|
||||
}
|
||||
//
|
||||
percentage.Rate = movable.Position
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
// 映射百分比到大数值
|
||||
func GetRateValue(rate int8) int64 {
|
||||
return int64(float64(float32(rate)/float32(100)) * float64(PercentageRateValueMax))
|
||||
}
|
||||
|
||||
// 大数值映射到百分比
|
||||
func GetRate(rateValue int64) int8 {
|
||||
return int8((float64(rateValue) / float64(PercentageRateValueMax)) * float64(100))
|
||||
}
|
||||
|
||||
// 比率值变动速率计算
|
||||
func CalculateRateSpeed(tick int32, lhDistance int64) int32 {
|
||||
return int32(float64(tick) * (float64(PercentageRateValueMax) / float64(lhDistance)))
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/components/cstate"
|
||||
)
|
||||
|
||||
var PsdQuery = ecs.NewQuery(filter.Contains(components.PsdStateComponent, components.PsdTagHandlerComponent))
|
||||
|
||||
const (
|
||||
//屏蔽门完全关闭
|
||||
PsdCellWholeCloseValue = PercentageRateValueMax
|
||||
//屏蔽门完全打开
|
||||
PsdCellWholeOpenValue = PercentageRateValueMin
|
||||
)
|
||||
|
||||
type PsdSystem struct {
|
||||
cellsQuery map[cstate.EntityTag]*ecs.Query
|
||||
}
|
||||
|
||||
func NewPsdSystem() *PsdSystem {
|
||||
return &PsdSystem{cellsQuery: make(map[cstate.EntityTag]*ecs.Query)}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *PsdSystem) Update(world ecs.World) {
|
||||
PsdQuery.Each(world, func(psdEntry *ecs.Entry) {
|
||||
psdTag := components.PsdTagHandlerComponent.Get(psdEntry).Tag
|
||||
psdCellQuery, ok := me.cellsQuery[psdTag]
|
||||
if !ok {
|
||||
psdCellQuery = ecs.NewQuery(filter.Contains(psdTag, components.PercentageDeviceStateComponent, components.MovableDeviceStateComponent))
|
||||
me.cellsQuery[psdTag] = psdCellQuery
|
||||
}
|
||||
//
|
||||
var allCellClosed, allCellOpened bool = true, true
|
||||
psdCellQuery.Each(world, func(psdCellEntry *ecs.Entry) {
|
||||
psdCellRate := components.PercentageDeviceStateComponent.Get(psdCellEntry).Rate
|
||||
if allCellClosed {
|
||||
allCellClosed = psdCellRate == PsdCellWholeCloseValue
|
||||
}
|
||||
if allCellOpened {
|
||||
allCellOpened = psdCellRate == PsdCellWholeOpenValue
|
||||
}
|
||||
})
|
||||
//
|
||||
psdState := components.PsdStateComponent.Get(psdEntry)
|
||||
psdState.AllClosed = allCellClosed
|
||||
psdState.AllOpened = allCellOpened
|
||||
})
|
||||
}
|
64
system/relay_system.go
Normal file
64
system/relay_system.go
Normal file
@ -0,0 +1,64 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
sysEvent "joylink.club/rtsssimulation/system/event"
|
||||
)
|
||||
|
||||
// 继电器有两个线圈1-2,3-4
|
||||
// 电流方向1->2,3->4或4->3,2->1时产生同向磁场
|
||||
type RelayState struct {
|
||||
//继电器是否吸合
|
||||
//true-吸合
|
||||
Xh bool
|
||||
//true-进行吸合动作,false-进行落下动作
|
||||
needXh bool
|
||||
}
|
||||
|
||||
// 继电器状态组件
|
||||
var RelayStateComponent = ecs.NewComponentType[RelayState]()
|
||||
|
||||
// 继电器系统
|
||||
type RelaySystem struct {
|
||||
relayQuery *ecs.Query
|
||||
}
|
||||
|
||||
// 继电器常量定义
|
||||
const (
|
||||
//JWXC-1700无极缓放继电器,缓放时间ms
|
||||
JWXC_1700_RELEASE_TIME int64 = 300
|
||||
//JWJXC-H125/80无极加强缓放继电器,缓放时间ms
|
||||
JWJXC_H125_80_RELEASE_TIME int64 = 300
|
||||
//整流式缓放继电器,缓放时间ms
|
||||
JZXC_H18_RELEASE_TIME int64 = 300
|
||||
//JPXC-1000偏极继电器,缓放时间ms
|
||||
JPXC_1000_RELEASE_TIME int64 = 500
|
||||
)
|
||||
|
||||
func NewRelaySystem() *RelaySystem {
|
||||
return &RelaySystem{
|
||||
relayQuery: ecs.NewQuery(filter.Contains(EntityIdentityComponent, RelayStateComponent)),
|
||||
}
|
||||
}
|
||||
|
||||
// 继电器须要改变事件处理
|
||||
var RelayNeedChangeEventProcessor = func(w ecs.World, event sysEvent.RelayNeedChangeEvent) {
|
||||
relayEntry := FindEntityById(w, event.Id)
|
||||
relayState := RelayStateComponent.Get(relayEntry)
|
||||
relayState.needXh = event.Xh
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *RelaySystem) Update(w ecs.World) {
|
||||
me.relayQuery.Each(w, func(e *ecs.Entry) {
|
||||
relayState := RelayStateComponent.Get(e)
|
||||
//实际与目标不符,须动作
|
||||
if relayState.needXh != relayState.Xh {
|
||||
relayState.Xh = relayState.needXh
|
||||
//发送动作事件
|
||||
relayId := EntityIdentityComponent.Get(e).Id
|
||||
sysEvent.RelayActionEventBus.Publish(w, &sysEvent.RelayActionEvent{Id: relayId, Xh: relayState.Xh})
|
||||
}
|
||||
})
|
||||
}
|
192
system/signal_3xh1_system.go
Normal file
192
system/signal_3xh1_system.go
Normal file
@ -0,0 +1,192 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
sysEvent "joylink.club/rtsssimulation/system/event"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 信号机电路继电器组合类型和功能名称常量
|
||||
// 其他信号机的一并定义于此
|
||||
const (
|
||||
//继电器组合类型
|
||||
SIGNAL_3XH1 = "3XH-1"
|
||||
SIGNAL_3XH2 = "3XH-2"
|
||||
SIGNAL_3XH3 = "3XH-3"
|
||||
SIGNAL_3XH4 = "3XH-4"
|
||||
SIGNAL_2XH1 = "2XH-1"
|
||||
//继电器功能名称
|
||||
SIGNAL_DDJ = "DDJ"
|
||||
SIGNAL_DJ = "DJ"
|
||||
SIGNAL_2DJ = "2DJ"
|
||||
SIGNAL_LXJ = "LXJ"
|
||||
SIGNAL_YXJ = "YXJ"
|
||||
SIGNAL_ZXJ = "ZXJ"
|
||||
)
|
||||
|
||||
// 电路状态:信号机3XH-1(红-绿-黄) 道岔防护信号机(三显示不封灯,有单黄显示、带引导)
|
||||
type Signal3XH1State struct {
|
||||
// 物理黄灯,true-亮
|
||||
U bool
|
||||
// 物理绿灯,true-亮
|
||||
L bool
|
||||
// 物理红灯,true-亮
|
||||
H bool
|
||||
// 点灯继电器,true-吸合,常态落下表示逻辑点灯
|
||||
DDJ bool
|
||||
//2DJ灯丝继电器,true-吸合
|
||||
EDJ bool
|
||||
//灯丝继电器,true-吸合
|
||||
DJ bool
|
||||
//列车信号继电器,true-吸合
|
||||
LXJ bool
|
||||
//引导信号继电器,true-吸合
|
||||
YXJ bool
|
||||
//开通正线信号继电器,true-吸合
|
||||
ZXJ bool
|
||||
}
|
||||
|
||||
func NewSignal3XH1State() *Signal3XH1State {
|
||||
return &Signal3XH1State{
|
||||
U: false,
|
||||
L: false,
|
||||
H: false,
|
||||
DDJ: true,
|
||||
EDJ: false,
|
||||
DJ: false,
|
||||
LXJ: false,
|
||||
YXJ: false,
|
||||
ZXJ: false,
|
||||
}
|
||||
}
|
||||
|
||||
// 信号机3XH-1电路状态组件
|
||||
var Signal3XH1StateComponent = ecs.NewComponentType[Signal3XH1State]()
|
||||
var signal3XH1Query = ecs.NewQuery(filter.Contains(EntityIdentityComponent, Signal3XH1StateComponent))
|
||||
|
||||
type Signal3XH1System struct {
|
||||
}
|
||||
|
||||
func NewSignal3XH1System() *Signal3XH1System {
|
||||
return &Signal3XH1System{}
|
||||
}
|
||||
|
||||
// 继电器动作事件处理
|
||||
// 将继电器动作的结果同步到系统
|
||||
var Signal3XH1RelayActionEventProcessor = func(w ecs.World, event sysEvent.RelayActionEvent) {
|
||||
//根据event来更新Signal3XH1State中对应继电器的状态
|
||||
signal3XH1Query.Each(w, func(e *ecs.Entry) {
|
||||
signalModel := FindModelStorage(w).FindById(EntityIdentityComponent.Get(e).Id)
|
||||
roler, ok := signalModel.(umi.IRelayCRole)
|
||||
if ok {
|
||||
if relayGroup, relayName, find := roler.FindCircuitRoleById(event.Id); find {
|
||||
if relayGroup == SIGNAL_3XH1 {
|
||||
state := Signal3XH1StateComponent.Get(e)
|
||||
switch relayName {
|
||||
case SIGNAL_DDJ:
|
||||
state.DDJ = event.Xh
|
||||
case SIGNAL_DJ:
|
||||
state.DJ = event.Xh
|
||||
case SIGNAL_2DJ:
|
||||
state.EDJ = event.Xh
|
||||
case SIGNAL_LXJ:
|
||||
state.LXJ = event.Xh
|
||||
case SIGNAL_YXJ:
|
||||
state.YXJ = event.Xh
|
||||
case SIGNAL_ZXJ:
|
||||
state.ZXJ = event.Xh
|
||||
default:
|
||||
panic(fmt.Sprintf("Signal3XH1的模型[%s]中继电器功能名称[%s]无法识别", signalModel.GetId(), relayName))
|
||||
}
|
||||
} else {
|
||||
panic(fmt.Sprintf("Signal3XH1的模型[%s]中继电器组合类型[%s]无法识别", signalModel.GetId(), relayGroup))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
panic("Signal3XH1的模型未实现接口umi.IRelayCRoler")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *Signal3XH1System) Update(w ecs.World) {
|
||||
signal3XH1Query.Each(w, func(e *ecs.Entry) {
|
||||
signal3XH1State := Signal3XH1StateComponent.Get(e)
|
||||
//
|
||||
_U := signal3XH1State.U
|
||||
_L := signal3XH1State.L
|
||||
_H := signal3XH1State.H
|
||||
//
|
||||
me.calculateU(w, signal3XH1State)
|
||||
me.calculateL(w, signal3XH1State)
|
||||
me.calculateH(w, signal3XH1State)
|
||||
me.calculateDJ(w, e, signal3XH1State)
|
||||
me.calculate2DJ(w, e, signal3XH1State)
|
||||
//状态改变发送事件
|
||||
if _U != signal3XH1State.U || _H != signal3XH1State.H || _L != signal3XH1State.L {
|
||||
signalId := EntityIdentityComponent.Get(e).Id
|
||||
sysEvent.Signal3XH1AspectChangedEventBus.Publish(w, &sysEvent.Signal3XH1AspectChangedEvent{
|
||||
Id: signalId,
|
||||
U: signal3XH1State.U,
|
||||
L: signal3XH1State.L,
|
||||
H: signal3XH1State.H,
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 黄灯点灯电路
|
||||
// 开放引导信号,黄灯亮且红灯亮
|
||||
// 开放列车信号且开通侧向,只黄灯亮
|
||||
func (me *Signal3XH1System) calculateU(w ecs.World, state *Signal3XH1State) {
|
||||
//引导信号
|
||||
isY := !state.DDJ && !state.LXJ && state.DJ && state.YXJ
|
||||
//侧向行车信号
|
||||
isLC := !state.DDJ && state.LXJ && !state.ZXJ
|
||||
state.U = isY || isLC
|
||||
}
|
||||
|
||||
// 绿灯点灯电路
|
||||
// 开放正线行车信号,只亮绿灯
|
||||
func (me *Signal3XH1System) calculateL(w ecs.World, state *Signal3XH1State) {
|
||||
isL := !state.DDJ && state.LXJ && state.ZXJ
|
||||
state.L = isL
|
||||
}
|
||||
|
||||
// 红灯点灯电路
|
||||
// 列车信号禁止时,亮红灯
|
||||
func (me *Signal3XH1System) calculateH(w ecs.World, state *Signal3XH1State) {
|
||||
isH := !state.DDJ && !state.LXJ
|
||||
state.H = isH
|
||||
}
|
||||
|
||||
// DJ 灯丝继电器电路
|
||||
func (me *Signal3XH1System) calculateDJ(w ecs.World, e *ecs.Entry, state *Signal3XH1State) {
|
||||
_DJ := state.DJ
|
||||
//
|
||||
isDj := !state.DDJ
|
||||
//通知继电器进行动作
|
||||
if _DJ != isDj {
|
||||
signalModel := FindModelStorage(w).FindById(EntityIdentityComponent.Get(e).Id)
|
||||
relayRole, _ := signalModel.(umi.IRelayCRole)
|
||||
relayModel := relayRole.FindRelayModelByCRole(SIGNAL_3XH1, SIGNAL_DJ)
|
||||
sysEvent.RelayNeedChangeEventBus.Publish(w, &sysEvent.RelayNeedChangeEvent{Id: relayModel.(umi.IDeviceModel).GetId(), Xh: isDj})
|
||||
}
|
||||
}
|
||||
|
||||
// 2DJ 灯丝继电器电路
|
||||
func (me *Signal3XH1System) calculate2DJ(w ecs.World, e *ecs.Entry, state *Signal3XH1State) {
|
||||
_2DJ := state.EDJ
|
||||
//
|
||||
is2DJ := state.U
|
||||
//通知继电器进行动作
|
||||
if _2DJ != is2DJ {
|
||||
signalModel := FindModelStorage(w).FindById(EntityIdentityComponent.Get(e).Id)
|
||||
relayRole, _ := signalModel.(umi.IRelayCRole)
|
||||
relayModel := relayRole.FindRelayModelByCRole(SIGNAL_3XH1, SIGNAL_2DJ)
|
||||
sysEvent.RelayNeedChangeEventBus.Publish(w, &sysEvent.RelayNeedChangeEvent{Id: relayModel.(umi.IDeviceModel).GetId(), Xh: is2DJ})
|
||||
}
|
||||
}
|
793
system/switch_2jzdj9_system.go
Normal file
793
system/switch_2jzdj9_system.go
Normal file
@ -0,0 +1,793 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
sysEvent "joylink.club/rtsssimulation/system/event"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 双机ZDJ9道岔电路系统状态定义
|
||||
// 继电器: true-吸合;false-未吸合
|
||||
type Switch2jZdj9State struct {
|
||||
//定操继电器
|
||||
DCJ bool
|
||||
//反操继电器
|
||||
FCJ bool
|
||||
//允许操作继电器
|
||||
YCJ bool
|
||||
//总定表继电器
|
||||
ZDBJ bool
|
||||
//总反表继电器
|
||||
ZFBJ bool
|
||||
//道岔第一启动继电器
|
||||
J1_1DQJ bool
|
||||
//道岔保护继电器
|
||||
J1_BHJ bool
|
||||
//道岔第二启动继电器
|
||||
//true-吸起即1-3通;false-打落即1-2通
|
||||
J1_2DQJ bool
|
||||
//true-2DQJ由落下转换到吸起,即定操
|
||||
J1_2DQJ_ToD bool
|
||||
//true-2DQJ由吸起转换到落下,即反操
|
||||
J1_2DQJ_ToF bool
|
||||
//道岔第一启动继电器复示继电器
|
||||
J1_1DQJF bool
|
||||
//断相保护器
|
||||
J1_DBQ DBQState
|
||||
//定位表示继电器
|
||||
J1_DBJ bool
|
||||
//true-当道岔转换到定位时,转辙机内端子9与电路接通;false-转辙机内端子9断开切断电路
|
||||
J1_DB_K9 bool
|
||||
//转辙机内部自动开闭器
|
||||
//true-接通1、3排表示电路,用于定操;false-接通2、4排表示电路,用于反操
|
||||
J1_AKB bool
|
||||
//道岔电机1的电源
|
||||
J1_Power Switch380ACPower
|
||||
//电机线圈相电流
|
||||
J1_U1 Switch380ACPhase
|
||||
J1_V1 Switch380ACPhase
|
||||
J1_W1 Switch380ACPhase
|
||||
//电机输出牵引力,大于0表示正转即定操,小于0表示反转即反操,等于0表示不转
|
||||
J1_Traction int8
|
||||
//反位表示继电器
|
||||
J1_FBJ bool
|
||||
//true-当道岔转换到反位时,转辙机内端子10与电路接通;false-转辙机内端子10断开切断电路
|
||||
J1_FB_K10 bool
|
||||
//道岔启动切断继电器
|
||||
J1_QDJ bool
|
||||
//道岔启动切断继电器的LC震荡电路保磁剩余时间,单位ms
|
||||
//最长保持时长3000ms
|
||||
J1_QDJ_LcTime int64
|
||||
//总保护继电器
|
||||
J1_ZBHJ bool
|
||||
//道岔第一启动继电器
|
||||
J2_1DQJ bool
|
||||
//道岔保护继电器
|
||||
J2_BHJ bool
|
||||
//道岔第二启动继电器
|
||||
//true-吸起即1-3通;false-打落即1-2通
|
||||
J2_2DQJ bool
|
||||
//true-2DQJ由落下转换到吸起,即定操
|
||||
J2_2DQJ_ToD bool
|
||||
//true-2DQJ由吸起转换到落下,即反操
|
||||
J2_2DQJ_ToF bool
|
||||
//道岔第一启动继电器复示继电器
|
||||
J2_1DQJF bool
|
||||
//断相保护器
|
||||
J2_DBQ DBQState
|
||||
//定位表示继电器
|
||||
J2_DBJ bool
|
||||
//true-当道岔转换到定位时,转辙机内端子9与电路接通;false-转辙机内端子9断开切断电路
|
||||
J2_DB_K9 bool
|
||||
//反位表示继电器
|
||||
J2_FBJ bool
|
||||
//true-当道岔转换到反位时,转辙机内端子10与电路接通;false-转辙机内端子10断开切断电路
|
||||
J2_FB_K10 bool
|
||||
//转辙机内部自动开闭器
|
||||
//true-接通1、3排表示电路,用于定操;false-接通2、4排表示电路,用于反操
|
||||
J2_AKB bool
|
||||
//道岔电机2的电源
|
||||
J2_Power Switch380ACPower
|
||||
//电机线圈相电流
|
||||
J2_U1 Switch380ACPhase
|
||||
J2_V1 Switch380ACPhase
|
||||
J2_W1 Switch380ACPhase
|
||||
//电机转速,大于0表示正转即定操,小于0表示反转即反操,等于0表示不转
|
||||
J2_Traction int8
|
||||
}
|
||||
|
||||
// 创建ZDJ9道岔状态并初始化
|
||||
func NewSwitch2jZdj9State() *Switch2jZdj9State {
|
||||
return &Switch2jZdj9State{
|
||||
DCJ: false,
|
||||
FCJ: false,
|
||||
YCJ: false,
|
||||
ZDBJ: true,
|
||||
ZFBJ: false,
|
||||
J1_1DQJ: false,
|
||||
J1_BHJ: false,
|
||||
J1_2DQJ: true,
|
||||
J1_2DQJ_ToD: false,
|
||||
J1_2DQJ_ToF: false,
|
||||
J1_1DQJF: false,
|
||||
J1_DBQ: DBQState{PhaseLoss: true, LimitedTime: 0, Dc24Voltage: false},
|
||||
J1_DBJ: true,
|
||||
J1_DB_K9: true,
|
||||
J1_AKB: true,
|
||||
J1_Power: Switch380ACPower{Active: false, PhaseA: false, PhaseB: false, PhaseC: false},
|
||||
J1_U1: ACPahseN,
|
||||
J1_V1: ACPahseN,
|
||||
J1_W1: ACPahseN,
|
||||
J1_Traction: 0,
|
||||
J1_FBJ: false,
|
||||
J1_FB_K10: false,
|
||||
J1_QDJ: true,
|
||||
J1_QDJ_LcTime: 0,
|
||||
J1_ZBHJ: false,
|
||||
J2_1DQJ: false,
|
||||
J2_BHJ: false,
|
||||
J2_2DQJ: true,
|
||||
J2_2DQJ_ToD: false,
|
||||
J2_2DQJ_ToF: false,
|
||||
J2_1DQJF: false,
|
||||
J2_DBQ: DBQState{PhaseLoss: true, LimitedTime: 0, Dc24Voltage: false},
|
||||
J2_DBJ: true,
|
||||
J2_DB_K9: true,
|
||||
J2_FBJ: false,
|
||||
J2_FB_K10: false,
|
||||
J2_AKB: true,
|
||||
J2_Power: Switch380ACPower{Active: false, PhaseA: false, PhaseB: false, PhaseC: false},
|
||||
J2_U1: ACPahseN,
|
||||
J2_V1: ACPahseN,
|
||||
J2_W1: ACPahseN,
|
||||
J2_Traction: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// 带限时功能断相保护器
|
||||
// 限时13秒
|
||||
type DBQState struct {
|
||||
//是否缺相,true-缺相,false-三相电正常未缺相
|
||||
PhaseLoss bool
|
||||
//剩余限时时间,单位ms
|
||||
LimitedTime int64
|
||||
//当三相电正常时,断相保护器内的24V直流整流电路会正常输出24V直流电
|
||||
//当三相电不正常如缺相时,断相保护器内的24V直流整流电路不会输出24V直流电
|
||||
//BHJ道岔保护继电器的励磁线圈由该24V直流供电
|
||||
Dc24Voltage bool
|
||||
}
|
||||
|
||||
// 表示电路变压器,变压比2:1,将220V交流电变压后作为为道岔表示电路的电源
|
||||
// 0-无电源;规定52端子为正,则,1-输出瞬时正电压;-1 - 输出瞬时负电压
|
||||
type SwitchBB struct {
|
||||
//true-变压器初级输入正常
|
||||
InDj220V bool
|
||||
//次级输出电压
|
||||
//0-无电源;规定52端子为正,则,1-输出瞬时正电压;-1 - 输出瞬时负电压
|
||||
OutBb int8
|
||||
}
|
||||
|
||||
// 道岔380V动力交流电源
|
||||
type Switch380ACPower struct {
|
||||
//true-激活
|
||||
Active bool
|
||||
//true-A相电正常输出
|
||||
PhaseA bool
|
||||
//true-B相电正常输出
|
||||
PhaseB bool
|
||||
//true-C相电正常输出
|
||||
PhaseC bool
|
||||
}
|
||||
|
||||
// 道岔380V动力交流电相位定义
|
||||
type Switch380ACPhase int8
|
||||
|
||||
const (
|
||||
//不存在相位交流电
|
||||
ACPahseN Switch380ACPhase = iota
|
||||
//存在A相位交流电
|
||||
ACPahseA
|
||||
//存在B相位交流电
|
||||
ACPahseB
|
||||
//存在C相位交流电
|
||||
ACPahseC
|
||||
)
|
||||
|
||||
// 继电器常量定义
|
||||
const (
|
||||
//QDJ 电源切断继电器LC震荡电路有效震荡时间ms
|
||||
QDJ_LC_TIME int64 = 3000
|
||||
//断相保护器限时,单位ms
|
||||
DBQ_LIMITED_TIME = 13 * 1000
|
||||
)
|
||||
|
||||
// 道岔ZDJ9电路状态组件
|
||||
var Switch2jZdj9StateComponent = ecs.NewComponentType[Switch2jZdj9State]()
|
||||
|
||||
// zdj9查询
|
||||
var zdj9Query = ecs.NewQuery(filter.Contains(EntityIdentityComponent, Switch2jZdj9StateComponent))
|
||||
|
||||
// 双机ZDJ9道岔系统
|
||||
type Switch2jZdj9System struct {
|
||||
}
|
||||
|
||||
// 双机ZDJ9道岔系统
|
||||
func NewSwitch2jZdj9System() *Switch2jZdj9System {
|
||||
return &Switch2jZdj9System{}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *Switch2jZdj9System) Update(w ecs.World) {
|
||||
zdj9Query.Each(w, func(e *ecs.Entry) {
|
||||
zdj9State := Switch2jZdj9StateComponent.Get(e)
|
||||
//电机电源
|
||||
me.calculateJPower(w, e, zdj9State)
|
||||
//断相保护器电路
|
||||
me.calculateDBQ(w, e, zdj9State)
|
||||
//断相保护继电器励磁电路
|
||||
me.calculateBHJ(w, e, zdj9State)
|
||||
//总保护继电器励磁电路
|
||||
me.calculateZBHJ(w, e, zdj9State)
|
||||
//道岔转换启动切断继电器励磁电路
|
||||
me.calculateQDJ(w, e, zdj9State)
|
||||
//道岔第一启动继电器励磁电路
|
||||
me.calculate1DQJ(w, e, zdj9State)
|
||||
//道岔第一启动继电器复示继电器励磁电路
|
||||
me.calculate1DQJF(w, e, zdj9State)
|
||||
//道岔第二启动继电器励磁电路
|
||||
me.calculate2DQJ(w, e, zdj9State)
|
||||
//转辙机内自动开闭器
|
||||
me.calculateAKB(w, e, zdj9State)
|
||||
//道岔转辙机定表反表继电器励磁电路
|
||||
me.calculateDBJ(w, e, zdj9State)
|
||||
me.calculateFBJ(w, e, zdj9State)
|
||||
//总定表/总反表继电器励磁电路
|
||||
me.calculateZDBJ(w, e, zdj9State)
|
||||
me.calculateZFBJ(w, e, zdj9State)
|
||||
//道岔转辙机内电机驱动电路
|
||||
me.calculateMotor(w, e, zdj9State)
|
||||
me.calculateMove(w, e, zdj9State)
|
||||
me.calculateK9K10(w, e, zdj9State)
|
||||
})
|
||||
}
|
||||
|
||||
// SJZDJ9双机zdj9
|
||||
const (
|
||||
//继电器组合类型
|
||||
SJZDJ9_TDC = "TDC"
|
||||
SJZDJ9_TDFJ1 = "TDFJ1"
|
||||
SJZDJ9_TDFJ2 = "TDFJ2"
|
||||
//继电器功能名称
|
||||
SJZDJ9_1DQJ = "1DQJ"
|
||||
SJZDJ9_BHJ = "BHJ"
|
||||
SJZDJ9_2DQJ = "2DQJ"
|
||||
SJZDJ9_1DQJF = "1DQJF"
|
||||
SJZDJ9_DBJ = "DBJ"
|
||||
SJZDJ9_FBJ = "FBJ"
|
||||
SJZDJ9_QDJ = "QDJ"
|
||||
SJZDJ9_ZBHJ = "ZBHJ"
|
||||
SJZDJ9_DCJ = "DCJ"
|
||||
SJZDJ9_FCJ = "FCJ"
|
||||
SJZDJ9_YCJ = "YCJ"
|
||||
SJZDJ9_ZDBJ = "ZDBJ"
|
||||
SJZDJ9_ZFBJ = "ZFBJ"
|
||||
)
|
||||
|
||||
// 接收继电器动作事件
|
||||
var Switch2jzdj9RelayActionEventProcessor = func(w ecs.World, event sysEvent.RelayActionEvent) {
|
||||
zdj9Query.Each(w, func(e *ecs.Entry) {
|
||||
switchModel := FindModelStorage(w).FindById(EntityIdentityComponent.Get(e).Id)
|
||||
roler, ok := switchModel.(umi.IRelayCRole)
|
||||
if ok {
|
||||
if relayGroup, relayName, find := roler.FindCircuitRoleById(event.Id); find {
|
||||
state := Switch2jZdj9StateComponent.Get(e)
|
||||
switch relayGroup {
|
||||
case SJZDJ9_TDC:
|
||||
{
|
||||
switch relayName {
|
||||
case SJZDJ9_DCJ:
|
||||
state.DCJ = event.Xh
|
||||
case SJZDJ9_FCJ:
|
||||
state.FCJ = event.Xh
|
||||
case SJZDJ9_YCJ:
|
||||
state.YCJ = event.Xh
|
||||
case SJZDJ9_ZDBJ:
|
||||
state.ZDBJ = event.Xh
|
||||
case SJZDJ9_ZFBJ:
|
||||
state.ZFBJ = event.Xh
|
||||
default:
|
||||
panic(fmt.Sprintf("SwitchZdj9的模型[%s]中继电器功能名称[%s]无法识别", switchModel.GetId(), relayName))
|
||||
}
|
||||
}
|
||||
case SJZDJ9_TDFJ1:
|
||||
{
|
||||
switch relayName {
|
||||
case SJZDJ9_1DQJ:
|
||||
state.J1_1DQJ = event.Xh
|
||||
case SJZDJ9_BHJ:
|
||||
state.J1_BHJ = event.Xh
|
||||
case SJZDJ9_2DQJ:
|
||||
{
|
||||
state.J1_2DQJ_ToD = !state.J1_2DQJ && event.Xh
|
||||
state.J1_2DQJ_ToF = state.J1_2DQJ && !event.Xh
|
||||
state.J1_2DQJ = event.Xh
|
||||
}
|
||||
case SJZDJ9_1DQJF:
|
||||
state.J1_1DQJF = event.Xh
|
||||
case SJZDJ9_DBJ:
|
||||
state.J1_DBJ = event.Xh
|
||||
case SJZDJ9_FBJ:
|
||||
state.J1_FBJ = event.Xh
|
||||
case SJZDJ9_QDJ:
|
||||
state.J1_QDJ = event.Xh
|
||||
case SJZDJ9_ZBHJ:
|
||||
state.J1_ZBHJ = event.Xh
|
||||
default:
|
||||
panic(fmt.Sprintf("SwitchZdj9的模型[%s]中继电器功能名称[%s]无法识别", switchModel.GetId(), relayName))
|
||||
}
|
||||
}
|
||||
case SJZDJ9_TDFJ2:
|
||||
{
|
||||
switch relayName {
|
||||
case SJZDJ9_1DQJ:
|
||||
state.J2_1DQJ = event.Xh
|
||||
case SJZDJ9_BHJ:
|
||||
state.J2_BHJ = event.Xh
|
||||
case SJZDJ9_2DQJ:
|
||||
{
|
||||
state.J2_2DQJ_ToD = !state.J2_2DQJ && event.Xh
|
||||
state.J2_2DQJ_ToF = state.J2_2DQJ && !event.Xh
|
||||
state.J2_2DQJ = event.Xh
|
||||
}
|
||||
case SJZDJ9_1DQJF:
|
||||
state.J2_1DQJF = event.Xh
|
||||
case SJZDJ9_DBJ:
|
||||
state.J2_DBJ = event.Xh
|
||||
case SJZDJ9_FBJ:
|
||||
state.J2_FBJ = event.Xh
|
||||
default:
|
||||
panic(fmt.Sprintf("SwitchZdj9的模型[%s]中继电器功能名称[%s]无法识别", switchModel.GetId(), relayName))
|
||||
}
|
||||
}
|
||||
default:
|
||||
panic(fmt.Sprintf("SwitchZdj9的模型[%s]中继电器组合类型[%s]无法识别", switchModel.GetId(), relayGroup))
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
panic("SwitchZdj9的模型未实现接口umi.IRelayCRoler")
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 发送继电器需要改变事件
|
||||
func (me *Switch2jZdj9System) publishRelayNeedChangeEvent(w ecs.World, switchEntry *ecs.Entry, relayGroup string, relayName string, needXh bool) {
|
||||
switchModel := FindModelStorage(w).FindById(EntityIdentityComponent.Get(switchEntry).Id)
|
||||
relayRole, _ := switchModel.(umi.IRelayCRole)
|
||||
relayModel := relayRole.FindRelayModelByCRole(relayGroup, relayName)
|
||||
sysEvent.RelayNeedChangeEventBus.Publish(w, &sysEvent.RelayNeedChangeEvent{Id: relayModel.(umi.IDeviceModel).GetId(), Xh: needXh})
|
||||
}
|
||||
|
||||
// 断相保护电路运算
|
||||
func (me *Switch2jZdj9System) calculateDBQ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
if state.J1_DBQ.LimitedTime > 0 {
|
||||
state.J1_DBQ.LimitedTime -= int64(w.Tick())
|
||||
if state.J1_DBQ.LimitedTime < 0 {
|
||||
state.J1_DBQ.LimitedTime = 0
|
||||
}
|
||||
}
|
||||
//
|
||||
state.J1_DBQ.PhaseLoss = !state.J1_Power.PhaseA || !state.J1_Power.PhaseB || !state.J1_Power.PhaseC
|
||||
//
|
||||
state.J1_DBQ.Dc24Voltage = !state.J1_DBQ.PhaseLoss
|
||||
///////////////////////////////////////////////////
|
||||
if state.J2_DBQ.LimitedTime > 0 {
|
||||
state.J2_DBQ.LimitedTime -= int64(w.Tick())
|
||||
if state.J2_DBQ.LimitedTime < 0 {
|
||||
state.J2_DBQ.LimitedTime = 0
|
||||
}
|
||||
}
|
||||
//
|
||||
state.J2_DBQ.PhaseLoss = !state.J2_Power.PhaseA || !state.J2_Power.PhaseB || !state.J2_Power.PhaseC
|
||||
//
|
||||
state.J2_DBQ.Dc24Voltage = !state.J2_DBQ.PhaseLoss
|
||||
}
|
||||
|
||||
// 转辙机内自动开闭器动作实现
|
||||
// 暂时规定:自动开闭器跟随2DQJ
|
||||
func (me *Switch2jZdj9System) calculateAKB(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
state.J1_AKB = state.J1_2DQJ
|
||||
state.J2_AKB = state.J2_2DQJ
|
||||
}
|
||||
|
||||
// 断相保护继电器运算
|
||||
// BHJ JWXC-1700无极缓放继电器
|
||||
func (me *Switch2jZdj9System) calculateBHJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
_J1_BHJ := state.J1_DBQ.Dc24Voltage
|
||||
_J2_BHJ := state.J2_DBQ.Dc24Voltage
|
||||
if _J1_BHJ != state.J1_BHJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_BHJ, _J1_BHJ)
|
||||
}
|
||||
if _J2_BHJ != state.J2_BHJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ2, SJZDJ9_BHJ, _J2_BHJ)
|
||||
}
|
||||
}
|
||||
|
||||
// 总保护继电器运算
|
||||
// ZBHJ JWXC-1700无极缓放继电器
|
||||
func (me *Switch2jZdj9System) calculateZBHJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//励磁
|
||||
method := state.J1_BHJ && state.J2_BHJ
|
||||
//自闭
|
||||
self := state.J1_ZBHJ && (state.J1_BHJ || state.J2_BHJ)
|
||||
//
|
||||
_J1_ZBHJ := method || self
|
||||
//为总保护继电器励磁
|
||||
if _J1_ZBHJ != state.J1_ZBHJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_ZBHJ, _J1_ZBHJ)
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔转换启动切断继电器运算
|
||||
// QDJ JWXC-1700无极缓放继电器
|
||||
func (me *Switch2jZdj9System) calculateQDJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//LC震荡电路运算
|
||||
fullLc := (!state.J1_BHJ && !state.J2_BHJ) || state.J1_ZBHJ
|
||||
if fullLc {
|
||||
state.J1_QDJ_LcTime = QDJ_LC_TIME
|
||||
} else {
|
||||
if state.J1_QDJ_LcTime > 0 {
|
||||
state.J1_QDJ_LcTime -= int64(w.Tick())
|
||||
if state.J1_QDJ_LcTime < 0 {
|
||||
state.J1_QDJ_LcTime = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
//自闭励磁电路
|
||||
self := state.J1_QDJ && state.J1_ZBHJ
|
||||
//为启动切断继电器励磁
|
||||
_J1_QDJ := self || fullLc || state.J1_QDJ_LcTime > 0
|
||||
if _J1_QDJ != state.J1_QDJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_QDJ, _J1_QDJ)
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔第一启动继电器运算
|
||||
// 1DQJ JWJXC-H125/80无极加强缓放继电器
|
||||
// J1先启动J2后启动
|
||||
func (me *Switch2jZdj9System) calculate1DQJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//自闭电路
|
||||
j2DqjSelf := state.J1_QDJ && state.J2_BHJ && state.J2_1DQJ
|
||||
//励磁电路
|
||||
j2DqjMethod1 := state.YCJ && state.J1_1DQJ && (!state.J2_2DQJ && state.DCJ || state.J2_2DQJ && state.FCJ)
|
||||
//
|
||||
j2DqjIs := j2DqjMethod1 || j2DqjSelf
|
||||
//为J2第一启动继电器励磁
|
||||
if j2DqjIs != state.J2_1DQJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ2, SJZDJ9_1DQJ, j2DqjIs)
|
||||
}
|
||||
// ---------------
|
||||
//励磁电路
|
||||
j1DqjMethod1 := state.YCJ && (!state.J1_2DQJ && state.DCJ || state.J1_2DQJ && state.FCJ)
|
||||
//自闭电路
|
||||
j1DqjSelf := state.J1_QDJ && state.J1_BHJ && state.J1_1DQJ
|
||||
//
|
||||
j1DqjIs := j1DqjMethod1 || j1DqjSelf
|
||||
//为J1第一启动继电器励磁
|
||||
if j1DqjIs != state.J1_1DQJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_1DQJ, j1DqjIs)
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔第一启动继电器复示继电器运算
|
||||
// 1DQJF JWJXC-480无极继电器
|
||||
func (me *Switch2jZdj9System) calculate1DQJF(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
_J1_1DQJF := state.J1_1DQJ
|
||||
_J2_1DQJF := state.J2_1DQJ
|
||||
if _J1_1DQJF != state.J1_1DQJF {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_1DQJF, _J1_1DQJF)
|
||||
}
|
||||
if _J2_1DQJF != state.J2_1DQJF {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ2, SJZDJ9_1DQJF, _J2_1DQJF)
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔第二启动继电器运算
|
||||
// 2DQJ JYJXC-160/260有极加强继电器
|
||||
// 2DQJ为有极继电器,根据线圈中电流极性不同具有 定位和反位 两种稳定状态,这两种稳定状态当线圈中电流消失时仍能继续保持;
|
||||
// 在线圈中通以规定极性的电流时,继电器吸起,断电后仍保持在吸起位置;通以反方向电流时,继电器打落,断电后保持在打落位置;
|
||||
// 断电保持由磁路系统中的一块长条形永久磁铁取代了大部分轭铁来实现;
|
||||
// 电流3->4吸起,电流2->1打落,如果21和34同时通过电流时磁场相互抵消则继电器保持原来状态不变
|
||||
func (me *Switch2jZdj9System) calculate2DQJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//J1-2DQJ
|
||||
j1_2dqj_21 := state.J1_1DQJF && state.FCJ
|
||||
j1_2dqj_34 := state.J1_1DQJF && state.DCJ
|
||||
//磁通量,矢量
|
||||
var j12dqj int8 = 0
|
||||
if j1_2dqj_34 {
|
||||
j12dqj++
|
||||
}
|
||||
if j1_2dqj_21 {
|
||||
j12dqj--
|
||||
}
|
||||
if j12dqj != 0 {
|
||||
_J1_2DQJ := j12dqj > 0
|
||||
if _J1_2DQJ != state.J1_2DQJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_2DQJ, _J1_2DQJ)
|
||||
}
|
||||
}
|
||||
//J2-2DQJ
|
||||
j2_2dqj_21 := state.J2_1DQJF && state.FCJ
|
||||
j2_2dqj_34 := state.J2_1DQJF && state.DCJ
|
||||
//磁通量,矢量
|
||||
var j22dqj int8 = 0
|
||||
if j2_2dqj_34 {
|
||||
j22dqj++
|
||||
}
|
||||
if j2_2dqj_21 {
|
||||
j22dqj--
|
||||
}
|
||||
if j22dqj != 0 {
|
||||
_J2_2DQJ := j22dqj > 0
|
||||
if _J2_2DQJ != state.J2_2DQJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ2, SJZDJ9_2DQJ, _J2_2DQJ)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔总定表继电器运算
|
||||
// ZDBJ JPXC-1000 偏极继电器是为了鉴别信号电路中的电流极性而设计
|
||||
// 继电器在磁路中增加一个偏极磁钢,使衔铁受永磁力的作用而偏于落下位置。衔铁的吸起与线圈中的电流的极性有关,
|
||||
// 通过线圈的电流为规定的方向时,衔铁才吸起,而电流的方向相反时,衔铁保持不动。
|
||||
// 它只具有一种稳定状态,即衔铁靠电磁力吸起后,断电即落下,始终偏向落下的定位状态
|
||||
func (me *Switch2jZdj9System) calculateZDBJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
_ZDBJ := state.J1_DBJ && state.J2_DBJ
|
||||
if _ZDBJ != state.ZDBJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDC, SJZDJ9_ZDBJ, _ZDBJ)
|
||||
}
|
||||
}
|
||||
func (me *Switch2jZdj9System) calculateZFBJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
_ZFBJ := state.J1_FBJ && state.J2_FBJ
|
||||
if _ZFBJ != state.ZFBJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDC, SJZDJ9_ZFBJ, _ZFBJ)
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔定表继电器运算
|
||||
// DBJ JPXC-1000 偏极继电器
|
||||
// BB的负半周期提供DBJ的励磁电流
|
||||
func (me *Switch2jZdj9System) calculateDBJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//j1 DBJ励磁
|
||||
j1DbjLc := state.J1_2DQJ && state.J1_AKB && state.J1_DB_K9 && !state.J1_1DQJ
|
||||
if j1DbjLc != state.J1_DBJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_DBJ, j1DbjLc)
|
||||
}
|
||||
//j2 DBJ励磁
|
||||
j2DbjLc := state.J2_2DQJ && state.J2_AKB && state.J2_DB_K9 && !state.J2_1DQJ
|
||||
if j2DbjLc != state.J2_DBJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ2, SJZDJ9_DBJ, j2DbjLc)
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔反表继电器运算
|
||||
// FBJ JPXC-1000 偏极继电器
|
||||
// BB的正半周期提供FBJ的励磁流
|
||||
func (me *Switch2jZdj9System) calculateFBJ(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//j1 FBJ励磁
|
||||
j1FbjLc := !state.J1_2DQJ && !state.J1_AKB && state.J1_FB_K10 && !state.J1_1DQJ
|
||||
if j1FbjLc != state.J1_FBJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ1, SJZDJ9_FBJ, j1FbjLc)
|
||||
}
|
||||
//j2
|
||||
j2FbjLc := !state.J2_2DQJ && !state.J2_AKB && state.J2_FB_K10 && !state.J2_1DQJ
|
||||
if j2FbjLc != state.J2_FBJ {
|
||||
me.publishRelayNeedChangeEvent(w, switchEntry, SJZDJ9_TDFJ2, SJZDJ9_FBJ, j2FbjLc)
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔转动运算
|
||||
// j1 完全转动须4000ms
|
||||
// j2 完全转动须5000ms
|
||||
const (
|
||||
J1Range int64 = 4000
|
||||
J2Range int64 = 5000
|
||||
)
|
||||
|
||||
// 道岔转动运算
|
||||
// j1 完全转动须4000ms
|
||||
// j2 完全转动须5000ms
|
||||
// j.Value 0-反位 jRange-定位
|
||||
func (me *Switch2jZdj9System) calculateMove(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
j1 := MovableObject1Component.Get(switchEntry)
|
||||
//
|
||||
if j1.Value < 0 {
|
||||
j1.Value = 0
|
||||
} else if j1.Value > J1Range {
|
||||
j1.Value = J1Range
|
||||
}
|
||||
j1.direction = state.J1_Traction
|
||||
//
|
||||
j2 := MovableObject2Component.Get(switchEntry)
|
||||
//
|
||||
if j2.Value < 0 {
|
||||
j2.Value = 0
|
||||
} else if j2.Value > J2Range {
|
||||
j2.Value = J2Range
|
||||
}
|
||||
j2.direction = state.J2_Traction
|
||||
}
|
||||
|
||||
// 转辙机对外端子9、10运算
|
||||
func (me *Switch2jZdj9System) calculateK9K10(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
j1 := MovableObject1Component.Get(switchEntry)
|
||||
j2 := MovableObject2Component.Get(switchEntry)
|
||||
//
|
||||
state.J1_DB_K9 = j1.Value >= J1Range
|
||||
state.J1_FB_K10 = j1.Value <= 0
|
||||
//
|
||||
state.J2_DB_K9 = j2.Value >= J2Range
|
||||
state.J2_FB_K10 = j2.Value <= 0
|
||||
}
|
||||
|
||||
// 转辙机电源控制
|
||||
// 1DQj启动继电器吸合时接通电源
|
||||
func (me *Switch2jZdj9System) calculateJPower(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//超时断电
|
||||
j1csdd := state.J1_Power.Active && state.J1_DBQ.LimitedTime <= 0
|
||||
//转换到位断电
|
||||
j1zhdwdd := state.J1_2DQJ_ToD && state.J1_DB_K9 || state.J1_2DQJ_ToF && state.J1_FB_K10
|
||||
if j1csdd || j1zhdwdd {
|
||||
state.J1_Power.PhaseA = false
|
||||
state.J1_Power.PhaseB = false
|
||||
state.J1_Power.PhaseC = false
|
||||
state.J1_2DQJ_ToD = false
|
||||
state.J1_2DQJ_ToF = false
|
||||
}
|
||||
//第一启动继电器落下
|
||||
if !state.J1_1DQJ {
|
||||
state.J1_Power.Active = false
|
||||
}
|
||||
//接通电源
|
||||
if state.J1_1DQJ && !state.J1_Power.Active {
|
||||
state.J1_Power.Active = true
|
||||
state.J1_Power.PhaseA = true
|
||||
state.J1_Power.PhaseB = true
|
||||
state.J1_Power.PhaseC = true
|
||||
state.J1_DBQ.LimitedTime = DBQ_LIMITED_TIME
|
||||
}
|
||||
//----------------
|
||||
//超时断电
|
||||
j2csdd := state.J2_Power.Active && state.J2_DBQ.LimitedTime <= 0
|
||||
//转换到位断电
|
||||
j2zhdwdd := state.J2_2DQJ_ToD && state.J2_DB_K9 || state.J2_2DQJ_ToF && state.J2_FB_K10
|
||||
if j2csdd || j2zhdwdd {
|
||||
state.J2_Power.PhaseA = false
|
||||
state.J2_Power.PhaseB = false
|
||||
state.J2_Power.PhaseC = false
|
||||
state.J2_2DQJ_ToD = false
|
||||
state.J2_2DQJ_ToF = false
|
||||
}
|
||||
//第一启动继电器落下
|
||||
if !state.J2_1DQJ {
|
||||
state.J2_Power.Active = false
|
||||
}
|
||||
//接通电源
|
||||
if state.J2_1DQJ && !state.J2_Power.Active {
|
||||
state.J2_Power.Active = true
|
||||
state.J2_Power.PhaseA = true
|
||||
state.J2_Power.PhaseB = true
|
||||
state.J2_Power.PhaseC = true
|
||||
state.J2_DBQ.LimitedTime = DBQ_LIMITED_TIME
|
||||
}
|
||||
}
|
||||
|
||||
// 道岔转辙机电机内线圈电路运算
|
||||
// ABC三相电,电机线圈UVW,
|
||||
// 定位到反位U-A V-C W-B 即U->W->V电机反转,反操接通2、4排表示电路
|
||||
// 反位到定位U-A V-B W-C 即U->V->W电机正转,定操接通1、3排表示电路
|
||||
func (me *Switch2jZdj9System) calculateMotor(w ecs.World, switchEntry *ecs.Entry, state *Switch2jZdj9State) {
|
||||
//电机1
|
||||
state.J1_U1 = ACPahseN
|
||||
state.J1_V1 = ACPahseN
|
||||
state.J1_W1 = ACPahseN
|
||||
state.J1_Traction = 0
|
||||
//A相电
|
||||
if state.J1_Power.PhaseA && state.J1_1DQJ {
|
||||
state.J1_U1 = ACPahseA
|
||||
}
|
||||
//B相电
|
||||
if state.J1_Power.PhaseB && state.J1_1DQJF {
|
||||
if state.J1_2DQJ {
|
||||
if state.J1_AKB {
|
||||
state.J1_V1 = ACPahseB
|
||||
}
|
||||
} else {
|
||||
if !state.J1_AKB {
|
||||
state.J1_W1 = ACPahseB
|
||||
}
|
||||
}
|
||||
}
|
||||
//C相电
|
||||
if state.J1_Power.PhaseC && state.J1_1DQJF {
|
||||
if state.J1_2DQJ {
|
||||
if state.J1_AKB {
|
||||
state.J1_W1 = ACPahseC
|
||||
}
|
||||
} else {
|
||||
if !state.J1_AKB {
|
||||
state.J1_V1 = ACPahseC
|
||||
}
|
||||
}
|
||||
}
|
||||
//牵引力
|
||||
if state.J1_U1 == ACPahseA {
|
||||
switch {
|
||||
case state.J1_V1 == ACPahseB: //U-A V-B W-C
|
||||
{
|
||||
if state.J1_W1 == ACPahseC {
|
||||
state.J1_Traction = 1
|
||||
}
|
||||
}
|
||||
case state.J1_V1 == ACPahseC: //U-A W-B V-C
|
||||
{
|
||||
if state.J1_W1 == ACPahseB {
|
||||
state.J1_Traction = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/////////////
|
||||
//电机2
|
||||
state.J2_U1 = ACPahseN
|
||||
state.J2_V1 = ACPahseN
|
||||
state.J2_W1 = ACPahseN
|
||||
state.J2_Traction = 0
|
||||
//A相电
|
||||
if state.J2_Power.PhaseA && state.J2_1DQJ {
|
||||
state.J2_U1 = ACPahseA
|
||||
}
|
||||
//B相电
|
||||
if state.J2_Power.PhaseB && state.J2_1DQJF {
|
||||
if state.J2_2DQJ {
|
||||
if state.J2_AKB {
|
||||
state.J2_V1 = ACPahseB
|
||||
}
|
||||
} else {
|
||||
if !state.J2_AKB {
|
||||
state.J2_W1 = ACPahseB
|
||||
}
|
||||
}
|
||||
}
|
||||
//C相电
|
||||
if state.J2_Power.PhaseC && state.J2_1DQJF {
|
||||
if state.J2_2DQJ {
|
||||
if state.J2_AKB {
|
||||
state.J2_W1 = ACPahseC
|
||||
}
|
||||
} else {
|
||||
if !state.J2_AKB {
|
||||
state.J2_V1 = ACPahseC
|
||||
}
|
||||
}
|
||||
}
|
||||
//牵引力
|
||||
if state.J2_U1 == ACPahseA {
|
||||
switch {
|
||||
case state.J2_V1 == ACPahseB: //U-A V-B W-C
|
||||
{
|
||||
if state.J2_W1 == ACPahseC {
|
||||
state.J2_Traction = 1
|
||||
}
|
||||
}
|
||||
case state.J2_V1 == ACPahseC: //U-A W-B V-C
|
||||
{
|
||||
if state.J2_W1 == ACPahseB {
|
||||
state.J2_Traction = -1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,68 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
var SwitchQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.SwitchRelayStateComponent, components.PercentageDeviceStateComponent))
|
||||
|
||||
const (
|
||||
//道岔定位
|
||||
SwitchNormalVaule int64 = PercentageRateValueMin
|
||||
//道岔反位
|
||||
SwitchReverseValue int64 = PercentageRateValueMax
|
||||
)
|
||||
|
||||
// 道岔系统操作
|
||||
type SwitchSystem struct {
|
||||
}
|
||||
|
||||
func NewSwitchSystem() *SwitchSystem {
|
||||
return &SwitchSystem{}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *SwitchSystem) Update(w ecs.World) {
|
||||
//根据定操反操继电器来设置道岔转动参数
|
||||
SwitchQuery.Each(w, func(e *ecs.Entry) {
|
||||
relay := components.SwitchRelayStateComponent.Get(e)
|
||||
if relay.DcJ || relay.FcJ {
|
||||
movable := components.MovableDeviceStateComponent.Get(e)
|
||||
percent := components.PercentageDeviceStateComponent.Get(e)
|
||||
switchId := components.DeviceIdentityComponent.Get(e).Id
|
||||
if relay.DcJ {
|
||||
movable.ToH = false
|
||||
percent.Target = SwitchNormalVaule
|
||||
}
|
||||
if relay.FcJ {
|
||||
movable.ToH = true
|
||||
percent.Target = SwitchReverseValue
|
||||
}
|
||||
movable.Speed = CalculateRateSpeed(int32(w.Tick()), getSwitchTurnTime(w, switchId))
|
||||
}
|
||||
})
|
||||
//观察道岔百分比组件来更新道岔逻辑继电器状态
|
||||
SwitchQuery.Each(w, func(e *ecs.Entry) {
|
||||
switchPercent := components.PercentageDeviceStateComponent.Get(e)
|
||||
switchRelay := components.SwitchRelayStateComponent.Get(e)
|
||||
if switchPercent.Rate == switchPercent.Target {
|
||||
switchRelay.DcJ = false
|
||||
switchRelay.FcJ = false
|
||||
switchRelay.DbJ = switchPercent.Rate <= SwitchNormalVaule
|
||||
switchRelay.FbJ = switchPercent.Rate >= SwitchReverseValue
|
||||
} else {
|
||||
switchRelay.DbJ = false
|
||||
switchRelay.FbJ = false
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// 获取道岔转动耗时ms
|
||||
func getSwitchTurnTime(world ecs.World, switchId string) int64 {
|
||||
dcModel := WorldModelStorage(world).FindById(switchId)
|
||||
var dc umi.ISwitchModel = dcModel.(umi.ISwitchModel)
|
||||
return dc.TurningTime()
|
||||
}
|
@ -1,165 +0,0 @@
|
||||
package system
|
||||
|
||||
import (
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
)
|
||||
|
||||
// 继电器: true-吸合;false-未吸合
|
||||
type SwitchZdj9State struct {
|
||||
//定操继电器
|
||||
DCJ bool
|
||||
//反操继电器
|
||||
FCJ bool
|
||||
//允许操作继电器
|
||||
YCJ bool
|
||||
//总定表继电器
|
||||
ZDBJ bool
|
||||
//总反表继电器
|
||||
ZFBJ bool
|
||||
//表示电路变压器,将220V交流电变压后作为为道岔表示电路的电源
|
||||
//0-无电源;规定52端子为正,则,1-输出瞬时正电压;-1 - 输出瞬时负电压
|
||||
J1_BB int8
|
||||
//道岔第一启动继电器
|
||||
J1_1DQJ bool
|
||||
//道岔保护继电器
|
||||
J1_BHJ bool
|
||||
//道岔第二启动继电器
|
||||
J1_2DQJ bool
|
||||
//道岔第一启动继电器复示继电器
|
||||
J1_1DQJF bool
|
||||
//断相保护器
|
||||
J1_DBQ DBQState
|
||||
//定位表示继电器
|
||||
J1_DBJ bool
|
||||
//反位表示继电器
|
||||
J1_FBJ bool
|
||||
//道岔启动切断继电器
|
||||
J1_QDJ bool
|
||||
//道岔启动切断继电器的LC震荡电路保磁剩余时间,单位ms
|
||||
//最长保持时长3000ms
|
||||
J1_QDJ_LcTime int64
|
||||
//总保护继电器
|
||||
J1_ZBHJ bool
|
||||
//表示电路变压器,将220V交流电变压后作为为道岔表示电路的电源
|
||||
//0-无电源;规定52端子为正,则,1-输出瞬时正电压;-1 - 输出瞬时负电压
|
||||
J2_BB int8
|
||||
//道岔第一启动继电器
|
||||
J2_1DQJ bool
|
||||
//道岔保护继电器
|
||||
J2_BHJ bool
|
||||
//道岔第二启动继电器
|
||||
J2_2DQJ bool
|
||||
//道岔第一启动继电器复示继电器
|
||||
J2_1DQJF bool
|
||||
//断相保护器
|
||||
J2_DBQ DBQState
|
||||
//定位表示继电器
|
||||
J2_DBJ bool
|
||||
//反位表示继电器
|
||||
J2_FBJ bool
|
||||
}
|
||||
|
||||
// 带限时功能断相保护器
|
||||
// 限时13秒
|
||||
type DBQState struct {
|
||||
//是否缺相,true-缺相,false-三相电正常未缺相
|
||||
PhaseLoss bool
|
||||
//剩余限时时间,单位ms
|
||||
LimitedTime int64
|
||||
//当三相电正常时,断相保护器内的24V直流整流电路会正常输出24V直流电
|
||||
//当三相电不正常如缺相时,断相保护器内的24V直流整流电路不会输出24V直流电
|
||||
//BHJ道岔保护继电器的励磁线圈由该24V直流供电
|
||||
Dc24Voltage bool
|
||||
}
|
||||
|
||||
// 道岔ZDJ9电路状态组件
|
||||
var SwitchZdj9StateComponent = ecs.NewComponentType[SwitchZdj9State]()
|
||||
|
||||
// ZDJ9道岔系统
|
||||
type SwitchZdj9System struct {
|
||||
zdj9Query *ecs.Query
|
||||
}
|
||||
|
||||
func NewSwitchZdj9System() *SwitchZdj9System {
|
||||
return &SwitchZdj9System{zdj9Query: ecs.NewQuery(filter.Contains(SwitchZdj9StateComponent))}
|
||||
}
|
||||
|
||||
// world 执行
|
||||
func (me *SwitchZdj9System) Update(w ecs.World) {
|
||||
me.zdj9Query.Each(w, func(e *ecs.Entry) {
|
||||
zdj9State := SwitchZdj9StateComponent.Get(e)
|
||||
//断相保护器电路
|
||||
calculateDBQ(w, zdj9State)
|
||||
//断相保护继电器励磁电路
|
||||
calculateBHJ(w, zdj9State)
|
||||
//总保护继电器励磁电路
|
||||
calculateZBHJ(w, zdj9State)
|
||||
//道岔转换启动切断继电器励磁电路
|
||||
calculateQDJ(w, zdj9State)
|
||||
//道岔一次启动继电器励磁电路
|
||||
calculateDQJ(w, zdj9State)
|
||||
})
|
||||
}
|
||||
|
||||
// 断相保护电路运算
|
||||
func calculateDBQ(w ecs.World, state *SwitchZdj9State) {
|
||||
if state.J1_DBQ.LimitedTime > 0 {
|
||||
state.J1_DBQ.LimitedTime -= int64(w.Tick())
|
||||
} else {
|
||||
state.J1_DBQ.LimitedTime = 0
|
||||
}
|
||||
state.J1_DBQ.Dc24Voltage = !state.J1_DBQ.PhaseLoss
|
||||
//
|
||||
if state.J2_DBQ.LimitedTime > 0 {
|
||||
state.J2_DBQ.LimitedTime -= int64(w.Tick())
|
||||
} else {
|
||||
state.J2_DBQ.LimitedTime = 0
|
||||
}
|
||||
state.J2_DBQ.Dc24Voltage = !state.J2_DBQ.PhaseLoss
|
||||
}
|
||||
|
||||
// 断相保护继电器运算
|
||||
func calculateBHJ(w ecs.World, state *SwitchZdj9State) {
|
||||
state.J1_BHJ = state.J1_DBQ.Dc24Voltage
|
||||
state.J2_BHJ = state.J2_DBQ.Dc24Voltage
|
||||
}
|
||||
|
||||
// 总保护继电器运算
|
||||
func calculateZBHJ(w ecs.World, state *SwitchZdj9State) {
|
||||
//励磁
|
||||
method1 := state.J1_BHJ && state.J2_BHJ
|
||||
//励磁
|
||||
method2 := state.J1_ZBHJ && (state.J1_BHJ || state.J2_BHJ)
|
||||
//为总保护继电器励磁
|
||||
state.J1_ZBHJ = method1 || method2
|
||||
}
|
||||
|
||||
// 道岔转换启动切断继电器运算
|
||||
func calculateQDJ(w ecs.World, state *SwitchZdj9State) {
|
||||
//LC震荡电路运算
|
||||
fullLc := (!state.J1_BHJ && !state.J2_BHJ) || state.J1_ZBHJ
|
||||
if fullLc {
|
||||
state.J1_QDJ_LcTime = 3000
|
||||
} else {
|
||||
state.J1_QDJ_LcTime -= int64(w.Tick())
|
||||
if state.J1_QDJ_LcTime < 0 {
|
||||
state.J1_QDJ_LcTime = 0
|
||||
}
|
||||
}
|
||||
//自闭励磁电路
|
||||
self := state.J1_QDJ && state.J1_ZBHJ
|
||||
//为启动切断继电器励磁
|
||||
state.J1_QDJ = self || fullLc || state.J1_QDJ_LcTime > 0
|
||||
}
|
||||
|
||||
// 道岔第一启动继电器运算
|
||||
func calculateDQJ(w ecs.World, state *SwitchZdj9State) {
|
||||
//励磁电路
|
||||
j1DqjMethod1 := state.YCJ && (state.DCJ || state.FCJ)
|
||||
//自闭电路
|
||||
j1DqjSelf := state.J1_QDJ && state.J1_BHJ && state.J1_1DQJ
|
||||
//为J1第一启动继电器励磁
|
||||
state.J1_1DQJ = j1DqjMethod1 || j1DqjSelf
|
||||
|
||||
}
|
@ -3,14 +3,22 @@ package system
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/yohamta/donburi/component"
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
"joylink.club/rtsssimulation/umi"
|
||||
)
|
||||
|
||||
// 实体身份定义
|
||||
type EntityIdentity struct {
|
||||
Id string
|
||||
}
|
||||
|
||||
// 实体身份组件
|
||||
var EntityIdentityComponent = ecs.NewComponentType[EntityIdentity]()
|
||||
|
||||
func FindEntityById(world ecs.World, id string) *ecs.Entry {
|
||||
query := ecs.NewQuery(filter.Contains(components.DeviceIdentityComponent))
|
||||
query := ecs.NewQuery(filter.Contains(EntityIdentityComponent))
|
||||
return QueryEntityById(world, query, id)
|
||||
}
|
||||
func QueryEntityById(world ecs.World, q *ecs.Query, id string) *ecs.Entry {
|
||||
@ -18,7 +26,7 @@ func QueryEntityById(world ecs.World, q *ecs.Query, id string) *ecs.Entry {
|
||||
func() {
|
||||
defer simpleRecover()
|
||||
q.Each(world, func(e *ecs.Entry) {
|
||||
if id == components.DeviceIdentityComponent.Get(e).Id {
|
||||
if id == EntityIdentityComponent.Get(e).Id {
|
||||
entry = e
|
||||
panic(fmt.Sprintf("找到实体[%s],结束查找", id))
|
||||
}
|
||||
@ -28,38 +36,35 @@ func QueryEntityById(world ecs.World, q *ecs.Query, id string) *ecs.Entry {
|
||||
return entry
|
||||
}
|
||||
|
||||
var modelStorageQuery = ecs.NewQuery(filter.Contains(ModelStorageComponent))
|
||||
|
||||
// 获取模型仓库
|
||||
func FindModelStorage(world ecs.World) umi.IModelManager {
|
||||
e, _ := modelStorageQuery.First(world)
|
||||
return ModelStorageComponent.Get(e).ModelManager
|
||||
}
|
||||
|
||||
// 捕获panic并恢复执行
|
||||
func simpleRecover() {
|
||||
recover()
|
||||
}
|
||||
|
||||
// /////////////////////////////////////////////////////////////////////////
|
||||
// 模型仓库查询
|
||||
var worldModelStorageQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.ModelStorageRefComponent))
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
func WorldModelStorage(world ecs.World) umi.IModelManager {
|
||||
e, ok := worldModelStorageQuery.First(world)
|
||||
if ok {
|
||||
return components.ModelStorageRefComponent.Get(e).ModelManager
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
// 实体标签
|
||||
type EntityTag = component.IComponentType
|
||||
|
||||
type EntityTagHandler struct {
|
||||
Tag EntityTag
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////
|
||||
// 继电器系统
|
||||
type relaySystem struct {
|
||||
// key-设备id
|
||||
relayQuery map[string]*ecs.Query
|
||||
/////////////////////////////////////////////////////////
|
||||
|
||||
// 模型仓库引用
|
||||
// 用于world内使用,查询模型
|
||||
type ModelStorageRef struct {
|
||||
ModelManager umi.IModelManager
|
||||
}
|
||||
|
||||
// 获取设备的相关继电器的查询
|
||||
func (me *relaySystem) getDeviceRelayQuery(deviceEntry *ecs.Entry) *ecs.Query {
|
||||
id := components.DeviceIdentityComponent.Get(deviceEntry).Id
|
||||
query, ok := me.relayQuery[id]
|
||||
if !ok {
|
||||
query = ecs.NewQuery(filter.Contains(components.RelayTagHandlerComponent.Get(deviceEntry).Tag))
|
||||
me.relayQuery[id] = query
|
||||
}
|
||||
return query
|
||||
}
|
||||
// 模型仓库组件
|
||||
var ModelStorageComponent = ecs.NewComponentType[ModelStorageRef]()
|
||||
|
@ -5,10 +5,11 @@ import (
|
||||
|
||||
"github.com/yohamta/donburi/filter"
|
||||
"joylink.club/ecs"
|
||||
"joylink.club/rtsssimulation/components"
|
||||
)
|
||||
|
||||
var timerQuery *ecs.Query = ecs.NewQuery(filter.Contains(components.SystemTimerComponent))
|
||||
var SystemTimerComponent = ecs.NewComponentType[SystemTimer]()
|
||||
|
||||
var timerQuery *ecs.Query = ecs.NewQuery(filter.Contains(SystemTimerComponent))
|
||||
|
||||
// 系统时钟操作
|
||||
type TimerSystem struct {
|
||||
@ -21,7 +22,7 @@ func NewTimerSystem() *TimerSystem {
|
||||
// world 执行
|
||||
func (me *TimerSystem) Update(w ecs.World) {
|
||||
if e, ok := timerQuery.First(w); ok {
|
||||
timer := components.SystemTimerComponent.Get(e)
|
||||
timer := SystemTimerComponent.Get(e)
|
||||
timer.Tick(w.Tick())
|
||||
}
|
||||
}
|
||||
@ -29,7 +30,7 @@ func (me *TimerSystem) Update(w ecs.World) {
|
||||
// 重置world时间
|
||||
func ResetWorldTimer(w ecs.World, time time.Time) {
|
||||
if e, ok := timerQuery.First(w); ok {
|
||||
timer := components.SystemTimerComponent.Get(e)
|
||||
timer := SystemTimerComponent.Get(e)
|
||||
timer.ResetTime(time)
|
||||
}
|
||||
}
|
||||
@ -37,9 +38,38 @@ func ResetWorldTimer(w ecs.World, time time.Time) {
|
||||
// 获取world当前时间
|
||||
func GetWorldNow(w ecs.World) *time.Time {
|
||||
if e, ok := timerQuery.First(w); ok {
|
||||
timer := components.SystemTimerComponent.Get(e)
|
||||
timer := SystemTimerComponent.Get(e)
|
||||
now := timer.Now()
|
||||
return &now
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
// 系统时钟,单例
|
||||
type SystemTimer struct {
|
||||
timer *time.Time
|
||||
}
|
||||
|
||||
// 以指定时间构建
|
||||
func NewSystemTimer(time *time.Time) *SystemTimer {
|
||||
return &SystemTimer{
|
||||
timer: time,
|
||||
}
|
||||
}
|
||||
|
||||
// 重置时间
|
||||
func (me *SystemTimer) ResetTime(time time.Time) {
|
||||
*me.timer = time
|
||||
}
|
||||
|
||||
// 获取当前时间的副本
|
||||
func (me *SystemTimer) Now() time.Time {
|
||||
return *me.timer
|
||||
}
|
||||
|
||||
// tick系统时钟,单位ms
|
||||
func (me *SystemTimer) Tick(tick int) {
|
||||
*me.timer = me.timer.Add(time.Duration(tick) * time.Millisecond)
|
||||
}
|
||||
|
@ -82,8 +82,6 @@ type ILinkOffsetRef interface {
|
||||
// 仿真底层道岔模型
|
||||
// 用户所有道岔模型定义须实现该接口
|
||||
type ISwitchModel interface {
|
||||
//道岔转动从0-100耗时,单位ms
|
||||
TurningTime() int64
|
||||
//道岔A端口连接的轨道
|
||||
PortALink() ILinkRef
|
||||
//道岔B端口连接的轨道
|
||||
@ -110,17 +108,51 @@ type IPsdModel interface {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
//继电器类型定义
|
||||
type RelayType = int8
|
||||
|
||||
//继电器类枚举
|
||||
const (
|
||||
//无极缓放继电器
|
||||
JWXC_1700 RelayType = iota + 1
|
||||
//
|
||||
JWXC_H340
|
||||
//偏极继电器是为了鉴别信号电路中的电流极性而设计
|
||||
//继电器在磁路中增加一个偏极磁钢,使衔铁受永磁力的作用而偏于落下位置。衔铁的吸起与线圈中的电流的极性有关,
|
||||
//通过线圈的电流为规定的方向时,衔铁才吸起,而电流的方向相反时,衔铁保持不动。
|
||||
//它只具有一种稳定状态,即衔铁靠电磁力吸起后,断电即落下,始终偏向落下的定位状态
|
||||
JPXC_1000
|
||||
//无极加强缓放继电器
|
||||
JWJXC_H125_80
|
||||
//有极加强继电器
|
||||
//根据线圈中电流极性不同具有 定位和反位 两种稳定状态,这两种稳定状态当线圈中电流消失时仍能继续保持;
|
||||
//在线圈中通以规定极性的电流时,继电器吸起,断电后仍保持在吸起位置;通以反方向电流时,继电器打落,断电后保持在打落位置;
|
||||
//断电保持由磁路系统中的一块长条形永久磁铁取代了大部分轭铁来实现即断电保持当前状态
|
||||
JYJXC_160_260
|
||||
//无极继电器
|
||||
JWJXC_480
|
||||
//整流式缓放继电器
|
||||
JZXC_H18
|
||||
)
|
||||
|
||||
// 继电器模型
|
||||
// 继电器按作用分类:驱动继电器、采集继电器
|
||||
type IRelayModel interface {
|
||||
//该继电器管理的设备
|
||||
ManagedDevice() IDeviceModel
|
||||
//true-驱动继电器;false-采集继电器
|
||||
IsDriver() bool
|
||||
//继电器作用名称,同一个设备的继电器的作用名称不能重复
|
||||
//如DJ-12、DDJ-83
|
||||
UsageName() string
|
||||
//该继电器类型
|
||||
JType() RelayType
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////
|
||||
// 获取继电器在具体电路中的角色(组合类型、功能名称)
|
||||
// 如信号机3XH-1电路中点灯继电器:组合类型-"3XH-1" 功能名称-"DDJ"
|
||||
// 对应设备电路中有继电器的设备模型须实现该接口
|
||||
type IRelayCRole interface {
|
||||
//根据继电器id获取在具体电路中的电路角色
|
||||
//relayId-继电器id
|
||||
//relayGroup-继电器组合类型
|
||||
//relayName-继电器在电路中的名称
|
||||
//find-true找到,false未找到
|
||||
FindCircuitRoleById(relayId string) (relayGroup string, relayName string, find bool)
|
||||
//根据继电器具体电路角色来获取继电器设备模型
|
||||
//relayGroup-继电器组合类型
|
||||
//relayName-继电器在电路中的名称
|
||||
FindRelayModelByCRole(relayGroup string, relayName string) IRelayModel
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user