Merge remote-tracking branch 'origin/master'

This commit is contained in:
joylink_zhangsai 2024-01-23 09:20:10 +08:00
commit 19c67811d0
23 changed files with 1014 additions and 375 deletions

View File

@ -372,15 +372,15 @@ func signalOperation(c *gin.Context) {
// @Failure 500 {object} dto.ErrorDto // @Failure 500 {object} dto.ErrorDto
// @Router /api/v1/simulation/axleSection/operation [post] // @Router /api/v1/simulation/axleSection/operation [post]
func axleSectionOperation(c *gin.Context) { //操作:设置故障占用、取消故障占用 func axleSectionOperation(c *gin.Context) { //操作:设置故障占用、取消故障占用
req := &dto.AxleSectionOperationReqDto{} req := &request_proto.SectionOperationReq{}
if err := c.ShouldBind(&req); err != nil { if err := c.ShouldBind(&req); err != nil {
panic(sys_error.New("输入参数格式错误", err)) panic(sys_error.New("输入参数格式错误", err))
} }
simulation := checkDeviceDataAndReturn(req.SimulationId) simulation := checkDeviceDataAndReturn(req.SimulationId)
slog.Info("传入状态参数", req) slog.Info("传入状态参数", "req", req)
err := memory.ChangeAxleSectionState(simulation, req) err := memory.HandleSectionOperation(simulation, req)
if err != nil { if err != nil {
panic(sys_error.New("操作失败", err)) panic(sys_error.New("区段操作失败", err))
} }
c.JSON(http.StatusOK, "ok") c.JSON(http.StatusOK, "ok")
} }

@ -1 +1 @@
Subproject commit 3a30efc9fe949cd5ab9898073f00a093716f279e Subproject commit bdd66d8625e76afb23f501de306224d35a8958d1

View File

@ -344,31 +344,26 @@ func (Signal_Force) EnumDescriptor() ([]byte, []int) {
type Section_Operation int32 type Section_Operation int32
const ( const (
Section_SetDrst Section_Operation = 0 //设置计轴直接复位 Section_Undefined Section_Operation = 0 // 未定义
Section_CancelDrst Section_Operation = 1 //取消计轴直接复位 Section_SetParams Section_Operation = 1 // 设置参数
Section_SetPdrst Section_Operation = 2 //设置计轴预复位 // SetDrst = 0;//设置计轴直接复位
Section_CancelPdrst Section_Operation = 3 //取消计轴预复位 // CancelDrst = 1;//取消计轴直接复位
// SetPdrst = 2;//设置计轴预复位
// CancelPdrst = 3;//取消计轴预复位
Section_SetFaultOcc Section_Operation = 4 //设置故障占用 Section_SetFaultOcc Section_Operation = 4 //设置故障占用
Section_CancelFaultOcc Section_Operation = 5 //取消故障占用
) )
// Enum value maps for Section_Operation. // Enum value maps for Section_Operation.
var ( var (
Section_Operation_name = map[int32]string{ Section_Operation_name = map[int32]string{
0: "SetDrst", 0: "Undefined",
1: "CancelDrst", 1: "SetParams",
2: "SetPdrst",
3: "CancelPdrst",
4: "SetFaultOcc", 4: "SetFaultOcc",
5: "CancelFaultOcc",
} }
Section_Operation_value = map[string]int32{ Section_Operation_value = map[string]int32{
"SetDrst": 0, "Undefined": 0,
"CancelDrst": 1, "SetParams": 1,
"SetPdrst": 2,
"CancelPdrst": 3,
"SetFaultOcc": 4, "SetFaultOcc": 4,
"CancelFaultOcc": 5,
} }
) )
@ -497,7 +492,7 @@ func (x Psd_Operation) Number() protoreflect.EnumNumber {
// Deprecated: Use Psd_Operation.Descriptor instead. // Deprecated: Use Psd_Operation.Descriptor instead.
func (Psd_Operation) EnumDescriptor() ([]byte, []int) { func (Psd_Operation) EnumDescriptor() ([]byte, []int) {
return file_request_proto_rawDescGZIP(), []int{9, 0} return file_request_proto_rawDescGZIP(), []int{11, 0}
} }
// 继电器 // 继电器
@ -990,6 +985,141 @@ func (*Section) Descriptor() ([]byte, []int) {
return file_request_proto_rawDescGZIP(), []int{8} return file_request_proto_rawDescGZIP(), []int{8}
} }
type SectionOperationReq struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
SimulationId string `protobuf:"bytes,1,opt,name=simulationId,proto3" json:"simulationId,omitempty"` // 仿真id
MapId int32 `protobuf:"varint,2,opt,name=mapId,proto3" json:"mapId,omitempty"` // 图id
DeviceId uint32 `protobuf:"varint,3,opt,name=deviceId,proto3" json:"deviceId,omitempty"` // 设备id
Operation Section_Operation `protobuf:"varint,4,opt,name=operation,proto3,enum=request.Section_Operation" json:"operation,omitempty"` // 区段操作
Param *SectionParam `protobuf:"bytes,5,opt,name=param,proto3" json:"param,omitempty"` // 区段参数,当operation为SetParams时有效
}
func (x *SectionOperationReq) Reset() {
*x = SectionOperationReq{}
if protoimpl.UnsafeEnabled {
mi := &file_request_proto_msgTypes[9]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SectionOperationReq) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SectionOperationReq) ProtoMessage() {}
func (x *SectionOperationReq) ProtoReflect() protoreflect.Message {
mi := &file_request_proto_msgTypes[9]
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 SectionOperationReq.ProtoReflect.Descriptor instead.
func (*SectionOperationReq) Descriptor() ([]byte, []int) {
return file_request_proto_rawDescGZIP(), []int{9}
}
func (x *SectionOperationReq) GetSimulationId() string {
if x != nil {
return x.SimulationId
}
return ""
}
func (x *SectionOperationReq) GetMapId() int32 {
if x != nil {
return x.MapId
}
return 0
}
func (x *SectionOperationReq) GetDeviceId() uint32 {
if x != nil {
return x.DeviceId
}
return 0
}
func (x *SectionOperationReq) GetOperation() Section_Operation {
if x != nil {
return x.Operation
}
return Section_Undefined
}
func (x *SectionOperationReq) GetParam() *SectionParam {
if x != nil {
return x.Param
}
return nil
}
type SectionParam struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
// bool faultOcc = 1; // 故障占用
MockDrst bool `protobuf:"varint,2,opt,name=mockDrst,proto3" json:"mockDrst,omitempty"` // 模拟CI计轴复位(临时)
MockPdrst bool `protobuf:"varint,3,opt,name=mockPdrst,proto3" json:"mockPdrst,omitempty"` // 模拟CI计轴预复位(临时)
}
func (x *SectionParam) Reset() {
*x = SectionParam{}
if protoimpl.UnsafeEnabled {
mi := &file_request_proto_msgTypes[10]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *SectionParam) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*SectionParam) ProtoMessage() {}
func (x *SectionParam) ProtoReflect() protoreflect.Message {
mi := &file_request_proto_msgTypes[10]
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 SectionParam.ProtoReflect.Descriptor instead.
func (*SectionParam) Descriptor() ([]byte, []int) {
return file_request_proto_rawDescGZIP(), []int{10}
}
func (x *SectionParam) GetMockDrst() bool {
if x != nil {
return x.MockDrst
}
return false
}
func (x *SectionParam) GetMockPdrst() bool {
if x != nil {
return x.MockPdrst
}
return false
}
// 屏蔽门 // 屏蔽门
type Psd struct { type Psd struct {
state protoimpl.MessageState state protoimpl.MessageState
@ -1000,7 +1130,7 @@ type Psd struct {
func (x *Psd) Reset() { func (x *Psd) Reset() {
*x = Psd{} *x = Psd{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_request_proto_msgTypes[9] mi := &file_request_proto_msgTypes[11]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1013,7 +1143,7 @@ func (x *Psd) String() string {
func (*Psd) ProtoMessage() {} func (*Psd) ProtoMessage() {}
func (x *Psd) ProtoReflect() protoreflect.Message { func (x *Psd) ProtoReflect() protoreflect.Message {
mi := &file_request_proto_msgTypes[9] mi := &file_request_proto_msgTypes[11]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1026,7 +1156,7 @@ func (x *Psd) ProtoReflect() protoreflect.Message {
// Deprecated: Use Psd.ProtoReflect.Descriptor instead. // Deprecated: Use Psd.ProtoReflect.Descriptor instead.
func (*Psd) Descriptor() ([]byte, []int) { func (*Psd) Descriptor() ([]byte, []int) {
return file_request_proto_rawDescGZIP(), []int{9} return file_request_proto_rawDescGZIP(), []int{11}
} }
// 屏蔽门操作请求 // 屏蔽门操作请求
@ -1046,7 +1176,7 @@ type PsdOperationReq struct {
func (x *PsdOperationReq) Reset() { func (x *PsdOperationReq) Reset() {
*x = PsdOperationReq{} *x = PsdOperationReq{}
if protoimpl.UnsafeEnabled { if protoimpl.UnsafeEnabled {
mi := &file_request_proto_msgTypes[10] mi := &file_request_proto_msgTypes[12]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi) ms.StoreMessageInfo(mi)
} }
@ -1059,7 +1189,7 @@ func (x *PsdOperationReq) String() string {
func (*PsdOperationReq) ProtoMessage() {} func (*PsdOperationReq) ProtoMessage() {}
func (x *PsdOperationReq) ProtoReflect() protoreflect.Message { func (x *PsdOperationReq) ProtoReflect() protoreflect.Message {
mi := &file_request_proto_msgTypes[10] mi := &file_request_proto_msgTypes[12]
if protoimpl.UnsafeEnabled && x != nil { if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil { if ms.LoadMessageInfo() == nil {
@ -1072,7 +1202,7 @@ func (x *PsdOperationReq) ProtoReflect() protoreflect.Message {
// Deprecated: Use PsdOperationReq.ProtoReflect.Descriptor instead. // Deprecated: Use PsdOperationReq.ProtoReflect.Descriptor instead.
func (*PsdOperationReq) Descriptor() ([]byte, []int) { func (*PsdOperationReq) Descriptor() ([]byte, []int) {
return file_request_proto_rawDescGZIP(), []int{10} return file_request_proto_rawDescGZIP(), []int{12}
} }
func (x *PsdOperationReq) GetSimulationId() string { func (x *PsdOperationReq) GetSimulationId() string {
@ -1193,48 +1323,63 @@ var file_request_proto_rawDesc = []byte{
0x61, 0x6c, 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12, 0x61, 0x6c, 0x2e, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x52, 0x05, 0x66, 0x6f, 0x72, 0x63, 0x65, 0x12,
0x2a, 0x0a, 0x06, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32, 0x2a, 0x0a, 0x06, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0e, 0x32,
0x12, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x12, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c,
0x2e, 0x44, 0x53, 0x52, 0x06, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x77, 0x0a, 0x07, 0x53, 0x2e, 0x44, 0x53, 0x52, 0x06, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x45, 0x0a, 0x07, 0x53,
0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74,
0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x44, 0x72, 0x73, 0x74, 0x10, 0x00, 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64,
0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x44, 0x72, 0x73, 0x74, 0x10, 0x01, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x10,
0x12, 0x0c, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x50, 0x64, 0x72, 0x73, 0x74, 0x10, 0x02, 0x12, 0x0f, 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4f, 0x63, 0x63,
0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x64, 0x72, 0x73, 0x74, 0x10, 0x03, 0x12, 0x10, 0x04, 0x22, 0xd2, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70,
0x0f, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4f, 0x63, 0x63, 0x10, 0x04, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x69,
0x12, 0x12, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4f, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
0x63, 0x63, 0x10, 0x05, 0x22, 0x87, 0x02, 0x0a, 0x03, 0x50, 0x73, 0x64, 0x22, 0xff, 0x01, 0x0a, 0x52, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14,
0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e, 0x0a, 0x05, 0x6d, 0x61, 0x70, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d,
0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4b, 0x6d, 0x10, 0x61, 0x70, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64,
0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4b, 0x6d, 0x10, 0x02, 0x12, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64,
0x06, 0x0a, 0x02, 0x47, 0x6d, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x38, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20,
0x6c, 0x47, 0x6d, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4b, 0x6d, 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x65,
0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x47, 0x6d, 0x10, 0x06, 0x12, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52,
0x0f, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x10, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x61,
0x12, 0x11, 0x0a, 0x0d, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x71, 0x75,
0x6e, 0x10, 0x0b, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d,
0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x10, 0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x22, 0x48, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x74, 0x69,
0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0d, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6f, 0x63, 0x6b, 0x44,
0x12, 0x18, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x72, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x6f, 0x63, 0x6b, 0x44,
0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0e, 0x12, 0x08, 0x0a, 0x04, 0x51, 0x44, 0x72, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x6f, 0x63, 0x6b, 0x50, 0x64, 0x72, 0x73, 0x74,
0x54, 0x43, 0x10, 0x0f, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x51, 0x44, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6d, 0x6f, 0x63, 0x6b, 0x50, 0x64, 0x72, 0x73,
0x54, 0x43, 0x10, 0x10, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x11, 0x12, 0x0e, 0x74, 0x22, 0x87, 0x02, 0x0a, 0x03, 0x50, 0x73, 0x64, 0x22, 0xff, 0x01, 0x0a, 0x09, 0x4f, 0x70,
0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x12, 0x22, 0xcf, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e, 0x64, 0x65, 0x66,
0x01, 0x0a, 0x0f, 0x50, 0x73, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4b, 0x6d, 0x10, 0x01, 0x12, 0x0c,
0x65, 0x71, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4b, 0x6d, 0x10, 0x02, 0x12, 0x06, 0x0a, 0x02,
0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x47, 0x6d, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x47, 0x6d,
0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x70, 0x49, 0x64, 0x18, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4b, 0x6d, 0x10, 0x05, 0x12,
0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x70, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x47, 0x6d, 0x10, 0x06, 0x12, 0x0f, 0x0a, 0x0b,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x10, 0x0a, 0x12, 0x11, 0x0a,
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x0d, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x10, 0x0b,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x72, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e,
0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x50, 0x73, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x10, 0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x73, 0x64,
0x69, 0x6f, 0x6e, 0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0d, 0x12, 0x18, 0x0a,
0x0a, 0x08, 0x61, 0x73, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x05, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74,
0x52, 0x08, 0x61, 0x73, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0e, 0x12, 0x08, 0x0a, 0x04, 0x51, 0x44, 0x54, 0x43, 0x10,
0x6f, 0x75, 0x70, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x0f, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x51, 0x44, 0x54, 0x43, 0x10,
0x42, 0x30, 0x5a, 0x2e, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x10, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x11, 0x12, 0x0e, 0x0a, 0x0a, 0x43,
0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x12, 0x22, 0xcf, 0x01, 0x0a, 0x0f,
0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x50, 0x73, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12,
0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, 0x22, 0x0a, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x18,
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x69, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x69, 0x6f,
0x6e, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6d, 0x61, 0x70, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01,
0x28, 0x05, 0x52, 0x05, 0x6d, 0x61, 0x70, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x64, 0x65, 0x76,
0x69, 0x63, 0x65, 0x49, 0x64, 0x12, 0x34, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69,
0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65,
0x73, 0x74, 0x2e, 0x50, 0x73, 0x64, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
0x52, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1a, 0x0a, 0x08, 0x61,
0x73, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x05, 0x52, 0x08, 0x61,
0x73, 0x64, 0x43, 0x6f, 0x64, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70,
0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x42, 0x30, 0x5a,
0x2e, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a,
0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64, 0x74,
0x6f, 0x2f, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62,
0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
} }
var ( var (
@ -1250,7 +1395,7 @@ func file_request_proto_rawDescGZIP() []byte {
} }
var file_request_proto_enumTypes = make([]protoimpl.EnumInfo, 8) var file_request_proto_enumTypes = make([]protoimpl.EnumInfo, 8)
var file_request_proto_msgTypes = make([]protoimpl.MessageInfo, 11) var file_request_proto_msgTypes = make([]protoimpl.MessageInfo, 13)
var file_request_proto_goTypes = []interface{}{ var file_request_proto_goTypes = []interface{}{
(Relay_Operation)(0), // 0: request.Relay.Operation (Relay_Operation)(0), // 0: request.Relay.Operation
(Points_Operation)(0), // 1: request.Points.Operation (Points_Operation)(0), // 1: request.Points.Operation
@ -1269,8 +1414,10 @@ var file_request_proto_goTypes = []interface{}{
(*SignalOperationReq)(nil), // 14: request.SignalOperationReq (*SignalOperationReq)(nil), // 14: request.SignalOperationReq
(*SignalParam)(nil), // 15: request.SignalParam (*SignalParam)(nil), // 15: request.SignalParam
(*Section)(nil), // 16: request.Section (*Section)(nil), // 16: request.Section
(*Psd)(nil), // 17: request.Psd (*SectionOperationReq)(nil), // 17: request.SectionOperationReq
(*PsdOperationReq)(nil), // 18: request.PsdOperationReq (*SectionParam)(nil), // 18: request.SectionParam
(*Psd)(nil), // 19: request.Psd
(*PsdOperationReq)(nil), // 20: request.PsdOperationReq
} }
var file_request_proto_depIdxs = []int32{ var file_request_proto_depIdxs = []int32{
0, // 0: request.RelayOperationReq.operation:type_name -> request.Relay.Operation 0, // 0: request.RelayOperationReq.operation:type_name -> request.Relay.Operation
@ -1281,12 +1428,14 @@ var file_request_proto_depIdxs = []int32{
15, // 5: request.SignalOperationReq.param:type_name -> request.SignalParam 15, // 5: request.SignalOperationReq.param:type_name -> request.SignalParam
5, // 6: request.SignalParam.force:type_name -> request.Signal.Force 5, // 6: request.SignalParam.force:type_name -> request.Signal.Force
4, // 7: request.SignalParam.dsList:type_name -> request.Signal.DS 4, // 7: request.SignalParam.dsList:type_name -> request.Signal.DS
7, // 8: request.PsdOperationReq.operation:type_name -> request.Psd.Operation 6, // 8: request.SectionOperationReq.operation:type_name -> request.Section.Operation
9, // [9:9] is the sub-list for method output_type 18, // 9: request.SectionOperationReq.param:type_name -> request.SectionParam
9, // [9:9] is the sub-list for method input_type 7, // 10: request.PsdOperationReq.operation:type_name -> request.Psd.Operation
9, // [9:9] is the sub-list for extension type_name 11, // [11:11] is the sub-list for method output_type
9, // [9:9] is the sub-list for extension extendee 11, // [11:11] is the sub-list for method input_type
0, // [0:9] is the sub-list for field type_name 11, // [11:11] is the sub-list for extension type_name
11, // [11:11] is the sub-list for extension extendee
0, // [0:11] is the sub-list for field type_name
} }
func init() { file_request_proto_init() } func init() { file_request_proto_init() }
@ -1404,7 +1553,7 @@ func file_request_proto_init() {
} }
} }
file_request_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { file_request_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Psd); i { switch v := v.(*SectionOperationReq); i {
case 0: case 0:
return &v.state return &v.state
case 1: case 1:
@ -1416,6 +1565,30 @@ func file_request_proto_init() {
} }
} }
file_request_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} { file_request_proto_msgTypes[10].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*SectionParam); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_request_proto_msgTypes[11].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Psd); i {
case 0:
return &v.state
case 1:
return &v.sizeCache
case 2:
return &v.unknownFields
default:
return nil
}
}
file_request_proto_msgTypes[12].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*PsdOperationReq); i { switch v := v.(*PsdOperationReq); i {
case 0: case 0:
return &v.state return &v.state
@ -1434,7 +1607,7 @@ func file_request_proto_init() {
GoPackagePath: reflect.TypeOf(x{}).PkgPath(), GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_request_proto_rawDesc, RawDescriptor: file_request_proto_rawDesc,
NumEnums: 8, NumEnums: 8,
NumMessages: 11, NumMessages: 13,
NumExtensions: 0, NumExtensions: 0,
NumServices: 0, NumServices: 0,
}, },

View File

@ -22,7 +22,7 @@ var ti = &ReceiveTrainInfo{
var trainRun bool var trainRun bool
var IP = net.IPv4(192, 168, 3, 7) var IP = net.IPv4(192, 168, 3, 7)
var SendIP = net.IPv4(192, 168, 3, 233) var SendIP = net.IPv4(192, 168, 3, 7)
func main() { func main() {
listen, err := net.ListenUDP("udp", &net.UDPAddr{ listen, err := net.ListenUDP("udp", &net.UDPAddr{

1
go.mod
View File

@ -9,6 +9,7 @@ require (
github.com/golang/protobuf v1.5.3 github.com/golang/protobuf v1.5.3
github.com/google/uuid v1.4.0 github.com/google/uuid v1.4.0
github.com/sagikazarmark/slog-shim v0.1.0 github.com/sagikazarmark/slog-shim v0.1.0
github.com/snksoft/crc v1.1.0
github.com/spf13/viper v1.18.1 github.com/spf13/viper v1.18.1
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.8.4
github.com/swaggo/files v1.0.1 github.com/swaggo/files v1.0.1

2
go.sum
View File

@ -176,6 +176,8 @@ github.com/samber/slog-gin v1.1.0 h1:dDvYEGJkJg0DxuNWo6m6gV5Bm+iSk85Ox9on7c7OjQU
github.com/samber/slog-gin v1.1.0/go.mod h1:vmMxOYIqDHbthu7SmiF/oOlMhpYukL62JB4Ct5etOvI= github.com/samber/slog-gin v1.1.0/go.mod h1:vmMxOYIqDHbthu7SmiF/oOlMhpYukL62JB4Ct5etOvI=
github.com/simonvetter/modbus v1.6.0 h1:RDHJevtc7LDIVoHAbhDun8fy+QwnGe+ZU+sLm9ZZzjc= github.com/simonvetter/modbus v1.6.0 h1:RDHJevtc7LDIVoHAbhDun8fy+QwnGe+ZU+sLm9ZZzjc=
github.com/simonvetter/modbus v1.6.0/go.mod h1:hh90ZaTaPLcK2REj6/fpTbiV0J6S7GWmd8q+GVRObPw= github.com/simonvetter/modbus v1.6.0/go.mod h1:hh90ZaTaPLcK2REj6/fpTbiV0J6S7GWmd8q+GVRObPw=
github.com/snksoft/crc v1.1.0 h1:HkLdI4taFlgGGG1KvsWMpz78PkOC9TkPVpTV/cuWn48=
github.com/snksoft/crc v1.1.0/go.mod h1:5/gUOsgAm7OmIhb6WJzw7w5g2zfJi4FrHYgGPdshE+A=
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=

View File

@ -10,8 +10,6 @@ import (
"joylink.club/bj-rtsts-server/docs" "joylink.club/bj-rtsts-server/docs"
"joylink.club/bj-rtsts-server/middleware" "joylink.club/bj-rtsts-server/middleware"
"joylink.club/bj-rtsts-server/mqtt" "joylink.club/bj-rtsts-server/mqtt"
"joylink.club/bj-rtsts-server/third_party"
) )
// @title CBTC测试系统API // @title CBTC测试系统API
@ -28,7 +26,6 @@ import (
func main() { func main() {
engine := InitServer() engine := InitServer()
mqtt.Startup(mqtt.NewMqttOptions(config.Config.Messaging.Mqtt.Address, config.Config.Messaging.Mqtt.Username, config.Config.Messaging.Mqtt.Password)) mqtt.Startup(mqtt.NewMqttOptions(config.Config.Messaging.Mqtt.Address, config.Config.Messaging.Mqtt.Username, config.Config.Messaging.Mqtt.Password))
third_party.Init()
authMiddleware := middleware.InitGinJwtMiddleware() authMiddleware := middleware.InitGinJwtMiddleware()
router := engine.Group("/api") router := engine.Group("/api")
api.InitUserRouter(router, authMiddleware) api.InitUserRouter(router, authMiddleware)

View File

@ -2,10 +2,11 @@ package axle_device
import ( import (
"fmt" "fmt"
"log/slog"
"joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/udp" "joylink.club/bj-rtsts-server/third_party/udp"
"log/slog"
) )
// 铁路信号安全通信协议实现 // 铁路信号安全通信协议实现
@ -48,8 +49,8 @@ func (s *RsspChannel) Init(config *config.RsspConfig) *RsspChannel {
s.config = config s.config = config
s.rsspTimer = &RsspTimer{t: 0} s.rsspTimer = &RsspTimer{t: 0}
s.sn = message.NewRsspSn(1) s.sn = message.NewRsspSn(1)
s.ch1Ts = message.NewRsspLFSR(message.RsspTsC1, 32, s.config.SID1, false) s.ch1Ts = message.NewRsspLFSR(message.RSSP_I_C1_TS, 32, s.config.SID1, false)
s.ch2Ts = message.NewRsspLFSR(message.RsspTsC2, 32, s.config.SID2, false) s.ch2Ts = message.NewRsspLFSR(message.RSSP_I_C2_TS, 32, s.config.SID2, false)
return s return s
} }
@ -178,11 +179,11 @@ func (s *RsspChannel) handleRsspRsd(rsd *message.RsspRsd) {
return return
} }
//SVC校验 //SVC校验
c1Crc32 := message.RsspC1Crc32(rsd.Sad) c1Crc32 := message.Rssp_I_Crc32C1(rsd.Sad)
c1SidTs := c1Crc32 ^ rsd.Svc1 ^ message.SCW_C1 //T(n) c1SidTs := c1Crc32 ^ rsd.Svc1 ^ message.RSSP_I_C1_SCW //T(n)
// //
c2Crc32 := message.RsspC2Crc32(rsd.Sad) c2Crc32 := message.Rssp_I_Crc32C2(rsd.Sad)
c2SidTs := c2Crc32 ^ rsd.Svc2 ^ message.SCW_C2 //T(n) c2SidTs := c2Crc32 ^ rsd.Svc2 ^ message.RSSP_I_C2_SCW //T(n)
//todo ... SVC校验待完善 //todo ... SVC校验待完善
_ = c1SidTs _ = c1SidTs
_ = c2SidTs _ = c2SidTs
@ -291,11 +292,11 @@ func (s *RsspChannel) SendUserData(userData []byte) {
rsd.Sn = s.sn.Get() rsd.Sn = s.sn.Get()
rsd.Sdl = uint16(len(userData) + 8) rsd.Sdl = uint16(len(userData) + 8)
//安全校验通道SVC_1 //安全校验通道SVC_1
crc_c1 := message.RsspC1Crc32(userData) crc_c1 := message.Rssp_I_Crc32C1(userData)
rsd.Svc1 = s.createSvcCode(crc_c1, s.config.SID1, s.ch1Ts.Get(), message.SCW_C1) rsd.Svc1 = s.createSvcCode(crc_c1, s.config.SID1, s.ch1Ts.Get(), message.RSSP_I_C1_SCW)
//安全校验通道SVC_2 //安全校验通道SVC_2
crc_c2 := message.RsspC2Crc32(userData) crc_c2 := message.Rssp_I_Crc32C2(userData)
rsd.Svc1 = s.createSvcCode(crc_c2, s.config.SID2, s.ch2Ts.Get(), message.SCW_C2) rsd.Svc1 = s.createSvcCode(crc_c2, s.config.SID2, s.ch2Ts.Get(), message.RSSP_I_C2_SCW)
rsd.Sad = userData rsd.Sad = userData
// //
rsspPack := rsd.Encode() rsspPack := rsd.Encode()

View File

@ -14,6 +14,7 @@ import (
"joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/sys_error" "joylink.club/bj-rtsts-server/sys_error"
"joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/tpapi"
"joylink.club/bj-rtsts-server/third_party/udp" "joylink.club/bj-rtsts-server/third_party/udp"
) )
@ -26,6 +27,7 @@ type DynamicsMessageManager interface {
// 动力学接口 // 动力学接口
type Dynamics interface { type Dynamics interface {
tpapi.ThirdPartyApiService
// 请求添加列车 // 请求添加列车
RequestAddTrain(info *message.InitTrainInfo) error RequestAddTrain(info *message.InitTrainInfo) error
// 请求移除列车 // 请求移除列车
@ -44,20 +46,34 @@ type Dynamics interface {
var _default Dynamics var _default Dynamics
var initMutex sync.Mutex var initMutex sync.Mutex
const Interval = 15
func Default() Dynamics { func Default() Dynamics {
initMutex.Lock() initMutex.Lock()
defer initMutex.Unlock() defer initMutex.Unlock()
if _default == nil { if _default == nil {
_default = &dynamics{} _default = &dynamics{
ThirdPartyApiService: tpapi.NewThirdPartyApiService(),
udpDelayRecorder: tpapi.NewUdpDelayRecorder(Interval, func(err error) {
if err != nil {
_default.UpdateState(tpapi.ThirdPartyState_Broken)
} else {
_default.UpdateState(tpapi.ThirdPartyState_Normal)
}
}),
}
} }
return _default return _default
} }
type dynamics struct { type dynamics struct {
tpapi.ThirdPartyApiService
trainInfoUdpServer udp.UdpServer trainInfoUdpServer udp.UdpServer
turnoutStateUdpClient udp.UdpClient turnoutStateUdpClient udp.UdpClient
trainControlUdpClient udp.UdpClient trainControlUdpClient udp.UdpClient
udpDelayRecorder *tpapi.UdpDelayRecorder
baseUrl string baseUrl string
httpClient *http.Client httpClient *http.Client
manager DynamicsMessageManager manager DynamicsMessageManager
@ -67,6 +83,7 @@ type dynamics struct {
// 解码列车信息并处理 // 解码列车信息并处理
func (d *dynamics) handleDynamicsTrainInfo(b []byte) { func (d *dynamics) handleDynamicsTrainInfo(b []byte) {
d.udpDelayRecorder.RecordInterval()
trainInfo := &message.DynamicsTrainInfo{} trainInfo := &message.DynamicsTrainInfo{}
err := trainInfo.Decode(b) err := trainInfo.Decode(b)
if err != nil { if err != nil {
@ -176,10 +193,10 @@ func (d *dynamics) TrainOperationConfig(req *message.TrainOperationConfig) error
data, _ := json.Marshal(req) data, _ := json.Marshal(req)
url := d.buildUrl("/api/config") url := d.buildUrl("/api/config")
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data)) resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
defer resp.Body.Close()
if err != nil { if err != nil {
return fmt.Errorf("动力学移除列车请求异常: %v", err) return fmt.Errorf("动力学移除列车请求异常: %v", err)
} }
defer resp.Body.Close()
var bodyData []byte var bodyData []byte
_, err = resp.Body.Read(bodyData) _, err = resp.Body.Read(bodyData)
if err != nil { if err != nil {
@ -210,6 +227,8 @@ func (d *dynamics) Start(manager DynamicsMessageManager) error {
ctx, cancle := context.WithCancel(context.Background()) ctx, cancle := context.WithCancel(context.Background())
go d.sendTurnoutStateTask(ctx) go d.sendTurnoutStateTask(ctx)
d.turnoutTaskCancel = cancle d.turnoutTaskCancel = cancle
d.UpdateState(tpapi.ThirdPartyState_Normal)
d.udpDelayRecorder.Start()
return nil return nil
} }
@ -236,7 +255,8 @@ func (d *dynamics) initDynamicsRunRepository() error {
func (d *dynamics) Stop() { func (d *dynamics) Stop() {
initMutex.Lock() initMutex.Lock()
defer initMutex.Unlock() defer initMutex.Unlock()
_default = nil // 停止网络监听
d.udpDelayRecorder.Stop()
if d.httpClient != nil { if d.httpClient != nil {
d.requestStopSimulation() d.requestStopSimulation()
d.httpClient = nil d.httpClient = nil
@ -254,6 +274,7 @@ func (d *dynamics) Stop() {
d.turnoutTaskCancel() d.turnoutTaskCancel()
} }
d.manager = nil d.manager = nil
d.UpdateState(tpapi.ThirdPartyState_Closed)
} }
const ( const (

View File

@ -2,14 +2,15 @@ package main
import ( import (
"fmt" "fmt"
"time"
"joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/third_party/example/rssp/ci" "joylink.club/bj-rtsts-server/third_party/example/rssp/ci"
"joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/message"
"time"
) )
func main() { func main() {
message.InitRsspCrcTable() // message.InitRsspCrcTable()
ci.InitCiServerCodePoints() ci.InitCiServerCodePoints()
// //
cfg := &config.RsspAxleConfig{} cfg := &config.RsspAxleConfig{}

View File

@ -145,7 +145,7 @@ func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
} else { } else {
return false return false
} }
crc16 := calculateAtpReqCrc16(timeArr) crc16 := Can_Crc16(timeArr)
t1 := uint32(timeArr[0]) t1 := uint32(timeArr[0])
t2 := uint32(timeArr[1]) t2 := uint32(timeArr[1])
t3 := uint32(timeArr[2]) t3 := uint32(timeArr[2])
@ -211,7 +211,7 @@ func (f *AtpRequestFrame) Encode() *CanetFrame {
bits.AddByte(timeByte) bits.AddByte(timeByte)
} }
//crc //crc
crc16 := calculateAtpReqCrc16(timeArr) crc16 := Can_Crc16(timeArr)
bits.AddByte(byte(crc16 >> 8)) bits.AddByte(byte(crc16 >> 8))
bits.AddByte(byte(crc16)) bits.AddByte(byte(crc16))
// //

View File

@ -44,7 +44,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
var crc32AData []byte var crc32AData []byte
crc32AData = append(crc32AData, msg...) crc32AData = append(crc32AData, msg...)
crc32AData = append(crc32AData, canTimeToBytes(dtA.TimeA)...) crc32AData = append(crc32AData, canTimeToBytes(dtA.TimeA)...)
dtA.Crc32A = calculateDataRspCrc32A(crc32AData) //CRC32A的校验范围是报文+时间戳A dtA.Crc32A = Can_Crc32(crc32AData) //CRC32A的校验范围是报文+时间戳A
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF” } else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
dtA.Crc32A = 0xff_ff_ff_ff dtA.Crc32A = 0xff_ff_ff_ff
} }
@ -55,7 +55,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
var crc32BData []byte var crc32BData []byte
crc32BData = append(crc32BData, msg...) crc32BData = append(crc32BData, msg...)
crc32BData = append(crc32BData, canTimeToBytes(dtB.TimeB)...) crc32BData = append(crc32BData, canTimeToBytes(dtB.TimeB)...)
dtB.Crc32B = calculateDataRspCrc32B(crc32BData) //CRC32B的校验范围是报文+时间戳B dtB.Crc32B = Can_Crc32(crc32BData) //CRC32B的校验范围是报文+时间戳B
} else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF” } else { //BTM解包发生错误则数据帧及CRC32A/B全填“0xFF”
dtB.Crc32B = 0xff_ff_ff_ff dtB.Crc32B = 0xff_ff_ff_ff
} }
@ -80,7 +80,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
crc32cData = append(crc32cData, dtBCf.CanData...) crc32cData = append(crc32cData, dtBCf.CanData...)
crc32cData = append(crc32cData, canTimeToBytes(end.TkB)...) crc32cData = append(crc32cData, canTimeToBytes(end.TkB)...)
// //
end.Crc32C = calculateDataRspCrc32C(crc32cData) end.Crc32C = Can_Crc32(crc32cData)
// //
endCf := end.Encode() endCf := end.Encode()
// //

View File

@ -1,5 +1,7 @@
package message package message
import "github.com/snksoft/crc"
/////////////////////CAN串行总线 bit 流处理 //////////////////////// /////////////////////CAN串行总线 bit 流处理 ////////////////////////
// CanBits 可以在CAN总线上传输的bit流 // CanBits 可以在CAN总线上传输的bit流
@ -199,42 +201,55 @@ const (
///////////////////// CRC //////////////////////// ///////////////////// CRC ////////////////////////
const ( // const (
CAN_CRC16_ATPREQ = 0x11021 // CAN_CRC16_ATPREQ = 0x11021
CAN_CRC32 = 0x04C11DB7 // CAN_CRC32 = 0x04C11DB7
) // )
var ( var (
crc16AtpReqTable []uint32 = nil CAN_CRC16 = crc.CCITT
crc32CanTable []uint32 = nil CAN_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x4A503DF1, Init: 0x00FF0000, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFF}
) )
func CreateCanCrcTable() { func Can_Crc16(data []byte) uint16 {
if crc16AtpReqTable == nil { return uint16(crc.CalculateCRC(CAN_CRC16, data))
crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false)
}
if crc32CanTable == nil {
crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false)
}
}
func calculateAtpReqCrc16(data []byte) uint16 {
crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable)
return uint16(crc)
}
func calculateCanCrc32(data []byte) uint32 {
crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable)
return crc
} }
// CRC32A的校验范围是报文+时间戳A func Can_Crc32(data []byte) uint32 {
func calculateDataRspCrc32A(data []byte) uint32 { return uint32(crc.CalculateCRC(CAN_CRC32, data))
return calculateCanCrc32(data)
} }
// CRC32B的校验范围是报文+时间戳B // var (
func calculateDataRspCrc32B(data []byte) uint32 { // crc16AtpReqTable []uint32 = nil
return calculateCanCrc32(data) // crc32CanTable []uint32 = nil
} // )
func calculateDataRspCrc32C(data []byte) uint32 {
return calculateCanCrc32(data) // func CreateCanCrcTable() {
} // if crc16AtpReqTable == nil {
// crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false)
// }
// if crc32CanTable == nil {
// crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false)
// }
// }
// func calculateAtpReqCrc16(data []byte) uint16 {
// crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable)
// return uint16(crc)
// }
// func calculateCanCrc32(data []byte) uint32 {
// crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable)
// return crc
// }
// // CRC32A的校验范围是报文+时间戳A
// func calculateDataRspCrc32A(data []byte) uint32 {
// return calculateCanCrc32(data)
// }
// // CRC32B的校验范围是报文+时间戳B
// func calculateDataRspCrc32B(data []byte) uint32 {
// return calculateCanCrc32(data)
// }
// func calculateDataRspCrc32C(data []byte) uint32 {
// return calculateCanCrc32(data)
// }

172
third_party/message/radar.go vendored Normal file
View File

@ -0,0 +1,172 @@
package message
import (
"bytes"
"encoding/binary"
"fmt"
"strings"
)
const (
radar_head1 byte = 0x0C
radar_head2 byte = 0xFC
)
// 雷达与VOBC接口-雷达通讯协议
type Radar struct {
AutoInc byte //自增计数器每发送一次自增1.范围0-256
RealSpeed *RadarData //实际速度
DriftCounterS1 *RadarData //位移计数器S1
DriftCounterS2 *RadarData //位移计数器S1
InnerCheck1 byte //内部使用,我们只有在协议效验时用到该两个字节
InnerCheck2 byte //内部使用,我们只有在协议效验时用到该两个字节
State *RadarState
Tail byte
}
type RadarData struct {
SourceData byte
valRange byte
}
type RadarState struct {
SourceState byte
Model string
SyntheticalState string
DirState string
Dir string
}
func (r *Radar) Decode(data []byte) error {
if len(data) < 13 {
return fmt.Errorf("雷达数据预读取失败需要读取13字节可读取:%v", len(data))
}
buf := bytes.NewBuffer(data)
_, _, err := readHeader(buf)
if err != nil {
return err
}
autoInc := readByteData(buf)
speed := readSpeedOrCounter(buf)
s1 := readSpeedOrCounter(buf)
s2 := readSpeedOrCounter(buf)
i1, i2 := readRadarInnerData(buf)
state := readRadarState(buf)
tail := readByteData(buf)
r.AutoInc = autoInc
r.RealSpeed = speed
r.DriftCounterS1 = s1
r.DriftCounterS2 = s2
r.InnerCheck1 = i1
r.InnerCheck2 = i2
r.State = state
r.Tail = tail
if !r.checkTail() {
return fmt.Errorf("数据解析完成,但协议效验不通过")
}
state.parseState()
return nil
}
func (rd *RadarData) getSumVal() byte {
return rd.SourceData + rd.valRange
}
func (s *RadarState) parseState() {
//第6位 == SW_Mode0, 第7位 == SW_Mode1
// 11:两个天线和双通道都OK
// 10DRS05_Single-Mode 40度,50度的天线或通道故障
// 01DRS05_Single-Mode 50度,40度的天线或通道故障
// 00错误模式 双侧天线或通道都故障
// 模式的工作差别工作在11.模式时效果最好。单模式10或01时可信度下降。
arr := s.getBitsStateArr()
s.Model = bitStateStr(arr[6:])
// 第3位=计算状态位,第4位=信号质量标志位,第5位=Black5out标志位
// 110计算状态高质量
// 地面信号反射良好,高精度的信号计算
// 100 计算状态,低质量
// 地面信号反射一般,信号计算可能会有缺陷
// 001 处于Blackout 状态
// 车辆行驶时无地面反射信号,无法进行信号计算
// 000 信号搜寻状态
// 在整个频率范围内搜寻多普勒信号,此时的速度和位移信息无效,当频率搜寻正确后,会转为计算模式。
s.SyntheticalState = bitStateStr(arr[3:6])
// 第1位 =方向状态
// 1行驶方向有效
// 0行驶方向无效
s.DirState = bitStateStr(arr[1:2])
// 第0位 =行驶方向
// 1前向
// 0反向
s.Dir = bitStateStr(arr[0:1])
}
func (s *RadarState) getBitsStateArr() []byte {
bits := make([]byte, 8)
for i := 0; i < 8; i++ {
bit := s.SourceState >> uint(i) & 1
bits[i] = bit
}
return bits
}
func bitStateStr(data []byte) string {
var build = strings.Builder{}
for _, d := range data {
build.WriteString(fmt.Sprintf("%v", d))
}
return build.String()
}
func (r *Radar) checkTail() bool {
var sum = int(radar_head1) + int(radar_head2) + int(r.AutoInc+r.RealSpeed.getSumVal()+r.DriftCounterS1.getSumVal()+r.DriftCounterS2.getSumVal()+r.InnerCheck1+r.InnerCheck2+r.State.SourceState)
return r.Tail == byte(^sum+1)
}
func readHeader(buf *bytes.Buffer) (byte, byte, error) {
/*if buf.Len() < 2 {
return 0, 0, fmt.Errorf("雷达协议解析头部没有可读充足的数据")
}*/
d1, _ := buf.ReadByte()
d2, _ := buf.ReadByte()
if d1 == radar_head1 && d2 == radar_head2 {
return d1, d2, nil
}
return 0, 0, fmt.Errorf("雷达协议解析头部未找到对应的头部帧")
}
func readByteData(buf *bytes.Buffer) byte {
/* if buf.Len() < 1 {
return 0, fmt.Errorf("")
}*/
d, _ := buf.ReadByte()
return d
}
func readSpeedOrCounter(buf *bytes.Buffer) *RadarData {
/* if buf.Len() < 2 {
return nil, fmt.Errorf("")
}*/
ss, _ := buf.ReadByte()
limit, _ := buf.ReadByte()
return &RadarData{SourceData: ss, valRange: limit}
}
func readRadarInnerData(buf *bytes.Buffer) (byte, byte) {
/*if buf.Len() < 2 {
return 0, 0, fmt.Errorf("")
}*/
i1, _ := buf.ReadByte()
i2, _ := buf.ReadByte()
return i1, i2
}
func readRadarState(buf *bytes.Buffer) *RadarState {
/*if buf.Len() < 1 {
return nil, fmt.Errorf("")
}*/
state, _ := buf.ReadByte()
return &RadarState{SourceState: state}
}
func driftCounter(buf *bytes.Buffer) (uint16, error) {
if buf.Len() < 2 {
return 0, fmt.Errorf("")
}
var driftCounter uint16
binary.Read(buf, binary.LittleEndian, &driftCounter)
return driftCounter, nil
}

View File

@ -62,7 +62,7 @@ func RsspPackCrc16Check(pack []byte) bool {
} }
// //
pack16 := binary.LittleEndian.Uint16(pack[len(pack)-2:]) pack16 := binary.LittleEndian.Uint16(pack[len(pack)-2:])
crc16 := RsspCrc16(pack[:len(pack)-2]) crc16 := Rssp_I_Crc16(pack[:len(pack)-2])
// //
return crc16 == pack16 return crc16 == pack16
} }
@ -104,7 +104,7 @@ func (r *RsspRsd) Encode() []byte {
//用户数据包 //用户数据包
data = append(data, r.Sad...) data = append(data, r.Sad...)
//报文尾-CRC16 //报文尾-CRC16
r.Crc16 = RsspCrc16(data) r.Crc16 = Rssp_I_Crc16(data)
data = binary.LittleEndian.AppendUint16(data, r.Crc16) data = binary.LittleEndian.AppendUint16(data, r.Crc16)
// //
return data return data
@ -156,7 +156,7 @@ func (r *RsspSse) Encode() []byte {
data = binary.LittleEndian.AppendUint32(data, r.SeqEnq1) data = binary.LittleEndian.AppendUint32(data, r.SeqEnq1)
data = binary.LittleEndian.AppendUint32(data, r.SeqEnq2) data = binary.LittleEndian.AppendUint32(data, r.SeqEnq2)
//报文尾-CRC16 //报文尾-CRC16
r.Crc16 = RsspCrc16(data) r.Crc16 = Rssp_I_Crc16(data)
data = binary.LittleEndian.AppendUint16(data, r.Crc16) data = binary.LittleEndian.AppendUint16(data, r.Crc16)
return data return data
} }
@ -207,7 +207,7 @@ func (r *RsspSsr) Encode() []byte {
data = binary.LittleEndian.AppendUint32(data, r.Tic2) data = binary.LittleEndian.AppendUint32(data, r.Tic2)
data = append(data, r.Dvn) data = append(data, r.Dvn)
//报文尾-CRC16 //报文尾-CRC16
r.Crc16 = RsspCrc16(data) r.Crc16 = Rssp_I_Crc16(data)
data = binary.LittleEndian.AppendUint16(data, r.Crc16) data = binary.LittleEndian.AppendUint16(data, r.Crc16)
return data return data
} }

View File

@ -1,206 +1,233 @@
package message package message
import "github.com/snksoft/crc"
//rssp 协议中crc校验查表法实现 //rssp 协议中crc校验查表法实现
// Crc16Table G(x)=X16+X11+X4+1计算初始值为0 // // Crc16Table G(x)=X16+X11+X4+1计算初始值为0
var crc16Table []uint32 = nil // var crc16Table []uint32 = nil
var crc32C1Table []uint32 = nil // var crc32C1Table []uint32 = nil
var crc32C2Table []uint32 = nil // var crc32C2Table []uint32 = nil
const ( //CRC生成多项式
RsspCrc16GX uint32 = 0b1_0000_1000_0001_0001 //生成多项式 G(X)=X16+X11+X4+1
RsspCrc32C1 uint32 = 0x100d4e63 //安全通道1 CRC32生成多项式
RsspCrc32C2 uint32 = 0x8ce56011 //安全通道1 CRC32生成多项式
)
const ( //时间戳生成多项式
RsspTsC1 uint32 = 0x0fc22f87
RsspTsC2 uint32 = 0xc3e887e1
)
const ( const (
SCW_C1 = uint32(0xae390b5a) //SCW常 // SCW常量
SCW_C2 = uint32(0xc103589c) //SCW常 RSSP_I_C1_SCW uint32 = 0xae390b5a
RSSP_I_C2_SCW uint32 = 0xc103589c
//时间戳生成多项式
RSSP_I_C1_TS uint32 = 0x0fc22f87
RSSP_I_C2_TS uint32 = 0xc3e887e1
) )
// InitRsspCrcTable 初始化RSSP协议中需要的CRC表 var (
func InitRsspCrcTable() { // crc16多项式为G(x)=X16+X11+X4+1
if crc16Table == nil { RSSP_I_CRC16 = &crc.Parameters{Width: 16, Polynomial: 0x0811, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0}
crc16Table = CreateCrcTable(RsspCrc16GX, 16, false) // 通道1 crc32多项式为0x100d4e63
} RSSP_I_C1_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x100d4e63, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0}
if crc32C1Table == nil { // 通道2 crc32多项式为0x8ce56011
crc32C1Table = CreateCrcTable(RsspCrc32C1, 32, false) RSSP_I_C2_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x8ce56011, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0}
} )
if crc32C2Table == nil {
crc32C2Table = CreateCrcTable(RsspCrc32C2, 32, false) // Rssp_I_Crc16计算
} func Rssp_I_Crc16(data []byte) uint16 {
} return uint16(crc.CalculateCRC(RSSP_I_CRC16, data))
func RsspCrc16(data []byte) uint16 {
return uint16(CrcTableBased(data, 16, 0, false, false, 0, crc16Table))
}
func RsspC1Crc32(data []byte) uint32 {
return CrcTableBased(data, 32, 0, false, false, 0, crc32C1Table)
}
func RsspC2Crc32(data []byte) uint32 {
return CrcTableBased(data, 32, 0, false, false, 0, crc32C2Table)
} }
// CreateCrcTable 创建CRC表支持8、16、32位 // 通道1的crc32
func CreateCrcTable(polynomial uint32, width int, input_reflected bool) []uint32 { func Rssp_I_Crc32C1(data []byte) uint32 {
var table = make([]uint32, 0, 256) return uint32(crc.CalculateCRC(RSSP_I_C1_CRC32, data))
for bt := 0x00; bt <= 0xff; bt++ {
table = append(table, lookup(uint32(bt), polynomial, width, input_reflected))
}
return table
} }
// 通道2的crc32
func Rssp_I_Crc32C2(data []byte) uint32 {
return uint32(crc.CalculateCRC(RSSP_I_C2_CRC32, data))
}
// const ( //CRC生成多项式
// RsspCrc16GX uint32 = 0b1_0000_1000_0001_0001 //生成多项式 G(X)=X16+X11+X4+1
// RsspCrc32C1 uint32 = 0x100d4e63 //安全通道1 CRC32生成多项式
// RsspCrc32C2 uint32 = 0x8ce56011 //安全通道1 CRC32生成多项式
// )
// // InitRsspCrcTable 初始化RSSP协议中需要的CRC表
// func InitRsspCrcTable() {
// if crc16Table == nil {
// crc16Table = CreateCrcTable(RsspCrc16GX, 16, false)
// }
// if crc32C1Table == nil {
// crc32C1Table = CreateCrcTable(RsspCrc32C1, 32, false)
// }
// if crc32C2Table == nil {
// crc32C2Table = CreateCrcTable(RsspCrc32C2, 32, false)
// }
// }
// func RsspCrc16(data []byte) uint16 {
// return uint16(CrcTableBased(data, 16, 0, false, false, 0, crc16Table))
// }
// func RsspC1Crc32(data []byte) uint32 {
// return CrcTableBased(data, 32, 0, false, false, 0, crc32C1Table)
// }
// func RsspC2Crc32(data []byte) uint32 {
// return CrcTableBased(data, 32, 0, false, false, 0, crc32C2Table)
// }
// // CreateCrcTable 创建CRC表支持8、16、32位
// func CreateCrcTable(polynomial uint32, width int, input_reflected bool) []uint32 {
// var table = make([]uint32, 0, 256)
// for bt := 0x00; bt <= 0xff; bt++ {
// table = append(table, lookup(uint32(bt), polynomial, width, input_reflected))
// }
// return table
// }
///////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////
// 反转(0b00001010->0b01010000) // // 反转(0b00001010->0b01010000)
func reflect(data uint32, width int) uint32 { // func reflect(data uint32, width int) uint32 {
var register1 uint32 = 0 // var register1 uint32 = 0
var significant_mask uint32 = 0xffffffff >> (32 - width) // var significant_mask uint32 = 0xffffffff >> (32 - width)
var register_msb_mask uint32 = 1 << (width - 1) // var register_msb_mask uint32 = 1 << (width - 1)
var register_lsb_mask uint32 = 1 // var register_lsb_mask uint32 = 1
for i := 0; i < width; i++ { // for i := 0; i < width; i++ {
need_or := (data>>i)&register_lsb_mask == register_lsb_mask // need_or := (data>>i)&register_lsb_mask == register_lsb_mask
if need_or { // if need_or {
register1 |= register_msb_mask >> i // register1 |= register_msb_mask >> i
} // }
} // }
return register1 & significant_mask // return register1 & significant_mask
} // }
// 计算单个数值的crc // // 计算单个数值的crc
func lookup(data uint32, // func lookup(data uint32,
polynomial uint32, // polynomial uint32,
width int, // width int,
input_reflected bool) uint32 { // input_reflected bool) uint32 {
var register1 uint32 = 0 // var register1 uint32 = 0
var significant_mask uint32 = 0xffffffff >> (32 - width) // var significant_mask uint32 = 0xffffffff >> (32 - width)
var register_msb_mask uint32 = 1 << (width - 1) // var register_msb_mask uint32 = 1 << (width - 1)
var register_lsb_mask uint32 = 1 // var register_lsb_mask uint32 = 1
var byte_msb_mask uint32 = 0x80 // var byte_msb_mask uint32 = 0x80
var byte_lsb_mask uint32 = 1 // var byte_lsb_mask uint32 = 1
if input_reflected { // if input_reflected {
polynomial = reflect(polynomial, width) // polynomial = reflect(polynomial, width)
} // }
for i := 0; i < 1+(width/8); i++ { // for i := 0; i < 1+(width/8); i++ {
var byteData uint32 = 0 // var byteData uint32 = 0
if i < 1 { // if i < 1 {
byteData = data // byteData = data
} // }
for j := 0; j < 8; j++ { // for j := 0; j < 8; j++ {
need_xor := false // need_xor := false
if input_reflected { // if input_reflected {
need_xor = (register1 & register_lsb_mask) == register_lsb_mask // need_xor = (register1 & register_lsb_mask) == register_lsb_mask
register1 >>= 1 // register1 >>= 1
need_or := (byteData & byte_lsb_mask) == byte_lsb_mask // need_or := (byteData & byte_lsb_mask) == byte_lsb_mask
byteData >>= 1 // byteData >>= 1
if need_or { // if need_or {
register1 |= register_msb_mask // register1 |= register_msb_mask
} // }
} else { // } else {
need_xor = (register1 & register_msb_mask) == register_msb_mask // need_xor = (register1 & register_msb_mask) == register_msb_mask
register1 <<= 1 // register1 <<= 1
need_or := (byteData & byte_msb_mask) == byte_msb_mask // need_or := (byteData & byte_msb_mask) == byte_msb_mask
byteData <<= 1 // byteData <<= 1
if need_or { // if need_or {
register1 |= register_lsb_mask // register1 |= register_lsb_mask
} // }
} // }
if need_xor { // if need_xor {
register1 ^= polynomial // register1 ^= polynomial
} // }
} // }
} // }
return register1 & significant_mask // return register1 & significant_mask
} // }
// CrcTableBased 查表法计算字节数组的crc // // CrcTableBased 查表法计算字节数组的crc
func CrcTableBased( // func CrcTableBased(
data []byte, // data []byte,
width int, // width int,
initial_value uint32, // initial_value uint32,
input_reflected bool, // input_reflected bool,
result_reflected bool, // result_reflected bool,
final_xor_value uint32, // final_xor_value uint32,
table []uint32) uint32 { // table []uint32) uint32 {
// // //
length := len(data) // length := len(data)
var register1 uint32 = initial_value // var register1 uint32 = initial_value
var significant_mask uint32 = 0xffffffff >> (32 - width) // var significant_mask uint32 = 0xffffffff >> (32 - width)
var register_lsb_mask uint32 = 0xff // var register_lsb_mask uint32 = 0xff
if input_reflected { // if input_reflected {
register1 = reflect(register1, width) // register1 = reflect(register1, width)
} // }
for i := 0; i < length; i++ { // for i := 0; i < length; i++ {
var byteData = uint32(data[i]) // var byteData = uint32(data[i])
var shift_out uint32 = 0 // var shift_out uint32 = 0
if input_reflected { // if input_reflected {
shift_out = register1 & register_lsb_mask // shift_out = register1 & register_lsb_mask
register1 = (register1 >> 8) ^ table[shift_out^byteData] // register1 = (register1 >> 8) ^ table[shift_out^byteData]
} else { // } else {
shift_out = (register1 >> (width - 8)) & register_lsb_mask // shift_out = (register1 >> (width - 8)) & register_lsb_mask
register1 = (register1 << 8) ^ table[shift_out^byteData] // register1 = (register1 << 8) ^ table[shift_out^byteData]
} // }
} // }
if input_reflected != result_reflected { // if input_reflected != result_reflected {
register1 = reflect(register1, width) // register1 = reflect(register1, width)
} // }
return (register1 ^ final_xor_value) & significant_mask // return (register1 ^ final_xor_value) & significant_mask
} // }
func Crc(data []byte, // func Crc(data []byte,
polynomial uint32, // polynomial uint32,
width int, // width int,
initial_value uint32, // initial_value uint32,
input_reflected bool, // input_reflected bool,
result_reflected bool, // result_reflected bool,
final_xor_value uint32) uint32 { // final_xor_value uint32) uint32 {
length := len(data) // length := len(data)
var register1 uint32 = initial_value // var register1 uint32 = initial_value
var significant_mask uint32 = 0xffffffff >> (32 - width) // var significant_mask uint32 = 0xffffffff >> (32 - width)
var register_lsb_mask uint32 = 0xff // var register_lsb_mask uint32 = 0xff
if input_reflected { // if input_reflected {
register1 = reflect(register1, width) // register1 = reflect(register1, width)
} // }
for i := 0; i < length; i++ { // for i := 0; i < length; i++ {
var byteData uint32 = uint32(data[i]) // var byteData uint32 = uint32(data[i])
var shift_out uint32 = 0 // var shift_out uint32 = 0
var value uint32 = 0 // var value uint32 = 0
if input_reflected { // if input_reflected {
shift_out = register1 & register_lsb_mask // shift_out = register1 & register_lsb_mask
value = lookup(shift_out^byteData, polynomial, width, input_reflected) // value = lookup(shift_out^byteData, polynomial, width, input_reflected)
register1 = (register1 >> 8) ^ value // register1 = (register1 >> 8) ^ value
} else { // } else {
shift_out = (register1 >> (width - 8)) & register_lsb_mask // shift_out = (register1 >> (width - 8)) & register_lsb_mask
value = lookup(shift_out^byteData, polynomial, width, input_reflected) // value = lookup(shift_out^byteData, polynomial, width, input_reflected)
register1 = (register1 << 8) ^ value // register1 = (register1 << 8) ^ value
} // }
} // }
if input_reflected != result_reflected { // if input_reflected != result_reflected {
register1 = reflect(register1, width) // register1 = reflect(register1, width)
} // }
return (register1 ^ final_xor_value) & significant_mask // return (register1 ^ final_xor_value) & significant_mask
} // }
//////////////////////////LFSR////////////////////////////// //////////////////////////LFSR//////////////////////////////

View File

@ -2,15 +2,18 @@ package semi_physical_train
import ( import (
"fmt" "fmt"
"log/slog"
"sync" "sync"
"joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/message"
"joylink.club/bj-rtsts-server/third_party/tpapi"
"joylink.club/bj-rtsts-server/third_party/udp" "joylink.club/bj-rtsts-server/third_party/udp"
) )
// 半实物仿真列车通信接口 // 半实物仿真列车通信接口
type SemiPhysicalTrain interface { type SemiPhysicalTrain interface {
tpapi.ThirdPartyApiService
// 启动半实物仿真消息处理 // 启动半实物仿真消息处理
Start(manager SemiPhysicalMessageManager) Start(manager SemiPhysicalMessageManager)
// 停止半实物仿真消息处理 // 停止半实物仿真消息处理
@ -27,14 +30,19 @@ type SemiPhysicalMessageManager interface {
} }
type semiPhysicalTrainImpl struct { type semiPhysicalTrainImpl struct {
tpapi.ThirdPartyApiService
trainControlUdpServer udp.UdpServer trainControlUdpServer udp.UdpServer
trainSpeedInfoUdpClient udp.UdpClient trainSpeedInfoUdpClient udp.UdpClient
udpDelayRecorder *tpapi.UdpDelayRecorder
manager SemiPhysicalMessageManager manager SemiPhysicalMessageManager
runConfig *config.VobcConfig runConfig *config.VobcConfig
} }
func (s *semiPhysicalTrainImpl) handleTrainControlMsg(b []byte) { func (s *semiPhysicalTrainImpl) handleTrainControlMsg(b []byte) {
s.udpDelayRecorder.RecordInterval()
slog.Debug(fmt.Sprintf("半实物列车控制消息近期消息间隔: %v", s.udpDelayRecorder.GetIntervals()))
handler := s.manager handler := s.manager
if handler != nil { if handler != nil {
handler.HandleSemiPhysicalTrainControlMsg(b) handler.HandleSemiPhysicalTrainControlMsg(b)
@ -55,12 +63,14 @@ func (s *semiPhysicalTrainImpl) Start(manager SemiPhysicalMessageManager) {
// 初始化客户端、服务端 // 初始化客户端、服务端
s.initSemiPhysical() s.initSemiPhysical()
s.manager = manager s.manager = manager
s.UpdateState(tpapi.ThirdPartyState_Normal)
s.udpDelayRecorder.Start()
} }
func (s *semiPhysicalTrainImpl) Stop() { func (s *semiPhysicalTrainImpl) Stop() {
initMutex.Lock() initMutex.Lock()
defer initMutex.Unlock() defer initMutex.Unlock()
_default = nil s.udpDelayRecorder.Stop()
if s.trainControlUdpServer != nil { if s.trainControlUdpServer != nil {
s.trainControlUdpServer.Close() s.trainControlUdpServer.Close()
} }
@ -68,6 +78,7 @@ func (s *semiPhysicalTrainImpl) Stop() {
s.trainSpeedInfoUdpClient.Close() s.trainSpeedInfoUdpClient.Close()
} }
s.manager = nil s.manager = nil
s.UpdateState(tpapi.ThirdPartyState_Closed)
} }
func (s *semiPhysicalTrainImpl) SendTrainControlMessage(info *message.DynamicsTrainInfo) { func (s *semiPhysicalTrainImpl) SendTrainControlMessage(info *message.DynamicsTrainInfo) {
@ -85,11 +96,22 @@ func (s *semiPhysicalTrainImpl) initSemiPhysical() {
var _default SemiPhysicalTrain var _default SemiPhysicalTrain
var initMutex sync.Mutex var initMutex sync.Mutex
const Interval int = 20
func Default() SemiPhysicalTrain { func Default() SemiPhysicalTrain {
initMutex.Lock() initMutex.Lock()
defer initMutex.Unlock() defer initMutex.Unlock()
if _default == nil { if _default == nil {
_default = &semiPhysicalTrainImpl{} _default = &semiPhysicalTrainImpl{
ThirdPartyApiService: tpapi.NewThirdPartyApiService(),
udpDelayRecorder: tpapi.NewUdpDelayRecorder(Interval, func(err error) {
if err != nil {
_default.UpdateState(tpapi.ThirdPartyState_Broken)
} else {
_default.UpdateState(tpapi.ThirdPartyState_Normal)
}
}),
}
} }
return _default return _default
} }

View File

@ -1,8 +1,24 @@
package third_party package third_party
import "joylink.club/bj-rtsts-server/third_party/message" import (
"joylink.club/bj-rtsts-server/dto/state_proto"
"joylink.club/bj-rtsts-server/third_party/dynamics"
"joylink.club/bj-rtsts-server/third_party/tpapi"
)
func Init() { func GetRunningServiceStates(t state_proto.SimulationThirdPartyApiService_Type) *state_proto.SimulationThirdPartyApiService {
message.InitRsspCrcTable() ss := &state_proto.SimulationThirdPartyApiService{}
message.CreateCanCrcTable() switch dynamics.Default().State() {
case tpapi.ThirdPartyState_Normal:
ss.States = append(ss.States, &state_proto.SimulationThirdPartyApiServiceState{
Type: state_proto.SimulationThirdPartyApiService_Dynamics,
State: state_proto.SimulationThirdPartyApiService_Normal,
})
case tpapi.ThirdPartyState_Broken:
ss.States = append(ss.States, &state_proto.SimulationThirdPartyApiServiceState{
Type: state_proto.SimulationThirdPartyApiService_Dynamics,
State: state_proto.SimulationThirdPartyApiService_Error,
})
}
return ss
} }

144
third_party/tpapi/service.go vendored Normal file
View File

@ -0,0 +1,144 @@
package tpapi
import (
"context"
"fmt"
"sync"
"time"
)
type ThirdPartyApiServiceState uint32
const (
// 服务未启动
ThirdPartyState_Closed ThirdPartyApiServiceState = iota
// 服务正常
ThirdPartyState_Normal
// 服务异常
ThirdPartyState_Broken
)
// 第三方对接接口服务
type ThirdPartyApiService interface {
// 服务状态
State() ThirdPartyApiServiceState
// 更新状态
UpdateState(state ThirdPartyApiServiceState)
}
func NewThirdPartyApiService() ThirdPartyApiService {
return &thirdPartyApiService{
state: ThirdPartyState_Closed,
}
}
type thirdPartyApiService struct {
state ThirdPartyApiServiceState
}
func (s *thirdPartyApiService) UpdateState(state ThirdPartyApiServiceState) {
s.state = state
}
func (s *thirdPartyApiService) State() ThirdPartyApiServiceState {
return s.state
}
// UDP通信延时记录
type UdpDelayRecorder struct {
mu sync.Mutex
// 接收消息间隔,单位毫秒
interval int
// 上一次收到消息时刻
lastReceiedTime int64
// 近期收到消息时间间隔
intervals []int64
// 是否发生异常
err error
// 长时间未收到消息或恢复处理回调
handler func(err error)
cancelFunc func()
done chan struct{} // 服务协程退出信号
}
func NewUdpDelayRecorder(interval int, handler func(err error)) *UdpDelayRecorder {
return &UdpDelayRecorder{
interval: interval,
lastReceiedTime: 0,
handler: handler,
}
}
func (r *UdpDelayRecorder) Start() {
r.mu.Lock()
defer r.mu.Unlock()
r.lastReceiedTime = 0
r.err = nil
r.done = make(chan struct{})
ctx, cf := context.WithCancel(context.Background())
r.cancelFunc = cf
go r.checkTimeout(ctx)
}
func (r *UdpDelayRecorder) checkTimeout(ctx context.Context) {
defer close(r.done)
for {
select {
case <-ctx.Done():
return
default:
}
time.Sleep(time.Millisecond * time.Duration(r.interval*2))
lastReceiedTime := r.lastReceiedTime
interval := int(time.Now().UnixMilli() - lastReceiedTime)
if r.err == nil && interval > calUdpTimeout(r.interval) { // 超时故障回调
r.err = fmt.Errorf("UDP通信超时未收到消息,可能网络异常")
if r.handler != nil {
r.handler(r.err)
}
} else if r.err != nil && interval <= r.interval*3 { // 恢复正常回调
r.err = nil
if r.handler != nil {
r.handler(r.err)
}
}
}
}
func (r *UdpDelayRecorder) Stop() {
r.mu.Lock()
defer r.mu.Unlock()
r.cancelFunc()
<-r.done
r.lastReceiedTime = 0
r.err = nil
}
// 记录时间间隔
func (r *UdpDelayRecorder) RecordInterval() {
r.mu.Lock()
defer r.mu.Unlock()
// 记录时间及间隔
ts := time.Now().UnixMilli()
if r.lastReceiedTime > 0 {
r.intervals = append(r.intervals, ts-r.lastReceiedTime)
if len(r.intervals) > 10 {
r.intervals = r.intervals[1:]
}
}
r.lastReceiedTime = ts
}
func (r *UdpDelayRecorder) GetIntervals() []int64 {
return r.intervals
}
func calUdpTimeout(interval int) int {
if interval <= 50 {
return interval * 10
} else {
return interval * 5
}
}

View File

@ -1,6 +1,7 @@
package udp package udp
import ( import (
"context"
"log/slog" "log/slog"
"net" "net"
"runtime/debug" "runtime/debug"
@ -17,6 +18,7 @@ type server struct {
addr string addr string
conn *net.UDPConn conn *net.UDPConn
handler UdpMsgHandler handler UdpMsgHandler
cancelFn context.CancelFunc
} }
// NewServer creates a new instance of UdpServer. // NewServer creates a new instance of UdpServer.
@ -34,29 +36,37 @@ func (s *server) Listen() {
panic(err) panic(err)
} }
s.conn = conn s.conn = conn
ctx, cfn := context.WithCancel(context.Background())
// 启动监听处理 // 启动监听处理
go s.listenAndHandle() go s.listenAndHandle(ctx)
s.cancelFn = cfn
} }
func (s *server) Close() { func (s *server) Close() {
err := s.conn.Close() s.cancelFn()
if err != nil { // err := s.conn.Close()
slog.Error("udp server close error", "error", err) // if err != nil {
} // slog.Error("udp server close error", "error", err)
// }
} }
func (s *server) listenAndHandle() { func (s *server) listenAndHandle(ctx context.Context) {
defer s.conn.Close() defer s.conn.Close()
for { for {
b := make([]byte, 1024) select {
n, err := s.conn.Read(b) case <-ctx.Done():
if err != nil { slog.Info("udp server listen 关闭", "addr", s.addr)
slog.Error("udp server read error", err)
return return
default:
} }
if n > 0 { buf := make([]byte, 1024)
go s.handle(b[0:n]) n, _, err := s.conn.ReadFromUDP(buf)
if err != nil {
slog.Error("udp server read error", "addr", s.addr, "error", err)
continue
} }
// slog.Debug("udp server handle", "addr", ap.String())
go s.handle(buf[:n])
} }
} }

View File

@ -8,4 +8,5 @@ import (
var ( var (
PointsParamType = ecs.NewComponentType[request_proto.PointsParam]() PointsParamType = ecs.NewComponentType[request_proto.PointsParam]()
SignalParamType = ecs.NewComponentType[request_proto.SignalParam]() SignalParamType = ecs.NewComponentType[request_proto.SignalParam]()
SectionParamType = ecs.NewComponentType[request_proto.SectionParam]()
) )

View File

@ -1,36 +1,74 @@
package memory package memory
import ( import (
"log/slog" "fmt"
"unsafe"
"joylink.club/bj-rtsts-server/dto"
"joylink.club/bj-rtsts-server/dto/data_proto" "joylink.club/bj-rtsts-server/dto/data_proto"
"joylink.club/bj-rtsts-server/dto/request_proto" "joylink.club/bj-rtsts-server/dto/request_proto"
appcomponent "joylink.club/bj-rtsts-server/ts/simulation/app_component"
"joylink.club/ecs"
"joylink.club/rtsssimulation/fi" "joylink.club/rtsssimulation/fi"
) )
func ChangeAxleSectionState(simulation *VerifySimulation, req *dto.AxleSectionOperationReqDto) error { // 处理区段操作
sectionUid := QueryUidByMidAndComId(req.MapId, req.DeviceId, &data_proto.Section{}) func HandleSectionOperation(simulation *VerifySimulation, req *request_proto.SectionOperationReq) error {
slog.Debug("操作计轴区段", "axleSectionUid", sectionUid) uid := QueryUidByMidAndComId(req.MapId, req.DeviceId, &data_proto.Section{})
if req.TrainIn { // 区段操作
return fi.AxleSectionTrainDrive(simulation.World, sectionUid, true)
}
if req.TrainOut {
return fi.AxleSectionTrainDrive(simulation.World, sectionUid, false)
}
switch req.Operation { switch req.Operation {
case request_proto.Section_CancelDrst:
return fi.AxleSectionDrstDrive(simulation.World, sectionUid, false)
case request_proto.Section_SetDrst:
return fi.AxleSectionDrstDrive(simulation.World, sectionUid, true)
case request_proto.Section_CancelPdrst:
return fi.AxleSectionPdrstDrive(simulation.World, sectionUid, false)
case request_proto.Section_SetPdrst:
return fi.AxleSectionPdrstDrive(simulation.World, sectionUid, true)
case request_proto.Section_CancelFaultOcc:
return fi.AxleSectionFaultOccDrive(simulation.World, sectionUid, false)
case request_proto.Section_SetFaultOcc: case request_proto.Section_SetFaultOcc:
return fi.AxleSectionFaultOccDrive(simulation.World, sectionUid, true) return fi.AxleSectionFaultOccDrive(simulation.World, uid, true)
case request_proto.Section_SetParams:
var err error
setSectionParam(simulation.World, uid, req.Param)
if req.Param.MockDrst {
err = fi.AxleSectionDrstDrive(simulation.World, uid, true)
} else {
err = fi.AxleSectionDrstDrive(simulation.World, uid, false)
}
if err != nil {
return err
}
if req.Param.MockPdrst {
err = fi.AxleSectionPdrstDrive(simulation.World, uid, true)
} else {
err = fi.AxleSectionPdrstDrive(simulation.World, uid, false)
}
return err
default:
return fmt.Errorf("未知的区段操作:%s", req.Operation)
} }
return nil
} }
func setSectionParam(world ecs.World, uid string, sectionParam *request_proto.SectionParam) error {
return handleEntityState(world, uid, func(e *ecs.Entry) error {
e.AddComponent(appcomponent.SectionParamType, unsafe.Pointer(sectionParam))
return nil
})
}
// func ChangeAxleSectionState(simulation *VerifySimulation, req *dto.AxleSectionOperationReqDto) error {
// sectionUid := QueryUidByMidAndComId(req.MapId, req.DeviceId, &data_proto.Section{})
// slog.Debug("操作计轴区段", "axleSectionUid", sectionUid)
// if req.TrainIn {
// return fi.AxleSectionTrainDrive(simulation.World, sectionUid, true)
// }
// if req.TrainOut {
// return fi.AxleSectionTrainDrive(simulation.World, sectionUid, false)
// }
// switch req.Operation {
// case request_proto.Section_CancelDrst:
// return fi.AxleSectionDrstDrive(simulation.World, sectionUid, false)
// case request_proto.Section_SetDrst:
// return fi.AxleSectionDrstDrive(simulation.World, sectionUid, true)
// case request_proto.Section_CancelPdrst:
// return fi.AxleSectionPdrstDrive(simulation.World, sectionUid, false)
// case request_proto.Section_SetPdrst:
// return fi.AxleSectionPdrstDrive(simulation.World, sectionUid, true)
// case request_proto.Section_CancelFaultOcc:
// return fi.AxleSectionFaultOccDrive(simulation.World, sectionUid, false)
// case request_proto.Section_SetFaultOcc:
// return fi.AxleSectionFaultOccDrive(simulation.World, sectionUid, true)
// }
// return nil
// }

View File

@ -181,9 +181,7 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
func createOrUpdateStateDynamicConfig(trainState *state_proto.TrainState, configTrainData dto.ConfigTrainData, trainEndsA dto.ConfigTrainEnds, func createOrUpdateStateDynamicConfig(trainState *state_proto.TrainState, configTrainData dto.ConfigTrainData, trainEndsA dto.ConfigTrainEnds,
trainEndsB dto.ConfigTrainEnds) { trainEndsB dto.ConfigTrainEnds) {
trainState.TrainDynamicConfig = service.TrainConfigToProtoConvert(&configTrainData) trainState.TrainDynamicConfig = service.TrainConfigToProtoConvert(&configTrainData)
if trainState.TrainDynamicConfig == nil { if trainState.TrainDynamicConfig != nil {
slog.Error("")
} else {
copyTrainEnds(trainState, "TrainEndsA", trainEndsA) copyTrainEnds(trainState, "TrainEndsA", trainEndsA)
copyTrainEnds(trainState, "TrainEndsB", trainEndsB) copyTrainEnds(trainState, "TrainEndsB", trainEndsB)
} }