diff --git a/api/simulation.go b/api/simulation.go index 5a0cfd4..43b944a 100644 --- a/api/simulation.go +++ b/api/simulation.go @@ -372,15 +372,15 @@ func signalOperation(c *gin.Context) { // @Failure 500 {object} dto.ErrorDto // @Router /api/v1/simulation/axleSection/operation [post] func axleSectionOperation(c *gin.Context) { //操作:设置故障占用、取消故障占用 - req := &dto.AxleSectionOperationReqDto{} + req := &request_proto.SectionOperationReq{} if err := c.ShouldBind(&req); err != nil { panic(sys_error.New("输入参数格式错误", err)) } simulation := checkDeviceDataAndReturn(req.SimulationId) - slog.Info("传入状态参数", req) - err := memory.ChangeAxleSectionState(simulation, req) + slog.Info("传入状态参数", "req", req) + err := memory.HandleSectionOperation(simulation, req) if err != nil { - panic(sys_error.New("操作失败", err)) + panic(sys_error.New("区段操作失败", err)) } c.JSON(http.StatusOK, "ok") } diff --git a/bj-rtss-message b/bj-rtss-message index 3a30efc..bdd66d8 160000 --- a/bj-rtss-message +++ b/bj-rtss-message @@ -1 +1 @@ -Subproject commit 3a30efc9fe949cd5ab9898073f00a093716f279e +Subproject commit bdd66d8625e76afb23f501de306224d35a8958d1 diff --git a/dto/request_proto/request.pb.go b/dto/request_proto/request.pb.go index 7c42b56..736bf24 100644 --- a/dto/request_proto/request.pb.go +++ b/dto/request_proto/request.pb.go @@ -344,31 +344,26 @@ func (Signal_Force) EnumDescriptor() ([]byte, []int) { type Section_Operation int32 const ( - Section_SetDrst Section_Operation = 0 //设置计轴直接复位 - Section_CancelDrst Section_Operation = 1 //取消计轴直接复位 - Section_SetPdrst Section_Operation = 2 //设置计轴预复位 - Section_CancelPdrst Section_Operation = 3 //取消计轴预复位 - Section_SetFaultOcc Section_Operation = 4 //设置故障占用 - Section_CancelFaultOcc Section_Operation = 5 //取消故障占用 + Section_Undefined Section_Operation = 0 // 未定义 + Section_SetParams Section_Operation = 1 // 设置参数 + // SetDrst = 0;//设置计轴直接复位 + // CancelDrst = 1;//取消计轴直接复位 + // SetPdrst = 2;//设置计轴预复位 + // CancelPdrst = 3;//取消计轴预复位 + Section_SetFaultOcc Section_Operation = 4 //设置故障占用 ) // Enum value maps for Section_Operation. var ( Section_Operation_name = map[int32]string{ - 0: "SetDrst", - 1: "CancelDrst", - 2: "SetPdrst", - 3: "CancelPdrst", + 0: "Undefined", + 1: "SetParams", 4: "SetFaultOcc", - 5: "CancelFaultOcc", } Section_Operation_value = map[string]int32{ - "SetDrst": 0, - "CancelDrst": 1, - "SetPdrst": 2, - "CancelPdrst": 3, - "SetFaultOcc": 4, - "CancelFaultOcc": 5, + "Undefined": 0, + "SetParams": 1, + "SetFaultOcc": 4, } ) @@ -497,7 +492,7 @@ func (x Psd_Operation) Number() protoreflect.EnumNumber { // Deprecated: Use Psd_Operation.Descriptor instead. 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} } +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 { state protoimpl.MessageState @@ -1000,7 +1130,7 @@ type Psd struct { func (x *Psd) Reset() { *x = Psd{} if protoimpl.UnsafeEnabled { - mi := &file_request_proto_msgTypes[9] + mi := &file_request_proto_msgTypes[11] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1013,7 +1143,7 @@ func (x *Psd) String() string { func (*Psd) ProtoMessage() {} func (x *Psd) ProtoReflect() protoreflect.Message { - mi := &file_request_proto_msgTypes[9] + mi := &file_request_proto_msgTypes[11] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1026,7 +1156,7 @@ func (x *Psd) ProtoReflect() protoreflect.Message { // Deprecated: Use Psd.ProtoReflect.Descriptor instead. 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() { *x = PsdOperationReq{} if protoimpl.UnsafeEnabled { - mi := &file_request_proto_msgTypes[10] + mi := &file_request_proto_msgTypes[12] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -1059,7 +1189,7 @@ func (x *PsdOperationReq) String() string { func (*PsdOperationReq) ProtoMessage() {} func (x *PsdOperationReq) ProtoReflect() protoreflect.Message { - mi := &file_request_proto_msgTypes[10] + mi := &file_request_proto_msgTypes[12] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -1072,7 +1202,7 @@ func (x *PsdOperationReq) ProtoReflect() protoreflect.Message { // Deprecated: Use PsdOperationReq.ProtoReflect.Descriptor instead. func (*PsdOperationReq) Descriptor() ([]byte, []int) { - return file_request_proto_rawDescGZIP(), []int{10} + return file_request_proto_rawDescGZIP(), []int{12} } 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, 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, - 0x2e, 0x44, 0x53, 0x52, 0x06, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x77, 0x0a, 0x07, 0x53, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x6c, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x0b, 0x0a, 0x07, 0x53, 0x65, 0x74, 0x44, 0x72, 0x73, 0x74, 0x10, 0x00, - 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x44, 0x72, 0x73, 0x74, 0x10, 0x01, - 0x12, 0x0c, 0x0a, 0x08, 0x53, 0x65, 0x74, 0x50, 0x64, 0x72, 0x73, 0x74, 0x10, 0x02, 0x12, 0x0f, - 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x50, 0x64, 0x72, 0x73, 0x74, 0x10, 0x03, 0x12, - 0x0f, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4f, 0x63, 0x63, 0x10, 0x04, - 0x12, 0x12, 0x0a, 0x0e, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4f, - 0x63, 0x63, 0x10, 0x05, 0x22, 0x87, 0x02, 0x0a, 0x03, 0x50, 0x73, 0x64, 0x22, 0xff, 0x01, 0x0a, - 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e, - 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4b, 0x6d, 0x10, - 0x01, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4b, 0x6d, 0x10, 0x02, 0x12, - 0x06, 0x0a, 0x02, 0x47, 0x6d, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, - 0x6c, 0x47, 0x6d, 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4b, 0x6d, - 0x10, 0x05, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x47, 0x6d, 0x10, 0x06, 0x12, - 0x0f, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x10, 0x0a, - 0x12, 0x11, 0x0a, 0x0d, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, - 0x6e, 0x10, 0x0b, 0x12, 0x17, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, - 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x10, 0x0c, 0x12, 0x12, 0x0a, 0x0e, - 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0d, - 0x12, 0x18, 0x0a, 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, - 0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0e, 0x12, 0x08, 0x0a, 0x04, 0x51, 0x44, - 0x54, 0x43, 0x10, 0x0f, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x51, 0x44, - 0x54, 0x43, 0x10, 0x10, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x11, 0x12, 0x0e, - 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x12, 0x22, 0xcf, - 0x01, 0x0a, 0x0f, 0x50, 0x73, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, - 0x65, 0x71, 0x12, 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, + 0x2e, 0x44, 0x53, 0x52, 0x06, 0x64, 0x73, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x45, 0x0a, 0x07, 0x53, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x3a, 0x0a, 0x09, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e, 0x64, 0x65, 0x66, 0x69, 0x6e, 0x65, 0x64, + 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x53, 0x65, 0x74, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x73, 0x10, + 0x01, 0x12, 0x0f, 0x0a, 0x0b, 0x53, 0x65, 0x74, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x4f, 0x63, 0x63, + 0x10, 0x04, 0x22, 0xd2, 0x01, 0x0a, 0x13, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 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, 0x38, 0x0a, 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x1a, 0x2e, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x53, 0x65, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x2e, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x09, 0x6f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x2b, 0x0a, 0x05, 0x70, 0x61, + 0x72, 0x61, 0x6d, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x72, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x53, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, + 0x52, 0x05, 0x70, 0x61, 0x72, 0x61, 0x6d, 0x22, 0x48, 0x0a, 0x0c, 0x53, 0x65, 0x63, 0x74, 0x69, + 0x6f, 0x6e, 0x50, 0x61, 0x72, 0x61, 0x6d, 0x12, 0x1a, 0x0a, 0x08, 0x6d, 0x6f, 0x63, 0x6b, 0x44, + 0x72, 0x73, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x6d, 0x6f, 0x63, 0x6b, 0x44, + 0x72, 0x73, 0x74, 0x12, 0x1c, 0x0a, 0x09, 0x6d, 0x6f, 0x63, 0x6b, 0x50, 0x64, 0x72, 0x73, 0x74, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x6d, 0x6f, 0x63, 0x6b, 0x50, 0x64, 0x72, 0x73, + 0x74, 0x22, 0x87, 0x02, 0x0a, 0x03, 0x50, 0x73, 0x64, 0x22, 0xff, 0x01, 0x0a, 0x09, 0x4f, 0x70, + 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x6e, 0x64, 0x65, 0x66, + 0x69, 0x6e, 0x65, 0x64, 0x10, 0x00, 0x12, 0x06, 0x0a, 0x02, 0x4b, 0x6d, 0x10, 0x01, 0x12, 0x0c, + 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x4b, 0x6d, 0x10, 0x02, 0x12, 0x06, 0x0a, 0x02, + 0x47, 0x6d, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x47, 0x6d, + 0x10, 0x04, 0x12, 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4b, 0x6d, 0x10, 0x05, 0x12, + 0x0b, 0x0a, 0x07, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x47, 0x6d, 0x10, 0x06, 0x12, 0x0f, 0x0a, 0x0b, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x10, 0x0a, 0x12, 0x11, 0x0a, + 0x0d, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x10, 0x0b, + 0x12, 0x17, 0x0a, 0x13, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, + 0x6e, 0x6f, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x10, 0x0c, 0x12, 0x12, 0x0a, 0x0e, 0x41, 0x73, 0x64, + 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0d, 0x12, 0x18, 0x0a, + 0x14, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x41, 0x73, 0x64, 0x43, 0x61, 0x6e, 0x6e, 0x6f, 0x74, + 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x10, 0x0e, 0x12, 0x08, 0x0a, 0x04, 0x51, 0x44, 0x54, 0x43, 0x10, + 0x0f, 0x12, 0x0e, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x51, 0x44, 0x54, 0x43, 0x10, + 0x10, 0x12, 0x08, 0x0a, 0x04, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x11, 0x12, 0x0e, 0x0a, 0x0a, 0x43, + 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x54, 0x5a, 0x54, 0x43, 0x10, 0x12, 0x22, 0xcf, 0x01, 0x0a, 0x0f, + 0x50, 0x73, 0x64, 0x4f, 0x70, 0x65, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, + 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 ( @@ -1250,27 +1395,29 @@ func file_request_proto_rawDescGZIP() []byte { } 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{}{ - (Relay_Operation)(0), // 0: request.Relay.Operation - (Points_Operation)(0), // 1: request.Points.Operation - (Points_Force)(0), // 2: request.Points.Force - (Signal_Operation)(0), // 3: request.Signal.Operation - (Signal_DS)(0), // 4: request.Signal.DS - (Signal_Force)(0), // 5: request.Signal.Force - (Section_Operation)(0), // 6: request.Section.Operation - (Psd_Operation)(0), // 7: request.Psd.Operation - (*Relay)(nil), // 8: request.Relay - (*RelayOperationReq)(nil), // 9: request.RelayOperationReq - (*Points)(nil), // 10: request.Points - (*PointsOperationReq)(nil), // 11: request.PointsOperationReq - (*PointsParam)(nil), // 12: request.PointsParam - (*Signal)(nil), // 13: request.Signal - (*SignalOperationReq)(nil), // 14: request.SignalOperationReq - (*SignalParam)(nil), // 15: request.SignalParam - (*Section)(nil), // 16: request.Section - (*Psd)(nil), // 17: request.Psd - (*PsdOperationReq)(nil), // 18: request.PsdOperationReq + (Relay_Operation)(0), // 0: request.Relay.Operation + (Points_Operation)(0), // 1: request.Points.Operation + (Points_Force)(0), // 2: request.Points.Force + (Signal_Operation)(0), // 3: request.Signal.Operation + (Signal_DS)(0), // 4: request.Signal.DS + (Signal_Force)(0), // 5: request.Signal.Force + (Section_Operation)(0), // 6: request.Section.Operation + (Psd_Operation)(0), // 7: request.Psd.Operation + (*Relay)(nil), // 8: request.Relay + (*RelayOperationReq)(nil), // 9: request.RelayOperationReq + (*Points)(nil), // 10: request.Points + (*PointsOperationReq)(nil), // 11: request.PointsOperationReq + (*PointsParam)(nil), // 12: request.PointsParam + (*Signal)(nil), // 13: request.Signal + (*SignalOperationReq)(nil), // 14: request.SignalOperationReq + (*SignalParam)(nil), // 15: request.SignalParam + (*Section)(nil), // 16: request.Section + (*SectionOperationReq)(nil), // 17: request.SectionOperationReq + (*SectionParam)(nil), // 18: request.SectionParam + (*Psd)(nil), // 19: request.Psd + (*PsdOperationReq)(nil), // 20: request.PsdOperationReq } var file_request_proto_depIdxs = []int32{ 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 5, // 6: request.SignalParam.force:type_name -> request.Signal.Force 4, // 7: request.SignalParam.dsList:type_name -> request.Signal.DS - 7, // 8: request.PsdOperationReq.operation:type_name -> request.Psd.Operation - 9, // [9:9] is the sub-list for method output_type - 9, // [9:9] is the sub-list for method input_type - 9, // [9:9] is the sub-list for extension type_name - 9, // [9:9] is the sub-list for extension extendee - 0, // [0:9] is the sub-list for field type_name + 6, // 8: request.SectionOperationReq.operation:type_name -> request.Section.Operation + 18, // 9: request.SectionOperationReq.param:type_name -> request.SectionParam + 7, // 10: request.PsdOperationReq.operation:type_name -> request.Psd.Operation + 11, // [11:11] is the sub-list for method output_type + 11, // [11:11] is the sub-list for method input_type + 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() } @@ -1404,7 +1553,7 @@ func file_request_proto_init() { } } file_request_proto_msgTypes[9].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Psd); i { + switch v := v.(*SectionOperationReq); i { case 0: return &v.state case 1: @@ -1416,6 +1565,30 @@ func file_request_proto_init() { } } 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 { case 0: return &v.state @@ -1434,7 +1607,7 @@ func file_request_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_request_proto_rawDesc, NumEnums: 8, - NumMessages: 11, + NumMessages: 13, NumExtensions: 0, NumServices: 0, }, diff --git a/example/mock_train_service/main.go b/example/mock_train_service/main.go index d23571b..9a670e7 100644 --- a/example/mock_train_service/main.go +++ b/example/mock_train_service/main.go @@ -22,7 +22,7 @@ var ti = &ReceiveTrainInfo{ var trainRun bool 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() { listen, err := net.ListenUDP("udp", &net.UDPAddr{ diff --git a/go.mod b/go.mod index be46fca..7d2dd3d 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/golang/protobuf v1.5.3 github.com/google/uuid v1.4.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/stretchr/testify v1.8.4 github.com/swaggo/files v1.0.1 diff --git a/go.sum b/go.sum index 723b2b3..4a55a18 100644 --- a/go.sum +++ b/go.sum @@ -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/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/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/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= diff --git a/main.go b/main.go index adaa180..f41bdc5 100644 --- a/main.go +++ b/main.go @@ -10,8 +10,6 @@ import ( "joylink.club/bj-rtsts-server/docs" "joylink.club/bj-rtsts-server/middleware" "joylink.club/bj-rtsts-server/mqtt" - - "joylink.club/bj-rtsts-server/third_party" ) // @title CBTC测试系统API @@ -28,7 +26,6 @@ import ( func main() { engine := InitServer() 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() router := engine.Group("/api") api.InitUserRouter(router, authMiddleware) diff --git a/third_party/axle_device/rssp_channel.go b/third_party/axle_device/rssp_channel.go index cfcd442..1e0d8f9 100644 --- a/third_party/axle_device/rssp_channel.go +++ b/third_party/axle_device/rssp_channel.go @@ -2,10 +2,11 @@ package axle_device import ( "fmt" + "log/slog" + "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/third_party/message" "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.rsspTimer = &RsspTimer{t: 0} s.sn = message.NewRsspSn(1) - s.ch1Ts = message.NewRsspLFSR(message.RsspTsC1, 32, s.config.SID1, false) - s.ch2Ts = message.NewRsspLFSR(message.RsspTsC2, 32, s.config.SID2, false) + s.ch1Ts = message.NewRsspLFSR(message.RSSP_I_C1_TS, 32, s.config.SID1, false) + s.ch2Ts = message.NewRsspLFSR(message.RSSP_I_C2_TS, 32, s.config.SID2, false) return s } @@ -178,11 +179,11 @@ func (s *RsspChannel) handleRsspRsd(rsd *message.RsspRsd) { return } //SVC校验 - c1Crc32 := message.RsspC1Crc32(rsd.Sad) - c1SidTs := c1Crc32 ^ rsd.Svc1 ^ message.SCW_C1 //T(n) + c1Crc32 := message.Rssp_I_Crc32C1(rsd.Sad) + c1SidTs := c1Crc32 ^ rsd.Svc1 ^ message.RSSP_I_C1_SCW //T(n) // - c2Crc32 := message.RsspC2Crc32(rsd.Sad) - c2SidTs := c2Crc32 ^ rsd.Svc2 ^ message.SCW_C2 //T(n) + c2Crc32 := message.Rssp_I_Crc32C2(rsd.Sad) + c2SidTs := c2Crc32 ^ rsd.Svc2 ^ message.RSSP_I_C2_SCW //T(n) //todo ... SVC校验待完善 _ = c1SidTs _ = c2SidTs @@ -291,11 +292,11 @@ func (s *RsspChannel) SendUserData(userData []byte) { rsd.Sn = s.sn.Get() rsd.Sdl = uint16(len(userData) + 8) //安全校验通道SVC_1 - crc_c1 := message.RsspC1Crc32(userData) - rsd.Svc1 = s.createSvcCode(crc_c1, s.config.SID1, s.ch1Ts.Get(), message.SCW_C1) + crc_c1 := message.Rssp_I_Crc32C1(userData) + rsd.Svc1 = s.createSvcCode(crc_c1, s.config.SID1, s.ch1Ts.Get(), message.RSSP_I_C1_SCW) //安全校验通道SVC_2 - crc_c2 := message.RsspC2Crc32(userData) - rsd.Svc1 = s.createSvcCode(crc_c2, s.config.SID2, s.ch2Ts.Get(), message.SCW_C2) + crc_c2 := message.Rssp_I_Crc32C2(userData) + rsd.Svc1 = s.createSvcCode(crc_c2, s.config.SID2, s.ch2Ts.Get(), message.RSSP_I_C2_SCW) rsd.Sad = userData // rsspPack := rsd.Encode() diff --git a/third_party/dynamics/dynamics.go b/third_party/dynamics/dynamics.go index 2c3243d..42f3f32 100644 --- a/third_party/dynamics/dynamics.go +++ b/third_party/dynamics/dynamics.go @@ -14,6 +14,7 @@ import ( "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/sys_error" "joylink.club/bj-rtsts-server/third_party/message" + "joylink.club/bj-rtsts-server/third_party/tpapi" "joylink.club/bj-rtsts-server/third_party/udp" ) @@ -26,6 +27,7 @@ type DynamicsMessageManager interface { // 动力学接口 type Dynamics interface { + tpapi.ThirdPartyApiService // 请求添加列车 RequestAddTrain(info *message.InitTrainInfo) error // 请求移除列车 @@ -44,20 +46,34 @@ type Dynamics interface { var _default Dynamics var initMutex sync.Mutex +const Interval = 15 + func Default() Dynamics { initMutex.Lock() defer initMutex.Unlock() 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 } type dynamics struct { + tpapi.ThirdPartyApiService trainInfoUdpServer udp.UdpServer turnoutStateUdpClient udp.UdpClient trainControlUdpClient udp.UdpClient + udpDelayRecorder *tpapi.UdpDelayRecorder + baseUrl string httpClient *http.Client manager DynamicsMessageManager @@ -67,6 +83,7 @@ type dynamics struct { // 解码列车信息并处理 func (d *dynamics) handleDynamicsTrainInfo(b []byte) { + d.udpDelayRecorder.RecordInterval() trainInfo := &message.DynamicsTrainInfo{} err := trainInfo.Decode(b) if err != nil { @@ -176,10 +193,10 @@ func (d *dynamics) TrainOperationConfig(req *message.TrainOperationConfig) error data, _ := json.Marshal(req) url := d.buildUrl("/api/config") resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data)) - defer resp.Body.Close() if err != nil { return fmt.Errorf("动力学移除列车请求异常: %v", err) } + defer resp.Body.Close() var bodyData []byte _, err = resp.Body.Read(bodyData) if err != nil { @@ -210,6 +227,8 @@ func (d *dynamics) Start(manager DynamicsMessageManager) error { ctx, cancle := context.WithCancel(context.Background()) go d.sendTurnoutStateTask(ctx) d.turnoutTaskCancel = cancle + d.UpdateState(tpapi.ThirdPartyState_Normal) + d.udpDelayRecorder.Start() return nil } @@ -236,7 +255,8 @@ func (d *dynamics) initDynamicsRunRepository() error { func (d *dynamics) Stop() { initMutex.Lock() defer initMutex.Unlock() - _default = nil + // 停止网络监听 + d.udpDelayRecorder.Stop() if d.httpClient != nil { d.requestStopSimulation() d.httpClient = nil @@ -254,6 +274,7 @@ func (d *dynamics) Stop() { d.turnoutTaskCancel() } d.manager = nil + d.UpdateState(tpapi.ThirdPartyState_Closed) } const ( diff --git a/third_party/example/rssp/main.go b/third_party/example/rssp/main.go index 50d3b5c..fcf37d8 100644 --- a/third_party/example/rssp/main.go +++ b/third_party/example/rssp/main.go @@ -2,14 +2,15 @@ package main import ( "fmt" + "time" + "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/third_party/example/rssp/ci" "joylink.club/bj-rtsts-server/third_party/message" - "time" ) func main() { - message.InitRsspCrcTable() + // message.InitRsspCrcTable() ci.InitCiServerCodePoints() // cfg := &config.RsspAxleConfig{} diff --git a/third_party/message/can_atp_req.go b/third_party/message/can_atp_req.go index cd07b7c..415935a 100644 --- a/third_party/message/can_atp_req.go +++ b/third_party/message/can_atp_req.go @@ -145,7 +145,7 @@ func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool { } else { return false } - crc16 := calculateAtpReqCrc16(timeArr) + crc16 := Can_Crc16(timeArr) t1 := uint32(timeArr[0]) t2 := uint32(timeArr[1]) t3 := uint32(timeArr[2]) @@ -211,7 +211,7 @@ func (f *AtpRequestFrame) Encode() *CanetFrame { bits.AddByte(timeByte) } //crc - crc16 := calculateAtpReqCrc16(timeArr) + crc16 := Can_Crc16(timeArr) bits.AddByte(byte(crc16 >> 8)) bits.AddByte(byte(crc16)) // diff --git a/third_party/message/can_btm_rsp.go b/third_party/message/can_btm_rsp.go index 2c2b06f..bff40ff 100644 --- a/third_party/message/can_btm_rsp.go +++ b/third_party/message/can_btm_rsp.go @@ -44,7 +44,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr var crc32AData []byte crc32AData = append(crc32AData, msg...) crc32AData = append(crc32AData, canTimeToBytes(dtA.TimeA)...) - dtA.Crc32A = calculateDataRspCrc32A(crc32AData) //CRC32A的校验范围是:报文+时间戳A + dtA.Crc32A = Can_Crc32(crc32AData) //CRC32A的校验范围是:报文+时间戳A } else { //BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF” dtA.Crc32A = 0xff_ff_ff_ff } @@ -55,7 +55,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr var crc32BData []byte crc32BData = append(crc32BData, msg...) crc32BData = append(crc32BData, canTimeToBytes(dtB.TimeB)...) - dtB.Crc32B = calculateDataRspCrc32B(crc32BData) //CRC32B的校验范围是:报文+时间戳B + dtB.Crc32B = Can_Crc32(crc32BData) //CRC32B的校验范围是:报文+时间戳B } else { //BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF” 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, canTimeToBytes(end.TkB)...) // - end.Crc32C = calculateDataRspCrc32C(crc32cData) + end.Crc32C = Can_Crc32(crc32cData) // endCf := end.Encode() // diff --git a/third_party/message/can_bus.go b/third_party/message/can_bus.go index 8c5ea4c..8706623 100644 --- a/third_party/message/can_bus.go +++ b/third_party/message/can_bus.go @@ -1,5 +1,7 @@ package message +import "github.com/snksoft/crc" + /////////////////////CAN串行总线 bit 流处理 //////////////////////// // CanBits 可以在CAN总线上传输的bit流 @@ -199,42 +201,55 @@ const ( ///////////////////// CRC //////////////////////// -const ( - CAN_CRC16_ATPREQ = 0x11021 - CAN_CRC32 = 0x04C11DB7 -) +// const ( +// CAN_CRC16_ATPREQ = 0x11021 +// CAN_CRC32 = 0x04C11DB7 +// ) var ( - crc16AtpReqTable []uint32 = nil - crc32CanTable []uint32 = nil + CAN_CRC16 = crc.CCITT + CAN_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x4A503DF1, Init: 0x00FF0000, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFF} ) -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 +func Can_Crc16(data []byte) uint16 { + return uint16(crc.CalculateCRC(CAN_CRC16, data)) } -// CRC32A的校验范围是:报文+时间戳A -func calculateDataRspCrc32A(data []byte) uint32 { - return calculateCanCrc32(data) +func Can_Crc32(data []byte) uint32 { + return uint32(crc.CalculateCRC(CAN_CRC32, data)) } -// CRC32B的校验范围是:报文+时间戳B -func calculateDataRspCrc32B(data []byte) uint32 { - return calculateCanCrc32(data) -} -func calculateDataRspCrc32C(data []byte) uint32 { - return calculateCanCrc32(data) -} +// var ( +// crc16AtpReqTable []uint32 = nil +// crc32CanTable []uint32 = nil +// ) + +// 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) +// } diff --git a/third_party/message/radar.go b/third_party/message/radar.go new file mode 100644 index 0000000..3add9a6 --- /dev/null +++ b/third_party/message/radar.go @@ -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 + // 10:DRS05_Single-Mode 40度,50度的天线或通道故障 + // 01:DRS05_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 +} diff --git a/third_party/message/rssp.go b/third_party/message/rssp.go index 2d0cce8..c090a89 100644 --- a/third_party/message/rssp.go +++ b/third_party/message/rssp.go @@ -62,7 +62,7 @@ func RsspPackCrc16Check(pack []byte) bool { } // 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 } @@ -104,7 +104,7 @@ func (r *RsspRsd) Encode() []byte { //用户数据包 data = append(data, r.Sad...) //报文尾-CRC16 - r.Crc16 = RsspCrc16(data) + r.Crc16 = Rssp_I_Crc16(data) data = binary.LittleEndian.AppendUint16(data, r.Crc16) // return data @@ -156,7 +156,7 @@ func (r *RsspSse) Encode() []byte { data = binary.LittleEndian.AppendUint32(data, r.SeqEnq1) data = binary.LittleEndian.AppendUint32(data, r.SeqEnq2) //报文尾-CRC16 - r.Crc16 = RsspCrc16(data) + r.Crc16 = Rssp_I_Crc16(data) data = binary.LittleEndian.AppendUint16(data, r.Crc16) return data } @@ -207,7 +207,7 @@ func (r *RsspSsr) Encode() []byte { data = binary.LittleEndian.AppendUint32(data, r.Tic2) data = append(data, r.Dvn) //报文尾-CRC16 - r.Crc16 = RsspCrc16(data) + r.Crc16 = Rssp_I_Crc16(data) data = binary.LittleEndian.AppendUint16(data, r.Crc16) return data } diff --git a/third_party/message/rssp_code.go b/third_party/message/rssp_code.go index 0ca1757..070aba6 100644 --- a/third_party/message/rssp_code.go +++ b/third_party/message/rssp_code.go @@ -1,206 +1,233 @@ package message +import "github.com/snksoft/crc" + //rssp 协议中crc校验,查表法实现 -// Crc16Table G(x)=X16+X11+X4+1,计算初始值为0 -var crc16Table []uint32 = nil -var crc32C1Table []uint32 = nil -var crc32C2Table []uint32 = nil +// // Crc16Table G(x)=X16+X11+X4+1,计算初始值为0 +// var crc16Table []uint32 = nil +// var crc32C1Table []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 ( - SCW_C1 = uint32(0xae390b5a) //SCW常 - SCW_C2 = uint32(0xc103589c) //SCW常 + // 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表 -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) +var ( + // crc16多项式为G(x)=X16+X11+X4+1 + RSSP_I_CRC16 = &crc.Parameters{Width: 16, Polynomial: 0x0811, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0} + // 通道1 crc32多项式为0x100d4e63 + RSSP_I_C1_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x100d4e63, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0} + // 通道2 crc32多项式为0x8ce56011 + RSSP_I_C2_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x8ce56011, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0} +) + +// Rssp_I_Crc16计算 +func Rssp_I_Crc16(data []byte) uint16 { + return uint16(crc.CalculateCRC(RSSP_I_CRC16, data)) } -// 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 +// 通道1的crc32 +func Rssp_I_Crc32C1(data []byte) uint32 { + return uint32(crc.CalculateCRC(RSSP_I_C1_CRC32, data)) } +// 通道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) -func reflect(data uint32, width int) uint32 { - var register1 uint32 = 0 - var significant_mask uint32 = 0xffffffff >> (32 - width) - var register_msb_mask uint32 = 1 << (width - 1) - var register_lsb_mask uint32 = 1 +// // 反转(0b00001010->0b01010000) +// func reflect(data uint32, width int) uint32 { +// var register1 uint32 = 0 +// var significant_mask uint32 = 0xffffffff >> (32 - width) +// var register_msb_mask uint32 = 1 << (width - 1) +// var register_lsb_mask uint32 = 1 - for i := 0; i < width; i++ { - need_or := (data>>i)®ister_lsb_mask == register_lsb_mask - if need_or { - register1 |= register_msb_mask >> i - } - } - return register1 & significant_mask -} +// for i := 0; i < width; i++ { +// need_or := (data>>i)®ister_lsb_mask == register_lsb_mask +// if need_or { +// register1 |= register_msb_mask >> i +// } +// } +// return register1 & significant_mask +// } -// 计算单个数值的crc -func lookup(data uint32, - polynomial uint32, - width int, - input_reflected bool) uint32 { - var register1 uint32 = 0 - var significant_mask uint32 = 0xffffffff >> (32 - width) - var register_msb_mask uint32 = 1 << (width - 1) - var register_lsb_mask uint32 = 1 - var byte_msb_mask uint32 = 0x80 - var byte_lsb_mask uint32 = 1 +// // 计算单个数值的crc +// func lookup(data uint32, +// polynomial uint32, +// width int, +// input_reflected bool) uint32 { +// var register1 uint32 = 0 +// var significant_mask uint32 = 0xffffffff >> (32 - width) +// var register_msb_mask uint32 = 1 << (width - 1) +// var register_lsb_mask uint32 = 1 +// var byte_msb_mask uint32 = 0x80 +// var byte_lsb_mask uint32 = 1 - if input_reflected { - polynomial = reflect(polynomial, width) - } +// if input_reflected { +// polynomial = reflect(polynomial, width) +// } - for i := 0; i < 1+(width/8); i++ { - var byteData uint32 = 0 +// for i := 0; i < 1+(width/8); i++ { +// var byteData uint32 = 0 - if i < 1 { - byteData = data - } +// if i < 1 { +// byteData = data +// } - for j := 0; j < 8; j++ { - need_xor := false +// for j := 0; j < 8; j++ { +// need_xor := false - if input_reflected { - need_xor = (register1 & register_lsb_mask) == register_lsb_mask - register1 >>= 1 +// if input_reflected { +// need_xor = (register1 & register_lsb_mask) == register_lsb_mask +// register1 >>= 1 - need_or := (byteData & byte_lsb_mask) == byte_lsb_mask - byteData >>= 1 +// need_or := (byteData & byte_lsb_mask) == byte_lsb_mask +// byteData >>= 1 - if need_or { - register1 |= register_msb_mask - } - } else { - need_xor = (register1 & register_msb_mask) == register_msb_mask - register1 <<= 1 +// if need_or { +// register1 |= register_msb_mask +// } +// } else { +// need_xor = (register1 & register_msb_mask) == register_msb_mask +// register1 <<= 1 - need_or := (byteData & byte_msb_mask) == byte_msb_mask - byteData <<= 1 +// need_or := (byteData & byte_msb_mask) == byte_msb_mask +// byteData <<= 1 - if need_or { - register1 |= register_lsb_mask - } - } +// if need_or { +// register1 |= register_lsb_mask +// } +// } - if need_xor { - register1 ^= polynomial - } - } - } - return register1 & significant_mask -} +// if need_xor { +// register1 ^= polynomial +// } +// } +// } +// return register1 & significant_mask +// } -// CrcTableBased 查表法计算字节数组的crc -func CrcTableBased( - data []byte, - width int, - initial_value uint32, - input_reflected bool, - result_reflected bool, - final_xor_value uint32, - table []uint32) uint32 { - // - length := len(data) - var register1 uint32 = initial_value - var significant_mask uint32 = 0xffffffff >> (32 - width) - var register_lsb_mask uint32 = 0xff +// // CrcTableBased 查表法计算字节数组的crc +// func CrcTableBased( +// data []byte, +// width int, +// initial_value uint32, +// input_reflected bool, +// result_reflected bool, +// final_xor_value uint32, +// table []uint32) uint32 { +// // +// length := len(data) +// var register1 uint32 = initial_value +// var significant_mask uint32 = 0xffffffff >> (32 - width) +// var register_lsb_mask uint32 = 0xff - if input_reflected { - register1 = reflect(register1, width) - } +// if input_reflected { +// register1 = reflect(register1, width) +// } - for i := 0; i < length; i++ { - var byteData = uint32(data[i]) - var shift_out uint32 = 0 +// for i := 0; i < length; i++ { +// var byteData = uint32(data[i]) +// var shift_out uint32 = 0 - if input_reflected { - shift_out = register1 & register_lsb_mask - register1 = (register1 >> 8) ^ table[shift_out^byteData] - } else { - shift_out = (register1 >> (width - 8)) & register_lsb_mask - register1 = (register1 << 8) ^ table[shift_out^byteData] - } - } +// if input_reflected { +// shift_out = register1 & register_lsb_mask +// register1 = (register1 >> 8) ^ table[shift_out^byteData] +// } else { +// shift_out = (register1 >> (width - 8)) & register_lsb_mask +// register1 = (register1 << 8) ^ table[shift_out^byteData] +// } +// } - if input_reflected != result_reflected { - register1 = reflect(register1, width) - } - return (register1 ^ final_xor_value) & significant_mask -} +// if input_reflected != result_reflected { +// register1 = reflect(register1, width) +// } +// return (register1 ^ final_xor_value) & significant_mask +// } -func Crc(data []byte, - polynomial uint32, - width int, - initial_value uint32, - input_reflected bool, - result_reflected bool, - final_xor_value uint32) uint32 { - length := len(data) - var register1 uint32 = initial_value - var significant_mask uint32 = 0xffffffff >> (32 - width) - var register_lsb_mask uint32 = 0xff +// func Crc(data []byte, +// polynomial uint32, +// width int, +// initial_value uint32, +// input_reflected bool, +// result_reflected bool, +// final_xor_value uint32) uint32 { +// length := len(data) +// var register1 uint32 = initial_value +// var significant_mask uint32 = 0xffffffff >> (32 - width) +// var register_lsb_mask uint32 = 0xff - if input_reflected { - register1 = reflect(register1, width) - } +// if input_reflected { +// register1 = reflect(register1, width) +// } - for i := 0; i < length; i++ { - var byteData uint32 = uint32(data[i]) - var shift_out uint32 = 0 - var value uint32 = 0 +// for i := 0; i < length; i++ { +// var byteData uint32 = uint32(data[i]) +// var shift_out uint32 = 0 +// var value uint32 = 0 - if input_reflected { - shift_out = register1 & register_lsb_mask - value = lookup(shift_out^byteData, polynomial, width, input_reflected) - register1 = (register1 >> 8) ^ value - } else { - shift_out = (register1 >> (width - 8)) & register_lsb_mask - value = lookup(shift_out^byteData, polynomial, width, input_reflected) - register1 = (register1 << 8) ^ value - } - } +// if input_reflected { +// shift_out = register1 & register_lsb_mask +// value = lookup(shift_out^byteData, polynomial, width, input_reflected) +// register1 = (register1 >> 8) ^ value +// } else { +// shift_out = (register1 >> (width - 8)) & register_lsb_mask +// value = lookup(shift_out^byteData, polynomial, width, input_reflected) +// register1 = (register1 << 8) ^ value +// } +// } - if input_reflected != result_reflected { - register1 = reflect(register1, width) - } - return (register1 ^ final_xor_value) & significant_mask -} +// if input_reflected != result_reflected { +// register1 = reflect(register1, width) +// } +// return (register1 ^ final_xor_value) & significant_mask +// } //////////////////////////LFSR////////////////////////////// diff --git a/third_party/semi_physical_train/semi_physical_train.go b/third_party/semi_physical_train/semi_physical_train.go index 374307a..246e74b 100644 --- a/third_party/semi_physical_train/semi_physical_train.go +++ b/third_party/semi_physical_train/semi_physical_train.go @@ -2,15 +2,18 @@ package semi_physical_train import ( "fmt" + "log/slog" "sync" "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/third_party/message" + "joylink.club/bj-rtsts-server/third_party/tpapi" "joylink.club/bj-rtsts-server/third_party/udp" ) // 半实物仿真列车通信接口 type SemiPhysicalTrain interface { + tpapi.ThirdPartyApiService // 启动半实物仿真消息处理 Start(manager SemiPhysicalMessageManager) // 停止半实物仿真消息处理 @@ -27,14 +30,19 @@ type SemiPhysicalMessageManager interface { } type semiPhysicalTrainImpl struct { + tpapi.ThirdPartyApiService trainControlUdpServer udp.UdpServer trainSpeedInfoUdpClient udp.UdpClient + udpDelayRecorder *tpapi.UdpDelayRecorder + manager SemiPhysicalMessageManager runConfig *config.VobcConfig } func (s *semiPhysicalTrainImpl) handleTrainControlMsg(b []byte) { + s.udpDelayRecorder.RecordInterval() + slog.Debug(fmt.Sprintf("半实物列车控制消息近期消息间隔: %v", s.udpDelayRecorder.GetIntervals())) handler := s.manager if handler != nil { handler.HandleSemiPhysicalTrainControlMsg(b) @@ -55,12 +63,14 @@ func (s *semiPhysicalTrainImpl) Start(manager SemiPhysicalMessageManager) { // 初始化客户端、服务端 s.initSemiPhysical() s.manager = manager + s.UpdateState(tpapi.ThirdPartyState_Normal) + s.udpDelayRecorder.Start() } func (s *semiPhysicalTrainImpl) Stop() { initMutex.Lock() defer initMutex.Unlock() - _default = nil + s.udpDelayRecorder.Stop() if s.trainControlUdpServer != nil { s.trainControlUdpServer.Close() } @@ -68,6 +78,7 @@ func (s *semiPhysicalTrainImpl) Stop() { s.trainSpeedInfoUdpClient.Close() } s.manager = nil + s.UpdateState(tpapi.ThirdPartyState_Closed) } func (s *semiPhysicalTrainImpl) SendTrainControlMessage(info *message.DynamicsTrainInfo) { @@ -85,11 +96,22 @@ func (s *semiPhysicalTrainImpl) initSemiPhysical() { var _default SemiPhysicalTrain var initMutex sync.Mutex +const Interval int = 20 + func Default() SemiPhysicalTrain { initMutex.Lock() defer initMutex.Unlock() 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 } diff --git a/third_party/third_party.go b/third_party/third_party.go index 1ade3b8..292c93c 100644 --- a/third_party/third_party.go +++ b/third_party/third_party.go @@ -1,8 +1,24 @@ 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() { - message.InitRsspCrcTable() - message.CreateCanCrcTable() +func GetRunningServiceStates(t state_proto.SimulationThirdPartyApiService_Type) *state_proto.SimulationThirdPartyApiService { + ss := &state_proto.SimulationThirdPartyApiService{} + 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 } diff --git a/third_party/tpapi/service.go b/third_party/tpapi/service.go new file mode 100644 index 0000000..b4abce9 --- /dev/null +++ b/third_party/tpapi/service.go @@ -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 + } +} diff --git a/third_party/udp/udp_server.go b/third_party/udp/udp_server.go index aea18ba..7e702e2 100644 --- a/third_party/udp/udp_server.go +++ b/third_party/udp/udp_server.go @@ -1,6 +1,7 @@ package udp import ( + "context" "log/slog" "net" "runtime/debug" @@ -14,9 +15,10 @@ type UdpServer interface { type UdpMsgHandler func(b []byte) type server struct { - addr string - conn *net.UDPConn - handler UdpMsgHandler + addr string + conn *net.UDPConn + handler UdpMsgHandler + cancelFn context.CancelFunc } // NewServer creates a new instance of UdpServer. @@ -34,29 +36,37 @@ func (s *server) Listen() { panic(err) } s.conn = conn + ctx, cfn := context.WithCancel(context.Background()) // 启动监听处理 - go s.listenAndHandle() + go s.listenAndHandle(ctx) + s.cancelFn = cfn } func (s *server) Close() { - err := s.conn.Close() - if err != nil { - slog.Error("udp server close error", "error", err) - } + s.cancelFn() + // err := s.conn.Close() + // 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() for { - b := make([]byte, 1024) - n, err := s.conn.Read(b) - if err != nil { - slog.Error("udp server read error", err) + select { + case <-ctx.Done(): + slog.Info("udp server listen 关闭", "addr", s.addr) return + default: } - if n > 0 { - go s.handle(b[0:n]) + buf := make([]byte, 1024) + 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]) } } diff --git a/ts/simulation/app_component/component.go b/ts/simulation/app_component/component.go index 183480e..e6ad5aa 100644 --- a/ts/simulation/app_component/component.go +++ b/ts/simulation/app_component/component.go @@ -6,6 +6,7 @@ import ( ) var ( - PointsParamType = ecs.NewComponentType[request_proto.PointsParam]() - SignalParamType = ecs.NewComponentType[request_proto.SignalParam]() + PointsParamType = ecs.NewComponentType[request_proto.PointsParam]() + SignalParamType = ecs.NewComponentType[request_proto.SignalParam]() + SectionParamType = ecs.NewComponentType[request_proto.SectionParam]() ) diff --git a/ts/simulation/wayside/memory/wayside_memory_section.go b/ts/simulation/wayside/memory/wayside_memory_section.go index cbfe53b..799561e 100644 --- a/ts/simulation/wayside/memory/wayside_memory_section.go +++ b/ts/simulation/wayside/memory/wayside_memory_section.go @@ -1,36 +1,74 @@ package memory 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/request_proto" + appcomponent "joylink.club/bj-rtsts-server/ts/simulation/app_component" + "joylink.club/ecs" "joylink.club/rtsssimulation/fi" ) -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) - } +// 处理区段操作 +func HandleSectionOperation(simulation *VerifySimulation, req *request_proto.SectionOperationReq) error { + uid := QueryUidByMidAndComId(req.MapId, req.DeviceId, &data_proto.Section{}) + // 区段操作 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 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 +// } diff --git a/ts/simulation/wayside/memory/wayside_memory_train.go b/ts/simulation/wayside/memory/wayside_memory_train.go index 1bf8094..a7de276 100644 --- a/ts/simulation/wayside/memory/wayside_memory_train.go +++ b/ts/simulation/wayside/memory/wayside_memory_train.go @@ -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, trainEndsB dto.ConfigTrainEnds) { trainState.TrainDynamicConfig = service.TrainConfigToProtoConvert(&configTrainData) - if trainState.TrainDynamicConfig == nil { - slog.Error("") - } else { + if trainState.TrainDynamicConfig != nil { copyTrainEnds(trainState, "TrainEndsA", trainEndsA) copyTrainEnds(trainState, "TrainEndsB", trainEndsB) }