Compare commits

...

45 Commits

Author SHA1 Message Date
88b24dff65 [修改]11号线BTM与VOBC通信服务逻辑 2024-11-19 10:48:12 +08:00
b7bc9bdb1f [重写]11号线BTM与VOBC通信服务 2024-11-15 09:52:19 +08:00
tiger_zhou
073f5e3156 过/欠标调整 2024-10-17 16:54:50 +08:00
tiger_zhou
2f7e505437 列车动力学添加车组,仿真内添加列车添加车组 2024-10-15 09:16:34 +08:00
tiger_zhou
150aa24307 停车点构建proto 2024-09-25 11:19:18 +08:00
tiger_zhou
ef7ff5459c Merge remote-tracking branch 'origin/master' 2024-09-10 15:39:30 +08:00
tiger_zhou
91f3fdb23d 折返 2024-09-10 15:37:40 +08:00
f1feee09cc [修改]11号线模式口采集和驱动逻辑调通 2024-09-05 15:14:38 +08:00
tiger_zhou
693576459c 列车11号线btm调整 2024-09-05 09:21:48 +08:00
a94fdb12f7 [修改]11号线联锁通信暂时提交 2024-08-28 11:32:27 +08:00
99ebcb04e5 [修改]移除屏蔽门继电器的自保持逻辑(因为自保持会导致12号线联锁宕机) 2024-08-26 11:23:22 +08:00
1f0a114c8d [新增]设备公里表长短链校正 2024-08-22 14:03:32 +08:00
12df28cc37 [修改]11号线联锁通信,区段状态从物理区段改为计轴区段 2024-08-13 11:00:26 +08:00
73e7f83cfa [新增]计轴区段的模型、ecs实体、ecs系统、发给前端的状态 2024-08-12 18:57:36 +08:00
51702238da [bug]现在ESB已经不是按钮了,去掉状态采集;构建repo时没有对站台方向赋值 2024-08-09 11:38:53 +08:00
ae5ee2729e [补充]12号线联锁通信应答器数据解析;
[修改]联锁配置中的车站编号不再改为车站uid
2024-08-08 13:23:24 +08:00
efa7d1655e Merge remote-tracking branch 'origin/master' 2024-08-07 14:54:17 +08:00
86c02883c4 [补充]11号线联锁通信 2024-08-07 14:53:56 +08:00
tiger_zhou
5f95106870 列车控制连接版本记录1 2024-08-05 16:32:20 +08:00
8d19129ec6 [bug]信号机电路系统逻辑没有正确处理驱动状态 2024-08-01 14:25:45 +08:00
3182e867c1 [重写]计轴的组件、实体、系统、预复位/复位逻辑 2024-07-31 17:08:53 +08:00
8c6bfb2aee [修改]北京12号线连锁rsd、sse、ssr编解码算法及交互流程 2024-07-29 13:53:46 +08:00
ef7e469175 [重写]北京12号线计轴通信交互逻辑(未完,主要是安全校验域计算逻辑) 2024-07-04 13:59:39 +08:00
181dd9951b [新增]继电器设置初始位置逻辑 2024-06-28 11:10:09 +08:00
c5f139267a [修改]车站EMP继电器组合缺少蜂鸣器等元素时不再报错;
[新增]车站电子元件组合构建逻辑
2024-06-26 17:27:47 +08:00
f94033ca44 [新增]ecs物理区段增加区段电路组件及逻辑;
[修改]12号线联锁通信服务如果启动失败,则启动参数无法更换bug
2024-06-21 15:53:16 +08:00
tiger_zhou
cebe83f5c4 日志调整及现场测试 2024-06-12 16:22:31 +08:00
468cc78964 [修改]区段、Link、运营方向/位置之间互相转换的函数的bug 2024-05-17 14:38:13 +08:00
a613ac109b [新增]区段、Link、运营方向/位置之间互相转换的函数 2024-05-16 21:19:52 +08:00
90003ec942 [新增]增加GJ继电器相关逻辑 2024-05-13 13:17:16 +08:00
8ccd46aa6c 【bug】车库门强制开关门无效;洗车机取消故障后依然有紧急停车 2024-04-07 13:38:30 +08:00
4371dad391 【新增】洗车机模型构建、ecs实体构建
【修改】洗车机ecs电路系统逻辑
2024-04-02 14:09:41 +08:00
cf942ab318 【新增】防淹门构建为车库门模型逻辑
【bug】当缺少继电器时,车库门的ecs系统逻辑和状态发送逻辑执行出错
2024-04-01 13:31:37 +08:00
cf783364fe 【修改】车库门继电器状态丢失的故障由应用层实现;不再影响继电器的实际状态;也不再导致门故障继电器接通; 2024-03-29 16:46:30 +08:00
6d5457f706 【bug】车库门ecs系统逻辑没有对MMSJ做处理 2024-03-27 17:11:04 +08:00
e1913b8f43 【bug】车库门ecs系统 2024-03-27 14:38:08 +08:00
33ed496dcd 【bug】车库门操作、状态发送等逻辑中的bug 2024-03-27 14:15:34 +08:00
01b0655eb5 【新增】测试模块车库门状态proto定义及车库门状态发送逻辑
【删除】ecs的车库门状态及相关逻辑
2024-03-26 16:48:36 +08:00
d63be32ad5 【新增】车库门PSL模型构建及相关ecs逻辑;
【改动】车库门ecs逻辑
2024-03-26 13:12:16 +08:00
f0a6c534ec 修改submodule url 2024-03-19 09:37:32 +08:00
21ca336b0c 车库门电路逻辑bug修改 2024-03-18 11:09:28 +08:00
tiger_zhou
88b5ea8c77 列车前端操作接口,列车连接三方映射接口及ws返回列车连接状态 2024-03-15 16:03:47 +08:00
tiger_zhou
ab72ff8e00 项目名称及路径更改 2024-03-14 09:18:12 +08:00
tiger_zhou
b6fbaf7272 项目名称及路径更改 2024-03-14 08:46:24 +08:00
tiger_zhou
ecb43fa7a3 项目名称及路径更改 2024-03-13 20:14:25 +08:00
85 changed files with 4205 additions and 2580 deletions

2
.gitmodules vendored
View File

@ -1,3 +1,3 @@
[submodule "jl-ecs"]
path = jl-ecs
url = http://120.46.212.6:3000/joylink/jl-ecs.git
url = https://gitea.joylink.club/joylink/jl-ecs.git

View File

@ -0,0 +1,11 @@
package component
import "joylink.club/ecs"
var (
AxleCountingSectionStateType = ecs.NewComponentType[AxleCountingSectionState]()
)
type AxleCountingSectionState struct {
Occupied bool
}

View File

@ -9,6 +9,9 @@ var (
BaliseVB = ecs.NewTag() // 主信号应答器
BaliseIB = ecs.NewTag() // 预告应答器
)
var ForceVariableTelegram = ecs.NewTag() //表示可变报文为强制设置并锁定
var BaliseFixedTelegramType = ecs.NewComponentType[BaliseTelegram]() //应答器固定报文
var BaliseVariableTelegramType = ecs.NewComponentType[BaliseTelegram]() //应答器可变报文
type BaliseTelegram struct {

View File

@ -2,14 +2,14 @@ package component
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component/component_data"
)
var (
CkmTag = ecs.NewTag()
CkmMgzTag = ecs.NewTag() //门故障tag
CkmCircuitType = ecs.NewComponentType[CkmCircuit]()
CkmStateType = ecs.NewComponentType[component_data.CkmState]()
CkmTag = ecs.NewTag()
CkmCircuitType = ecs.NewComponentType[CkmCircuit]()
CkmPslType = ecs.NewComponentType[CkmPsl]()
CkmForceOpenTag = ecs.NewTag()
CkmForceCloseTag = ecs.NewTag()
)
type CkmCircuit struct {
@ -23,3 +23,14 @@ type CkmCircuit struct {
KMJ *ecs.Entry //开门继电器
GMJ *ecs.Entry //关门继电器
}
func (c *CkmCircuit) RelayList() []*ecs.Entry {
return []*ecs.Entry{c.MKJ, c.MGJ, c.MGZJ, c.MPLJ, c.MMSJ, c.KMJ, c.GMJ}
}
type CkmPsl struct {
KMA *ecs.Entry //开门按钮
GMA *ecs.Entry //关门按钮
MPLA *ecs.Entry //门旁路按钮
MMSA *ecs.Entry //门模式按钮
}

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.33.0
// protoc v4.23.1
// source: component/ci.proto

View File

@ -1,180 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc v4.23.1
// source: component/ckm.proto
package component_data
import (
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
reflect "reflect"
sync "sync"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
type CkmState struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Close bool `protobuf:"varint,1,opt,name=close,proto3" json:"close,omitempty"`
Mms bool `protobuf:"varint,2,opt,name=mms,proto3" json:"mms,omitempty"` //门模式true远程false本地
Mgz bool `protobuf:"varint,3,opt,name=mgz,proto3" json:"mgz,omitempty"` //门故障
// 驱动状态(没有继电器时直接操作以下状态)
Km bool `protobuf:"varint,4,opt,name=km,proto3" json:"km,omitempty"` //开门
Gm bool `protobuf:"varint,5,opt,name=gm,proto3" json:"gm,omitempty"` //关门
}
func (x *CkmState) Reset() {
*x = CkmState{}
if protoimpl.UnsafeEnabled {
mi := &file_component_ckm_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *CkmState) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*CkmState) ProtoMessage() {}
func (x *CkmState) ProtoReflect() protoreflect.Message {
mi := &file_component_ckm_proto_msgTypes[0]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use CkmState.ProtoReflect.Descriptor instead.
func (*CkmState) Descriptor() ([]byte, []int) {
return file_component_ckm_proto_rawDescGZIP(), []int{0}
}
func (x *CkmState) GetClose() bool {
if x != nil {
return x.Close
}
return false
}
func (x *CkmState) GetMms() bool {
if x != nil {
return x.Mms
}
return false
}
func (x *CkmState) GetMgz() bool {
if x != nil {
return x.Mgz
}
return false
}
func (x *CkmState) GetKm() bool {
if x != nil {
return x.Km
}
return false
}
func (x *CkmState) GetGm() bool {
if x != nil {
return x.Gm
}
return false
}
var File_component_ckm_proto protoreflect.FileDescriptor
var file_component_ckm_proto_rawDesc = []byte{
0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6b, 0x6d, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74,
0x22, 0x64, 0x0a, 0x08, 0x43, 0x6b, 0x6d, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x63, 0x6c, 0x6f, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x63, 0x6c, 0x6f,
0x73, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x6d, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52,
0x03, 0x6d, 0x6d, 0x73, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x67, 0x7a, 0x18, 0x03, 0x20, 0x01, 0x28,
0x08, 0x52, 0x03, 0x6d, 0x67, 0x7a, 0x12, 0x0e, 0x0a, 0x02, 0x6b, 0x6d, 0x18, 0x04, 0x20, 0x01,
0x28, 0x08, 0x52, 0x02, 0x6b, 0x6d, 0x12, 0x0e, 0x0a, 0x02, 0x67, 0x6d, 0x18, 0x05, 0x20, 0x01,
0x28, 0x08, 0x52, 0x02, 0x67, 0x6d, 0x42, 0x1c, 0x5a, 0x1a, 0x2e, 0x2f, 0x63, 0x6f, 0x6d, 0x70,
0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f,
0x64, 0x61, 0x74, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
file_component_ckm_proto_rawDescOnce sync.Once
file_component_ckm_proto_rawDescData = file_component_ckm_proto_rawDesc
)
func file_component_ckm_proto_rawDescGZIP() []byte {
file_component_ckm_proto_rawDescOnce.Do(func() {
file_component_ckm_proto_rawDescData = protoimpl.X.CompressGZIP(file_component_ckm_proto_rawDescData)
})
return file_component_ckm_proto_rawDescData
}
var file_component_ckm_proto_msgTypes = make([]protoimpl.MessageInfo, 1)
var file_component_ckm_proto_goTypes = []interface{}{
(*CkmState)(nil), // 0: component.CkmState
}
var file_component_ckm_proto_depIdxs = []int32{
0, // [0:0] is the sub-list for method output_type
0, // [0:0] is the sub-list for method input_type
0, // [0:0] is the sub-list for extension type_name
0, // [0:0] is the sub-list for extension extendee
0, // [0:0] is the sub-list for field type_name
}
func init() { file_component_ckm_proto_init() }
func file_component_ckm_proto_init() {
if File_component_ckm_proto != nil {
return
}
if !protoimpl.UnsafeEnabled {
file_component_ckm_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*CkmState); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_component_ckm_proto_rawDesc,
NumEnums: 0,
NumMessages: 1,
NumExtensions: 0,
NumServices: 0,
},
GoTypes: file_component_ckm_proto_goTypes,
DependencyIndexes: file_component_ckm_proto_depIdxs,
MessageInfos: file_component_ckm_proto_msgTypes,
}.Build()
File_component_ckm_proto = out.File
file_component_ckm_proto_rawDesc = nil
file_component_ckm_proto_goTypes = nil
file_component_ckm_proto_depIdxs = nil
}

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.33.0
// protoc v4.23.1
// source: component/common.proto

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.33.0
// protoc v4.23.1
// source: component/equipment.proto

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.33.0
// protoc v4.23.1
// source: component/points.proto

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.33.0
// protoc v4.23.1
// source: component/psd.proto
@ -74,8 +74,9 @@ type PsdState struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Close bool `protobuf:"varint,1,opt,name=close,proto3" json:"close,omitempty"`
Obstacle bool `protobuf:"varint,2,opt,name=obstacle,proto3" json:"obstacle,omitempty"`
Close bool `protobuf:"varint,1,opt,name=close,proto3" json:"close,omitempty"`
Obstacle bool `protobuf:"varint,2,opt,name=obstacle,proto3" json:"obstacle,omitempty"` //有障碍物
InterlockRelease bool `protobuf:"varint,3,opt,name=interlockRelease,proto3" json:"interlockRelease,omitempty"` //互锁解除
}
func (x *PsdState) Reset() {
@ -124,6 +125,13 @@ func (x *PsdState) GetObstacle() bool {
return false
}
func (x *PsdState) GetInterlockRelease() bool {
if x != nil {
return x.InterlockRelease
}
return false
}
type Psd struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@ -246,24 +254,27 @@ var File_component_psd_proto protoreflect.FileDescriptor
var file_component_psd_proto_rawDesc = []byte{
0x0a, 0x13, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x73, 0x64, 0x2e,
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74,
0x22, 0x3c, 0x0a, 0x08, 0x50, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x22, 0x68, 0x0a, 0x08, 0x50, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x14, 0x0a, 0x05,
0x63, 0x6c, 0x6f, 0x73, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x63, 0x6c, 0x6f,
0x73, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6f, 0x62, 0x73, 0x74, 0x61, 0x63, 0x6c, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x62, 0x73, 0x74, 0x61, 0x63, 0x6c, 0x65, 0x22, 0x44,
0x0a, 0x03, 0x50, 0x73, 0x64, 0x22, 0x3d, 0x0a, 0x05, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x0d,
0x0a, 0x09, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x12, 0x0a,
0x0e, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10,
0x01, 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70,
0x65, 0x6e, 0x10, 0x02, 0x22, 0x6c, 0x0a, 0x08, 0x41, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65,
0x12, 0x12, 0x0a, 0x04, 0x67, 0x6d, 0x64, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04,
0x67, 0x6d, 0x64, 0x77, 0x12, 0x12, 0x0a, 0x04, 0x6b, 0x6d, 0x64, 0x77, 0x18, 0x02, 0x20, 0x01,
0x28, 0x08, 0x52, 0x04, 0x6b, 0x6d, 0x64, 0x77, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x67, 0x6a, 0x18,
0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x6d, 0x67, 0x6a, 0x12, 0x10, 0x0a, 0x03, 0x7a, 0x61,
0x77, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x03, 0x7a, 0x61, 0x77, 0x12, 0x14, 0x0a, 0x05,
0x66, 0x6f, 0x72, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72,
0x63, 0x65, 0x42, 0x1d, 0x5a, 0x1b, 0x2e, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e,
0x74, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74,
0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6f, 0x62, 0x73, 0x74, 0x61, 0x63, 0x6c, 0x65, 0x12, 0x2a,
0x0a, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61,
0x73, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x10, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6c,
0x6f, 0x63, 0x6b, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x22, 0x44, 0x0a, 0x03, 0x50, 0x73,
0x64, 0x22, 0x3d, 0x0a, 0x05, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e,
0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x73, 0x64,
0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x01, 0x12, 0x11, 0x0a,
0x0d, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x10, 0x02,
0x22, 0x6c, 0x0a, 0x08, 0x41, 0x73, 0x64, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x12, 0x0a, 0x04,
0x67, 0x6d, 0x64, 0x77, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04, 0x67, 0x6d, 0x64, 0x77,
0x12, 0x12, 0x0a, 0x04, 0x6b, 0x6d, 0x64, 0x77, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x04,
0x6b, 0x6d, 0x64, 0x77, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x67, 0x6a, 0x18, 0x03, 0x20, 0x01, 0x28,
0x08, 0x52, 0x03, 0x6d, 0x67, 0x6a, 0x12, 0x10, 0x0a, 0x03, 0x7a, 0x61, 0x77, 0x18, 0x04, 0x20,
0x01, 0x28, 0x08, 0x52, 0x03, 0x7a, 0x61, 0x77, 0x12, 0x14, 0x0a, 0x05, 0x66, 0x6f, 0x72, 0x63,
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x42, 0x1d,
0x5a, 0x1b, 0x2e, 0x2f, 0x63, 0x6f, 0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x2f, 0x63, 0x6f,
0x6d, 0x70, 0x6f, 0x6e, 0x65, 0x6e, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70,
0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.33.0
// protoc v4.23.1
// source: component/signal.proto

View File

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

View File

@ -0,0 +1,11 @@
package component
import "joylink.club/ecs"
var (
TrackCircuitType = ecs.NewComponentType[TrackCircuit]()
)
type TrackCircuit struct {
GJ *ecs.Entry
}

View File

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

View File

@ -6,22 +6,18 @@ import (
var (
XcjTag = ecs.NewTag()
XcjFaultTag = ecs.NewTag()
XcjCircuitType = ecs.NewComponentType[XcjCircuit]()
)
type XcjCircuit struct {
//联锁驱动的继电器
XQJ *ecs.Entry //洗车请求
TWJ1 *ecs.Entry //头部停稳
TWJ2 *ecs.Entry //尾部停稳
TWJ3 *ecs.Entry //中部停稳
TGQJ *ecs.Entry //通过请求
XCJXJ *ecs.Entry //洗车就绪
XCYXJ *ecs.Entry //洗车允许
CFJ1 *ecs.Entry //头部移动允许
CFJ2 *ecs.Entry //尾部移动允许
CFJ3 *ecs.Entry //中部移动允许
JTJ *ecs.Entry //紧急停车
TGYXJ *ecs.Entry //通过允许
XQJ *ecs.Entry //洗车请求
TWJList []*ecs.Entry //停稳继电器
TGQJ *ecs.Entry //通过请求
XCJXJ *ecs.Entry //洗车就绪
XCYXJ *ecs.Entry //洗车允许
CFJList []*ecs.Entry //移动允许继电器
JTJ *ecs.Entry //紧急停车
TGYXJ *ecs.Entry //通过允许
}

View File

@ -12,7 +12,7 @@ func GetBitOfBytes(bs []byte, bitIndex int) bool {
panic(fmt.Errorf("从字节数组获取位值错误,位索引超出字节数组范围: 数组len=%d,位索引=%d", len(bs), bitIndex))
}
by := bs[bi]
v := byte(1 << (7 - i))
v := byte(1 << i)
return (by & v) == v
}

View File

@ -0,0 +1,20 @@
package entity
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
)
var AxleCountingSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.AxleCountingSectionStateType}
// LoadPhysicalSections 加载计轴区段
func LoadAxleCountingSections(w ecs.World) error {
wd := GetWorldData(w)
sections := wd.Repo.AxleCountingSectionList()
for _, section := range sections {
entry := w.Entry(w.Create(AxleCountingSectionBaseComponentTypes...))
component.UidType.SetValue(entry, component.Uid{Id: section.Id()})
wd.EntityMap[section.Id()] = entry
}
return nil
}

View File

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

View File

@ -108,3 +108,27 @@ func NewDYPEntity(w ecs.World, station *repository.Station) error {
}
return nil
}
// NewLsEntity 创建零散继电器实体
func NewLsEntity(w ecs.World, station *repository.Station) error {
data := GetWorldData(w)
repo := data.Repo
for _, ecc := range station.DeviceEcc() {
if ecc.DeviceType != proto.DeviceType_DeviceType_LS {
continue
}
for _, eg := range ecc.Egs {
if eg.Code != "LS" {
continue
}
for _, componentId := range eg.ComponentIds {
relay := repo.FindById(componentId)
if relay == nil {
return fmt.Errorf("零散继电器实体构建错误: 找不到id=%s的继电器", componentId)
}
NewRelayEntity(w, relay.(*repository.Relay), data.EntityMap)
}
}
}
return nil
}

View File

@ -1,47 +1,74 @@
package entity
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"unsafe"
)
var CkmBaseComponentTypes = []ecs.IComponentType{component.UidType, component.CkmTag, component.CkmStateType, component.FixedPositionTransformType}
var CkmBaseComponentTypes = []ecs.IComponentType{component.UidType, component.CkmTag, component.FixedPositionTransformType}
func LoadCkm(w ecs.World) error {
data := GetWorldData(w)
for _, ckm := range data.Repo.CkmList() {
//创建基础entry
entry := w.Entry(w.Create(CkmBaseComponentTypes...))
component.UidType.SetValue(entry, component.Uid{Id: ckm.Id()})
data.EntityMap[ckm.Id()] = entry
//加载电路
if len(ckm.ComponentGroups()) != 0 {
circuit := &component.CkmCircuit{}
entry.AddComponent(component.CkmCircuitType, unsafe.Pointer(circuit))
for _, group := range ckm.ComponentGroups() {
for _, ec := range group.Components() {
relay := ec.(*repository.Relay)
switch ec.Code() {
case "MKJ":
circuit.MKJ = NewRelayEntity(w, relay, data.EntityMap)
case "MGJ":
circuit.MGJ = NewRelayEntity(w, relay, data.EntityMap)
case "MGZJ":
circuit.MGZJ = NewRelayEntity(w, relay, data.EntityMap)
case "MPLJ":
circuit.MPLJ = NewRelayEntity(w, relay, data.EntityMap)
case "MMSJ":
circuit.MMSJ = NewRelayEntity(w, relay, data.EntityMap)
case "KMJ":
circuit.KMJ = NewRelayEntity(w, relay, data.EntityMap)
case "GMJ":
circuit.GMJ = NewRelayEntity(w, relay, data.EntityMap)
}
ckmEntry := newCkmEntry(w, ckm, data)
addCkmCircuit(w, ckm, ckmEntry, data)
}
for _, psl := range data.Repo.CkmPslList() {
ckmEntry := data.EntityMap[psl.Ckm().Id()]
addCkmPsl(w, psl, ckmEntry, data)
}
return nil
}
// 构建基础镜像
func newCkmEntry(w ecs.World, ckm *repository.Ckm, data *component.WorldData) *donburi.Entry {
//创建基础entry
entry := w.Entry(w.Create(CkmBaseComponentTypes...))
component.UidType.SetValue(entry, component.Uid{Id: ckm.Id()})
data.EntityMap[ckm.Id()] = entry
return entry
}
// 添加车库门电路
func addCkmCircuit(w ecs.World, ckm *repository.Ckm, ckmEntry *donburi.Entry, data *component.WorldData) {
//加载电路
if len(ckm.ComponentGroups()) != 0 {
circuit := &component.CkmCircuit{}
ckmEntry.AddComponent(component.CkmCircuitType, unsafe.Pointer(circuit))
for _, group := range ckm.ComponentGroups() {
for _, ec := range group.Components() {
relay := ec.(*repository.Relay)
switch ec.Code() {
case "MKJ":
circuit.MKJ = NewRelayEntity(w, relay, data.EntityMap)
case "MGJ":
circuit.MGJ = NewRelayEntity(w, relay, data.EntityMap)
case "MGZJ":
circuit.MGZJ = NewRelayEntity(w, relay, data.EntityMap)
case "MPLJ":
circuit.MPLJ = NewRelayEntity(w, relay, data.EntityMap)
case "MMSJ":
circuit.MMSJ = NewRelayEntity(w, relay, data.EntityMap)
case "KMJ":
circuit.KMJ = NewRelayEntity(w, relay, data.EntityMap)
case "GMJ":
circuit.GMJ = NewRelayEntity(w, relay, data.EntityMap)
}
}
}
}
return nil
}
// 添加车库门PSL
func addCkmPsl(w ecs.World, psl *repository.CkmPsl, ckmEntry *ecs.Entry, data *component.WorldData) {
ckmPsl := component.CkmPsl{
KMA: NewButtonEntity(w, psl.Kma(), data.EntityMap),
GMA: NewButtonEntity(w, psl.Gma(), data.EntityMap),
MPLA: NewButtonEntity(w, psl.Mpla(), data.EntityMap),
MMSA: NewButtonEntity(w, psl.Mmsa(), data.EntityMap),
}
ckmEntry.AddComponent(component.CkmPslType, unsafe.Pointer(&ckmPsl))
}

View File

@ -1,64 +0,0 @@
package entity
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"strings"
)
func newAxleManageDevice(w ecs.World, data *component.WorldData, centralizedStation string) *ecs.Entry {
entry := w.Entry(w.Create(component.AxleManageDeviceType))
component.AxleManageDeviceType.Set(entry, component.NewAxleManageDevice(centralizedStation))
data.AxleManageDeviceEntities = append(data.AxleManageDeviceEntities, entry)
return entry
}
// LoadAxlePhysicalSections 加载计轴区段
func LoadAxlePhysicalSections(w ecs.World) error {
data := GetWorldData(w)
sections := data.Repo.PhysicalSectionList()
for _, section := range sections {
if is, se := section.IsAxleSection(); se == nil && is {
if len(strings.TrimSpace(section.CentralizedStation())) == 0 {
return fmt.Errorf("区段[%s]未设置所属集中站", section.Id())
}
amdEntry := FindAxleManageDevice(data, section.CentralizedStation())
if amdEntry == nil {
amdEntry = newAxleManageDevice(w, data, section.CentralizedStation())
}
amd := component.AxleManageDeviceType.Get(amdEntry)
//
createAxleSectionEntity(w, section, data)
//
amd.Adrs[section.Id()] = component.NewAxleDeviceRuntime()
}
}
return nil
}
func FindAxleManageDevice(data *component.WorldData, centralizedStation string) *ecs.Entry {
for _, entry := range data.AxleManageDeviceEntities {
amd := component.AxleManageDeviceType.Get(entry)
if amd != nil && amd.CentralizedStation == centralizedStation {
return entry
}
}
return nil
}
// 计轴区段实体
func createAxleSectionEntity(w ecs.World, axleSection *repository.PhysicalSection, worldData *component.WorldData) *ecs.Entry {
uid := axleSection.Id()
entry, ok := worldData.EntityMap[uid]
if !ok {
entry = w.Entry(w.Create(component.UidType, component.PhysicalSectionStateType, component.AxlePhysicalSectionType))
//
component.UidType.SetValue(entry, component.Uid{Id: uid})
component.PhysicalSectionStateType.Set(entry, &component.PhysicalSectionState{Occ: false})
component.AxlePhysicalSectionType.Set(entry, component.NewAxlePhysicalSection())
//
worldData.EntityMap[uid] = entry
}
return entry
}

View File

@ -195,13 +195,16 @@ func LoadEMPEntity(w ecs.World, entry *ecs.Entry, datas []*repository.Electronic
}
}
if emp.Alarm == nil || emp.QBA == nil || emp.SDA == nil {
return fmt.Errorf("EMP组合初始化出错,请检查IBP地图组合数据")
slog.Warn("EMP组合缺少元素将不添加EMP电路组件")
return nil
}
for code, e := range emp.EMPJMap {
if e.EMPFA_BTN == nil || e.EMPD == nil || len(e.EMP_BTNS) == 0 {
return fmt.Errorf("组合[%s]还原按钮未关联,请检查IBP地图组合数据", code)
slog.Warn(fmt.Sprintf("组合[%s]还原按钮未关联,请检查IBP地图组合数据", code))
return nil
} else if e.EMPJ == nil {
return fmt.Errorf("组合[%s]继电器未关联,请检查继电器地图组合数据", code)
slog.Warn(fmt.Sprintf("组合[%s]继电器未关联,请检查继电器地图组合数据", code))
return nil
}
}
entry.AddComponent(component.EmpElectronicType, unsafe.Pointer(emp))

View File

@ -36,8 +36,13 @@ func Load(w ecs.World, repo *repository.Repository) error {
if err != nil {
return err
}
// 加载物理区段相关实体
err = LoadPhysicalSections(w)
if err != nil {
return err
}
// 加载计轴区段相关实体
err = LoadAxlePhysicalSections(w)
err = LoadAxleCountingSections(w)
if err != nil {
return err
}
@ -56,5 +61,15 @@ func Load(w ecs.World, repo *repository.Repository) error {
if err != nil {
return err
}
//加载轨道电路
err = LoadTrackCircuit(w)
if err != nil {
return err
}
//加载站台(继电器)
err = LoadPlatform(w)
if err != nil {
return err
}
return err
}

View File

@ -0,0 +1,34 @@
package entity
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"unsafe"
)
var PhysicalSectionBaseComponentTypes = []ecs.IComponentType{component.UidType, component.PhysicalSectionTag, component.PhysicalSectionManagerType}
// LoadPhysicalSections 加载计轴区段
func LoadPhysicalSections(w ecs.World) error {
wd := GetWorldData(w)
sections := wd.Repo.PhysicalSectionList()
for _, section := range sections {
if is, err := section.IsAxleSection(); err == nil && is {
entry := w.Entry(w.Create(PhysicalSectionBaseComponentTypes...))
component.UidType.SetValue(entry, component.Uid{Id: section.Id()})
for _, group := range section.ComponentGroups() {
for _, ec := range group.Components() {
if ec.Code() == "GJ" {
relay := ec.(*repository.Relay)
gjEntry := NewRelayEntity(w, relay, wd.EntityMap)
circuit := &component.PhysicalSectionCircuit{GJ: gjEntry}
entry.AddComponent(component.PhysicalSectionCircuitType, unsafe.Pointer(circuit))
}
}
}
wd.EntityMap[section.Id()] = entry
}
}
return nil
}

22
entity/platform.go Normal file
View File

@ -0,0 +1,22 @@
package entity
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/repository"
)
func LoadPlatform(w ecs.World) error {
wd := GetWorldData(w)
for _, platform := range wd.Repo.PlatformList() {
for _, group := range platform.ComponentGroups() {
for _, component := range group.Components() {
relay, ok := component.(*repository.Relay)
if !ok {
continue
}
NewRelayEntity(w, relay, wd.EntityMap)
}
}
}
return nil
}

View File

@ -1,11 +1,11 @@
package entity
import (
"strconv"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"regexp"
"strconv"
)
var PsdBaseComponentTypeArr = []ecs.IComponentType{component.PsdTag, component.UidType,
@ -29,7 +29,7 @@ func LoadPsd(w ecs.World) error {
}
func loadPlatformMkxCircuit(world ecs.World, entryMap map[string]*ecs.Entry, pmcMap map[string]*ecs.Entry,
mkx *repository.Mkx, mkxEntry *ecs.Entry, psdEntry *ecs.Entry) {
mkx *repository.PsdPsl, mkxEntry *ecs.Entry, psdEntry *ecs.Entry) {
platformMkx, ok := pmcMap[mkx.Psd().Id()]
if !ok {
platformMkx = NewPlatformMkxEntry(world, entryMap, mkx)
@ -46,18 +46,26 @@ func loadPsdCircuit(world ecs.World, entry *ecs.Entry, psd *repository.Psd, entr
return
}
circuit := &component.PsdCircuit{KMJMap: make(map[int32]*ecs.Entry)}
pattern := regexp.MustCompile("(\\d*).*KMJ") //用来匹配开门继电器的正则表达式
for _, group := range psd.ComponentGroups() {
for _, ec := range group.Components() {
relay := ec.(*repository.Relay)
matches := pattern.FindStringSubmatch(relay.Code())
if len(matches) != 0 { //匹配上了
if matches[1] == "" { //SKMJ/XKMJ
circuit.KMJMap[0] = NewRelayEntity(world, relay, entryMap)
} else {
num, err := strconv.Atoi(matches[1])
if err != nil {
panic(err)
}
circuit.KMJMap[int32(num)] = NewRelayEntity(world, relay, entryMap)
}
continue
}
switch ec.Code() {
case "XGMJ", "SGMJ":
circuit.GMJ = NewRelayEntity(world, relay, entryMap)
case "XKMJ", "SKMJ":
circuit.KMJMap[0] = NewRelayEntity(world, relay, entryMap)
case "4XKMJ", "4SKMJ":
circuit.KMJMap[4] = NewRelayEntity(world, relay, entryMap)
case "8XKMJ", "8SKMJ":
circuit.KMJMap[8] = NewRelayEntity(world, relay, entryMap)
case "XMGJ", "SMGJ":
circuit.MGJ = NewRelayEntity(world, relay, entryMap)
case "XMPLJ", "SMPLJ":
@ -103,7 +111,7 @@ func NewAsdEntry(world ecs.World, worldData *component.WorldData, psdId string,
return entry
}
func NewMkxEntry(world ecs.World, worldData *component.WorldData, mkx *repository.Mkx) *ecs.Entry {
func NewMkxEntry(world ecs.World, worldData *component.WorldData, mkx *repository.PsdPsl) *ecs.Entry {
entry := world.Entry(world.Create(component.UidType, component.MkxType))
worldData.EntityMap[mkx.Id()] = entry
component.UidType.SetValue(entry, component.Uid{Id: mkx.Id()})
@ -149,7 +157,7 @@ func NewMkxEntry(world ecs.World, worldData *component.WorldData, mkx *repositor
return entry
}
func NewPlatformMkxEntry(world ecs.World, entryMap map[string]*ecs.Entry, mkx *repository.Mkx) *ecs.Entry {
func NewPlatformMkxEntry(world ecs.World, entryMap map[string]*ecs.Entry, mkx *repository.PsdPsl) *ecs.Entry {
entry := world.Entry(world.Create(component.PlatformMkxCircuitType))
circuit := &component.PlatformMkxCircuit{}
if pcbj := mkx.Pcbj(); pcbj != nil {

View File

@ -26,6 +26,13 @@ func NewRelayEntity(w ecs.World, relay *repository.Relay, entityMap map[string]*
entry.AddComponent(component.HfRelayTag)
}
entityMap[uid] = entry
//设置继电器初始状态
switch relay.DefaultPos() {
case proto.Relay_Pos_Q:
component.RelayDriveType.Get(entry).Td = true
case proto.Relay_Pos_H:
component.RelayDriveType.Get(entry).Td = false
}
}
return entry
}

View File

@ -10,7 +10,6 @@ import (
func LoadStations(w ecs.World) error {
data := GetWorldData(w)
stations := data.Repo.StationList()
// 加载零散组合继电器
for _, station := range stations {
err := NewSFAEntity(w, station)
if err != nil {
@ -24,6 +23,10 @@ func LoadStations(w ecs.World) error {
if err != nil {
return err
}
err = NewLsEntity(w, station)
if err != nil {
return err
}
entry := NewStationEntity(w, station.Id(), data)
err = LoadSPKEntity(w, entry, station.SpksComponents(), data) // 人员防护
if err != nil {

51
entity/track_circuit.go Normal file
View File

@ -0,0 +1,51 @@
package entity
import (
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"unsafe"
)
var TrackCircuitBaseComponentTypeArr = []ecs.IComponentType{component.UidType, component.TrackCircuitType}
func LoadTrackCircuit(w ecs.World) error {
data := GetWorldData(w)
for _, trackCircuit := range data.Repo.PhysicalSectionList() {
isAxleSection, err := trackCircuit.IsAxleSection()
if isAxleSection || err != nil {
continue
}
trackCircuitEntry := newTrackCircuitEntry(w, trackCircuit, data)
addTrackCircuit(w, trackCircuit, trackCircuitEntry, data)
}
return nil
}
func newTrackCircuitEntry(w ecs.World, section *repository.PhysicalSection, data *component.WorldData) *ecs.Entry {
uid := section.Id()
entry, ok := data.EntityMap[uid]
if !ok {
entry = w.Entry(w.Create(TrackCircuitBaseComponentTypeArr...))
component.UidType.SetValue(entry, component.Uid{Id: uid})
data.EntityMap[uid] = entry
}
return entry
}
func addTrackCircuit(w ecs.World, circuit *repository.PhysicalSection, entry *ecs.Entry, data *component.WorldData) {
if len(circuit.ComponentGroups()) == 0 {
return
}
trackCircuit := component.TrackCircuit{}
entry.AddComponent(component.TrackCircuitType, unsafe.Pointer(&trackCircuit))
for _, group := range circuit.ComponentGroups() {
for _, ec := range group.Components() {
relay := ec.(*repository.Relay)
switch ec.Code() {
case "GJ":
trackCircuit.GJ = NewRelayEntity(w, relay, data.EntityMap)
}
}
}
}

View File

@ -1,9 +1,13 @@
package entity
import (
"errors"
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/repository"
"strconv"
"strings"
"unsafe"
)
@ -18,7 +22,10 @@ func LoadXcj(w ecs.World) error {
wd.EntityMap[xcj.Id()] = entry
//加载电路
if len(xcj.ComponentGroups()) != 0 {
circuit := &component.XcjCircuit{}
circuit := &component.XcjCircuit{
TWJList: make([]*ecs.Entry, xcj.NumSegments),
CFJList: make([]*ecs.Entry, xcj.NumSegments),
}
entry.AddComponent(component.XcjCircuitType, unsafe.Pointer(circuit))
for _, group := range xcj.ComponentGroups() {
for _, ec := range group.Components() {
@ -26,28 +33,30 @@ func LoadXcj(w ecs.World) error {
switch ec.Code() {
case "XQJ":
circuit.XQJ = NewRelayEntity(w, relay, wd.EntityMap)
case "TWJ1":
circuit.TWJ1 = NewRelayEntity(w, relay, wd.EntityMap)
case "TWJ2":
circuit.TWJ2 = NewRelayEntity(w, relay, wd.EntityMap)
case "TWJ3":
circuit.TWJ3 = NewRelayEntity(w, relay, wd.EntityMap)
case "TGQJ":
circuit.TGQJ = NewRelayEntity(w, relay, wd.EntityMap)
case "XCJXJ":
circuit.XCJXJ = NewRelayEntity(w, relay, wd.EntityMap)
case "XCYXJ":
circuit.XCYXJ = NewRelayEntity(w, relay, wd.EntityMap)
case "CFJ1":
circuit.CFJ1 = NewRelayEntity(w, relay, wd.EntityMap)
case "CFJ2":
circuit.CFJ2 = NewRelayEntity(w, relay, wd.EntityMap)
case "CFJ3":
circuit.CFJ3 = NewRelayEntity(w, relay, wd.EntityMap)
case "JTJ":
circuit.JTJ = NewRelayEntity(w, relay, wd.EntityMap)
case "TGYXJ":
circuit.TGYXJ = NewRelayEntity(w, relay, wd.EntityMap)
default:
if strings.Contains(ec.Code(), "TWJ") {
index, err := strconv.Atoi(ec.Code()[3:])
if err != nil {
return errors.New(fmt.Sprintf("洗车机继电器[%s]编号异常", ec.Code()))
}
circuit.TWJList[index-1] = NewRelayEntity(w, relay, wd.EntityMap)
} else if strings.Contains(ec.Code(), "CFJ") {
index, err := strconv.Atoi(ec.Code()[3:])
if err != nil {
return errors.New(fmt.Sprintf("洗车机继电器[%s]编号异常", ec.Code()))
}
circuit.CFJList[index-1] = NewRelayEntity(w, relay, wd.EntityMap)
}
}
}
}

View File

@ -2,16 +2,9 @@ package main
import (
"fmt"
"log/slog"
"os"
"time"
"joylink.club/ecs"
rtss_simulation "joylink.club/rtsssimulation"
"joylink.club/rtsssimulation/consts"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/examples/signal_3xh1/sigSys"
"joylink.club/rtsssimulation/fi"
"joylink.club/rtsssimulation/repository"
"joylink.club/rtsssimulation/repository/model/proto"
)
@ -22,37 +15,37 @@ const (
// 信号机测试
func main() {
logConfig := &slog.HandlerOptions{AddSource: false, Level: slog.LevelDebug}
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, logConfig)))
//
proto := &proto.Repository{}
proto.Id = "test-for-signal"
proto.Version = "v1.0"
addProtoSignal3XH1(proto)
repo := repository.BuildRepositoryForSignalTest(proto)
sim, _ := rtss_simulation.NewSimulation(repo)
loadEntities(sim, repo)
sim.SetSpeed(1)
sim.AddSystem(sigSys.NewSignalDebugSystem())
sim.StartUp()
//
time.Sleep(1 * time.Second)
slog.Debug("灭灯 .....")
fi.DriveSignal3XH1Dd(sim, IdSignal3XH1, false)
//
time.Sleep(1 * time.Second)
slog.Debug("亮灯 .....")
fi.DriveSignal3XH1Dd(sim, IdSignal3XH1, true)
//
time.Sleep(2 * time.Second)
slog.Debug("开通引导信号 .....")
fi.DriveSignal3XH1Yx(sim, IdSignal3XH1)
time.Sleep(2 * time.Second)
slog.Debug("开通列车信号 .....")
fi.DriveSignal3XH1Lx(sim, IdSignal3XH1, false)
//
time.Sleep(5 * time.Second)
sim.Close()
/* logConfig := &slog.HandlerOptions{AddSource: false, Level: slog.LevelDebug}
slog.SetDefault(slog.New(slog.NewTextHandler(os.Stderr, logConfig)))
//
proto := &proto.Repository{}
proto.Id = "test-for-signal"
proto.Version = "v1.0"
addProtoSignal3XH1(proto)
repo := repository.BuildRepositoryForSignalTest(proto)
sim, _ := rtss_simulation.NewSimulation(repo)
loadEntities(sim, repo)
sim.SetSpeed(1)
sim.AddSystem(sigSys.NewSignalDebugSystem())
sim.StartUp()
//
time.Sleep(1 * time.Second)
slog.Debug("灭灯 .....")
fi.DriveSignal3XH1Dd(sim, IdSignal3XH1, false)
//
time.Sleep(1 * time.Second)
slog.Debug("亮灯 .....")
fi.DriveSignal3XH1Dd(sim, IdSignal3XH1, true)
//
time.Sleep(2 * time.Second)
slog.Debug("开通引导信号 .....")
fi.DriveSignal3XH1Yx(sim, IdSignal3XH1)
time.Sleep(2 * time.Second)
slog.Debug("开通列车信号 .....")
fi.DriveSignal3XH1Lx(sim, IdSignal3XH1, false)
//
time.Sleep(5 * time.Second)
sim.Close()*/
}
func addProtoSignal3XH1(r *proto.Repository) {
//相关继电器

66
fi/balise.go Normal file
View File

@ -0,0 +1,66 @@
package fi
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// BaliseUpdateFixedTelegram 更新固定报文
func BaliseUpdateFixedTelegram(w ecs.World, id string, telegram []byte, userTelegram []byte) error {
result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
entry, ok := wd.EntityMap[id]
if ok {
baliseFixedTelegram := component.BaliseFixedTelegramType.Get(entry)
baliseFixedTelegram.Telegram = telegram
baliseFixedTelegram.UserTelegram = userTelegram
} else {
return ecs.NewErrResult(fmt.Errorf("未找到id=%s的应答器", id))
}
return ecs.NewOkEmptyResult()
})
return result.Err
}
// BaliseUpdateVariableTelegram 更新可变报文
func BaliseUpdateVariableTelegram(w ecs.World, id string, telegram []byte, userTelegram []byte, force bool) error {
result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
entry, ok := wd.EntityMap[id]
if ok {
if entry.HasComponent(component.BaliseVariableTelegramType) {
if force {
entry.AddComponent(component.ForceVariableTelegram)
} else if entry.HasComponent(component.ForceVariableTelegram) {
return ecs.NewOkEmptyResult()
}
baliseVariableTelegram := component.BaliseVariableTelegramType.Get(entry)
baliseVariableTelegram.Telegram = telegram
baliseVariableTelegram.UserTelegram = userTelegram
} else {
ecs.NewErrResult(fmt.Errorf("应答器[%s]无可变报文组件", id))
}
} else {
return ecs.NewErrResult(fmt.Errorf("未找到应答器[%s]", id))
}
return ecs.NewOkEmptyResult()
})
return result.Err
}
// BaliseCancelForceVariableTelegram 取消强制可变报文
func BaliseCancelForceVariableTelegram(w ecs.World, id string) error {
request := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
wd := entity.GetWorldData(w)
entry, ok := wd.EntityMap[id]
if ok {
if entry.HasComponent(component.ForceVariableTelegram) {
entry.RemoveComponent(component.ForceVariableTelegram)
}
}
return ecs.NewOkEmptyResult()
})
return request.Err
}

View File

@ -59,43 +59,3 @@ func SwitchKeyGear(w ecs.World, id string, gear int32) error {
})
return result.Err
}
//func SetBypassBtn(w ecs.World, id string, p request_proto.BypassOperationReq_Operation) error {
//
// result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
// wd := entity.GetWorldData(w)
// entry, ok := wd.EntityMap[id]
// if ok {
// state := component.BitStateType.Get(entry)
// state.Bypass.BypassEnable = convertBypassBoolVal(p)
// state.Bypass.OldVal = state.Val
// } else {
// return ecs.NewErrResult(fmt.Errorf("未找到id=%s的按钮", id))
// }
// return ecs.NewOkEmptyResult()
// })
// return result.Err
//}
//func SetBypassSwitchKey(w ecs.World, id string, p request_proto.BypassOperationReq_Operation) error {
// result := <-ecs.Request[ecs.EmptyType](w, func() ecs.Result[ecs.EmptyType] {
// wd := entity.GetWorldData(w)
// entry, ok := wd.EntityMap[id]
// if ok {
// state := component.GearStateType.Get(entry)
// state.BypassEnable = convertBypassBoolVal(p)
// state.OldVal = state.Val == 0
// } else {
// return ecs.NewErrResult(fmt.Errorf("未找到id=%s的钥匙开关", id))
// }
// return ecs.NewOkEmptyResult()
// })
// return result.Err
//}
//
//func convertBypassBoolVal(p request_proto.BypassOperationReq_Operation) bool {
// val := true
// if p == request_proto.BypassOperationReq_bypass_reset {
// val = false
// }
// return val
//}

View File

@ -1,42 +0,0 @@
package fi
import (
"fmt"
"joylink.club/ecs"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
// 采集继电器吸起电路状态
func CollectXQCircuitState(w ecs.World, id string) bool {
wd := entity.GetWorldData(w)
entry, ok := wd.EntityMap[id]
if ok {
state := component.BitStateType.Get(entry)
return state.Val
} else {
fmt.Printf("未找到id=%s的继电器\n", id)
}
return false
}
// 采集继电器落下电路状态
func CollectLXCircuitState(w ecs.World, id string) bool {
wd := entity.GetWorldData(w)
entry, ok := wd.EntityMap[id]
if ok {
state := component.BitStateType.Get(entry)
return !state.Val
} else {
fmt.Printf("未找到id=%s的继电器\n", id)
}
return false
}
// 驱动电路状态修改
// x,y:二维数组的索引
// state : 32位的bool数组
func DriveCircuitStateChange(w ecs.World, x, y int, state bool) {
}

120
fi/physical_section.go Normal file
View File

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

View File

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

View File

@ -99,6 +99,18 @@ type TrainHeadPositionInfo struct {
Speed float32
//加速度(m/s^2)
Acceleration float32
//列车上一次所在轨道link
OldLink string
//列车上一次车头位置信息
OldLinkOffset int64
TailUp bool
TailLink string
//列车上一次车头位置信息
TailLinkOffset int64
OldTailLink string
//列车上一次车头位置信息
OldTailLinkOffset int64
IsLine12 bool
}
func (t *TrainHeadPositionInfo) String() string {

4
go.mod
View File

@ -4,11 +4,11 @@ go 1.21
require (
github.com/stretchr/testify v1.8.4
google.golang.org/protobuf v1.31.0
google.golang.org/protobuf v1.32.0
joylink.club/ecs v0.0.1
)
replace joylink.club/ecs => ./jl-ecs-go
replace joylink.club/ecs => ./jl-ecs
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect

7
go.sum
View File

@ -1,7 +1,5 @@
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
@ -11,10 +9,7 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/yohamta/donburi v1.3.9 h1:sYAPaelSnxmoTGjgH9ZlYt4pUKrnwvAv4YGXxLZCK6E=
github.com/yohamta/donburi v1.3.9/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=

View File

@ -2,5 +2,5 @@ go 1.21
use (
.
./jl-ecs-go
./jl-ecs
)

View File

@ -1,31 +1,42 @@
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/ebitengine/purego v0.0.0-20220905075623-aeed57cda744/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
github.com/ebitengine/purego v0.1.0 h1:vAEo1FvmbjA050QKsbDbcHj03hhMMvh0fmr9LSehpnU=
github.com/ebitengine/purego v0.1.0/go.mod h1:Eh8I3yvknDYZeCuXH9kRNaPuHEwvXDCk378o9xszmHg=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad h1:kX51IjbsJPCvzV9jUoVQG9GEUqIq5hjfYzXTqQ52Rh8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20220806181222-55e207c401ad/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/hajimehoshi/bitmapfont/v2 v2.2.2/go.mod h1:Ua/x9Dkz7M9CU4zr1VHWOqGwjKdXbOTRsH7lWfb1Co0=
github.com/hajimehoshi/ebiten/v2 v2.4.13 h1:ZZ5y+bFkAbUeD2WGquHF+xSbg83SIbcsxCwEVeZgHWM=
github.com/hajimehoshi/ebiten/v2 v2.4.13/go.mod h1:BZcqCU4XHmScUi+lsKexocWcf4offMFwfp8dVGIB/G4=
github.com/hajimehoshi/file2byteslice v0.0.0-20210813153925-5340248a8f41/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/file2byteslice v1.0.0 h1:ljd5KTennqyJ4vG9i/5jS8MD1prof97vlH5JOdtw3WU=
github.com/hajimehoshi/file2byteslice v1.0.0/go.mod h1:CqqAHp7Dk/AqQiwuhV1yT2334qbA/tFWQW0MD2dGqUE=
github.com/hajimehoshi/go-mp3 v0.3.3/go.mod h1:qMJj/CSDxx6CGHiZeCgbiq2DSUkbK0UbtXShQcnfyMM=
github.com/hajimehoshi/oto v0.6.1/go.mod h1:0QXGEkbuJRohbJaxr7ZQSxnju7hEhseiPx2hrh6raOI=
github.com/hajimehoshi/oto/v2 v2.3.1/go.mod h1:seWLbgHH7AyUMYKfKYT9pg7PhUu9/SisyJvNTT+ASQo=
github.com/jakecoffman/cp v1.2.1/go.mod h1:JjY/Fp6d8E1CHnu74gWNnU0+b9VzEdUVPoJxg2PsTQg=
github.com/jezek/xgb v1.0.1 h1:YUGhxps0aR7J2Xplbs23OHnV1mWaxFVcOl9b+1RQkt8=
github.com/jezek/xgb v1.0.1/go.mod h1:nrhwO0FX/enq75I7Y7G8iN1ubpSGZEiA3v9e9GyRFlk=
github.com/jfreymuth/oggvorbis v1.0.4/go.mod h1:1U4pqWmghcoVsCJJ4fRBKv9peUJMBHixthRlBeD6uII=
github.com/jfreymuth/vorbis v1.0.2/go.mod h1:DoftRo4AznKnShRl1GxiTFCseHr4zR9BN3TWXyuzrqQ=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e h1:aoZm08cpOy4WuID//EZDgcC4zIxODThtZNPirFr42+A=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
@ -39,13 +50,16 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190415191353-3e0bab5405d6/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mobile v0.0.0-20220722155234-aaac322e2105/go.mod h1:pe2sM7Uk+2Su1y7u/6Z8KJ24D7lepUjFZbhFOrmDfuQ=
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303 h1:K4fp1rDuJBz0FCPAWzIJwnzwNEM7S6yobdZzMrZ/Zws=
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303/go.mod h1:M32cGdzp91A8Ex9qQtyZinr19EYxzkFqDjW2oyHzTDQ=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
@ -73,6 +87,7 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220712014510-0a85c31ab51e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 h1:OK7RB6t2WQX54srQQYSXMW8dF5C6/8+oA/s5QBmmto4=
golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@ -88,6 +103,9 @@ golang.org/x/tools v0.1.8-0.20211022200916-316ba0b74098/go.mod h1:LGqMHiF4EqQNHR
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -10,7 +10,7 @@ import (
const (
// 仿真循环间隔单位ms
RtssSimulationTick = 20
RtssSimulationTick = 10
)
// 初始化仿真

2
jl-ecs

@ -1 +1 @@
Subproject commit 9c5dde7b2ec28c555488eee7dec81bb1f612c443
Subproject commit f0a56ea6722b620c8b900efa9f0d626f00af00ad

View File

@ -19,7 +19,7 @@ var goOutDir string = "./"
func main() {
//先安装以下插件
//go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
//go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0
args := os.Args
if len(args) >= 2 {
switch {

View File

@ -1,15 +0,0 @@
syntax = "proto3";
package component;
option go_package = "./component/component_data";
message CkmState {
bool close = 1;
bool mms = 2; //true远程false本地
bool mgz = 3; //
//
bool km = 4; //
bool gm = 5; //
}

View File

@ -6,7 +6,8 @@ option go_package = "./component/component_proto";
message PsdState {
bool close = 1;
bool obstacle = 2;
bool obstacle = 2; //
bool interlockRelease = 3; //
}
message Psd {

View File

@ -30,6 +30,13 @@ message Repository {
repeated Route routes = 23;
repeated Ckm ckms = 24;
repeated Xcj xcjs = 25;
repeated CkmPsl ckmPsls = 26;
repeated Esb esbs = 27;
repeated Spks spkss = 28;
repeated AxleCountingSection axleCountingSections = 29; //
repeated KilometerCalibration kilometerCalibrations = 30; //
repeated StopPosition stopPosition = 31;
//ISCS [300,500]
//ISCS管线
repeated Pipe pipes = 300;
@ -74,7 +81,15 @@ message Repository {
//ISCS气体环境
repeated GasEnvironment gasEnvironments = 320;
}
message StopPosition{
string id = 1;
uint32 linkId = 2;
uint32 linkOffset = 3;
Kilometer km = 4;
string sectionId = 5; //
DevicePort turnoutPort = 6; //
uint32 coachNum = 7;//
}
//
message SignalLayout {
//
@ -94,8 +109,16 @@ message PhysicalSection {
repeated string turnoutIds = 2; //
DevicePort aDevicePort = 3; //A端关联的设备端口
DevicePort bDevicePort = 4;
//
string centralizedStation = 5;
//uid
repeated string centralizedStation = 5;
repeated ElectronicComponentGroup electronicComponentGroups = 6;
}
//
message AxleCountingSection {
string id = 1;
repeated string axleCountingIds = 2;
repeated TurnoutAndPos turnoutAndPos = 3;
}
//
@ -113,6 +136,11 @@ message Turnout {
ZDJ9_Single = 1;
ZDJ9_Double = 2;
}
enum Pos {
Pos_Unknown = 0;
Pos_N = 1; //
Pos_R = 2; //
}
string id = 1;
Kilometer km = 2;
DevicePort aDevicePort = 3;
@ -162,6 +190,8 @@ message Transponder {
bytes fixedTelegram = 5;//
Type type = 6;//
bytes fixedUserTelegram = 7; //
uint32 leuIndex = 8; //LEU的索引
uint32 indexInLeu = 9; //LEU内部的索引
enum Type {
FB = 0; //
WB = 1; //
@ -192,6 +222,12 @@ message DevicePort {
Port port = 3;
}
//
message TurnoutAndPos {
string turnoutId = 1;
Turnout.Pos pos = 2;
}
enum DeviceType {
DeviceType_Unknown = 0;
DeviceType_PhysicalSection = 1;
@ -216,13 +252,20 @@ enum DeviceType {
//
DeviceType_SignalFaultAlarm = 20;
//
DeviceType_Breakers = 21;
DeviceType_Breakers = 21;
//
DeviceType_PowerScreen = 22;
DeviceType_PowerScreen = 22;
//
DeviceType_Route = 23;
DeviceType_Ckm = 24;
DeviceType_Xcj = 25;
DeviceType_Ckm = 24; //
DeviceType_Xcj = 25; //
DeviceType_CkmPsl = 26; //PSL
DeviceType_TrackCircuit = 27; //
DeviceType_LS = 28; //
DeviceType_Esb = 29; //
DeviceType_Spks = 30; //
DeviceTYpe_AxleCountingSection = 31; //
deviceType_Stop_position = 32;
//--------ISCS [300,500]------
//ISCS门磁
@ -388,6 +431,12 @@ message KilometerConvert {
bool sameTrend = 3; //
}
//
message KilometerCalibration {
Kilometer design = 1; //
Kilometer actual = 2; //
}
//
enum Direction {
LEFT = 0;
@ -414,10 +463,16 @@ message Relay {
JYJXC_160_260 = 7;
JZXC_H18 = 8;
}
enum Pos {
Pos_None = 0; //
Pos_Q = 1; //
Pos_H = 2; //
}
string id = 1;
string code = 2;
Model model = 3;
string stationId = 4; // id
Pos defaultPos = 5; //
}
//
@ -493,7 +548,7 @@ message ElectronicGroup {
//
message ElectronicComponent {
string id= 1; // ID
string id = 1; // ID
DeviceType deviceType = 3; //
}
//
@ -518,9 +573,32 @@ message Mkx {
string mplaId = 18; //
string jxtcplaId = 19; //
}
//PSL
message CkmPsl {
string id = 1;
string ckmId = 2;
string gmaId = 3; //
string kmaId = 4; //
string mplaId = 5; //
string mmsaId = 6; //
}
//
message Esb {
string id = 1;
string platformId = 2;
}
//
message Spks {
string id = 1;
string code = 2;
string platformId = 3;
}
//
message Platform {
enum PlatformDirection {
enum Direction {
Unknown = 0;
Up = 1; //
Down = 2; //
@ -529,7 +607,8 @@ message Platform {
string code = 2;
string stationId = 3;
string physicalSectionId = 4;
PlatformDirection direction = 5;
Direction direction = 5;
repeated ElectronicComponentGroup electronicComponentGroups = 6; //
}
//
@ -728,10 +807,10 @@ message Valve{
string code = 2;
//
enum Type{
ElectricControlValve = 0;//
ElectricAirValve = 1;//
CombinationAirValve = 2;//
ElectricButterflyValve = 3;//
ElectricControlValve = 0;//
ElectricAirValve = 1;//
CombinationAirValve = 2;//
ElectricButterflyValve = 3;//
}
Type valveType = 3;//
}
@ -798,5 +877,6 @@ message Ckm {
message Xcj {
string id = 1;
repeated ElectronicComponentGroup electronicComponentGroups = 2;
uint32 numSegments = 3; //
}

View File

@ -1,6 +1,6 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.32.0
// protoc-gen-go v1.33.0
// protoc v4.23.1
// source: cg_repo.proto

View File

@ -0,0 +1,29 @@
package repository
import "joylink.club/rtsssimulation/repository/model/proto"
type AxleCountingSection struct {
Identity
//axleCountingList []CheckPoint //暂时用不上,先不要了
turnoutAndPosList []*proto.TurnoutAndPos
physicalSection *PhysicalSection
}
func NewAxleCountingSection(id string, turnoutAndPosList []*proto.TurnoutAndPos) *AxleCountingSection {
return &AxleCountingSection{
Identity: identity{
id: id,
deviceType: proto.DeviceType_DeviceTYpe_AxleCountingSection,
},
turnoutAndPosList: turnoutAndPosList,
}
}
func (a *AxleCountingSection) TurnoutAndPosList() []*proto.TurnoutAndPos {
return a.turnoutAndPosList
}
func (a *AxleCountingSection) PhysicalSection() *PhysicalSection {
return a.physicalSection
}

View File

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

34
repository/ckm_psl.go Normal file
View File

@ -0,0 +1,34 @@
package repository
import "joylink.club/rtsssimulation/repository/model/proto"
type CkmPsl struct {
Identity
ckm *Ckm
kma *Button
gma *Button
mpla *Button
mmsa *Button
}
func NewCkmPsl(id string) *CkmPsl {
return &CkmPsl{
Identity: identity{id, proto.DeviceType_DeviceType_CkmPsl},
}
}
func (psl *CkmPsl) Ckm() *Ckm {
return psl.ckm
}
func (psl *CkmPsl) Kma() *Button {
return psl.kma
}
func (psl *CkmPsl) Gma() *Button {
return psl.gma
}
func (psl *CkmPsl) Mpla() *Button {
return psl.mpla
}
func (psl *CkmPsl) Mmsa() *Button {
return psl.mmsa
}

View File

@ -11,21 +11,23 @@ type IGroupedElectronicComponent interface {
// Relay 继电器
type Relay struct {
Identity
code string
model proto.Relay_Model
code string
model proto.Relay_Model
defaultPos proto.Relay_Pos
// 所属车站
station *Station
}
func newRelay(id string, code string, model proto.Relay_Model, s *Station) *Relay {
func newRelay(id string, code string, model proto.Relay_Model, defaultPos proto.Relay_Pos, s *Station) *Relay {
return &Relay{
Identity: identity{
id: id,
deviceType: proto.DeviceType_DeviceType_Relay,
},
code: code,
model: model,
station: s,
code: code,
model: model,
defaultPos: defaultPos,
station: s,
}
}
@ -37,6 +39,10 @@ func (r *Relay) Model() proto.Relay_Model {
return r.model
}
func (r *Relay) DefaultPos() proto.Relay_Pos {
return r.defaultPos
}
// ElectronicComponentGroup 电子元件组合
type ElectronicComponentGroup struct {
code string

16
repository/esb.go Normal file
View File

@ -0,0 +1,16 @@
package repository
// Esb 紧急停车系统。目前内部属性仅作为和第三方联锁通信时,获取紧急停车系统状态的便捷途径
type Esb struct {
Identity
plaId string //旁路按钮ID
relayId string //紧急停车继电器ID
}
func (e *Esb) PlaId() string {
return e.plaId
}
func (e *Esb) RelayId() string {
return e.relayId
}

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@ -7,7 +7,7 @@ import (
"joylink.club/rtsssimulation/util/number"
)
// 物理区段
// PhysicalSection 物理区段
type PhysicalSection struct {
Identity
@ -33,11 +33,18 @@ type PhysicalSection struct {
//在Link上的区间start小于end
linkRanges []*LinkRange
//物理区段所属集中站
centralizedStation string
//物理区段所属集中站uid
centralizedStation []*Station
// 所属站台
platform *Platform
//电子元件
componentGroups []*ElectronicComponentGroup
}
func (p *PhysicalSection) ComponentGroups() []*ElectronicComponentGroup {
return p.componentGroups
}
func NewPhysicalSection(id string) *PhysicalSection {
@ -54,44 +61,44 @@ func (p *PhysicalSection) bindLinkRange(link *Link, one int64, two int64) {
})
}
func (s *PhysicalSection) PortNum() int {
func (p *PhysicalSection) PortNum() int {
return 2
}
func (s *PhysicalSection) ALinkPosition() *LinkPosition {
return s.aLinkPosition
func (p *PhysicalSection) ALinkPosition() *LinkPosition {
return p.aLinkPosition
}
func (s *PhysicalSection) BLinkPosition() *LinkPosition {
return s.bLinkPosition
func (p *PhysicalSection) BLinkPosition() *LinkPosition {
return p.bLinkPosition
}
func (s *PhysicalSection) ARelation() DevicePort {
return s.aRelation
func (p *PhysicalSection) ARelation() DevicePort {
return p.aRelation
}
func (s *PhysicalSection) BRelation() DevicePort {
return s.bRelation
func (p *PhysicalSection) BRelation() DevicePort {
return p.bRelation
}
func (s *PhysicalSection) AKilometer() *proto.Kilometer {
return s.aKm
func (p *PhysicalSection) AKilometer() *proto.Kilometer {
return p.aKm
}
func (s *PhysicalSection) BKilometer() *proto.Kilometer {
return s.bKm
func (p *PhysicalSection) BKilometer() *proto.Kilometer {
return p.bKm
}
// IsAxleSection 判断是否为计轴区段
func (s *PhysicalSection) IsAxleSection() (bool, error) {
if len(s.checkPoints) > 0 {
func (p *PhysicalSection) IsAxleSection() (bool, error) {
if len(p.checkPoints) > 0 {
axleCount := 0
for _, cp := range s.checkPoints {
for _, cp := range p.checkPoints {
if cp.pointType == proto.CheckPointType_AxleCounter {
axleCount++
}
}
if axleCount == len(s.checkPoints) {
if axleCount == len(p.checkPoints) {
return true, nil
} else if axleCount == 0 {
return false, nil
@ -102,10 +109,10 @@ func (s *PhysicalSection) IsAxleSection() (bool, error) {
return false, fmt.Errorf("物理区段没有检测点")
}
}
func (s *PhysicalSection) CentralizedStation() string {
return s.centralizedStation
func (p *PhysicalSection) CentralizedStation() []*Station {
return p.centralizedStation
}
func (s *PhysicalSection) bindDevicePort(port proto.Port, devicePort DevicePort) error {
func (p *PhysicalSection) bindDevicePort(port proto.Port, devicePort DevicePort) error {
_, isSectionPort := devicePort.(*PhysicalSectionPort)
_, isTurnoutPort := devicePort.(*TurnoutPort)
if !isSectionPort && !isTurnoutPort {
@ -113,9 +120,9 @@ func (s *PhysicalSection) bindDevicePort(port proto.Port, devicePort DevicePort)
}
switch port {
case proto.Port_A:
s.aRelation = devicePort
p.aRelation = devicePort
case proto.Port_B:
s.bRelation = devicePort
p.bRelation = devicePort
default:
return fmt.Errorf("物理区段无端口[%s]", port)
}
@ -123,15 +130,15 @@ func (s *PhysicalSection) bindDevicePort(port proto.Port, devicePort DevicePort)
}
// 绑定区段边界公里标。(仅限非道岔物理区段调用)
func (s *PhysicalSection) bindBoundaryKm(km *proto.Kilometer, port proto.Port) error {
func (p *PhysicalSection) bindBoundaryKm(km *proto.Kilometer, port proto.Port) error {
if km == nil || (km.CoordinateSystem == "" && km.Value == 0) {
return nil
}
switch port {
case proto.Port_A:
s.aKm = km
p.aKm = km
case proto.Port_B:
s.bKm = km
p.bKm = km
default:
return fmt.Errorf("区段无端口[%s]", port)
}
@ -139,56 +146,56 @@ func (s *PhysicalSection) bindBoundaryKm(km *proto.Kilometer, port proto.Port) e
}
// 道岔物理区段绑定道岔
func (s *PhysicalSection) bindTurnouts(turnouts ...*Turnout) {
func (p *PhysicalSection) bindTurnouts(turnouts ...*Turnout) {
for _, turnout := range turnouts {
s.turnouts = append(s.turnouts, turnout)
p.turnouts = append(p.turnouts, turnout)
for _, cp := range turnout.checkPoints() {
s.bindDevices(cp)
p.bindDevices(cp)
}
}
}
func (s *PhysicalSection) bindDevices(devices ...Identity) {
func (p *PhysicalSection) bindDevices(devices ...Identity) {
for _, device := range devices {
s.devices = append(s.devices, device)
p.devices = append(p.devices, device)
cp, ok := device.(*CheckPoint)
if ok {
s.checkPoints = append(s.checkPoints, cp)
p.checkPoints = append(p.checkPoints, cp)
}
}
}
func (s *PhysicalSection) findOtherDevicePort(port proto.Port) DevicePort {
func (p *PhysicalSection) findOtherDevicePort(port proto.Port) DevicePort {
switch port {
case proto.Port_A:
return s.bRelation
return p.bRelation
case proto.Port_B:
return s.aRelation
return p.aRelation
}
return nil
}
func (s *PhysicalSection) findOtherBoundaryKmByPort(port proto.Port) *proto.Kilometer {
func (p *PhysicalSection) findOtherBoundaryKmByPort(port proto.Port) *proto.Kilometer {
switch port {
case proto.Port_A:
return s.bKm
return p.bKm
case proto.Port_B:
return s.aKm
return p.aKm
}
return nil
}
func (s *PhysicalSection) findBoundaryKmByPort(port proto.Port) *proto.Kilometer {
func (p *PhysicalSection) findBoundaryKmByPort(port proto.Port) *proto.Kilometer {
switch port {
case proto.Port_A:
return s.aKm
return p.aKm
case proto.Port_B:
return s.bKm
return p.bKm
}
return nil
}
func (s *PhysicalSection) LinkRanges() []*LinkRange {
return s.linkRanges
func (p *PhysicalSection) LinkRanges() []*LinkRange {
return p.linkRanges
}
func (p *PhysicalSection) Platform() *Platform {

View File

@ -4,18 +4,21 @@ import "joylink.club/rtsssimulation/repository/model/proto"
type Platform struct {
Identity
code string
station *Station
section *PhysicalSection
code string
dir proto.Platform_Direction
station *Station
section *PhysicalSection
componentGroups []*ElectronicComponentGroup
}
func NewPlatform(id string, code string) *Platform {
func NewPlatform(id string, code string, dir proto.Platform_Direction) *Platform {
return &Platform{
Identity: identity{
id: id,
deviceType: proto.DeviceType_DeviceType_Platform,
},
code: code,
dir: dir,
}
}
@ -30,3 +33,7 @@ func (p *Platform) Station() *Station {
func (p *Platform) Section() *PhysicalSection {
return p.section
}
func (p *Platform) ComponentGroups() []*ElectronicComponentGroup {
return p.componentGroups
}

View File

@ -2,7 +2,7 @@ package repository
import "joylink.club/rtsssimulation/repository/model/proto"
type Mkx struct {
type PsdPsl struct {
Identity
psd *Psd
@ -25,8 +25,8 @@ type Mkx struct {
jxtcpl *Button
}
func NewMkx(id string) *Mkx {
return &Mkx{
func NewPsdPsl(id string) *PsdPsl {
return &PsdPsl{
Identity: identity{
id: id,
deviceType: proto.DeviceType_DeviceType_Mkx,
@ -34,74 +34,74 @@ func NewMkx(id string) *Mkx {
}
}
func (m *Mkx) Psd() *Psd {
func (m *PsdPsl) Psd() *Psd {
return m.psd
}
func (m *Mkx) Pcb() *Button {
func (m *PsdPsl) Pcb() *Button {
return m.pcb
}
func (m *Mkx) Pcbpl() *Button {
func (m *PsdPsl) Pcbpl() *Button {
return m.pcbpl
}
func (m *Mkx) Pcbj() *Relay {
func (m *PsdPsl) Pcbj() *Relay {
return m.pcbj
}
func (m *Mkx) Pob() *Button {
func (m *PsdPsl) Pob() *Button {
return m.pob
}
func (m *Mkx) Pobpl() *Button {
func (m *PsdPsl) Pobpl() *Button {
return m.pobpl
}
func (m *Mkx) Pobj() *Relay {
func (m *PsdPsl) Pobj() *Relay {
return m.pobj
}
func (m *Mkx) Pab() *Button {
func (m *PsdPsl) Pab() *Button {
return m.pab
}
func (m *Mkx) Pabpl() *Button {
func (m *PsdPsl) Pabpl() *Button {
return m.pabpl
}
func (m *Mkx) Pabj() *Relay {
func (m *PsdPsl) Pabj() *Relay {
return m.pabj
}
func (m *Mkx) Wrzf() *Button {
func (m *PsdPsl) Wrzf() *Button {
return m.wrzf
}
func (m *Mkx) Wrzfpl() *Button {
func (m *PsdPsl) Wrzfpl() *Button {
return m.wrzfpl
}
func (m *Mkx) Wrzfj() *Relay {
func (m *PsdPsl) Wrzfj() *Relay {
return m.wrzfj
}
func (m *Mkx) Qkqr() *Button {
func (m *PsdPsl) Qkqr() *Button {
return m.qkqr
}
func (m *Mkx) Qkqrpl() *Button {
func (m *PsdPsl) Qkqrpl() *Button {
return m.qkqrpl
}
func (m *Mkx) Qkqrj() *Relay {
func (m *PsdPsl) Qkqrj() *Relay {
return m.qkqrj
}
func (m *Mkx) Mpl() *Button {
func (m *PsdPsl) Mpl() *Button {
return m.mpl
}
func (m *Mkx) Jxtcpl() *Button {
func (m *PsdPsl) Jxtcpl() *Button {
return m.jxtcpl
}

View File

@ -8,31 +8,38 @@ import (
)
type Repository struct {
id string
version string
coordinate *MapCoordinate // 基准坐标系类型,在列车画图时统一坐标系
physicalSectionMap map[string]*PhysicalSection
checkPointMap map[string]*CheckPoint
turnoutMap map[string]*Turnout
signalMap map[string]*Signal
responderMap map[string]*Transponder
slopeMap map[string]*Slope
sectionalCurvatureMap map[string]*SectionalCurvature
kilometerConvertMap map[string]*proto.KilometerConvert
relayMap map[string]*Relay
phaseFailureProtectorMap map[string]*PhaseFailureProtector
buttonMap map[string]*Button
psdMap map[string]*Psd
lightMap map[string]*Light
alarmMap map[string]*Alarm
stationMap map[string]*Station
mkxMap map[string]*Mkx
keyMap map[string]*Key
linkMap map[string]*Link
platformMap map[string]*Platform
centralizedMap map[string]*proto.CentralizedStationRef
ckmMap map[string]*Ckm
xcjMap map[string]*Xcj
id string
version string
coordinate *MapCoordinate // 基准坐标系类型,在列车画图时统一坐标系
physicalSectionMap map[string]*PhysicalSection
axleCountingSectionMap map[string]*AxleCountingSection
checkPointMap map[string]*CheckPoint
turnoutMap map[string]*Turnout
signalMap map[string]*Signal
responderMap map[string]*Transponder
slopeMap map[string]*Slope
sectionalCurvatureMap map[string]*SectionalCurvature
kilometerConvertMap map[string]*proto.KilometerConvert
relayMap map[string]*Relay
phaseFailureProtectorMap map[string]*PhaseFailureProtector
buttonMap map[string]*Button
psdMap map[string]*Psd
lightMap map[string]*Light
alarmMap map[string]*Alarm
stationMap map[string]*Station
psdPslMap map[string]*PsdPsl
keyMap map[string]*Key
linkMap map[string]*Link
platformMap map[string]*Platform
centralizedMap map[string]*proto.CentralizedStationRef
ckmMap map[string]*Ckm
ckmPslMap map[string]*CkmPsl
xcjMap map[string]*Xcj
esbMap map[string]*Esb
spksMap map[string]*Spks
kilometerCalibrationMap map[string][]*proto.KilometerCalibration //从大到小排序
StopPosition map[string]*StopPosition
PipeMap map[string]*Pipe //ISCS 管线
PipeFittingMap map[string]*PipeFitting //ISCS 管件
CircuitBreakerMap map[string]*CircuitBreaker //ISCS 断路器
@ -58,28 +65,37 @@ type Repository struct {
func newRepository(id string, version string) *Repository {
return &Repository{
id: id,
version: version,
physicalSectionMap: make(map[string]*PhysicalSection),
checkPointMap: make(map[string]*CheckPoint),
turnoutMap: make(map[string]*Turnout),
signalMap: make(map[string]*Signal),
responderMap: make(map[string]*Transponder),
slopeMap: make(map[string]*Slope),
sectionalCurvatureMap: make(map[string]*SectionalCurvature),
kilometerConvertMap: make(map[string]*proto.KilometerConvert),
relayMap: make(map[string]*Relay),
phaseFailureProtectorMap: make(map[string]*PhaseFailureProtector),
linkMap: make(map[string]*Link),
buttonMap: make(map[string]*Button),
psdMap: make(map[string]*Psd),
lightMap: make(map[string]*Light),
alarmMap: make(map[string]*Alarm),
stationMap: make(map[string]*Station),
mkxMap: make(map[string]*Mkx),
keyMap: make(map[string]*Key),
platformMap: make(map[string]*Platform),
centralizedMap: make(map[string]*proto.CentralizedStationRef),
id: id,
version: version,
physicalSectionMap: make(map[string]*PhysicalSection),
axleCountingSectionMap: make(map[string]*AxleCountingSection),
checkPointMap: make(map[string]*CheckPoint),
turnoutMap: make(map[string]*Turnout),
signalMap: make(map[string]*Signal),
responderMap: make(map[string]*Transponder),
slopeMap: make(map[string]*Slope),
sectionalCurvatureMap: make(map[string]*SectionalCurvature),
kilometerConvertMap: make(map[string]*proto.KilometerConvert),
relayMap: make(map[string]*Relay),
phaseFailureProtectorMap: make(map[string]*PhaseFailureProtector),
linkMap: make(map[string]*Link),
buttonMap: make(map[string]*Button),
psdMap: make(map[string]*Psd),
lightMap: make(map[string]*Light),
alarmMap: make(map[string]*Alarm),
stationMap: make(map[string]*Station),
psdPslMap: make(map[string]*PsdPsl),
keyMap: make(map[string]*Key),
platformMap: make(map[string]*Platform),
centralizedMap: make(map[string]*proto.CentralizedStationRef),
ckmMap: make(map[string]*Ckm),
ckmPslMap: make(map[string]*CkmPsl),
xcjMap: make(map[string]*Xcj),
esbMap: make(map[string]*Esb),
spksMap: make(map[string]*Spks),
kilometerCalibrationMap: make(map[string][]*proto.KilometerCalibration),
StopPosition: make(map[string]*StopPosition),
PipeMap: make(map[string]*Pipe), //ISCS 管线
PipeFittingMap: make(map[string]*PipeFitting), //ISCS 管件
CircuitBreakerMap: make(map[string]*CircuitBreaker), //ISCS 断路器
@ -206,6 +222,13 @@ func (repo *Repository) PhysicalSectionList() []*PhysicalSection {
}
return list
}
func (repo *Repository) AxleCountingSectionList() []*AxleCountingSection {
var list []*AxleCountingSection
for _, model := range repo.axleCountingSectionMap {
list = append(list, model)
}
return list
}
func (repo *Repository) CheckPointList() []*CheckPoint {
var list []*CheckPoint
for _, model := range repo.checkPointMap {
@ -293,9 +316,9 @@ func (repo *Repository) PsdList() []*Psd {
}
return list
}
func (repo *Repository) MkxList() []*Mkx {
var list []*Mkx
for _, model := range repo.mkxMap {
func (repo *Repository) MkxList() []*PsdPsl {
var list []*PsdPsl
for _, model := range repo.psdPslMap {
list = append(list, model)
}
return list
@ -340,6 +363,38 @@ func (repo *Repository) XcjList() []*Xcj {
return list
}
func (repo *Repository) CkmPslList() []*CkmPsl {
var list []*CkmPsl
for _, model := range repo.ckmPslMap {
list = append(list, model)
}
return list
}
func (repo *Repository) PlatformList() []*Platform {
var list []*Platform
for _, model := range repo.platformMap {
list = append(list, model)
}
return list
}
func (repo *Repository) CentralizedStationRefList() []*proto.CentralizedStationRef {
var list []*proto.CentralizedStationRef
for _, model := range repo.centralizedMap {
list = append(list, model)
}
return list
}
func (repo *Repository) TransponderList() []*Transponder {
var list []*Transponder
for _, model := range repo.responderMap {
list = append(list, model)
}
return list
}
func (repo *Repository) GetCentralizedStationRef(centralizedStationId string) *proto.CentralizedStationRef {
return repo.centralizedMap[centralizedStationId]
}
@ -424,6 +479,14 @@ func (repo *Repository) FindPhysicalSection(id string) *PhysicalSection {
return repo.physicalSectionMap[id]
}
func (repo *Repository) FindAxleCountingSection(id string) *AxleCountingSection {
return repo.axleCountingSectionMap[id]
}
func (repo *Repository) FindRelay(id string) *Relay {
return repo.relayMap[id]
}
func (repo *Repository) FindStationByStationName(name string) *Station {
for _, s := range repo.StationList() {
if s.code == name {
@ -437,12 +500,16 @@ func (repo *Repository) FindPsd(id string) *Psd {
return repo.psdMap[id]
}
func (repo *Repository) FindPlatfrom(id string) *Platform {
func (repo *Repository) FindPlatform(id string) *Platform {
return repo.platformMap[id]
}
func (repo *Repository) AddPhysicalSection(section *PhysicalSection) {
repo.physicalSectionMap[section.Id()] = section
func (repo *Repository) FindEsb(id string) *Esb {
return repo.esbMap[id]
}
func (repo *Repository) FindSpks(id string) *Spks {
return repo.spksMap[id]
}
func (repo *Repository) ConvertKilometer(km *proto.Kilometer, cs string) (*proto.Kilometer, error) {
@ -517,7 +584,7 @@ func (repo *Repository) generateCoordinateInfo(coordinateSystem string) error {
return nil
}
func (repo Repository) GetCoordinateInfo() *MapCoordinate {
func (repo *Repository) GetCoordinateInfo() *MapCoordinate {
return repo.coordinate
}

View File

@ -75,5 +75,16 @@ func baseCheck(source *proto.Repository) []string {
errMsg = append(errMsg, fmt.Sprintf("应答器[%s]缺少关联的区段或道岔", transponder.Id))
}
}
//停车点
for _, sp := range source.StopPosition {
if uidMap[sp.Id] {
errMsg = append(errMsg, fmt.Sprintf("uid[%s]重复", sp.Id))
continue
}
uidMap[sp.Id] = true
if sp.Km == nil || sp.Km.CoordinateSystem == "" {
errMsg = append(errMsg, fmt.Sprintf("停车点[%s]公里标数据错误", sp.Id))
}
}
return errMsg
}

View File

@ -3,13 +3,13 @@ package repository
import (
"errors"
"fmt"
"log/slog"
"math"
"strconv"
"strings"
"joylink.club/rtsssimulation/repository/model/proto"
"joylink.club/rtsssimulation/util/number"
"log/slog"
"math"
"sort"
"strconv"
"strings"
)
var repositoryMap = make(map[string]*Repository)
@ -55,6 +55,10 @@ func buildModels(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.KilometerConverts {
repository.addKilometerConvert(protoData)
}
err := buildKilometerCalibration(source, repository)
if err != nil {
return err
}
for _, protoData := range source.Stations {
m := NewStation(protoData.Id, protoData.Code)
_, ok := repository.stationMap[m.Id()]
@ -63,31 +67,53 @@ func buildModels(source *proto.Repository, repository *Repository) error {
}
repository.stationMap[m.Id()] = m
}
for _, protoData := range source.PhysicalSections {
m := NewPhysicalSection(protoData.Id)
repository.physicalSectionMap[m.Id()] = m
}
for _, protoData := range source.AxleCountingSections {
m := NewAxleCountingSection(protoData.Id, protoData.TurnoutAndPos)
repository.axleCountingSectionMap[m.Id()] = m
}
for _, protoData := range source.CheckPoints {
calibrationKilometer(protoData.Km, repository)
m := NewCheckPoint(protoData.Id, protoData.Km, protoData.Type)
repository.checkPointMap[m.Id()] = m
}
for _, protoData := range source.Turnouts {
calibrationKilometer(protoData.Km, repository)
m := NewTurnout(protoData.Id, protoData.Km, protoData.SwitchMachineType)
repository.turnoutMap[m.Id()] = m
}
for _, protoData := range source.Signals {
calibrationKilometer(protoData.Km, repository)
m := NewSignal(protoData.Id, protoData.Km, protoData.Code, protoData.Model)
repository.signalMap[m.Id()] = m
}
for _, protoData := range source.Transponders {
m := NewTransponder(protoData.Id, protoData.Km, protoData.FixedTelegram, protoData.FixedUserTelegram, protoData.Type)
calibrationKilometer(protoData.Km, repository)
m := NewTransponder(protoData.Id, protoData.Km, protoData.FixedTelegram, protoData.FixedUserTelegram,
protoData.Type, protoData.LeuIndex, protoData.IndexInLeu)
repository.responderMap[m.Id()] = m
}
for _, sp := range source.StopPosition {
calibrationKilometer(sp.Km, repository)
t := NewStopPosition(sp.Id, sp.Km, sp.CoachNum)
repository.StopPosition[t.Id()] = t
}
for _, protoData := range source.Slopes {
for _, km := range protoData.Kms {
calibrationKilometer(km, repository)
}
m := NewSlope(protoData.Id, protoData.Kms, protoData.Degree)
repository.slopeMap[m.Id()] = m
}
for _, protoData := range source.SectionalCurvatures {
for _, km := range protoData.Kms {
calibrationKilometer(km, repository)
}
m := NewSectionalCurvature(protoData.Id, protoData.Kms, protoData.Radius)
repository.sectionalCurvatureMap[m.Id()] = m
}
@ -96,7 +122,7 @@ func buildModels(source *proto.Repository, repository *Repository) error {
if !ok {
return fmt.Errorf("id=%s的继电器所属车站不存在,车站id=%s", protoData.Id, protoData.StationId)
}
m := newRelay(protoData.Id, protoData.Code, protoData.Model, s)
m := newRelay(protoData.Id, protoData.Code, protoData.Model, protoData.DefaultPos, s)
repository.relayMap[m.Id()] = m
}
for _, protoData := range source.PhaseFailureProtectors {
@ -123,15 +149,15 @@ func buildModels(source *proto.Repository, repository *Repository) error {
repository.alarmMap[m.Id()] = m
}
for _, protoData := range source.Mkxs {
m := NewMkx(protoData.Id)
repository.mkxMap[m.Id()] = m
m := NewPsdPsl(protoData.Id)
repository.psdPslMap[m.Id()] = m
}
for _, protoData := range source.Keys {
m := NewKey(protoData.Id, protoData.Code, protoData.Gear)
repository.keyMap[m.Id()] = m
}
for _, protoData := range source.Platforms {
m := NewPlatform(protoData.Id, protoData.Code)
m := NewPlatform(protoData.Id, protoData.Code, protoData.Direction)
repository.platformMap[m.Id()] = m
}
for _, protoData := range source.Ckms {
@ -139,18 +165,28 @@ func buildModels(source *proto.Repository, repository *Repository) error {
repository.ckmMap[m.Id()] = m
}
for _, protoData := range source.Xcjs {
m := NewXcj(protoData.Id)
m := NewXcj(protoData.Id, protoData.NumSegments)
repository.xcjMap[m.Id()] = m
}
err := repository.generateCoordinateInfo(source.MainCoordinateSystem)
for _, protoData := range source.CkmPsls {
m := NewCkmPsl(protoData.Id)
repository.ckmPslMap[m.Id()] = m
}
err = repository.generateCoordinateInfo(source.MainCoordinateSystem)
if err != nil {
return err
}
for _, protoData := range source.CentralizedStationRefs {
repository.centralizedMap[protoData.StationId] = protoData
}
//
for _, protoData := range source.Esbs {
repository.esbMap[protoData.Id] = &Esb{Identity: identity{id: protoData.Id, deviceType: proto.DeviceType_DeviceType_Esb}}
}
for _, protoData := range source.Spkss {
repository.spksMap[protoData.Id] = &Spks{Identity: identity{id: protoData.Id, deviceType: proto.DeviceType_DeviceType_Spks}}
}
err = buildIscsModels(source, repository)
//
return err
}
@ -164,6 +200,10 @@ func buildModelRelationship(source *proto.Repository, repository *Repository) er
if err != nil {
return err
}
err = buildAxleCountingSectionRelationShip(source, repository)
if err != nil {
return err
}
err = buildTurnoutRelationShip(source, repository)
if err != nil {
return err
@ -208,9 +248,167 @@ func buildModelRelationship(source *proto.Repository, repository *Repository) er
if err != nil {
return err
}
err = buildCkmPslRelationShip(source, repository)
if err != nil {
return err
}
err = buildEsbRelationship(source, repository)
if err != nil {
return err
}
err = buildSpksRelationship(source, repository)
buildStopPositionRelationShip(source, repository)
return err
}
func calibrationKilometer(km *proto.Kilometer, repository *Repository) {
params := repository.kilometerCalibrationMap[km.CoordinateSystem+km.Direction.String()]
for _, param := range params {
if param.Design.Value <= km.Value {
km.Value += param.Actual.Value - param.Design.Value
break
}
}
}
func buildKilometerCalibration(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.KilometerCalibrations {
key := protoData.Design.CoordinateSystem + protoData.Design.Direction.String()
repository.kilometerCalibrationMap[key] = append(repository.kilometerCalibrationMap[key], protoData)
}
for _, calibrations := range repository.kilometerCalibrationMap {
sort.Slice(calibrations, func(i, j int) bool {
return calibrations[i].Design.Value > calibrations[j].Design.Value
})
}
return nil
}
func buildAxleCountingSectionRelationShip(source *proto.Repository, repository *Repository) error {
turnout_physicalSection_map := make(map[string]*PhysicalSection)
for _, physicalSection := range repository.physicalSectionMap {
for _, turnout := range physicalSection.turnouts {
turnout_physicalSection_map[turnout.Id()] = physicalSection
}
}
for _, protoData := range source.AxleCountingSections {
axleCountingSection := repository.axleCountingSectionMap[protoData.Id]
if len(protoData.TurnoutAndPos) != 0 {
axleCountingSection.physicalSection = turnout_physicalSection_map[protoData.TurnoutAndPos[0].TurnoutId]
} else {
commonPhysicalSectionMap := make(map[*PhysicalSection]int)
for _, axleCountingId := range protoData.AxleCountingIds {
for _, dp := range repository.checkPointMap[axleCountingId].devicePorts {
physicalSection, ok := dp.Device().(*PhysicalSection)
if ok {
commonPhysicalSectionMap[physicalSection]++
}
}
}
for physicalSection, i := range commonPhysicalSectionMap {
if i > 1 {
axleCountingSection.physicalSection = physicalSection
break
}
}
if axleCountingSection.physicalSection == nil { //轨道尽头的区段
for section, _ := range commonPhysicalSectionMap {
if len(section.checkPoints) == 1 {
axleCountingSection.physicalSection = section
break
}
}
}
}
if axleCountingSection.physicalSection == nil {
return fmt.Errorf("计轴区段[%s]找不到对应的物理区段", protoData.Id)
}
}
return nil
}
func buildSpksRelationship(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.Spkss {
platform := repository.platformMap[protoData.PlatformId]
var num byte
if len(protoData.Code) > 4 { //暂时默认Code为SPKS+数字SPKS1、SPKS3等
num = protoData.Code[4] //这一位应该是数字
}
var plajCode string
var relayCode string
switch platform.dir {
case proto.Platform_Up:
plajCode = "SPKSSPLAJ"
relayCode = fmt.Sprintf("SPKSS%cJ", num)
case proto.Platform_Down:
plajCode = "SPKSXPLAJ"
relayCode = fmt.Sprintf("SPKSX%cJ", num)
default:
panic(fmt.Sprintf("未知的站台方向:%s", platform.dir))
}
spks := repository.spksMap[protoData.Id]
station := platform.station
for _, component := range station.spksComponents {
if component.Code() == plajCode && component.Type() == proto.DeviceType_DeviceType_Relay {
spks.plaId = component.Id()
}
if component.Code() == relayCode && component.Type() == proto.DeviceType_DeviceType_Relay {
spks.relayId = component.Id()
}
}
if spks.plaId == "" || spks.relayId == "" {
return fmt.Errorf("SPKS[%s]未找到对应的旁路继电器或状态继电器", protoData.Id)
}
}
return nil
}
func buildEsbRelationship(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.Esbs {
platform := repository.platformMap[protoData.PlatformId]
var plaCode string
var relayCode string
switch platform.dir {
case proto.Platform_Up:
plaCode = "SEMPFA"
relayCode = "SEMPJ"
case proto.Platform_Down:
plaCode = "XEMPFA"
relayCode = "XEMPJ"
default:
panic(fmt.Sprintf("站台[%s]的方向[%s]不正确", platform.Id(), platform.dir))
}
esb := repository.esbMap[protoData.Id]
station := platform.station
for _, group := range station.empGroups {
for _, component := range group.components {
if component.Code() == plaCode && component.Type() == proto.DeviceType_DeviceType_Button {
esb.plaId = component.Id()
}
if component.Code() == relayCode && component.Type() == proto.DeviceType_DeviceType_Relay {
esb.relayId = component.Id()
}
}
}
if esb.plaId == "" || esb.relayId == "" {
return fmt.Errorf("ESB[%s]未找到对应的旁路按钮或继电器", protoData.Id)
}
}
return nil
}
func buildCkmPslRelationShip(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.CkmPsls {
psl := repository.ckmPslMap[protoData.Id]
psl.ckm = repository.ckmMap[protoData.CkmId]
psl.gma = repository.buttonMap[protoData.GmaId]
psl.kma = repository.buttonMap[protoData.KmaId]
psl.mpla = repository.buttonMap[protoData.MplaId]
psl.mmsa = repository.buttonMap[protoData.MmsaId]
}
return nil
}
func buildXcjRelationShip(source *proto.Repository, repo *Repository) error {
for _, protoData := range source.Ckms {
ckm := repo.ckmMap[protoData.Id]
@ -257,6 +455,18 @@ func buildPlatformRelationShip(source *proto.Repository, repo *Repository) error
return fmt.Errorf("站台[id:%s]关联的车站[id:%s]不存在", platform.Id(), protoData.StationId)
}
platform.station = station
for _, group := range protoData.ElectronicComponentGroups {
var components []IGroupedElectronicComponent
for _, id := range group.GetComponentIds() {
if relay := repo.relayMap[id]; relay != nil {
components = append(components, relay)
}
}
platform.componentGroups = append(platform.componentGroups, &ElectronicComponentGroup{
code: group.Code,
components: components,
})
}
}
return nil
}
@ -270,7 +480,7 @@ func buildCentralizedStationRelationShip(source *proto.Repository, repo *Reposit
}
func buildMkxRelationShip(source *proto.Repository, repo *Repository) error {
for _, protoData := range source.Mkxs {
mkx := repo.mkxMap[protoData.Id]
mkx := repo.psdPslMap[protoData.Id]
mkx.psd = repo.psdMap[protoData.PsdId]
mkx.pcb = repo.buttonMap[protoData.PcbaId]
mkx.pcbpl = repo.buttonMap[protoData.PcbplaId]
@ -423,7 +633,15 @@ func buildResponderRelationShip(source *proto.Repository, repository *Repository
}
return nil
}
func buildStopPositionRelationShip(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.StopPosition {
responder := repository.StopPosition[protoData.Id]
if protoData.SectionId != "" {
repository.physicalSectionMap[protoData.SectionId].bindDevices(responder)
}
}
return nil
}
func buildSignalRelationShip(source *proto.Repository, repository *Repository) error {
for _, protoData := range source.Signals {
signal := repository.signalMap[protoData.Id]
@ -509,26 +727,26 @@ func buildTurnoutPortRelation(repo *Repository, turnout *Turnout, port proto.Por
return err
}
func buildPhysicalSectionRelationShip(source *proto.Repository, repository *Repository) error {
func buildPhysicalSectionRelationShip(source *proto.Repository, repo *Repository) error {
for _, protoData := range source.PhysicalSections {
section := repository.physicalSectionMap[protoData.Id]
section := repo.physicalSectionMap[protoData.Id]
//A端关联
if protoData.ADevicePort != nil {
err := buildSectionPortRelation(repository, section, proto.Port_A, protoData.ADevicePort)
err := buildSectionPortRelation(repo, section, proto.Port_A, protoData.ADevicePort)
if err != nil {
return err
}
}
//B端关联
if protoData.BDevicePort != nil {
err := buildSectionPortRelation(repository, section, proto.Port_B, protoData.BDevicePort)
err := buildSectionPortRelation(repo, section, proto.Port_B, protoData.BDevicePort)
if err != nil {
return err
}
}
//道岔关联
for _, turnoutId := range protoData.TurnoutIds {
turnout := repository.turnoutMap[turnoutId]
turnout := repo.turnoutMap[turnoutId]
if turnout == nil {
return fmt.Errorf("id[%s]的道岔不存在", turnoutId)
}
@ -536,7 +754,24 @@ func buildPhysicalSectionRelationShip(source *proto.Repository, repository *Repo
turnout.section = section
}
//关联联锁集中站
section.centralizedStation = protoData.CentralizedStation
for _, stationId := range protoData.CentralizedStation {
section.centralizedStation = append(section.centralizedStation, repo.stationMap[stationId])
}
//关联电子元件
for _, group := range protoData.ElectronicComponentGroups {
var components []IGroupedElectronicComponent
for _, id := range group.GetComponentIds() {
if relay := repo.relayMap[id]; relay != nil {
components = append(components, relay)
} else if pfp := repo.phaseFailureProtectorMap[id]; pfp != nil {
components = append(components, pfp)
}
}
section.componentGroups = append(section.componentGroups, &ElectronicComponentGroup{
code: group.Code,
components: components,
})
}
}
return nil
}
@ -643,6 +878,18 @@ func buildLinksAndRelate(repo *Repository) error {
return nil
}
/*func stopPositionRelateLink(repo *Repository) {
for _, curvature := range repo {
start, end, err := calculateLinkSegment(repo, curvature.kms[0], curvature.kms[1])
if err != nil {
return err
}
curvature.bindStartLinkPosition(start)
curvature.bindEndLinkPosition(end)
}
return nil
}*/
func buildLinks(repo *Repository) error {
visitedTurnoutPortMap := make(map[string]bool)
allTurnouts := repo.TurnoutList()
@ -698,6 +945,7 @@ func findEndTurnoutPortOrEndKm(repo *Repository, link *Link, startTp *TurnoutPor
var currentDp DevicePort = startTp
devices := startTp.turnout.findDevicesByPort(startTp.port)
for {
//遍历设备并构建、关联其在Link上的位置
err = relateDevicesAndLink(repo, link, baseKm, visitedModelMap, devices...)
if err != nil {
@ -719,7 +967,10 @@ func findEndTurnoutPortOrEndKm(repo *Repository, link *Link, startTp *TurnoutPor
if nextDp == nil {
endKm = turnout.findBoundaryKmByPort(currentDp.Port())
}
//case proto.DeviceType_deviceType_Stop_position:
// turnout := currentDp.Device().(*StopPosition)
}
//根据下一个端口设备的信息决定是否结束循环
if nextDp == nil {
break
@ -788,9 +1039,14 @@ func buildTurnoutPortKey(tp *TurnoutPort) string {
func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer, visitedModelMap map[string]bool, devices ...Identity) error {
for _, device := range devices {
if visitedModelMap[device.Id()] {
continue
}
linkPositionDevice, ok := device.(LinkPositionDevice)
if !ok {
return fmt.Errorf("device [%s:%s] not implements LinkPositionDevice", device.Id(), device.Type().String())
}
km := findModelKm(device)
if km == nil || km.CoordinateSystem == "" {
continue
@ -800,19 +1056,12 @@ func relateDevicesAndLink(repo *Repository, link *Link, startKm *proto.Kilometer
return err
}
offset := int64(math.Abs(float64(convertedKm.Value - startKm.Value)))
linkPosition := &LinkPosition{
linkPosition := LinkPosition{
link: link,
offset: offset,
}
switch device.Type() {
case proto.DeviceType_DeviceType_CheckPoint:
device.(*CheckPoint).bindLinkPosition(linkPosition)
case proto.DeviceType_DeviceType_Signal:
device.(*Signal).bindLinkPosition(linkPosition)
case proto.DeviceType_DeviceType_Transponder:
device.(*Transponder).bindLinkPosition(linkPosition)
}
link.bindDevices(device)
linkPositionDevice.bindLinkPosition(linkPosition)
link.bindDevices(linkPositionDevice)
}
return nil
}
@ -862,7 +1111,10 @@ func findModelKm(model Identity) *proto.Kilometer {
return model.(*CheckPoint).km
case proto.DeviceType_DeviceType_Turnout:
return model.(*Turnout).km
case proto.DeviceType_deviceType_Stop_position:
return model.(*StopPosition).km
}
return nil
}

View File

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

16
repository/spks.go Normal file
View File

@ -0,0 +1,16 @@
package repository
// Spks 人员防护系统。目前内部属性仅作为和第三方联锁通信时获取SPKS系统状态的便捷途径
type Spks struct {
Identity
plaId string //SPKS旁路按钮ID
relayId string //SPKS继电器ID
}
func (s *Spks) PlaId() string {
return s.plaId
}
func (s *Spks) Relay() string {
return s.relayId
}

View File

@ -0,0 +1,29 @@
package repository
import (
"joylink.club/rtsssimulation/repository/model/proto"
)
type StopPosition struct {
Identity
dir proto.Platform_Direction
km *proto.Kilometer
linkPosition LinkPosition
coachNum uint32
}
func NewStopPosition(id string, km *proto.Kilometer, coachNum uint32) *StopPosition {
return &StopPosition{
Identity: identity{id, proto.DeviceType_deviceType_Stop_position},
km: km, coachNum: coachNum,
}
}
func (t *StopPosition) bindLinkPosition(position LinkPosition) {
t.linkPosition = position
}
func (t *StopPosition) LinkPosition() LinkPosition {
return t.linkPosition
}
func (t *StopPosition) CoachNum() int32 {
return int32(t.coachNum)
}

View File

@ -1,6 +1,8 @@
package repository
import "joylink.club/rtsssimulation/repository/model/proto"
import (
"joylink.club/rtsssimulation/repository/model/proto"
)
type Transponder struct {
Identity
@ -8,21 +10,27 @@ type Transponder struct {
km *proto.Kilometer
//section *PhysicalSection
//turnoutPort TurnoutPort
linkPosition *LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取
linkPosition LinkPosition //此位置是应答器初始位置,当前位置需从应答器实体中获取
fixedTelegram []byte //应答器固定报文
fixedUserTelegram []byte //应答器固定用户报文
baliseType proto.Transponder_Type //应答器类型
leuIndex uint32 //应答器所属LEU的索引
indexInLeu uint32 //应答器在LEU内的索引
}
func NewTransponder(id string, km *proto.Kilometer, fixedTelegram []byte, fixedUserTelegram []byte, baliseType proto.Transponder_Type) *Transponder {
func NewTransponder(id string, km *proto.Kilometer, fixedTelegram []byte, fixedUserTelegram []byte,
baliseType proto.Transponder_Type, leuIndex uint32, indexInLeu uint32) *Transponder {
return &Transponder{
Identity: identity{id, proto.DeviceType_DeviceType_Transponder},
km: km,
fixedTelegram: fixedTelegram,
fixedUserTelegram: fixedUserTelegram,
baliseType: baliseType,
leuIndex: leuIndex,
indexInLeu: indexInLeu,
}
}
func (t *Transponder) TransponderType() proto.Transponder_Type {
return t.baliseType
}
@ -32,11 +40,10 @@ func (t *Transponder) FixedTelegram() []byte {
func (t *Transponder) FixedUserTelegram() []byte {
return t.fixedUserTelegram
}
func (t *Transponder) bindLinkPosition(position *LinkPosition) {
func (t *Transponder) bindLinkPosition(position LinkPosition) {
t.linkPosition = position
}
func (t *Transponder) LinkPosition() *LinkPosition {
func (t *Transponder) LinkPosition() LinkPosition {
return t.linkPosition
}
@ -47,3 +54,11 @@ func (t *Transponder) Km() *proto.Kilometer {
func (t *Transponder) BaliseType() proto.Transponder_Type {
return t.baliseType
}
func (t *Transponder) LeuIndex() uint32 {
return t.leuIndex
}
func (t *Transponder) IndexInLeu() uint32 {
return t.indexInLeu
}

View File

@ -44,6 +44,10 @@ type Turnout struct {
componentGroups []*ElectronicComponentGroup
}
func (t *Turnout) Km() *proto.Kilometer {
return t.km
}
func NewTurnout(id string, km *proto.Kilometer, switchMachineType proto.Turnout_SwitchMachineType) *Turnout {
return &Turnout{
Identity: identity{id, proto.DeviceType_DeviceType_Turnout},

View File

@ -5,11 +5,13 @@ import "joylink.club/rtsssimulation/repository/model/proto"
type Xcj struct {
Identity
componentGroups []*ElectronicComponentGroup
NumSegments uint32
}
func NewXcj(id string) *Xcj {
func NewXcj(id string, numSegments uint32) *Xcj {
return &Xcj{
Identity: identity{id: id, deviceType: proto.DeviceType_DeviceType_Xcj},
Identity: identity{id: id, deviceType: proto.DeviceType_DeviceType_Xcj},
NumSegments: numSegments,
}
}

View File

@ -30,6 +30,7 @@ func BindSystem(w ecs.World) {
circuit_sys.NewSignalJDXHSystem(),
circuit_sys.NewCkmSys(),
circuit_sys.NewXcjSys(),
circuit_sys.NewTrackCircuitSys(),
device_sys.NewLightSys(),
//屏蔽门
circuit_sys.NewPsdSys(),
@ -38,8 +39,9 @@ func BindSystem(w ecs.World) {
circuit_sys.NewIBPSys(),
device_sys.NewAlarmSys(),
//物理区段
device_sys.NewFaDcAxleDeviceSystem(),
device_sys.NewSectionDetectSystem(),
device_sys.NewPhysicalSectionSystem(),
//计轴区段
device_sys.NewAxleCountingSectionSystem(),
//应答器
device_sys.NewBaliseSystem(),
//电机

View File

@ -15,31 +15,40 @@ type CkmSys struct {
func NewCkmSys() *CkmSys {
return &CkmSys{
query: ecs.NewQuery(filter.Contains(entity.PsdBaseComponentTypeArr...)),
query: ecs.NewQuery(filter.Contains(entity.CkmBaseComponentTypes...)),
}
}
func (p *CkmSys) Update(world ecs.World) {
worldData := entity.GetWorldData(world)
p.query.Each(world, func(entry *ecs.Entry) {
if !entry.HasComponent(component.CkmCircuitType) {
return
}
posCom := component.FixedPositionTransformType.Get(entry)
state := component.CkmStateType.Get(entry)
if entry.HasComponent(component.CkmCircuitType) {
circuit := component.CkmCircuitType.Get(entry)
//门开/关继电器及状态
if posCom.Pos == consts.TwoPosMin {
component.RelayDriveType.Get(circuit.MGJ).Td = true
component.RelayDriveType.Get(circuit.MKJ).Td = false
state.Close = true
} else {
component.RelayDriveType.Get(circuit.MGJ).Td = false
component.RelayDriveType.Get(circuit.MKJ).Td = true
state.Close = false
}
//门故障继电器及状态
component.RelayDriveType.Get(circuit.MGZJ).Td = entry.HasComponent(component.CkmMgzTag)
state.Mgz = entry.HasComponent(component.CkmMgzTag)
//开/关门继电器驱动状态
circuit := component.CkmCircuitType.Get(entry) //目前不考虑没有车库门电路的情况
//车库门PSL
if entry.HasComponent(component.CkmPslType) {
ckmPsl := component.CkmPslType.Get(entry)
component.RelayDriveType.Get(circuit.MPLJ).Td = component.BitStateType.Get(ckmPsl.MPLA).Val //门旁路
component.RelayDriveType.Get(circuit.MMSJ).Td = component.BitStateType.Get(ckmPsl.MMSA).Val //门模式
}
//门开/关继电器及状态
if posCom.Pos == consts.TwoPosMin {
component.RelayDriveType.Get(circuit.MGJ).Td = true
component.RelayDriveType.Get(circuit.MKJ).Td = false
} else {
component.RelayDriveType.Get(circuit.MGJ).Td = false
component.RelayDriveType.Get(circuit.MKJ).Td = true
}
////门故障继电器及状态
//component.RelayDriveType.Get(circuit.MGZJ).Td =
//开/关门继电器驱动状态
if component.BitStateType.Get(circuit.MMSJ).Val {
ckmPsl := component.CkmPslType.Get(entry)
component.RelayDriveType.Get(circuit.KMJ).Td = component.BitStateType.Get(ckmPsl.KMA).Val
component.RelayDriveType.Get(circuit.GMJ).Td = component.BitStateType.Get(ckmPsl.GMA).Val
} else {
kmBit, err := worldData.QueryQdBit(component.UidType.Get(circuit.KMJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.KMJ).Td = kmBit
@ -52,21 +61,21 @@ func (p *CkmSys) Update(world ecs.World) {
} else {
slog.Error(err.Error())
}
state.Km = component.BitStateType.Get(circuit.KMJ).Val
state.Gm = component.BitStateType.Get(circuit.GMJ).Val
} else {
if posCom.Pos == consts.TwoPosMin {
state.Close = true
} else {
state.Close = false
}
state.Mgz = entry.HasComponent(component.CkmMgzTag)
}
//强制开门
if entry.HasComponent(component.CkmForceOpenTag) {
posCom.Pos = consts.TwoPosMax
posCom.Speed = 0
return
} else if entry.HasComponent(component.CkmForceCloseTag) {
posCom.Pos = consts.TwoPosMin
posCom.Speed = 0
return
}
//驱动
if state.Gm {
if component.BitStateType.Get(circuit.GMJ).Val {
posCom.Speed = -component.CalculateTwoPositionAvgSpeed(3*1000, world.Tick())
} else if state.Km {
} else if component.BitStateType.Get(circuit.KMJ).Val {
posCom.Speed = component.CalculateTwoPositionAvgSpeed(3*1000, world.Tick())
}
})

View File

@ -35,6 +35,11 @@ func (p *PsdSys) Update(world ecs.World) {
}
asdList := component.AsdListType.Get(entry)
psdState := component.PsdStateType.Get(entry)
//更新站台门控箱继电器状态
if mkx != nil {
pmc := component.PlatformMkxCircuitType.Get(entry)
mkxBtnDriveRelay(mkx, pmc, psdCircuit)
}
//更新屏蔽门电路及PSC相关状态
if psdCircuit != nil { //有屏蔽门电路
//屏蔽门关门
@ -62,14 +67,17 @@ func (p *PsdSys) Update(world ecs.World) {
p.exciteZAWJ(psdCircuit, asdList)
psdState.Obstacle = component.BitStateType.Get(psdCircuit.ZAWJ).Val
}
//互锁解除
if psdCircuit.MPLJ != nil {
psdState.InterlockRelease = component.BitStateType.Get(psdCircuit.MPLJ).Val
}
} else {
psdState.Close = p.isAllAsdMotorClosed(asdList)
if mkx != nil {
psdState.InterlockRelease = component.BitStateType.Get(mkx.MPL).Val
}
}
//更新站台门控箱继电器状态
if mkx != nil {
pmc := component.PlatformMkxCircuitType.Get(entry)
mkxBtnDriveRelay(mkx, pmc, psdCircuit)
}
//设置滑动门电机通断电状态
repo := entity.GetWorldData(world).Repo
psd := repo.FindPsd(component.UidType.Get(entry).Id)
@ -175,18 +183,24 @@ func (p *PsdSys) driveGMJ(data *component.WorldData, circuit *component.PsdCircu
if err != nil {
return
}
if bit { //驱动
component.RelayDriveType.Get(circuit.GMJ).Td = true
} else if component.BitStateType.Get(circuit.GMJ).Val { //判断自保持
for _, entry := range circuit.KMJMap {
if component.BitStateType.Get(entry).Val { //无法自保持
component.RelayDriveType.Get(circuit.GMJ).Td = false
return
}
}
//自保持
component.RelayDriveType.Get(circuit.GMJ).Td = true
}
component.RelayDriveType.Get(circuit.GMJ).Td = bit
//bit, err := data.QueryQdBit(component.UidType.Get(circuit.GMJ).Id)
//if err != nil {
// return
//}
//if bit { //驱动
// component.RelayDriveType.Get(circuit.GMJ).Td = true
//} else if component.BitStateType.Get(circuit.GMJ).Val { //判断自保持
// for _, entry := range circuit.KMJMap {
// if component.BitStateType.Get(entry).Val { //无法自保持
// component.RelayDriveType.Get(circuit.GMJ).Td = false
// return
// }
// }
// //自保持
// component.RelayDriveType.Get(circuit.GMJ).Td = true
//}
}
func (p *PsdSys) driveKMJ(data *component.WorldData, circuit *component.PsdCircuit, kmj *ecs.Entry) {
@ -194,22 +208,28 @@ func (p *PsdSys) driveKMJ(data *component.WorldData, circuit *component.PsdCircu
if err != nil {
return
}
if bit { //驱动
component.RelayDriveType.Get(kmj).Td = true
} else if component.BitStateType.Get(kmj).Val { //判断自保持
if component.BitStateType.Get(circuit.GMJ).Val {
component.RelayDriveType.Get(kmj).Td = false
return
}
for _, entry := range circuit.KMJMap {
if entry != kmj && component.BitStateType.Get(entry).Val {
component.RelayDriveType.Get(kmj).Td = false
return
}
}
//自保持
component.RelayDriveType.Get(kmj).Td = true
}
component.RelayDriveType.Get(kmj).Td = bit
//bit, err := data.QueryQdBit(component.UidType.Get(kmj).Id)
//if err != nil {
// return
//}
//if bit { //驱动
// component.RelayDriveType.Get(kmj).Td = true
//} else if component.BitStateType.Get(kmj).Val { //判断自保持
// if component.BitStateType.Get(circuit.GMJ).Val {
// component.RelayDriveType.Get(kmj).Td = false
// return
// }
// for _, entry := range circuit.KMJMap {
// if entry != kmj && component.BitStateType.Get(entry).Val {
// component.RelayDriveType.Get(kmj).Td = false
// return
// }
// }
// //自保持
// component.RelayDriveType.Get(kmj).Td = true
//}
}
func (p *PsdSys) driveMGJ(psdCircuit *component.PsdCircuit, asdList *component.AsdList) {

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type Signal2XH1System struct {
@ -20,21 +21,35 @@ func NewSignal2XH1System() *Signal2XH1System {
// Update world 执行
func (s *Signal2XH1System) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.Signal2XH1ElectronicType.Get(entry)
lsq := component.Signal2XH1LsqType.Get(entry)
lsc := component.Signal2XH1LscType.Get(entry)
circuit := component.Signal2XH1ElectronicType.Get(entry)
excite2xh1ByCiDrive(circuit, wd)
//lsq := component.Signal2XH1LsqType.Get(entry)
//lsc := component.Signal2XH1LscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
Z2XH1_L := lights.GetLightByTag(component.LdTag)
Z2XH1_H := lights.GetLightByTag(component.HdTag)
s.calculateLsq(state, lsq)
s.calculateL(state, Z2XH1_L)
s.calculateH(state, Z2XH1_H)
s.calculateDJ(state, Z2XH1_L, Z2XH1_H)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateL(circuit, Z2XH1_L)
s.calculateH(circuit, Z2XH1_H)
s.calculateDJ(circuit, Z2XH1_L, Z2XH1_H)
//s.calculateLsc(circuit, lsc)
})
}
func excite2xh1ByCiDrive(circuit *component.Signal2XH1Electronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.Z2XH1_DDJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z2XH1_DDJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z2XH1_LXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z2XH1_LXJ).Td = bit
}
}
// 联锁驱
func (s *Signal2XH1System) calculateLsq(state *component.Signal2XH1Electronic, lsq *component.Signal2XH1Lsq) {
ddj := component.RelayDriveType.Get(state.Z2XH1_DDJ)

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type Signal3XH1System struct {
@ -20,25 +21,49 @@ func NewSignal3XH1System() *Signal3XH1System {
// Update world 执行
func (s *Signal3XH1System) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.Signal3XH1ElectronicType.Get(entry)
lsq := component.Signal3XH1LsqType.Get(entry)
lsc := component.Signal3XH1LscType.Get(entry)
circuit := component.Signal3XH1ElectronicType.Get(entry)
excite3xh1ByCiDrive(circuit, wd)
//lsq := component.Signal3XH1LsqType.Get(entry)
//lsc := component.Signal3XH1LscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
Z3XH1_L := lights.GetLightByTag(component.LdTag)
Z3XH1_H := lights.GetLightByTag(component.HdTag)
Z3XH1_U := lights.GetLightByTag(component.UdTag)
//
s.calculateLsq(state, lsq)
s.calculateU(state, Z3XH1_U)
s.calculateL(state, Z3XH1_L)
s.calculateH(state, Z3XH1_H)
s.calculateDJ(state, Z3XH1_H, Z3XH1_L, Z3XH1_U)
s.calculate2DJ(state, Z3XH1_U)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateU(circuit, Z3XH1_U)
s.calculateL(circuit, Z3XH1_L)
s.calculateH(circuit, Z3XH1_H)
s.calculateDJ(circuit, Z3XH1_H, Z3XH1_L, Z3XH1_U)
s.calculate2DJ(circuit, Z3XH1_U)
//s.calculateLsc(circuit, lsc)
})
}
func excite3xh1ByCiDrive(circuit *component.Signal3XH1Electronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.Z3XH1_DDJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH1_DDJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH1_LXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH1_LXJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH1_ZXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH1_ZXJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH1_YXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH1_YXJ).Td = bit
}
}
// 联锁驱
func (s *Signal3XH1System) calculateLsq(state *component.Signal3XH1Electronic, lsq *component.Signal3XH1Lsq) {
ddj := component.RelayDriveType.Get(state.Z3XH1_DDJ)

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type Signal3XH2System struct {
@ -20,24 +21,44 @@ func NewSignal3XH2System() *Signal3XH2System {
// Update world 执行
func (s *Signal3XH2System) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.Signal3XH2ElectronicType.Get(entry)
lsq := component.Signal3XH2LsqType.Get(entry)
lsc := component.Signal3XH2LscType.Get(entry)
circuit := component.Signal3XH2ElectronicType.Get(entry)
excite3xh2ByCiDrive(circuit, wd)
//lsq := component.Signal3XH2LsqType.Get(entry)
//lsc := component.Signal3XH2LscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
Z3XH2_L := lights.GetLightByTag(component.LdTag)
Z3XH2_H := lights.GetLightByTag(component.HdTag)
Z3XH2_U := lights.GetLightByTag(component.UdTag)
s.calculateLsq(state, lsq)
s.calculateU(state, Z3XH2_U)
s.calculateL(state, Z3XH2_L)
s.calculateH(state, Z3XH2_H)
s.calculateDJ(state, Z3XH2_L, Z3XH2_H)
s.calculate2DJ(state, Z3XH2_U)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateU(circuit, Z3XH2_U)
s.calculateL(circuit, Z3XH2_L)
s.calculateH(circuit, Z3XH2_H)
s.calculateDJ(circuit, Z3XH2_L, Z3XH2_H)
s.calculate2DJ(circuit, Z3XH2_U)
//s.calculateLsc(circuit, lsc)
})
}
// 根据联锁驱动给继电器励磁
func excite3xh2ByCiDrive(circuit *component.Signal3XH2Electronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.Z3XH2_DDJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH2_DDJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH2_LXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH2_LXJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH2_YXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH2_YXJ).Td = bit
}
}
// 联锁驱
func (s *Signal3XH2System) calculateLsq(state *component.Signal3XH2Electronic, lsq *component.Signal3XH2Lsq) {
ddj := component.RelayDriveType.Get(state.Z3XH2_DDJ)

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type Signal3XH3System struct {
@ -20,23 +21,42 @@ func NewSignal3XH3System() *Signal3XH3System {
// Update world 执行
func (s *Signal3XH3System) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.Signal3XH3ElectronicType.Get(entry)
lsq := component.Signal3XH3LsqType.Get(entry)
lsc := component.Signal3XH3LscType.Get(entry)
circuit := component.Signal3XH3ElectronicType.Get(entry)
excite3xh3ByCiDrive(circuit, wd)
//lsq := component.Signal3XH3LsqType.Get(entry)
//lsc := component.Signal3XH3LscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
Z3XH3_H := lights.GetLightByTag(component.HdTag)
Z3XH3_U := lights.GetLightByTag(component.UdTag)
//
s.calculateLsq(state, lsq)
s.calculateU(state, Z3XH3_U)
s.calculateH(state, Z3XH3_H)
s.calculateDJ(state, Z3XH3_U, Z3XH3_H)
s.calculate2DJ(state, Z3XH3_U)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateU(circuit, Z3XH3_U)
s.calculateH(circuit, Z3XH3_H)
s.calculateDJ(circuit, Z3XH3_U, Z3XH3_H)
s.calculate2DJ(circuit, Z3XH3_U)
//s.calculateLsc(circuit, lsc)
})
}
func excite3xh3ByCiDrive(circuit *component.Signal3XH3Electronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.Z3XH3_DDJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH3_DDJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH3_LXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH3_LXJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH3_YXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH3_YXJ).Td = bit
}
}
// 联锁驱
func (s *Signal3XH3System) calculateLsq(state *component.Signal3XH3Electronic, lsq *component.Signal3XH3Lsq) {
ddj := component.RelayDriveType.Get(state.Z3XH3_DDJ)

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type Signal3XH4System struct {
@ -20,24 +21,43 @@ func NewSignal3XH4System() *Signal3XH4System {
// Update world 执行
func (s *Signal3XH4System) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.Signal3XH4ElectronicType.Get(entry)
lsq := component.Signal3XH4LsqType.Get(entry)
lsc := component.Signal3XH4LscType.Get(entry)
circuit := component.Signal3XH4ElectronicType.Get(entry)
excite3xh4ByCiDrive(circuit, wd)
//lsq := component.Signal3XH4LsqType.Get(entry)
//lsc := component.Signal3XH4LscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
Z3XH4_H := lights.GetLightByTag(component.HdTag)
Z3XH4_L := lights.GetLightByTag(component.LdTag)
Z3XH4_U := lights.GetLightByTag(component.UdTag)
//
s.calculateLsq(state, lsq)
s.calculateU(state, Z3XH4_U)
s.calculateL(state, Z3XH4_L)
s.calculateH(state, Z3XH4_H)
s.calculateDJ(state, Z3XH4_H, Z3XH4_L, Z3XH4_U)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateU(circuit, Z3XH4_U)
s.calculateL(circuit, Z3XH4_L)
s.calculateH(circuit, Z3XH4_H)
s.calculateDJ(circuit, Z3XH4_H, Z3XH4_L, Z3XH4_U)
//s.calculateLsc(circuit, lsc)
})
}
func excite3xh4ByCiDrive(circuit *component.Signal3XH4Electronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.Z3XH4_DDJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH4_DDJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH4_LXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH4_LXJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.Z3XH4_ZXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.Z3XH4_ZXJ).Td = bit
}
}
// 联锁驱
func (s *Signal3XH4System) calculateLsq(state *component.Signal3XH4Electronic, lsq *component.Signal3XH4Lsq) {
ddj := component.RelayDriveType.Get(state.Z3XH4_DDJ)

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type SignalDCXHSystem struct {
@ -20,23 +21,32 @@ func NewSignalDCXHSystem() *SignalDCXHSystem {
// Update world 执行
func (s *SignalDCXHSystem) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.SignalDCXHElectronicType.Get(entry)
lsq := component.SignalDCXHLsqType.Get(entry)
lsc := component.SignalDCXHLscType.Get(entry)
circuit := component.SignalDCXHElectronicType.Get(entry)
exciteDcxhByCiDrive(circuit, wd)
//lsq := component.SignalDCXHLsqType.Get(entry)
//lsc := component.SignalDCXHLscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
DCXH_A := lights.GetLightByTag(component.AdTag)
DCXH_B := lights.GetLightByTag(component.BdTag)
//
s.calculateLsq(state, lsq)
s.calculateA(state, DCXH_A)
s.calculateB(state, DCXH_B)
s.calculateDJ(state, DCXH_B, DCXH_A)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateA(circuit, DCXH_A)
s.calculateB(circuit, DCXH_B)
s.calculateDJ(circuit, DCXH_B, DCXH_A)
//s.calculateLsc(circuit, lsc)
})
}
func exciteDcxhByCiDrive(circuit *component.SignalDCXHElectronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.DCXH_DXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.DCXH_DXJ).Td = bit
}
}
// 联锁驱
func (s *SignalDCXHSystem) calculateLsq(state *component.SignalDCXHElectronic, lsq *component.SignalDCXHLsq) {
dxj := component.RelayDriveType.Get(state.DCXH_DXJ)

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type SignalJCKXHSystem struct {
@ -20,24 +21,38 @@ func NewSignalJCKXHSystem() *SignalJCKXHSystem {
// Update world 执行
func (s *SignalJCKXHSystem) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.SignalJCKXHElectronicType.Get(entry)
lsq := component.SignalJCKXHLsqType.Get(entry)
lsc := component.SignalJCKXHLscType.Get(entry)
circuit := component.SignalJCKXHElectronicType.Get(entry)
exciteJckxhByCiDrive(circuit, wd)
//lsq := component.SignalJCKXHLsqType.Get(entry)
//lsc := component.SignalJCKXHLscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
JCKXH_H := lights.GetLightByTag(component.HdTag)
JCKXH_B := lights.GetLightByTag(component.BdTag)
JCKXH_U := lights.GetLightByTag(component.UdTag)
//
s.calculateLsq(state, lsq)
s.calculateU(state, JCKXH_U)
s.calculateB(state, JCKXH_B)
s.calculateH(state, JCKXH_H)
s.calculateDJ(state, JCKXH_H, JCKXH_B, JCKXH_U)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateU(circuit, JCKXH_U)
s.calculateB(circuit, JCKXH_B)
s.calculateH(circuit, JCKXH_H)
s.calculateDJ(circuit, JCKXH_H, JCKXH_B, JCKXH_U)
//s.calculateLsc(circuit, lsc)
})
}
func exciteJckxhByCiDrive(circuit *component.SignalJCKXHElectronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.JCKXH_LXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.JCKXH_LXJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.JCKXH_DXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.JCKXH_DXJ).Td = bit
}
}
// 联锁驱
func (s *SignalJCKXHSystem) calculateLsq(state *component.SignalJCKXHElectronic, lsq *component.SignalJCKXHLsq) {
dxj := component.RelayDriveType.Get(state.JCKXH_DXJ)

View File

@ -4,6 +4,7 @@ import (
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type SignalJDXHSystem struct {
@ -20,25 +21,39 @@ func NewSignalJDXHSystem() *SignalJDXHSystem {
// Update world 执行
func (s *SignalJDXHSystem) Update(w ecs.World) {
wd := entity.GetWorldData(w)
s.query.Each(w, func(entry *ecs.Entry) {
state := component.SignalJDXHElectronicType.Get(entry)
lsq := component.SignalJDXHLsqType.Get(entry)
lsc := component.SignalJDXHLscType.Get(entry)
circuit := component.SignalJDXHElectronicType.Get(entry)
exciteJdxhByCiDrive(circuit, wd)
//lsq := component.SignalJDXHLsqType.Get(entry)
//lsc := component.SignalJDXHLscType.Get(entry)
lights := component.SignalLightsType.Get(entry)
JDXH_H := lights.GetLightByTag(component.HdTag)
JDXH_L := lights.GetLightByTag(component.LdTag)
JDXH_U := lights.GetLightByTag(component.UdTag)
//
s.calculateLsq(state, lsq)
s.calculateL(state, JDXH_L)
s.calculateU(state, JDXH_U)
s.calculateH(state, JDXH_H)
s.calculateDJ(state, JDXH_L, JDXH_H)
s.calculate2DJ(state, JDXH_U)
s.calculateLsc(state, lsc)
//s.calculateLsq(circuit, lsq)
s.calculateL(circuit, JDXH_L)
s.calculateU(circuit, JDXH_U)
s.calculateH(circuit, JDXH_H)
s.calculateDJ(circuit, JDXH_L, JDXH_H)
s.calculate2DJ(circuit, JDXH_U)
//s.calculateLsc(circuit, lsc)
})
}
func exciteJdxhByCiDrive(circuit *component.SignalJDXHElectronic, wd *component.WorldData) {
bit, err := wd.QueryQdBit(component.UidType.Get(circuit.JDXH_LXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.JDXH_LXJ).Td = bit
}
bit, err = wd.QueryQdBit(component.UidType.Get(circuit.JDXH_YXJ).Id)
if err == nil {
component.RelayDriveType.Get(circuit.JDXH_YXJ).Td = bit
}
}
// 联锁驱
func (s *SignalJDXHSystem) calculateLsq(state *component.SignalJDXHElectronic, lsq *component.SignalJDXHLsq) {
lxj := component.RelayDriveType.Get(state.JDXH_LXJ)

View File

@ -0,0 +1,44 @@
package circuit_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
"joylink.club/rtsssimulation/sys/device_sys"
)
type TrackCircuitSys struct {
trainQuery *ecs.Query
query *ecs.Query
}
func NewTrackCircuitSys() *TrackCircuitSys {
return &TrackCircuitSys{
trainQuery: ecs.NewQuery(filter.Contains(component.UidType, component.TrainPositionInfoType)),
query: ecs.NewQuery(filter.Contains(entity.TrackCircuitBaseComponentTypeArr...)),
}
}
func (t *TrackCircuitSys) Update(world ecs.World) {
var withTrainSectionMap = make(map[string]bool)
t.trainQuery.Each(world, func(entry *donburi.Entry) {
trainPos := component.TrainPositionInfoType.Get(entry)
sections := device_sys.DoSearchTrainOccupiedSections(world, trainPos)
for _, sectionId := range sections {
withTrainSectionMap[sectionId] = true
}
})
t.query.Each(world, func(entry *ecs.Entry) {
if !entry.HasComponent(component.TrackCircuitType) {
return
}
gj := component.TrackCircuitType.Get(entry).GJ
if withTrainSectionMap[component.UidType.Get(entry).Id] {
component.RelayDriveType.Get(gj).Td = false
} else {
component.RelayDriveType.Get(gj).Td = true
}
})
}

View File

@ -23,40 +23,44 @@ func (x *XcjSys) Update(w ecs.World) {
circuit := component.XcjCircuitType.Get(entry)
//处理联锁对继电器的驱动
handleDrive(wd, circuit)
//驱动继电器
x.drive(circuit)
//洗车流程驱动继电器
x.process(circuit)
//紧急停车
if entry.HasComponent(component.XcjFaultTag) {
component.RelayDriveType.Get(circuit.JTJ).Td = true
} else {
component.RelayDriveType.Get(circuit.JTJ).Td = false
}
}
})
}
func (x *XcjSys) drive(circuit *component.XcjCircuit) {
func (x *XcjSys) process(circuit *component.XcjCircuit) {
//初始状态
if !component.BitStateType.Get(circuit.XQJ).Val && !component.BitStateType.Get(circuit.TGQJ).Val {
component.RelayDriveType.Get(circuit.XCJXJ).Td = true
component.RelayDriveType.Get(circuit.XCJXJ).Td = true
component.RelayDriveType.Get(circuit.XCYXJ).Td = false
for _, cfj := range circuit.CFJList {
component.RelayDriveType.Get(cfj).Td = false
}
component.RelayDriveType.Get(circuit.TGYXJ).Td = false
}
//洗车流程
if component.BitStateType.Get(circuit.XCJXJ).Val { //洗车就绪
if component.BitStateType.Get(circuit.XQJ).Val { //洗车请求
component.RelayDriveType.Get(circuit.XCYXJ).Td = true
component.RelayDriveType.Get(circuit.XCJXJ).Td = false
}
} else if component.BitStateType.Get(circuit.XCYXJ).Val { //洗车允许
if component.BitStateType.Get(circuit.TWJ1).Val {
component.RelayDriveType.Get(circuit.CFJ1).Td = true
}
if component.BitStateType.Get(circuit.TWJ2).Val {
component.RelayDriveType.Get(circuit.CFJ2).Td = true
}
if component.BitStateType.Get(circuit.TWJ3).Val {
component.RelayDriveType.Get(circuit.CFJ3).Td = true
for i, twj := range circuit.TWJList {
if component.BitStateType.Get(twj).Val {
component.RelayDriveType.Get(circuit.CFJList[i]).Td = true
}
}
if component.BitStateType.Get(circuit.TGQJ).Val {
component.RelayDriveType.Get(circuit.TGYXJ).Td = true
}
} else if component.BitStateType.Get(circuit.TGYXJ).Val { //通过允许
if !component.BitStateType.Get(circuit.XQJ).Val && !component.BitStateType.Get(circuit.TGQJ).Val {
component.RelayDriveType.Get(circuit.XCJXJ).Td = true
component.RelayDriveType.Get(circuit.XCYXJ).Td = false
component.RelayDriveType.Get(circuit.CFJ1).Td = false
component.RelayDriveType.Get(circuit.CFJ2).Td = false
component.RelayDriveType.Get(circuit.CFJ3).Td = false
component.RelayDriveType.Get(circuit.TGYXJ).Td = false
}
}
}
@ -69,26 +73,14 @@ func handleDrive(wd *component.WorldData, circuit *component.XcjCircuit) {
} else {
component.RelayDriveType.Get(circuit.XQJ).Td = XQJBit
}
TWJ1Id := component.UidType.Get(circuit.TWJ1).Id
TWJ1Bit, err := wd.QueryQdBit(TWJ1Id)
if err != nil {
slog.Error(err.Error())
} else {
component.RelayDriveType.Get(circuit.TWJ1).Td = TWJ1Bit
}
TWJ2Id := component.UidType.Get(circuit.TWJ2).Id
TWJ2Bit, err := wd.QueryQdBit(TWJ2Id)
if err != nil {
slog.Error(err.Error())
} else {
component.RelayDriveType.Get(circuit.TWJ2).Td = TWJ2Bit
}
TWJ3Id := component.UidType.Get(circuit.TWJ3).Id
TWJ3Bit, err := wd.QueryQdBit(TWJ3Id)
if err != nil {
slog.Error(err.Error())
} else {
component.RelayDriveType.Get(circuit.TWJ3).Td = TWJ3Bit
for _, twj := range circuit.TWJList {
id := component.UidType.Get(twj).Id
twjBit, err := wd.QueryQdBit(id)
if err != nil {
slog.Error(err.Error())
} else {
component.RelayDriveType.Get(twj).Td = twjBit
}
}
TGQJId := component.UidType.Get(circuit.TGQJ).Id
TGQJBit, err := wd.QueryQdBit(TGQJId)

View File

@ -0,0 +1,30 @@
package device_sys
import (
"github.com/yohamta/donburi"
"joylink.club/ecs"
"joylink.club/ecs/filter"
"joylink.club/rtsssimulation/component"
"joylink.club/rtsssimulation/entity"
)
type AxleCountingSectionSystem struct {
axleCountingSectionQuery *ecs.Query
}
func NewAxleCountingSectionSystem() *AxleCountingSectionSystem {
return &AxleCountingSectionSystem{
axleCountingSectionQuery: ecs.NewQuery(filter.Contains(entity.AxleCountingSectionBaseComponentTypes...)),
}
}
func (a *AxleCountingSectionSystem) Update(w ecs.World) {
a.axleCountingSectionQuery.Each(w, func(entry *donburi.Entry) {
wd := entity.GetWorldData(w)
uid := component.UidType.Get(entry).Id
section := wd.Repo.FindAxleCountingSection(uid)
physicalSectionEntry := wd.EntityMap[section.PhysicalSection().Id()]
occupied := component.PhysicalSectionManagerType.Get(physicalSectionEntry).Occupied
component.AxleCountingSectionStateType.Get(entry).Occupied = occupied
})
}

View File

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

View File

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

View File

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