Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
19c67811d0
@ -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")
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 3a30efc9fe949cd5ab9898073f00a093716f279e
|
||||
Subproject commit bdd66d8625e76afb23f501de306224d35a8958d1
|
@ -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_Undefined Section_Operation = 0 // 未定义
|
||||
Section_SetParams Section_Operation = 1 // 设置参数
|
||||
// SetDrst = 0;//设置计轴直接复位
|
||||
// CancelDrst = 1;//取消计轴直接复位
|
||||
// SetPdrst = 2;//设置计轴预复位
|
||||
// CancelPdrst = 3;//取消计轴预复位
|
||||
Section_SetFaultOcc Section_Operation = 4 //设置故障占用
|
||||
Section_CancelFaultOcc Section_Operation = 5 //取消故障占用
|
||||
)
|
||||
|
||||
// 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,
|
||||
"Undefined": 0,
|
||||
"SetParams": 1,
|
||||
"SetFaultOcc": 4,
|
||||
"CancelFaultOcc": 5,
|
||||
}
|
||||
)
|
||||
|
||||
@ -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,7 +1395,7 @@ 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
|
||||
@ -1269,8 +1414,10 @@ var file_request_proto_goTypes = []interface{}{
|
||||
(*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
|
||||
(*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,
|
||||
},
|
||||
|
@ -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{
|
||||
|
1
go.mod
1
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
|
||||
|
2
go.sum
2
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=
|
||||
|
3
main.go
3
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)
|
||||
|
23
third_party/axle_device/rssp_channel.go
vendored
23
third_party/axle_device/rssp_channel.go
vendored
@ -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()
|
||||
|
27
third_party/dynamics/dynamics.go
vendored
27
third_party/dynamics/dynamics.go
vendored
@ -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 (
|
||||
|
5
third_party/example/rssp/main.go
vendored
5
third_party/example/rssp/main.go
vendored
@ -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{}
|
||||
|
4
third_party/message/can_atp_req.go
vendored
4
third_party/message/can_atp_req.go
vendored
@ -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))
|
||||
//
|
||||
|
6
third_party/message/can_btm_rsp.go
vendored
6
third_party/message/can_btm_rsp.go
vendored
@ -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()
|
||||
//
|
||||
|
77
third_party/message/can_bus.go
vendored
77
third_party/message/can_bus.go
vendored
@ -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)
|
||||
// }
|
||||
|
172
third_party/message/radar.go
vendored
Normal file
172
third_party/message/radar.go
vendored
Normal 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
|
||||
// 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
|
||||
}
|
8
third_party/message/rssp.go
vendored
8
third_party/message/rssp.go
vendored
@ -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
|
||||
}
|
||||
|
359
third_party/message/rssp_code.go
vendored
359
third_party/message/rssp_code.go
vendored
@ -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))
|
||||
// 通道1的crc32
|
||||
func Rssp_I_Crc32C1(data []byte) uint32 {
|
||||
return uint32(crc.CalculateCRC(RSSP_I_C1_CRC32, data))
|
||||
}
|
||||
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)
|
||||
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//////////////////////////////
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
24
third_party/third_party.go
vendored
24
third_party/third_party.go
vendored
@ -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
|
||||
}
|
||||
|
144
third_party/tpapi/service.go
vendored
Normal file
144
third_party/tpapi/service.go
vendored
Normal 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
|
||||
}
|
||||
}
|
34
third_party/udp/udp_server.go
vendored
34
third_party/udp/udp_server.go
vendored
@ -1,6 +1,7 @@
|
||||
package udp
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net"
|
||||
"runtime/debug"
|
||||
@ -17,6 +18,7 @@ type server struct {
|
||||
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])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -8,4 +8,5 @@ import (
|
||||
var (
|
||||
PointsParamType = ecs.NewComponentType[request_proto.PointsParam]()
|
||||
SignalParamType = ecs.NewComponentType[request_proto.SignalParam]()
|
||||
SectionParamType = ecs.NewComponentType[request_proto.SectionParam]()
|
||||
)
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
// }
|
||||
|
@ -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)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user