增加与动力学的http通信;修改udp通信

This commit is contained in:
joylink_zhangsai 2023-08-07 14:08:02 +08:00
parent 39a394be75
commit 2c13ea702c
7 changed files with 273 additions and 110 deletions

View File

@ -2,14 +2,16 @@ package simulation
import (
"net"
"strconv"
"strings"
"sync"
"fmt"
"go.uber.org/zap"
"joylink.club/bj-rtsts-server/ats/verify/protos/state"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/dynamics"
"net/http"
"strconv"
"sync"
"joylink.club/bj-rtsts-server/ats/verify/simulation/wayside/memory"
"joylink.club/bj-rtsts-server/dto"
@ -41,38 +43,9 @@ func init() {
break
}
}
//simulationMap.Range(func(key, value any) bool {
// simulation := value.(*memory.VerifySimulation)
// sta, ok := simulation.Memory.Status.TrainStateMap.Load(strconv.Itoa(int(info.Number)))
// if ok {
// memory.UpdateTrainState(simulation, convert(info, *sta.(*state.TrainState)))
// return false
// }
// return true
//})
})
}
func convert(info *dynamics.TrainInfo, sta state.TrainState) *state.TrainState {
sta.HeadLinkId = strconv.Itoa(int(info.Link))
sta.HeadLinkOffset = int64(info.LinkOffset * 10)
sta.Slope = int32(info.Slope)
sta.Upslope = info.UpSlope
sta.RunningUp = info.Up
sta.RunningResistanceSum = info.TotalResistance
sta.AirResistance = info.AirResistance
sta.RampResistance = info.SlopeResistance
sta.CurveResistance = info.CurveResistance
sta.Speed = info.Speed
sta.HeadSensorSpeed1 = info.HeadSpeed1
sta.HeadSensorSpeed2 = info.HeadSpeed2
sta.TailSensorSpeed1 = info.TailSpeed1
sta.TailSensorSpeed2 = info.TailSpeed2
sta.HeadRadarSpeed = info.HeadRadarSpeed
sta.TailRadarSpeed = info.TailRadarSpeed
return &sta
}
// 仿真存储集合
var simulationMap sync.Map
@ -81,36 +54,29 @@ func CreateSimulation(mapId int32) string {
simulationId := createSimulationId(mapId)
_, e := simulationMap.Load(simulationId)
if !e {
////通知动力学
//httpCode, _, err := dynamics.SendSimulationStartReq()
//if httpCode != http.StatusOK || err != nil {
// panic(dto.ErrorDto{Code: dto.LogicError, Message: fmt.Sprintf("动力学接口调用失败:[%d][%s]", httpCode, err)})
//}
verifySimulation := memory.CreateSimulation(mapId, simulationId)
simulationMap.Store(simulationId, verifySimulation)
//道岔状态发送
dynamics.AddTurnoutInfoFunc(simulationId, func() []*dynamics.TurnoutInfo {
stateSlice := memory.GetAllTurnoutState(verifySimulation)
var turnoutInfoSlice []*dynamics.TurnoutInfo
for _, sta := range stateSlice {
code64, err := strconv.ParseUint(sta.Id, 10, 16)
if err != nil {
zap.S().Error("id转uint16报错", err)
}
info := dynamics.TurnoutInfo{
Code: uint16(code64),
NPosition: sta.Normal,
RPosition: sta.Reverse,
}
turnoutInfoSlice = append(turnoutInfoSlice, &info)
}
return turnoutInfoSlice
})
//
startSendTurnoutInfo(simulationId, verifySimulation)
}
return simulationId
}
// 删除仿真对象
func DestroySimulation(simulationId string) {
simulationMap.Delete(simulationId)
//移除道岔状态发送
dynamics.RemoveTurnoutInfoFunc(simulationId)
dynamics.RemoveTurnoutInfoSource(simulationId)
//通知动力学
httpCode, _, err := dynamics.SendSimulationEndReq()
if httpCode != http.StatusOK || err != nil {
panic(dto.ErrorDto{Code: dto.LogicError, Message: fmt.Sprintf("动力学接口调用失败:[%d][%s]", httpCode, err)})
}
simulationMap.Delete(simulationId)
}
// 创建时生成仿真Id
@ -151,3 +117,43 @@ func GetSimulationArr() []*memory.VerifySimulation {
})
return result
}
func convert(info *dynamics.TrainInfo, sta state.TrainState) *state.TrainState {
sta.HeadLinkId = strconv.Itoa(int(info.Link))
sta.HeadLinkOffset = int64(info.LinkOffset * 10)
sta.Slope = int32(info.Slope)
sta.Upslope = info.UpSlope
sta.RunningUp = info.Up
sta.RunningResistanceSum = float32(info.TotalResistance) / 1000
sta.AirResistance = float32(info.AirResistance) / 1000
sta.RampResistance = float32(info.SlopeResistance) / 1000
sta.CurveResistance = float32(info.CurveResistance) / 1000
sta.Speed = info.Speed * 3.6
sta.HeadSensorSpeed1 = info.HeadSpeed1 * 3.6
sta.HeadSensorSpeed2 = info.HeadSpeed2 * 3.6
sta.TailSensorSpeed1 = info.TailSpeed1 * 3.6
sta.TailSensorSpeed2 = info.TailSpeed2 * 3.6
sta.HeadRadarSpeed = info.HeadRadarSpeed * 3.6
sta.TailRadarSpeed = info.TailRadarSpeed * 3.6
return &sta
}
func startSendTurnoutInfo(simulationId string, verifySimulation *memory.VerifySimulation) {
dynamics.AddTurnoutInfoSource(simulationId, func() []*dynamics.TurnoutInfo {
stateSlice := memory.GetAllTurnoutState(verifySimulation)
var turnoutInfoSlice []*dynamics.TurnoutInfo
for _, sta := range stateSlice {
code64, err := strconv.ParseUint(sta.Id, 10, 16)
if err != nil {
zap.S().Error("id转uint16报错", err)
}
info := dynamics.TurnoutInfo{
Code: uint16(code64),
NPosition: sta.Normal,
RPosition: sta.Reverse,
}
turnoutInfoSlice = append(turnoutInfoSlice, &info)
}
return turnoutInfoSlice
})
}

View File

@ -34,7 +34,7 @@ func AddTrainState(simulation *VerifySimulation, status *state.TrainState) {
Up: status.Up,
})
if err != nil || httpCode != http.StatusOK {
panic(dto.ErrorDto{Code: dto.LogicError, Message: fmt.Sprintf("动力学接口调用失败:%s", err.Error())})
panic(dto.ErrorDto{Code: dto.LogicError, Message: fmt.Sprintf("动力学接口调用失败:[%d][%s]", httpCode, err)})
}
// 将信息合并到当前设备状态中
allTrainMap.Store(status.Id, status)

View File

@ -4,25 +4,14 @@ import (
"bytes"
"encoding/json"
"fmt"
"go.uber.org/zap"
"joylink.club/bj-rtsts-server/config"
"net/http"
)
func SendInitTrainReq(info *InitTrainInfo) (int, *[]byte, error) {
defer func() {
if r := recover(); r != nil {
zap.S().Error("发送列车初始化请求失败", r)
}
}()
ip := config.Config.Dynamics.Ip
var port string
if config.Config.Dynamics.HttpPort != 0 {
port = fmt.Sprintf(":%d", config.Config.Dynamics.HttpPort)
}
uri := "/api/aerodynamics/init/train"
url := "http://" + ip + port + uri
baseUrl := getUrlBase()
uri := "/api/aerodynamics/init/train/"
url := baseUrl + uri
data, _ := json.Marshal(info)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {
@ -37,3 +26,56 @@ func SendInitTrainReq(info *InitTrainInfo) (int, *[]byte, error) {
}
return resp.StatusCode, &buf, resp.Body.Close()
}
func SendSimulationStartReq(base *LineBaseInfo) (int, *[]byte, error) {
baseUrl := getUrlBase()
uri := "/api/start/"
url := baseUrl + uri
data, _ := json.Marshal(base)
resp, err := http.Post(url, "application/json", bytes.NewBuffer(data))
if err != nil {
s := err.Error()
println(s)
return 0, nil, err
}
var buf []byte
_, err = resp.Body.Read(buf)
if err != nil {
return resp.StatusCode, nil, err
}
return resp.StatusCode, &buf, resp.Body.Close()
}
func SendSimulationEndReq() (int, *[]byte, error) {
baseUrl := getUrlBase()
uri := "/api/end"
url := baseUrl + uri
resp, err := http.Post(url, "application/json", nil)
if err != nil {
s := err.Error()
println(s)
return 0, nil, err
}
var buf []byte
_, err = resp.Body.Read(buf)
if err != nil {
return resp.StatusCode, nil, err
}
return resp.StatusCode, &buf, resp.Body.Close()
}
var (
urlBase string
)
func getUrlBase() string {
if urlBase == "" {
ip := config.Config.Dynamics.Ip
var port string
if config.Config.Dynamics.HttpPort != 0 {
port = fmt.Sprintf(":%d", config.Config.Dynamics.HttpPort)
}
urlBase = "http://" + ip + port
}
return urlBase
}

View File

@ -8,3 +8,40 @@ type InitTrainInfo struct {
Speed uint16 `json:"speed"`
Up bool `json:"up"`
}
// LineBaseInfo 线路基础信息,提供给动力学作为计算依据
type LineBaseInfo struct {
LinkList []Link `json:"linkList"`
SlopeList []Slope `json:"slopeList"`
CurveList []Curve `json:"curveList"`
}
type Link struct {
ID int32 `json:"id"`
//长度 mm
Len int32 `json:"len"`
ARelTurnoutId int32 `json:"ARelTurnoutId"`
ARelTurnoutPoint string `json:"ARelTurnoutPoint"`
BRelTurnoutId int32 `json:"BRelTurnoutId"`
BRelTurnoutPoint string `json:"BRelTurnoutPoint"`
}
type Slope struct {
ID int32 `json:"id"`
StartLinkId int32 `json:"startLinkId"`
StartLinkOffset int32 `json:"startLinkOffset"`
EndLinkId int32 `json:"endLinkId"`
EndLinkOffset int32 `json:"endLinkOffset"`
//坡度的三角函数(猜是sin)值的*1000
DegreeTrig int32 `json:"degreeTrig"`
}
type Curve struct {
int
ID int32 `json:"id"`
StartLinkId int32 `json:"startLinkId"`
StartLinkOffset int32 `json:"startLinkOffset"`
EndLinkId int32 `json:"endLinkId"`
EndLinkOffset int32 `json:"endLinkOffset"`
Curvature int32 `json:"curvature"`
}

View File

@ -1,6 +1,7 @@
package dynamics
import (
"encoding/json"
"github.com/spf13/viper"
"joylink.club/bj-rtsts-server/config"
"testing"
@ -10,15 +11,91 @@ import (
func TestSendTrainInitReq(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
for i := 1; i <= 5; i++ {
info := InitTrainInfo{
TrainIndex: uint16(i),
LinkIndex: 2,
LinkOffset: 3,
Speed: 4,
Up: true,
}
time.Sleep(time.Second)
SendInitTrainReq(&info)
info := InitTrainInfo{
TrainIndex: uint16(1),
LinkIndex: 2,
LinkOffset: 3,
Speed: 4,
Up: true,
}
time.Sleep(time.Second)
SendInitTrainReq(&info)
}
func TestSendSimulationStartReq(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
SendSimulationStartReq(mockLineBaseInfo())
}
func TestSendSimulationEndReq(t *testing.T) {
viper.AddConfigPath("../")
config.LoadConfig()
SendSimulationEndReq()
}
func mockLineBaseInfo() *LineBaseInfo {
var links []Link
for i := 1; i <= 12; i++ {
var atid int32
var btid int32
if i <= 6 {
atid = int32(i - 1)
btid = int32(i)
} else {
atid = int32(i - 2)
btid = int32(i - 1)
}
if i == 1 || i == 7 {
atid = 0
} else if i == 6 || i == 12 {
btid = 0
}
links = append(links, Link{
ID: int32(i),
Len: int32(i * 100000),
ARelTurnoutId: atid,
ARelTurnoutPoint: "A",
BRelTurnoutId: btid,
BRelTurnoutPoint: "B",
})
}
for i := 13; i <= 17; i++ {
links = append(links, Link{
ID: int32(i),
Len: int32(i * 100000),
ARelTurnoutId: int32(i - 12),
ARelTurnoutPoint: "A",
BRelTurnoutId: int32(i - 12 + 5),
BRelTurnoutPoint: "B",
})
}
slopes := []Slope{{
ID: 1,
StartLinkId: 1,
StartLinkOffset: 1,
EndLinkId: 1,
EndLinkOffset: 1,
DegreeTrig: 1,
}}
curves := []Curve{{
ID: 1,
StartLinkId: 1,
StartLinkOffset: 1,
EndLinkId: 1,
EndLinkOffset: 1,
Curvature: 1,
}}
base := LineBaseInfo{
LinkList: links,
SlopeList: slopes,
CurveList: curves,
}
return &base
}
func TestCalculationBase(t *testing.T) {
base := mockLineBaseInfo()
marshal, _ := json.Marshal(base)
println(string(marshal))
}

View File

@ -7,6 +7,7 @@ import (
"github.com/panjf2000/gnet/v2"
"go.uber.org/zap"
"joylink.club/bj-rtsts-server/config"
"math"
"net"
"sync"
"time"
@ -40,11 +41,11 @@ func runSendTurnoutStateTask() {
}()
}
func AddTurnoutInfoFunc(simId string, tiFunc TurnoutInfoFunc) {
func AddTurnoutInfoSource(simId string, tiFunc TurnoutInfoFunc) {
m.Store(simId, tiFunc)
}
func RemoveTurnoutInfoFunc(simId string) {
func RemoveTurnoutInfoSource(simId string) {
m.Delete(simId)
}
@ -95,7 +96,7 @@ type udpServer struct {
func (server *udpServer) OnBoot(eng gnet.Engine) gnet.Action {
server.eng = eng
println("udp server with multi-core=%t is listening on %s\n", server.multicore, server.addr)
fmt.Printf("udp server with multi-core=%t is listening on %s\n", server.multicore, server.addr)
zap.S().Infof("udp server with multi-core=%t is listening on %s\n", server.multicore, server.addr)
return gnet.None
}
@ -114,21 +115,21 @@ func (server *udpServer) OnTraffic(c gnet.Conn) gnet.Action {
trainInfo.Len = binary.BigEndian.Uint16(buf[3:5])
trainInfo.Link = buf[5]
trainInfo.LinkOffset = binary.BigEndian.Uint32(buf[6:10])
trainInfo.Slope = buf[10]
b := buf[11]
trainInfo.Slope = binary.BigEndian.Uint16(buf[10:12])
b := buf[12]
trainInfo.UpSlope = (b & (1 << 7)) != 0
trainInfo.Up = (b & (1 << 6)) != 0
trainInfo.TotalResistance = float32(binary.BigEndian.Uint16(buf[13:15])) / 100
trainInfo.AirResistance = float32(binary.BigEndian.Uint16(buf[15:17])) / 100
trainInfo.SlopeResistance = float32(binary.BigEndian.Uint16(buf[17:19])) / 100
trainInfo.CurveResistance = float32(binary.BigEndian.Uint16(buf[19:21])) / 100
trainInfo.Speed = float32(binary.BigEndian.Uint16(buf[21:23])) / 10
trainInfo.HeadSpeed1 = float32(binary.BigEndian.Uint16(buf[23:25])) / 10
trainInfo.HeadSpeed2 = float32(binary.BigEndian.Uint16(buf[25:27])) / 10
trainInfo.TailSpeed1 = float32(binary.BigEndian.Uint16(buf[27:29])) / 10
trainInfo.TailSpeed2 = float32(binary.BigEndian.Uint16(buf[29:31])) / 10
trainInfo.HeadRadarSpeed = float32(binary.BigEndian.Uint16(buf[31:33])) / 10
trainInfo.TailRadarSpeed = float32(binary.BigEndian.Uint16(buf[33:35])) / 10
trainInfo.TotalResistance = binary.BigEndian.Uint32(buf[14:18])
trainInfo.AirResistance = binary.BigEndian.Uint32(buf[18:22])
trainInfo.SlopeResistance = binary.BigEndian.Uint32(buf[22:26])
trainInfo.CurveResistance = binary.BigEndian.Uint32(buf[26:30])
trainInfo.Speed = math.Float32frombits(binary.BigEndian.Uint32(buf[30:34]))
trainInfo.HeadSpeed1 = math.Float32frombits(binary.BigEndian.Uint32(buf[34:38]))
trainInfo.HeadSpeed2 = math.Float32frombits(binary.BigEndian.Uint32(buf[38:42]))
trainInfo.TailSpeed1 = math.Float32frombits(binary.BigEndian.Uint32(buf[42:46]))
trainInfo.TailSpeed2 = math.Float32frombits(binary.BigEndian.Uint32(buf[46:50]))
trainInfo.HeadRadarSpeed = math.Float32frombits(binary.BigEndian.Uint32(buf[50:54]))
trainInfo.TailRadarSpeed = math.Float32frombits(binary.BigEndian.Uint32(buf[54:58]))
for e := handlerList.Front(); e != nil; e = e.Next() {
handler := e.Value.(TrainInfoHandler)

View File

@ -11,38 +11,38 @@ type TrainInfo struct {
LifeSignal uint16
//列车号(车辆)
Number uint8
//列车长度
//列车长度 cm
Len uint16
//列车所在轨道link
Link uint8
//列车所在link偏移量cm
//列车所在link偏移量mm
LinkOffset uint32
//列车所在位置坡度值(‰)
Slope uint8
Slope uint16
//列车所在位置坡度走势(上/下坡)
UpSlope bool
//列车当前运行方向(上/下行)
Up bool
//实际运行阻力(总)(KN
TotalResistance float32
//阻力1空气阻力KN
AirResistance float32
//阻力2坡道阻力KN
SlopeResistance float32
//阻力3曲线阻力KN
CurveResistance float32
//列车运行速度(km/h
//实际运行阻力(总)(N
TotalResistance uint32
//阻力1空气阻力N
AirResistance uint32
//阻力2坡道阻力N
SlopeResistance uint32
//阻力3曲线阻力N
CurveResistance uint32
//列车运行速度(m/s
Speed float32
//头车速传1速度值km/h
//头车速传1速度值m/s
HeadSpeed1 float32
//头车速度2速度值
//头车速度2速度值m/s
HeadSpeed2 float32
//尾车速传1速度值
//尾车速传1速度值m/s
TailSpeed1 float32
//尾车速度2速度值
//尾车速度2速度值m/s
TailSpeed2 float32
//头车雷达速度值
//头车雷达速度值m/s
HeadRadarSpeed float32
//尾车雷达速度值
//尾车雷达速度值m/s
TailRadarSpeed float32
}