列车pc仿真
This commit is contained in:
parent
089d62cfc2
commit
9b58348297
@ -354,7 +354,7 @@ func controlTrain(c *gin.Context) {
|
|||||||
panic(sys_error.New("修改列车控制参数失败,请求参数异常", err))
|
panic(sys_error.New("修改列车控制参数失败,请求参数异常", err))
|
||||||
}
|
}
|
||||||
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
||||||
memory.ControlTrainUpdate(simulation, req)
|
simulation.ControlTrainUpdate(req)
|
||||||
c.JSON(http.StatusOK, "ok")
|
c.JSON(http.StatusOK, "ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -12,19 +12,6 @@ import (
|
|||||||
|
|
||||||
// 综合后备盘IBP消息服务
|
// 综合后备盘IBP消息服务
|
||||||
func NewTrainControlMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
func NewTrainControlMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
||||||
/* var findMapId int32 = 0
|
|
||||||
for _, d := range vs.MapIds {
|
|
||||||
mapData := memory.QueryGiType(d)
|
|
||||||
if mapData == data_proto.PictureType_TrainControlCab {
|
|
||||||
findMapId = d
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if findMapId == 0 {
|
|
||||||
slog.Error("未找到对应的列城控制图形")
|
|
||||||
return nil
|
|
||||||
}*/
|
|
||||||
return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]列车控制", mapId), func() error {
|
return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]列车控制", mapId), func() error {
|
||||||
allTrainMap := &vs.Memory.Status.TrainStateMap
|
allTrainMap := &vs.Memory.Status.TrainStateMap
|
||||||
allTrainMap.Range(func(key, value any) bool {
|
allTrainMap.Range(func(key, value any) bool {
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 78f0ddfd2413bdac81d33ea2b199edaa4de9e6fb
|
Subproject commit 5dd8f8963e28e79012656f95999016ad503ae43a
|
42
third_party/can_btm/balise_btm.go
vendored
42
third_party/can_btm/balise_btm.go
vendored
@ -46,7 +46,7 @@ type btmCanetClient struct {
|
|||||||
//最近一次车载ATP系统查询帧CRC16校验结果,true-校验通过
|
//最近一次车载ATP系统查询帧CRC16校验结果,true-校验通过
|
||||||
atpReqCrc16Check bool
|
atpReqCrc16Check bool
|
||||||
//btm系统时间,每次接收到ATP查询请求帧时同步一次时间
|
//btm系统时间,每次接收到ATP查询请求帧时同步一次时间
|
||||||
btmTime btmClock
|
btmTime BtmClock
|
||||||
//数据流水号
|
//数据流水号
|
||||||
dsn byte
|
dsn byte
|
||||||
//重发的数据
|
//重发的数据
|
||||||
@ -57,6 +57,7 @@ type btmCanetClient struct {
|
|||||||
|
|
||||||
func (s *btmCanetClient) GetState() state_proto.BTMState {
|
func (s *btmCanetClient) GetState() state_proto.BTMState {
|
||||||
detector := s.baliseDetector
|
detector := s.baliseDetector
|
||||||
|
|
||||||
var telegram string
|
var telegram string
|
||||||
info := detector.eq[len(detector.eq)-1]
|
info := detector.eq[len(detector.eq)-1]
|
||||||
if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 {
|
if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 {
|
||||||
@ -69,17 +70,19 @@ func (s *btmCanetClient) GetState() state_proto.BTMState {
|
|||||||
BaliseCount: uint32(detector.baliseCounter),
|
BaliseCount: uint32(detector.baliseCounter),
|
||||||
MessageCounter: uint32(detector.messageCounter),
|
MessageCounter: uint32(detector.messageCounter),
|
||||||
Telegram: telegram,
|
Telegram: telegram,
|
||||||
|
Distance: info.Distance,
|
||||||
|
AboveBalise: detector.aboveBalise,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type btmClock struct {
|
type BtmClock struct {
|
||||||
btmTk uint32 //与ATP系统同步的时间ms
|
BtmTk uint32 //与ATP系统同步的时间ms
|
||||||
sysTk time.Time //本地系统时间
|
SysTk time.Time //本地系统时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取以btmTk为基准的当前时间ms
|
// 获取以btmTk为基准的当前时间ms
|
||||||
func (c *btmClock) tkNow() uint32 {
|
func (c *BtmClock) TkNow() uint32 {
|
||||||
return c.btmTk + uint32(time.Now().UnixMilli()-c.sysTk.UnixMilli())
|
return c.BtmTk + uint32(time.Now().UnixMilli()-c.SysTk.UnixMilli())
|
||||||
}
|
}
|
||||||
|
|
||||||
type BtmCanetClient interface {
|
type BtmCanetClient interface {
|
||||||
@ -87,7 +90,7 @@ type BtmCanetClient interface {
|
|||||||
Stop()
|
Stop()
|
||||||
//HandleTrainHeadPositionInfo 处理收到列车位置信息
|
//HandleTrainHeadPositionInfo 处理收到列车位置信息
|
||||||
HandleTrainHeadPositionInfo(w ecs.World, h *TrainHeadPositionInfo)
|
HandleTrainHeadPositionInfo(w ecs.World, h *TrainHeadPositionInfo)
|
||||||
//获取BTM显示状态
|
//获取BTM显示状态 + btm最新的状态
|
||||||
GetState() state_proto.BTMState
|
GetState() state_proto.BTMState
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -156,7 +159,7 @@ func (s *btmCanetClient) handleCanetFrames(cfs []byte) {
|
|||||||
dms := make([]*message.CanetFrame, 0, 16) //13个应答器报文数据帧+TimeA帧+TimeB帧+结束帧
|
dms := make([]*message.CanetFrame, 0, 16) //13个应答器报文数据帧+TimeA帧+TimeB帧+结束帧
|
||||||
for cfi := 0; cfi < cfSum; cfi++ {
|
for cfi := 0; cfi < cfSum; cfi++ {
|
||||||
cfStart := cfi * 13
|
cfStart := cfi * 13
|
||||||
cf := message.NewCanetFrame(cfs[cfStart : cfStart+13])
|
cf := message.NewCanetFrame(cfs[cfStart:cfStart+13], false)
|
||||||
//
|
//
|
||||||
switch cf.CanFrameType() {
|
switch cf.CanFrameType() {
|
||||||
case message.CfReq:
|
case message.CfReq:
|
||||||
@ -206,8 +209,8 @@ func (s *btmCanetClient) dealWithAptReq(f *message.CanetFrame) {
|
|||||||
//处理查询请求
|
//处理查询请求
|
||||||
//slog.Debug(fmt.Sprintf("处理查询请求:%s", atpReq.String()))
|
//slog.Debug(fmt.Sprintf("处理查询请求:%s", atpReq.String()))
|
||||||
//
|
//
|
||||||
s.btmTime.btmTk = atpReq.Time
|
s.btmTime.BtmTk = atpReq.Time
|
||||||
s.btmTime.sysTk = now
|
s.btmTime.SysTk = now
|
||||||
s.atpReqSn = atpReq.FId.ID4
|
s.atpReqSn = atpReq.FId.ID4
|
||||||
s.atpReqCrc16Check = atpReq.Crc16CheckOk
|
s.atpReqCrc16Check = atpReq.Crc16CheckOk
|
||||||
s.baliseDetector.powerAmplifierSwitch = atpReq.PowerAmplifierTurnOn
|
s.baliseDetector.powerAmplifierSwitch = atpReq.PowerAmplifierTurnOn
|
||||||
@ -256,14 +259,14 @@ func (s *btmCanetClient) rspResendToAtp() {
|
|||||||
// 当未收到应答器报文时响应:时间同步帧、状态应答帧
|
// 当未收到应答器报文时响应:时间同步帧、状态应答帧
|
||||||
func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
|
func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
|
||||||
//BTM状态
|
//BTM状态
|
||||||
statusF := message.NewBtmStatusRspFrame(s.atpReqSn)
|
statusF := message.NewBtmStatusRspFrame(s.atpReqSn, false)
|
||||||
btmStatus := s.createTrainBtmStatus()
|
btmStatus := s.createTrainBtmStatus()
|
||||||
|
|
||||||
statusF.AntennaFault = btmStatus.AntennaFault
|
statusF.AntennaFault = btmStatus.AntennaFault
|
||||||
statusF.BaliseCounter = byte(btmStatus.BaliseCounter)
|
statusF.BaliseCounter = byte(btmStatus.BaliseCounter)
|
||||||
statusF.MessageCounter = byte(btmStatus.MessageCounter)
|
statusF.MessageCounter = byte(btmStatus.MessageCounter)
|
||||||
statusF.PowerAmplifierOn = btmStatus.PowerAmplifierOn
|
statusF.PowerAmplifierOn = btmStatus.PowerAmplifierOn
|
||||||
statusF.TkTimeA = s.btmTime.tkNow()
|
statusF.TkTimeA = s.btmTime.TkNow()
|
||||||
statusF.PowerAmplifierFailure = btmStatus.PowerAmplifierFault
|
statusF.PowerAmplifierFailure = btmStatus.PowerAmplifierFault
|
||||||
statusF.DetailedCode = 0
|
statusF.DetailedCode = 0
|
||||||
if btmStatus.AboveBalise {
|
if btmStatus.AboveBalise {
|
||||||
@ -271,16 +274,17 @@ func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
|
|||||||
}
|
}
|
||||||
statusF.AtpReqCrcCheckWrong = !s.atpReqCrc16Check
|
statusF.AtpReqCrcCheckWrong = !s.atpReqCrc16Check
|
||||||
statusF.Dsn = s.dsn
|
statusF.Dsn = s.dsn
|
||||||
|
|
||||||
s.dsnAdd1()
|
s.dsnAdd1()
|
||||||
//
|
//
|
||||||
//true-收到应答器报文
|
//true-收到应答器报文
|
||||||
isRcvTelegram := sb != nil && len(sb.telegram) > 0
|
isRcvTelegram := sb != nil && len(sb.telegram) > 0
|
||||||
if isRcvTelegram { //当收到应答器报文时响应:时间同步帧、状态应答帧、数据帧
|
if isRcvTelegram { //当收到应答器报文时响应:时间同步帧、状态应答帧、数据帧
|
||||||
statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(statusF, sb.telegram, false, s.btmTime.tkNow(), s.btmTime.tkNow(), s.btmTime.tkNow())
|
statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(statusF, sb.telegram, false, s.btmTime.TkNow(), s.btmTime.TkNow(), s.btmTime.TkNow(), false)
|
||||||
if statusDataCfOk {
|
if statusDataCfOk {
|
||||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn, false)
|
||||||
timeSyncF.T2 = s.btmTime.btmTk
|
timeSyncF.T2 = s.btmTime.BtmTk
|
||||||
timeSyncF.T3 = s.btmTime.tkNow()
|
timeSyncF.T3 = s.btmTime.TkNow()
|
||||||
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
||||||
//
|
//
|
||||||
s.resendData = newResendData(statusDataCf)
|
s.resendData = newResendData(statusDataCf)
|
||||||
@ -289,9 +293,9 @@ func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
|
|||||||
slog.Warn("BtmCanetClient应答帧、数据帧编码失败")
|
slog.Warn("BtmCanetClient应答帧、数据帧编码失败")
|
||||||
}
|
}
|
||||||
} else { //当未收到应答器报文时响应:时间同步帧、状态应答帧
|
} else { //当未收到应答器报文时响应:时间同步帧、状态应答帧
|
||||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn, false)
|
||||||
timeSyncF.T2 = s.btmTime.btmTk
|
timeSyncF.T2 = s.btmTime.BtmTk
|
||||||
timeSyncF.T3 = s.btmTime.tkNow()
|
timeSyncF.T3 = s.btmTime.TkNow()
|
||||||
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
||||||
//
|
//
|
||||||
statusCf := statusF.Encode().Encode()
|
statusCf := statusF.Encode().Encode()
|
||||||
|
3
third_party/can_btm/balise_detection.go
vendored
3
third_party/can_btm/balise_detection.go
vendored
@ -41,6 +41,7 @@ type BtmAntennaScanningBaliseInfo struct {
|
|||||||
Time time.Time //应答器预计被BTM天线激活的时刻
|
Time time.Time //应答器预计被BTM天线激活的时刻
|
||||||
active bool //true-激活过,即列车扫过
|
active bool //true-激活过,即列车扫过
|
||||||
telegram []byte //应答器报文
|
telegram []byte //应答器报文
|
||||||
|
Distance int64 //BTM天线中心到应答器的距离,mm
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaliseDetector 车载BTM天线,应答器探测器
|
// BaliseDetector 车载BTM天线,应答器探测器
|
||||||
@ -185,7 +186,7 @@ func (t *BaliseDetector) timeScanNearestBalise(curTime time.Time, wd *component.
|
|||||||
s := float64(expectedBalise.Distance) / 1000
|
s := float64(expectedBalise.Distance) / 1000
|
||||||
st, ok := t.calculateBtmAntennaScanNextBaliseTime(curTime, curV, curAc, s)
|
st, ok := t.calculateBtmAntennaScanNextBaliseTime(curTime, curV, curAc, s)
|
||||||
if ok {
|
if ok {
|
||||||
return &BtmAntennaScanningBaliseInfo{BaliseId: expectedBalise.BaliseId, Time: st}
|
return &BtmAntennaScanningBaliseInfo{BaliseId: expectedBalise.BaliseId, Time: st, Distance: expectedBalise.Distance}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
36
third_party/message/can_btm_data.go
vendored
36
third_party/message/can_btm_data.go
vendored
@ -8,16 +8,19 @@ type BtmDataMessageFrame struct {
|
|||||||
//帧ID
|
//帧ID
|
||||||
FId CanFrameId
|
FId CanFrameId
|
||||||
//8字节,应答器报文片段
|
//8字节,应答器报文片段
|
||||||
Message []byte
|
Message []byte
|
||||||
|
IsTrainPcSim bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBtmDataMessageFrame(sn byte, offset byte) *BtmDataMessageFrame {
|
func NewBtmDataMessageFrame(sn byte, offset byte, isTrainPcSim bool) *BtmDataMessageFrame {
|
||||||
return &BtmDataMessageFrame{
|
return &BtmDataMessageFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn),
|
||||||
|
IsTrainPcSim: isTrainPcSim,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (f *BtmDataMessageFrame) Encode() *CanetFrame {
|
func (f *BtmDataMessageFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
cf.IsTrainPcSim = f.IsTrainPcSim
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
@ -59,16 +62,19 @@ type BtmDataMessageTimeAFrame struct {
|
|||||||
//时间戳A
|
//时间戳A
|
||||||
TimeA uint32
|
TimeA uint32
|
||||||
//CRC
|
//CRC
|
||||||
Crc32A uint32
|
Crc32A uint32
|
||||||
|
IsTrainPcSim bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBtmDataMessageTimeAFrame(sn byte) *BtmDataMessageTimeAFrame {
|
func NewBtmDataMessageTimeAFrame(sn byte, isTrainPcSim bool) *BtmDataMessageTimeAFrame {
|
||||||
return &BtmDataMessageTimeAFrame{
|
return &BtmDataMessageTimeAFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
|
||||||
|
IsTrainPcSim: isTrainPcSim,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame {
|
func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
cf.IsTrainPcSim = f.IsTrainPcSim
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
@ -161,16 +167,19 @@ type BtmDataMessageTimeBFrame struct {
|
|||||||
//时间戳B
|
//时间戳B
|
||||||
TimeB uint32
|
TimeB uint32
|
||||||
//CRC
|
//CRC
|
||||||
Crc32B uint32
|
Crc32B uint32
|
||||||
|
IsTrainPcSim bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBtmDataMessageTimeBFrame(sn byte) *BtmDataMessageTimeBFrame {
|
func NewBtmDataMessageTimeBFrame(sn byte, isTrainPcSim bool) *BtmDataMessageTimeBFrame {
|
||||||
return &BtmDataMessageTimeBFrame{
|
return &BtmDataMessageTimeBFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0e, sn),
|
||||||
|
IsTrainPcSim: isTrainPcSim,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame {
|
func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
cf.IsTrainPcSim = f.IsTrainPcSim
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
@ -263,16 +272,19 @@ type BtmDataMessageEndFrame struct {
|
|||||||
TkB uint32
|
TkB uint32
|
||||||
//CRC32C校验包含对状态应答帧与数据帧的总校验,总共为8×17-4=132字节,4-即Crc32C
|
//CRC32C校验包含对状态应答帧与数据帧的总校验,总共为8×17-4=132字节,4-即Crc32C
|
||||||
//1个状态应答帧 + 13个BtmDataMessageFrame + 1个BtmDataMessageTimeAFrame + 1个BtmDataMessageTimeBFrame + 1个BtmDataMessageEndFrame
|
//1个状态应答帧 + 13个BtmDataMessageFrame + 1个BtmDataMessageTimeAFrame + 1个BtmDataMessageTimeBFrame + 1个BtmDataMessageEndFrame
|
||||||
Crc32C uint32
|
Crc32C uint32
|
||||||
|
IsTrainPcSim bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBtmDataMessageEndFrame(sn byte) *BtmDataMessageEndFrame {
|
func NewBtmDataMessageEndFrame(sn byte, isTrainPcSim bool) *BtmDataMessageEndFrame {
|
||||||
return &BtmDataMessageEndFrame{
|
return &BtmDataMessageEndFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
|
||||||
|
IsTrainPcSim: isTrainPcSim,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (f *BtmDataMessageEndFrame) Encode() *CanetFrame {
|
func (f *BtmDataMessageEndFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
cf.IsTrainPcSim = f.IsTrainPcSim
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
|
11
third_party/message/can_btm_rsp.go
vendored
11
third_party/message/can_btm_rsp.go
vendored
@ -8,16 +8,17 @@ import "log/slog"
|
|||||||
// 共17帧,17X12个字节,每个帧12字节
|
// 共17帧,17X12个字节,每个帧12字节
|
||||||
// msg - 应答器报文
|
// msg - 应答器报文
|
||||||
// msgPackError - true BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF”
|
// msgPackError - true BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF”
|
||||||
func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32) ([]byte, bool) {
|
func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32, isTrainPcSim bool) ([]byte, bool) {
|
||||||
if len(msg) > 104 { //数据帧最多存储13*8个字节
|
if len(msg) > 104 { //数据帧最多存储13*8个字节
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
//最近一次ATP查询请求序列号
|
//最近一次ATP查询请求序列号
|
||||||
sn := statusRsp.FId.ID4
|
sn := statusRsp.FId.ID4
|
||||||
//13个BtmDataMessageFrame [0x00,0x0c]
|
//13个BtmDataMessageFrame [0x00,0x0c]
|
||||||
|
//数据
|
||||||
dms := make([]*BtmDataMessageFrame, 13)
|
dms := make([]*BtmDataMessageFrame, 13)
|
||||||
for mr := 0x00; mr <= 0x0c; mr++ {
|
for mr := 0x00; mr <= 0x0c; mr++ {
|
||||||
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr))
|
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr), isTrainPcSim)
|
||||||
dms[mr].Message = make([]byte, 8) //8字节数组,默认值0
|
dms[mr].Message = make([]byte, 8) //8字节数组,默认值0
|
||||||
//
|
//
|
||||||
if !msgPackError {
|
if !msgPackError {
|
||||||
@ -38,7 +39,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
dtA := NewBtmDataMessageTimeAFrame(sn)
|
dtA := NewBtmDataMessageTimeAFrame(sn, isTrainPcSim)
|
||||||
dtA.TimeA = msgTimeA
|
dtA.TimeA = msgTimeA
|
||||||
if !msgPackError {
|
if !msgPackError {
|
||||||
var crc32AData []byte
|
var crc32AData []byte
|
||||||
@ -49,7 +50,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
|
|||||||
dtA.Crc32A = 0xff_ff_ff_ff
|
dtA.Crc32A = 0xff_ff_ff_ff
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
dtB := NewBtmDataMessageTimeBFrame(sn)
|
dtB := NewBtmDataMessageTimeBFrame(sn, isTrainPcSim)
|
||||||
dtB.TimeB = msgTimeB
|
dtB.TimeB = msgTimeB
|
||||||
if !msgPackError {
|
if !msgPackError {
|
||||||
var crc32BData []byte
|
var crc32BData []byte
|
||||||
@ -60,7 +61,7 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
|
|||||||
dtB.Crc32B = 0xff_ff_ff_ff
|
dtB.Crc32B = 0xff_ff_ff_ff
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
end := NewBtmDataMessageEndFrame(sn)
|
end := NewBtmDataMessageEndFrame(sn, isTrainPcSim)
|
||||||
end.TkB = tkTimeB
|
end.TkB = tkTimeB
|
||||||
//
|
//
|
||||||
statusCf := statusRsp.Encode()
|
statusCf := statusRsp.Encode()
|
||||||
|
9
third_party/message/can_btm_status_rsp.go
vendored
9
third_party/message/can_btm_status_rsp.go
vendored
@ -26,12 +26,14 @@ type BtmStatusRspFrame struct {
|
|||||||
//BTM detailed code
|
//BTM detailed code
|
||||||
DetailedCode byte
|
DetailedCode byte
|
||||||
//有具体报文内容时TK A时刻填充为CD信号上升沿时刻,报文全零时TK A时刻填充为CD信号下降沿时刻。
|
//有具体报文内容时TK A时刻填充为CD信号上升沿时刻,报文全零时TK A时刻填充为CD信号下降沿时刻。
|
||||||
TkTimeA uint32
|
TkTimeA uint32
|
||||||
|
IsTrainPcSim bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBtmStatusRspFrame(sn byte) *BtmStatusRspFrame {
|
func NewBtmStatusRspFrame(sn byte, isTrainPcSim bool) *BtmStatusRspFrame {
|
||||||
return &BtmStatusRspFrame{
|
return &BtmStatusRspFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn),
|
||||||
|
IsTrainPcSim: isTrainPcSim,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
|
func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
|
||||||
@ -113,6 +115,7 @@ func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
|
|||||||
}
|
}
|
||||||
func (f *BtmStatusRspFrame) Encode() *CanetFrame {
|
func (f *BtmStatusRspFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
cf.IsTrainPcSim = f.IsTrainPcSim
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
|
9
third_party/message/can_btm_time_sync_rsp.go
vendored
9
third_party/message/can_btm_time_sync_rsp.go
vendored
@ -14,12 +14,14 @@ type BtmTimeSyncCheckFrame struct {
|
|||||||
T2 uint32
|
T2 uint32
|
||||||
//T3时刻
|
//T3时刻
|
||||||
//BTM将在T3时刻发送回复帧给ATP,并保持流水号与ATP查询帧一致。
|
//BTM将在T3时刻发送回复帧给ATP,并保持流水号与ATP查询帧一致。
|
||||||
T3 uint32
|
T3 uint32
|
||||||
|
IsTrainPcSim bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewBtmTimeSyncCheckFrame(sn byte) *BtmTimeSyncCheckFrame {
|
func NewBtmTimeSyncCheckFrame(sn byte, isTrainPcSim bool) *BtmTimeSyncCheckFrame {
|
||||||
return &BtmTimeSyncCheckFrame{
|
return &BtmTimeSyncCheckFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn),
|
||||||
|
IsTrainPcSim: isTrainPcSim,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -76,6 +78,7 @@ func (f *BtmTimeSyncCheckFrame) Decode(cf *CanetFrame) bool {
|
|||||||
}
|
}
|
||||||
func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame {
|
func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
cf.IsTrainPcSim = f.IsTrainPcSim
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
|
49
third_party/message/can_net.go
vendored
49
third_party/message/can_net.go
vendored
@ -8,30 +8,33 @@ import (
|
|||||||
|
|
||||||
// CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(13字节)
|
// CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(13字节)
|
||||||
type CanetFrame struct {
|
type CanetFrame struct {
|
||||||
FF bool //true-1扩展帧
|
FF bool //true-1扩展帧
|
||||||
RTR bool //true-1远程帧
|
RTR bool //true-1远程帧
|
||||||
CanLen byte //CAN帧数据长度[0,8],CanData中有效数据字节数
|
CanLen byte //CAN帧数据长度[0,8],CanData中有效数据字节数
|
||||||
CanId CanFrameId //CAN帧ID
|
CanId CanFrameId //CAN帧ID
|
||||||
CanData []byte //CAN帧数据,8字节
|
CanData []byte //CAN帧数据,8字节
|
||||||
|
IsTrainPcSim bool //是否列车pc仿真
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCanetFrame(buf []byte) *CanetFrame {
|
func NewCanetFrame(buf []byte, isTrainPcSim bool) *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{IsTrainPcSim: isTrainPcSim}
|
||||||
cf.Decode(buf)
|
cf.Decode(buf)
|
||||||
return cf
|
return cf
|
||||||
}
|
}
|
||||||
func (p *CanetFrame) Encode() []byte {
|
func (p *CanetFrame) Encode() []byte {
|
||||||
buf := make([]byte, 0, 13)
|
buf := make([]byte, 0)
|
||||||
//canet200帧信息
|
if !p.IsTrainPcSim {
|
||||||
b1 := byte(0x00)
|
//canet200帧信息
|
||||||
if p.FF {
|
b1 := byte(0x00)
|
||||||
b1 |= 0x80 //bit7
|
if p.FF {
|
||||||
|
b1 |= 0x80 //bit7
|
||||||
|
}
|
||||||
|
if p.RTR {
|
||||||
|
b1 |= 0x40 //bit6
|
||||||
|
}
|
||||||
|
b1 |= p.CanLen & 0x0f
|
||||||
|
buf = append(buf, b1)
|
||||||
}
|
}
|
||||||
if p.RTR {
|
|
||||||
b1 |= 0x40 //bit6
|
|
||||||
}
|
|
||||||
b1 |= p.CanLen & 0x0f
|
|
||||||
buf = append(buf, b1)
|
|
||||||
//CAN 帧ID
|
//CAN 帧ID
|
||||||
buf = append(buf, p.CanId.ID1)
|
buf = append(buf, p.CanId.ID1)
|
||||||
buf = append(buf, p.CanId.ID2)
|
buf = append(buf, p.CanId.ID2)
|
||||||
@ -44,13 +47,17 @@ func (p *CanetFrame) Encode() []byte {
|
|||||||
buf = append(buf, p.CanData...)
|
buf = append(buf, p.CanData...)
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *CanetFrame) Decode(buf []byte) {
|
func (p *CanetFrame) Decode(buf []byte) {
|
||||||
if len(buf) != 13 {
|
if len(buf) != 13 {
|
||||||
panic("len(buf)!=13")
|
panic("len(buf)!=13")
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
p.FF = buf[0]&0x80 == 0x80
|
if !p.IsTrainPcSim {
|
||||||
p.RTR = buf[0]&0x40 == 0x40
|
p.FF = buf[0]&0x80 == 0x80
|
||||||
|
p.RTR = buf[0]&0x40 == 0x40
|
||||||
|
}
|
||||||
|
|
||||||
p.CanLen = buf[0] & 0x0f
|
p.CanLen = buf[0] & 0x0f
|
||||||
//1 2 3 4
|
//1 2 3 4
|
||||||
p.CanId.ID1 = buf[1]
|
p.CanId.ID1 = buf[1]
|
||||||
@ -62,8 +69,8 @@ func (p *CanetFrame) Decode(buf []byte) {
|
|||||||
}
|
}
|
||||||
func (p *CanetFrame) String() string {
|
func (p *CanetFrame) String() string {
|
||||||
sb := strings.Builder{}
|
sb := strings.Builder{}
|
||||||
sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x,", p.FF, p.RTR, p.CanLen,
|
sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x, isTrainPcSim=%v", p.FF, p.RTR, p.CanLen,
|
||||||
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
|
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4, p.IsTrainPcSim))
|
||||||
sb.WriteString("CanData = ")
|
sb.WriteString("CanData = ")
|
||||||
for _, d := range p.CanData {
|
for _, d := range p.CanData {
|
||||||
sb.WriteString(fmt.Sprintf(" 0x%0x ", d))
|
sb.WriteString(fmt.Sprintf(" 0x%0x ", d))
|
||||||
|
191
third_party/train_pc_sim/train_pc_sim.go
vendored
Normal file
191
third_party/train_pc_sim/train_pc_sim.go
vendored
Normal file
@ -0,0 +1,191 @@
|
|||||||
|
package train_pc_sim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/dto/state_proto"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/tcp"
|
||||||
|
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
||||||
|
"joylink.club/ecs"
|
||||||
|
"log/slog"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type TrainPcSim interface {
|
||||||
|
Start(pcSimManage TrainPcSimManage)
|
||||||
|
Stop()
|
||||||
|
SendDriverActive(tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState)
|
||||||
|
SendHandleSwitch(oldTraction, oldBrakeForce int64, tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState)
|
||||||
|
SendBaliseData(msgType uint16, data []byte)
|
||||||
|
PublishTrainControlEvent(world ecs.World, events []TrainControlEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
type TrainPcSimManage interface {
|
||||||
|
GetTrainPcSimConfig() config.VehiclePCSimConfig
|
||||||
|
//4.4.1. 车载输出数字量信息报文内容
|
||||||
|
TrainPcSimDigitalOutInfoHandle(data []byte)
|
||||||
|
//4.4.2. 车载输出数字反馈量信息报文内容
|
||||||
|
TrainPcSimDigitalReportHandle(data []byte)
|
||||||
|
//创建/删除列车
|
||||||
|
TrainPcSimConnOrRemoveHandle(state byte)
|
||||||
|
//门模式
|
||||||
|
TrainDoorModeHandle(state byte)
|
||||||
|
TrainPcSimMockInfo(data []byte)
|
||||||
|
|
||||||
|
TrainBtmQuery(data []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
initLock = &sync.Mutex{}
|
||||||
|
singleObj *trainPcSimService
|
||||||
|
)
|
||||||
|
|
||||||
|
func Default() TrainPcSim {
|
||||||
|
defer initLock.Unlock()
|
||||||
|
initLock.Lock()
|
||||||
|
if singleObj == nil {
|
||||||
|
singleObj = &trainPcSimService{}
|
||||||
|
}
|
||||||
|
return singleObj
|
||||||
|
}
|
||||||
|
|
||||||
|
type trainPcSimService struct {
|
||||||
|
pcSimClient *tcp.TcpClient
|
||||||
|
cancleContext context.CancelFunc
|
||||||
|
trainPcSimManage TrainPcSimManage
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
|
||||||
|
config := pcSimManage.GetTrainPcSimConfig()
|
||||||
|
if config.PcSimIp == "" || !config.Open {
|
||||||
|
slog.Info("车载pc仿真配置未开启")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
client, err := tcp.StartTcpClient(fmt.Sprintf("%v:%v", config.PcSimIp, config.PcSimPort), pc.reivceData)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("连接车载pc平台失败", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pc.pcSimClient = client
|
||||||
|
ctx, ctxFun := context.WithCancel(context.Background())
|
||||||
|
pc.cancleContext = ctxFun
|
||||||
|
pc.trainPcSimManage = pcSimManage
|
||||||
|
vs := pcSimManage.(*memory.VerifySimulation)
|
||||||
|
FireTrainControlEventType.Subscribe(vs.World, pc.trainControlEventHandle)
|
||||||
|
|
||||||
|
go pc.sendTrainLocationAndSpeedTask(ctx)
|
||||||
|
}
|
||||||
|
func (pc *trainPcSimService) Stop() {
|
||||||
|
if pc.cancleContext != nil {
|
||||||
|
pc.cancleContext()
|
||||||
|
pc.cancleContext = nil
|
||||||
|
}
|
||||||
|
pc.pcSimClient.Close()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 依据文档80ms发送列车速度位置
|
||||||
|
func (pc *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
/* trainStatus := acc.radarVobcManager.FindAccTrain()
|
||||||
|
if trainStatus != nil {
|
||||||
|
speedAcc := trainStatus.DynamicState.Acceleration
|
||||||
|
t := speedAcc / accSpeedUnit
|
||||||
|
acc.vobcClient.SendMsg(&message.Accelerometer{Acc: math.Float32bits(t)})
|
||||||
|
}*/
|
||||||
|
time.Sleep(time.Millisecond * 80)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (pc *trainPcSimService) SendDriverActive(tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState) {
|
||||||
|
if tc.Conn && tc.ConnType == state_proto.TrainConnState_PC_SIM {
|
||||||
|
defulatBuf := make([]byte, 0)
|
||||||
|
msg := &TrainPcSimBaseMessage{Data: defulatBuf}
|
||||||
|
if vobc.Tc1Active || vobc.Tc2Active {
|
||||||
|
msg.Type = SENDER_TRAIN_TC_ACTIVE
|
||||||
|
} else if vobc.Tc1Active == false && vobc.Tc2Active == false {
|
||||||
|
msg.Type = SENDER_TRAIN_TC_NOT_ACTIVE
|
||||||
|
}
|
||||||
|
pc.pcSimClient.Send(msg.Encode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (pc *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, tc *state_proto.TrainConnState, vobc *state_proto.TrainVobcState) {
|
||||||
|
if tc.Conn && tc.ConnType == state_proto.TrainConnState_PC_SIM {
|
||||||
|
msg := &TrainPcSimBaseMessage{}
|
||||||
|
newTraction := vobc.TractionForce
|
||||||
|
newBrake := vobc.BrakeForce
|
||||||
|
if newTraction <= oldTraction && newTraction == 0 {
|
||||||
|
//手柄取消前进
|
||||||
|
msg.Type = RECIVE_TRAIN_HAND_KEY_CANCLE_FORWARD
|
||||||
|
} else if newTraction > oldTraction {
|
||||||
|
//手柄前进
|
||||||
|
msg.Type = SENDER_TRAIN_HAND_KEY_FORWARD
|
||||||
|
} else if newBrake >= oldBrakeForce && newBrake == 0 {
|
||||||
|
//手柄取消后退
|
||||||
|
msg.Type = RECIVE_TRAIN_HAND_KEY_CACLE_BACKWARD
|
||||||
|
} else if newBrake < oldBrakeForce {
|
||||||
|
//手柄后退
|
||||||
|
msg.Type = RECIVE_TRAIN_HAND_KEY_BACKWARD
|
||||||
|
} else {
|
||||||
|
slog.Error("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
pc.pcSimClient.Send(msg.Encode())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *trainPcSimService) SendBaliseData(msgType uint16, data []byte) {
|
||||||
|
msg := &TrainPcSimBaseMessage{}
|
||||||
|
msg.Type = msgType
|
||||||
|
msg.Data = data
|
||||||
|
pc.pcSimClient.Send(msg.Encode())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (pc *trainPcSimService) trainControlEventHandle(w ecs.World, event TrainControlEvent) {
|
||||||
|
msg := &TrainPcSimBaseMessage{}
|
||||||
|
msg.Type = SENDER_TRAIN_OUTR_INFO
|
||||||
|
data := []byte{event.Command, event.Status}
|
||||||
|
msg.Data = data
|
||||||
|
pc.pcSimClient.Send(msg.Encode())
|
||||||
|
}
|
||||||
|
func (pc *trainPcSimService) PublishTrainControlEvent(world ecs.World, events []TrainControlEvent) {
|
||||||
|
if len(events) <= 0 {
|
||||||
|
slog.Warn("")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, event := range events {
|
||||||
|
FireTrainControlEventType.Publish(world, &event)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接受来自pc仿真的消息
|
||||||
|
func (pc *trainPcSimService) reivceData(len int, data []byte) {
|
||||||
|
baseMsg := &TrainPcSimBaseMessage{}
|
||||||
|
err := baseMsg.Decode(data)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("车载pc仿真接受数据解析失败 ")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch baseMsg.Type {
|
||||||
|
case RECIVE_TRAIN_CREATE_REMOVE:
|
||||||
|
pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(data[0])
|
||||||
|
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR:
|
||||||
|
pc.trainPcSimManage.TrainPcSimDigitalOutInfoHandle(data)
|
||||||
|
case RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
|
||||||
|
pc.trainPcSimManage.TrainPcSimDigitalReportHandle(data)
|
||||||
|
case RECIVE_TRAIN_QUERY_STATUS:
|
||||||
|
pc.trainPcSimManage.TrainBtmQuery(data)
|
||||||
|
case RECIVE_TRAIN_MOCK_DATA:
|
||||||
|
pc.trainPcSimManage.TrainPcSimMockInfo(data)
|
||||||
|
case RECIVE_TRAIN_DOOR_MODE:
|
||||||
|
pc.trainPcSimManage.TrainDoorModeHandle(data[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
95
third_party/train_pc_sim/train_pc_sim_message.go
vendored
Normal file
95
third_party/train_pc_sim/train_pc_sim_message.go
vendored
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package train_pc_sim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"fmt"
|
||||||
|
"github.com/snksoft/crc"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
)
|
||||||
|
|
||||||
|
const PC_SIM_HEADER = 0xEB
|
||||||
|
|
||||||
|
type TrainPcSimBaseMessage struct {
|
||||||
|
Type uint16
|
||||||
|
DataLen byte
|
||||||
|
Data []byte
|
||||||
|
Crc uint16 // 校验码
|
||||||
|
}
|
||||||
|
|
||||||
|
// 编码
|
||||||
|
func (tp *TrainPcSimBaseMessage) Encode() []byte {
|
||||||
|
pack := make([]byte, 0)
|
||||||
|
pack = append(pack, PC_SIM_HEADER)
|
||||||
|
pack = binary.BigEndian.AppendUint16(pack, tp.Type)
|
||||||
|
pack = append(pack, byte(len(tp.Data)))
|
||||||
|
dataBufs := bytes.NewBuffer(tp.Data)
|
||||||
|
binary.Write(dataBufs, binary.BigEndian, tp.Data)
|
||||||
|
data := dataBufs.Bytes()
|
||||||
|
pack = append(pack, data...)
|
||||||
|
pack = binary.BigEndian.AppendUint16(pack, uint16(crc.CalculateCRC(crc.CRC16, data)))
|
||||||
|
return pack
|
||||||
|
}
|
||||||
|
|
||||||
|
// 解码
|
||||||
|
func (tp *TrainPcSimBaseMessage) Decode(data []byte) error {
|
||||||
|
if len(data) < 3 {
|
||||||
|
return fmt.Errorf("")
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer(data)
|
||||||
|
h, _ := buf.ReadByte()
|
||||||
|
if h != PC_SIM_HEADER {
|
||||||
|
return fmt.Errorf("")
|
||||||
|
}
|
||||||
|
var pcType uint16
|
||||||
|
binary.Read(buf, binary.BigEndian, &pcType)
|
||||||
|
len, _ := buf.ReadByte()
|
||||||
|
if buf.Len() < int(len)+2 {
|
||||||
|
return fmt.Errorf("")
|
||||||
|
}
|
||||||
|
var dd = make([]byte, 0, len)
|
||||||
|
binary.Read(buf, binary.BigEndian, &dd)
|
||||||
|
var crcCode uint16
|
||||||
|
binary.Read(buf, binary.BigEndian, &crcCode)
|
||||||
|
tp.Type = pcType
|
||||||
|
tp.DataLen = len
|
||||||
|
tp.Data = dd
|
||||||
|
tp.Crc = crcCode
|
||||||
|
return nil
|
||||||
|
//crc.CalculateCRC(crc.CRC16, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func IsTrue(d bool) byte {
|
||||||
|
if d {
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
func IsTrueForByte(d byte) bool {
|
||||||
|
if d == 1 {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列车pc仿真btm查询
|
||||||
|
type TrainPcSimBtmQueryFrame struct {
|
||||||
|
message.CanetFrame //这里不是用 can 网络的前2帧
|
||||||
|
}
|
||||||
|
|
||||||
|
// func (pc *TrainPcSimBtmQueryFrame) GetCanFrameId() message.CanFrameId {
|
||||||
|
// return pc.CanId
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// func (pc *TrainPcSimBtmQueryFrame) GetCanFrameData() []byte {
|
||||||
|
// return pc.CanData
|
||||||
|
// }
|
||||||
|
func (q *TrainPcSimBtmQueryFrame) Decode(d []byte) error {
|
||||||
|
q.CanId.ID1 = d[0]
|
||||||
|
q.CanId.ID2 = d[1]
|
||||||
|
q.CanId.ID3 = d[2]
|
||||||
|
q.CanId.ID4 = d[3] >> 3
|
||||||
|
//
|
||||||
|
q.CanData = d[4:]
|
||||||
|
return nil
|
||||||
|
}
|
103
third_party/train_pc_sim/train_pc_sim_message_sender.go
vendored
Normal file
103
third_party/train_pc_sim/train_pc_sim_message_sender.go
vendored
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
package train_pc_sim
|
||||||
|
|
||||||
|
import (
|
||||||
|
"joylink.club/ecs"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
//钥匙开关状态
|
||||||
|
KEY_STATE = iota
|
||||||
|
//手柄向前控制
|
||||||
|
HANDLE_FORWORD
|
||||||
|
//手柄向后控制
|
||||||
|
HANDLE_BACKWORD
|
||||||
|
//外部紧急制动反馈
|
||||||
|
OUTER_EMERGENCY_BRAKE
|
||||||
|
//列车制动状态
|
||||||
|
TRAIN_BRAKE_STATE
|
||||||
|
//开左门
|
||||||
|
LEFT_OPEN_DOOR
|
||||||
|
//关右门
|
||||||
|
CLOSE_RIGHT_DOOR
|
||||||
|
//关左门
|
||||||
|
CLOSE_LEFT_DOOR
|
||||||
|
//开右门
|
||||||
|
OPEN_RIGHT_DOOR
|
||||||
|
//折返按钮
|
||||||
|
TURN_BACK
|
||||||
|
//强制门允许
|
||||||
|
FORCE_DOOR_ALLOW
|
||||||
|
//模式降级按钮
|
||||||
|
TRAIN_MODE_DOWN
|
||||||
|
|
||||||
|
//确认按钮
|
||||||
|
CONFIRM
|
||||||
|
//模式升级按钮
|
||||||
|
TRAIN_MODE_UP
|
||||||
|
//牵引制动手柄零位
|
||||||
|
HANDLE_TO_ZERO
|
||||||
|
//ATO发车按钮
|
||||||
|
ATO_SEND_TRAIN
|
||||||
|
|
||||||
|
//列车完整性
|
||||||
|
TRAIN_INTEGRITY
|
||||||
|
//车载ATP/ATO旁路状态
|
||||||
|
ATP_ATO_BYPASS_STATe
|
||||||
|
//车辆牵引已切除状态
|
||||||
|
TRAIN_TRACTION_CUTED
|
||||||
|
//障碍物检测按钮
|
||||||
|
OBSTACLE_CHECK
|
||||||
|
//驾驶室激活反馈按钮
|
||||||
|
DRIVER_ACTIVE_REPORT
|
||||||
|
//制动重故障按钮
|
||||||
|
BRAKE_HEAVY_FAULT
|
||||||
|
//左门状态按钮
|
||||||
|
LEFT_DOOR_STATE
|
||||||
|
//右门状态按钮
|
||||||
|
RIGHT_DOOR_STATE
|
||||||
|
//唤醒按钮
|
||||||
|
WAKE_UP
|
||||||
|
//检修按钮
|
||||||
|
OVERHAUL
|
||||||
|
//欠压按钮
|
||||||
|
UNDERVOLTAGE
|
||||||
|
//休眠按钮
|
||||||
|
SLEEP
|
||||||
|
_
|
||||||
|
//紧急手柄拉下
|
||||||
|
EMERGENT_HANDLE_DOWN
|
||||||
|
//车门锁闭状态
|
||||||
|
DOOR_LOCK_STATE
|
||||||
|
//逃生门状态
|
||||||
|
LIFE_DOOR
|
||||||
|
//车辆低压上电状态
|
||||||
|
TRAIN_LOW_POWER
|
||||||
|
//ATP上电按钮
|
||||||
|
ATP_POWER_ON
|
||||||
|
_
|
||||||
|
//AA自动开关门
|
||||||
|
DOOR_MODE_AA
|
||||||
|
|
||||||
|
//AM自开人关
|
||||||
|
DOOR_MODE_AM
|
||||||
|
//MM人开人关
|
||||||
|
DOOR_MODE_MM
|
||||||
|
)
|
||||||
|
|
||||||
|
type TrainControlEvent struct {
|
||||||
|
Command byte
|
||||||
|
Status byte
|
||||||
|
}
|
||||||
|
|
||||||
|
var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
|
||||||
|
|
||||||
|
// 应答器组内序号
|
||||||
|
// 唯一标识组内一个应答器,目前固定为1
|
||||||
|
const PC_SIM_BALISE_NUM uint32 = 1
|
||||||
|
|
||||||
|
// 4.3.3. 应答器信息报文内容
|
||||||
|
type TrainPcSimBtm struct {
|
||||||
|
BaliseId uint32 //应答器组ID
|
||||||
|
BaliseLocation float32 //应答器与车头发车位置的距离,单位cm
|
||||||
|
BaliseData []byte //有数据的CAN数据报文
|
||||||
|
}
|
49
third_party/train_pc_sim/train_pc_sim_message_type.go
vendored
Normal file
49
third_party/train_pc_sim/train_pc_sim_message_type.go
vendored
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
package train_pc_sim
|
||||||
|
|
||||||
|
const (
|
||||||
|
//仿真系统车载pc仿真平台
|
||||||
|
|
||||||
|
//车辆输出数字量信息
|
||||||
|
SENDER_TRAIN_OUTR_INFO = 0x00
|
||||||
|
//速度位置信息
|
||||||
|
sender_train_location_info = 0x01
|
||||||
|
//驾驶室激活
|
||||||
|
SENDER_TRAIN_TC_ACTIVE = 0x04
|
||||||
|
//驾驶室未激活
|
||||||
|
SENDER_TRAIN_TC_NOT_ACTIVE = 0x05
|
||||||
|
|
||||||
|
//手柄前进
|
||||||
|
SENDER_TRAIN_HAND_KEY_FORWARD = 0x06
|
||||||
|
|
||||||
|
//车载pc仿真平台 仿真系统
|
||||||
|
|
||||||
|
//手柄取消前进(注1)
|
||||||
|
RECIVE_TRAIN_HAND_KEY_CANCLE_FORWARD = 0x07
|
||||||
|
//手柄后退
|
||||||
|
RECIVE_TRAIN_HAND_KEY_BACKWARD = 0x08
|
||||||
|
//手柄取消后退(注1)
|
||||||
|
RECIVE_TRAIN_HAND_KEY_CACLE_BACKWARD = 0x09
|
||||||
|
//有数据应答器
|
||||||
|
RECIVE_TRAIN_BTM_HAS_DATA = 0x31
|
||||||
|
|
||||||
|
//无数据应答器
|
||||||
|
RECIVE_TRAIN_BTM_NOT_DATA = 0x32
|
||||||
|
|
||||||
|
//清空所有预发应答器
|
||||||
|
recive_train_btn_clear_all_pre_data = 0x33
|
||||||
|
//创建/删除列车
|
||||||
|
RECIVE_TRAIN_CREATE_REMOVE = 0x50
|
||||||
|
|
||||||
|
//门模式
|
||||||
|
RECIVE_TRAIN_DOOR_MODE = 0x60
|
||||||
|
|
||||||
|
//车载接口柜输出数字量信息
|
||||||
|
RECIVE_TRAIN_INTERFACE_CABINET_OUTR = 0x01
|
||||||
|
//车载接口柜输出数字反馈量信息
|
||||||
|
RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK = 0x02
|
||||||
|
//电流环模拟量
|
||||||
|
RECIVE_TRAIN_MOCK_DATA = 0x03
|
||||||
|
|
||||||
|
//状态查询帧
|
||||||
|
RECIVE_TRAIN_QUERY_STATUS = 0x04
|
||||||
|
)
|
@ -139,7 +139,7 @@ func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
train := data.(*state_proto.TrainState)
|
train := data.(*state_proto.TrainState)
|
||||||
train.ConnState.Conn = conn
|
//train.ConnState.Conn = conn
|
||||||
train.ConnState.ConnType = ct.ConnType
|
train.ConnState.ConnType = ct.ConnType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,118 +0,0 @@
|
|||||||
package memory
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/request_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/sys_error"
|
|
||||||
)
|
|
||||||
|
|
||||||
/*func createTrainControl(vs *VerifySimulation) *state_proto.TrainControlState {
|
|
||||||
var tccMapId int32
|
|
||||||
for _, mapId := range vs.MapIds {
|
|
||||||
picProType := QueryGiType(mapId)
|
|
||||||
if picProType == data_proto.PictureType_TrainControlCab {
|
|
||||||
tccMapId = mapId
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if tccMapId == 0 {
|
|
||||||
panic(sys_error.New("未找到列车控制相关图形数据"))
|
|
||||||
}
|
|
||||||
tcs := &state_proto.TrainControlState{
|
|
||||||
ConnState: &state_proto.TrainConnState{Conn: false, ConnType: state_proto.TrainConnState_NONE},
|
|
||||||
}
|
|
||||||
tcc := QueryUidStructure[*TccUidStructure](tccMapId)
|
|
||||||
for _, d := range tcc.ButtonIds {
|
|
||||||
tcs.Buttons = append(tcs.Buttons, &state_proto.TrainControlState_TccButton{Id: d.CommonId, Code: d.Code})
|
|
||||||
}
|
|
||||||
for _, d := range tcc.Keys {
|
|
||||||
tcs.Keys = append(tcs.Keys, &state_proto.TrainControlState_TccKey{Id: d.CommonId, Code: d.Code})
|
|
||||||
}
|
|
||||||
for _, d := range tcc.Handler {
|
|
||||||
tcs.Handlers = append(tcs.Handlers, &state_proto.TrainControlState_TccHander{Id: d.CommonId, Code: d.Code})
|
|
||||||
}
|
|
||||||
return tcs
|
|
||||||
}*/
|
|
||||||
// 列车控制修改参数
|
|
||||||
func ControlTrainUpdate(vs *VerifySimulation, ct *request_proto.TrainControl) {
|
|
||||||
allTrainMap := &vs.Memory.Status.TrainStateMap
|
|
||||||
data, ok := allTrainMap.Load(ct.TrainId)
|
|
||||||
if !ok {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", ct.TrainId)))
|
|
||||||
}
|
|
||||||
sta := data.(*state_proto.TrainState)
|
|
||||||
|
|
||||||
if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON {
|
|
||||||
trainControlEB(sta, ct.Button, ct.DeviceId)
|
|
||||||
} else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH {
|
|
||||||
trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId)
|
|
||||||
} else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH {
|
|
||||||
trainControlDirKey(sta, ct.DirKey, ct.DeviceId)
|
|
||||||
} else if ct.ControlType == request_proto.TrainControl_HANDLER {
|
|
||||||
trainControlHandle(sta, ct.Handler, ct.DeviceId)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func trainControlEB(trainState *state_proto.TrainState, request *request_proto.TrainControl_EmergentButton, deviceId uint32) {
|
|
||||||
trainState.VobcState.EmergencyBrakingStatus = request.Active
|
|
||||||
if trainState.Tcc.Ebutton == nil {
|
|
||||||
trainState.Tcc.Ebutton = &state_proto.TrainControlState_EmergentButton{Id: deviceId, Passed: request.Active}
|
|
||||||
} else {
|
|
||||||
trainState.Tcc.Ebutton.Passed = request.Active
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func trainControlDirKey(trainState *state_proto.TrainState, request *request_proto.TrainControl_DirectionKeySwitch, deviceId uint32) {
|
|
||||||
trainState.VobcState.DirectionForward = false
|
|
||||||
trainState.VobcState.DirectionBackward = false
|
|
||||||
if request.Val == 1 {
|
|
||||||
trainState.VobcState.DirectionForward = true
|
|
||||||
} else if request.Val == 0 {
|
|
||||||
trainState.VobcState.DirectionBackward = false
|
|
||||||
}
|
|
||||||
if trainState.Tcc.DirKey == nil {
|
|
||||||
trainState.Tcc.DirKey = &state_proto.TrainControlState_DirectionKeySwitch{Id: deviceId, Val: request.Val}
|
|
||||||
} else {
|
|
||||||
trainState.Tcc.DirKey.Val = request.Val
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func trainControlDriverKey(trainState *state_proto.TrainState, request *request_proto.TrainControl_DriverKeySwitch, deviceId uint32) {
|
|
||||||
if request.Dt == request_proto.DriverType_ONE_END {
|
|
||||||
trainState.VobcState.Tc1Active = request.Val
|
|
||||||
} else if request.Dt == request_proto.DriverType_TWO_END {
|
|
||||||
trainState.VobcState.Tc2Active = request.Val
|
|
||||||
}
|
|
||||||
var addNew = true
|
|
||||||
for _, k := range trainState.Tcc.DriverKey {
|
|
||||||
if k.Id == deviceId {
|
|
||||||
k.Dt = request.Dt
|
|
||||||
k.Id = deviceId
|
|
||||||
k.Val = request.Val
|
|
||||||
addNew = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if addNew {
|
|
||||||
trainState.Tcc.DriverKey = append(trainState.Tcc.DriverKey, &state_proto.TrainControlState_DriverKeySwitch{Id: deviceId, Val: request.Val, Dt: request.Dt})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func trainControlHandle(trainState *state_proto.TrainState, request *request_proto.TrainControl_PushHandler, deviceId uint32) {
|
|
||||||
trainState.VobcState.TractionStatus = false
|
|
||||||
trainState.VobcState.TractionForce = 0
|
|
||||||
trainState.VobcState.BrakingStatus = false
|
|
||||||
trainState.VobcState.BrakeForce = 0
|
|
||||||
if request.Val > 0 {
|
|
||||||
trainState.VobcState.TractionStatus = true
|
|
||||||
trainState.VobcState.TractionForce = int64(request.Val)
|
|
||||||
} else if request.Val < 0 {
|
|
||||||
trainState.VobcState.BrakingStatus = true
|
|
||||||
trainState.VobcState.BrakeForce = int64(request.Val)
|
|
||||||
}
|
|
||||||
if trainState.Tcc.DirKey == nil {
|
|
||||||
trainState.Tcc.PushHandler = &state_proto.TrainControlState_PushHandler{Id: deviceId, Val: request.Val}
|
|
||||||
} else {
|
|
||||||
trainState.Tcc.PushHandler.Val = request.Val
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -134,10 +134,6 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRun
|
|||||||
// return s.runState
|
// return s.runState
|
||||||
// }
|
// }
|
||||||
|
|
||||||
func (s *VerifySimulation) GetTrainPcSimConfig() config.VehiclePCSimConfig {
|
|
||||||
return s.runConfig.PcSimConfig
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取仿真世界信息
|
// 获取仿真世界信息
|
||||||
func (s *VerifySimulation) GetComIdByUid(uid string) uint32 {
|
func (s *VerifySimulation) GetComIdByUid(uid string) uint32 {
|
||||||
es := s.UidMap
|
es := s.UidMap
|
||||||
@ -391,11 +387,11 @@ func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(b []byte) {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
connState := train.ConnState
|
connState := train.ConnState
|
||||||
|
trainId, err := strconv.Atoi(train.Id)
|
||||||
|
if err != nil {
|
||||||
|
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
|
||||||
|
}
|
||||||
if connState.Conn == true && connState.ConnType == state_proto.TrainConnState_VOBC {
|
if connState.Conn == true && connState.ConnType == state_proto.TrainConnState_VOBC {
|
||||||
trainId, err := strconv.Atoi(train.Id)
|
|
||||||
if err != nil {
|
|
||||||
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
|
|
||||||
}
|
|
||||||
d := append(b, uint8(trainId))
|
d := append(b, uint8(trainId))
|
||||||
// 发送给动力学
|
// 发送给动力学
|
||||||
dynamics.Default().SendTrainControlMessage(d)
|
dynamics.Default().SendTrainControlMessage(d)
|
||||||
|
404
ts/simulation/wayside/memory/wayside_simulation_train_pc.go
Normal file
404
ts/simulation/wayside/memory/wayside_simulation_train_pc.go
Normal file
@ -0,0 +1,404 @@
|
|||||||
|
package memory
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/const/balise_const"
|
||||||
|
"joylink.club/bj-rtsts-server/dto/request_proto"
|
||||||
|
"joylink.club/bj-rtsts-server/dto/state_proto"
|
||||||
|
"joylink.club/bj-rtsts-server/sys_error"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/can_btm"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim"
|
||||||
|
"log/slog"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *VerifySimulation) GetTrainPcSimConfig() config.VehiclePCSimConfig {
|
||||||
|
return s.runConfig.PcSimConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列车控制
|
||||||
|
func (s *VerifySimulation) ControlTrainUpdate(ct *request_proto.TrainControl) {
|
||||||
|
allTrainMap := &s.Memory.Status.TrainStateMap
|
||||||
|
data, ok := allTrainMap.Load(ct.TrainId)
|
||||||
|
if !ok {
|
||||||
|
panic(sys_error.New(fmt.Sprintf("列车【%s】不存在", ct.TrainId)))
|
||||||
|
}
|
||||||
|
sta := data.(*state_proto.TrainState)
|
||||||
|
var tce []train_pc_sim.TrainControlEvent = nil
|
||||||
|
if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON {
|
||||||
|
trainControlEB(sta, ct.Button, ct.DeviceId)
|
||||||
|
} else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH {
|
||||||
|
tce = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId)
|
||||||
|
train_pc_sim.Default().SendDriverActive(sta.ConnState, sta.VobcState)
|
||||||
|
} else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH {
|
||||||
|
trainControlDirKey(sta, ct.DirKey, ct.DeviceId)
|
||||||
|
} else if ct.ControlType == request_proto.TrainControl_HANDLER {
|
||||||
|
oldTraction := sta.VobcState.TractionForce
|
||||||
|
oldBrakeForce := sta.VobcState.BrakeForce
|
||||||
|
tce = trainControlHandle(sta, ct.Handler, ct.DeviceId)
|
||||||
|
train_pc_sim.Default().SendHandleSwitch(oldTraction, oldBrakeForce, sta.ConnState, sta.VobcState)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !sta.ConnState.Conn && sta.ConnState.ConnType != state_proto.TrainConnState_PC_SIM {
|
||||||
|
slog.Error("当前列车未连接车载pc仿真,", sta.Id)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
train_pc_sim.Default().PublishTrainControlEvent(s.World, tce)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func trainControlEB(trainState *state_proto.TrainState, request *request_proto.TrainControl_EmergentButton, deviceId uint32) {
|
||||||
|
trainState.VobcState.EmergencyBrakingStatus = request.Active
|
||||||
|
if trainState.Tcc.Ebutton == nil {
|
||||||
|
trainState.Tcc.Ebutton = &state_proto.TrainControlState_EmergentButton{Id: deviceId, Passed: request.Active}
|
||||||
|
} else {
|
||||||
|
trainState.Tcc.Ebutton.Passed = request.Active
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列车方向
|
||||||
|
func trainControlDirKey(trainState *state_proto.TrainState, request *request_proto.TrainControl_DirectionKeySwitch, deviceId uint32) {
|
||||||
|
trainState.VobcState.DirectionForward = false
|
||||||
|
trainState.VobcState.DirectionBackward = false
|
||||||
|
if request.Val == 1 {
|
||||||
|
trainState.VobcState.DirectionForward = true
|
||||||
|
} else if request.Val == 0 {
|
||||||
|
trainState.VobcState.DirectionBackward = false
|
||||||
|
}
|
||||||
|
if trainState.Tcc.DirKey == nil {
|
||||||
|
trainState.Tcc.DirKey = &state_proto.TrainControlState_DirectionKeySwitch{Id: deviceId, Val: request.Val}
|
||||||
|
} else {
|
||||||
|
trainState.Tcc.DirKey.Val = request.Val
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列车驾驶端激活
|
||||||
|
func trainControlDriverKey(trainState *state_proto.TrainState, request *request_proto.TrainControl_DriverKeySwitch, deviceId uint32) []train_pc_sim.TrainControlEvent {
|
||||||
|
if request.Dt == request_proto.DriverType_ONE_END {
|
||||||
|
trainState.VobcState.Tc1Active = request.Val
|
||||||
|
} else if request.Dt == request_proto.DriverType_TWO_END {
|
||||||
|
trainState.VobcState.Tc2Active = request.Val
|
||||||
|
}
|
||||||
|
var addNew = true
|
||||||
|
for _, k := range trainState.Tcc.DriverKey {
|
||||||
|
if k.Id == deviceId {
|
||||||
|
k.Id = deviceId
|
||||||
|
k.Val = request.Val
|
||||||
|
addNew = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if addNew {
|
||||||
|
trainState.Tcc.DriverKey = append(trainState.Tcc.DriverKey, &state_proto.TrainControlState_DriverKeySwitch{Id: deviceId, Val: request.Val})
|
||||||
|
}
|
||||||
|
return []train_pc_sim.TrainControlEvent{{Command: train_pc_sim.KEY_STATE, Status: train_pc_sim.IsTrue(request.Val)}}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// 列车牵引控制
|
||||||
|
func trainControlHandle(trainState *state_proto.TrainState, request *request_proto.TrainControl_PushHandler, deviceId uint32) []train_pc_sim.TrainControlEvent {
|
||||||
|
trainState.VobcState.TractionStatus = false
|
||||||
|
trainState.VobcState.TractionForce = 0
|
||||||
|
trainState.VobcState.BrakingStatus = false
|
||||||
|
trainState.VobcState.BrakeForce = 0
|
||||||
|
tce := make([]train_pc_sim.TrainControlEvent, 0)
|
||||||
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_FORWORD, Status: 0})
|
||||||
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_BACKWORD, Status: 0})
|
||||||
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_TO_ZERO, Status: 0})
|
||||||
|
if request.Val > 0 {
|
||||||
|
trainState.VobcState.TractionStatus = true
|
||||||
|
trainState.VobcState.TractionForce = int64(request.Val)
|
||||||
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_FORWORD, Status: 1})
|
||||||
|
} else if request.Val < 0 {
|
||||||
|
trainState.VobcState.BrakingStatus = true
|
||||||
|
trainState.VobcState.BrakeForce = int64(request.Val)
|
||||||
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_BACKWORD, Status: 1})
|
||||||
|
} else {
|
||||||
|
|
||||||
|
tce = append(tce, train_pc_sim.TrainControlEvent{Command: train_pc_sim.HANDLE_TO_ZERO, Status: 1})
|
||||||
|
}
|
||||||
|
if trainState.Tcc.PushHandler == nil {
|
||||||
|
trainState.Tcc.PushHandler = &state_proto.TrainControlState_PushHandler{Id: deviceId, Val: request.Val}
|
||||||
|
} else {
|
||||||
|
trainState.Tcc.PushHandler.Val = request.Val
|
||||||
|
}
|
||||||
|
return tce
|
||||||
|
}
|
||||||
|
func (s *VerifySimulation) findConnTrain(ct state_proto.TrainConnState_TrainConnType) *state_proto.TrainState {
|
||||||
|
var findTrain *state_proto.TrainState
|
||||||
|
s.Memory.Status.TrainStateMap.Range(func(k, v any) bool {
|
||||||
|
train := v.(*state_proto.TrainState)
|
||||||
|
connState := train.ConnState
|
||||||
|
if connState.ConnType == ct {
|
||||||
|
findTrain = train
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
})
|
||||||
|
return findTrain
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.4.1. 车载输出数字量信息报文内容
|
||||||
|
func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(data []byte) {
|
||||||
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||||
|
if train == nil {
|
||||||
|
slog.Error("车载输出数字量,未找到连接车载pc仿真的列车")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !train.ConnState.Conn {
|
||||||
|
slog.Error("车载输出数字量,,列车未连接车载pc仿真")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buf := bytes.NewBuffer(data)
|
||||||
|
vobc := train.VobcState
|
||||||
|
cutTraction, _ := buf.ReadByte() //切牵引
|
||||||
|
trainDoorOutLed, _ := buf.ReadByte() //车门外指示灯
|
||||||
|
stopBrakeAppend, _ := buf.ReadByte() //停放制动施加
|
||||||
|
emergentBrake, _ := buf.ReadByte() //紧急制动
|
||||||
|
leftOpenDoor, _ := buf.ReadByte() //开左门允许
|
||||||
|
rightOpenDoor, _ := buf.ReadByte() //开右门允许
|
||||||
|
closeRightDoor, _ := buf.ReadByte() //关右门
|
||||||
|
doorAlwaysClosed, _ := buf.ReadByte() //车门保持关闭
|
||||||
|
localAtpControl, _ := buf.ReadByte() //本端ATP控车
|
||||||
|
atoMode, _ := buf.ReadByte() //ATO模式
|
||||||
|
atoTractionCommandOut, _ := buf.ReadByte() //ATO牵引命令输出
|
||||||
|
atoTractionCommand1, _ := buf.ReadByte() //ATO牵引指令1
|
||||||
|
atoTractionCommand2, _ := buf.ReadByte() //ATO牵引指令2
|
||||||
|
atoTractionCommand3, _ := buf.ReadByte() //ATO牵引指令3
|
||||||
|
atoBrakeCommand, _ := buf.ReadByte() //ATO制动命令输出
|
||||||
|
skipCommand, _ := buf.ReadByte() //跳跃指令
|
||||||
|
direction1, _ := buf.ReadByte() //列车方向1
|
||||||
|
direction2, _ := buf.ReadByte() //列车方向2
|
||||||
|
atoLazyCommandOut, _ := buf.ReadByte() //ATO惰行命令输出
|
||||||
|
sleepCommand, _ := buf.ReadByte() //休眠指令
|
||||||
|
wakeUpCommand, _ := buf.ReadByte() //唤醒指令
|
||||||
|
toPullTrainLed, _ := buf.ReadByte() //ATO发车指示灯
|
||||||
|
arLightCommand, _ := buf.ReadByte() //AR灯命令
|
||||||
|
atoAlwaysBrake, _ := buf.ReadByte() //ATO保持制动
|
||||||
|
atoOpenLeftDoor, _ := buf.ReadByte() //ATO开左门
|
||||||
|
atoOpenRightDoor, _ := buf.ReadByte() //ATO开右门
|
||||||
|
atoCloseLeftDoor, _ := buf.ReadByte() //ATO关左门
|
||||||
|
ariverActive, _ := buf.ReadByte() //驾驶室激活
|
||||||
|
noSpeedSigle, _ := buf.ReadByte() //零速信号
|
||||||
|
famMode, _ := buf.ReadByte() //FAM模式
|
||||||
|
camMode, _ := buf.ReadByte() //CAM模式
|
||||||
|
trainStartedLed, _ := buf.ReadByte() //列车启动指示灯
|
||||||
|
mostUseBrake, _ := buf.ReadByte() //常用制动
|
||||||
|
splittingOut, _ := buf.ReadByte() //过分相输出
|
||||||
|
modeRelay, _ := buf.ReadByte() //模式继电器
|
||||||
|
tractionEffective, _ := buf.ReadByte() //牵引有效
|
||||||
|
brakeEffective, _ := buf.ReadByte() //制动有效
|
||||||
|
lifeDoorUsed, _ := buf.ReadByte() //逃生门使能
|
||||||
|
brakeQuarantine, _ := buf.ReadByte() //制动隔离
|
||||||
|
stopNotAllBrake, _ := buf.ReadByte() //停放制动缓解
|
||||||
|
|
||||||
|
vobc.TractionSafetyCircuit = train_pc_sim.IsTrueForByte(cutTraction)
|
||||||
|
vobc.TrainDoorOutLed = train_pc_sim.IsTrueForByte(trainDoorOutLed) //? 说明暂无此属性
|
||||||
|
vobc.ParkingBrakeStatus = train_pc_sim.IsTrueForByte(stopBrakeAppend)
|
||||||
|
vobc.EmergencyBrakingStatus = train_pc_sim.IsTrueForByte(emergentBrake)
|
||||||
|
vobc.LeftDoorOpenCommand = train_pc_sim.IsTrueForByte(leftOpenDoor)
|
||||||
|
vobc.RightDoorOpenCommand = train_pc_sim.IsTrueForByte(rightOpenDoor)
|
||||||
|
vobc.RightDoorCloseCommand = train_pc_sim.IsTrueForByte(closeRightDoor)
|
||||||
|
vobc.AllDoorClose = train_pc_sim.IsTrueForByte(doorAlwaysClosed)
|
||||||
|
vobc.LocalAtpControl = train_pc_sim.IsTrueForByte(localAtpControl) //?
|
||||||
|
vobc.Ato = train_pc_sim.IsTrueForByte(atoMode)
|
||||||
|
vobc.AtoTractionCommandOut = train_pc_sim.IsTrueForByte(atoTractionCommandOut) //?
|
||||||
|
|
||||||
|
vobc.AtoTractionCommand1 = train_pc_sim.IsTrueForByte(atoTractionCommand1) //?
|
||||||
|
vobc.AtoTractionCommand2 = train_pc_sim.IsTrueForByte(atoTractionCommand2) //?
|
||||||
|
vobc.AtoTractionCommand3 = train_pc_sim.IsTrueForByte(atoTractionCommand3) //?
|
||||||
|
vobc.AtoBrakeCommand = train_pc_sim.IsTrueForByte(atoBrakeCommand) //?
|
||||||
|
vobc.JumpStatus = train_pc_sim.IsTrueForByte(skipCommand)
|
||||||
|
vobc.DirectionForward = train_pc_sim.IsTrueForByte(direction1)
|
||||||
|
vobc.DirectionBackward = train_pc_sim.IsTrueForByte(direction2)
|
||||||
|
|
||||||
|
vobc.AtoLazyCommandOut = train_pc_sim.IsTrueForByte(atoLazyCommandOut) //?
|
||||||
|
vobc.SleepBtn = train_pc_sim.IsTrueForByte(sleepCommand)
|
||||||
|
vobc.WakeUpBtn = train_pc_sim.IsTrueForByte(wakeUpCommand)
|
||||||
|
vobc.AtoSendTrainBtn = train_pc_sim.IsTrueForByte(toPullTrainLed)
|
||||||
|
vobc.TurnbackStatus = train_pc_sim.IsTrueForByte(arLightCommand) //?
|
||||||
|
vobc.AtoAlwaysBrake = train_pc_sim.IsTrueForByte(atoAlwaysBrake) //?
|
||||||
|
vobc.AtoOpenLeftDoor = train_pc_sim.IsTrueForByte(atoOpenLeftDoor) //?
|
||||||
|
vobc.AtoOpenRightDoor = train_pc_sim.IsTrueForByte(atoOpenRightDoor) //?
|
||||||
|
vobc.AtoCloseLeftDoor = train_pc_sim.IsTrueForByte(atoCloseLeftDoor) //?
|
||||||
|
vobc.Tc1Active = train_pc_sim.IsTrueForByte(ariverActive)
|
||||||
|
vobc.NoSpeedSigle = train_pc_sim.IsTrueForByte(noSpeedSigle) //?
|
||||||
|
vobc.Fam = train_pc_sim.IsTrueForByte(famMode)
|
||||||
|
vobc.Cam = train_pc_sim.IsTrueForByte(camMode)
|
||||||
|
vobc.TrainStartedLed = train_pc_sim.IsTrueForByte(trainStartedLed) //?
|
||||||
|
vobc.MostUseBrake = train_pc_sim.IsTrueForByte(mostUseBrake) //? //常用制动
|
||||||
|
vobc.SplittingOut = train_pc_sim.IsTrueForByte(splittingOut) //? //过分相输出
|
||||||
|
vobc.ModeRelay = train_pc_sim.IsTrueForByte(modeRelay) //? //模式继电器
|
||||||
|
vobc.TractionEffective = train_pc_sim.IsTrueForByte(tractionEffective) //? //牵引有效
|
||||||
|
vobc.BrakeEffective = train_pc_sim.IsTrueForByte(brakeEffective) //? //制动有效
|
||||||
|
vobc.LifeDoorState = train_pc_sim.IsTrueForByte(lifeDoorUsed) //逃生门使能
|
||||||
|
vobc.BrakeQuarantine = train_pc_sim.IsTrueForByte(brakeQuarantine) //? //制动隔离
|
||||||
|
vobc.StopNotAllBrake = train_pc_sim.IsTrueForByte(stopNotAllBrake) //? //停放制动缓解
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.4.2. 车载输出数字反馈量信息报文内容
|
||||||
|
func (s *VerifySimulation) TrainPcSimDigitalReportHandle(data []byte) {
|
||||||
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||||
|
if train == nil {
|
||||||
|
slog.Error("车载输出数字反馈量信息,未找到连接车载pc仿真的列车")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !train.ConnState.Conn {
|
||||||
|
slog.Error("车载输出数字反馈量信息,列车未连接车载pc仿真")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vobc := train.VobcState
|
||||||
|
buf := bytes.NewBuffer(data)
|
||||||
|
localEndAct, _ := buf.ReadByte()
|
||||||
|
direction1, _ := buf.ReadByte()
|
||||||
|
direction2, _ := buf.ReadByte()
|
||||||
|
|
||||||
|
vobc.Tc1Active = train_pc_sim.IsTrueForByte(localEndAct) //本端驾驶室激活(钥匙)
|
||||||
|
vobc.DirectionForward = train_pc_sim.IsTrueForByte(direction1) //方向手柄进位
|
||||||
|
vobc.DirectionBackward = train_pc_sim.IsTrueForByte(direction2) //方向手柄退位
|
||||||
|
}
|
||||||
|
|
||||||
|
// 创建/删除列车
|
||||||
|
func (s *VerifySimulation) TrainPcSimConnOrRemoveHandle(state byte) {
|
||||||
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||||
|
if train == nil {
|
||||||
|
slog.Error("创建删除列车,未找到连接车载pc仿真的列车")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
connState := train.ConnState
|
||||||
|
if state == 0x01 {
|
||||||
|
connState.Conn = true
|
||||||
|
} else {
|
||||||
|
connState.Conn = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 门模式
|
||||||
|
func (s *VerifySimulation) TrainDoorModeHandle(state byte) {
|
||||||
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||||
|
if train == nil {
|
||||||
|
slog.Error("车载pc仿真门模式,未找到连接车载pc仿真的列车")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !train.ConnState.Conn {
|
||||||
|
slog.Error("车载pc仿真门模式,列车未连接车载pc仿真")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
switch state {
|
||||||
|
case 0x00:
|
||||||
|
//0x00表示自开自关(AA)
|
||||||
|
train.VobcState.DoorModeAA = true
|
||||||
|
case 0x01:
|
||||||
|
//0x01表示自开人关(AM)
|
||||||
|
train.VobcState.DoorModeAM = true
|
||||||
|
case 0x02:
|
||||||
|
//0x02表示人开人关(MM)
|
||||||
|
train.VobcState.DoorModeMM = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.4.3. 车载输出模拟量信息报文内容(0x03)
|
||||||
|
func (s *VerifySimulation) TrainPcSimMockInfo(data []byte) {
|
||||||
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||||
|
if train == nil {
|
||||||
|
slog.Error("车载输出模拟量,未找到连接车载pc仿真的列车")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !train.ConnState.Conn {
|
||||||
|
slog.Error("车载输出模拟量,列车未连接车载pc仿真")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mockData := binary.BigEndian.Uint16(data)
|
||||||
|
train.VobcState.MockInfo = uint32(mockData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4.4.4. 车载输出BTM查询同步帧报文内容(0x04)
|
||||||
|
func (s *VerifySimulation) TrainBtmQuery(data []byte) {
|
||||||
|
if len(data) < 12 {
|
||||||
|
slog.Error("列车btm查询报文长度错误:", len(data))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
train := s.findConnTrain(state_proto.TrainConnState_PC_SIM)
|
||||||
|
if train == nil {
|
||||||
|
slog.Error("车载输出btm查询,未找到连接车载pc仿真的列车")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !train.ConnState.Conn {
|
||||||
|
slog.Error("车载输出btm查询,列车未连接车载pc仿真")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
trainAtm := message.NewCanetFrame(data, true)
|
||||||
|
atpReq := &message.AtpRequestFrame{}
|
||||||
|
if !atpReq.Decode(trainAtm) {
|
||||||
|
slog.Warn("列车pc驾驶模拟-CanetFrame解码成AtpRequestFrame失败", "CanetFrame", trainAtm.String())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cl := clock(atpReq)
|
||||||
|
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl)
|
||||||
|
if atpReq.ResendRequest == 2 {
|
||||||
|
//重新发送
|
||||||
|
if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 {
|
||||||
|
dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend)
|
||||||
|
train_pc_sim.Default().SendBaliseData(train_pc_sim.RECIVE_TRAIN_BTM_HAS_DATA, dd)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4, true)
|
||||||
|
timeSyncF.T2 = cl.BtmTk
|
||||||
|
timeSyncF.T3 = cl.TkNow()
|
||||||
|
telCount := strings.Count(train.BtmState.Telegram, "00")
|
||||||
|
if telCount >= balise_const.UserTelegramByteLen {
|
||||||
|
//无数据
|
||||||
|
queryData := make([]byte, 0)
|
||||||
|
queryData = append(queryData, btmRepFrame.Encode().Encode()...)
|
||||||
|
queryData = append(queryData, timeSyncF.Encode().Encode()...)
|
||||||
|
train_pc_sim.Default().SendBaliseData(train_pc_sim.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
|
||||||
|
} else {
|
||||||
|
//有数据
|
||||||
|
aliseData, _ := hex.DecodeString(train.BtmState.Telegram)
|
||||||
|
statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(btmRepFrame, aliseData, false, cl.TkNow(), cl.TkNow(), cl.TkNow(), true)
|
||||||
|
if statusDataCfOk {
|
||||||
|
queryData := make([]byte, 0)
|
||||||
|
queryData = append(queryData, btmRepFrame.Encode().Encode()...)
|
||||||
|
queryData = append(queryData, timeSyncF.Encode().Encode()...)
|
||||||
|
queryData = append(queryData, statusDataCf...) //数据帧包含结束帧
|
||||||
|
train.BtmState.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf)
|
||||||
|
train_pc_sim.Default().SendBaliseData(train_pc_sim.RECIVE_TRAIN_BTM_HAS_DATA, queryData)
|
||||||
|
} else {
|
||||||
|
slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *message.AtpRequestFrame, cl can_btm.BtmClock) *message.BtmStatusRspFrame {
|
||||||
|
statusF := message.NewBtmStatusRspFrame(canIdSn, true)
|
||||||
|
//btmStatus := aa(train, atpReq)
|
||||||
|
|
||||||
|
statusF.PowerAmplifierOn = true
|
||||||
|
statusF.PowerAmplifierFailure = false
|
||||||
|
statusF.AtpReqCrcCheckWrong = !atpReq.Crc16CheckOk
|
||||||
|
statusF.AntennaFault = false
|
||||||
|
statusF.BaliseCounter = byte(btmState.BaliseCount)
|
||||||
|
statusF.MessageCounter = byte(btmState.MessageCounter)
|
||||||
|
statusF.TkTimeA = cl.TkNow()
|
||||||
|
statusF.DetailedCode = 0
|
||||||
|
if btmState.AboveBalise {
|
||||||
|
statusF.DetailedCode = 0x07
|
||||||
|
}
|
||||||
|
statusF.Dsn = byte(btmState.DataSerialNumber)
|
||||||
|
return statusF
|
||||||
|
}
|
||||||
|
|
||||||
|
func clock(atpReq *message.AtpRequestFrame) can_btm.BtmClock {
|
||||||
|
now := time.Now()
|
||||||
|
return can_btm.BtmClock{BtmTk: atpReq.Time, SysTk: now}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user