Compare commits
12 Commits
cf3d38a2f5
...
15bdc45892
Author | SHA1 | Date | |
---|---|---|---|
|
15bdc45892 | ||
|
449162856b | ||
|
8b5ef2e597 | ||
|
903fd14a61 | ||
|
9809df4b27 | ||
|
9a5e8be378 | ||
|
f144f29386 | ||
|
efe1ff69c9 | ||
|
f9ffa1cf10 | ||
3d66efe8f4 | |||
|
39b4ffb633 | ||
|
f485e7a639 |
@ -96,6 +96,7 @@ func createByProjectId(c *gin.Context) {
|
|||||||
if len(mapInfos) == 0 {
|
if len(mapInfos) == 0 {
|
||||||
panic(sys_error.New("测试启动失败,项目未关联发布图"))
|
panic(sys_error.New("测试启动失败,项目未关联发布图"))
|
||||||
}
|
}
|
||||||
|
|
||||||
var mapIds []int32
|
var mapIds []int32
|
||||||
for _, mapInfo := range mapInfos {
|
for _, mapInfo := range mapInfos {
|
||||||
if mapInfo.Type == data_proto.PictureType_value[data_proto.PictureType_TrainData.String()] {
|
if mapInfo.Type == data_proto.PictureType_value[data_proto.PictureType_TrainData.String()] {
|
||||||
@ -251,6 +252,7 @@ func addTrain(c *gin.Context) {
|
|||||||
TrainMaxAcc: req.TrainMaxAcc,
|
TrainMaxAcc: req.TrainMaxAcc,
|
||||||
TrainMaxBrake: req.TrainMaxBrake,
|
TrainMaxBrake: req.TrainMaxBrake,
|
||||||
TrainEmergencyBrake: req.TrainEmergencyBrake,
|
TrainEmergencyBrake: req.TrainEmergencyBrake,
|
||||||
|
ProjectCode: simulation.ProjectCode,
|
||||||
//HeadOffset: 93211,
|
//HeadOffset: 93211,
|
||||||
DevicePort: req.DevicePort,
|
DevicePort: req.DevicePort,
|
||||||
TrainRunUp: req.RunDirection,
|
TrainRunUp: req.RunDirection,
|
||||||
|
@ -152,8 +152,8 @@ func trainPcConnErr(err error) {
|
|||||||
func main() {
|
func main() {
|
||||||
|
|
||||||
initConfig()
|
initConfig()
|
||||||
//initBtmTest()
|
initBtmTest()
|
||||||
initTrainPc()
|
//initTrainPc()
|
||||||
//initAccTest()
|
//initAccTest()
|
||||||
//initSpeedTest()
|
//initSpeedTest()
|
||||||
|
|
||||||
@ -168,9 +168,9 @@ func sendPacket(lifeNum uint32, autoId byte) {
|
|||||||
userMsg, _ := hex.DecodeString(testUserBtmMsg)
|
userMsg, _ := hex.DecodeString(testUserBtmMsg)
|
||||||
|
|
||||||
msg := &message.BtmVobcMessage{FontTtl: 2, BtmStatus: 0x00, DecodeTime: 10, BackTtl: 2, BtmMsg: userMsg, ResponseTime: 10,
|
msg := &message.BtmVobcMessage{FontTtl: 2, BtmStatus: 0x00, DecodeTime: 10, BackTtl: 2, BtmMsg: userMsg, ResponseTime: 10,
|
||||||
VobcLifeNum: lifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoId}, MsgSerial: message.GetAutoMessageId()}
|
VobcLifeNum: lifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoId} /*MsgSerial: message.GetAutoMessageId()*/}
|
||||||
sendData := msg.Encode()
|
sendData := msg.Encode()
|
||||||
fmt.Println("发送btm vobc len:", len(sendData), "报文:", hex.EncodeToString(sendData), "报文序列号:", msg.MsgSerial)
|
//fmt.Println("发送btm vobc len:", len(sendData), "报文:", hex.EncodeToString(sendData), "报文序列号:", msg.MsgSerial)
|
||||||
time.Sleep(time.Millisecond * 100)
|
time.Sleep(time.Millisecond * 100)
|
||||||
err := btmCli.Send(sendData)
|
err := btmCli.Send(sendData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -194,9 +194,9 @@ func sendPacketFree(lifeNum uint32, autoId byte, msgs byte) {
|
|||||||
}
|
}
|
||||||
msg2 := &message.BtmVobcMsgFree{BtmStatus: 0x00, WorkTemperature: 10, Fun1: uint16(0), Fun2: uint16(0), Fun3: uint16(0), Fun4: uint16(0),
|
msg2 := &message.BtmVobcMsgFree{BtmStatus: 0x00, WorkTemperature: 10, Fun1: uint16(0), Fun2: uint16(0), Fun3: uint16(0), Fun4: uint16(0),
|
||||||
//FreeMsg: freeMsg, RespTime: 20, VobcLifeNum: lifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoId}, MsgSerial: newMsg}
|
//FreeMsg: freeMsg, RespTime: 20, VobcLifeNum: lifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoId}, MsgSerial: newMsg}
|
||||||
FreeMsg: freeMsg, RespTime: 20, VobcLifeNum: lifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoId}, MsgSerial: message.GetAutoMessageId()}
|
FreeMsg: freeMsg, RespTime: 20, VobcLifeNum: lifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoId} /* MsgSerial: message.GetAutoMessageId()*/}
|
||||||
sendData2 := msg2.Encode()
|
sendData2 := msg2.Encode()
|
||||||
fmt.Println("发送btm vobc 空报文:", hex.EncodeToString(sendData2), "len:", len(sendData2), "报文序列号:", msg2.MsgSerial, "atoId=", autoId, "报文序列号:", msg2.MsgSerial)
|
//fmt.Println("发送btm vobc 空报文:", hex.EncodeToString(sendData2), "len:", len(sendData2), "报文序列号:", msg2.MsgSerial, "atoId=", autoId, "报文序列号:", msg2.MsgSerial)
|
||||||
time.Sleep(time.Millisecond * 100)
|
time.Sleep(time.Millisecond * 100)
|
||||||
err := btmCli.Send(sendData2)
|
err := btmCli.Send(sendData2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -207,15 +207,15 @@ func sendPacketFree(lifeNum uint32, autoId byte, msgs byte) {
|
|||||||
func RequestFramePackets(req *message.BtmVobcReq, vobcLife uint32) {
|
func RequestFramePackets(req *message.BtmVobcReq, vobcLife uint32) {
|
||||||
//fmt.Println(fmt.Sprintf("接受 请求帧 frameStatus:%v,messageType:%v,lifeNum:%v,序列号:%v", req.FrameStatus, req.MessageType, req.VobcLifeNum, req.MessageSerial))
|
//fmt.Println(fmt.Sprintf("接受 请求帧 frameStatus:%v,messageType:%v,lifeNum:%v,序列号:%v", req.FrameStatus, req.MessageType, req.VobcLifeNum, req.MessageSerial))
|
||||||
if req.FrameStatus == message.REQ_FRAME_STATUS_BOOT && req.MessageType == message.REQ_PACKETS_TYPE_BOOT {
|
if req.FrameStatus == message.REQ_FRAME_STATUS_BOOT && req.MessageType == message.REQ_PACKETS_TYPE_BOOT {
|
||||||
fmt.Println("000000000000000000000000000")
|
//fmt.Println("000000000000000000000000000")
|
||||||
sendPacketFree(vobcLife, req.AutoIdFrame, req.MessageSerial)
|
sendPacketFree(vobcLife, req.AutoIdFrame, req.MessageSerial)
|
||||||
} else if req.FrameStatus == message.REQ_FRAME_STATUS_OK {
|
} else if req.FrameStatus == message.REQ_FRAME_STATUS_OK {
|
||||||
//帧正确,删除之前发送的数据
|
//帧正确,删除之前发送的数据
|
||||||
fmt.Println("11111111111111111111")
|
//fmt.Println("11111111111111111111")
|
||||||
|
|
||||||
} else if req.FrameStatus == message.REQ_FRAME_STATUS_ERROR {
|
} else if req.FrameStatus == message.REQ_FRAME_STATUS_ERROR {
|
||||||
//帧不正确 重新发送2次,如果2次后仍然不正确,则删除之前发送的数据
|
//帧不正确 重新发送2次,如果2次后仍然不正确,则删除之前发送的数据
|
||||||
fmt.Println("22222222222222222")
|
///**/fmt.Println("22222222222222222")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +224,7 @@ var vobcNumLife uint32 = 0
|
|||||||
|
|
||||||
func handleBtmVobcFrames(cfs []byte) {
|
func handleBtmVobcFrames(cfs []byte) {
|
||||||
|
|
||||||
fmt.Println(fmt.Sprintf("收到源数据:%v ,请求帧时间:%v ,vobcLife:%v", hex.EncodeToString(cfs), time.Now().UnixMilli()-btmReceiveTime, vobcNumLife))
|
fmt.Println(fmt.Sprintf("收到源数据:%v ,数据长度:%v", hex.EncodeToString(cfs), len(cfs)))
|
||||||
frameType, dataText, err := message.BtmVobcDecode(cfs)
|
frameType, dataText, err := message.BtmVobcDecode(cfs)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
@ -241,11 +241,11 @@ func handleBtmVobcFrames(cfs []byte) {
|
|||||||
if vobcNumLife <= 0 {
|
if vobcNumLife <= 0 {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
fmt.Println(fmt.Sprintf("准备发送vobcLife:%v", vobcNumLife))
|
//fmt.Println(fmt.Sprintf("准备发送vobcLife:%v", vobcNumLife))
|
||||||
}
|
}
|
||||||
req := &message.BtmVobcReq{}
|
req := &message.BtmVobcReq{}
|
||||||
req.Decode(dataText)
|
req.Decode(dataText)
|
||||||
fmt.Println(fmt.Sprintf("接受 请求帧 frameStatus:%v,messageType:%v,lifeNum:%v,序列号:%v", req.FrameStatus, req.MessageType, req.VobcLifeNum, req.MessageSerial))
|
//fmt.Println(fmt.Sprintf("接受 请求帧 frameStatus:%v,messageType:%v,lifeNum:%v,序列号:%v", req.FrameStatus, req.MessageType, req.VobcLifeNum, req.MessageSerial))
|
||||||
if time.Now().UnixMilli()-btmReceiveTime > 20*1000 {
|
if time.Now().UnixMilli()-btmReceiveTime > 20*1000 {
|
||||||
idCommand := &message.BtmVobcIdCommand{}
|
idCommand := &message.BtmVobcIdCommand{}
|
||||||
idCommand.Decode(dataText)
|
idCommand.Decode(dataText)
|
||||||
|
@ -161,11 +161,15 @@ type VehiclePCSimConfig2 struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type VehiclePCSimConfig struct {
|
type VehiclePCSimConfig struct {
|
||||||
|
Open bool `json:"open" description:"是否开启"`
|
||||||
//TrainEnds bool `json:"trainEnds" description:"列车端点A?"`
|
//TrainEnds bool `json:"trainEnds" description:"列车端点A?"`
|
||||||
ConfigName string `json:"configName" description:"连接名称"`
|
ConfigName string `json:"configName" description:"连接名称"`
|
||||||
Open bool `json:"open" description:"是否开启"`
|
OpenA bool `json:"openA" description:"是否开启A端"`
|
||||||
PcSimIp string `json:"pcSimIp" description:"pc仿真平台通信ip"`
|
APcSimIp string `json:"apcSimIp" description:"pc仿真平台通信ip A端"`
|
||||||
PcSimPort uint32 `json:"pcSimPort" description:"pc仿真平台通信端口"`
|
APcSimPort uint32 `json:"apcSimPort" description:"pc仿真平台通信端口A端"`
|
||||||
|
OpenB bool `json:"openB" description:"是否开启B端"`
|
||||||
|
BPcSimIp string `json:"bpcSimIp" description:"pc仿真平台通信ip B端"`
|
||||||
|
BPcSimPort uint32 `json:"bpcSimPort" description:"pc仿真平台通信端口B端"`
|
||||||
//LocalTestingPort uint32 `json:"localTestingPort" description:"本地测试端口"`
|
//LocalTestingPort uint32 `json:"localTestingPort" description:"本地测试端口"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -528,8 +528,8 @@ func convertTrainState(v *state_proto.TrainState) *state_proto.TrainMapState {
|
|||||||
TailDeviceId: v.TailDeviceId,
|
TailDeviceId: v.TailDeviceId,
|
||||||
TailOffset: v.TailOffset,
|
TailOffset: v.TailOffset,
|
||||||
TailDevicePort: v.TailDevicePort,
|
TailDevicePort: v.TailDevicePort,
|
||||||
BtmState: v.BtmState,
|
//BtmState: v.BtmState,
|
||||||
ConnState: v.ConnState,
|
ConnState: v.ConnState,
|
||||||
}
|
}
|
||||||
convertDynamicConfig(v.TrainDynamicConfig, t.TrainDynamicConfig)
|
convertDynamicConfig(v.TrainDynamicConfig, t.TrainDynamicConfig)
|
||||||
convertDynamicConfig(v.TrainEndsA, t.TrainEndsA)
|
convertDynamicConfig(v.TrainEndsA, t.TrainEndsA)
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit a94fdb12f720a5d9bbf57b1916e8ba5990130e6e
|
Subproject commit ef7ff5459cde3eced121d1908b192ee586a47c97
|
@ -1 +1 @@
|
|||||||
Subproject commit 7629f290ea612d4ce368c40d4cf793dffc4b21ec
|
Subproject commit 76a91b6495fc3a6b725b4ff3ba003423e3efb38e
|
@ -45,7 +45,7 @@ func checkRunConfig(jsonConfigStr string) *sys_error.BusinessError {
|
|||||||
checkSameMap := make(map[string]bool)
|
checkSameMap := make(map[string]bool)
|
||||||
for _, simConfig := range configMap.PcSimConfigs {
|
for _, simConfig := range configMap.PcSimConfigs {
|
||||||
if simConfig.ConfigName == "" || len(strings.TrimSpace(simConfig.ConfigName)) == 0 {
|
if simConfig.ConfigName == "" || len(strings.TrimSpace(simConfig.ConfigName)) == 0 {
|
||||||
return sys_error.New(fmt.Sprintf("车载运行配置名称不能为空 配置ip:%v,端口%v", simConfig.PcSimIp, simConfig.PcSimPort), err)
|
return sys_error.New(fmt.Sprintf("车载运行配置名称不能为空 "), err)
|
||||||
}
|
}
|
||||||
if checkSameMap[simConfig.ConfigName] {
|
if checkSameMap[simConfig.ConfigName] {
|
||||||
return sys_error.New(fmt.Sprintf("车载运行配置重复的名称:%v", simConfig.ConfigName), err)
|
return sys_error.New(fmt.Sprintf("车载运行配置重复的名称:%v", simConfig.ConfigName), err)
|
||||||
|
378
third_party/btm_vobc/btm_vobc.go
vendored
378
third_party/btm_vobc/btm_vobc.go
vendored
@ -1,378 +0,0 @@
|
|||||||
package btm_vobc
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"encoding/hex"
|
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"github.com/google/uuid"
|
|
||||||
"github.com/snksoft/crc"
|
|
||||||
"joylink.club/bj-rtsts-server/config"
|
|
||||||
"joylink.club/bj-rtsts-server/const/balise_const"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
|
||||||
"log/slog"
|
|
||||||
"math"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"strings"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type BtmVobcManage interface {
|
|
||||||
GetBtmVobcConfig() config.BtmVobcConfig
|
|
||||||
|
|
||||||
GetAllTrain() []*state_proto.TrainState
|
|
||||||
GetConnVobcTrain() *state_proto.TrainState
|
|
||||||
}
|
|
||||||
type BtmVobcService interface {
|
|
||||||
Start(btmVobcManage BtmVobcManage)
|
|
||||||
Stop()
|
|
||||||
SendData(data []byte)
|
|
||||||
AppendBaliseMsgForTrain(vobcBtm *state_proto.VobcBtmState, baliseId string, baliseSource []byte, arriveTime int64)
|
|
||||||
UpdateTrainLeave(vobcBtm *state_proto.VobcBtmState, baliseId string, leaveTime int64)
|
|
||||||
RemoveBaliseFirst(vobcBtm *state_proto.VobcBtmState)
|
|
||||||
}
|
|
||||||
type BtmVobcClient struct {
|
|
||||||
calFun context.CancelFunc
|
|
||||||
client udp.UdpClient
|
|
||||||
server udp.UdpServer
|
|
||||||
manage BtmVobcManage
|
|
||||||
}
|
|
||||||
|
|
||||||
var (
|
|
||||||
btmVobcLocker sync.Mutex
|
|
||||||
btmVobcClient *BtmVobcClient
|
|
||||||
btmVobcBaliseLocker sync.Mutex
|
|
||||||
//最新接受数据时间
|
|
||||||
reviceTimeStamp int64
|
|
||||||
)
|
|
||||||
|
|
||||||
func Default() BtmVobcService {
|
|
||||||
defer btmVobcLocker.Unlock()
|
|
||||||
btmVobcLocker.Lock()
|
|
||||||
if btmVobcClient == nil {
|
|
||||||
btmVobcClient = &BtmVobcClient{}
|
|
||||||
}
|
|
||||||
return btmVobcClient
|
|
||||||
}
|
|
||||||
|
|
||||||
// 缓存列车经过的应答器报文
|
|
||||||
func (b *BtmVobcClient) AppendBaliseMsgForTrain(vobcBtm *state_proto.VobcBtmState, baliseId string, baliseSource []byte, arriveTime int64) {
|
|
||||||
defer btmVobcBaliseLocker.Unlock()
|
|
||||||
btmVobcBaliseLocker.Lock()
|
|
||||||
baliseHex := hex.EncodeToString(baliseSource)
|
|
||||||
tel := &state_proto.VobcBtmState_TelegramState{Telegram: baliseHex, BaliseId: baliseId, ArriveTime: arriveTime}
|
|
||||||
if len(vobcBtm.TelegramState) == 0 {
|
|
||||||
vobcBtm.TelegramState = append(vobcBtm.TelegramState, tel)
|
|
||||||
} else {
|
|
||||||
bs := crc.CalculateCRC(crc.CRC32, baliseSource)
|
|
||||||
exists := false
|
|
||||||
for _, d := range vobcBtm.TelegramState {
|
|
||||||
sd, _ := hex.DecodeString(d.Telegram)
|
|
||||||
t := crc.CalculateCRC(crc.CRC32, sd)
|
|
||||||
if t == bs {
|
|
||||||
exists = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !exists {
|
|
||||||
if len(vobcBtm.TelegramState) >= 8 {
|
|
||||||
vobcBtm.TelegramState = append(vobcBtm.TelegramState[1:], tel)
|
|
||||||
} else {
|
|
||||||
vobcBtm.TelegramState = append(vobcBtm.TelegramState, tel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (b *BtmVobcClient) UpdateTrainLeave(vobcBtm *state_proto.VobcBtmState, baliseId string, leaveTime int64) {
|
|
||||||
defer btmVobcBaliseLocker.Unlock()
|
|
||||||
btmVobcBaliseLocker.Lock()
|
|
||||||
if vobcBtm.TelegramState == nil || len(vobcBtm.TelegramState) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, bs := range vobcBtm.TelegramState {
|
|
||||||
if bs.BaliseId == baliseId {
|
|
||||||
bs.LeaveTime = leaveTime
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BtmVobcClient) RemoveBaliseFirst(vobcBtm *state_proto.VobcBtmState) {
|
|
||||||
defer btmVobcBaliseLocker.Unlock()
|
|
||||||
btmVobcBaliseLocker.Lock()
|
|
||||||
|
|
||||||
if vobcBtm.TelegramState == nil || len(vobcBtm.TelegramState) == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
vobcBtm.TelegramState = vobcBtm.TelegramState[1:]
|
|
||||||
}
|
|
||||||
func (b *BtmVobcClient) Start(btmVobcManage BtmVobcManage) {
|
|
||||||
cfg := btmVobcManage.GetBtmVobcConfig()
|
|
||||||
if !cfg.Open {
|
|
||||||
slog.Info("11号线 btm vobc配置未开启...")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
udpServer := udp.NewServer(fmt.Sprintf("%v:%d", cfg.LocalUdpIp, cfg.LocalUdpPort), b.handleBtmVobcFrames)
|
|
||||||
err := udpServer.Listen()
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("11号线 btm VOBC 服务启动失败...")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//
|
|
||||||
udpClient := udp.NewClient(fmt.Sprintf("%s:%d", cfg.RemoteIp, cfg.RemoteUdpPort))
|
|
||||||
b.manage = btmVobcManage
|
|
||||||
b.server = udpServer
|
|
||||||
b.client = udpClient
|
|
||||||
reviceTimeStamp = time.Now().UnixMilli()
|
|
||||||
ctx, calFun := context.WithCancel(context.Background())
|
|
||||||
b.calFun = calFun
|
|
||||||
go b.checkTrainTTLIsOver(ctx)
|
|
||||||
}
|
|
||||||
func (b *BtmVobcClient) checkTrainTTLIsOver(ctx context.Context) {
|
|
||||||
defer btmVobcBaliseLocker.Unlock()
|
|
||||||
btmVobcBaliseLocker.Lock()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
if time.Now().UnixMilli()-reviceTimeStamp < 1000 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
trains := b.manage.GetAllTrain()
|
|
||||||
if len(trains) > 0 {
|
|
||||||
slog.Info("检测网络中断情况 前沿ttl 超时...")
|
|
||||||
newTel := make([]*state_proto.VobcBtmState_TelegramState, 0)
|
|
||||||
for _, train := range b.manage.GetAllTrain() {
|
|
||||||
for _, state := range train.VobcBtm.TelegramState {
|
|
||||||
if time.Now().UnixMilli()-state.ArriveTime < 1000 {
|
|
||||||
newTel = append(newTel, state)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
time.Sleep(time.Second * 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
func (b *BtmVobcClient) handleBtmVobcFrames(cfs []byte) {
|
|
||||||
reviceTimeStamp = time.Now().UnixMilli()
|
|
||||||
|
|
||||||
train := b.manage.GetConnVobcTrain()
|
|
||||||
if train == nil {
|
|
||||||
//slog.Error("vobc btm 未找到VOBC连接的列车...")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
requestId := uuid.New().String()
|
|
||||||
slog.Info(fmt.Sprintf("获取到vobc btm原始数据:%v, requestId:%v", hex.EncodeToString(cfs), requestId))
|
|
||||||
frameType, dataText, err := message.BtmVobcDecode(cfs)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(fmt.Sprintf("%v,请求id:%v", err, requestId))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
receiveDataTime := time.Now().UnixMicro()
|
|
||||||
decodePayMicoTime := (receiveDataTime - receiveDataTime) / 100
|
|
||||||
if frameType == message.COMMAND_TYPE {
|
|
||||||
idCommand := &message.BtmVobcIdCommand{}
|
|
||||||
idCommand.Decode(dataText)
|
|
||||||
slog.Info(fmt.Sprintf("成功接受btm vobc的id命令帧,requestId:%v,接受时间(微秒):%v", requestId, receiveDataTime))
|
|
||||||
b.packets(requestId, idCommand.VobcLifeNum, idCommand.AutoIdFrame, receiveDataTime, decodePayMicoTime, train.VobcBtm)
|
|
||||||
|
|
||||||
} else if frameType == message.REQUEST_TYPE {
|
|
||||||
slog.Info(fmt.Sprintf("成功接受btm vobc的请求帧,requestId:%v,接受时间(微秒):%v", requestId, receiveDataTime))
|
|
||||||
req := &message.BtmVobcReq{}
|
|
||||||
req.Decode(dataText)
|
|
||||||
b.RequestFramePackets(req.VobcLifeNum, req.AutoIdFrame, requestId, receiveDataTime, decodePayMicoTime, req, train.VobcBtm)
|
|
||||||
} else {
|
|
||||||
slog.Error(fmt.Sprintf("btm vobc 解析未知命令帧类型:0x%v,原始数据:%v,长度:%v,requestId:%v", strconv.FormatInt(int64(frameType), 16), hex.EncodeToString(cfs), len(cfs), requestId))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func createFreeBalisePacketString() string {
|
|
||||||
return strings.Repeat("00", balise_const.UserTelegramByteLen)
|
|
||||||
}
|
|
||||||
func createFreeBalisePackets() []byte {
|
|
||||||
str := createFreeBalisePacketString()
|
|
||||||
d, _ := hex.DecodeString(str)
|
|
||||||
return d
|
|
||||||
}
|
|
||||||
|
|
||||||
const MAX_SEND_COUNT = 3
|
|
||||||
|
|
||||||
// 请求帧
|
|
||||||
func (b *BtmVobcClient) RequestFramePackets(vobcLifeNum uint32, autoId byte, requestId string, receiveTime int64, decodePayMicoTime int64, req *message.BtmVobcReq, vobcbtm *state_proto.VobcBtmState) {
|
|
||||||
if req.FrameStatus == message.REQ_FRAME_STATUS_BOOT && req.MessageType == message.REQ_PACKETS_TYPE_BOOT {
|
|
||||||
slog.Info(fmt.Sprintf("接受请求帧,准备发送空闲帧数据 帧状态:0x%v,消息类型:0x%v ,requestId:%v", strconv.FormatInt(int64(req.FrameStatus), 16), strconv.FormatInt(int64(req.MessageType), 16), requestId))
|
|
||||||
vobcbtm.TelegramState = make([]*state_proto.VobcBtmState_TelegramState, 0)
|
|
||||||
vobcbtm.History = make(map[uint32]*state_proto.VobcBtmState_VobcBtmHistoryState)
|
|
||||||
b.packets(requestId, vobcLifeNum, autoId, receiveTime, decodePayMicoTime, vobcbtm)
|
|
||||||
|
|
||||||
} else if req.FrameStatus == message.REQ_FRAME_STATUS_OK {
|
|
||||||
//帧正确,删除之前发送的数据
|
|
||||||
slog.Info(fmt.Sprintf("接受请求帧,帧正确,删除之前发送的数据requestId:%v", requestId))
|
|
||||||
delete(vobcbtm.History, uint32(req.MessageSerial))
|
|
||||||
} else if req.FrameStatus == message.REQ_FRAME_STATUS_ERROR {
|
|
||||||
//帧不正确 重新发送2次,如果2次后仍然不正确,则删除之前发送的数据
|
|
||||||
dd := vobcbtm.History[uint32(req.MessageSerial)]
|
|
||||||
if dd.SendCount > MAX_SEND_COUNT {
|
|
||||||
slog.Info(fmt.Sprintf("接受请求帧,帧不正确,重发超过2次,删除之前发送的数据,准备发送新数据 requestId:%v", requestId))
|
|
||||||
sendBalisePacket := dd.BalisePacket
|
|
||||||
delete(vobcbtm.History, uint32(req.MessageSerial))
|
|
||||||
if vobcbtm.TelegramState[0].Telegram == sendBalisePacket {
|
|
||||||
b.RemoveBaliseFirst(vobcbtm)
|
|
||||||
}
|
|
||||||
if len(vobcbtm.TelegramState) == 0 {
|
|
||||||
b.balisePacketsFree(requestId, time.Now().UnixMicro(), req.VobcLifeNum, req.AutoIdFrame, vobcbtm)
|
|
||||||
} else {
|
|
||||||
b.balisePackets(requestId, vobcbtm.TelegramState[0], receiveTime, decodePayMicoTime, req.VobcLifeNum, req.AutoIdFrame, vobcbtm)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
dd.SendCount = dd.SendCount + 1
|
|
||||||
if dd.IsFreePacket {
|
|
||||||
freeMsg := &message.BtmVobcMsgFree{}
|
|
||||||
if b.unmarshalJson(dd.SendTelegram, freeMsg) == nil {
|
|
||||||
freeMsg.FreeMsg = createFreeBalisePackets()
|
|
||||||
repeatData := freeMsg.Encode()
|
|
||||||
logStr := fmt.Sprintf("重新发送空闲帧数据,发送次数:%v,帧系列id:%v,数据:%v,requestId:%v", dd.SendCount, freeMsg.MsgSerial, hex.EncodeToString(repeatData), requestId)
|
|
||||||
slog.Info(logStr)
|
|
||||||
err := b.client.Send(repeatData)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(logStr, err)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
packetMsg := &message.BtmVobcMessage{}
|
|
||||||
if b.unmarshalJson(dd.SendTelegram, packetMsg) == nil {
|
|
||||||
balise, _ := hex.DecodeString(dd.BalisePacket)
|
|
||||||
packetMsg.BtmMsg = balise
|
|
||||||
baliseData := packetMsg.Encode()
|
|
||||||
logStr := fmt.Sprintf("重新发送空闲帧数据,发送次数:%v,帧系列id:%v 数据:%v ,requestId:%v", dd.SendCount, packetMsg.MsgSerial, hex.EncodeToString(baliseData), requestId)
|
|
||||||
slog.Info(logStr)
|
|
||||||
err := b.client.Send(baliseData)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(logStr, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BtmVobcClient) unmarshalJson(jsonStr string, obj any) error {
|
|
||||||
err := json.Unmarshal([]byte(jsonStr), obj)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(fmt.Sprintf("vobc btm 数据转换失败 source:%v,对象:%v", jsonStr, reflect.TypeOf(obj).Name()))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 有应答器报文
|
|
||||||
func (b *BtmVobcClient) balisePackets(requestId string, tel *state_proto.VobcBtmState_TelegramState, receiveTime int64, decodePayMicoTime int64, vobcLifeNum uint32, autoCommandId byte, vobcbtm *state_proto.VobcBtmState) {
|
|
||||||
|
|
||||||
data, e := hex.DecodeString(tel.Telegram)
|
|
||||||
if e != nil {
|
|
||||||
slog.Error(fmt.Sprintf("解析应答器报文失败应答器报文长度:%v", tel.Telegram), e)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(data) < balise_const.UserTelegramByteLen {
|
|
||||||
for i := 0; i < balise_const.UserTelegramByteLen-len(data); i++ {
|
|
||||||
data = append(data, 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//前沿时间
|
|
||||||
|
|
||||||
var fttl uint16 = 0
|
|
||||||
tmpFttl := int64(math.Abs(float64(time.Now().UnixMilli() - tel.ArriveTime)))
|
|
||||||
if tmpFttl >= 0xffff {
|
|
||||||
fttl = 0xffff
|
|
||||||
} else {
|
|
||||||
fttl = uint16(tmpFttl)
|
|
||||||
}
|
|
||||||
|
|
||||||
var bttl uint16 = 0
|
|
||||||
tmpBttl := int64(math.Abs(float64(time.Now().UnixMilli() - tel.ArriveTime)))
|
|
||||||
if tmpBttl >= 0xffff {
|
|
||||||
bttl = 0xffff
|
|
||||||
} else {
|
|
||||||
bttl = uint16(tmpBttl)
|
|
||||||
}
|
|
||||||
repTimeMicro := (receiveTime - time.Now().UnixMicro()) / 100
|
|
||||||
baliseMsg := &message.BtmVobcMessage{FontTtl: fttl, BtmStatus: message.BTM_STSTUS_NORMAL, DecodeTime: uint16(decodePayMicoTime),
|
|
||||||
BackTtl: bttl, ResponseTime: byte(repTimeMicro), MsgSerial: message.GetAutoMessageId(),
|
|
||||||
VobcLifeNum: vobcLifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoCommandId}}
|
|
||||||
u32MsgId := uint32(baliseMsg.MsgSerial)
|
|
||||||
jsonArr, _ := json.Marshal(baliseMsg)
|
|
||||||
baliseMsg.BtmMsg = data
|
|
||||||
baliseData := baliseMsg.Encode()
|
|
||||||
baliseMsgHex := hex.EncodeToString(baliseData)
|
|
||||||
vobcbtm.History[u32MsgId] = &state_proto.VobcBtmState_VobcBtmHistoryState{SendCount: 1, PacketSendId: u32MsgId, VobcLifeNum: vobcLifeNum,
|
|
||||||
IsFreePacket: false, SendTelegram: string(jsonArr), BalisePacket: tel.Telegram}
|
|
||||||
logStr := fmt.Sprintf("发送btm vobc 报文数据 报文序列id:%v 报文内容:%v 长度:%v ,requestId:%v", u32MsgId, baliseMsgHex, len(baliseData), requestId)
|
|
||||||
slog.Info(logStr)
|
|
||||||
err := b.client.Send(baliseData)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(logStr, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 无应答器报文
|
|
||||||
func (b *BtmVobcClient) balisePacketsFree(requestId string, receiveTime int64, vobcLifeNum uint32, autoCommandId byte, vobcbtm *state_proto.VobcBtmState) {
|
|
||||||
repTimeMicro := (receiveTime - time.Now().UnixMicro()) / 100
|
|
||||||
data := createFreeBalisePackets()
|
|
||||||
freeMsg := &message.BtmVobcMsgFree{BtmStatus: message.BTM_STSTUS_NORMAL, Fun1: 0xffff, Fun2: 0x00CF, Fun3: uint16(0), Fun4: uint16(0),
|
|
||||||
FreeMsg: data, RespTime: byte(repTimeMicro), MsgSerial: message.GetAutoMessageId(), VobcLifeNum: vobcLifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoCommandId}}
|
|
||||||
u32MsgId := uint32(freeMsg.MsgSerial)
|
|
||||||
jsonArr, _ := json.Marshal(freeMsg)
|
|
||||||
vobcbtm.History[u32MsgId] = &state_proto.VobcBtmState_VobcBtmHistoryState{SendCount: 1, PacketSendId: u32MsgId, VobcLifeNum: vobcLifeNum, IsFreePacket: true, SendTelegram: string(jsonArr)}
|
|
||||||
freeData := freeMsg.Encode()
|
|
||||||
dataEncode := hex.EncodeToString(freeData)
|
|
||||||
logStr := fmt.Sprintf("发送btm vobc 报文序列id:%v 空闲帧报文:%v 长度:%v ,requestId:%v", u32MsgId, dataEncode, len(freeData), requestId)
|
|
||||||
slog.Info(logStr)
|
|
||||||
err := b.client.Send(freeData)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(logStr, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 应答器报文或空报文
|
|
||||||
func (b *BtmVobcClient) packets(requestId string, vobcLifeNum uint32, autoIdFrame byte, receiveTime int64, decodePayMicoTime int64, vobcbtm *state_proto.VobcBtmState) {
|
|
||||||
|
|
||||||
if len(vobcbtm.TelegramState) == 0 {
|
|
||||||
b.balisePacketsFree(requestId, receiveTime, vobcLifeNum, autoIdFrame, vobcbtm)
|
|
||||||
} else {
|
|
||||||
b.balisePackets(requestId, vobcbtm.TelegramState[0], receiveTime, decodePayMicoTime, vobcLifeNum, autoIdFrame, vobcbtm)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BtmVobcClient) SendData(data []byte) {
|
|
||||||
if b.client != nil {
|
|
||||||
slog.Info(fmt.Sprintf("发送btm vobc 报文:%v 长度:%v", hex.EncodeToString(data), len(data)))
|
|
||||||
err := b.client.Send(data)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("发送btm vobc 报文失败:", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
func (b *BtmVobcClient) Stop() {
|
|
||||||
if b.server != nil {
|
|
||||||
b.calFun()
|
|
||||||
b.server.Close()
|
|
||||||
}
|
|
||||||
if b.client != nil {
|
|
||||||
b.client.Close()
|
|
||||||
}
|
|
||||||
}
|
|
57
third_party/can_btm/balise_btm.go
vendored
57
third_party/can_btm/balise_btm.go
vendored
@ -53,39 +53,6 @@ type btmCanetClient struct {
|
|||||||
baliseDetector *BaliseDetector
|
baliseDetector *BaliseDetector
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *btmCanetClient) FindBaliseResend(train *state_proto.TrainState) (*state_proto.BTMState, byte, byte, byte) {
|
|
||||||
s.baliseDetector.eqLock.Lock()
|
|
||||||
defer s.baliseDetector.eqLock.Unlock()
|
|
||||||
cache := train.BtmBaliseCache
|
|
||||||
|
|
||||||
for _, balise := range cache.BaliseList {
|
|
||||||
slog.Info(fmt.Sprintf("===========%v", len(cache.BaliseList)))
|
|
||||||
if balise != nil && balise.BaliseId == cache.ResendBaliseId && balise.ResendCount < 3 {
|
|
||||||
balise.ResendCount++
|
|
||||||
ndsn := BaliseCounterAdd(cache.Dsn)
|
|
||||||
cache.Dsn = uint32(ndsn)
|
|
||||||
return balise, ndsn, byte(cache.BaliseCount), byte(cache.MessageCounter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, 0, 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *btmCanetClient) FindBaliseByNotSend(train *state_proto.TrainState) (*state_proto.BTMState, byte, byte, byte) {
|
|
||||||
s.baliseDetector.eqLock.Lock()
|
|
||||||
defer s.baliseDetector.eqLock.Unlock()
|
|
||||||
cache := train.BtmBaliseCache
|
|
||||||
for _, btmCache := range cache.BaliseList {
|
|
||||||
if btmCache != nil && !btmCache.IsSend {
|
|
||||||
ndsn := BaliseCounterAdd(cache.Dsn)
|
|
||||||
cache.Dsn = uint32(ndsn)
|
|
||||||
cache.ResendBaliseId = btmCache.BaliseId
|
|
||||||
return btmCache, ndsn, byte(cache.BaliseCount), byte(cache.MessageCounter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, 0, 0, 0
|
|
||||||
}
|
|
||||||
|
|
||||||
type BtmClock struct {
|
type BtmClock struct {
|
||||||
BtmTk uint32 //与ATP系统同步的时间ms
|
BtmTk uint32 //与ATP系统同步的时间ms
|
||||||
SysTk time.Time //本地系统时间
|
SysTk time.Time //本地系统时间
|
||||||
@ -100,11 +67,8 @@ type BtmCanetClient interface {
|
|||||||
Start(bcm BtmCanetManager)
|
Start(bcm BtmCanetManager)
|
||||||
Stop()
|
Stop()
|
||||||
//HandleTrainHeadPositionInfo 处理收到列车位置信息
|
//HandleTrainHeadPositionInfo 处理收到列车位置信息
|
||||||
HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state_proto.VobcBtmState, h *TrainHeadPositionInfo)
|
HandleTrainHeadPositionInfo(w ecs.World, h *TrainHeadPositionInfo)
|
||||||
HandleTrainHeadPositionInfoForTrain(w ecs.World, train *state_proto.TrainBtmCache, h *TrainHeadPositionInfo)
|
HandleTrainHeadPositionInfoForTrain(w ecs.World, train *state_proto.TrainState, h *TrainHeadPositionInfo)
|
||||||
|
|
||||||
FindBaliseByNotSend(train *state_proto.TrainState) (*state_proto.BTMState, byte, byte, byte)
|
|
||||||
FindBaliseResend(train *state_proto.TrainState) (*state_proto.BTMState, byte, byte, byte)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -120,7 +84,7 @@ func Default() BtmCanetClient {
|
|||||||
}
|
}
|
||||||
return btmClient
|
return btmClient
|
||||||
}
|
}
|
||||||
func (s *btmCanetClient) HandleTrainHeadPositionInfoForTrain(w ecs.World, btmCache *state_proto.TrainBtmCache, h *TrainHeadPositionInfo) {
|
func (s *btmCanetClient) HandleTrainHeadPositionInfoForTrain(w ecs.World, train *state_proto.TrainState, h *TrainHeadPositionInfo) {
|
||||||
wd := entity.GetWorldData(w)
|
wd := entity.GetWorldData(w)
|
||||||
repo := wd.Repo
|
repo := wd.Repo
|
||||||
h2 := &TrainHeadPositionInfo{
|
h2 := &TrainHeadPositionInfo{
|
||||||
@ -130,16 +94,23 @@ func (s *btmCanetClient) HandleTrainHeadPositionInfoForTrain(w ecs.World, btmCac
|
|||||||
LinkOffset: h.OldLinkOffset,
|
LinkOffset: h.OldLinkOffset,
|
||||||
Speed: h.Speed,
|
Speed: h.Speed,
|
||||||
Acceleration: h.Acceleration}
|
Acceleration: h.Acceleration}
|
||||||
s.baliseDetector.newDetect(wd, repo, h, h2, btmCache)
|
s.baliseDetector.newDetect(wd, repo, h, h2, train.BtmBaliseCacheA, h.IsLine12, false, "11")
|
||||||
//s.baliseDetector.detect2(wd, repo, h, h2, vobcBtm)
|
h.Up = h.TailUp
|
||||||
|
h.Link = h.TailLink
|
||||||
|
h.LinkOffset = h.TailLinkOffset
|
||||||
|
h2.Up = h.TailUp
|
||||||
|
h2.Link = h.OldTailLink
|
||||||
|
h2.LinkOffset = h.OldTailLinkOffset
|
||||||
|
s.baliseDetector.newDetect(wd, repo, h, h2, train.BtmBaliseCacheB, h.IsLine12, false, "222")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// HandleTrainHeadPositionInfo 处理来自动力学的列车位置信息
|
// HandleTrainHeadPositionInfo 处理来自动力学的列车位置信息
|
||||||
func (s *btmCanetClient) HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state_proto.VobcBtmState, h *TrainHeadPositionInfo) {
|
func (s *btmCanetClient) HandleTrainHeadPositionInfo(w ecs.World, h *TrainHeadPositionInfo) {
|
||||||
//slog.Debug(h.String())
|
//slog.Debug(h.String())
|
||||||
wd := entity.GetWorldData(w)
|
wd := entity.GetWorldData(w)
|
||||||
repo := wd.Repo
|
repo := wd.Repo
|
||||||
s.baliseDetector.detect(wd, repo, h, vobcBtm)
|
s.baliseDetector.detect(wd, repo, h)
|
||||||
}
|
}
|
||||||
func (s *btmCanetClient) Start(bcm BtmCanetManager) {
|
func (s *btmCanetClient) Start(bcm BtmCanetManager) {
|
||||||
s.bcm = bcm
|
s.bcm = bcm
|
||||||
|
91
third_party/can_btm/balise_detection.go
vendored
91
third_party/can_btm/balise_detection.go
vendored
@ -2,9 +2,7 @@ package can_btm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/const/balise_const"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
"joylink.club/bj-rtsts-server/dto/state_proto"
|
||||||
"joylink.club/bj-rtsts-server/third_party/btm_vobc"
|
|
||||||
"joylink.club/rtsssimulation/component"
|
"joylink.club/rtsssimulation/component"
|
||||||
"joylink.club/rtsssimulation/fi"
|
"joylink.club/rtsssimulation/fi"
|
||||||
"joylink.club/rtsssimulation/repository"
|
"joylink.club/rtsssimulation/repository"
|
||||||
@ -12,7 +10,6 @@ import (
|
|||||||
"log/slog"
|
"log/slog"
|
||||||
"math"
|
"math"
|
||||||
"sort"
|
"sort"
|
||||||
"strings"
|
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -80,7 +77,7 @@ func (t *BaliseDetector) tryRebind(th *TrainHeadPositionInfo) {
|
|||||||
//slog.Debug(fmt.Sprintf("列车[%s]与CAN-BTM绑定", t.trianId))
|
//slog.Debug(fmt.Sprintf("列车[%s]与CAN-BTM绑定", t.trianId))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (t *BaliseDetector) newDetect(wd *component.WorldData, repo *repository.Repository, th, th2 *TrainHeadPositionInfo, btmCache *state_proto.TrainBtmCache) {
|
func (t *BaliseDetector) newDetect(wd *component.WorldData, repo *repository.Repository, th, th2 *TrainHeadPositionInfo, btmCache *state_proto.TrainBtmCache, isLine12, show bool, id string) {
|
||||||
//BTM天线中心点运行信息
|
//BTM天线中心点运行信息
|
||||||
curAntennaRi := t.createBtmAntennaRunningInfo(wd, repo, th) //目前车头
|
curAntennaRi := t.createBtmAntennaRunningInfo(wd, repo, th) //目前车头
|
||||||
curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, th2) //上次车头
|
curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, th2) //上次车头
|
||||||
@ -90,13 +87,8 @@ func (t *BaliseDetector) newDetect(wd *component.WorldData, repo *repository.Rep
|
|||||||
} else {
|
} else {
|
||||||
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
|
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
|
||||||
}
|
}
|
||||||
|
|
||||||
//startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi.LinkId, th2.LinkOffset, th.LinkOffset)
|
|
||||||
//startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
|
|
||||||
|
|
||||||
balises := make([]*repository.Transponder, 0)
|
balises := make([]*repository.Transponder, 0)
|
||||||
for _, balise := range startBalises {
|
for _, balise := range startBalises {
|
||||||
//slog.Info(fmt.Sprintf("id:%v , %v,linkeId:%v ,headoffset:%v,tailOffset:%v", balise.Id(), th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset))
|
|
||||||
find := false
|
find := false
|
||||||
for _, transponder := range balises {
|
for _, transponder := range balises {
|
||||||
if transponder.Id() == balise.Id() {
|
if transponder.Id() == balise.Id() {
|
||||||
@ -110,16 +102,21 @@ func (t *BaliseDetector) newDetect(wd *component.WorldData, repo *repository.Rep
|
|||||||
}
|
}
|
||||||
if len(balises) > 0 {
|
if len(balises) > 0 {
|
||||||
balise := balises[0]
|
balise := balises[0]
|
||||||
//slog.Info(fmt.Sprintf("-----------------id:%v ,offset:%v, up: %v,linkeId:%v ,headoffset:%v,tailOffset:%v", balise.Id(), balise.LinkPosition().Offset(), th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset))
|
|
||||||
telegram, utel := t.rcvTelegram(wd, balise.Id())
|
telegram, utel := t.rcvTelegram(wd, balise.Id())
|
||||||
if t.addNewExpectedBalise(balise, btmCache, telegram, utel) {
|
/*if show {
|
||||||
//slog.Info(fmt.Sprintf("+++++++++++++id:%v ,offset:%v, up: %v,linkeId:%v ,headoffset:%v,tailOffset:%v", balise.Id(), balise.LinkPosition().Offset(), th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset))
|
slog.Info(fmt.Sprintf("%v --------------------id:%v ,offset:%v, up: %v,linkeId:%v ,headoffset:%v,tailOffset:%v", id, balise.Id(), balise.LinkPosition().Offset(), th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset))
|
||||||
|
}*/
|
||||||
|
if AddNewExpectedBalise(balise, btmCache, telegram, utel, isLine12) {
|
||||||
|
if show {
|
||||||
|
slog.Info(fmt.Sprintf("%v +++++++++++++id:%v ,offset:%v, up: %v,linkeId:%v ,headoffset:%v,tailOffset:%v", id, balise.Id(), balise.LinkPosition().Offset(), th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset))
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Repository, th *TrainHeadPositionInfo, vobcBtm *state_proto.VobcBtmState) {
|
func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Repository, th *TrainHeadPositionInfo) {
|
||||||
t.tryRebind(th)
|
t.tryRebind(th)
|
||||||
//if !t.powerAmplifierSwitch { //天线功率放大器未开启,不进行探测
|
//if !t.powerAmplifierSwitch { //天线功率放大器未开启,不进行探测
|
||||||
// return
|
// return
|
||||||
@ -131,14 +128,9 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
|
|||||||
curExpect := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi)
|
curExpect := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi)
|
||||||
|
|
||||||
if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms
|
if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms
|
||||||
//if curExpect != nil && curExpect.Distance < 80 { //20ms
|
|
||||||
//slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt)
|
|
||||||
//slog.Info(fmt.Sprintf("baliseId:%v,Distance:%v,up:%v", curExpect.BaliseId, curExpect.Distance, curAntennaRi.Up))
|
|
||||||
telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId)
|
telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId)
|
||||||
|
|
||||||
if curExpect.Distance <= 50 {
|
|
||||||
btm_vobc.Default().AppendBaliseMsgForTrain(vobcBtm, curExpect.BaliseId, telegram, curTime.UnixMilli())
|
|
||||||
}
|
|
||||||
//记录即将经过的应答器
|
//记录即将经过的应答器
|
||||||
if t.addExpectedBalise(curExpect) {
|
if t.addExpectedBalise(curExpect) {
|
||||||
t.baliseCounterAdd1() //应答器计数器
|
t.baliseCounterAdd1() //应答器计数器
|
||||||
@ -154,16 +146,6 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
|
|||||||
t.aboveBalise = false
|
t.aboveBalise = false
|
||||||
}
|
}
|
||||||
|
|
||||||
curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, &TrainHeadPositionInfo{TrainId: th.TrainId,
|
|
||||||
Up: !th.Up,
|
|
||||||
Link: th.Link,
|
|
||||||
LinkOffset: th.LinkOffset,
|
|
||||||
Speed: th.Speed,
|
|
||||||
Acceleration: th.Acceleration})
|
|
||||||
curExpect2 := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi2)
|
|
||||||
if curExpect2 != nil && curExpect2.Distance > 20 {
|
|
||||||
btm_vobc.Default().UpdateTrainLeave(vobcBtm, curExpect2.BaliseId, curTime.UnixMilli())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应答器计数器加1,[0,255]
|
// 应答器计数器加1,[0,255]
|
||||||
@ -182,11 +164,14 @@ func (t *BaliseDetector) baliseMessageCounterAdd1() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BaliseCounterAdd(counter uint32) byte {
|
func BaliseCounterAdd(counter uint32, isLine12 bool) byte {
|
||||||
c := byte(counter)
|
c := byte(counter)
|
||||||
c++
|
c++
|
||||||
if c > 255 {
|
if c > 255 {
|
||||||
c = 0
|
c = 1
|
||||||
|
if isLine12 {
|
||||||
|
c = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
@ -202,7 +187,7 @@ func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) (
|
|||||||
if !workedState.Work {
|
if !workedState.Work {
|
||||||
return fixBalise.Telegram, fixBalise.UserTelegram
|
return fixBalise.Telegram, fixBalise.UserTelegram
|
||||||
} else if baliseVar.UserTelegram == nil || len(baliseVar.UserTelegram) == 0 {
|
} else if baliseVar.UserTelegram == nil || len(baliseVar.UserTelegram) == 0 {
|
||||||
slog.Warn(fmt.Sprintf("BTM天线未接受到应答器可变报文,即将使用对应的固定报文, baliseId: %v", baliseId))
|
//slog.Warn(fmt.Sprintf("BTM天线未接受到应答器可变报文,即将使用对应的固定报文, baliseId: %v", baliseId))
|
||||||
return fixBalise.Telegram, fixBalise.UserTelegram
|
return fixBalise.Telegram, fixBalise.UserTelegram
|
||||||
} else {
|
} else {
|
||||||
return baliseVar.Telegram, baliseVar.UserTelegram
|
return baliseVar.Telegram, baliseVar.UserTelegram
|
||||||
@ -210,51 +195,13 @@ func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) (
|
|||||||
} else if workedState.Work {
|
} else if workedState.Work {
|
||||||
return fixBalise.Telegram, fixBalise.UserTelegram
|
return fixBalise.Telegram, fixBalise.UserTelegram
|
||||||
} else {
|
} else {
|
||||||
slog.Warn(fmt.Sprintf("BTM天线未接受到应答器报文,应答器未工作 baliseId: %v", baliseId))
|
//slog.Warn(fmt.Sprintf("BTM天线未接受到应答器报文,应答器未工作 baliseId: %v", baliseId))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
slog.Warn(fmt.Sprintf("BTM天线接收应答器报文,未找到 baliseId: %v", baliseId))
|
//slog.Warn(fmt.Sprintf("BTM天线接收应答器报文,未找到 baliseId: %v", baliseId))
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
func (t *BaliseDetector) addNewExpectedBalise(balise *repository.Transponder, btmCache *state_proto.TrainBtmCache, telegram, userTelegram []byte) bool {
|
|
||||||
t.eqLock.Lock()
|
|
||||||
defer t.eqLock.Unlock()
|
|
||||||
bl := btmCache.BaliseList
|
|
||||||
for _, tt := range bl {
|
|
||||||
if tt != nil && tt.BaliseId == balise.Id() {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 1; i < len(bl); i++ {
|
|
||||||
bl[i-1] = bl[i]
|
|
||||||
}
|
|
||||||
unpack := false
|
|
||||||
bc := BaliseCounterAdd(btmCache.BaliseCount)
|
|
||||||
mc := btmCache.MessageCounter
|
|
||||||
if userTelegram != nil && len(userTelegram) > 0 {
|
|
||||||
mc = uint32(BaliseCounterAdd(mc))
|
|
||||||
unpack = true
|
|
||||||
}
|
|
||||||
|
|
||||||
btmCache.BaliseCount = uint32(bc)
|
|
||||||
btmCache.MessageCounter = mc
|
|
||||||
btmS := &state_proto.BTMState{BaliseId: balise.Id(),
|
|
||||||
Telegram: fmt.Sprintf("%x", userTelegram),
|
|
||||||
Telegram128: fmt.Sprintf("%X", telegram),
|
|
||||||
Unpack: unpack,
|
|
||||||
BaliseType: int32(balise.BaliseType().Number()),
|
|
||||||
AboveBalise: true, HasData: true}
|
|
||||||
|
|
||||||
if userTelegram == nil || len(userTelegram) == 0 {
|
|
||||||
btmS.Telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
|
|
||||||
btmS.Telegram128 = strings.Repeat("00", balise_const.TelegramByteLen)
|
|
||||||
btmS.HasData = false
|
|
||||||
}
|
|
||||||
//存入队尾
|
|
||||||
bl[len(bl)-1] = btmS
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
// true-新增;false-更新
|
// true-新增;false-更新
|
||||||
func (t *BaliseDetector) addExpectedBalise(curExpect *BtmAntennaScanningBaliseInfo) bool {
|
func (t *BaliseDetector) addExpectedBalise(curExpect *BtmAntennaScanningBaliseInfo) bool {
|
||||||
|
121
third_party/can_btm/train_balise_cache.go
vendored
Normal file
121
third_party/can_btm/train_balise_cache.go
vendored
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
package can_btm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"joylink.club/bj-rtsts-server/const/balise_const"
|
||||||
|
"joylink.club/bj-rtsts-server/dto/state_proto"
|
||||||
|
"joylink.club/rtsssimulation/repository"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var baliseLock = &sync.Mutex{}
|
||||||
|
|
||||||
|
func IsLine12(train *state_proto.TrainState) bool {
|
||||||
|
if strings.Contains(train.ProjectCode, "12") {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func AddNewExpectedBalise(balise *repository.Transponder, btmCache *state_proto.TrainBtmCache, telegram, userTelegram []byte, isLine12 bool) bool {
|
||||||
|
baliseLock.Lock()
|
||||||
|
defer baliseLock.Unlock()
|
||||||
|
bl := btmCache.BaliseList
|
||||||
|
for _, tt := range bl {
|
||||||
|
if tt != nil && tt.BaliseId == balise.Id() {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := 1; i < len(bl); i++ {
|
||||||
|
bl[i-1] = bl[i]
|
||||||
|
}
|
||||||
|
unpack := false
|
||||||
|
bc := BaliseCounterAdd(btmCache.BaliseCount, isLine12)
|
||||||
|
mc := btmCache.MessageCounter
|
||||||
|
if userTelegram != nil && len(userTelegram) > 0 {
|
||||||
|
mc = uint32(BaliseCounterAdd(mc, isLine12))
|
||||||
|
unpack = true
|
||||||
|
}
|
||||||
|
|
||||||
|
btmCache.BaliseCount = uint32(bc)
|
||||||
|
btmCache.MessageCounter = mc
|
||||||
|
btmS := &state_proto.BTMState{BaliseId: balise.Id(),
|
||||||
|
Telegram: fmt.Sprintf("%x", userTelegram),
|
||||||
|
Telegram128: fmt.Sprintf("%X", telegram),
|
||||||
|
Unpack: unpack,
|
||||||
|
BaliseType: int32(balise.BaliseType().Number()),
|
||||||
|
AboveBalise: true, HasData: true}
|
||||||
|
|
||||||
|
if userTelegram == nil || len(userTelegram) == 0 {
|
||||||
|
btmS.Telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
|
||||||
|
btmS.Telegram128 = strings.Repeat("00", balise_const.TelegramByteLen)
|
||||||
|
btmS.HasData = false
|
||||||
|
}
|
||||||
|
//存入队尾
|
||||||
|
bl[len(bl)-1] = btmS
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// HandleTrainHeadPositionInfoForTrain 处理列车位置信息
|
||||||
|
// 参数1: 参数2:发送序列号,参数3:应答器计数(每过一个应答器加一,在同一个应答器内不变),参数4:报文计数器 (每解出一个报文加一)(0~255)
|
||||||
|
func FindBaliseResend(cache *state_proto.TrainBtmCache, isLine12 bool) (*state_proto.BTMState, byte, byte, byte) {
|
||||||
|
baliseLock.Lock()
|
||||||
|
defer baliseLock.Unlock()
|
||||||
|
for _, balise := range cache.BaliseList {
|
||||||
|
if balise != nil && balise.BaliseId == cache.ResendBaliseId && balise.ResendCount < 3 {
|
||||||
|
balise.ResendCount++
|
||||||
|
ndsn := BaliseCounterAdd(cache.Dsn, isLine12)
|
||||||
|
cache.Dsn = uint32(ndsn)
|
||||||
|
return balise, ndsn, byte(cache.BaliseCount), byte(cache.MessageCounter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ndsn := BaliseCounterAdd(cache.Dsn, isLine12)
|
||||||
|
return nil, ndsn, 0, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func FindBaliseByNotSend(cache *state_proto.TrainBtmCache, isLine12 bool) (*state_proto.BTMState, byte, byte, byte) {
|
||||||
|
baliseLock.Lock()
|
||||||
|
defer baliseLock.Unlock()
|
||||||
|
|
||||||
|
for _, btmCache := range cache.BaliseList {
|
||||||
|
if btmCache != nil && !btmCache.IsSend {
|
||||||
|
ndsn := BaliseCounterAdd(cache.Dsn, isLine12)
|
||||||
|
cache.Dsn = uint32(ndsn)
|
||||||
|
cache.ResendBaliseId = btmCache.BaliseId
|
||||||
|
return btmCache, ndsn, byte(cache.BaliseCount), byte(cache.MessageCounter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ndsn := BaliseCounterAdd(cache.Dsn, isLine12)
|
||||||
|
return nil, ndsn, 0, 0
|
||||||
|
}
|
||||||
|
func ClearBalise(train *state_proto.TrainState) {
|
||||||
|
baliseLock.Lock()
|
||||||
|
defer baliseLock.Unlock()
|
||||||
|
train.BtmBaliseCacheA.BaliseList = make([]*state_proto.BTMState, 3)
|
||||||
|
train.BtmBaliseCacheB.BaliseList = make([]*state_proto.BTMState, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 11号线根据序列号查询
|
||||||
|
func FindBaliseByMessageSerial(cache *state_proto.TrainBtmCache, isLine12 bool, ms byte) (*state_proto.BTMState, byte, bool) {
|
||||||
|
baliseLock.Lock()
|
||||||
|
defer baliseLock.Unlock()
|
||||||
|
|
||||||
|
for _, btmCache := range cache.BaliseList {
|
||||||
|
if btmCache != nil {
|
||||||
|
if btmCache.BaliseId == cache.ResendBaliseId {
|
||||||
|
if byte(btmCache.PackageDataSN) == ms {
|
||||||
|
bt, dsn, _, _ := FindBaliseByNotSend(cache, isLine12)
|
||||||
|
return bt, dsn, true
|
||||||
|
} else {
|
||||||
|
ndsn := BaliseCounterAdd(cache.Dsn, isLine12)
|
||||||
|
cache.Dsn = uint32(ndsn)
|
||||||
|
return btmCache, ndsn, false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bt, dsn, _, _ := FindBaliseByNotSend(cache, isLine12)
|
||||||
|
return bt, dsn, true
|
||||||
|
|
||||||
|
}
|
28
third_party/interlock/beijing11/msg.go
vendored
28
third_party/interlock/beijing11/msg.go
vendored
@ -2,6 +2,7 @@ package beijing11
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
|
"github.com/snksoft/crc"
|
||||||
)
|
)
|
||||||
|
|
||||||
const ( //不知道对不对,问也不回,先瞎写吧
|
const ( //不知道对不对,问也不回,先瞎写吧
|
||||||
@ -10,11 +11,12 @@ const ( //不知道对不对,问也不回,先瞎写吧
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
SignalAspect_No = 0x01 //灭灯
|
SignalAspect_No = 0x99 //灭灯,这个值目前未知,先用一个应该没被使用的值占位
|
||||||
SignalAspect_H = 0x02 //红灯
|
SignalAspect_H = 0x01 //红灯
|
||||||
SignalAspect_L = 0x03 //绿灯
|
SignalAspect_L = 0x04 //绿灯
|
||||||
SignalAspect_U = 0x04 //黄灯
|
SignalAspect_U = 0x02 //黄灯
|
||||||
SignalAspect_HU = 0x05 //红黄
|
SignalAspect_HU = 0x03 //红黄
|
||||||
|
SignalAspect_B = 0x08 //白灯
|
||||||
)
|
)
|
||||||
|
|
||||||
func GetStateByte(state bool) byte {
|
func GetStateByte(state bool) byte {
|
||||||
@ -265,10 +267,12 @@ func (t *ToInterlockFrame) encode() []byte {
|
|||||||
for _, state := range t.SPKSStates {
|
for _, state := range t.SPKSStates {
|
||||||
data = state.encode(data)
|
data = state.encode(data)
|
||||||
}
|
}
|
||||||
////车库门,数量0
|
//填充字节
|
||||||
//data = binary.BigEndian.AppendUint16(data, 0)
|
fillSlice := make([]byte, 19)
|
||||||
//CRC32,不校验,随便填
|
fillSlice[2] = 1
|
||||||
data = append(data, 0xff, 0xff, 0xff, 0xff)
|
data = append(data, fillSlice...)
|
||||||
|
//CRC32
|
||||||
|
data = binary.BigEndian.AppendUint32(data, crc32(data[3:]))
|
||||||
//填充报文长度
|
//填充报文长度
|
||||||
binary.BigEndian.PutUint16(data[1:3], uint16(len(data)-7))
|
binary.BigEndian.PutUint16(data[1:3], uint16(len(data)-7))
|
||||||
return data
|
return data
|
||||||
@ -387,3 +391,9 @@ type XcjState struct {
|
|||||||
BackConfirm byte //返回确认状态
|
BackConfirm byte //返回确认状态
|
||||||
BackMode byte //模式
|
BackMode byte //模式
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var crcHash = crc.NewHash(&crc.Parameters{Width: 32, Polynomial: 0x4c11db7, Init: 0x0, ReflectIn: false, ReflectOut: false, FinalXor: 0x0})
|
||||||
|
|
||||||
|
func crc32(data []byte) uint32 {
|
||||||
|
return uint32(crcHash.CalculateCRC(data))
|
||||||
|
}
|
||||||
|
137
third_party/interlock/beijing11/msg_test.go
vendored
137
third_party/interlock/beijing11/msg_test.go
vendored
@ -3,41 +3,25 @@ package beijing11
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/util/myreader"
|
"joylink.club/bj-rtsts-server/util/myreader"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestFromInterlockFrame_Decode(t *testing.T) {
|
func TestFromInterlockFrame_Decode(t *testing.T) {
|
||||||
str := "82009a3c0163010006000100000200000300000600000700000800000200010000050000020001aaaa0005aaaa00000008000401000501000601000701001801001901001a01001b010010000480000580000680000780000800000900000a00001d00001e00001f000020000021000022000023000024000025000000000000040001aaaa0002aaaa0003aaaa0004aaaa00000000000000000000000040ace569"
|
str := "58bea4c65e0e583f5bdedc310800450000bd030c0000801100003d0b0a0d3d0b7814413c40d800a9fcf182009a3c016301000600010000020000030000060000070000080000020001000005aa00020001aaaa0005aaaa00000008000401000501000601000701001801001901001a01001b010010000400000500000600000700000800000900000a00001d00001e00001f000020000021000022000023000024000025000000000000040001aaaa0002aaaa0003aaaa0004aaaa0000000000000000000000004c428d88"
|
||||||
data, err := hex.DecodeString(str)
|
data, err := hex.DecodeString(str)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
frame := &FromInterlockFrame{}
|
if data[0] != 0x82 {
|
||||||
err = frame.Decode(data)
|
data = data[42:] //去掉wireshark抓包携带的额外字节
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
marshal, err := json.Marshal(frame)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
fmt.Println(string(marshal))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestToInterlockFrame_Decode(t *testing.T) {
|
|
||||||
str := "83009663013c0100060001010002010003010006010007010008010002000155ffaaaaaa000555ffaaaaaa00020001aaaa0005aaaa00000008000401000501000601000701001801001901001a01001b010010000440000540000640000740000840000940000a40001d40001e40001f40002040002140002240002340002440002540000000000004000155aa000255aa000355aa000455aaffffffff"
|
|
||||||
data, err := hex.DecodeString(str)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
}
|
||||||
reader := myreader.NewReader(data)
|
reader := myreader.NewReader(data)
|
||||||
fmt.Printf("%x【报文类型】\t\n", reader.ReadByte())
|
fmt.Printf("%x\t【报文类型】\n", reader.ReadByte())
|
||||||
fmt.Printf("%x【报文长度】\t\n", reader.ReadBytes(2))
|
fmt.Printf("%x\t【报文长度】\n", reader.ReadBytes(2))
|
||||||
fmt.Printf("%x【轨旁编号】\t\n", reader.ReadBytes(2))
|
fmt.Printf("%x\t【联锁编号】\n", reader.ReadBytes(2))
|
||||||
fmt.Printf("%x【联锁编号】\t\n", reader.ReadBytes(2))
|
fmt.Printf("%x\t【轨旁编号】\n", reader.ReadBytes(2))
|
||||||
{ //道岔
|
{ //道岔
|
||||||
deviceNum := reader.ReadBytes(2)
|
deviceNum := reader.ReadBytes(2)
|
||||||
fmt.Printf("%x\t", deviceNum)
|
fmt.Printf("%x\t", deviceNum)
|
||||||
@ -50,7 +34,110 @@ func TestToInterlockFrame_Decode(t *testing.T) {
|
|||||||
deviceNum := reader.ReadBytes(2)
|
deviceNum := reader.ReadBytes(2)
|
||||||
fmt.Printf("%x\t", deviceNum)
|
fmt.Printf("%x\t", deviceNum)
|
||||||
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
||||||
fmt.Printf("%x ", reader.ReadBytes(8))
|
fmt.Printf("%x ", reader.ReadBytes(3))
|
||||||
|
}
|
||||||
|
fmt.Println("【屏蔽门】")
|
||||||
|
}
|
||||||
|
{ //紧急停车按钮
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
||||||
|
fmt.Printf("%x ", reader.ReadBytes(4))
|
||||||
|
}
|
||||||
|
fmt.Println("【紧急停车按钮】")
|
||||||
|
}
|
||||||
|
{ //扣车按钮
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
fmt.Println("【扣车按钮】")
|
||||||
|
}
|
||||||
|
{ //信号机
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
||||||
|
fmt.Printf("%x ", reader.ReadBytes(3))
|
||||||
|
}
|
||||||
|
fmt.Println("【信号机】")
|
||||||
|
}
|
||||||
|
{ //计轴区段
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
||||||
|
fmt.Printf("%x ", reader.ReadBytes(3))
|
||||||
|
}
|
||||||
|
fmt.Println("【计轴区段】")
|
||||||
|
}
|
||||||
|
{ //无人折返
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
fmt.Println("【无人折返】")
|
||||||
|
}
|
||||||
|
{ //防淹门
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
fmt.Println("【防淹门】")
|
||||||
|
}
|
||||||
|
{ //SPKS
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
||||||
|
fmt.Printf("%x ", reader.ReadBytes(4))
|
||||||
|
}
|
||||||
|
fmt.Println("【SPKS】")
|
||||||
|
}
|
||||||
|
{ //车库门
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
fmt.Println("【车库门】")
|
||||||
|
}
|
||||||
|
{ //预留
|
||||||
|
deviceNum := reader.ReadBytes(10)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
fmt.Println("【预留】")
|
||||||
|
}
|
||||||
|
//CRC32
|
||||||
|
fmt.Printf("%x【CRC32】\n", reader.ReadBytes(4))
|
||||||
|
//{ //json
|
||||||
|
// frame := &FromInterlockFrame{}
|
||||||
|
// err = frame.Decode(data)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
// marshal, err := json.Marshal(frame)
|
||||||
|
// if err != nil {
|
||||||
|
// t.Fatal(err)
|
||||||
|
// }
|
||||||
|
// fmt.Println(string(marshal))
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestToInterlockFrame_Decode(t *testing.T) {
|
||||||
|
str := "583f5bdedc3158bea4c65e0e0800450000f6dfe9400040115dd63d0b78143d0b0a0dd341413c00e2e8c88300d363013c0100060001010002010003010006010007010008010002000102eeaaaaaa000502eeaaaaaa00020001aa000005aa0000000011000101000201000301000401000501000601000701001501001601001701001801001901001a01001b01002901002a01002c010015000100000200000300000400000500000600000700000800000900000a00001b00001c00001d00001e00001f000020000021000022000023000024000025000000000000040001aaff0002aaff0003aaff0004aaff00000100000000000000000000000000000000f38414ee"
|
||||||
|
data, err := hex.DecodeString(str)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
if data[0] != 0x83 {
|
||||||
|
data = data[42:] //去掉wireshark抓包携带的额外字节
|
||||||
|
}
|
||||||
|
reader := myreader.NewReader(data)
|
||||||
|
fmt.Printf("%x\t【报文类型】\n", reader.ReadByte())
|
||||||
|
fmt.Printf("%x\t【报文长度】\n", reader.ReadBytes(2))
|
||||||
|
fmt.Printf("%x\t【轨旁编号】\n", reader.ReadBytes(2))
|
||||||
|
fmt.Printf("%x\t【联锁编号】\n", reader.ReadBytes(2))
|
||||||
|
{ //道岔
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
||||||
|
fmt.Printf("%x ", reader.ReadBytes(3))
|
||||||
|
}
|
||||||
|
fmt.Println("【道岔】")
|
||||||
|
}
|
||||||
|
{ //屏蔽门
|
||||||
|
deviceNum := reader.ReadBytes(2)
|
||||||
|
fmt.Printf("%x\t", deviceNum)
|
||||||
|
for i := 0; i < int(binary.BigEndian.Uint16(deviceNum)); i++ {
|
||||||
|
fmt.Printf("%x ", reader.ReadBytes(7))
|
||||||
}
|
}
|
||||||
fmt.Println("【屏蔽门】")
|
fmt.Println("【屏蔽门】")
|
||||||
}
|
}
|
||||||
@ -102,5 +189,5 @@ func TestToInterlockFrame_Decode(t *testing.T) {
|
|||||||
fmt.Println("【SPKS】")
|
fmt.Println("【SPKS】")
|
||||||
}
|
}
|
||||||
//CRC32
|
//CRC32
|
||||||
fmt.Printf("%x【CRC32】", reader.ReadBytes(4))
|
fmt.Printf("%x【CRC32】\n", reader.ReadBytes(reader.Len()))
|
||||||
}
|
}
|
||||||
|
647
third_party/interlock/beijing11/service.go
vendored
647
third_party/interlock/beijing11/service.go
vendored
@ -10,8 +10,10 @@ import (
|
|||||||
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
||||||
"joylink.club/rtsssimulation/component"
|
"joylink.club/rtsssimulation/component"
|
||||||
"joylink.club/rtsssimulation/entity"
|
"joylink.club/rtsssimulation/entity"
|
||||||
|
"joylink.club/rtsssimulation/fi"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"math"
|
"math"
|
||||||
|
"net"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sort"
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
@ -31,13 +33,12 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type serviceContext struct {
|
type serviceContext struct {
|
||||||
cancelFunc context.CancelFunc //用来结束各个协程的函数
|
cancelFunc context.CancelFunc //用来结束各个协程的函数
|
||||||
client udp.UdpClient //向联锁发送数据的客户端
|
ioAddr *net.UDPAddr //向联锁发送数据的客户端
|
||||||
server udp.UdpServer //接收联锁数据的服务端
|
server udp.UdpServer //接收联锁数据的服务端(同时也是向联锁发送数据的udp客户端)
|
||||||
sim *memory.VerifySimulation //启动服务所使用的仿真
|
sim *memory.VerifySimulation //启动服务所使用的仿真
|
||||||
iConfig config.InterlockConfig //启动服务使用的联锁配置
|
iConfig config.InterlockConfig //启动服务使用的联锁配置
|
||||||
deviceTable *StationDeviceIndexTable //联锁站的设备ID表,key-车站名
|
deviceTable *StationDeviceIndexTable //联锁站的设备ID表,key-车站名
|
||||||
driveMsgSlice []*FromInterlockFrame //驱动消息切片
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimulation) {
|
func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimulation) {
|
||||||
@ -55,13 +56,16 @@ func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimu
|
|||||||
if serviceCtx != nil {
|
if serviceCtx != nil {
|
||||||
panic(fmt.Sprintf("%s重复启动联锁站[%s]通信服务", logTag, interlockConfig.Code))
|
panic(fmt.Sprintf("%s重复启动联锁站[%s]通信服务", logTag, interlockConfig.Code))
|
||||||
}
|
}
|
||||||
//UDP客户端
|
//仿真IO地址
|
||||||
client := udp.NewClient(fmt.Sprintf("%s:%d", interlockConfig.Ip, interlockConfig.RemotePort))
|
ioAddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf("%s:%d", interlockConfig.Ip, interlockConfig.RemotePort))
|
||||||
|
if err != nil {
|
||||||
|
panic(fmt.Sprintf("%s解析IP地址出错:%s", logTag, err))
|
||||||
|
}
|
||||||
|
|
||||||
ctx, cancelFunc := context.WithCancel(context.Background())
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
serviceCtx = &serviceContext{
|
serviceCtx = &serviceContext{
|
||||||
cancelFunc: cancelFunc,
|
cancelFunc: cancelFunc,
|
||||||
client: client,
|
ioAddr: ioAddr,
|
||||||
sim: simulation,
|
sim: simulation,
|
||||||
iConfig: interlockConfig,
|
iConfig: interlockConfig,
|
||||||
deviceTable: table,
|
deviceTable: table,
|
||||||
@ -69,7 +73,7 @@ func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimu
|
|||||||
//UDP服务端
|
//UDP服务端
|
||||||
server := udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), serviceCtx.handleDriveMsg)
|
server := udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), serviceCtx.handleDriveMsg)
|
||||||
serviceCtx.server = server
|
serviceCtx.server = server
|
||||||
err := server.Listen()
|
err = server.Listen()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("%s启动UDP服务失败:%s", logTag, err))
|
panic(fmt.Sprintf("%s启动UDP服务失败:%s", logTag, err))
|
||||||
}
|
}
|
||||||
@ -86,201 +90,220 @@ func (s *serviceContext) handleDriveMsg(data []byte) {
|
|||||||
logger().Error("解析数据出错", "error", err)
|
logger().Error("解析数据出错", "error", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(s.driveMsgSlice) < 2 {
|
|
||||||
if frame.InterlockCode == 0x3c01 || frame.InterlockCode == 0x3c02 {
|
wd := entity.GetWorldData(s.sim.World)
|
||||||
s.driveMsgSlice = append(s.driveMsgSlice, frame)
|
for _, cmd := range frame.TurnoutData.CmdList {
|
||||||
|
uid := s.deviceTable.TurnoutMap[cmd.Id].uid
|
||||||
|
if cmd.Cmd == 0x55 {
|
||||||
|
err = fi.DriveTurnoutDCOn(s.sim.World, uid)
|
||||||
|
} else if cmd.Cmd == 0xaa {
|
||||||
|
err = fi.DriveTurnoutFCOn(s.sim.World, uid)
|
||||||
|
} else {
|
||||||
|
err = fi.DriveTurnoutDCOff(s.sim.World, uid)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
logger().Error("驱动道岔出错", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cmd := range frame.PSDData.CmdList {
|
||||||
|
row := s.deviceTable.PsdMap[cmd.Id]
|
||||||
|
entry := wd.EntityMap[row.uid]
|
||||||
|
circuit := component.PsdCircuitType.Get(entry)
|
||||||
|
logger().Info(fmt.Sprintf("屏蔽门命令:%x", cmd.Cmd))
|
||||||
|
switch cmd.Cmd {
|
||||||
|
case 0xAA: //短编组开门
|
||||||
|
wd.SetQdBit(row.relateDeviceMap[S], true)
|
||||||
|
wd.SetQdBit(row.relateDeviceMap[L], false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(circuit.GMJ).Id, false)
|
||||||
|
case 0xBB: //长编组开门
|
||||||
|
wd.SetQdBit(row.relateDeviceMap[S], false)
|
||||||
|
wd.SetQdBit(row.relateDeviceMap[L], true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(circuit.GMJ).Id, false)
|
||||||
|
case 0x55: //关门
|
||||||
|
wd.SetQdBit(row.relateDeviceMap[S], false)
|
||||||
|
wd.SetQdBit(row.relateDeviceMap[L], false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(circuit.GMJ).Id, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cmd := range frame.ESBData.CmdList {
|
||||||
|
uid := s.deviceTable.EsbMap[cmd.Id].uid
|
||||||
|
esb := s.sim.Repo.FindEsb(uid)
|
||||||
|
if cmd.JjtcplCmd == 0x55 {
|
||||||
|
err = fi.PressDownButton(s.sim.World, esb.PlaId())
|
||||||
|
if err != nil {
|
||||||
|
logger().Error("驱动ESB出错", "error", err)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
err = fi.PressUpButton(s.sim.World, esb.PlaId())
|
||||||
|
if err != nil {
|
||||||
|
logger().Error("驱动ESB出错", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if cmd.JjtcCmd == 0x55 {
|
||||||
|
err := fi.DriveRelayDown(s.sim.World, esb.RelayId())
|
||||||
|
if err != nil {
|
||||||
|
logger().Error("驱动ESB出错", "error", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
err := fi.DriveRelayUp(s.sim.World, esb.RelayId())
|
||||||
|
if err != nil {
|
||||||
|
logger().Error("驱动ESB出错", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cmd := range frame.SignalData.CmdList {
|
||||||
|
uid := s.deviceTable.SignalMap[cmd.Id].uid
|
||||||
|
entry := wd.EntityMap[uid]
|
||||||
|
if entry.HasComponent(component.Signal2XH1ElectronicType) { // 2XH1信号机
|
||||||
|
signal2XH1 := component.Signal2XH1ElectronicType.Get(entry)
|
||||||
|
switch cmd.Cmd {
|
||||||
|
case SignalAspect_No:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_DDJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_LXJ).Id, false)
|
||||||
|
case SignalAspect_H:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_LXJ).Id, false)
|
||||||
|
case SignalAspect_L:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal2XH1.Z2XH1_LXJ).Id, true)
|
||||||
|
default:
|
||||||
|
logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
||||||
|
}
|
||||||
|
} else if entry.HasComponent(component.Signal3XH1ElectronicType) { // 3XH1信号机
|
||||||
|
signal3XH1 := component.Signal3XH1ElectronicType.Get(entry)
|
||||||
|
switch cmd.Cmd {
|
||||||
|
case SignalAspect_No:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false)
|
||||||
|
case SignalAspect_H:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false)
|
||||||
|
case SignalAspect_L:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false)
|
||||||
|
case SignalAspect_U:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, false)
|
||||||
|
case SignalAspect_HU:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_ZXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH1.Z3XH1_YXJ).Id, true)
|
||||||
|
default:
|
||||||
|
logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
||||||
|
}
|
||||||
|
} else if entry.HasComponent(component.Signal3XH2ElectronicType) { // 3XH2信号机
|
||||||
|
signal3XH2 := component.Signal3XH2ElectronicType.Get(entry)
|
||||||
|
switch cmd.Cmd {
|
||||||
|
case SignalAspect_No:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, false)
|
||||||
|
case SignalAspect_H:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, false)
|
||||||
|
case SignalAspect_L:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, false)
|
||||||
|
case SignalAspect_HU:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH2.Z3XH2_YXJ).Id, true)
|
||||||
|
default:
|
||||||
|
logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
||||||
|
}
|
||||||
|
} else if entry.HasComponent(component.Signal3XH3ElectronicType) { // 3XH3信号机
|
||||||
|
signal3XH3 := component.Signal3XH3ElectronicType.Get(entry)
|
||||||
|
switch cmd.Cmd {
|
||||||
|
case SignalAspect_No:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, false)
|
||||||
|
case SignalAspect_H:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, false)
|
||||||
|
case SignalAspect_U:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, false)
|
||||||
|
case SignalAspect_HU:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH3.Z3XH3_YXJ).Id, true)
|
||||||
|
default:
|
||||||
|
logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
||||||
|
}
|
||||||
|
} else if entry.HasComponent(component.Signal3XH4ElectronicType) { // 3XH4信号机
|
||||||
|
signal3XH4 := component.Signal3XH4ElectronicType.Get(entry)
|
||||||
|
switch cmd.Cmd {
|
||||||
|
case SignalAspect_No:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, false)
|
||||||
|
case SignalAspect_H:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, false)
|
||||||
|
case SignalAspect_L:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, true)
|
||||||
|
case SignalAspect_U:
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_DDJ).Id, false)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_LXJ).Id, true)
|
||||||
|
wd.SetQdBit(component.UidType.Get(signal3XH4.Z3XH4_ZXJ).Id, false)
|
||||||
|
default:
|
||||||
|
logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger().Error(fmt.Sprintf("信号机[%s]的型号未知", uid))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cmd := range frame.AxleSectionData.CmdList {
|
||||||
|
if cmd.Cmd == 0x80 {
|
||||||
|
uid := s.deviceTable.AxleSectionMap[cmd.Id].uid
|
||||||
|
physicalSectionUid := s.sim.Repo.FindAxleCountingSection(uid).PhysicalSection().Id()
|
||||||
|
_, err := fi.PhysicalSectionDrstDrive(s.sim.World, physicalSectionUid)
|
||||||
|
if err != nil {
|
||||||
|
logger().Error(fmt.Sprintf("计轴区段[%s]复位出错:%s", uid, err))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, cmd := range frame.SPKSData.CmdList {
|
||||||
|
uid := s.deviceTable.SpksMap[cmd.Id].uid
|
||||||
|
spks := s.sim.Repo.FindSpks(uid)
|
||||||
|
if cmd.SPKSPLCmd == 0x55 {
|
||||||
|
err = fi.PressDownButton(s.sim.World, spks.PlaId())
|
||||||
|
} else {
|
||||||
|
err = fi.PressUpButton(s.sim.World, spks.PlaId())
|
||||||
|
}
|
||||||
|
if cmd.SPKSCmd == 0x55 {
|
||||||
|
err = fi.DriveRelayDown(s.sim.World, spks.Relay())
|
||||||
|
} else {
|
||||||
|
err = fi.DriveRelayUp(s.sim.World, spks.Relay())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//wd := entity.GetWorldData(s.sim.World)
|
|
||||||
////for _, cmd := range frame.TurnoutData.CmdList {
|
|
||||||
//// uid := s.deviceTable.TurnoutMap[cmd.Id].uid
|
|
||||||
////}
|
|
||||||
//for _, cmd := range frame.PSDData.CmdList {
|
|
||||||
// row := s.deviceTable.PsdMap[cmd.Id]
|
|
||||||
// entry := wd.EntityMap[row.uid]
|
|
||||||
// circuit := component.PsdCircuitType.Get(entry)
|
|
||||||
// switch cmd.Cmd {
|
|
||||||
// case 0xAA: //短编组开门
|
|
||||||
// component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[S]]).Td = true
|
|
||||||
// component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[L]]).Td = false
|
|
||||||
// component.RelayDriveType.Get(circuit.GMJ).Td = false
|
|
||||||
// case 0xBB: //长编组开门
|
|
||||||
// component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[S]]).Td = false
|
|
||||||
// component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[L]]).Td = true
|
|
||||||
// component.RelayDriveType.Get(circuit.GMJ).Td = false
|
|
||||||
// case 0x55:
|
|
||||||
// component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[S]]).Td = false
|
|
||||||
// component.RelayDriveType.Get(wd.EntityMap[row.relateDeviceMap[L]]).Td = false
|
|
||||||
// component.RelayDriveType.Get(circuit.GMJ).Td = true
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//for _, cmd := range frame.ESBData.CmdList {
|
|
||||||
// uid := s.deviceTable.EsbMap[cmd.Id].uid
|
|
||||||
// esb := s.sim.Repo.FindEsb(uid)
|
|
||||||
// if cmd.JjtcplCmd == ON {
|
|
||||||
// err := fi.DriveRelayUp(s.sim.World, esb.RelayId())
|
|
||||||
// if err != nil {
|
|
||||||
// logger().Error("驱动ESB出错", "error", err)
|
|
||||||
// }
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// if cmd.JjtcCmd == ON {
|
|
||||||
// err := fi.DriveRelayDown(s.sim.World, esb.RelayId())
|
|
||||||
// if err != nil {
|
|
||||||
// logger().Error("驱动ESB出错", "error", err)
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// err := fi.DriveRelayUp(s.sim.World, esb.RelayId())
|
|
||||||
// if err != nil {
|
|
||||||
// logger().Error("驱动ESB出错", "error", err)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//for _, cmd := range frame.SignalData.CmdList {
|
|
||||||
// uid := s.deviceTable.SignalMap[cmd.Id].uid
|
|
||||||
// entry := wd.EntityMap[uid]
|
|
||||||
// if entry.HasComponent(component.Signal2XH1ElectronicType) { // 2XH1信号机
|
|
||||||
// signal2XH1 := component.Signal2XH1ElectronicType.Get(entry)
|
|
||||||
// switch cmd.Cmd {
|
|
||||||
// case SignalAspect_No:
|
|
||||||
// component.RelayDriveType.Get(signal2XH1.Z2XH1_DDJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal2XH1.Z2XH1_LXJ).Td = false
|
|
||||||
// case SignalAspect_H:
|
|
||||||
// component.RelayDriveType.Get(signal2XH1.Z2XH1_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal2XH1.Z2XH1_LXJ).Td = false
|
|
||||||
// case SignalAspect_L:
|
|
||||||
// component.RelayDriveType.Get(signal2XH1.Z2XH1_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal2XH1.Z2XH1_LXJ).Td = true
|
|
||||||
// default:
|
|
||||||
// logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
|
||||||
// }
|
|
||||||
// } else if entry.HasComponent(component.Signal3XH1ElectronicType) { // 3XH1信号机
|
|
||||||
// signal3XH1 := component.Signal3XH1ElectronicType.Get(entry)
|
|
||||||
// switch cmd.Cmd {
|
|
||||||
// case SignalAspect_No:
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false
|
|
||||||
// case SignalAspect_H:
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false
|
|
||||||
// case SignalAspect_L:
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false
|
|
||||||
// case SignalAspect_U:
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = false
|
|
||||||
// case SignalAspect_HU:
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_ZXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH1.Z3XH1_YXJ).Td = true
|
|
||||||
// default:
|
|
||||||
// logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
|
||||||
// }
|
|
||||||
// } else if entry.HasComponent(component.Signal3XH2ElectronicType) { // 3XH2信号机
|
|
||||||
// signal3XH2 := component.Signal3XH2ElectronicType.Get(entry)
|
|
||||||
// switch cmd.Cmd {
|
|
||||||
// case SignalAspect_No:
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = false
|
|
||||||
// case SignalAspect_H:
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = false
|
|
||||||
// case SignalAspect_L:
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = false
|
|
||||||
// case SignalAspect_HU:
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH2.Z3XH2_YXJ).Td = true
|
|
||||||
// default:
|
|
||||||
// logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
|
||||||
// }
|
|
||||||
// } else if entry.HasComponent(component.Signal3XH3ElectronicType) { // 3XH3信号机
|
|
||||||
// signal3XH3 := component.Signal3XH3ElectronicType.Get(entry)
|
|
||||||
// switch cmd.Cmd {
|
|
||||||
// case SignalAspect_No:
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = false
|
|
||||||
// case SignalAspect_H:
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = false
|
|
||||||
// case SignalAspect_U:
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = false
|
|
||||||
// case SignalAspect_HU:
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH3.Z3XH3_YXJ).Td = true
|
|
||||||
// default:
|
|
||||||
// logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
|
||||||
// }
|
|
||||||
// } else if entry.HasComponent(component.Signal3XH4ElectronicType) { // 3XH4信号机
|
|
||||||
// signal3XH4 := component.Signal3XH4ElectronicType.Get(entry)
|
|
||||||
// switch cmd.Cmd {
|
|
||||||
// case SignalAspect_No:
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = false
|
|
||||||
// case SignalAspect_H:
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = false
|
|
||||||
// case SignalAspect_L:
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = true
|
|
||||||
// case SignalAspect_U:
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_DDJ).Td = false
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_LXJ).Td = true
|
|
||||||
// component.RelayDriveType.Get(signal3XH4.Z3XH4_ZXJ).Td = false
|
|
||||||
// default:
|
|
||||||
// logger().Error(fmt.Sprintf("信号机[%s]无法开放[%x]信号", uid, cmd.Cmd))
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// logger().Error(fmt.Sprintf("信号机[%s]的型号未知", uid))
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
//for _, cmd := range frame.AxleSectionData.CmdList {
|
|
||||||
// if cmd.Cmd == 0x80 {
|
|
||||||
// uid := s.deviceTable.AxleSectionMap[cmd.Id].uid
|
|
||||||
// physicalSectionUid := s.sim.Repo.FindAxleCountingSection(uid).PhysicalSection().Id()
|
|
||||||
// _, err := fi.PhysicalSectionDrstDrive(s.sim.World, physicalSectionUid)
|
|
||||||
// if err != nil {
|
|
||||||
// logger().Error(fmt.Sprintf("计轴区段[%s]复位出错:%s", uid, err))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
////for _, cmd := range frame.SPKSData.CmdList {
|
|
||||||
//// uid := s.deviceTable.SpksMap[cmd.Id].uid
|
|
||||||
////}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Stop(stationCode string) {
|
func Stop(stationCode string) {
|
||||||
mu.Lock()
|
mu.Lock()
|
||||||
defer mu.Unlock()
|
defer mu.Unlock()
|
||||||
context := serviceContextMap[stationCode]
|
serviceContext := serviceContextMap[stationCode]
|
||||||
if context != nil {
|
if serviceContext != nil {
|
||||||
if context.client != nil {
|
if serviceContext.server != nil {
|
||||||
context.client.Close()
|
serviceContext.server.Close()
|
||||||
}
|
|
||||||
if context.server != nil {
|
|
||||||
context.server.Close()
|
|
||||||
}
|
}
|
||||||
delete(serviceContextMap, stationCode)
|
delete(serviceContextMap, stationCode)
|
||||||
}
|
}
|
||||||
@ -459,47 +482,39 @@ func (s *serviceContext) runCollectTask(ctx context.Context) {
|
|||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
for _, driveMsg := range s.driveMsgSlice {
|
frame := s.collectDeviceState()
|
||||||
frame := s.collectDeviceState(driveMsg)
|
data := frame.encode()
|
||||||
data := frame.encode()
|
_, err := s.server.WriteToUdp(data, s.ioAddr)
|
||||||
err := s.client.Send(data)
|
if err != nil {
|
||||||
if err != nil {
|
logger().Error("向联锁发送数据失败", "error", err)
|
||||||
logger().Error("向联锁发送数据失败", "error", err)
|
} else {
|
||||||
} else {
|
logger().Info(fmt.Sprintf("向联锁发送数据:%x", data))
|
||||||
logger().Info(fmt.Sprintf("向联锁发送数据:%x", data))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//frame := s.collectDeviceState()
|
|
||||||
//data := frame.encode()
|
|
||||||
//err := s.client.Send(data)
|
|
||||||
//if err != nil {
|
|
||||||
// logger().Error("向联锁发送数据失败", "error", err)
|
|
||||||
//} else {
|
|
||||||
// logger().Info(fmt.Sprintf("向联锁发送数据:%x", data))
|
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterlockFrame {
|
func (s *serviceContext) collectDeviceState() *ToInterlockFrame {
|
||||||
wd := entity.GetWorldData(s.sim.World)
|
wd := entity.GetWorldData(s.sim.World)
|
||||||
frame := &ToInterlockFrame{}
|
frame := &ToInterlockFrame{}
|
||||||
frame.WaysideCode = waysideCode
|
frame.WaysideCode = waysideCode
|
||||||
frame.InterlockCode = msg.InterlockCode
|
frame.InterlockCode = s.deviceTable.InterlockCode
|
||||||
//道岔
|
//道岔
|
||||||
for _, cmd := range msg.TurnoutData.CmdList {
|
for _, row := range s.deviceTable.TurnoutMap {
|
||||||
row := s.deviceTable.TurnoutMap[cmd.Id]
|
|
||||||
entry := wd.EntityMap[row.uid]
|
entry := wd.EntityMap[row.uid]
|
||||||
tp := component.TurnoutPositionType.Get(entry)
|
tp := component.TurnoutPositionType.Get(entry)
|
||||||
var stateByte byte
|
var stateByte byte
|
||||||
if tp.Dw {
|
if entry.HasComponent(component.TurnoutFaultCiqdType) {
|
||||||
stateByte = 0x01
|
stateByte = 0xff
|
||||||
} else if tp.Fw {
|
|
||||||
stateByte = 0x02
|
|
||||||
} else {
|
} else {
|
||||||
stateByte = 0x08
|
if tp.Dw {
|
||||||
|
stateByte = 0x01
|
||||||
|
} else if tp.Fw {
|
||||||
|
stateByte = 0x02
|
||||||
|
} else {
|
||||||
|
stateByte = 0x08
|
||||||
|
}
|
||||||
}
|
}
|
||||||
frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{
|
frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{
|
||||||
Id: row.index,
|
Id: row.index,
|
||||||
@ -510,8 +525,7 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
|
|||||||
return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id
|
return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id
|
||||||
})
|
})
|
||||||
//屏蔽门
|
//屏蔽门
|
||||||
for _, cmd := range msg.PSDData.CmdList {
|
for _, row := range s.deviceTable.PsdMap {
|
||||||
row := s.deviceTable.PsdMap[cmd.Id]
|
|
||||||
entry := wd.EntityMap[row.uid]
|
entry := wd.EntityMap[row.uid]
|
||||||
psdState := component.PsdStateType.Get(entry)
|
psdState := component.PsdStateType.Get(entry)
|
||||||
mkxBytes := make([]byte, 0, 3)
|
mkxBytes := make([]byte, 0, 3)
|
||||||
@ -521,10 +535,22 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
|
|||||||
}
|
}
|
||||||
mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val))
|
mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val))
|
||||||
}
|
}
|
||||||
|
var state byte
|
||||||
|
if psdState.Close {
|
||||||
|
state = 0x02
|
||||||
|
} else {
|
||||||
|
state = 0x01
|
||||||
|
}
|
||||||
|
var hsjc byte
|
||||||
|
if psdState.InterlockRelease {
|
||||||
|
hsjc = 0xff
|
||||||
|
} else {
|
||||||
|
hsjc = 0xee
|
||||||
|
}
|
||||||
frame.PsdStates = append(frame.PsdStates, &PSDState{
|
frame.PsdStates = append(frame.PsdStates, &PSDState{
|
||||||
Id: row.index,
|
Id: row.index,
|
||||||
State: GetStateByte(psdState.Close),
|
State: state,
|
||||||
Hsjc: 0xff,
|
Hsjc: hsjc,
|
||||||
PCB: mkxBytes[0],
|
PCB: mkxBytes[0],
|
||||||
POB: mkxBytes[1],
|
POB: mkxBytes[1],
|
||||||
DPB: mkxBytes[2],
|
DPB: mkxBytes[2],
|
||||||
@ -534,8 +560,7 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
|
|||||||
return frame.PsdStates[i].Id < frame.PsdStates[j].Id
|
return frame.PsdStates[i].Id < frame.PsdStates[j].Id
|
||||||
})
|
})
|
||||||
//紧急停车
|
//紧急停车
|
||||||
for _, cmd := range msg.ESBData.CmdList {
|
for _, row := range s.deviceTable.EsbMap {
|
||||||
row := s.deviceTable.EsbMap[cmd.Id]
|
|
||||||
esb := s.sim.Repo.FindEsb(row.uid)
|
esb := s.sim.Repo.FindEsb(row.uid)
|
||||||
relay := wd.EntityMap[esb.RelayId()]
|
relay := wd.EntityMap[esb.RelayId()]
|
||||||
pla := wd.EntityMap[esb.PlaId()]
|
pla := wd.EntityMap[esb.PlaId()]
|
||||||
@ -543,14 +568,14 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
|
|||||||
Id: row.index,
|
Id: row.index,
|
||||||
State: GetStateByte(!component.BitStateType.Get(relay).Val),
|
State: GetStateByte(!component.BitStateType.Get(relay).Val),
|
||||||
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
||||||
|
//PlState: 0x00,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.Slice(frame.ESBStates, func(i, j int) bool {
|
sort.Slice(frame.ESBStates, func(i, j int) bool {
|
||||||
return frame.ESBStates[i].Id < frame.ESBStates[j].Id
|
return frame.ESBStates[i].Id < frame.ESBStates[j].Id
|
||||||
})
|
})
|
||||||
//信号机
|
//信号机
|
||||||
for _, cmd := range msg.SignalData.CmdList {
|
for _, row := range s.deviceTable.SignalMap {
|
||||||
row := s.deviceTable.SignalMap[cmd.Id]
|
|
||||||
entry := wd.EntityMap[row.uid]
|
entry := wd.EntityMap[row.uid]
|
||||||
lights := component.SignalLightsType.Get(entry)
|
lights := component.SignalLightsType.Get(entry)
|
||||||
isL := false
|
isL := false
|
||||||
@ -598,11 +623,10 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
|
|||||||
return frame.SignalStates[i].Id < frame.SignalStates[j].Id
|
return frame.SignalStates[i].Id < frame.SignalStates[j].Id
|
||||||
})
|
})
|
||||||
//计轴区段
|
//计轴区段
|
||||||
for _, cmd := range msg.AxleSectionData.CmdList {
|
for _, row := range s.deviceTable.AxleSectionMap {
|
||||||
row := s.deviceTable.AxleSectionMap[cmd.Id]
|
|
||||||
entry := wd.EntityMap[row.uid]
|
entry := wd.EntityMap[row.uid]
|
||||||
sectionState := component.AxleCountingSectionStateType.Get(entry)
|
sectionState := component.AxleCountingSectionStateType.Get(entry)
|
||||||
var stateByte byte = 0x40
|
var stateByte byte = 0x00
|
||||||
if sectionState.Occupied {
|
if sectionState.Occupied {
|
||||||
stateByte = 0x40
|
stateByte = 0x40
|
||||||
}
|
}
|
||||||
@ -615,15 +639,15 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
|
|||||||
return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id
|
return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id
|
||||||
})
|
})
|
||||||
//SPKS
|
//SPKS
|
||||||
for _, cmd := range msg.SPKSData.CmdList {
|
for _, row := range s.deviceTable.SpksMap {
|
||||||
row := s.deviceTable.SpksMap[cmd.Id]
|
|
||||||
spks := s.sim.Repo.FindSpks(row.uid)
|
spks := s.sim.Repo.FindSpks(row.uid)
|
||||||
relay := wd.EntityMap[spks.Relay()]
|
relay := wd.EntityMap[spks.Relay()]
|
||||||
pla := wd.EntityMap[spks.PlaId()]
|
pla := wd.EntityMap[spks.PlaId()]
|
||||||
frame.SPKSStates = append(frame.SPKSStates, &SPKSState{
|
frame.SPKSStates = append(frame.SPKSStates, &SPKSState{
|
||||||
Id: row.index,
|
Id: row.index,
|
||||||
State: GetStateByte(component.BitStateType.Get(relay).Val),
|
State: GetStateByte(!component.BitStateType.Get(relay).Val),
|
||||||
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
||||||
|
//PlState: 0xff,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
sort.Slice(frame.SPKSStates, func(i, j int) bool {
|
sort.Slice(frame.SPKSStates, func(i, j int) bool {
|
||||||
@ -632,149 +656,6 @@ func (s *serviceContext) collectDeviceState(msg *FromInterlockFrame) *ToInterloc
|
|||||||
return frame
|
return frame
|
||||||
}
|
}
|
||||||
|
|
||||||
//func (s *serviceContext) collectDeviceState() *ToInterlockFrame {
|
|
||||||
// wd := entity.GetWorldData(s.sim.World)
|
|
||||||
// frame := &ToInterlockFrame{}
|
|
||||||
// frame.WaysideCode = waysideCode
|
|
||||||
// frame.InterlockCode = s.deviceTable.InterlockCode
|
|
||||||
// //道岔
|
|
||||||
// for _, row := range s.deviceTable.TurnoutMap {
|
|
||||||
// entry := wd.EntityMap[row.uid]
|
|
||||||
// tp := component.TurnoutPositionType.Get(entry)
|
|
||||||
// var stateByte byte
|
|
||||||
// if tp.Dw {
|
|
||||||
// stateByte = 0x01
|
|
||||||
// } else if tp.Fw {
|
|
||||||
// stateByte = 0x02
|
|
||||||
// } else {
|
|
||||||
// stateByte = 0x08
|
|
||||||
// }
|
|
||||||
// frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{
|
|
||||||
// Id: row.index,
|
|
||||||
// State: stateByte,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// sort.Slice(frame.TurnoutStates, func(i, j int) bool {
|
|
||||||
// return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id
|
|
||||||
// })
|
|
||||||
// //屏蔽门
|
|
||||||
// for _, row := range s.deviceTable.PsdMap {
|
|
||||||
// entry := wd.EntityMap[row.uid]
|
|
||||||
// psdState := component.PsdStateType.Get(entry)
|
|
||||||
// mkxBytes := make([]byte, 0, 3)
|
|
||||||
// for _, mkxRelayUid := range []string{row.relateDeviceMap[POB], row.relateDeviceMap[PCB], row.relateDeviceMap[DPB]} {
|
|
||||||
// if mkxRelayUid == "" {
|
|
||||||
// continue
|
|
||||||
// }
|
|
||||||
// mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val))
|
|
||||||
// }
|
|
||||||
// frame.PsdStates = append(frame.PsdStates, &PSDState{
|
|
||||||
// Id: row.index,
|
|
||||||
// State: GetStateByte(psdState.Close),
|
|
||||||
// Hsjc: 0xff,
|
|
||||||
// PCB: mkxBytes[0],
|
|
||||||
// POB: mkxBytes[1],
|
|
||||||
// DPB: mkxBytes[2],
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// sort.Slice(frame.PsdStates, func(i, j int) bool {
|
|
||||||
// return frame.PsdStates[i].Id < frame.PsdStates[j].Id
|
|
||||||
// })
|
|
||||||
// //紧急停车
|
|
||||||
// for _, row := range s.deviceTable.EsbMap {
|
|
||||||
// esb := s.sim.Repo.FindEsb(row.uid)
|
|
||||||
// relay := wd.EntityMap[esb.RelayId()]
|
|
||||||
// pla := wd.EntityMap[esb.PlaId()]
|
|
||||||
// frame.ESBStates = append(frame.ESBStates, &ESBState{
|
|
||||||
// Id: row.index,
|
|
||||||
// State: GetStateByte(!component.BitStateType.Get(relay).Val),
|
|
||||||
// PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// sort.Slice(frame.ESBStates, func(i, j int) bool {
|
|
||||||
// return frame.ESBStates[i].Id < frame.ESBStates[j].Id
|
|
||||||
// })
|
|
||||||
// //信号机
|
|
||||||
// for _, row := range s.deviceTable.SignalMap {
|
|
||||||
// entry := wd.EntityMap[row.uid]
|
|
||||||
// lights := component.SignalLightsType.Get(entry)
|
|
||||||
// isL := false
|
|
||||||
// isH := false
|
|
||||||
// isU := false
|
|
||||||
// isA := false
|
|
||||||
// isB := false
|
|
||||||
// for _, light := range lights.Lights {
|
|
||||||
// switch {
|
|
||||||
// case light.HasComponent(component.LdTag):
|
|
||||||
// isL = component.BitStateType.Get(light).Val
|
|
||||||
// case light.HasComponent(component.HdTag):
|
|
||||||
// isH = component.BitStateType.Get(light).Val
|
|
||||||
// case light.HasComponent(component.UdTag):
|
|
||||||
// isU = component.BitStateType.Get(light).Val
|
|
||||||
// case light.HasComponent(component.BdTag):
|
|
||||||
// isB = component.BitStateType.Get(light).Val
|
|
||||||
// case light.HasComponent(component.AdTag):
|
|
||||||
// isA = component.BitStateType.Get(light).Val
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// var stateByte byte
|
|
||||||
// if isH && isU {
|
|
||||||
// stateByte = 0x03
|
|
||||||
// } else {
|
|
||||||
// switch {
|
|
||||||
// case isL:
|
|
||||||
// stateByte = 0x04
|
|
||||||
// case isH:
|
|
||||||
// stateByte = 0x01
|
|
||||||
// case isU:
|
|
||||||
// stateByte = 0x02
|
|
||||||
// case isB:
|
|
||||||
// stateByte = 0x08
|
|
||||||
// case isA:
|
|
||||||
// stateByte = 0x09
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// frame.SignalStates = append(frame.SignalStates, &SignalState{
|
|
||||||
// Id: row.index,
|
|
||||||
// State: stateByte,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// sort.Slice(frame.SignalStates, func(i, j int) bool {
|
|
||||||
// return frame.SignalStates[i].Id < frame.SignalStates[j].Id
|
|
||||||
// })
|
|
||||||
// //计轴区段
|
|
||||||
// for _, row := range s.deviceTable.AxleSectionMap {
|
|
||||||
// entry := wd.EntityMap[row.uid]
|
|
||||||
// sectionState := component.AxleCountingSectionStateType.Get(entry)
|
|
||||||
// var stateByte byte = 0x40
|
|
||||||
// if sectionState.Occupied {
|
|
||||||
// stateByte = 0x40
|
|
||||||
// }
|
|
||||||
// frame.AxleSectionStates = append(frame.AxleSectionStates, &AxleSectionState{
|
|
||||||
// Id: row.index,
|
|
||||||
// State: stateByte,
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// sort.Slice(frame.AxleSectionStates, func(i, j int) bool {
|
|
||||||
// return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id
|
|
||||||
// })
|
|
||||||
// //SPKS
|
|
||||||
// for _, row := range s.deviceTable.SpksMap {
|
|
||||||
// spks := s.sim.Repo.FindSpks(row.uid)
|
|
||||||
// relay := wd.EntityMap[spks.Relay()]
|
|
||||||
// pla := wd.EntityMap[spks.PlaId()]
|
|
||||||
// frame.SPKSStates = append(frame.SPKSStates, &SPKSState{
|
|
||||||
// Id: row.index,
|
|
||||||
// State: GetStateByte(component.BitStateType.Get(relay).Val),
|
|
||||||
// PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// sort.Slice(frame.SPKSStates, func(i, j int) bool {
|
|
||||||
// return frame.SPKSStates[i].Id < frame.SPKSStates[j].Id
|
|
||||||
// })
|
|
||||||
// return frame
|
|
||||||
//}
|
|
||||||
|
|
||||||
func logger() *slog.Logger {
|
func logger() *slog.Logger {
|
||||||
loggerInit.Do(func() {
|
loggerInit.Do(func() {
|
||||||
privateLogger = slog.Default().With("tag", logTag)
|
privateLogger = slog.Default().With("tag", logTag)
|
||||||
|
476
third_party/message/btm_vobc_data.go
vendored
476
third_party/message/btm_vobc_data.go
vendored
@ -75,355 +75,47 @@ const (
|
|||||||
COM_WAIT_STOP_FD = 0x03
|
COM_WAIT_STOP_FD = 0x03
|
||||||
)
|
)
|
||||||
|
|
||||||
func aa(src []byte, dest []byte) uint16 {
|
/*
|
||||||
var (
|
func SourceDataDecode(packData []byte) []BaseBtmVobc {
|
||||||
SrcPos, TgtPos, Pos1, Pos2, iii, Gap uint16
|
data, _ := TranslateFromFFFE(packData)
|
||||||
Got1stFF uint8
|
buf := bytes.NewBuffer(data)
|
||||||
)
|
|
||||||
srouceLen := uint16(len(src))
|
|
||||||
for SrcPos = 0; SrcPos < srouceLen; SrcPos++ {
|
|
||||||
if Got1stFF == 1 {
|
|
||||||
if src[SrcPos] == 0xff {
|
|
||||||
//Got2ndFF = 1
|
|
||||||
Pos2 = SrcPos
|
|
||||||
dest[TgtPos] = byte(Pos2 - Pos1)
|
|
||||||
TgtPos++
|
|
||||||
|
|
||||||
for iii = Pos1 + 1; iii < Pos2; iii++ {
|
|
||||||
dest[TgtPos] = src[iii]
|
|
||||||
TgtPos++
|
|
||||||
}
|
|
||||||
Got1stFF = 0
|
|
||||||
//Got2ndFF = 0
|
|
||||||
Pos1 = 0
|
|
||||||
Pos2 = 0
|
|
||||||
Gap = 0
|
|
||||||
} else {
|
|
||||||
/*已遇到前一个FF,且当前遇到非FF*/
|
|
||||||
Gap++
|
|
||||||
if 252 == Gap {
|
|
||||||
Got1stFF = 0
|
|
||||||
Gap = 0
|
|
||||||
dest[TgtPos] = 0
|
|
||||||
TgtPos++
|
|
||||||
for iii = Pos1 + 1; iii <= SrcPos; iii++ {
|
|
||||||
dest[TgtPos] = src[iii]
|
|
||||||
TgtPos++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
/*尚未遇到前一个FF*/
|
|
||||||
dest[TgtPos] = src[SrcPos]
|
|
||||||
TgtPos++
|
|
||||||
if 0xFF == src[SrcPos] {
|
|
||||||
/*遇到前一个FF*/
|
|
||||||
Got1stFF = 1
|
|
||||||
Pos1 = SrcPos
|
|
||||||
Gap = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if 1 == Got1stFF {
|
|
||||||
dest[TgtPos] = 0
|
|
||||||
TgtPos++
|
|
||||||
for iii = Pos1 + 1; iii < srouceLen; iii++ {
|
|
||||||
dest[TgtPos] = src[iii]
|
|
||||||
TgtPos++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return TgtPos
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TranslateFromFFFE(pSrc []byte) ([]byte, uint16) {
|
func parseData(buf *bytes.Buffer) {
|
||||||
var (
|
h1, _ := buf.ReadByte()
|
||||||
srcPos, tgtPos, nonFFCount, nextFFPos uint16
|
h2, _ := buf.ReadByte()
|
||||||
char uint8
|
if bytes.Equal(PACKAGE_HEAD, []byte{h1, h2}) {
|
||||||
state int
|
t, _ := buf.ReadByte()
|
||||||
)
|
var ft byte = 0
|
||||||
|
if t == ID_COMMAND_TYPE || t == REQT_TYPE {
|
||||||
|
ft, _ = buf.ReadByte()
|
||||||
|
if t == ID_COMMAND_TYPE {
|
||||||
|
return parseIdFrame(ft, buf.Bytes())
|
||||||
|
} else if t == REQT_TYPE {
|
||||||
|
|
||||||
if len(pSrc) == 0 {
|
|
||||||
return nil, 0 // 入参错误
|
|
||||||
}
|
|
||||||
|
|
||||||
pTgt := make([]byte, len(pSrc)) // 预分配与输入等长的缓冲区
|
|
||||||
tgtPos = 0
|
|
||||||
state = WAIT_FF_C1
|
|
||||||
nonFFCount = 0
|
|
||||||
|
|
||||||
for srcPos = 0; srcPos < uint16(len(pSrc)); srcPos++ {
|
|
||||||
char = pSrc[srcPos]
|
|
||||||
switch state {
|
|
||||||
case WAIT_FF_C1:
|
|
||||||
if char == 0xFF {
|
|
||||||
pTgt[tgtPos] = char
|
|
||||||
tgtPos++
|
|
||||||
state = WAIT_FF_C2
|
|
||||||
} else {
|
|
||||||
pTgt[tgtPos] = char
|
|
||||||
tgtPos++
|
|
||||||
}
|
|
||||||
case WAIT_FF_C2:
|
|
||||||
if char == 0xFD || char == 0xFE || char == 0xFF {
|
|
||||||
state = ABNORMAL_STATE
|
|
||||||
} else {
|
|
||||||
if char == 0 {
|
|
||||||
state = WAIT_NO_FF
|
|
||||||
} else if char == 1 {
|
|
||||||
pTgt[tgtPos] = 0xFF
|
|
||||||
tgtPos++
|
|
||||||
state = WAIT_FF_C1
|
|
||||||
} else {
|
|
||||||
nextFFPos = srcPos + uint16(char) - 1
|
|
||||||
state = WAIT_FF_POS
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case WAIT_NO_FF:
|
|
||||||
nonFFCount++
|
|
||||||
if char == 0xFF && nonFFCount < 252 {
|
|
||||||
state = ABNORMAL_STATE
|
|
||||||
} else {
|
|
||||||
pTgt[tgtPos] = char
|
|
||||||
tgtPos++
|
|
||||||
if nonFFCount == 252 {
|
|
||||||
nonFFCount = 0
|
|
||||||
state = WAIT_FF_C1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case WAIT_FF_POS:
|
|
||||||
if char == 0xFF {
|
|
||||||
state = ABNORMAL_STATE
|
|
||||||
} else {
|
|
||||||
pTgt[tgtPos] = char
|
|
||||||
tgtPos++
|
|
||||||
if srcPos == nextFFPos {
|
|
||||||
pTgt[tgtPos] = 0xFF
|
|
||||||
tgtPos++
|
|
||||||
state = WAIT_FF_C1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
state = ABNORMAL_STATE
|
|
||||||
}
|
|
||||||
|
|
||||||
if state == ABNORMAL_STATE {
|
|
||||||
tgtPos = 0
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 退出时的状态判断
|
|
||||||
if state == WAIT_FF_C2 || state == WAIT_FF_POS {
|
|
||||||
tgtPos = 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return pTgt[:tgtPos], tgtPos
|
|
||||||
}
|
|
||||||
|
|
||||||
// TranslateToFFFE 对给定的字节切片进行FFFE转义处理
|
|
||||||
func TranslateToFFFE(src []byte) ([]byte, error) {
|
|
||||||
if src == nil {
|
|
||||||
return nil, fmt.Errorf("source data is nil")
|
|
||||||
}
|
|
||||||
var tgt []byte
|
|
||||||
var pos1, pos2 int
|
|
||||||
var gap int
|
|
||||||
var got1stFF bool
|
|
||||||
|
|
||||||
for i, b := range src {
|
|
||||||
if got1stFF {
|
|
||||||
if b == 0xFF {
|
|
||||||
// 已遇到前一个FF,且当前又遇到FF
|
|
||||||
got1stFF = false
|
|
||||||
pos2 = i
|
|
||||||
if gap > 252 {
|
|
||||||
// 间隙过大,特殊处理
|
|
||||||
tgt = append(tgt, 0)
|
|
||||||
tgt = append(tgt, src[pos1+1:pos2]...)
|
|
||||||
} else {
|
|
||||||
// 写入间隙长度
|
|
||||||
tgt = append(tgt, byte(gap))
|
|
||||||
// 写入间隙中的字节
|
|
||||||
tgt = append(tgt, src[pos1+1:pos2]...)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// 已遇到前一个FF,且当前遇到非FF,增加gap计数
|
|
||||||
gap++
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 尚未遇到前一个FF
|
|
||||||
tgt = append(tgt, b)
|
|
||||||
if b == 0xFF {
|
|
||||||
// 遇到前一个FF
|
|
||||||
got1stFF = true
|
|
||||||
pos1 = i
|
|
||||||
gap = 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 如果在数据末尾遇到了FF且没有第二个FF
|
|
||||||
if got1stFF {
|
|
||||||
if gap > 252 {
|
|
||||||
tgt = append(tgt, 0)
|
|
||||||
tgt = append(tgt, src[pos1+1:]...)
|
|
||||||
} else {
|
|
||||||
tgt = append(tgt, 0)
|
|
||||||
tgt = append(tgt, src[pos1+1:len(src)]...)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return tgt, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// TranslateToFFFE 将数据进行FFFE转义处理(不加头FFFE及尾FFFD)。
|
|
||||||
/*func TranslateToFFFE2(pSrc []byte) []byte {
|
|
||||||
var (
|
|
||||||
srcPos, tgtPos, pos1, pos2, iii uint16
|
|
||||||
gap uint16
|
|
||||||
got1stFF bool
|
|
||||||
)
|
|
||||||
|
|
||||||
if pSrc == nil {
|
|
||||||
return nil // 入口参数错误
|
|
||||||
}
|
|
||||||
|
|
||||||
pTgt := make([]byte, 0, len(pSrc)*2) // 预分配空间以应对最坏情况
|
|
||||||
|
|
||||||
for srcPos = 0; srcPos < uint16(len(pSrc)); srcPos++ {
|
|
||||||
if got1stFF {
|
|
||||||
if pSrc[srcPos] == 0xFF {
|
|
||||||
// 已遇到前一个FF,且当前又遇到FF
|
|
||||||
|
|
||||||
pos2 = srcPos
|
|
||||||
pTgt = append(pTgt, byte(pos2-pos1))
|
|
||||||
tgtPos++
|
|
||||||
|
|
||||||
for iii = pos1 + 1; iii < pos2; iii++ {
|
|
||||||
pTgt = append(pTgt, pSrc[iii])
|
|
||||||
tgtPos++
|
|
||||||
}
|
|
||||||
|
|
||||||
got1stFF = false
|
|
||||||
pos1, pos2, gap = 0, 0, 0
|
|
||||||
} else {
|
|
||||||
// 已遇到前一个FF,且当前遇到非FF
|
|
||||||
gap++
|
|
||||||
if gap == 252 {
|
|
||||||
got1stFF, gap = false, 0
|
|
||||||
pTgt = append(pTgt, 0)
|
|
||||||
tgtPos++
|
|
||||||
|
|
||||||
for iii = pos1 + 1; iii <= srcPos; iii++ {
|
|
||||||
pTgt = append(pTgt, pSrc[iii])
|
|
||||||
tgtPos++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 尚未遇到前一个FF
|
|
||||||
pTgt = append(pTgt, pSrc[srcPos])
|
|
||||||
tgtPos++
|
|
||||||
|
|
||||||
if pSrc[srcPos] == 0xFF {
|
|
||||||
// 遇到前一个FF
|
|
||||||
got1stFF = true
|
|
||||||
pos1 = srcPos
|
|
||||||
gap = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 已经遇到了前一个FF, 且源数据已到了末尾仍未遇到后一个FF
|
|
||||||
if got1stFF {
|
|
||||||
pTgt = append(pTgt, 0)
|
|
||||||
tgtPos++
|
|
||||||
|
|
||||||
for iii = pos1 + 1; iii < uint16(len(pSrc)); iii++ {
|
|
||||||
pTgt = append(pTgt, pSrc[iii])
|
|
||||||
tgtPos++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 截取实际使用的部分返回
|
|
||||||
return pTgt[:tgtPos]
|
|
||||||
}
|
|
||||||
*/
|
*/
|
||||||
func TranslateToFFFE3(pSrc []uint8, SrcLen uint16) ([]byte, uint16) {
|
func parseIdFrame(frame byte, data []byte) BtmVobcIdCommand {
|
||||||
var (
|
buf := bytes.NewBuffer(data)
|
||||||
SrcPos, TgtPos, Pos1, Pos2, iii uint16
|
dataLen, _ := buf.ReadByte()
|
||||||
Gap uint16
|
dsn, _ := buf.ReadByte()
|
||||||
Got1stFF uint8
|
var btmId uint16
|
||||||
pTgt []uint8
|
var vobcId uint16
|
||||||
)
|
var vobcLifeId uint32
|
||||||
|
var yuliu [5]byte
|
||||||
if pSrc == nil {
|
var crc32 uint32
|
||||||
fmt.Println("入口参数错误")
|
binary.Read(buf, binary.BigEndian, &btmId)
|
||||||
return nil, 0
|
binary.Read(buf, binary.BigEndian, &vobcId)
|
||||||
}
|
binary.Read(buf, binary.BigEndian, &vobcLifeId)
|
||||||
|
binary.Read(buf, binary.BigEndian, &yuliu)
|
||||||
pTgt = make([]uint8, 0, SrcLen*2) // 预分配足够的空间以避免频繁扩容
|
binary.Read(buf, binary.BigEndian, &crc32)
|
||||||
TgtPos = 0
|
return BtmVobcIdCommand{BaseBtmVobc: BaseBtmVobc{Frame: frame, FrameLen: dataLen, AutoIdFrame: dsn, Crc32: crc32}}
|
||||||
|
|
||||||
for SrcPos = 0; SrcPos < SrcLen; SrcPos++ {
|
|
||||||
if Got1stFF == 1 {
|
|
||||||
if pSrc[SrcPos] == 0xFF {
|
|
||||||
// 已遇到前一个FF,且当前又遇到FF
|
|
||||||
//Got2ndFF = 1
|
|
||||||
Pos2 = SrcPos
|
|
||||||
pTgt = append(pTgt, uint8(Pos2-Pos1-1))
|
|
||||||
TgtPos++
|
|
||||||
|
|
||||||
for iii = Pos1 + 1; iii < Pos2; iii++ {
|
|
||||||
pTgt = append(pTgt, pSrc[iii])
|
|
||||||
TgtPos++
|
|
||||||
}
|
|
||||||
|
|
||||||
Got1stFF = 0
|
|
||||||
//Got2ndFF = 0
|
|
||||||
Pos1 = 0
|
|
||||||
Pos2 = 0
|
|
||||||
Gap = 0
|
|
||||||
} else {
|
|
||||||
// 已遇到前一个FF,且当前遇到非FF
|
|
||||||
Gap++
|
|
||||||
if Gap == 252 {
|
|
||||||
Got1stFF = 0
|
|
||||||
Gap = 0
|
|
||||||
pTgt = append(pTgt, 0)
|
|
||||||
TgtPos++
|
|
||||||
|
|
||||||
for iii = Pos1 + 1; iii <= SrcPos; iii++ {
|
|
||||||
pTgt = append(pTgt, pSrc[iii])
|
|
||||||
TgtPos++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 尚未遇到前一个FF
|
|
||||||
pTgt = append(pTgt, pSrc[SrcPos])
|
|
||||||
TgtPos++
|
|
||||||
if pSrc[SrcPos] == 0xFF {
|
|
||||||
// 遇到前一个FF
|
|
||||||
Got1stFF = 1
|
|
||||||
Pos1 = SrcPos
|
|
||||||
Gap = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 已经遇到了前一个FF, 且源数据已到了末尾仍未遇到后一个FF
|
|
||||||
if Got1stFF == 1 {
|
|
||||||
pTgt = append(pTgt, 0)
|
|
||||||
TgtPos++
|
|
||||||
|
|
||||||
for iii = Pos1 + 1; iii < SrcLen; iii++ {
|
|
||||||
pTgt = append(pTgt, pSrc[iii])
|
|
||||||
TgtPos++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pTgt, TgtPos
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type BaseBtmVobc struct {
|
type BaseBtmVobc struct {
|
||||||
@ -457,67 +149,6 @@ func baseEncode(source []byte) []byte {
|
|||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
/*func TranslateToFFFE4(pSrc []byte, pTgt []byte) (int, error) {
|
|
||||||
if pSrc == nil || pTgt == nil {
|
|
||||||
return 0, fmt.Errorf("pSrc or pTgt is nil")
|
|
||||||
}
|
|
||||||
|
|
||||||
srcLen := len(pSrc)
|
|
||||||
tgtLen := 0
|
|
||||||
pos1 := -1 // 前一个FF的位置
|
|
||||||
gap := 0 // 两个FF之间的字节数
|
|
||||||
|
|
||||||
for i, b := range pSrc {
|
|
||||||
if pos1 != -1 {
|
|
||||||
if b == 0xFF {
|
|
||||||
// 遇到了第二个FF
|
|
||||||
pTgt[tgtLen] = byte(i - pos1 - 1) // 减1是因为不包括第一个FF
|
|
||||||
tgtLen++
|
|
||||||
|
|
||||||
// 复制pos1和当前位置之间的数据
|
|
||||||
copy(pTgt[tgtLen:tgtLen+gap], pSrc[pos1+1:i])
|
|
||||||
tgtLen += gap
|
|
||||||
|
|
||||||
// 重置状态
|
|
||||||
pos1 = -1
|
|
||||||
gap = 0
|
|
||||||
} else {
|
|
||||||
// 计数两个FF之间的字节数
|
|
||||||
gap++
|
|
||||||
if gap == 252 {
|
|
||||||
// 如果gap超过252,则写入一个0并复制数据
|
|
||||||
pTgt[tgtLen] = 0
|
|
||||||
tgtLen++
|
|
||||||
copy(pTgt[tgtLen:tgtLen+gap], pSrc[pos1+1:i])
|
|
||||||
tgtLen += gap
|
|
||||||
// 重置状态
|
|
||||||
pos1 = -1
|
|
||||||
gap = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 尚未遇到前一个FF
|
|
||||||
pTgt[tgtLen] = b
|
|
||||||
tgtLen++
|
|
||||||
if b == 0xFF {
|
|
||||||
// 遇到了第一个FF
|
|
||||||
pos1 = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果数据以FF结尾,但没有第二个FF
|
|
||||||
if pos1 != -1 {
|
|
||||||
pTgt[tgtLen] = 0
|
|
||||||
tgtLen++
|
|
||||||
// 复制pos1之后的数据
|
|
||||||
copy(pTgt[tgtLen:tgtLen+srcLen-pos1-1], pSrc[pos1+1:])
|
|
||||||
tgtLen += srcLen - pos1 - 1
|
|
||||||
}
|
|
||||||
|
|
||||||
return tgtLen, nil
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// ID 命令帧的正文
|
// ID 命令帧的正文
|
||||||
type BtmVobcIdCommand struct {
|
type BtmVobcIdCommand struct {
|
||||||
BaseBtmVobc
|
BaseBtmVobc
|
||||||
@ -546,9 +177,10 @@ const (
|
|||||||
REQ_FRAME_STATUS_OK = 0x06
|
REQ_FRAME_STATUS_OK = 0x06
|
||||||
REQ_FRAME_STATUS_ERROR = 0x15
|
REQ_FRAME_STATUS_ERROR = 0x15
|
||||||
REQ_FRAME_STATUS_BOOT = 0x00
|
REQ_FRAME_STATUS_BOOT = 0x00
|
||||||
REQ_PACKETS_TYPE_FREE = 0x05
|
|
||||||
REQ_PACKETS_TYPE_MSG = 0x0A
|
REQ_PACKETS_TYPE_FREE = 0x05
|
||||||
REQ_PACKETS_TYPE_BOOT = 0x00
|
REQ_PACKETS_TYPE_MSG = 0x0A
|
||||||
|
REQ_PACKETS_TYPE_BOOT = 0x00
|
||||||
)
|
)
|
||||||
|
|
||||||
// 请求帧的正文
|
// 请求帧的正文
|
||||||
@ -564,11 +196,6 @@ type BtmVobcReq struct {
|
|||||||
VobcLifeWalkDistance uint16 //VOBC 周期走行距离 单位:cm
|
VobcLifeWalkDistance uint16 //VOBC 周期走行距离 单位:cm
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
a = 0x06
|
|
||||||
b = 0x15
|
|
||||||
)
|
|
||||||
|
|
||||||
func (b *BtmVobcReq) Decode(data []byte) {
|
func (b *BtmVobcReq) Decode(data []byte) {
|
||||||
base, buf := baseDecode(data)
|
base, buf := baseDecode(data)
|
||||||
|
|
||||||
@ -594,34 +221,8 @@ func (b *BtmVobcReq) Decode(data []byte) {
|
|||||||
b.VobcLifeWalkDistance = walkDis
|
b.VobcLifeWalkDistance = walkDis
|
||||||
}
|
}
|
||||||
|
|
||||||
var MESSAGE_AUTO_ID byte = 1
|
|
||||||
var MESSAGE_SERIAL byte = 1
|
|
||||||
var lock sync.Mutex
|
var lock sync.Mutex
|
||||||
|
|
||||||
func getAutoId() byte {
|
|
||||||
defer lock.Unlock()
|
|
||||||
lock.Lock()
|
|
||||||
if MESSAGE_AUTO_ID <= 0 {
|
|
||||||
MESSAGE_AUTO_ID = 1
|
|
||||||
} else if MESSAGE_AUTO_ID > 255 {
|
|
||||||
MESSAGE_AUTO_ID = 1
|
|
||||||
}
|
|
||||||
MESSAGE_AUTO_ID += 1
|
|
||||||
return MESSAGE_AUTO_ID
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetAutoMessageId() byte {
|
|
||||||
defer lock.Unlock()
|
|
||||||
lock.Lock()
|
|
||||||
if MESSAGE_SERIAL <= 0 {
|
|
||||||
MESSAGE_SERIAL = 1
|
|
||||||
} else if MESSAGE_SERIAL > 255 {
|
|
||||||
MESSAGE_SERIAL = 1
|
|
||||||
}
|
|
||||||
MESSAGE_SERIAL += 1
|
|
||||||
return MESSAGE_SERIAL
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
const (
|
||||||
btm_status_ok = 0x00
|
btm_status_ok = 0x00
|
||||||
btm_status_warn = 0x04
|
btm_status_warn = 0x04
|
||||||
@ -658,8 +259,9 @@ func (b *BtmVobcMessage) Encode() []byte {
|
|||||||
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(MESSAGE_TYPE))
|
binary.Write(buf, binary.BigEndian, byte(MESSAGE_TYPE))
|
||||||
binary.Write(buf, binary.BigEndian, byte(0x87))
|
binary.Write(buf, binary.BigEndian, byte(0x87))
|
||||||
|
|
||||||
//binary.Write(buf, binary.BigEndian, b.AutoIdFrame)
|
//binary.Write(buf, binary.BigEndian, b.AutoIdFrame)
|
||||||
binary.Write(buf, binary.BigEndian, getAutoId())
|
binary.Write(buf, binary.BigEndian, b.AutoIdFrame)
|
||||||
binary.Write(buf, binary.BigEndian, b.FontTtl)
|
binary.Write(buf, binary.BigEndian, b.FontTtl)
|
||||||
binary.Write(buf, binary.BigEndian, b.MsgSerial)
|
binary.Write(buf, binary.BigEndian, b.MsgSerial)
|
||||||
binary.Write(buf, binary.BigEndian, b.BtmStatus)
|
binary.Write(buf, binary.BigEndian, b.BtmStatus)
|
||||||
@ -724,8 +326,8 @@ func (b *BtmVobcMsgFree) Encode() []byte {
|
|||||||
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(FREE_MESSAGE_TYPE))
|
binary.Write(buf, binary.BigEndian, byte(FREE_MESSAGE_TYPE))
|
||||||
binary.Write(buf, binary.BigEndian, byte(0x87))
|
binary.Write(buf, binary.BigEndian, byte(0x87))
|
||||||
binary.Write(buf, binary.BigEndian, getAutoId())
|
|
||||||
//binary.Write(buf, binary.BigEndian, b.AutoIdFrame)
|
binary.Write(buf, binary.BigEndian, b.AutoIdFrame)
|
||||||
binary.Write(buf, binary.BigEndian, byte(0)) //保留
|
binary.Write(buf, binary.BigEndian, byte(0)) //保留
|
||||||
binary.Write(buf, binary.BigEndian, byte(0)) //保留
|
binary.Write(buf, binary.BigEndian, byte(0)) //保留
|
||||||
binary.Write(buf, binary.BigEndian, b.MsgSerial)
|
binary.Write(buf, binary.BigEndian, b.MsgSerial)
|
||||||
|
283
third_party/message/btm_vobc_translate_fffe.go
vendored
Normal file
283
third_party/message/btm_vobc_translate_fffe.go
vendored
Normal file
@ -0,0 +1,283 @@
|
|||||||
|
package message
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
|
func aa(src []byte, dest []byte) uint16 {
|
||||||
|
var (
|
||||||
|
SrcPos, TgtPos, Pos1, Pos2, iii, Gap uint16
|
||||||
|
Got1stFF uint8
|
||||||
|
)
|
||||||
|
srouceLen := uint16(len(src))
|
||||||
|
for SrcPos = 0; SrcPos < srouceLen; SrcPos++ {
|
||||||
|
if Got1stFF == 1 {
|
||||||
|
if src[SrcPos] == 0xff {
|
||||||
|
//Got2ndFF = 1
|
||||||
|
Pos2 = SrcPos
|
||||||
|
dest[TgtPos] = byte(Pos2 - Pos1)
|
||||||
|
TgtPos++
|
||||||
|
|
||||||
|
for iii = Pos1 + 1; iii < Pos2; iii++ {
|
||||||
|
dest[TgtPos] = src[iii]
|
||||||
|
TgtPos++
|
||||||
|
}
|
||||||
|
Got1stFF = 0
|
||||||
|
//Got2ndFF = 0
|
||||||
|
Pos1 = 0
|
||||||
|
Pos2 = 0
|
||||||
|
Gap = 0
|
||||||
|
} else {
|
||||||
|
/*已遇到前一个FF,且当前遇到非FF*/
|
||||||
|
Gap++
|
||||||
|
if 252 == Gap {
|
||||||
|
Got1stFF = 0
|
||||||
|
Gap = 0
|
||||||
|
dest[TgtPos] = 0
|
||||||
|
TgtPos++
|
||||||
|
for iii = Pos1 + 1; iii <= SrcPos; iii++ {
|
||||||
|
dest[TgtPos] = src[iii]
|
||||||
|
TgtPos++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/*尚未遇到前一个FF*/
|
||||||
|
dest[TgtPos] = src[SrcPos]
|
||||||
|
TgtPos++
|
||||||
|
if 0xFF == src[SrcPos] {
|
||||||
|
/*遇到前一个FF*/
|
||||||
|
Got1stFF = 1
|
||||||
|
Pos1 = SrcPos
|
||||||
|
Gap = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if 1 == Got1stFF {
|
||||||
|
dest[TgtPos] = 0
|
||||||
|
TgtPos++
|
||||||
|
for iii = Pos1 + 1; iii < srouceLen; iii++ {
|
||||||
|
dest[TgtPos] = src[iii]
|
||||||
|
TgtPos++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TgtPos
|
||||||
|
}
|
||||||
|
|
||||||
|
func TranslateFromFFFE(pSrc []byte) ([]byte, uint16) {
|
||||||
|
var (
|
||||||
|
srcPos, tgtPos, nonFFCount, nextFFPos uint16
|
||||||
|
char uint8
|
||||||
|
state int
|
||||||
|
)
|
||||||
|
|
||||||
|
if len(pSrc) == 0 {
|
||||||
|
return nil, 0 // 入参错误
|
||||||
|
}
|
||||||
|
|
||||||
|
pTgt := make([]byte, len(pSrc)) // 预分配与输入等长的缓冲区
|
||||||
|
tgtPos = 0
|
||||||
|
state = WAIT_FF_C1
|
||||||
|
nonFFCount = 0
|
||||||
|
|
||||||
|
for srcPos = 0; srcPos < uint16(len(pSrc)); srcPos++ {
|
||||||
|
char = pSrc[srcPos]
|
||||||
|
switch state {
|
||||||
|
case WAIT_FF_C1:
|
||||||
|
if char == 0xFF {
|
||||||
|
pTgt[tgtPos] = char
|
||||||
|
tgtPos++
|
||||||
|
state = WAIT_FF_C2
|
||||||
|
} else {
|
||||||
|
pTgt[tgtPos] = char
|
||||||
|
tgtPos++
|
||||||
|
}
|
||||||
|
case WAIT_FF_C2:
|
||||||
|
if char == 0xFD || char == 0xFE || char == 0xFF {
|
||||||
|
state = ABNORMAL_STATE
|
||||||
|
} else {
|
||||||
|
if char == 0 {
|
||||||
|
state = WAIT_NO_FF
|
||||||
|
} else if char == 1 {
|
||||||
|
pTgt[tgtPos] = 0xFF
|
||||||
|
tgtPos++
|
||||||
|
state = WAIT_FF_C1
|
||||||
|
} else {
|
||||||
|
nextFFPos = srcPos + uint16(char) - 1
|
||||||
|
state = WAIT_FF_POS
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case WAIT_NO_FF:
|
||||||
|
nonFFCount++
|
||||||
|
if char == 0xFF && nonFFCount < 252 {
|
||||||
|
state = ABNORMAL_STATE
|
||||||
|
} else {
|
||||||
|
pTgt[tgtPos] = char
|
||||||
|
tgtPos++
|
||||||
|
if nonFFCount == 252 {
|
||||||
|
nonFFCount = 0
|
||||||
|
state = WAIT_FF_C1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case WAIT_FF_POS:
|
||||||
|
if char == 0xFF {
|
||||||
|
state = ABNORMAL_STATE
|
||||||
|
} else {
|
||||||
|
pTgt[tgtPos] = char
|
||||||
|
tgtPos++
|
||||||
|
if srcPos == nextFFPos {
|
||||||
|
pTgt[tgtPos] = 0xFF
|
||||||
|
tgtPos++
|
||||||
|
state = WAIT_FF_C1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
state = ABNORMAL_STATE
|
||||||
|
}
|
||||||
|
|
||||||
|
if state == ABNORMAL_STATE {
|
||||||
|
tgtPos = 0
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 退出时的状态判断
|
||||||
|
if state == WAIT_FF_C2 || state == WAIT_FF_POS {
|
||||||
|
tgtPos = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
return pTgt[:tgtPos], tgtPos
|
||||||
|
}
|
||||||
|
|
||||||
|
// TranslateToFFFE 对给定的字节切片进行FFFE转义处理
|
||||||
|
func TranslateToFFFE(src []byte) ([]byte, error) {
|
||||||
|
if src == nil {
|
||||||
|
return nil, fmt.Errorf("source data is nil")
|
||||||
|
}
|
||||||
|
var tgt []byte
|
||||||
|
var pos1, pos2 int
|
||||||
|
var gap int
|
||||||
|
var got1stFF bool
|
||||||
|
|
||||||
|
for i, b := range src {
|
||||||
|
if got1stFF {
|
||||||
|
if b == 0xFF {
|
||||||
|
// 已遇到前一个FF,且当前又遇到FF
|
||||||
|
got1stFF = false
|
||||||
|
pos2 = i
|
||||||
|
if gap > 252 {
|
||||||
|
// 间隙过大,特殊处理
|
||||||
|
tgt = append(tgt, 0)
|
||||||
|
tgt = append(tgt, src[pos1+1:pos2]...)
|
||||||
|
} else {
|
||||||
|
// 写入间隙长度
|
||||||
|
tgt = append(tgt, byte(gap))
|
||||||
|
// 写入间隙中的字节
|
||||||
|
tgt = append(tgt, src[pos1+1:pos2]...)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 已遇到前一个FF,且当前遇到非FF,增加gap计数
|
||||||
|
gap++
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 尚未遇到前一个FF
|
||||||
|
tgt = append(tgt, b)
|
||||||
|
if b == 0xFF {
|
||||||
|
// 遇到前一个FF
|
||||||
|
got1stFF = true
|
||||||
|
pos1 = i
|
||||||
|
gap = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果在数据末尾遇到了FF且没有第二个FF
|
||||||
|
if got1stFF {
|
||||||
|
if gap > 252 {
|
||||||
|
tgt = append(tgt, 0)
|
||||||
|
tgt = append(tgt, src[pos1+1:]...)
|
||||||
|
} else {
|
||||||
|
tgt = append(tgt, 0)
|
||||||
|
tgt = append(tgt, src[pos1+1:len(src)]...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return tgt, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func TranslateToFFFE3(pSrc []uint8, SrcLen uint16) ([]byte, uint16) {
|
||||||
|
var (
|
||||||
|
SrcPos, TgtPos, Pos1, Pos2, iii uint16
|
||||||
|
Gap uint16
|
||||||
|
Got1stFF uint8
|
||||||
|
pTgt []uint8
|
||||||
|
)
|
||||||
|
|
||||||
|
if pSrc == nil {
|
||||||
|
fmt.Println("入口参数错误")
|
||||||
|
return nil, 0
|
||||||
|
}
|
||||||
|
|
||||||
|
pTgt = make([]uint8, 0, SrcLen*2) // 预分配足够的空间以避免频繁扩容
|
||||||
|
TgtPos = 0
|
||||||
|
|
||||||
|
for SrcPos = 0; SrcPos < SrcLen; SrcPos++ {
|
||||||
|
if Got1stFF == 1 {
|
||||||
|
if pSrc[SrcPos] == 0xFF {
|
||||||
|
// 已遇到前一个FF,且当前又遇到FF
|
||||||
|
//Got2ndFF = 1
|
||||||
|
Pos2 = SrcPos
|
||||||
|
pTgt = append(pTgt, uint8(Pos2-Pos1-1))
|
||||||
|
TgtPos++
|
||||||
|
|
||||||
|
for iii = Pos1 + 1; iii < Pos2; iii++ {
|
||||||
|
pTgt = append(pTgt, pSrc[iii])
|
||||||
|
TgtPos++
|
||||||
|
}
|
||||||
|
|
||||||
|
Got1stFF = 0
|
||||||
|
//Got2ndFF = 0
|
||||||
|
Pos1 = 0
|
||||||
|
Pos2 = 0
|
||||||
|
Gap = 0
|
||||||
|
} else {
|
||||||
|
// 已遇到前一个FF,且当前遇到非FF
|
||||||
|
Gap++
|
||||||
|
if Gap == 252 {
|
||||||
|
Got1stFF = 0
|
||||||
|
Gap = 0
|
||||||
|
pTgt = append(pTgt, 0)
|
||||||
|
TgtPos++
|
||||||
|
|
||||||
|
for iii = Pos1 + 1; iii <= SrcPos; iii++ {
|
||||||
|
pTgt = append(pTgt, pSrc[iii])
|
||||||
|
TgtPos++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 尚未遇到前一个FF
|
||||||
|
pTgt = append(pTgt, pSrc[SrcPos])
|
||||||
|
TgtPos++
|
||||||
|
if pSrc[SrcPos] == 0xFF {
|
||||||
|
// 遇到前一个FF
|
||||||
|
Got1stFF = 1
|
||||||
|
Pos1 = SrcPos
|
||||||
|
Gap = 0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已经遇到了前一个FF, 且源数据已到了末尾仍未遇到后一个FF
|
||||||
|
if Got1stFF == 1 {
|
||||||
|
pTgt = append(pTgt, 0)
|
||||||
|
TgtPos++
|
||||||
|
|
||||||
|
for iii = Pos1 + 1; iii < SrcLen; iii++ {
|
||||||
|
pTgt = append(pTgt, pSrc[iii])
|
||||||
|
TgtPos++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pTgt, TgtPos
|
||||||
|
}
|
5
third_party/message/train_pc_sim_message.go
vendored
5
third_party/message/train_pc_sim_message.go
vendored
@ -122,7 +122,7 @@ func AtpLowPowerByte(d byte) bool {
|
|||||||
// 列车速度位置报告
|
// 列车速度位置报告
|
||||||
type TrainSpeedPlaceReportMsg struct {
|
type TrainSpeedPlaceReportMsg struct {
|
||||||
PulseCount1 float32
|
PulseCount1 float32
|
||||||
PulseCount2 float32
|
//PulseCount2 float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir uint16, s1, runRange uint32) []byte {
|
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir uint16, s1, runRange uint32) []byte {
|
||||||
@ -255,4 +255,7 @@ const (
|
|||||||
DOOR_MODE_MM
|
DOOR_MODE_MM
|
||||||
_
|
_
|
||||||
NOT_BREAK
|
NOT_BREAK
|
||||||
|
//aa = 0x2e
|
||||||
|
//bb = 0x2f
|
||||||
|
cc = 0x2d
|
||||||
)
|
)
|
||||||
|
270
third_party/semi_physical_train/btm_vobc.go
vendored
Normal file
270
third_party/semi_physical_train/btm_vobc.go
vendored
Normal file
@ -0,0 +1,270 @@
|
|||||||
|
package semi_physical_train
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/const/balise_const"
|
||||||
|
"joylink.club/bj-rtsts-server/dto/state_proto"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/can_btm"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
|
"log/slog"
|
||||||
|
"math"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BtmVobcManage interface {
|
||||||
|
GetBtmVobcConfig() config.BtmVobcConfig
|
||||||
|
|
||||||
|
GetAllTrain() []*state_proto.TrainState
|
||||||
|
GetConnVobcTrain() *state_proto.TrainState
|
||||||
|
}
|
||||||
|
type BtmVobcService interface {
|
||||||
|
Start(btmVobcManage BtmVobcManage)
|
||||||
|
Stop()
|
||||||
|
SendData(data []byte)
|
||||||
|
}
|
||||||
|
type BtmVobcClient struct {
|
||||||
|
calFun context.CancelFunc
|
||||||
|
client udp.UdpClient
|
||||||
|
server udp.UdpServer
|
||||||
|
manage BtmVobcManage
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
btmVobcLocker sync.Mutex
|
||||||
|
btmVobcClient *BtmVobcClient
|
||||||
|
btmVobcBaliseLocker sync.Mutex
|
||||||
|
//最新接受数据时间
|
||||||
|
reviceTimeStamp int64
|
||||||
|
)
|
||||||
|
|
||||||
|
func BtmDefault() BtmVobcService {
|
||||||
|
defer btmVobcLocker.Unlock()
|
||||||
|
btmVobcLocker.Lock()
|
||||||
|
if btmVobcClient == nil {
|
||||||
|
btmVobcClient = &BtmVobcClient{}
|
||||||
|
}
|
||||||
|
return btmVobcClient
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BtmVobcClient) Start(btmVobcManage BtmVobcManage) {
|
||||||
|
cfg := btmVobcManage.GetBtmVobcConfig()
|
||||||
|
if !cfg.Open {
|
||||||
|
slog.Info("11号线 btm vobc配置未开启...")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
udpServer := udp.NewServer(fmt.Sprintf("%v:%d", cfg.LocalUdpIp, cfg.LocalUdpPort), b.handleBtmVobcFrames)
|
||||||
|
err := udpServer.Listen()
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("11号线 btm VOBC 服务启动失败...")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//
|
||||||
|
udpClient := udp.NewClient(fmt.Sprintf("%s:%d", cfg.RemoteIp, cfg.RemoteUdpPort))
|
||||||
|
b.manage = btmVobcManage
|
||||||
|
b.server = udpServer
|
||||||
|
b.client = udpClient
|
||||||
|
reviceTimeStamp = time.Now().UnixMilli()
|
||||||
|
_, calFun := context.WithCancel(context.Background())
|
||||||
|
b.calFun = calFun
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BtmVobcClient) vobcBtmQueryHandle(data []byte) {
|
||||||
|
train := b.manage.GetConnVobcTrain()
|
||||||
|
if train == nil {
|
||||||
|
slog.Error("vobc btm 未找到VOBC连接的列车...")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
requestId := uuid.New().String()
|
||||||
|
frameType, dataText, err := message.BtmVobcDecode(data)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error(fmt.Sprintf("%v,请求id:%v", err, requestId))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
receiveDataTime := time.Now().UnixMilli()
|
||||||
|
if frameType == message.COMMAND_TYPE {
|
||||||
|
idCommand := &message.BtmVobcIdCommand{}
|
||||||
|
idCommand.Decode(dataText)
|
||||||
|
slog.Info(fmt.Sprintf("成功接受btm vobc的id命令帧,requestId:%v,接受时间:%v", requestId, receiveDataTime))
|
||||||
|
if train.VobcState.VobcBtmInfo == nil {
|
||||||
|
train.VobcState.VobcBtmInfo = &state_proto.TrainVobcState_VobcBtmInfo{BtmId: uint32(idCommand.BtmId), VobcId: uint32(idCommand.VobcId), VobcLifeId: idCommand.VobcLifeNum}
|
||||||
|
}
|
||||||
|
} else if train.VobcState.VobcBtmInfo != nil && frameType == message.REQUEST_TYPE {
|
||||||
|
slog.Info(fmt.Sprintf("成功接受btm vobc的请求帧,requestId:%v,接受时间(微秒):%v", requestId, receiveDataTime))
|
||||||
|
req := &message.BtmVobcReq{}
|
||||||
|
req.Decode(dataText)
|
||||||
|
b.requestFramePackets(requestId, req, train, receiveDataTime)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
//slog.Error(fmt.Sprintf("btm vobc 解析未知命令帧类型:0x%v,原始数据:%v,长度:%v,requestId:%v", strconv.FormatInt(int64(frameType), 16), hex.EncodeToString(cfs), len(cfs), requestId))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BtmVobcClient) handleBtmVobcFrames(cfs []byte) {
|
||||||
|
/* reviceTimeStamp = time.Now().UnixMilli()
|
||||||
|
train := b.manage.GetConnVobcTrain()
|
||||||
|
if train == nil {
|
||||||
|
//slog.Error("vobc btm 未找到VOBC连接的列车...")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
requestId := uuid.New().String()
|
||||||
|
slog.Info(fmt.Sprintf("获取到vobc btm原始数据:%v, requestId:%v", hex.EncodeToString(cfs), requestId))
|
||||||
|
frameType, dataText, err := message.BtmVobcDecode(cfs)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error(fmt.Sprintf("%v,请求id:%v", err, requestId))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
receiveDataTime := time.Now().UnixMicro()
|
||||||
|
decodePayMicoTime := (receiveDataTime - receiveDataTime) / 100
|
||||||
|
if frameType == message.COMMAND_TYPE {
|
||||||
|
idCommand := &message.BtmVobcIdCommand{}
|
||||||
|
idCommand.Decode(dataText)
|
||||||
|
slog.Info(fmt.Sprintf("成功接受btm vobc的id命令帧,requestId:%v,接受时间(微秒):%v", requestId, receiveDataTime))
|
||||||
|
b.packets(requestId, idCommand.VobcLifeNum, idCommand.AutoIdFrame, receiveDataTime, decodePayMicoTime, train.VobcBtm)
|
||||||
|
} else if frameType == message.REQUEST_TYPE {
|
||||||
|
slog.Info(fmt.Sprintf("成功接受btm vobc的请求帧,requestId:%v,接受时间(微秒):%v", requestId, receiveDataTime))
|
||||||
|
req := &message.BtmVobcReq{}
|
||||||
|
req.Decode(dataText)
|
||||||
|
b.RequestFramePackets(req.VobcLifeNum, req.AutoIdFrame, requestId, receiveDataTime, decodePayMicoTime, req, train.VobcBtm)
|
||||||
|
} else {
|
||||||
|
slog.Error(fmt.Sprintf("btm vobc 解析未知命令帧类型:0x%v,原始数据:%v,长度:%v,requestId:%v", strconv.FormatInt(int64(frameType), 16), hex.EncodeToString(cfs), len(cfs), requestId))
|
||||||
|
return
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
func createFreeBalisePacketString() string {
|
||||||
|
return strings.Repeat("00", balise_const.UserTelegramByteLen)
|
||||||
|
}
|
||||||
|
func createFreeBalisePackets() []byte {
|
||||||
|
str := createFreeBalisePacketString()
|
||||||
|
d, _ := hex.DecodeString(str)
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
// 请求帧
|
||||||
|
func (b *BtmVobcClient) requestFramePackets(requestId string, req *message.BtmVobcReq, train *state_proto.TrainState, receiveTime int64) {
|
||||||
|
|
||||||
|
if req.FrameStatus == message.REQ_FRAME_STATUS_BOOT && req.MessageType == message.REQ_PACKETS_TYPE_BOOT {
|
||||||
|
//vobc 上电,清空应答器
|
||||||
|
can_btm.ClearBalise(train)
|
||||||
|
} else {
|
||||||
|
var (
|
||||||
|
btmState *state_proto.BTMState
|
||||||
|
dsn byte
|
||||||
|
matcher bool
|
||||||
|
)
|
||||||
|
ms := req.MessageSerial
|
||||||
|
|
||||||
|
if req.FrameStatus == message.REQ_FRAME_STATUS_ERROR {
|
||||||
|
//抢答器错误,重新发送
|
||||||
|
btmState, dsn, _, _ = can_btm.FindBaliseResend(train.BtmBaliseCacheA, false)
|
||||||
|
} else {
|
||||||
|
//判断 报文序列号与之前发送的 是否一致,不一致
|
||||||
|
//如果一致返回新的应答器,如果不一致返回之前发送的应答器,如果不一致并且没有找到之前发送的应答器,则返回新应答器
|
||||||
|
btmState, dsn, matcher = can_btm.FindBaliseByMessageSerial(train.BtmBaliseCacheA, false, req.MessageSerial)
|
||||||
|
if matcher {
|
||||||
|
if btmState != nil {
|
||||||
|
//正常应答
|
||||||
|
btmState.IsSend = true
|
||||||
|
ms = req.MessageSerial + 1
|
||||||
|
if ms > 255 {
|
||||||
|
ms = 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//vobc 未收到应答器,重新发送
|
||||||
|
}
|
||||||
|
}
|
||||||
|
b.packets(requestId, btmState, ms, dsn, req.VobcLifeNum, receiveTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 有应答器报文
|
||||||
|
func (b *BtmVobcClient) balisePackets(telegram, requestId string, messageSerial, dsn byte, vobcLifeNum uint32, receiveTime int64) {
|
||||||
|
|
||||||
|
data, e := hex.DecodeString(telegram)
|
||||||
|
if e != nil {
|
||||||
|
slog.Error(fmt.Sprintf("解析应答器报文失败应答器报文长度:%v", telegram), e)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//前沿时间
|
||||||
|
var fttl uint16 = 0
|
||||||
|
tmpFttl := int64(math.Abs(float64(time.Now().UnixMilli() - receiveTime)))
|
||||||
|
if tmpFttl >= 0xffff {
|
||||||
|
fttl = 0xffff
|
||||||
|
} else {
|
||||||
|
fttl = uint16(tmpFttl)
|
||||||
|
}
|
||||||
|
|
||||||
|
var bttl uint16 = 0
|
||||||
|
tmpBttl := int64(math.Abs(float64(time.Now().UnixMilli() - receiveTime)))
|
||||||
|
if tmpBttl >= 0xffff {
|
||||||
|
bttl = 0xffff
|
||||||
|
} else {
|
||||||
|
bttl = uint16(tmpBttl)
|
||||||
|
}
|
||||||
|
repTimeMicro := (time.Now().UnixMilli() - receiveTime) / 10
|
||||||
|
baliseMsg := &message.BtmVobcMessage{FontTtl: fttl, BtmStatus: message.BTM_STSTUS_NORMAL, DecodeTime: uint16(repTimeMicro),
|
||||||
|
BackTtl: bttl, ResponseTime: byte(repTimeMicro), MsgSerial: messageSerial, BtmMsg: data,
|
||||||
|
VobcLifeNum: vobcLifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: dsn}}
|
||||||
|
baliseData := baliseMsg.Encode()
|
||||||
|
slog.Info(fmt.Sprintf("发送btm vobc 报文数据 报文序列id:%v 报文内容:%X 长度:%v ,requestId:%v", messageSerial, baliseData, len(baliseData), requestId))
|
||||||
|
err := b.client.Send(baliseData)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error(fmt.Sprintf("发送btm vobc 报文数据 报文序列id:%v 报文内容:%X 长度:%v ,requestId:%v", messageSerial, baliseData, len(baliseData), requestId), err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// 无应答器报文
|
||||||
|
func (b *BtmVobcClient) balisePacketsFree(requestId string, receiveTime int64, vobcLifeNum uint32, autoCommandId, messageSerial byte) {
|
||||||
|
repTimeMicro := (time.Now().UnixMicro() - receiveTime) / 10
|
||||||
|
freeMsg := &message.BtmVobcMsgFree{BtmStatus: message.BTM_STSTUS_NORMAL, Fun1: 0xffff, Fun2: 0x00CF, Fun3: uint16(0), Fun4: uint16(0),
|
||||||
|
FreeMsg: createFreeBalisePackets(), RespTime: byte(repTimeMicro), MsgSerial: messageSerial, VobcLifeNum: vobcLifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: autoCommandId}}
|
||||||
|
freeData := freeMsg.Encode()
|
||||||
|
logStr := fmt.Sprintf("发送btm vobc 报文序列id:%v 空闲帧报文:%X 长度:%v ,requestId:%v", messageSerial, freeData, len(freeData), requestId)
|
||||||
|
slog.Info(logStr)
|
||||||
|
err := b.client.Send(freeData)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error(logStr, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 应答器报文或空报文
|
||||||
|
func (b *BtmVobcClient) packets(requestId string, btmState *state_proto.BTMState, messageSerial, dsn byte, vobcLifeNum uint32, receiveTime int64) {
|
||||||
|
if btmState == nil {
|
||||||
|
b.balisePacketsFree(requestId, receiveTime, vobcLifeNum, dsn, messageSerial)
|
||||||
|
} else {
|
||||||
|
b.balisePackets(btmState.Telegram, requestId, messageSerial, dsn, vobcLifeNum, receiveTime)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *BtmVobcClient) SendData(data []byte) {
|
||||||
|
if b.client != nil {
|
||||||
|
slog.Info(fmt.Sprintf("发送btm vobc 报文:%v 长度:%v", hex.EncodeToString(data), len(data)))
|
||||||
|
err := b.client.Send(data)
|
||||||
|
if err != nil {
|
||||||
|
slog.Error("发送btm vobc 报文失败:", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func (b *BtmVobcClient) Stop() {
|
||||||
|
if b.server != nil {
|
||||||
|
b.calFun()
|
||||||
|
b.server.Close()
|
||||||
|
}
|
||||||
|
if b.client != nil {
|
||||||
|
b.client.Close()
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package btm_vobc
|
package semi_physical_train
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
@ -163,7 +163,7 @@ func TestDecode232(t *testing.T) {
|
|||||||
|
|
||||||
func TestDocode(t *testing.T) {
|
func TestDocode(t *testing.T) {
|
||||||
fmt.Println(time.Microsecond * 200)
|
fmt.Println(time.Microsecond * 200)
|
||||||
ss := "fffe9287d300056f006464000a000000000000000000000490007f8181b60b10183280003fff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff01ff000a00221eedf0be28e9fffd"
|
ss := "fffee601804f004d0032d8e1002a006aff0020fc60316e299122ea0000000000000000000000000000e1d83000000000000000000000768888cc4961fffd"
|
||||||
cfs, _ := hex.DecodeString(ss)
|
cfs, _ := hex.DecodeString(ss)
|
||||||
frameType, dataText, err := message.BtmVobcDecode(cfs)
|
frameType, dataText, err := message.BtmVobcDecode(cfs)
|
||||||
fmt.Println(frameType)
|
fmt.Println(frameType)
|
@ -1,4 +1,4 @@
|
|||||||
package btm_vobc
|
package semi_physical_train
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
4
third_party/tcp/tcp_client.go
vendored
4
third_party/tcp/tcp_client.go
vendored
@ -88,3 +88,7 @@ func (c *TcpClient) Send(data []byte) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *TcpClient) RemoteInfo() net.Addr {
|
||||||
|
return c.conn.RemoteAddr()
|
||||||
|
}
|
||||||
|
4
third_party/third_party.go
vendored
4
third_party/third_party.go
vendored
@ -46,7 +46,9 @@ func GetRunningServiceStates() *state_proto.SimulationThirdPartyApiService {
|
|||||||
trueServices := tpas.FindAppendApiService()
|
trueServices := tpas.FindAppendApiService()
|
||||||
if trueServices != nil && len(trueServices) > 0 {
|
if trueServices != nil && len(trueServices) > 0 {
|
||||||
for _, trueService := range trueServices {
|
for _, trueService := range trueServices {
|
||||||
collectServiceState(ss, trueService)
|
if trueService != nil {
|
||||||
|
collectServiceState(ss, trueService)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
package train_pc_sim
|
package train_pc_sim
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
"joylink.club/bj-rtsts-server/dto/state_proto"
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
"joylink.club/bj-rtsts-server/third_party/tcp"
|
"joylink.club/bj-rtsts-server/third_party/tcp"
|
||||||
@ -13,10 +14,24 @@ type TrainPcReciverData struct {
|
|||||||
clientKey string
|
clientKey string
|
||||||
tcpClient *tcp.TcpClient
|
tcpClient *tcp.TcpClient
|
||||||
pcSimManage TrainPcSimManage
|
pcSimManage TrainPcSimManage
|
||||||
//trainInit bool
|
state tpapi.ThirdPartyApiServiceState
|
||||||
state tpapi.ThirdPartyApiServiceState
|
speedPlace *message.TrainSpeedPlaceReportMsg
|
||||||
speedPlace *message.TrainSpeedPlaceReportMsg
|
train *state_proto.TrainState
|
||||||
train *state_proto.TrainState
|
success bool
|
||||||
|
//aPort bool //列车钥匙激活端口 true = 1端 ,false = 2端
|
||||||
|
RealTrainPort state_proto.TrainState_TrainPort
|
||||||
|
LineInitTimeStamp int64
|
||||||
|
TrainConnInitComplate bool
|
||||||
|
ConnErr bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (rd *TrainPcReciverData) ConnError() bool {
|
||||||
|
connState := tpapi.ThirdPartyState_Normal
|
||||||
|
if rd.ConnErr {
|
||||||
|
connState = tpapi.ThirdPartyState_Broken
|
||||||
|
}
|
||||||
|
rd.updateState(connState)
|
||||||
|
return rd.ConnErr
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rd *TrainPcReciverData) Name() string {
|
func (rd *TrainPcReciverData) Name() string {
|
||||||
@ -35,17 +50,22 @@ func (d *TrainPcReciverData) readError(err error) {
|
|||||||
slog.Error("连接车载pc仿真tcp服务断开", err)
|
slog.Error("连接车载pc仿真tcp服务断开", err)
|
||||||
d.updateState(tpapi.ThirdPartyState_Broken)
|
d.updateState(tpapi.ThirdPartyState_Broken)
|
||||||
d.tcpClient = nil
|
d.tcpClient = nil
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *TrainPcReciverData) ServiceDesc() string {
|
func (d *TrainPcReciverData) ServiceDesc() string {
|
||||||
return d.clientKey
|
if d.RealTrainPort == state_proto.TrainState_PORT_A {
|
||||||
|
return fmt.Sprintf("%v-A端", d.clientKey)
|
||||||
|
} else if d.RealTrainPort == state_proto.TrainState_PORT_B {
|
||||||
|
return fmt.Sprintf("%v-B端", d.clientKey)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%v-位置服务端口", d.clientKey)
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (rd *TrainPcReciverData) receiverDataHandle(n int, data []byte) {
|
func (rd *TrainPcReciverData) receiverDataHandle(n int, data []byte) {
|
||||||
|
|
||||||
receiveData := data[:n]
|
|
||||||
|
|
||||||
trainPcMsgs := message.TrainPcSimDecode(receiveData)
|
|
||||||
train := rd.train
|
train := rd.train
|
||||||
|
//vs := train.VobcState
|
||||||
if train == nil {
|
if train == nil {
|
||||||
slog.Error("车载输出数字量,未找到连接车载pc仿真的列车")
|
slog.Error("车载输出数字量,未找到连接车载pc仿真的列车")
|
||||||
return
|
return
|
||||||
@ -54,22 +74,25 @@ func (rd *TrainPcReciverData) receiverDataHandle(n int, data []byte) {
|
|||||||
slog.Error("车载输出数字量,,列车未连接车载pc仿真")
|
slog.Error("车载输出数字量,,列车未连接车载pc仿真")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//hexSourceData := hex.EncodeToString(receiveData)
|
//a := rd.tcpClient.RemoteInfo()
|
||||||
//slog.Info(fmt.Sprintf("接受列车激活端:%v pc仿真接收数据:%v", rd.clientKey, hexSourceData))
|
//slog.Info(fmt.Sprintf("nw:%v ,add:%v", a.Network(), a.String()), rd.aPort)
|
||||||
|
//slog.Info(fmt.Sprintf("接受atp信息 列车:%v 列车端口:%v ,钥匙1:%v,钥匙2:%v", train.Id, rd.aPort, train.VobcState.Tc1Active, train.VobcState.Tc2Active))
|
||||||
|
receiveData := data[:n]
|
||||||
|
trainPcMsgs := message.TrainPcSimDecode(receiveData)
|
||||||
|
|
||||||
for _, baseMsg := range trainPcMsgs {
|
for _, baseMsg := range trainPcMsgs {
|
||||||
//slog.Info(fmt.Sprintf("pc仿真接收数据:%v,类型:%X", hexSourceData, baseMsg.Type))
|
|
||||||
switch baseMsg.Type {
|
switch baseMsg.Type {
|
||||||
//case RECIVE_TRAIN_CREATE_REMOVE:
|
//case RECIVE_TRAIN_CREATE_REMOVE:
|
||||||
// pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(baseMsg.Data[0])
|
// pc.trainPcSimManage.TrainPcSimConnOrRemoveHandle(baseMsg.Data[0])
|
||||||
case message.RECIVE_TRAIN_INTERFACE_CABINET_OUTR:
|
case message.RECIVE_TRAIN_INTERFACE_CABINET_OUTR:
|
||||||
rd.pcSimManage.TrainPcSimDigitalOutInfoHandle(train, baseMsg.Data)
|
rd.pcSimManage.TrainPcSimDigitalOutInfoHandle(rd, train, baseMsg.Data)
|
||||||
|
|
||||||
case message.RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
|
case message.RECIVE_TRAIN_INTERFACE_CABINET_OUTR_BACK:
|
||||||
rd.pcSimManage.TrainPcSimDigitalReportHandle(train, baseMsg.Data)
|
rd.pcSimManage.TrainPcSimDigitalReportHandle(train, baseMsg.Data)
|
||||||
case message.RECIVE_TRAIN_QUERY_STATUS:
|
case message.RECIVE_TRAIN_QUERY_STATUS:
|
||||||
rd.pcSimManage.TrainBtmQuery2(train, baseMsg.Data)
|
rd.pcSimManage.TrainBtmQuery2(train, baseMsg.Data, rd.RealTrainPort)
|
||||||
case message.RECIVE_TRAIN_MOCK_DATA:
|
//case message.RECIVE_TRAIN_MOCK_DATA:
|
||||||
rd.pcSimManage.TrainPcSimMockInfo(train, baseMsg.Data)
|
// rd.pcSimManage.TrainPcSimMockInfo(train, baseMsg.Data)
|
||||||
|
|
||||||
//case RECIVE_TRAIN_DOOR_MODE:
|
//case RECIVE_TRAIN_DOOR_MODE:
|
||||||
// pc.trainPcSimManage.TrainDoorModeHandle(baseMsg.Data[0])
|
// pc.trainPcSimManage.TrainDoorModeHandle(baseMsg.Data[0])
|
||||||
|
393
third_party/train_pc_sim/train_pc_sim.go
vendored
393
third_party/train_pc_sim/train_pc_sim.go
vendored
@ -16,10 +16,10 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TrainControlEvent struct {
|
//type TrainControlEvent struct {
|
||||||
Type byte
|
// Type byte
|
||||||
Data []byte
|
// Data []byte
|
||||||
}
|
//}
|
||||||
|
|
||||||
//var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
|
//var FireTrainControlEventType = ecs.NewEventType[TrainControlEvent]()
|
||||||
|
|
||||||
@ -29,19 +29,20 @@ type TrainPcSim interface {
|
|||||||
Stop()
|
Stop()
|
||||||
|
|
||||||
// SendDriverActive Deprecated 发送驾驶端激活
|
// SendDriverActive Deprecated 发送驾驶端激活
|
||||||
SendDriverActive(train *state_proto.TrainState)
|
//SendDriverActive(train *state_proto.TrainState)
|
||||||
// SendHandleSwitch 发送牵引制动手柄
|
// SendHandleSwitch 发送牵引制动手柄
|
||||||
SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, train *state_proto.TrainState)
|
SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, train *state_proto.TrainState)
|
||||||
// SendTrainDirection 列车运行方向
|
// SendTrainDirection 列车运行方向
|
||||||
//因文档说明不清楚,在调用的时候目前是注释状态,现场调试可能会用到
|
//因文档说明不清楚,在调用的时候目前是注释状态,现场调试可能会用到
|
||||||
SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool)
|
SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool)
|
||||||
//发送应答器信息数据
|
//发送应答器信息数据
|
||||||
SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte)
|
|
||||||
|
SendBaliseData2(train *state_proto.TrainState, trainClientPort state_proto.TrainState_TrainPort, msgType byte, data []byte)
|
||||||
|
|
||||||
//发布列车控制的相关事件
|
//发布列车控制的相关事件
|
||||||
//PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent)
|
//PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent)
|
||||||
|
|
||||||
SendTrainControlMsg(train *state_proto.TrainState, baseMessage []message.TrainPcSimBaseMessage)
|
SendTrainControlMsg2(train *state_proto.TrainState, baseMessage []message.TrainPcSimBaseMessage, trainClientPort state_proto.TrainState_TrainPort)
|
||||||
// CreateOrRemoveSpeedPLace 创建或删除速度位置信息
|
// CreateOrRemoveSpeedPLace 创建或删除速度位置信息
|
||||||
//CreateOrRemoveSpeedPLace(train *state_proto.TrainState)
|
//CreateOrRemoveSpeedPLace(train *state_proto.TrainState)
|
||||||
// CreateOrRemoveTrain 创建或删除列车
|
// CreateOrRemoveTrain 创建或删除列车
|
||||||
@ -57,7 +58,7 @@ type TrainPcSimManage interface {
|
|||||||
//获取列车模拟量数据
|
//获取列车模拟量数据
|
||||||
ObtainTrainDigitalMockData(train *state_proto.TrainState) []message.TrainPcSimBaseMessage
|
ObtainTrainDigitalMockData(train *state_proto.TrainState) []message.TrainPcSimBaseMessage
|
||||||
// TrainPcSimDigitalOutInfoHandle 4.4.1. 车载输出数字量信息报文内容
|
// TrainPcSimDigitalOutInfoHandle 4.4.1. 车载输出数字量信息报文内容
|
||||||
TrainPcSimDigitalOutInfoHandle(train *state_proto.TrainState, data []byte)
|
TrainPcSimDigitalOutInfoHandle(pc *TrainPcReciverData, train *state_proto.TrainState, data []byte) bool
|
||||||
// TrainPcSimDigitalReportHandle 4.4.2. 车载输出数字反馈量信息报文内容
|
// TrainPcSimDigitalReportHandle 4.4.2. 车载输出数字反馈量信息报文内容
|
||||||
TrainPcSimDigitalReportHandle(train *state_proto.TrainState, data []byte)
|
TrainPcSimDigitalReportHandle(train *state_proto.TrainState, data []byte)
|
||||||
FindConnTrain(ct state_proto.TrainConnState_TrainConnType) *state_proto.TrainState
|
FindConnTrain(ct state_proto.TrainConnState_TrainConnType) *state_proto.TrainState
|
||||||
@ -67,15 +68,18 @@ type TrainPcSimManage interface {
|
|||||||
TrainPcSimMockInfo(train *state_proto.TrainState, data []byte)
|
TrainPcSimMockInfo(train *state_proto.TrainState, data []byte)
|
||||||
// TrainBtmQuery 处理列车btm查询
|
// TrainBtmQuery 处理列车btm查询
|
||||||
|
|
||||||
TrainBtmQuery2(train *state_proto.TrainState, data []byte)
|
TrainBtmQuery2(train *state_proto.TrainState, data []byte, trainClientPort state_proto.TrainState_TrainPort)
|
||||||
}
|
}
|
||||||
type trainPcSimService struct {
|
type trainPcSimService struct {
|
||||||
state tpapi.ThirdPartyApiServiceState
|
state tpapi.ThirdPartyApiServiceState
|
||||||
newPcSimclientMap map[string]*TrainPcReciverData
|
//newPcSimclientMap map[string]*TrainPcReciverData
|
||||||
cancleContextFun context.CancelFunc
|
|
||||||
context context.Context
|
newPcSimclientMap3 map[string][]*TrainPcReciverData
|
||||||
trainPcSimManage TrainPcSimManage
|
|
||||||
configs []config.VehiclePCSimConfig
|
cancleContextFun context.CancelFunc
|
||||||
|
context context.Context
|
||||||
|
trainPcSimManage TrainPcSimManage
|
||||||
|
configs []config.VehiclePCSimConfig
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -113,17 +117,41 @@ func (d *trainPcSimService) ServiceDesc() string {
|
|||||||
func FindTrainPcSimClientKey2(t *state_proto.TrainState) string {
|
func FindTrainPcSimClientKey2(t *state_proto.TrainState) string {
|
||||||
return t.ConnState.TypeName
|
return t.ConnState.TypeName
|
||||||
}
|
}
|
||||||
func (d *trainPcSimService) findTrainConn(sta *state_proto.TrainState) (*TrainPcReciverData, error) {
|
func (d *trainPcSimService) findTrainConnForPort2(sta *state_proto.TrainState, trainClientPort state_proto.TrainState_TrainPort) (*TrainPcReciverData, error) {
|
||||||
trainPcReciver := d.newPcSimclientMap[sta.ConnState.TypeName]
|
rds := d.newPcSimclientMap3[sta.ConnState.TypeName]
|
||||||
if trainPcReciver == nil {
|
if rds == nil {
|
||||||
return nil, fmt.Errorf("")
|
return nil, fmt.Errorf("")
|
||||||
}
|
}
|
||||||
return trainPcReciver, nil
|
for _, rd := range rds {
|
||||||
|
if rd.RealTrainPort == trainClientPort {
|
||||||
|
return rd, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *trainPcSimService) findTrainConn(sta *state_proto.TrainState) (*TrainPcReciverData, error) {
|
||||||
|
rds := d.newPcSimclientMap3[sta.ConnState.TypeName]
|
||||||
|
if rds == nil {
|
||||||
|
return nil, fmt.Errorf("")
|
||||||
|
}
|
||||||
|
if sta.VobcState.Tc1Active {
|
||||||
|
return rds[0], nil
|
||||||
|
} else {
|
||||||
|
return rds[1], nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (d *trainPcSimService) findTrainAllConn(sta *state_proto.TrainState) []*TrainPcReciverData {
|
||||||
|
rds := d.newPcSimclientMap3[sta.ConnState.TypeName]
|
||||||
|
return rds
|
||||||
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) findAllThirdPartState() []tpapi.ThirdPartyApiService {
|
func (d *trainPcSimService) findAllThirdPartState() []tpapi.ThirdPartyApiService {
|
||||||
services := make([]tpapi.ThirdPartyApiService, 0)
|
services := make([]tpapi.ThirdPartyApiService, 0)
|
||||||
for _, data := range d.newPcSimclientMap {
|
for _, data := range d.newPcSimclientMap3 {
|
||||||
services = append(services, data)
|
for _, rd := range data {
|
||||||
|
services = append(services, rd)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return services
|
return services
|
||||||
}
|
}
|
||||||
@ -136,22 +164,23 @@ func pluseCountSpeed(wheelDiameter int32, speedMeter float32) uint32 {
|
|||||||
return uint32(pluseCountData)
|
return uint32(pluseCountData)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) pluseSpeed(sta *state_proto.TrainState) (uint32, float32) {
|
func (d *trainPcSimService) pluseSpeed(pc *state_proto.SensorSpeedPulseCount, wheelDiameter int32) (uint32, float32) {
|
||||||
defer initLock.Unlock()
|
defer initLock.Unlock()
|
||||||
initLock.Lock()
|
initLock.Lock()
|
||||||
|
|
||||||
var sum float32 = 0
|
var sum float32 = 0
|
||||||
pcLen := len(sta.PluseCount.PulseCount3)
|
pcLen := len(pc.PulseCount3)
|
||||||
if pcLen == 0 {
|
if pcLen == 0 {
|
||||||
return 0, 0
|
return 0, 0
|
||||||
}
|
}
|
||||||
for _, f := range sta.PluseCount.PulseCount3 {
|
for _, f := range pc.PulseCount3 {
|
||||||
sum += f
|
sum += f
|
||||||
}
|
}
|
||||||
d.TrainPluseCountReset(sta)
|
d.trainPluseCountReset(pc)
|
||||||
speed := sum / float32(pcLen)
|
speed := sum / float32(pcLen)
|
||||||
return pluseCountSpeed(sta.WheelDiameter, speed*1000), speed
|
return pluseCountSpeed(wheelDiameter, speed*1000), speed
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
|
func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
|
||||||
defer initLock.Unlock()
|
defer initLock.Unlock()
|
||||||
initLock.Lock()
|
initLock.Lock()
|
||||||
@ -161,37 +190,32 @@ func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2,
|
|||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
if sd, err := d.findTrainConn(sta); err == nil {
|
|
||||||
sd.speedPlace.PulseCount1 += sta.DynamicState.Displacement
|
for _, sd := range d.findTrainAllConn(sta) {
|
||||||
//sd.speedPlace.PulseCount1 += float32(uint32(h1 * 10))
|
if sd.speedPlace != nil {
|
||||||
sd.speedPlace.PulseCount2 = sd.speedPlace.PulseCount1
|
sd.speedPlace.PulseCount1 += sta.DynamicState.Displacement
|
||||||
}
|
|
||||||
if sta.TrainRunUp {
|
|
||||||
if sta.TrainEndsA.SpeedSensorEnableA {
|
|
||||||
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, h1)
|
|
||||||
sta.PluseCount.PulseCount3 = append(sta.PluseCount.PulseCount3, h1)
|
|
||||||
}
|
|
||||||
if sta.TrainEndsA.SpeedSensorEnableB {
|
|
||||||
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, h2)
|
|
||||||
sta.PluseCount.PulseCount4 = append(sta.PluseCount.PulseCount3, h2)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if sta.TrainEndsB.SpeedSensorEnableA {
|
|
||||||
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, t1)
|
|
||||||
sta.PluseCount.PulseCount3 = append(sta.PluseCount.PulseCount3, t1)
|
|
||||||
}
|
|
||||||
if sta.TrainEndsB.SpeedSensorEnableB {
|
|
||||||
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, t2)
|
|
||||||
sta.PluseCount.PulseCount4 = append(sta.PluseCount.PulseCount3, t2)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, pc := range sta.PulseCountMap {
|
||||||
|
|
||||||
|
if sta.TrainRunUp {
|
||||||
|
if sta.TrainEndsA.SpeedSensorEnableA || sta.TrainEndsA.SpeedSensorEnableB {
|
||||||
|
pc.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, h1)
|
||||||
|
pc.PulseCount3 = append(pc.PulseCount3, h1)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if sta.TrainEndsB.SpeedSensorEnableA || sta.TrainEndsB.SpeedSensorEnableB {
|
||||||
|
pc.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, t1)
|
||||||
|
pc.PulseCount3 = append(pc.PulseCount3, t1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) TrainPluseCountReset(sta *state_proto.TrainState) {
|
func (d *trainPcSimService) trainPluseCountReset(pc *state_proto.SensorSpeedPulseCount) {
|
||||||
sta.PluseCount.PulseCount1 = 0
|
pc.PulseCount1 = 0
|
||||||
sta.PluseCount.PulseCount2 = 0
|
pc.PulseCount3 = make([]float32, 0)
|
||||||
sta.PluseCount.PulseCount3 = make([]float32, 0)
|
|
||||||
sta.PluseCount.PulseCount4 = make([]float32, 0)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) newCloseAllConn() {
|
func (d *trainPcSimService) newCloseAllConn() {
|
||||||
@ -202,15 +226,16 @@ func (d *trainPcSimService) newCloseAllConn() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) newCloseConn(clientKey string) {
|
func (d *trainPcSimService) newCloseConn(clientKey string) {
|
||||||
rd := d.newPcSimclientMap[clientKey]
|
rds := d.newPcSimclientMap3[clientKey]
|
||||||
if rd != nil {
|
if rds != nil {
|
||||||
rd.tcpClient.Close()
|
for _, rd := range rds {
|
||||||
rd.tcpClient = nil
|
rd.tcpClient.Close()
|
||||||
rd.train = nil
|
rd.tcpClient = nil
|
||||||
rd.speedPlace = nil
|
rd.train = nil
|
||||||
//rd.trainInit = false
|
rd.speedPlace = nil
|
||||||
//d.cancleContextFun()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) findConfig(configName string) (*config.VehiclePCSimConfig, error) {
|
func (d *trainPcSimService) findConfig(configName string) (*config.VehiclePCSimConfig, error) {
|
||||||
@ -223,30 +248,55 @@ func (d *trainPcSimService) findConfig(configName string) (*config.VehiclePCSimC
|
|||||||
return nil, fmt.Errorf("未找到对应的车载pc连接配置")
|
return nil, fmt.Errorf("未找到对应的车载pc连接配置")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) initConn(clientKey string) error {
|
func (d *trainPcSimService) initConn2(clientKey string) error {
|
||||||
|
|
||||||
rd := d.newPcSimclientMap[clientKey]
|
rds := d.newPcSimclientMap3[clientKey]
|
||||||
|
rd1 := rds[0]
|
||||||
|
rd2 := rds[1]
|
||||||
|
cfg, cfgErr := d.findConfig(clientKey)
|
||||||
|
if cfgErr != nil {
|
||||||
|
return sys_error.New(fmt.Sprintf("没找到对应的配置信息 key:%v", clientKey), cfgErr)
|
||||||
|
}
|
||||||
|
if !cfg.OpenB && !cfg.OpenA {
|
||||||
|
return sys_error.New(fmt.Sprintf("配置:%v A,B端配置均为打开", clientKey))
|
||||||
|
}
|
||||||
|
e1 := d.connServer(cfg.OpenA, cfg.APcSimIp, cfg.APcSimPort, rd1)
|
||||||
|
if e1 != nil {
|
||||||
|
rd1.updateState(tpapi.ThirdPartyState_Broken)
|
||||||
|
return sys_error.New(fmt.Sprintf("配置:%v 端口A连接失败", clientKey))
|
||||||
|
}
|
||||||
|
e2 := d.connServer(cfg.OpenB, cfg.BPcSimIp, cfg.BPcSimPort, rd2)
|
||||||
|
if e2 != nil {
|
||||||
|
rd1.updateState(tpapi.ThirdPartyState_Broken)
|
||||||
|
return sys_error.New(fmt.Sprintf("配置:%v 端口B连接失败", clientKey))
|
||||||
|
}
|
||||||
|
if rd1.success {
|
||||||
|
//rd1.aPort = true
|
||||||
|
rd1.RealTrainPort = state_proto.TrainState_PORT_A
|
||||||
|
}
|
||||||
|
if rd2.success {
|
||||||
|
rd2.RealTrainPort = state_proto.TrainState_PORT_B
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *trainPcSimService) connServer(open bool, ip string, port uint32, rd *TrainPcReciverData) *sys_error.BusinessError {
|
||||||
if rd != nil && rd.tcpClient != nil && rd.tcpClient.IsConning() {
|
if rd != nil && rd.tcpClient != nil && rd.tcpClient.IsConning() {
|
||||||
return nil
|
return nil
|
||||||
} else {
|
} else {
|
||||||
//rd.trainInit = false
|
|
||||||
rd.tcpClient = nil
|
rd.tcpClient = nil
|
||||||
}
|
}
|
||||||
cfg, cfgErr := d.findConfig(clientKey)
|
if !open {
|
||||||
if cfgErr != nil {
|
rd.success = false
|
||||||
errMsg := fmt.Sprintf("没找到对应的配置信息 key:%v", clientKey)
|
return nil
|
||||||
//slog.Error(errMsg, cfgErr.Error())
|
|
||||||
rd.updateState(tpapi.ThirdPartyState_Broken)
|
|
||||||
return sys_error.New(errMsg, cfgErr)
|
|
||||||
}
|
}
|
||||||
addr := fmt.Sprintf("%v:%v", cfg.PcSimIp, cfg.PcSimPort)
|
addr := fmt.Sprintf("%v:%v", ip, port)
|
||||||
|
//slog.Info(addr, "连接.,...")
|
||||||
client2, err := tcp.StartTcpClient(addr, rd.receiverDataHandle, rd.readError)
|
client2, err := tcp.StartTcpClient(addr, rd.receiverDataHandle, rd.readError)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
connErrMsg := fmt.Sprintf("车载pc连接失败 clientKey:%v", clientKey)
|
return sys_error.New(fmt.Sprintf("车载atp连接失败,add:%v ,message:%v", addr, err))
|
||||||
//slog.Error(connErrMsg, err.Error())
|
|
||||||
rd.updateState(tpapi.ThirdPartyState_Broken)
|
|
||||||
return sys_error.New(connErrMsg, err)
|
|
||||||
} else {
|
} else {
|
||||||
|
rd.success = true
|
||||||
rd.tcpClient = client2
|
rd.tcpClient = client2
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -255,7 +305,8 @@ func (d *trainPcSimService) initConn(clientKey string) error {
|
|||||||
func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
|
func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
|
||||||
|
|
||||||
configs := pcSimManage.GetTrainPcSimConfig()
|
configs := pcSimManage.GetTrainPcSimConfig()
|
||||||
d.newPcSimclientMap = make(map[string]*TrainPcReciverData)
|
//d.newPcSimclientMap = make(map[string]*TrainPcReciverData)
|
||||||
|
d.newPcSimclientMap3 = make(map[string][]*TrainPcReciverData)
|
||||||
if len(configs) <= 0 {
|
if len(configs) <= 0 {
|
||||||
slog.Info("车载pc仿真配置未开启")
|
slog.Info("车载pc仿真配置未开启")
|
||||||
return
|
return
|
||||||
@ -266,9 +317,16 @@ func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
|
|||||||
closedCount++
|
closedCount++
|
||||||
} else {
|
} else {
|
||||||
ck := c.ConfigName
|
ck := c.ConfigName
|
||||||
pcReciver := &TrainPcReciverData{clientKey: ck, pcSimManage: pcSimManage}
|
pcReceivers := make([]*TrainPcReciverData, 2)
|
||||||
pcReciver.updateState(tpapi.ThirdPartyState_Closed)
|
for i := 0; i < 2; i++ {
|
||||||
d.newPcSimclientMap[ck] = pcReciver
|
ss := fmt.Sprintf("%v%v", c.ConfigName, i)
|
||||||
|
pcReciver := &TrainPcReciverData{clientKey: ss, pcSimManage: pcSimManage}
|
||||||
|
pcReciver.updateState(tpapi.ThirdPartyState_Closed)
|
||||||
|
pcReceivers[i] = pcReciver
|
||||||
|
}
|
||||||
|
d.newPcSimclientMap3[ck] = pcReceivers
|
||||||
|
//d.newPcSimclientMap[ck] = pcReciver
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if closedCount == len(configs) {
|
if closedCount == len(configs) {
|
||||||
@ -285,8 +343,11 @@ func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) Stop() {
|
func (d *trainPcSimService) Stop() {
|
||||||
for _, data := range d.newPcSimclientMap {
|
|
||||||
data.updateState(tpapi.ThirdPartyState_Closed)
|
for _, rds := range d.newPcSimclientMap3 {
|
||||||
|
for _, rd := range rds {
|
||||||
|
rd.updateState(tpapi.ThirdPartyState_Closed)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if d.cancleContextFun != nil {
|
if d.cancleContextFun != nil {
|
||||||
d.cancleContextFun()
|
d.cancleContextFun()
|
||||||
@ -297,46 +358,57 @@ func (d *trainPcSimService) Stop() {
|
|||||||
|
|
||||||
func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, isCreate bool) error {
|
func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, isCreate bool) error {
|
||||||
clientKey := FindTrainPcSimClientKey2(train)
|
clientKey := FindTrainPcSimClientKey2(train)
|
||||||
err := d.initConn(clientKey)
|
|
||||||
if err != nil {
|
|
||||||
d.newCloseConn(clientKey)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
data := []byte{message.FLAG_CAMMAND_REMOVE_TRAIN}
|
data := []byte{message.FLAG_CAMMAND_REMOVE_TRAIN}
|
||||||
if isCreate {
|
if isCreate {
|
||||||
|
err := d.initConn2(clientKey)
|
||||||
|
if err != nil {
|
||||||
|
d.newCloseConn(clientKey)
|
||||||
|
return err
|
||||||
|
}
|
||||||
data[0] = message.FLAG_CAMMAND_CREATE_TRAIN
|
data[0] = message.FLAG_CAMMAND_CREATE_TRAIN
|
||||||
}
|
}
|
||||||
msg := &message.TrainPcSimBaseMessage{Data: data, Type: message.RECIVE_TRAIN_CREATE_REMOVE}
|
msg := &message.TrainPcSimBaseMessage{Data: data, Type: message.RECIVE_TRAIN_CREATE_REMOVE}
|
||||||
rd := d.newPcSimclientMap[clientKey]
|
rds := d.newPcSimclientMap3[clientKey]
|
||||||
if rd != nil {
|
if rds != nil {
|
||||||
initTrainErr := d.initTrain(rd, train, isCreate, msg)
|
for index, rd := range rds {
|
||||||
if !isCreate {
|
if rd != nil && rd.success {
|
||||||
d.newCloseConn(clientKey)
|
slog.Info(fmt.Sprintf("index%v---rd client:%v clientnil :%v", index, rd.tcpClient, rd.tcpClient == nil))
|
||||||
}
|
initTrainErr := d.initTrain(rd, train, isCreate, msg)
|
||||||
if initTrainErr != nil {
|
if !isCreate {
|
||||||
return initTrainErr
|
d.newCloseConn(clientKey)
|
||||||
|
}
|
||||||
|
if initTrainErr != nil {
|
||||||
|
return initTrainErr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (d *trainPcSimService) initTrain(rd *TrainPcReciverData, train *state_proto.TrainState, isCreate bool, trains *message.TrainPcSimBaseMessage) error {
|
func (d *trainPcSimService) initTrain(rd *TrainPcReciverData, train *state_proto.TrainState, isCreate bool, trains *message.TrainPcSimBaseMessage) error {
|
||||||
msgs := make([]message.TrainPcSimBaseMessage, 0)
|
msgs := make([]message.TrainPcSimBaseMessage, 0)
|
||||||
sendMsg := make([]byte, 0)
|
sendMsg := make([]byte, 0)
|
||||||
rd.speedPlace = &message.TrainSpeedPlaceReportMsg{}
|
rd.speedPlace = &message.TrainSpeedPlaceReportMsg{}
|
||||||
train.PluseCount = &state_proto.SensorSpeedPulseCount{}
|
train.PulseCountMap = make(map[int32]*state_proto.SensorSpeedPulseCount)
|
||||||
|
train.PulseCountMap[int32(state_proto.TrainState_PORT_A.Number())] = &state_proto.SensorSpeedPulseCount{}
|
||||||
|
train.PulseCountMap[int32(state_proto.TrainState_PORT_B.Number())] = &state_proto.SensorSpeedPulseCount{}
|
||||||
rd.train = train
|
rd.train = train
|
||||||
tcc := train.Tcc
|
tcc := train.Tcc
|
||||||
tcc.LineInitTimeStamp12 = 0
|
rd.TrainConnInitComplate = false
|
||||||
tcc.Line12ConnErr = false
|
rd.LineInitTimeStamp = 0
|
||||||
|
|
||||||
if isCreate {
|
if isCreate {
|
||||||
tmpMsgs := d.trainPcSimManage.ObtainTrainDigitalMockData(train)
|
tmpMsgs := d.trainPcSimManage.ObtainTrainDigitalMockData(train)
|
||||||
msgs = append(msgs, tmpMsgs...)
|
msgs = append(msgs, tmpMsgs...)
|
||||||
msgs = append(msgs, message.TrainPcSimBaseMessage{Data: []byte{0x00}, Type: message.RECIVE_TRAIN_DOOR_MODE}) //门模式
|
msgs = append(msgs, message.TrainPcSimBaseMessage{Data: []byte{0x00}, Type: message.RECIVE_TRAIN_DOOR_MODE}) //门模式
|
||||||
msgs = append(msgs, message.TrainPcSimBaseMessage{Data: []byte{}, Type: message.RECIVE_TRAIN_BTN_CLEAR_ALL_PRE_DATA}) //清空应答器
|
msgs = append(msgs, message.TrainPcSimBaseMessage{Data: []byte{}, Type: message.RECIVE_TRAIN_BTN_CLEAR_ALL_PRE_DATA}) //清空应答器
|
||||||
|
msgs = append(msgs, message.TrainPcSimBaseMessage{Data: []byte{}, Type: message.SENDER_TRAIN_TC_ACTIVE}) //清空应答器
|
||||||
} else {
|
} else {
|
||||||
train.VobcState.Tc1Active = false
|
train.VobcState.Tc1Active = false
|
||||||
train.VobcState.Tc2Active = false
|
train.VobcState.Tc2Active = false
|
||||||
|
|
||||||
for _, key := range tcc.DriverKey {
|
for _, key := range tcc.DriverKey {
|
||||||
key.Val = false
|
key.Val = false
|
||||||
}
|
}
|
||||||
@ -357,91 +429,67 @@ func (d *trainPcSimService) initTrain(rd *TrainPcReciverData, train *state_proto
|
|||||||
|
|
||||||
// 依据文档80ms发送列车速度位置
|
// 依据文档80ms发送列车速度位置
|
||||||
func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
|
func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
|
||||||
for {
|
for range time.Tick(time.Millisecond * 80) {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
||||||
trains := d.trainPcSimManage.GetConnTrain2()
|
trains := d.trainPcSimManage.GetConnTrain2()
|
||||||
for _, train := range trains {
|
for _, train := range trains {
|
||||||
if train.ConnState.Conn && train.PluseCount != nil {
|
if train.ConnState.Conn {
|
||||||
trainClient, trainDataErr := d.findTrainConn(train)
|
for numKey, pc := range train.PulseCountMap {
|
||||||
if trainDataErr != nil {
|
trainPort := state_proto.TrainState_TrainPort(numKey)
|
||||||
slog.Error(fmt.Sprintf("pc仿真速度位置未找到对应的列车 id:%v", train.Id))
|
trainClient, _ := d.findTrainConnForPort2(train, trainPort)
|
||||||
continue
|
if trainClient.success {
|
||||||
}
|
if trainClient.speedPlace == nil || trainClient.tcpClient == nil {
|
||||||
if trainClient.speedPlace == nil {
|
slog.Error(fmt.Sprintf("pc仿真速度位置脉冲对象为空 列车id:%v", train.Id))
|
||||||
slog.Error(fmt.Sprintf("pc仿真速度位置脉冲对象为空 列车id:%v", train.Id))
|
continue
|
||||||
continue
|
}
|
||||||
}
|
if trainClient.ConnError() {
|
||||||
|
continue
|
||||||
connState := tpapi.ThirdPartyState_Normal
|
}
|
||||||
if train.Tcc.Line12ConnErr {
|
s1, speed := d.pluseSpeed(pc, train.WheelDiameter)
|
||||||
connState = tpapi.ThirdPartyState_Broken
|
runDir := d.trainDirection(speed, train, trainClient.RealTrainPort)
|
||||||
}
|
disPluse := pluseCountSpeed(train.WheelDiameter, trainClient.speedPlace.PulseCount1)
|
||||||
trainClient.updateState(connState)
|
data := trainClient.speedPlace.Encode(runDir, s1, disPluse)
|
||||||
s1, speed := d.pluseSpeed(train)
|
bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
|
||||||
runDir := uint16(2)
|
dataCode := bm.Encode()
|
||||||
if train.VobcState.DirectionForward {
|
slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,列车服务端:%v,列车速度:%v,计数脉冲: %v,累计里程: %v ,发送数据:%X", train.Id, trainClient.RealTrainPort.String(), speed, s1, trainClient.speedPlace.PulseCount1, dataCode))
|
||||||
runDir = 1
|
err := trainClient.tcpClient.Send(dataCode)
|
||||||
}
|
if err != nil {
|
||||||
disPluse := pluseCountSpeed(train.WheelDiameter, trainClient.speedPlace.PulseCount1)
|
slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode)))
|
||||||
data := trainClient.speedPlace.Encode(runDir, s1, disPluse)
|
}
|
||||||
bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
|
}
|
||||||
dataCode := bm.Encode()
|
|
||||||
slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,列车速度:%v,计数脉冲: %v,累计里程: %v ,发送数据:%v", train.Id, speed, s1, trainClient.speedPlace.PulseCount1, hex.EncodeToString(dataCode)))
|
|
||||||
err := trainClient.tcpClient.Send(dataCode)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode)))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
time.Sleep(time.Millisecond * 80)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendDriverActive Deprecated 发送驾驶激活
|
func (d *trainPcSimService) trainDirection(speed float32, train *state_proto.TrainState, clientPort state_proto.TrainState_TrainPort) uint16 {
|
||||||
func (d *trainPcSimService) SendDriverActive(train *state_proto.TrainState) {
|
runDir := uint16(2)
|
||||||
trainClient, trainDataErr := d.findTrainConn(train)
|
|
||||||
if trainDataErr != nil {
|
|
||||||
slog.Error(fmt.Sprintf("发送驾驶激活,未找到对应的列车连接,列车id:%v", train.Id))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
vobc := train.VobcState
|
vobc := train.VobcState
|
||||||
|
if speed == 0 || train.TrainPort == state_proto.TrainState_PORT_NONE || (vobc.DirectionForward == false && vobc.DirectionBackward == false) {
|
||||||
msg := &message.TrainPcSimBaseMessage{}
|
return runDir
|
||||||
if train.TrainRunUp {
|
}
|
||||||
if vobc.Tc1Active {
|
if vobc.DirectionForward {
|
||||||
msg.Type = message.SENDER_TRAIN_TC_ACTIVE
|
runDir = 1
|
||||||
} else if vobc.Tc1Active == false {
|
} else if vobc.DirectionBackward {
|
||||||
msg.Type = message.SENDER_TRAIN_TC_NOT_ACTIVE
|
runDir = 0
|
||||||
}
|
}
|
||||||
} else if !train.TrainRunUp {
|
if train.TrainPort != clientPort {
|
||||||
if vobc.Tc2Active {
|
if vobc.DirectionForward {
|
||||||
msg.Type = message.SENDER_TRAIN_TC_ACTIVE
|
runDir = 0
|
||||||
} else if vobc.Tc2Active == false {
|
} else if vobc.DirectionBackward {
|
||||||
msg.Type = message.SENDER_TRAIN_TC_NOT_ACTIVE
|
runDir = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msgs := make([]byte, 0)
|
|
||||||
if msg.Type == message.SENDER_TRAIN_TC_ACTIVE {
|
|
||||||
dd3 := message.TrainPcSimBaseMessage{Data: []byte{message.KEY_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}
|
|
||||||
msgs = append(msgs, dd3.Encode()...)
|
|
||||||
} else {
|
|
||||||
dd3 := message.TrainPcSimBaseMessage{Data: []byte{message.KEY_STATE, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}
|
|
||||||
msgs = append(msgs, dd3.Encode()...)
|
|
||||||
}
|
|
||||||
msgs = append(msgs, msg.Encode()...)
|
|
||||||
hexData := hex.EncodeToString(msgs)
|
|
||||||
//slog.Info(fmt.Sprintf("发送驾驶激活列车id:%v,数据:%v", train.Id, hexData))
|
|
||||||
err := trainClient.tcpClient.Send(msgs)
|
|
||||||
|
|
||||||
if err != nil {
|
return runDir
|
||||||
slog.Error(fmt.Sprintf("发送驾驶激活失败列车id:%v,数据:%v,err:%v", train.Id, hexData, err.Error()))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, train *state_proto.TrainState) {
|
func (d *trainPcSimService) SendHandleSwitch(oldTraction, oldBrakeForce int64, tractionState bool, train *state_proto.TrainState) {
|
||||||
trainClient, trainDataErr := d.findTrainConn(train)
|
trainClient, trainDataErr := d.findTrainConn(train)
|
||||||
if trainDataErr != nil {
|
if trainDataErr != nil {
|
||||||
@ -511,8 +559,9 @@ func (d *trainPcSimService) SendTrainDirection(train *state_proto.TrainState, tr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte) {
|
func (d *trainPcSimService) SendBaliseData2(train *state_proto.TrainState, trainClientPort state_proto.TrainState_TrainPort, msgType byte, data []byte) {
|
||||||
trainClient, trainDataErr := d.findTrainConn(train)
|
|
||||||
|
trainClient, trainDataErr := d.findTrainConnForPort2(train, trainClientPort)
|
||||||
if trainDataErr != nil {
|
if trainDataErr != nil {
|
||||||
slog.Error(fmt.Sprintf("发送列车PC仿真应答器信息失败,未找到列车连接,trainId:%v", train.Id))
|
slog.Error(fmt.Sprintf("发送列车PC仿真应答器信息失败,未找到列车连接,trainId:%v", train.Id))
|
||||||
return
|
return
|
||||||
@ -529,11 +578,12 @@ func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgTyp
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) SendTrainControlMsg(train *state_proto.TrainState, baseMessage []message.TrainPcSimBaseMessage) {
|
func (d *trainPcSimService) SendTrainControlMsg2(train *state_proto.TrainState, baseMessage []message.TrainPcSimBaseMessage, trainClientPort state_proto.TrainState_TrainPort) {
|
||||||
if len(baseMessage) <= 0 {
|
if len(baseMessage) <= 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
trainClient, trainDataErr := d.findTrainConn(train)
|
//trainClient, trainDataErr := d.findTrainConn(train)
|
||||||
|
trainClient, trainDataErr := d.findTrainConnForPort2(train, trainClientPort)
|
||||||
if trainDataErr != nil {
|
if trainDataErr != nil {
|
||||||
slog.Error(fmt.Sprintf("发送列车控制信息失败,无连接,列车Id:%v", train.Id))
|
slog.Error(fmt.Sprintf("发送列车控制信息失败,无连接,列车Id:%v", train.Id))
|
||||||
return
|
return
|
||||||
@ -541,10 +591,11 @@ func (d *trainPcSimService) SendTrainControlMsg(train *state_proto.TrainState, b
|
|||||||
|
|
||||||
for _, msg := range baseMessage {
|
for _, msg := range baseMessage {
|
||||||
dd := msg.Encode()
|
dd := msg.Encode()
|
||||||
//slog.Info(fmt.Sprintf("发送列车控制信息:%x", dd))
|
//slog.Info(fmt.Sprintf("发送操控列车控制信息:%x", dd), aport)
|
||||||
d.sendData(trainClient.tcpClient, dd)
|
d.sendData(trainClient.tcpClient, dd)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) sendData(client *tcp.TcpClient, data []byte) {
|
func (d *trainPcSimService) sendData(client *tcp.TcpClient, data []byte) {
|
||||||
err := client.Send(data)
|
err := client.Send(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
5
third_party/udp/udp_server.go
vendored
5
third_party/udp/udp_server.go
vendored
@ -10,6 +10,7 @@ import (
|
|||||||
type UdpServer interface {
|
type UdpServer interface {
|
||||||
Listen() error
|
Listen() error
|
||||||
Close()
|
Close()
|
||||||
|
WriteToUdp(data []byte, addr *net.UDPAddr) (int, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type UdpMsgHandler func(b []byte)
|
type UdpMsgHandler func(b []byte)
|
||||||
@ -53,6 +54,10 @@ func (s *server) Close() {
|
|||||||
<-s.done
|
<-s.done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *server) WriteToUdp(data []byte, addr *net.UDPAddr) (int, error) {
|
||||||
|
return s.conn.WriteToUDP(data, addr)
|
||||||
|
}
|
||||||
|
|
||||||
func (s *server) listenAndHandle(ctx context.Context) {
|
func (s *server) listenAndHandle(ctx context.Context) {
|
||||||
defer close(s.done)
|
defer close(s.done)
|
||||||
defer s.conn.Close()
|
defer s.conn.Close()
|
||||||
|
@ -77,6 +77,7 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
|
|||||||
calctailOffset := calcTrailTailOffset(loffset, status.TrainLength, up)
|
calctailOffset := calcTrailTailOffset(loffset, status.TrainLength, up)
|
||||||
// 车尾位置
|
// 车尾位置
|
||||||
tailLink, tailDeviceId, tailDevicePort, tailLOffset, tailDeviceOffset, _, e1 := CalcInitializeLink(vs, linkId, calctailOffset, up)
|
tailLink, tailDeviceId, tailDevicePort, tailLOffset, tailDeviceOffset, _, e1 := CalcInitializeLink(vs, linkId, calctailOffset, up)
|
||||||
|
|
||||||
if e1 != nil {
|
if e1 != nil {
|
||||||
panic(sys_error.New("添加列车失败,列车车尾占用位置计算出错", e1))
|
panic(sys_error.New("添加列车失败,列车车尾占用位置计算出错", e1))
|
||||||
}
|
}
|
||||||
@ -95,7 +96,9 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
|
|||||||
status.TailDeviceId = vs.GetComIdByUid(tailDeviceId)
|
status.TailDeviceId = vs.GetComIdByUid(tailDeviceId)
|
||||||
status.TailOffset = tailDeviceOffset
|
status.TailOffset = tailDeviceOffset
|
||||||
status.TailDevicePort = tailDevicePort
|
status.TailDevicePort = tailDevicePort
|
||||||
status.BtmBaliseCache = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)}
|
status.BtmBaliseCacheA = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)}
|
||||||
|
status.BtmBaliseCacheB = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)}
|
||||||
|
|
||||||
//初始化列车参数状态
|
//初始化列车参数状态
|
||||||
createOrUpdateStateDynamicConfig(status, configTrainData, trainEndsA, trainEndsB)
|
createOrUpdateStateDynamicConfig(status, configTrainData, trainEndsA, trainEndsB)
|
||||||
tl := status.TrainLoad * 100
|
tl := status.TrainLoad * 100
|
||||||
@ -107,7 +110,7 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
|
|||||||
status.VobcState = vobc
|
status.VobcState = vobc
|
||||||
|
|
||||||
status.Tcc = initTrainTcc(vs)
|
status.Tcc = initTrainTcc(vs)
|
||||||
status.VobcBtm = &state_proto.VobcBtmState{TelegramState: make([]*state_proto.VobcBtmState_TelegramState, 3), History: make(map[uint32]*state_proto.VobcBtmState_VobcBtmHistoryState)}
|
//status.VobcBtm = &state_proto.VobcBtmState{TelegramState: make([]*state_proto.VobcBtmState_TelegramState, 3), History: make(map[uint32]*state_proto.VobcBtmState_VobcBtmHistoryState)}
|
||||||
linkIdInt, _ := strconv.Atoi(linkId)
|
linkIdInt, _ := strconv.Atoi(linkId)
|
||||||
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
|
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
|
||||||
TrainIndex: uint16(trainIndex),
|
TrainIndex: uint16(trainIndex),
|
||||||
@ -167,7 +170,10 @@ func TrainConnTypeUpdate(vs *VerifySimulation, ct *dto.TrainConnThirdDto) {
|
|||||||
train.ConnState.ConnType = ct.ConnType
|
train.ConnState.ConnType = ct.ConnType
|
||||||
train.ConnState.TypeName = ct.TypeName
|
train.ConnState.TypeName = ct.TypeName
|
||||||
if ct.ConnType == state_proto.TrainConnState_PC_SIM {
|
if ct.ConnType == state_proto.TrainConnState_PC_SIM {
|
||||||
train.Tcc.LineInitTimeStamp12 = 0
|
//train.Tcc.LineInitTimeStamp12 = 0
|
||||||
|
//train.Tcc.LineInitTimeStamp12PortA = 0
|
||||||
|
//train.Tcc.LineInitTimeStamp12PortB = 0
|
||||||
|
|
||||||
err := TrainPcSimConnOrRemoveHandle(train, true)
|
err := TrainPcSimConnOrRemoveHandle(train, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
train.ConnState.Conn = false
|
train.ConnState.Conn = false
|
||||||
@ -323,6 +329,8 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
|
|||||||
//calctailOffset := calcTrailTailOffset(outLinkOffset, int64(info.Len), info.Up)
|
//calctailOffset := calcTrailTailOffset(outLinkOffset, int64(info.Len), info.Up)
|
||||||
calctailOffset := calcTrailTailOffset(outLinkOffset, int64(info.Len), trainHeadActUp)
|
calctailOffset := calcTrailTailOffset(outLinkOffset, int64(info.Len), trainHeadActUp)
|
||||||
tailLinkId, tailDeviceId, tailDevicePort, tailLinkOffset, tailOffset, _, e2 := CalcInitializeLink(vs, outLinkId, calctailOffset, !info.Up)
|
tailLinkId, tailDeviceId, tailDevicePort, tailLinkOffset, tailOffset, _, e2 := CalcInitializeLink(vs, outLinkId, calctailOffset, !info.Up)
|
||||||
|
|
||||||
|
tailUp, _ := QueryUpAndABByDevice(vs.Repo, tailDeviceId, tailDevicePort, sta.TrainRunUp)
|
||||||
if e2 != nil {
|
if e2 != nil {
|
||||||
panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2))
|
panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2))
|
||||||
}
|
}
|
||||||
@ -335,8 +343,12 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
|
|||||||
sta.OldLinkOffset = outLinkOffset
|
sta.OldLinkOffset = outLinkOffset
|
||||||
sta.OldLink = outLinkId
|
sta.OldLink = outLinkId
|
||||||
}
|
}
|
||||||
|
if sta.OldTailLinkOffset == 0 {
|
||||||
|
sta.OldTailLinkOffset = tailLinkOffset
|
||||||
|
sta.OldTailLink = tailLinkId
|
||||||
|
}
|
||||||
|
|
||||||
updateTrainBtmPosition(vs, info, sta, outLinkId, outLinkOffset)
|
updateTrainBtmPosition(vs, info, sta, outLinkId, outLinkOffset, tailUp, tailLinkId, tailLinkOffset)
|
||||||
//slog.Info(fmt.Sprintf("动力学,当前速度(米/秒):%v,加速度:%v,位移距离:%v", info.Speed, info.Acceleration, info.Displacement))
|
//slog.Info(fmt.Sprintf("动力学,当前速度(米/秒):%v,加速度:%v,位移距离:%v", info.Speed, info.Acceleration, info.Displacement))
|
||||||
if sta.OldLink != outLinkId {
|
if sta.OldLink != outLinkId {
|
||||||
sta.OldLink = outLinkId
|
sta.OldLink = outLinkId
|
||||||
@ -344,6 +356,13 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
|
|||||||
if sta.OldLinkOffset != outLinkOffset {
|
if sta.OldLinkOffset != outLinkOffset {
|
||||||
sta.OldLinkOffset = outLinkOffset
|
sta.OldLinkOffset = outLinkOffset
|
||||||
}
|
}
|
||||||
|
if sta.OldTailLink != tailLinkId {
|
||||||
|
sta.OldTailLink = tailLinkId
|
||||||
|
}
|
||||||
|
if sta.OldTailLinkOffset != tailLinkOffset {
|
||||||
|
sta.OldTailLinkOffset = tailLinkOffset
|
||||||
|
}
|
||||||
|
|
||||||
sta.HeadDeviceId = vs.GetComIdByUid(id)
|
sta.HeadDeviceId = vs.GetComIdByUid(id)
|
||||||
sta.DevicePort = port
|
sta.DevicePort = port
|
||||||
sta.HeadOffset = offset
|
sta.HeadOffset = offset
|
||||||
@ -398,33 +417,25 @@ func updateTrainActiveDirFromDynamic(vs *VerifySimulation, info *message.Dynamic
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 根据列车位置修改列车应答器
|
// 根据列车位置修改列车应答器
|
||||||
func updateTrainBtmPosition(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64) {
|
func updateTrainBtmPosition(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64, tailUp bool, tailLinkId string, tailLinkOffset int64) {
|
||||||
// 更新BTM中列车位置信息
|
// 更新BTM中列车位置信息
|
||||||
//isup := sta.TrainActiveDirection == 1
|
//isup := sta.TrainActiveDirection == 1
|
||||||
can_btm.Default().HandleTrainHeadPositionInfoForTrain(vs.World, sta.BtmBaliseCache, &fi.TrainHeadPositionInfo{
|
can_btm.Default().HandleTrainHeadPositionInfoForTrain(vs.World, sta, &fi.TrainHeadPositionInfo{
|
||||||
TrainId: sta.Id,
|
TrainId: sta.Id,
|
||||||
Up: info.Up,
|
Up: info.Up,
|
||||||
Link: outLinkId,
|
Link: outLinkId,
|
||||||
LinkOffset: outLinkOffset,
|
LinkOffset: outLinkOffset,
|
||||||
Speed: info.Speed,
|
Speed: info.Speed,
|
||||||
Acceleration: info.Acceleration,
|
Acceleration: info.Acceleration,
|
||||||
OldLinkOffset: sta.OldLinkOffset,
|
OldLinkOffset: sta.OldLinkOffset,
|
||||||
OldLink: sta.OldLink,
|
OldLink: sta.OldLink,
|
||||||
|
TailUp: tailUp,
|
||||||
|
TailLink: tailLinkId,
|
||||||
|
TailLinkOffset: tailLinkOffset,
|
||||||
|
OldTailLink: sta.OldTailLink,
|
||||||
|
OldTailLinkOffset: sta.OldTailLinkOffset,
|
||||||
|
IsLine12: can_btm.IsLine12(sta),
|
||||||
})
|
})
|
||||||
/*can_btm.Default().HandleTrainHeadPositionInfo(vs.World, sta.VobcBtm, &fi.TrainHeadPositionInfo{
|
|
||||||
TrainId: sta.Id,
|
|
||||||
Up: info.Up,
|
|
||||||
Link: outLinkId,
|
|
||||||
LinkOffset: outLinkOffset,
|
|
||||||
Speed: info.Speed,
|
|
||||||
Acceleration: info.Acceleration,
|
|
||||||
OldLinkOffset: sta.OldLinkOffset,
|
|
||||||
OldLink: sta.OldLink,
|
|
||||||
})*/
|
|
||||||
/* state := can_btm.Default().GetState()
|
|
||||||
if sta.BtmState == nil || sta.BtmState.BaliseId != state.BaliseId {
|
|
||||||
sta.BtmState = &state
|
|
||||||
}*/
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -442,7 +453,7 @@ func handleTrainPositionFromDynamic(vs *VerifySimulation, info *message.Dynamics
|
|||||||
}
|
}
|
||||||
|
|
||||||
func pluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
|
func pluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
|
||||||
if sta.PluseCount == nil {
|
if sta.PulseCountMap == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
train_pc_sim.Default().TrainPluseCount(sta, h1, h2, t1, t2)
|
train_pc_sim.Default().TrainPluseCount(sta, h1, h2, t1, t2)
|
||||||
@ -494,7 +505,8 @@ func RemoveTrainState(vs *VerifySimulation, id string) {
|
|||||||
if ok {
|
if ok {
|
||||||
t := d.(*state_proto.TrainState)
|
t := d.(*state_proto.TrainState)
|
||||||
err := removeTrain(vs, id, t)
|
err := removeTrain(vs, id, t)
|
||||||
clearTrainVobcBtmState(vs, id)
|
t.VobcState.VobcBtmInfo = nil
|
||||||
|
//clearTrainVobcBtmState(vs, id)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: err.Error()})
|
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: err.Error()})
|
||||||
}
|
}
|
||||||
@ -514,12 +526,12 @@ func calcTrailTailOffset(headerOffset, length int64, up bool) (calctailOffset in
|
|||||||
}
|
}
|
||||||
|
|
||||||
func clearTrainVobcBtmState(vs *VerifySimulation, id string) {
|
func clearTrainVobcBtmState(vs *VerifySimulation, id string) {
|
||||||
allTrainMap := &vs.Memory.Status.TrainStateMap
|
//allTrainMap := &vs.Memory.Status.TrainStateMap
|
||||||
d, ok := allTrainMap.Load(id)
|
//d, ok := allTrainMap.Load(id)
|
||||||
if !ok {
|
//if !ok {
|
||||||
slog.Error(fmt.Sprintf("vobc btm 清空操作 列车【%s】不存在", id))
|
// slog.Error(fmt.Sprintf("vobc btm 清空操作 列车【%s】不存在", id))
|
||||||
return
|
// return
|
||||||
}
|
//}
|
||||||
t := d.(*state_proto.TrainState)
|
//t := d.(*state_proto.TrainState)
|
||||||
t.VobcBtm.History = nil
|
//t.VobcBtm.History = nil
|
||||||
}
|
}
|
||||||
|
@ -47,6 +47,8 @@ type VerifySimulation struct {
|
|||||||
UidMap map[string]*DeviceRelationship
|
UidMap map[string]*DeviceRelationship
|
||||||
// 运行环境配置
|
// 运行环境配置
|
||||||
runConfig *config.ThirdPartyConfig
|
runConfig *config.ThirdPartyConfig
|
||||||
|
//运行线路code
|
||||||
|
ProjectCode string
|
||||||
}
|
}
|
||||||
|
|
||||||
// 轨旁仿真内存模型
|
// 轨旁仿真内存模型
|
||||||
@ -263,7 +265,18 @@ func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainIn
|
|||||||
// 更新列车状态
|
// 更新列车状态
|
||||||
trainState := UpdateTrainStateByDynamics(s, trainId, info)
|
trainState := UpdateTrainStateByDynamics(s, trainId, info)
|
||||||
vs := train.VobcState
|
vs := train.VobcState
|
||||||
|
if train.ConnState.Conn && train.ConnState.ConnType == state_proto.TrainConnState_VOBC {
|
||||||
|
semi_physical_train.Default().SendTrainControlMessage(info)
|
||||||
|
electrical_machinery.Default().SendElectricMachineryMessage2(info, trainState)
|
||||||
|
radar.Default().TrainSpeedSender(info, trainState)
|
||||||
|
acc.Default().TrainAccSender(info, trainState)
|
||||||
|
}
|
||||||
if vs.Ato {
|
if vs.Ato {
|
||||||
|
|
||||||
|
if train.TrainPort == state_proto.TrainState_PORT_NONE {
|
||||||
|
slog.Info("")
|
||||||
|
return
|
||||||
|
}
|
||||||
trainAtoControlTractionAndBrake(train)
|
trainAtoControlTractionAndBrake(train)
|
||||||
var msgs []message.TrainPcSimBaseMessage
|
var msgs []message.TrainPcSimBaseMessage
|
||||||
if vs.AtoOpenRightDoor || vs.AtoOpenLeftDoor {
|
if vs.AtoOpenRightDoor || vs.AtoOpenLeftDoor {
|
||||||
@ -279,19 +292,12 @@ func (s *VerifySimulation) HandleDynamicsTrainInfo(info *message.DynamicsTrainIn
|
|||||||
}
|
}
|
||||||
msgs = controlDoorCloseBtn(train.VobcState, true, btn, vs.AtoOpenLeftDoor, false)
|
msgs = controlDoorCloseBtn(train.VobcState, true, btn, vs.AtoOpenLeftDoor, false)
|
||||||
}
|
}
|
||||||
train_pc_sim.Default().SendTrainControlMsg(train, msgs)
|
train_pc_sim.Default().SendTrainControlMsg2(train, msgs, train.TrainPort)
|
||||||
|
|
||||||
} else if vs.TractionStatus {
|
} else if vs.TractionStatus {
|
||||||
f := trainTractionPower(train.TrainLoad, train.Tcc.PushHandler.Val, trainState.DynamicState.Speed, train.TrainMaxAcc, train.TrainMaxSpeed)
|
f := trainTractionPower(train.TrainLoad, train.Tcc.PushHandler.Val, trainState.DynamicState.Speed, train.TrainMaxAcc, train.TrainMaxSpeed)
|
||||||
vs.TractionForce = f / 1000 * 100
|
vs.TractionForce = f / 1000 * 100
|
||||||
}
|
}
|
||||||
|
|
||||||
if train.ConnState.Conn && train.ConnState.ConnType == state_proto.TrainConnState_VOBC {
|
|
||||||
semi_physical_train.Default().SendTrainControlMessage(info)
|
|
||||||
electrical_machinery.Default().SendElectricMachineryMessage2(info, trainState)
|
|
||||||
radar.Default().TrainSpeedSender(info, trainState)
|
|
||||||
acc.Default().TrainAccSender(info, trainState)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取动力学配置信息
|
// 获取动力学配置信息
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"joylink.club/bj-rtsts-server/third_party/can_btm"
|
"joylink.club/bj-rtsts-server/third_party/can_btm"
|
||||||
"joylink.club/bj-rtsts-server/third_party/electrical_machinery"
|
"joylink.club/bj-rtsts-server/third_party/electrical_machinery"
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/tcp"
|
||||||
train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim"
|
train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"math"
|
"math"
|
||||||
@ -37,13 +38,16 @@ func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
|
|||||||
sta := data.(*state_proto.TrainState)
|
sta := data.(*state_proto.TrainState)
|
||||||
vobc := sta.VobcState
|
vobc := sta.VobcState
|
||||||
tcc := sta.Tcc
|
tcc := sta.Tcc
|
||||||
|
if ct.ControlType != request_proto.TrainControl_DRIVER_KEY_SWITCH && vobc.Tc1Active == false && vobc.Tc2Active == false {
|
||||||
|
panic(sys_error.New("请先上驾驶端钥匙"))
|
||||||
|
}
|
||||||
|
|
||||||
var baseMsg []message.TrainPcSimBaseMessage = nil
|
var baseMsg []message.TrainPcSimBaseMessage = nil
|
||||||
if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON {
|
if ct.ControlType == request_proto.TrainControl_EMERGENT_BUTTON {
|
||||||
baseMsg = trainControlButton(sta, ct.DeviceId, ct.ControlButton.Active, tccGraphicData)
|
baseMsg = trainControlButton(sta, ct.DeviceId, ct.ControlButton.Active, tccGraphicData)
|
||||||
} else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH {
|
} else if ct.ControlType == request_proto.TrainControl_DRIVER_KEY_SWITCH {
|
||||||
baseMsg = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId, tccGraphicData)
|
baseMsg = trainControlDriverKey(sta, ct.DriverKey, ct.DeviceId, tccGraphicData)
|
||||||
train_pc_sim.Default().SendDriverActive(sta)
|
//train_pc_sim.Default().SendDriverActive(sta)
|
||||||
} else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH {
|
} else if ct.ControlType == request_proto.TrainControl_DIRECTION_KEY_SWITCH {
|
||||||
baseMsg = trainControlDirKey(sta.DynamicState.Speed, vobc, tcc, ct.SwitchKey, ct.DeviceId, tccGraphicData)
|
baseMsg = trainControlDirKey(sta.DynamicState.Speed, vobc, tcc, ct.SwitchKey, ct.DeviceId, tccGraphicData)
|
||||||
//此处先注释,根据现场调试情况 2024-4-16
|
//此处先注释,根据现场调试情况 2024-4-16
|
||||||
@ -76,7 +80,10 @@ func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
|
|||||||
vobc.TractionForce = 0
|
vobc.TractionForce = 0
|
||||||
}
|
}
|
||||||
if sta.ConnState.Conn && (sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM) && baseMsg != nil {
|
if sta.ConnState.Conn && (sta.ConnState.ConnType == state_proto.TrainConnState_PC_SIM) && baseMsg != nil {
|
||||||
train_pc_sim.Default().SendTrainControlMsg(sta, baseMsg)
|
train_pc_sim.Default().SendTrainControlMsg2(sta, baseMsg, sta.TrainPort)
|
||||||
|
if vobc.Tc1Active == false && vobc.Tc2Active == false {
|
||||||
|
sta.TrainPort = state_proto.TrainState_PORT_NONE
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,10 +103,8 @@ func trainControlButton(train *state_proto.TrainState, deviceId uint32, active b
|
|||||||
return controlAtpBtn(vobc, active, btn)
|
return controlAtpBtn(vobc, active, btn)
|
||||||
case KZM, KYM: //开左门按钮
|
case KZM, KYM: //开左门按钮
|
||||||
return controlDoorOpenBtn(vobc, active, btn, graphicBtn.Code == KZM, true)
|
return controlDoorOpenBtn(vobc, active, btn, graphicBtn.Code == KZM, true)
|
||||||
|
|
||||||
case GZM, GYM: //关左门按钮
|
case GZM, GYM: //关左门按钮
|
||||||
return controlDoorCloseBtn(vobc, active, btn, graphicBtn.Code == GZM, true)
|
return controlDoorCloseBtn(vobc, active, btn, graphicBtn.Code == GZM, true)
|
||||||
|
|
||||||
case ZF: //折返按钮
|
case ZF: //折返按钮
|
||||||
return controlReverseBtn(vobc, active, btn)
|
return controlReverseBtn(vobc, active, btn)
|
||||||
case QZMYX: //强制门允许
|
case QZMYX: //强制门允许
|
||||||
@ -387,9 +392,14 @@ func trainControlDriverKey(train *state_proto.TrainState, request *request_proto
|
|||||||
tcc := train.Tcc
|
tcc := train.Tcc
|
||||||
if obj.Code == SKQYS1 {
|
if obj.Code == SKQYS1 {
|
||||||
vobc.Tc1Active = request.Val
|
vobc.Tc1Active = request.Val
|
||||||
|
train.TrainPort = state_proto.TrainState_PORT_A
|
||||||
|
train.BtmBaliseCacheA = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)}
|
||||||
} else if obj.Code == SKQYS2 {
|
} else if obj.Code == SKQYS2 {
|
||||||
vobc.Tc2Active = request.Val
|
vobc.Tc2Active = request.Val
|
||||||
|
train.TrainPort = state_proto.TrainState_PORT_B
|
||||||
|
train.BtmBaliseCacheB = &state_proto.TrainBtmCache{BaliseList: make([]*state_proto.BTMState, 3)}
|
||||||
}
|
}
|
||||||
|
|
||||||
if vobc.Tc1Active && vobc.Tc2Active {
|
if vobc.Tc1Active && vobc.Tc2Active {
|
||||||
if obj.Code == SKQYS1 {
|
if obj.Code == SKQYS1 {
|
||||||
vobc.Tc1Active = false
|
vobc.Tc1Active = false
|
||||||
@ -398,19 +408,28 @@ func trainControlDriverKey(train *state_proto.TrainState, request *request_proto
|
|||||||
}
|
}
|
||||||
panic(sys_error.New("驾驶端不能同时激活"))
|
panic(sys_error.New("驾驶端不能同时激活"))
|
||||||
}
|
}
|
||||||
var addNew = true
|
|
||||||
for _, k := range tcc.DriverKey {
|
for _, k := range tcc.DriverKey {
|
||||||
if k.Id == deviceId {
|
if k.Id == deviceId {
|
||||||
k.Id = deviceId
|
k.Id = deviceId
|
||||||
k.Val = request.Val
|
k.Val = request.Val
|
||||||
addNew = false
|
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if addNew {
|
|
||||||
tcc.DriverKey = append(tcc.DriverKey, &state_proto.TrainControlState_DriverKeySwitch{Id: deviceId, Val: request.Val})
|
tce := make([]message.TrainPcSimBaseMessage, 0)
|
||||||
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.KEY_STATE, message.IsTrue(request.Val)}})
|
||||||
|
train.OldLink = ""
|
||||||
|
train.OldLinkOffset = 0
|
||||||
|
train.OldTailLink = ""
|
||||||
|
train.OldTailLinkOffset = 0
|
||||||
|
if request.Val {
|
||||||
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_TC_ACTIVE})
|
||||||
|
} else {
|
||||||
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_TC_NOT_ACTIVE})
|
||||||
}
|
}
|
||||||
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.KEY_STATE, message.IsTrue(request.Val)}}}
|
|
||||||
|
return tce
|
||||||
|
|
||||||
}
|
}
|
||||||
func trainDoorModeChangeHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_SwitchKeyChange, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage {
|
func trainDoorModeChangeHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.TrainControlState, request *request_proto.TrainControl_SwitchKeyChange, deviceId uint32, tccGraphic *data_proto.TccGraphicStorage) []message.TrainPcSimBaseMessage {
|
||||||
@ -512,7 +531,7 @@ func trainAtoControlTractionAndBrake(train *state_proto.TrainState) {
|
|||||||
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, notBreak}},
|
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, notBreak}},
|
||||||
}
|
}
|
||||||
slog.Info(fmt.Sprintf("列车 id:%v,ato:%v,AtoLevle:%v,牵引:%v,制动:%v,牵引力:%v,制动力%v", train.Id, vs.Ato, vs.AtoStepLevel, vs.AtoTractionCommandOut, vs.AtoBrakeCommand, vs.TractionForce, vs.BrakeForce))
|
slog.Info(fmt.Sprintf("列车 id:%v,ato:%v,AtoLevle:%v,牵引:%v,制动:%v,牵引力:%v,制动力%v", train.Id, vs.Ato, vs.AtoStepLevel, vs.AtoTractionCommandOut, vs.AtoBrakeCommand, vs.TractionForce, vs.BrakeForce))
|
||||||
train_pc_sim.Default().SendTrainControlMsg(train, msg)
|
train_pc_sim.Default().SendTrainControlMsg2(train, msg, train.TrainPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// 列车牵引控制
|
// 列车牵引控制
|
||||||
@ -607,59 +626,66 @@ func (s *VerifySimulation) FindConnTrain(ct state_proto.TrainConnState_TrainConn
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 反馈atp输出数字量数据
|
// 反馈atp输出数字量数据
|
||||||
func (s *VerifySimulation) reportTrainMockInitMsg(train *state_proto.TrainState, data1, data3 byte) {
|
func (s *VerifySimulation) reportTrainMockInitMsg2(driverActive, initConn bool, initTimeStamp int64, trainClientPort state_proto.TrainState_TrainPort, train *state_proto.TrainState, data1, data3 byte) (int64, bool, bool, []message.TrainPcSimBaseMessage) {
|
||||||
vobc := train.VobcState
|
|
||||||
tcc := train.Tcc
|
tcc := train.Tcc
|
||||||
tce := make([]message.TrainPcSimBaseMessage, 0)
|
tce := make([]message.TrainPcSimBaseMessage, 0)
|
||||||
tcc.Line12ConnErr = false
|
connErr := false
|
||||||
//initResult := trainInit
|
state := message.GetBit(data1, 3)
|
||||||
if vobc.Tc1Active || vobc.Tc2Active {
|
//slog.Info(fmt.Sprintf("act:%v ,t1:%v ,a1 :%v,t2:%v,a2:%v,init:%v,ts:%v", act, train.VobcState.Tc1Active, tcc.ActiveTrainA, train.VobcState.Tc2Active, tcc.ActiveTrainB, initConn, initTimeStamp), aport)
|
||||||
state := message.GetBit(data1, 3)
|
|
||||||
//if trainInit {
|
if message.GetBit(data3, 3) == 0 {
|
||||||
if vobc.TrainConnInitComplate {
|
actt := byte(0)
|
||||||
if data1 == 0 {
|
if driverActive {
|
||||||
tcc.Line12ConnErr = true
|
actt = 1
|
||||||
}
|
}
|
||||||
if state == 0 {
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DRIVER_ACTIVE_REPORT, actt}})
|
||||||
jjzdBtn := tcc.Buttons[JJZD]
|
}
|
||||||
ebTce := controlEBBtn(train, true, jjzdBtn)
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_INTEGRITY, 1}})
|
||||||
tce = append(tce, ebTce...)
|
|
||||||
} else if message.GetBit(data1, 0) == 0 {
|
if driverActive == false {
|
||||||
jjzdBtn := tcc.Buttons[JJZD]
|
return initTimeStamp, initConn, false, tce
|
||||||
ebTce := controlEBBtn(train, true, jjzdBtn)
|
}
|
||||||
tce = append(tce, ebTce...)
|
if initConn {
|
||||||
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}})
|
if data1 == 0 {
|
||||||
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_TRACTION_CUTED, 1}})
|
connErr = true
|
||||||
}
|
}
|
||||||
} else {
|
if state == 0 {
|
||||||
//initResult = false
|
jjzdBtn := tcc.Buttons[JJZD]
|
||||||
vobc.TrainConnInitComplate = true
|
ebTce := controlEBBtn(train, true, jjzdBtn)
|
||||||
if tcc.LineInitTimeStamp12 <= 0 {
|
tce = append(tce, ebTce...)
|
||||||
tcc.LineInitTimeStamp12 = time.Now().Add(time.Second * 6).Unix()
|
} else if message.GetBit(data1, 0) == 0 {
|
||||||
}
|
jjzdBtn := tcc.Buttons[JJZD]
|
||||||
if tcc.LineInitTimeStamp12 > time.Now().Unix() {
|
ebTce := controlEBBtn(train, true, jjzdBtn)
|
||||||
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}})
|
tce = append(tce, ebTce...)
|
||||||
initData := s.ObtainTrainDigitalMockDataForStatus(train)
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}})
|
||||||
tce = append(tce, initData...)
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_TRACTION_CUTED, 1}})
|
||||||
//initResult = false
|
|
||||||
vobc.TrainConnInitComplate = false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//驾驶室激活反馈
|
} else {
|
||||||
if message.GetBit(data3, 3) == 0 {
|
initConn = true
|
||||||
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.DRIVER_ACTIVE_REPORT, 1}})
|
if initTimeStamp <= 0 {
|
||||||
|
initTimeStamp = time.Now().Add(time.Second * 6).Unix()
|
||||||
|
}
|
||||||
|
if initTimeStamp > time.Now().Unix() {
|
||||||
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}})
|
||||||
|
initData := s.ObtainTrainDigitalMockDataForStatus(train)
|
||||||
|
tce = append(tce, initData...)
|
||||||
|
/* if trainClientPort == state_proto.TrainState_PORT_A {
|
||||||
|
tcc.ActiveTrainA = true
|
||||||
|
} else if trainClientPort == state_proto.TrainState_PORT_A {
|
||||||
|
tcc.ActiveTrainB = true
|
||||||
|
}*/
|
||||||
|
initConn = false
|
||||||
}
|
}
|
||||||
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_INTEGRITY, 1}})
|
|
||||||
}
|
}
|
||||||
train_pc_sim.Default().SendTrainControlMsg(train, tce)
|
|
||||||
//return initResult
|
return initTimeStamp, initConn, connErr, tce
|
||||||
}
|
}
|
||||||
func trainAtoLevel(at3, at2, at1 bool) state_proto.TrainVobcState_AtoStepLevel {
|
func trainAtoLevel(at3, at2, at1 bool) state_proto.TrainVobcState_AtoStepLevel {
|
||||||
switch {
|
switch {
|
||||||
case at3 == false && at2 == false && at1 == true:
|
case at3 == false && at2 == false && at1 == true:
|
||||||
return state_proto.TrainVobcState_ATO_STEP_LEVEL_1
|
return state_proto.TrainVobcState_ATO_STEP_LEVEL_1
|
||||||
|
|
||||||
case at3 == false && at2 == true && at1 == true:
|
case at3 == false && at2 == true && at1 == true:
|
||||||
return state_proto.TrainVobcState_ATO_STEP_LEVEL_2
|
return state_proto.TrainVobcState_ATO_STEP_LEVEL_2
|
||||||
case at3 == false && at2 == true && at1 == false:
|
case at3 == false && at2 == true && at1 == false:
|
||||||
@ -676,31 +702,91 @@ func trainAtoLevel(at3, at2, at1 bool) state_proto.TrainVobcState_AtoStepLevel {
|
|||||||
return state_proto.TrainVobcState_ATO_STEP_LEVEL_NONE
|
return state_proto.TrainVobcState_ATO_STEP_LEVEL_NONE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (s *VerifySimulation) shuziliang(client *tcp.TcpClient, baseMessage []message.TrainPcSimBaseMessage) {
|
||||||
|
for _, msg := range baseMessage {
|
||||||
|
dd := msg.Encode()
|
||||||
|
//slog.Info(fmt.Sprintf("发送列车控制信息:%x", dd), aport)
|
||||||
|
client.Send(dd)
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4.4.1. 车载输出数字量信息报文内容
|
// 4.4.1. 车载输出数字量信息报文内容
|
||||||
func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(train *state_proto.TrainState, data []byte) {
|
func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(pc *train_pc_sim.TrainPcReciverData, train *state_proto.TrainState, data []byte) bool {
|
||||||
/* slog.Info("开始接受atp输出模拟量==============")
|
|
||||||
for i, d := range data {
|
|
||||||
|
|
||||||
dd := &strings.Builder{}
|
//slog.Info("开始接受atp输出模拟量==============%v", aport)
|
||||||
|
/* for i, d := range data {
|
||||||
|
dd := &strings.Builder{}
|
||||||
for j := 0; j < 8; j++ {
|
for j := 0; j < 8; j++ {
|
||||||
dd.WriteString(fmt.Sprintf(" bit%v val:%v , ", j, message.GetBit(d, uint(j))))
|
dd.WriteString(fmt.Sprintf(" bit%v val:%v , ", j, message.GetBit(d, uint(j))))
|
||||||
}
|
}
|
||||||
slog.Info(fmt.Sprintf("接受atp模拟量id:%v,data:%b,bits:%v", i, d, dd.String()))
|
slog.Info(fmt.Sprintf("接受atp模拟量id:%v,data:%b,bits:%v", i, d, dd.String()))
|
||||||
|
}*/
|
||||||
|
|
||||||
}
|
//slog.Info(fmt.Sprintf("%v", dd.String()), aport)
|
||||||
slog.Info("结束接受atp输出模拟量eeeeeeeeeeeeeeeeee")*/
|
//slog.Info("结束接受atp输出模拟量eeeeeeeeeeeeeeeeee", aport)
|
||||||
s.reportTrainMockInitMsg(train, data[4], data[1])
|
|
||||||
|
//s.reportTrainMockInitMsg(aport, client, train, data[4], data[1])
|
||||||
vobc := train.VobcState
|
vobc := train.VobcState
|
||||||
trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc)
|
act := vobc.Tc1Active
|
||||||
trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc)
|
if pc.RealTrainPort == state_proto.TrainState_PORT_B {
|
||||||
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
|
act = vobc.Tc2Active
|
||||||
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
|
|
||||||
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
|
|
||||||
if vobc.Ato {
|
|
||||||
vobc.AtoStepLevel = trainAtoLevel(vobc.AtoTractionCommand3, vobc.AtoTractionCommand2, vobc.AtoTractionCommand1)
|
|
||||||
}
|
}
|
||||||
//return initResult
|
ts, initConn, connErr, tce := s.reportTrainMockInitMsg2(act, pc.TrainConnInitComplate, pc.LineInitTimeStamp, pc.RealTrainPort, train, data[4], data[1])
|
||||||
|
pc.TrainConnInitComplate = initConn
|
||||||
|
pc.LineInitTimeStamp = ts
|
||||||
|
pc.ConnErr = connErr
|
||||||
|
|
||||||
|
train_pc_sim.Default().SendTrainControlMsg2(train, tce, pc.RealTrainPort)
|
||||||
|
if act {
|
||||||
|
trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
|
||||||
|
if vobc.Ato {
|
||||||
|
vobc.AtoStepLevel = trainAtoLevel(vobc.AtoTractionCommand3, vobc.AtoTractionCommand2, vobc.AtoTractionCommand1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
if pc.RealTrainPort == state_proto.TrainState_PORT_A {
|
||||||
|
ts, initConn, connErr, tce := s.reportTrainMockInitMsg2(vobc.Tc1Active, pc.TrainConnInitComplate, pc.LineInitTimeStamp, pc.RealTrainPort, train, data[4], data[1])
|
||||||
|
pc.TrainConnInitComplate = initConn
|
||||||
|
pc.LineInitTimeStamp = ts
|
||||||
|
pc.ConnErr = connErr
|
||||||
|
|
||||||
|
train_pc_sim.Default().SendTrainControlMsg2(train, tce, pc.RealTrainPort)
|
||||||
|
if train.VobcState.Tc1Active {
|
||||||
|
trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
|
||||||
|
if vobc.Ato {
|
||||||
|
vobc.AtoStepLevel = trainAtoLevel(vobc.AtoTractionCommand3, vobc.AtoTractionCommand2, vobc.AtoTractionCommand1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if pc.RealTrainPort == state_proto.TrainState_PORT_B {
|
||||||
|
ts, initConn, connErr, tce := s.reportTrainMockInitMsg2(vobc.Tc2Active, pc.TrainConnInitComplate, pc.LineInitTimeStamp, pc.RealTrainPort, train, data[4], data[1])
|
||||||
|
pc.TrainConnInitComplate = initConn
|
||||||
|
pc.LineInitTimeStamp = ts
|
||||||
|
pc.ConnErr = connErr
|
||||||
|
|
||||||
|
train_pc_sim.Default().SendTrainControlMsg2(train, tce, pc.RealTrainPort)
|
||||||
|
if train.VobcState.Tc2Active {
|
||||||
|
trainPcSimDigitalOutInfoHandleCode7_0(data[4], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode15_8(data[3], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
|
||||||
|
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
|
||||||
|
if vobc.Ato {
|
||||||
|
vobc.AtoStepLevel = trainAtoLevel(vobc.AtoTractionCommand3, vobc.AtoTractionCommand2, vobc.AtoTractionCommand1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
}
|
}
|
||||||
func trainPcSimDigitalOutInfoHandleCode39_32(d byte, vobc *state_proto.TrainVobcState) {
|
func trainPcSimDigitalOutInfoHandleCode39_32(d byte, vobc *state_proto.TrainVobcState) {
|
||||||
@ -840,7 +926,7 @@ func (s *VerifySimulation) TrainPcSimMockInfo(train *state_proto.TrainState, dat
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 4.4.4. 车载输出BTM查询同步帧报文内容(0x04)
|
// 4.4.4. 车载输出BTM查询同步帧报文内容(0x04)
|
||||||
func (s *VerifySimulation) TrainBtmQuery2(train *state_proto.TrainState, data []byte) {
|
func (s *VerifySimulation) TrainBtmQuery2(train *state_proto.TrainState, data []byte, trainClientPort state_proto.TrainState_TrainPort) {
|
||||||
|
|
||||||
ts := time.Now().UnixMilli()
|
ts := time.Now().UnixMilli()
|
||||||
if len(data) < 12 {
|
if len(data) < 12 {
|
||||||
@ -856,35 +942,39 @@ func (s *VerifySimulation) TrainBtmQuery2(train *state_proto.TrainState, data []
|
|||||||
}
|
}
|
||||||
var balise *state_proto.BTMState
|
var balise *state_proto.BTMState
|
||||||
var dsn, bc, mc byte
|
var dsn, bc, mc byte
|
||||||
if atpReq.IsResend() {
|
btmCache := train.BtmBaliseCacheA
|
||||||
balise, dsn, bc, mc = can_btm.Default().FindBaliseResend(train)
|
if train.TrainPort != trainClientPort {
|
||||||
} else {
|
btmCache = train.BtmBaliseCacheB
|
||||||
balise, dsn, bc, mc = can_btm.Default().FindBaliseByNotSend(train)
|
}
|
||||||
|
|
||||||
|
if atpReq.IsResend() {
|
||||||
|
balise, dsn, bc, mc = can_btm.FindBaliseResend(btmCache, true)
|
||||||
|
} else {
|
||||||
|
balise, dsn, bc, mc = can_btm.FindBaliseByNotSend(btmCache, true)
|
||||||
}
|
}
|
||||||
balise, dsn, bc, mc = can_btm.Default().FindBaliseByNotSend(train)
|
|
||||||
cl := clock(atpReq)
|
cl := clock(atpReq)
|
||||||
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, balise, atpReq, cl, dsn, bc, mc)
|
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, balise, atpReq, cl, dsn, bc, mc)
|
||||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
|
||||||
timeSyncF.T2 = cl.BtmTk
|
timeSyncF.T2 = cl.BtmTk
|
||||||
timeSyncF.T3 = cl.TkNow()
|
timeSyncF.T3 = cl.TkNow()
|
||||||
if balise == nil {
|
if balise == nil {
|
||||||
queryData := make([]byte, 0)
|
queryData := createLine12EmptyBaliseData(btmRepFrame, timeSyncF)
|
||||||
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
|
sendLine12EmptyBaliseData(train, trainClientPort, queryData)
|
||||||
queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
|
|
||||||
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
|
|
||||||
//slog.Info(fmt.Sprintf("接受应答器查询:%x发送无应答器数据,id:%v,数据:%X", data, trainAtm.CanId.ID4, queryData))
|
//slog.Info(fmt.Sprintf("接受应答器查询:%x发送无应答器数据,id:%v,数据:%X", data, trainAtm.CanId.ID4, queryData))
|
||||||
} else {
|
} else {
|
||||||
logstr := ""
|
logstr := ""
|
||||||
if atpReq.IsResend() {
|
if atpReq.IsResend() {
|
||||||
logstr = fmt.Sprintf("准备重新发送应答id:%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v,接受应答器报文:%X", balise.BaliseId, ts, time.Now().UnixMilli(), balise.Telegram, bc, mc, data)
|
logstr = fmt.Sprintf("准备重新发送应答id:%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v,接受应答器报文:%X clientPoret:%v trainPort:%v", balise.BaliseId, ts, time.Now().UnixMilli(), balise.Telegram, bc, mc, data, trainClientPort.String(), train.TrainPort.String())
|
||||||
|
|
||||||
} else if !balise.IsSend {
|
} else if !balise.IsSend {
|
||||||
balise.IsSend = true
|
balise.IsSend = true
|
||||||
logstr = fmt.Sprintf("准备发送应答id:%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v,接受应答器报文:%X", balise.BaliseId, ts, time.Now().UnixMilli(), balise.Telegram, bc, mc, data)
|
logstr = fmt.Sprintf("准备发送应答id:%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v,接受应答器报文:%X clientPoret:%v trainPort:%v", balise.BaliseId, ts, time.Now().UnixMilli(), balise.Telegram, bc, mc, data, trainClientPort.String(), train.TrainPort.String())
|
||||||
} else {
|
} /*else {
|
||||||
|
queryData := createLine12EmptyBaliseData(btmRepFrame, timeSyncF)
|
||||||
|
sendLine12EmptyBaliseData(train, trainClientPort, queryData)
|
||||||
return
|
return
|
||||||
}
|
}*/
|
||||||
slog.Info(logstr)
|
slog.Info(logstr, trainClientPort.String())
|
||||||
aliseData, _ := hex.DecodeString(balise.Telegram)
|
aliseData, _ := hex.DecodeString(balise.Telegram)
|
||||||
stateRepFrame := btmRepFrame.EncodeBtmAtp()
|
stateRepFrame := btmRepFrame.EncodeBtmAtp()
|
||||||
statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, balise.HasData, cl.BtmTk, cl.BtmTk, cl.BtmTk)
|
statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, balise.HasData, cl.BtmTk, cl.BtmTk, cl.BtmTk)
|
||||||
@ -896,13 +986,24 @@ func (s *VerifySimulation) TrainBtmQuery2(train *state_proto.TrainState, data []
|
|||||||
queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
|
queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
|
||||||
queryData = append(queryData, statusDataCf...) //数据帧包含结束帧
|
queryData = append(queryData, statusDataCf...) //数据帧包含结束帧
|
||||||
balise.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf)
|
balise.BaliseTelegramForPcSimResend = fmt.Sprintf("%X", statusDataCf)
|
||||||
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, queryData)
|
train_pc_sim.Default().SendBaliseData2(train, trainClientPort, message.RECIVE_TRAIN_BTM_HAS_DATA, queryData)
|
||||||
} else {
|
} else {
|
||||||
slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败")
|
slog.Error("列车pc仿真 BtmCanetClient应答帧、数据帧编码失败")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func sendLine12EmptyBaliseData(train *state_proto.TrainState, trainClientPort state_proto.TrainState_TrainPort, emptyBaliseData []byte) {
|
||||||
|
train_pc_sim.Default().SendBaliseData2(train, trainClientPort, message.RECIVE_TRAIN_BTM_NOT_DATA, emptyBaliseData)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createLine12EmptyBaliseData(btmRepFrame *message.BtmStatusRspFrame, timeSyncFrame *message.BtmTimeSyncCheckFrame) []byte {
|
||||||
|
queryData := make([]byte, 0)
|
||||||
|
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
|
||||||
|
queryData = append(queryData, timeSyncFrame.EncodeBtmAtp().Encode()...)
|
||||||
|
return queryData
|
||||||
|
}
|
||||||
|
|
||||||
func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *message.AtpRequestFrame, cl can_btm.BtmClock, dsn, baliseCount, messageCount byte) *message.BtmStatusRspFrame {
|
func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *message.AtpRequestFrame, cl can_btm.BtmClock, dsn, baliseCount, messageCount byte) *message.BtmStatusRspFrame {
|
||||||
statusF := message.NewBtmStatusRspFrame(canIdSn)
|
statusF := message.NewBtmStatusRspFrame(canIdSn)
|
||||||
statusF.PowerAmplifierOn = true
|
statusF.PowerAmplifierOn = true
|
||||||
@ -917,8 +1018,6 @@ func createBtmStatus(canIdSn byte, btmState *state_proto.BTMState, atpReq *messa
|
|||||||
if btmState != nil && btmState.AboveBalise {
|
if btmState != nil && btmState.AboveBalise {
|
||||||
statusF.DetailedCode = 0x07
|
statusF.DetailedCode = 0x07
|
||||||
}
|
}
|
||||||
|
|
||||||
//btmState.DataSerialNumber = uint32(dsn)
|
|
||||||
statusF.Dsn = dsn
|
statusF.Dsn = dsn
|
||||||
return statusF
|
return statusF
|
||||||
}
|
}
|
||||||
@ -932,11 +1031,11 @@ func (s *VerifySimulation) ObtainTrainDigitalMockDataForStatus(train *state_prot
|
|||||||
vs := train.VobcState
|
vs := train.VobcState
|
||||||
|
|
||||||
if vs.Tc1Active || vs.Tc2Active {
|
if vs.Tc1Active || vs.Tc2Active {
|
||||||
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.KEY_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //钥匙激活
|
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.KEY_STATE, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //钥匙激活
|
||||||
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DRIVER_ACTIVE_REPORT, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性
|
//msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DRIVER_ACTIVE_REPORT, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性
|
||||||
} else {
|
} /* else {
|
||||||
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DRIVER_ACTIVE_REPORT, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性
|
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DRIVER_ACTIVE_REPORT, 0}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车完整性
|
||||||
}
|
}*/
|
||||||
if vs.BrakeForce == 0 {
|
if vs.BrakeForce == 0 {
|
||||||
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.HANDLE_TO_ZERO, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车制动状态
|
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.HANDLE_TO_ZERO, 1}, Type: message.SENDER_TRAIN_OUTR_INFO}) //列车制动状态
|
||||||
}
|
}
|
||||||
@ -1016,6 +1115,6 @@ func (s *VerifySimulation) ObtainTrainDigitalMockData(train *state_proto.TrainSt
|
|||||||
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_AA, modeAA}, Type: message.SENDER_TRAIN_OUTR_INFO})
|
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_AA, modeAA}, Type: message.SENDER_TRAIN_OUTR_INFO})
|
||||||
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_AM, modeAM}, Type: message.SENDER_TRAIN_OUTR_INFO})
|
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_AM, modeAM}, Type: message.SENDER_TRAIN_OUTR_INFO})
|
||||||
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_MM, modeMM}, Type: message.SENDER_TRAIN_OUTR_INFO})
|
msgArr = append(msgArr, message.TrainPcSimBaseMessage{Data: []byte{message.DOOR_MODE_MM, modeMM}, Type: message.SENDER_TRAIN_OUTR_INFO})
|
||||||
train.BtmState = nil
|
|
||||||
return msgArr
|
return msgArr
|
||||||
}
|
}
|
||||||
|
@ -2,9 +2,9 @@ package ts
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"joylink.club/bj-rtsts-server/service"
|
||||||
"joylink.club/bj-rtsts-server/third_party/acc"
|
"joylink.club/bj-rtsts-server/third_party/acc"
|
||||||
axleBeijing12 "joylink.club/bj-rtsts-server/third_party/axle_device/beijing12"
|
axleBeijing12 "joylink.club/bj-rtsts-server/third_party/axle_device/beijing12"
|
||||||
"joylink.club/bj-rtsts-server/third_party/btm_vobc"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/interlock/beijing11"
|
"joylink.club/bj-rtsts-server/third_party/interlock/beijing11"
|
||||||
"joylink.club/bj-rtsts-server/third_party/interlock/beijing12"
|
"joylink.club/bj-rtsts-server/third_party/interlock/beijing12"
|
||||||
"joylink.club/bj-rtsts-server/third_party/radar"
|
"joylink.club/bj-rtsts-server/third_party/radar"
|
||||||
@ -51,6 +51,7 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRun
|
|||||||
return "", sys_error.New("一套环境同时只能运行一个仿真")
|
return "", sys_error.New("一套环境同时只能运行一个仿真")
|
||||||
}
|
}
|
||||||
if !e {
|
if !e {
|
||||||
|
project := service.QueryProject(projectId)
|
||||||
verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig)
|
verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -68,6 +69,7 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRun
|
|||||||
verifySimulation.World.Close()
|
verifySimulation.World.Close()
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
verifySimulation.ProjectCode = project.Code
|
||||||
simulationMap.Store(simulationId, verifySimulation)
|
simulationMap.Store(simulationId, verifySimulation)
|
||||||
// verifySimulation.Start()
|
// verifySimulation.Start()
|
||||||
// 全部成功,启动仿真
|
// 全部成功,启动仿真
|
||||||
@ -148,7 +150,7 @@ func runThirdParty(s *memory.VerifySimulation) error {
|
|||||||
acc.Default().Start(s)
|
acc.Default().Start(s)
|
||||||
train_pc_sim.Default().Start(s)
|
train_pc_sim.Default().Start(s)
|
||||||
//btm vobc
|
//btm vobc
|
||||||
btm_vobc.Default().Start(s)
|
semi_physical_train.BtmDefault().Start(s)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,7 +169,7 @@ func stopThirdParty(s *memory.VerifySimulation) {
|
|||||||
//列车PC仿真停止
|
//列车PC仿真停止
|
||||||
train_pc_sim.Default().Stop()
|
train_pc_sim.Default().Stop()
|
||||||
|
|
||||||
btm_vobc.Default().Stop()
|
semi_physical_train.BtmDefault().Stop()
|
||||||
// 停止动力学接口功能
|
// 停止动力学接口功能
|
||||||
dynamics.Default().Stop()
|
dynamics.Default().Stop()
|
||||||
// 联锁启动
|
// 联锁启动
|
||||||
|
@ -36,3 +36,7 @@ func (r *Reader) ReadBytes(n int) []byte {
|
|||||||
r.Read(b)
|
r.Read(b)
|
||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (r *Reader) Len() int {
|
||||||
|
return r.r.Len()
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user