2023-07-31 08:41:42 +08:00
|
|
|
package simulation
|
|
|
|
|
|
|
|
import (
|
2023-08-23 15:33:07 +08:00
|
|
|
"encoding/binary"
|
2023-10-12 10:10:23 +08:00
|
|
|
"log/slog"
|
2023-09-05 15:12:11 +08:00
|
|
|
"math"
|
2023-09-12 10:00:13 +08:00
|
|
|
"time"
|
2023-08-03 10:41:43 +08:00
|
|
|
|
2023-09-21 14:54:27 +08:00
|
|
|
"joylink.club/rtsssimulation/repository/model/proto"
|
|
|
|
|
2023-08-07 14:08:02 +08:00
|
|
|
"fmt"
|
2023-08-10 14:18:55 +08:00
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
"sync"
|
|
|
|
|
2023-08-02 15:47:48 +08:00
|
|
|
"joylink.club/bj-rtsts-server/ats/verify/protos/state"
|
2023-09-12 10:00:13 +08:00
|
|
|
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/memory"
|
2023-08-03 10:41:43 +08:00
|
|
|
"joylink.club/bj-rtsts-server/config"
|
2023-08-02 15:47:48 +08:00
|
|
|
"joylink.club/bj-rtsts-server/dynamics"
|
2023-08-18 16:20:40 +08:00
|
|
|
"joylink.club/bj-rtsts-server/vobc"
|
2023-07-31 08:41:42 +08:00
|
|
|
|
2023-08-01 14:54:11 +08:00
|
|
|
"joylink.club/bj-rtsts-server/dto"
|
2023-07-31 08:41:42 +08:00
|
|
|
)
|
|
|
|
|
2023-08-02 15:47:48 +08:00
|
|
|
func init() {
|
2023-08-23 15:33:07 +08:00
|
|
|
// vobc 发来的列车信息
|
|
|
|
vobc.RegisterTrainInfoHandler(func(info []byte) {
|
|
|
|
for _, simulation := range GetSimulationArr() {
|
2023-08-25 15:35:00 +08:00
|
|
|
simulation.Memory.Status.TrainStateMap.Range(func(_, value any) bool {
|
2023-08-23 15:33:07 +08:00
|
|
|
train := value.(*state.TrainState)
|
2023-08-31 16:16:18 +08:00
|
|
|
if !train.Show { // 下线列车
|
|
|
|
return false
|
2023-08-23 15:33:07 +08:00
|
|
|
}
|
2023-08-31 16:16:18 +08:00
|
|
|
// 拼接列车ID
|
|
|
|
trainId, err := strconv.Atoi(train.Id)
|
|
|
|
if err != nil {
|
|
|
|
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
|
|
|
|
}
|
|
|
|
trainInfo := decoderVobcTrainState(info)
|
2023-09-07 16:04:55 +08:00
|
|
|
d := append(info, uint8(trainId))
|
2023-08-31 16:16:18 +08:00
|
|
|
// 发送给动力学
|
2023-09-07 16:04:55 +08:00
|
|
|
dynamics.SendDynamicsTrainMsg(d)
|
2023-08-31 16:16:18 +08:00
|
|
|
// 存放至列车中
|
|
|
|
train.VobcState = trainInfo
|
|
|
|
return true
|
2023-08-23 15:33:07 +08:00
|
|
|
})
|
|
|
|
}
|
2023-08-18 16:20:40 +08:00
|
|
|
})
|
2023-08-02 15:47:48 +08:00
|
|
|
dynamics.RegisterTrainInfoHandler(func(info *dynamics.TrainInfo) {
|
|
|
|
for _, simulation := range GetSimulationArr() {
|
|
|
|
sta, ok := simulation.Memory.Status.TrainStateMap.Load(strconv.Itoa(int(info.Number)))
|
2023-08-31 16:16:18 +08:00
|
|
|
if !ok {
|
|
|
|
continue
|
2023-08-02 15:47:48 +08:00
|
|
|
}
|
2023-08-31 16:16:18 +08:00
|
|
|
trainState := sta.(*state.TrainState)
|
|
|
|
// 给半实物仿真发送速度
|
2023-10-16 14:52:58 +08:00
|
|
|
vobc.SendTrainSpeedTask(convertVobc(info))
|
2023-08-31 16:16:18 +08:00
|
|
|
// 更新列车状态
|
|
|
|
memory.UpdateTrainState(simulation, convert(info, trainState, simulation))
|
2023-08-02 15:47:48 +08:00
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2023-07-31 08:41:42 +08:00
|
|
|
// 仿真存储集合
|
2023-08-01 14:54:11 +08:00
|
|
|
var simulationMap sync.Map
|
2023-07-31 08:41:42 +08:00
|
|
|
|
2023-08-30 18:05:11 +08:00
|
|
|
// 创建前检查
|
|
|
|
func IsExistSimulation() bool {
|
|
|
|
i := 0
|
|
|
|
simulationMap.Range(func(_, _ any) bool {
|
|
|
|
i++
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
return i > 0
|
|
|
|
}
|
|
|
|
|
2023-07-31 08:41:42 +08:00
|
|
|
// 创建仿真对象
|
2023-09-19 11:02:50 +08:00
|
|
|
func CreateSimulation(projectId int32, mapIds []int32) string {
|
|
|
|
simulationId := createSimulationId(projectId)
|
2023-08-01 14:54:11 +08:00
|
|
|
_, e := simulationMap.Load(simulationId)
|
2023-09-01 10:25:27 +08:00
|
|
|
if !e && IsExistSimulation() {
|
|
|
|
panic(dto.ErrorDto{Code: dto.DataAlreadyExist, Message: "已有仿真在运行"})
|
|
|
|
}
|
2023-08-01 14:54:11 +08:00
|
|
|
if !e {
|
2023-09-20 15:14:40 +08:00
|
|
|
verifySimulation, err := memory.CreateSimulation(projectId, mapIds)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Sprintf("创建仿真失败:%s", err.Error()))
|
2023-09-19 11:02:50 +08:00
|
|
|
}
|
2023-09-20 15:14:40 +08:00
|
|
|
verifySimulation.SimulationId = simulationId
|
2023-08-09 15:34:19 +08:00
|
|
|
//通知动力学
|
2023-10-07 15:59:22 +08:00
|
|
|
lineBaseInfo := buildLineBaseInfo(verifySimulation)
|
|
|
|
httpCode, _, err := dynamics.SendSimulationStartReq(lineBaseInfo)
|
|
|
|
if httpCode != http.StatusOK || err != nil {
|
|
|
|
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: fmt.Sprintf("动力学接口调用失败:[%d][%s]", httpCode, err)})
|
|
|
|
}
|
2023-08-01 14:54:11 +08:00
|
|
|
simulationMap.Store(simulationId, verifySimulation)
|
2023-10-07 15:59:22 +08:00
|
|
|
dynamicsRun(verifySimulation)
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
return simulationId
|
|
|
|
}
|
|
|
|
|
|
|
|
// 删除仿真对象
|
|
|
|
func DestroySimulation(simulationId string) {
|
2023-09-21 14:54:27 +08:00
|
|
|
s, e := simulationMap.Load(simulationId)
|
|
|
|
if !e {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
simulationInfo := s.(*memory.VerifySimulation)
|
2023-08-25 17:49:09 +08:00
|
|
|
simulationMap.Delete(simulationId)
|
2023-09-21 14:54:27 +08:00
|
|
|
// 停止ecs world
|
2023-09-28 17:28:20 +08:00
|
|
|
simulationInfo.World.Close()
|
|
|
|
//ecsSimulation.DestroySimulation(simulationInfo.WorldId)
|
2023-08-02 15:47:48 +08:00
|
|
|
//移除道岔状态发送
|
2023-08-09 15:34:19 +08:00
|
|
|
dynamics.Stop()
|
2023-08-07 14:08:02 +08:00
|
|
|
//通知动力学
|
|
|
|
httpCode, _, err := dynamics.SendSimulationEndReq()
|
2023-09-26 14:12:26 +08:00
|
|
|
if httpCode != http.StatusOK {
|
2023-09-12 10:00:13 +08:00
|
|
|
panic(dto.ErrorDto{Code: dto.DynamicsError, Message: fmt.Sprintf("动力学接口调用失败:[%d][%s]", httpCode, err)})
|
2023-08-07 14:08:02 +08:00
|
|
|
}
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
|
2023-09-19 11:02:50 +08:00
|
|
|
func createSimulationId(projectId int32) string {
|
|
|
|
// 当前服务器IP + 端口 + 项目
|
|
|
|
return config.SimulationId_prefix + "_" + strconv.Itoa(config.Config.Server.Port) + "_" + strconv.Itoa(int(projectId))
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 获取仿真列表
|
2023-08-30 13:25:57 +08:00
|
|
|
func ListAllSimulations() []*dto.SimulationInfoRspDto {
|
2023-08-31 16:16:18 +08:00
|
|
|
var simArr []*dto.SimulationInfoRspDto
|
2023-08-25 15:35:00 +08:00
|
|
|
simulationMap.Range(func(_, v any) bool {
|
2023-08-01 14:54:11 +08:00
|
|
|
s := v.(*memory.VerifySimulation)
|
2023-08-30 13:25:57 +08:00
|
|
|
simArr = append(simArr, &dto.SimulationInfoRspDto{
|
2023-08-01 14:54:11 +08:00
|
|
|
SimulationId: s.SimulationId,
|
2023-09-19 11:02:50 +08:00
|
|
|
MapId: s.MapIds[0],
|
|
|
|
MapIds: s.MapIds,
|
2023-08-30 13:25:57 +08:00
|
|
|
ProjectId: s.ProjectId,
|
2023-08-01 14:54:11 +08:00
|
|
|
})
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
return simArr
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// 根据仿真id查找仿真实例
|
2023-08-01 14:54:11 +08:00
|
|
|
func FindSimulation(simulationId string) *memory.VerifySimulation {
|
|
|
|
m, e := simulationMap.Load(simulationId)
|
|
|
|
if e {
|
|
|
|
return m.(*memory.VerifySimulation)
|
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// 获取普通仿真数组
|
|
|
|
func GetSimulationArr() []*memory.VerifySimulation {
|
2023-08-31 16:16:18 +08:00
|
|
|
var result []*memory.VerifySimulation
|
2023-08-25 15:35:00 +08:00
|
|
|
simulationMap.Range(func(_, v any) bool {
|
2023-08-01 14:54:11 +08:00
|
|
|
result = append(result, v.(*memory.VerifySimulation))
|
|
|
|
return true
|
|
|
|
})
|
|
|
|
return result
|
2023-07-31 08:41:42 +08:00
|
|
|
}
|
2023-08-07 14:08:02 +08:00
|
|
|
|
2023-08-24 18:22:25 +08:00
|
|
|
func convert(info *dynamics.TrainInfo, sta *state.TrainState, simulation *memory.VerifySimulation) *state.TrainState {
|
2023-10-18 16:41:41 +08:00
|
|
|
if sta.VobcState.LifeSignal == int32(info.VobcLifeSignal) {
|
2023-10-18 14:56:24 +08:00
|
|
|
sta.ControlDelayTime = time.Now().UnixMilli() - sta.VobcState.UpdateTime
|
2023-10-18 16:41:41 +08:00
|
|
|
if sta.ControlDelayTime > memory.DelayMaxTime {
|
|
|
|
sta.ControlDelayTime = memory.DelayMaxTime
|
|
|
|
}
|
2023-10-18 08:50:53 +08:00
|
|
|
} else {
|
2023-10-18 16:41:41 +08:00
|
|
|
sta.ControlDelayTime = memory.DelayMaxTime
|
2023-10-17 18:19:31 +08:00
|
|
|
}
|
2023-10-12 10:10:23 +08:00
|
|
|
slog.Debug("收到动力学原始消息", "Number", info.Number, "Link", info.Link, "LinkOffset", info.LinkOffset)
|
2023-09-20 18:21:00 +08:00
|
|
|
id, port, offset, runDirection, pointTo, kilometer := memory.QueryDeviceByCalcLink(simulation.Repo, strconv.Itoa(int(info.Link)), int64(info.LinkOffset), info.Up)
|
2023-10-12 10:10:23 +08:00
|
|
|
slog.Debug("处理动力学转换后的消息", "number", info.Number,
|
|
|
|
"车头位置", id, "偏移", offset, "是否上行", runDirection, "是否ab", pointTo)
|
2023-09-27 18:11:16 +08:00
|
|
|
sta.HeadDeviceId = simulation.GetComIdByUid(id)
|
2023-09-20 18:21:00 +08:00
|
|
|
sta.DevicePort = port
|
|
|
|
sta.HeadOffset = offset
|
|
|
|
sta.PointTo = pointTo
|
|
|
|
sta.TrainKilometer = kilometer
|
|
|
|
sta.RunDirection = runDirection
|
|
|
|
//判定车头方向
|
|
|
|
sta.HeadDirection = runDirection
|
|
|
|
if sta.VobcState != nil {
|
|
|
|
if sta.VobcState.DirectionForward {
|
|
|
|
sta.HeadDirection = runDirection
|
|
|
|
} else if sta.VobcState.DirectionBackward {
|
|
|
|
sta.HeadDirection = !runDirection
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if info.Speed < 0 {
|
|
|
|
sta.RunDirection = !sta.RunDirection
|
|
|
|
}
|
|
|
|
// 赋值动力学信息
|
|
|
|
sta.DynamicState.Heartbeat = int32(info.LifeSignal)
|
|
|
|
sta.DynamicState.HeadLinkId = strconv.Itoa(int(info.Link))
|
|
|
|
sta.DynamicState.HeadLinkOffset = int64(info.LinkOffset)
|
|
|
|
sta.DynamicState.Slope = int32(info.Slope)
|
|
|
|
sta.DynamicState.Upslope = info.UpSlope
|
|
|
|
sta.DynamicState.RunningUp = info.Up
|
|
|
|
sta.DynamicState.RunningResistanceSum = float32(info.TotalResistance) / 1000
|
|
|
|
sta.DynamicState.AirResistance = float32(info.AirResistance) / 1000
|
|
|
|
sta.DynamicState.RampResistance = float32(info.SlopeResistance) / 1000
|
|
|
|
sta.DynamicState.CurveResistance = float32(info.CurveResistance) / 1000
|
|
|
|
sta.DynamicState.Speed = speedParse(info.Speed)
|
|
|
|
sta.DynamicState.HeadSensorSpeed1 = speedParse(info.HeadSpeed1)
|
|
|
|
sta.DynamicState.HeadSensorSpeed2 = speedParse(info.HeadSpeed2)
|
|
|
|
sta.DynamicState.TailSensorSpeed1 = speedParse(info.TailSpeed1)
|
|
|
|
sta.DynamicState.TailSensorSpeed2 = speedParse(info.TailSpeed2)
|
|
|
|
sta.DynamicState.HeadRadarSpeed = speedParse(info.HeadRadarSpeed)
|
|
|
|
sta.DynamicState.TailRadarSpeed = speedParse(info.TailRadarSpeed)
|
2023-10-07 17:00:39 +08:00
|
|
|
sta.DynamicState.Acceleration = info.Acceleration
|
2023-08-10 14:18:55 +08:00
|
|
|
return sta
|
2023-08-07 14:08:02 +08:00
|
|
|
}
|
|
|
|
|
2023-10-16 14:52:58 +08:00
|
|
|
// 转换成Vobc发送参数
|
|
|
|
func convertVobc(info *dynamics.TrainInfo) *vobc.SendTrainInfo {
|
|
|
|
param := &vobc.SendTrainInfo{
|
|
|
|
Speed: uint16(math.Abs(float64(info.Speed * 36))),
|
|
|
|
Upslope: info.UpSlope,
|
|
|
|
Slope: uint16(info.Slope),
|
2023-10-16 17:37:27 +08:00
|
|
|
TotalResistance: uint32(math.Abs(float64(info.TotalResistance / 10))),
|
2023-10-16 15:48:58 +08:00
|
|
|
AirResistance: uint32(info.AirResistance / 10),
|
|
|
|
SlopeResistance: uint32(math.Abs(float64(info.SlopeResistance / 10))),
|
|
|
|
CurveResistance: uint32(info.CurveResistance / 10),
|
2023-10-16 14:52:58 +08:00
|
|
|
}
|
2023-10-16 15:24:04 +08:00
|
|
|
d := math.Abs(float64(info.Acceleration * 100))
|
|
|
|
if info.Acceleration > 0 {
|
|
|
|
param.Acceleration = uint8(d)
|
|
|
|
} else {
|
|
|
|
param.Deceleration = uint8(d)
|
|
|
|
}
|
2023-10-16 14:52:58 +08:00
|
|
|
return param
|
|
|
|
}
|
|
|
|
|
2023-08-09 15:34:19 +08:00
|
|
|
func dynamicsRun(verifySimulation *memory.VerifySimulation) {
|
|
|
|
_ = dynamics.Run(func() []*dynamics.TurnoutInfo {
|
2023-08-07 14:08:02 +08:00
|
|
|
stateSlice := memory.GetAllTurnoutState(verifySimulation)
|
|
|
|
var turnoutInfoSlice []*dynamics.TurnoutInfo
|
|
|
|
for _, sta := range stateSlice {
|
2023-09-25 17:32:38 +08:00
|
|
|
code64, err := strconv.ParseUint(sta.Id, 10, 16)
|
2023-08-07 14:08:02 +08:00
|
|
|
if err != nil {
|
2023-10-12 10:10:23 +08:00
|
|
|
slog.Error("id转uint16报错", err)
|
2023-08-07 14:08:02 +08:00
|
|
|
}
|
|
|
|
info := dynamics.TurnoutInfo{
|
|
|
|
Code: uint16(code64),
|
2023-10-07 15:59:22 +08:00
|
|
|
NPosition: sta.Dw,
|
|
|
|
RPosition: sta.Fw,
|
2023-08-07 14:08:02 +08:00
|
|
|
}
|
|
|
|
turnoutInfoSlice = append(turnoutInfoSlice, &info)
|
|
|
|
}
|
|
|
|
return turnoutInfoSlice
|
|
|
|
})
|
|
|
|
}
|
2023-08-09 15:34:19 +08:00
|
|
|
|
2023-09-25 17:05:17 +08:00
|
|
|
func buildLineBaseInfo(sim *memory.VerifySimulation) *dynamics.LineBaseInfo {
|
2023-09-20 15:14:40 +08:00
|
|
|
info := &dynamics.LineBaseInfo{}
|
2023-09-25 17:05:17 +08:00
|
|
|
for _, model := range sim.Repo.LinkList() {
|
2023-09-20 15:14:40 +08:00
|
|
|
id, _ := strconv.Atoi(model.Id())
|
|
|
|
link := &dynamics.Link{
|
|
|
|
ID: int32(id),
|
|
|
|
Len: int32(model.Length()),
|
2023-08-09 15:34:19 +08:00
|
|
|
}
|
2023-09-20 15:14:40 +08:00
|
|
|
info.LinkList = append(info.LinkList, link)
|
|
|
|
if model.ARelation() != nil {
|
2023-09-25 17:05:17 +08:00
|
|
|
turnoutId, _ := strconv.Atoi(sim.GetComIdByUid(model.ARelation().Device().Id()))
|
2023-09-20 15:14:40 +08:00
|
|
|
link.ARelTurnoutId = int32(turnoutId)
|
|
|
|
switch model.ARelation().Port() {
|
|
|
|
case proto.Port_A:
|
|
|
|
link.ARelTurnoutPoint = "A"
|
|
|
|
case proto.Port_B:
|
|
|
|
link.ARelTurnoutPoint = "B"
|
|
|
|
case proto.Port_C:
|
|
|
|
link.ARelTurnoutPoint = "C"
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if model.BRelation() != nil {
|
2023-09-25 17:05:17 +08:00
|
|
|
turnoutId, _ := strconv.Atoi(sim.GetComIdByUid(model.BRelation().Device().Id()))
|
2023-09-20 15:14:40 +08:00
|
|
|
link.BRelTurnoutId = int32(turnoutId)
|
|
|
|
switch model.BRelation().Port() {
|
|
|
|
case proto.Port_A:
|
|
|
|
link.BRelTurnoutPoint = "A"
|
|
|
|
case proto.Port_B:
|
|
|
|
link.BRelTurnoutPoint = "B"
|
|
|
|
case proto.Port_C:
|
|
|
|
link.BRelTurnoutPoint = "C"
|
|
|
|
}
|
2023-08-09 15:34:19 +08:00
|
|
|
}
|
|
|
|
}
|
2023-09-25 17:05:17 +08:00
|
|
|
for _, model := range sim.Repo.SlopeList() {
|
|
|
|
id, _ := strconv.Atoi(sim.GetComIdByUid(model.Id()))
|
2023-09-20 15:14:40 +08:00
|
|
|
slope := &dynamics.Slope{
|
2023-09-06 10:26:26 +08:00
|
|
|
ID: int32(id),
|
2023-09-20 15:14:40 +08:00
|
|
|
StartLinkOffset: int32(model.StartLinkPosition().Offset()),
|
|
|
|
EndLinkOffset: int32(model.EndLinkPosition().Offset()),
|
|
|
|
DegreeTrig: model.Degree(),
|
|
|
|
}
|
|
|
|
info.SlopeList = append(info.SlopeList, slope)
|
|
|
|
startLinkId, _ := strconv.Atoi(model.StartLinkPosition().Link().Id())
|
|
|
|
slope.StartLinkId = int32(startLinkId)
|
|
|
|
endLinkId, _ := strconv.Atoi(model.EndLinkPosition().Link().Id())
|
|
|
|
slope.EndLinkId = int32(endLinkId)
|
2023-09-06 10:26:26 +08:00
|
|
|
}
|
2023-09-25 17:05:17 +08:00
|
|
|
for _, model := range sim.Repo.SectionalCurvatureList() {
|
|
|
|
id, _ := strconv.Atoi(sim.GetComIdByUid(model.Id()))
|
2023-09-20 15:14:40 +08:00
|
|
|
curve := &dynamics.Curve{
|
2023-09-06 10:26:26 +08:00
|
|
|
ID: int32(id),
|
2023-09-20 15:14:40 +08:00
|
|
|
StartLinkOffset: int32(model.StartLinkPosition().Offset()),
|
|
|
|
EndLinkOffset: int32(model.EndLinkPosition().Offset()),
|
|
|
|
Curvature: model.Radius(),
|
|
|
|
}
|
|
|
|
info.CurveList = append(info.CurveList, curve)
|
|
|
|
startLinkId, _ := strconv.Atoi(model.StartLinkPosition().Link().Id())
|
|
|
|
curve.StartLinkId = int32(startLinkId)
|
|
|
|
endLinkId, _ := strconv.Atoi(model.EndLinkPosition().Link().Id())
|
|
|
|
curve.EndLinkId = int32(endLinkId)
|
2023-08-09 15:34:19 +08:00
|
|
|
}
|
2023-09-20 15:14:40 +08:00
|
|
|
return info
|
2023-08-09 15:34:19 +08:00
|
|
|
}
|
2023-08-23 15:33:07 +08:00
|
|
|
|
|
|
|
// 解析VOBC列车信息
|
|
|
|
func decoderVobcTrainState(buf []byte) *state.TrainVobcState {
|
|
|
|
trainVobcInfo := &state.TrainVobcState{}
|
|
|
|
trainVobcInfo.LifeSignal = int32(binary.BigEndian.Uint16(buf[0:2]))
|
|
|
|
b2 := buf[2]
|
2023-08-25 10:41:13 +08:00
|
|
|
trainVobcInfo.Tc1Active = (b2 & 1) != 0
|
|
|
|
trainVobcInfo.Tc2Active = (b2 & (1 << 1)) != 0
|
|
|
|
trainVobcInfo.DirectionForward = (b2 & (1 << 2)) != 0
|
|
|
|
trainVobcInfo.DirectionBackward = (b2 & (1 << 3)) != 0
|
|
|
|
trainVobcInfo.TractionStatus = (b2 & (1 << 4)) != 0
|
|
|
|
trainVobcInfo.BrakingStatus = (b2 & (1 << 5)) != 0
|
|
|
|
trainVobcInfo.EmergencyBrakingStatus = (b2 & (1 << 6)) != 0
|
|
|
|
trainVobcInfo.TurnbackStatus = (b2 & 7) != 0
|
2023-08-23 15:33:07 +08:00
|
|
|
b3 := buf[3]
|
2023-08-25 10:41:13 +08:00
|
|
|
trainVobcInfo.JumpStatus = (b3 & 1) != 0
|
|
|
|
trainVobcInfo.Ato = (b3 & (1 << 1)) != 0
|
|
|
|
trainVobcInfo.Fam = (b3 & (1 << 2)) != 0
|
|
|
|
trainVobcInfo.Cam = (b3 & (1 << 3)) != 0
|
|
|
|
trainVobcInfo.TractionSafetyCircuit = (b3 & (1 << 4)) != 0
|
|
|
|
trainVobcInfo.ParkingBrakeStatus = (b3 & (1 << 5)) != 0
|
|
|
|
trainVobcInfo.MaintainBrakeStatus = (b3 & (1 << 6)) != 0
|
2023-09-05 17:11:48 +08:00
|
|
|
trainVobcInfo.TractionForce = int64(binary.BigEndian.Uint16(buf[4:6]))
|
|
|
|
trainVobcInfo.BrakeForce = int64(binary.BigEndian.Uint16(buf[6:8]))
|
|
|
|
trainVobcInfo.TrainLoad = int64(binary.BigEndian.Uint16(buf[8:10]))
|
2023-08-23 15:33:07 +08:00
|
|
|
b4 := buf[15]
|
2023-08-25 10:41:13 +08:00
|
|
|
trainVobcInfo.LeftDoorOpenCommand = (b4 & 1) != 0
|
|
|
|
trainVobcInfo.RightDoorOpenCommand = (b4 & (1 << 1)) != 0
|
|
|
|
trainVobcInfo.LeftDoorCloseCommand = (b4 & (1 << 2)) != 0
|
|
|
|
trainVobcInfo.RightDoorCloseCommand = (b4 & (1 << 3)) != 0
|
|
|
|
trainVobcInfo.AllDoorClose = (b4 & (1 << 4)) != 0
|
2023-10-17 18:19:31 +08:00
|
|
|
trainVobcInfo.UpdateTime = time.Now().UnixMilli()
|
2023-08-23 15:33:07 +08:00
|
|
|
return trainVobcInfo
|
|
|
|
}
|
2023-09-05 15:12:11 +08:00
|
|
|
|
|
|
|
// 发送给前端的速度格式化
|
|
|
|
func speedParse(speed float32) int32 {
|
2023-09-05 16:23:13 +08:00
|
|
|
return int32(math.Abs(float64(speed * 3.6 * 100)))
|
2023-09-05 15:12:11 +08:00
|
|
|
}
|