Compare commits
No commits in common. "local-test" and "master" have entirely different histories.
local-test
...
master
@ -1,9 +1,9 @@
|
|||||||
name: local-test分支打包构建docker并发布运行
|
name: CI
|
||||||
run-name: ${{ gitea.actor }} is testing out Gitea Actions
|
run-name: ${{ gitea.actor }} is testing out Gitea Actions
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- local-test
|
- develop
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
Docker-Build:
|
Docker-Build:
|
||||||
@ -14,19 +14,18 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
submodules: recursive
|
submodules: recursive
|
||||||
- name: 设置go环境
|
- name: 设置go环境
|
||||||
uses: https://gitea.joylink.club/actions/local-setup-go@v0.1.2
|
uses: https://gitea.joylink.club/actions/local-setup-go@v0.1.1
|
||||||
with:
|
with:
|
||||||
go-version: '1.22.1'
|
go-version: '1.22.1'
|
||||||
- name: 构建go build
|
- name: 构建go build
|
||||||
run: |
|
run: |
|
||||||
go env -w GO111MODULE=on
|
go env -w GO111MODULE=on
|
||||||
go env -w GOPROXY=https://goproxy.cn,direct
|
go env -w GOPROXY=https://goproxy.cn,direct
|
||||||
go env -w CGO_ENABLED=0
|
|
||||||
go build -o rts-sim-testing-service
|
go build -o rts-sim-testing-service
|
||||||
- name: 设置 Docker
|
|
||||||
uses: https://gitea.joylink.club/actions/local-setup-docker-cli-action@v0.1.1
|
|
||||||
- name: 设置 Docker Buildx
|
- name: 设置 Docker Buildx
|
||||||
uses: https://gitea.joylink.club/actions/local-setup-buildx-action@v0.1.3
|
uses: https://gitea.joylink.club/actions/local-setup-buildx-action@v0.1.1
|
||||||
|
with:
|
||||||
|
version: 'v0.13.1'
|
||||||
- name: docker登录gitea.joylink.club
|
- name: docker登录gitea.joylink.club
|
||||||
uses: https://gitea.joylink.club/docker/login-action@v3
|
uses: https://gitea.joylink.club/docker/login-action@v3
|
||||||
with:
|
with:
|
||||||
@ -40,18 +39,16 @@ jobs:
|
|||||||
file: ./Dockerfile_Gitea
|
file: ./Dockerfile_Gitea
|
||||||
push: true
|
push: true
|
||||||
tags: |
|
tags: |
|
||||||
gitea.joylink.club/joylink/rts-sim-testing-service:local-test
|
gitea.joylink.club/joylink/rts-sim-testing-service:0.1.1
|
||||||
- name: 发布到服务器
|
gitea.joylink.club/joylink/rts-sim-testing-service:latest
|
||||||
uses: https://gitea.joylink.club/appleboy/ssh-action@v1.0.3
|
# - name: SSH Connect and Publish
|
||||||
with:
|
# uses: http://120.46.212.6:3000/appleboy/ssh-action@v1.0.3
|
||||||
host: ${{ secrets.LOCAL_233_SSH_HOST }}
|
# with:
|
||||||
port: ${{ secrets.LOCAL_233_SSH_PORT }}
|
# host: ${{ secrets.LOCAL_SSH_HOST }}
|
||||||
username: ${{ secrets.LOCAL_233_SSH_USER }}
|
# port: ${{ secrets.LOCAL_SSH_PORT }}
|
||||||
password: ${{ secrets.LOCAL_233_SSH_PASSWORD }}
|
# username: ${{ secrets.LOCAL_SSH_USER }}
|
||||||
script: |
|
# password: ${{ secrets.LOCAL_SSH_PASSWORD }}
|
||||||
docker rm -f rts-sim-testing-service || echo "rts-sim-testing-service not exist"
|
# script: |
|
||||||
docker pull gitea.joylink.club/joylink/rts-sim-testing-service:local-test
|
# whoami
|
||||||
docker run --name rts-sim-testing-service --restart=always --network net --ip 192.168.53.191 -d -p 9091:9091 -p 4000:4000/udp -v /usr/local/joylink/logs/bjrtsts:/logs/bjrtsts gitea.joylink.club/joylink/rts-sim-testing-service:local-test rts-sim-testing-service -config test_local
|
# sudo docker images
|
||||||
- name: 清理tag为none的镜像
|
- run: echo "This job's status is ${{ job.status }}."
|
||||||
run: |
|
|
||||||
docker rmi $(docker images --filter "dangling=true" -q)
|
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -26,5 +26,4 @@ output/
|
|||||||
|
|
||||||
# Go workspace file
|
# Go workspace file
|
||||||
/go.work.sum
|
/go.work.sum
|
||||||
/pom.xml
|
/pom.xml
|
||||||
/bj-rtsts-server
|
|
6
.gitmodules
vendored
6
.gitmodules
vendored
@ -1,9 +1,9 @@
|
|||||||
[submodule "rts-sim-testing-message"]
|
[submodule "rts-sim-testing-message"]
|
||||||
path = rts-sim-testing-message
|
path = rts-sim-testing-message
|
||||||
url = https://gitea.joylink.club/joylink/rts-sim-testing-message.git
|
url = http://120.46.212.6:3000/joylink/rts-sim-testing-message.git
|
||||||
[submodule "rts-sim-module"]
|
[submodule "rts-sim-module"]
|
||||||
path = rts-sim-module
|
path = rts-sim-module
|
||||||
url = https://gitea.joylink.club/joylink/rts-sim-module.git
|
url = http://120.46.212.6:3000/joylink/rts-sim-module.git
|
||||||
[submodule "jl-iot-module"]
|
[submodule "jl-iot-module"]
|
||||||
path = jl-iot-module
|
path = jl-iot-module
|
||||||
url = https://gitea.joylink.club/joylink/jl-iot.git
|
url = http://120.46.212.6:3000/joylink/jl-iot.git
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
FROM docker.m.daocloud.io/library/alpine:3.20
|
FROM alpine
|
||||||
COPY ./rts-sim-testing-service /usr/local/bin/rts-sim-testing-service
|
COPY ./rts-sim-testing-service /usr/local/bin/rts-sim-testing-service
|
||||||
WORKDIR /bj-rtsts
|
WORKDIR /bj-rtsts
|
||||||
COPY ./config/*.yml ./
|
COPY ./config/*.yml ./
|
||||||
|
@ -14,17 +14,9 @@
|
|||||||
- viper 配置管理
|
- viper 配置管理
|
||||||
- swagger 文档生成(基于[swaggo](https://github.com/swaggo/swag))(需要安装 go install github.com/swaggo/swag/cmd/swag@latest,在项目根目录(即 bj-rtsts-server-go)执行 swag init,然后启动项目即可,启动后访问 http://{ip}:{port}/swagger/index.html)
|
- swagger 文档生成(基于[swaggo](https://github.com/swaggo/swag))(需要安装 go install github.com/swaggo/swag/cmd/swag@latest,在项目根目录(即 bj-rtsts-server-go)执行 swag init,然后启动项目即可,启动后访问 http://{ip}:{port}/swagger/index.html)
|
||||||
|
|
||||||
# 动力学
|
|
||||||
- dotnet.exe publish -r win-x64 -p:PublishSingleFile=true
|
|
||||||
|
|
||||||
# 开发说明
|
# 开发说明
|
||||||
|
|
||||||
- 在 api 目录下添加路由及请求数据解析返回
|
- 在 api 目录下添加路由及请求数据解析返回
|
||||||
- 在 service 目录下添加具体的业务逻辑(数据库查询)
|
- 在 service 目录下添加具体的业务逻辑(数据库查询)
|
||||||
- 设置 go 代理 go env -w GOPROXY=https://goproxy.cn,direct
|
- 设置 go 代理 go env -w GOPROXY=https://goproxy.cn,direct
|
||||||
- 运行 go mod download / go mod tidy
|
- 运行 go mod download / go mod tidy
|
||||||
|
|
||||||
# windows 编译linux环境
|
|
||||||
- go env -w GOOS=linux
|
|
||||||
- go build -o appname
|
|
||||||
- go env -w GOOS=windows
|
|
||||||
|
@ -190,7 +190,7 @@ func deleteProjectRunConfig(c *gin.Context) {
|
|||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/runconfig/description [get]
|
// @Router /api/v1/runconfig/description [get]
|
||||||
func getRunCofigDescription(c *gin.Context) {
|
func getRunCofigDescription(c *gin.Context) {
|
||||||
c.JSON(http.StatusOK, parseRunCofigStruct(&config.ThirdPartyConfig{}))
|
c.JSON(http.StatusOK, parseRunCofigStruct(&config.ThridPartyConfig{}))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析环境配置结构
|
// 解析环境配置结构
|
||||||
|
@ -22,12 +22,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware) {
|
||||||
|
|
||||||
authed := api.Group("/v1/simulation").Use(authMiddleware.MiddlewareFunc(), middleware.PermissMiddleware)
|
authed := api.Group("/v1/simulation").Use(authMiddleware.MiddlewareFunc(), middleware.PermissMiddleware)
|
||||||
authed.POST("/createByProject", createByProjectId)
|
authed.POST("/createByProject", createByProjectId)
|
||||||
authed.POST("/destroy/:id", destroy)
|
authed.POST("/destroy/:id", destroy)
|
||||||
authed.GET("/list", findAllSimulations)
|
authed.GET("/list", findAllSimulations)
|
||||||
|
|
||||||
authed.POST("/check/data", checkSimMapData)
|
authed.POST("/check/data", checkSimMapData)
|
||||||
authed.POST("/train/add", addTrain)
|
authed.POST("/train/add", addTrain)
|
||||||
authed.POST("/train/config", configTrain)
|
authed.POST("/train/config", configTrain)
|
||||||
@ -36,8 +34,6 @@ func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
|
|||||||
authed.POST("/train/update", updateTrain)
|
authed.POST("/train/update", updateTrain)
|
||||||
authed.POST("/train/control", controlTrain)
|
authed.POST("/train/control", controlTrain)
|
||||||
authed.POST("/train/conn", trainConnThird)
|
authed.POST("/train/conn", trainConnThird)
|
||||||
authed.DELETE("/train/unconn/:trainId/:id", trainUnConnThird)
|
|
||||||
|
|
||||||
authed.GET("/train/conn/type/:id", trainConnTypeList)
|
authed.GET("/train/conn/type/:id", trainConnTypeList)
|
||||||
|
|
||||||
authed.POST("/switch/operation", turnoutOperation)
|
authed.POST("/switch/operation", turnoutOperation)
|
||||||
@ -51,14 +47,12 @@ func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
|
|||||||
authed.POST("/psl/operation", pslBtnOperation) //1
|
authed.POST("/psl/operation", pslBtnOperation) //1
|
||||||
authed.POST("/psd/operation", psdOperation)
|
authed.POST("/psd/operation", psdOperation)
|
||||||
authed.PUT("/balise/position/modify", balisePositionModify)
|
authed.PUT("/balise/position/modify", balisePositionModify)
|
||||||
authed.PUT("/balise/position/reset", balisePositionReset)
|
authed.PUT("/balise/position/reset", transponderPositionReset)
|
||||||
authed.PUT("/balise/telegram/modify", baliseTelegramModify)
|
authed.PUT("/balise/telegram/modify", baliseTelegramModify)
|
||||||
authed.PUT("/balise/telegram/reset", baliseTelegramReset)
|
authed.PUT("/balise/telegram/reset", baliseTelegramReset)
|
||||||
authed.PUT("/balise/telegram/stop", baliseTelegramStop)
|
authed.PUT("/balise/telegram/stop", baliseTelegramStop)
|
||||||
authed.PUT("/balise/telegram/send", baliseTelegramSend)
|
authed.PUT("/balise/telegram/send", baliseTelegramSend)
|
||||||
authed.PUT("/balise/reset", baliseReset)
|
authed.PUT("/balise/reset", baliseReset)
|
||||||
authed.PUT("/ckm/operation", ckmOperation)
|
|
||||||
authed.PUT("/xcj/operation", xcjOperation)
|
|
||||||
//authed.POST("/bypass/operation", bypassBtnOrKeyOperation)
|
//authed.POST("/bypass/operation", bypassBtnOrKeyOperation)
|
||||||
|
|
||||||
// 初始化地图信息
|
// 初始化地图信息
|
||||||
@ -98,7 +92,6 @@ 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()] {
|
||||||
@ -242,28 +235,15 @@ func addTrain(c *gin.Context) {
|
|||||||
if req.TrainId < 0 || req.TrainId >= 255 {
|
if req.TrainId < 0 || req.TrainId >= 255 {
|
||||||
panic(sys_error.New("列车编号不能小于0,大于255"))
|
panic(sys_error.New("列车编号不能小于0,大于255"))
|
||||||
}
|
}
|
||||||
if req.TrainSpeed < 0 || req.TrainSpeed > 90 {
|
|
||||||
panic(sys_error.New("列车编号不能小于0,大于255"))
|
|
||||||
}
|
|
||||||
rsp := &state_proto.TrainState{
|
rsp := &state_proto.TrainState{
|
||||||
Id: fmt.Sprintf("%v", req.TrainId),
|
Id: fmt.Sprintf("%v", req.TrainId),
|
||||||
HeadDeviceId: req.Id,
|
HeadDeviceId: req.Id,
|
||||||
HeadOffset: req.HeadOffset,
|
HeadOffset: req.HeadOffset,
|
||||||
TrainLoad: req.TrainLoad,
|
DevicePort: req.DevicePort,
|
||||||
TrainMaxSpeed: req.TrainMaxSpeed,
|
RunDirection: req.RunDirection,
|
||||||
TrainMaxAcc: req.TrainMaxAcc,
|
|
||||||
TrainMaxBrake: req.TrainMaxBrake,
|
|
||||||
TrainEmergencyBrake: req.TrainEmergencyBrake,
|
|
||||||
ProjectCode: simulation.ProjectCode,
|
|
||||||
//HeadOffset: 93211,
|
|
||||||
DevicePort: req.DevicePort,
|
|
||||||
TrainRunUp: req.RunDirection,
|
|
||||||
//RunDirection: req.RunDirection,
|
|
||||||
TrainLength: req.TrainLength,
|
TrainLength: req.TrainLength,
|
||||||
WheelDiameter: req.WheelDiameter,
|
WheelDiameter: req.WheelDiameter,
|
||||||
Speed: req.TrainSpeed,
|
Speed: req.TrainSpeed,
|
||||||
Show: true,
|
|
||||||
TrainCoachNum: req.TrainCoachNum,
|
|
||||||
ConnState: &state_proto.TrainConnState{TrainControlMapId: req.TrainControlMapId, Conn: false, ConnType: state_proto.TrainConnState_NONE},
|
ConnState: &state_proto.TrainConnState{TrainControlMapId: req.TrainControlMapId, Conn: false, ConnType: state_proto.TrainConnState_NONE},
|
||||||
}
|
}
|
||||||
var err *sys_error.BusinessError = memory.AddTrainStateNew(simulation,
|
var err *sys_error.BusinessError = memory.AddTrainStateNew(simulation,
|
||||||
@ -329,30 +309,6 @@ func trainConnThird(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, "ok")
|
c.JSON(http.StatusOK, "ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ATS测试仿真-取消列车连接三方
|
|
||||||
//
|
|
||||||
// @Summary ATS测试仿真-取消列车连接三方
|
|
||||||
//
|
|
||||||
// @Security JwtAuth
|
|
||||||
//
|
|
||||||
// @Description ATS测试仿真-取消列车连接三方
|
|
||||||
// @Tags ATS测试仿真Api
|
|
||||||
// @Accept json
|
|
||||||
// @Produce json
|
|
||||||
// @Param Authorization header string true "JWT Token"
|
|
||||||
// @Param trainId path string true "列车id"
|
|
||||||
// @Param id path string true "仿真id"
|
|
||||||
// @Success 200 {object} dto.AddTrainRspDto
|
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
|
||||||
// @Router /api/v1/simulation/train/conn [delete]
|
|
||||||
func trainUnConnThird(c *gin.Context) {
|
|
||||||
trainId := c.Param("trainId")
|
|
||||||
simId := c.Param("id")
|
|
||||||
simulation := checkDeviceDataAndReturn(simId)
|
|
||||||
memory.TrainUnConn(simulation, trainId)
|
|
||||||
c.JSON(http.StatusOK, "ok")
|
|
||||||
}
|
|
||||||
|
|
||||||
// ATS测试仿真-列车连接三方类型列表
|
// ATS测试仿真-列车连接三方类型列表
|
||||||
//
|
//
|
||||||
// @Summary ATS测试仿真-列车连接三方类型列表
|
// @Summary ATS测试仿真-列车连接三方类型列表
|
||||||
@ -417,13 +373,14 @@ func controlTrain(c *gin.Context) {
|
|||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/train/remove/all [post]
|
// @Router /api/v1/simulation/train/remove/all [post]
|
||||||
func removeAllTrain(c *gin.Context) {
|
func removeAllTrain(c *gin.Context) {
|
||||||
|
|
||||||
rt := &dto.RemoveAllTrainRspDto{}
|
rt := &dto.RemoveAllTrainRspDto{}
|
||||||
if err := c.ShouldBind(&rt); err != nil {
|
if err := c.ShouldBind(&rt); err != nil {
|
||||||
panic(sys_error.New("移除所有列车失败,请求参数异常", err))
|
panic(sys_error.New("移除所有列车失败,请求参数异常", err))
|
||||||
}
|
}
|
||||||
slog.Debug("ATS测试仿真-移除所有列车,请求:", rt)
|
slog.Debug("ATS测试仿真-移除所有列车,请求:", rt)
|
||||||
simulation := checkDeviceDataAndReturn(rt.SimulationId)
|
simulation := checkDeviceDataAndReturn(rt.SimulationId)
|
||||||
memory.RemoveAllTrain(simulation, false)
|
memory.RemoveAllTrain(simulation)
|
||||||
//TODO 后续调用列车删除操作
|
//TODO 后续调用列车删除操作
|
||||||
c.JSON(http.StatusOK, "ok")
|
c.JSON(http.StatusOK, "ok")
|
||||||
}
|
}
|
||||||
@ -451,7 +408,7 @@ func removeTrain(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
slog.Debug("ATS测试仿真-移除列车,请求:", rt)
|
slog.Debug("ATS测试仿真-移除列车,请求:", rt)
|
||||||
simulation := checkDeviceDataAndReturn(rt.SimulationId)
|
simulation := checkDeviceDataAndReturn(rt.SimulationId)
|
||||||
memory.RemoveTrainState(simulation, rt.TrainId, false)
|
memory.RemoveTrainState(simulation, rt.TrainId)
|
||||||
//TODO 后续调用列车删除操作
|
//TODO 后续调用列车删除操作
|
||||||
c.JSON(http.StatusOK, "ok")
|
c.JSON(http.StatusOK, "ok")
|
||||||
}
|
}
|
||||||
@ -656,10 +613,7 @@ func pslBtnOperation(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
||||||
slog.Info("传入状态参数", req)
|
slog.Info("传入状态参数", req)
|
||||||
var err *sys_error.BusinessError = memory.ChangePSLButtonState(simulation, req.MapId, req.PslId, req.ButtonCode, req.Down)
|
memory.ChangePSLButtonState(simulation, req.MapId, req.PslId, req.ButtonCode, req.Down)
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, "ok")
|
c.JSON(http.StatusOK, "ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -760,7 +714,7 @@ func relayOperation(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
// @Success 200 {object} string
|
// @Success 200 {object} string
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/balisecodec/position/modify [put]
|
// @Router /api/v1/simulation/balise/position/modify [put]
|
||||||
func balisePositionModify(c *gin.Context) {
|
func balisePositionModify(c *gin.Context) {
|
||||||
req := &dto.BaliseMoveReqDto{}
|
req := &dto.BaliseMoveReqDto{}
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
@ -789,8 +743,8 @@ func balisePositionModify(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
// @Success 200 {object} string
|
// @Success 200 {object} string
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/balisecodec/position/reset [put]
|
// @Router /api/v1/simulation/balise/position/reset [put]
|
||||||
func balisePositionReset(c *gin.Context) {
|
func transponderPositionReset(c *gin.Context) {
|
||||||
req := &dto.BaliseReqDto{}
|
req := &dto.BaliseReqDto{}
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
panic(sys_error.New("应答器复位操作失败,请求参数异常", err))
|
panic(sys_error.New("应答器复位操作失败,请求参数异常", err))
|
||||||
@ -818,7 +772,7 @@ func balisePositionReset(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
// @Success 200 {object} string
|
// @Success 200 {object} string
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/balisecodec/telegram/modify [put]
|
// @Router /api/v1/simulation/balise/telegram/modify [put]
|
||||||
func baliseTelegramModify(c *gin.Context) {
|
func baliseTelegramModify(c *gin.Context) {
|
||||||
req := &dto.BaliseModifyTelegramReqDto{}
|
req := &dto.BaliseModifyTelegramReqDto{}
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
@ -847,7 +801,7 @@ func baliseTelegramModify(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
// @Success 200 {object} string
|
// @Success 200 {object} string
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/balisecodec/telegram/reset [put]
|
// @Router /api/v1/simulation/balise/telegram/reset [put]
|
||||||
func baliseTelegramReset(c *gin.Context) {
|
func baliseTelegramReset(c *gin.Context) {
|
||||||
req := &dto.BaliseReqDto{}
|
req := &dto.BaliseReqDto{}
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
@ -855,7 +809,7 @@ func baliseTelegramReset(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
||||||
slog.Info("传入状态参数", req)
|
slog.Info("传入状态参数", req)
|
||||||
var err = memory.BaliseTelegramReset(simulation, req)
|
var err *sys_error.BusinessError = memory.BaliseTelegramReset(simulation, req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
@ -876,7 +830,7 @@ func baliseTelegramReset(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
// @Success 200 {object} string
|
// @Success 200 {object} string
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/balisecodec/telegram/stop [put]
|
// @Router /api/v1/simulation/balise/telegram/stop [put]
|
||||||
func baliseTelegramStop(c *gin.Context) {
|
func baliseTelegramStop(c *gin.Context) {
|
||||||
req := &dto.BaliseReqDto{}
|
req := &dto.BaliseReqDto{}
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
@ -905,7 +859,7 @@ func baliseTelegramStop(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
// @Success 200 {object} string
|
// @Success 200 {object} string
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/balisecodec/telegram/send [put]
|
// @Router /api/v1/simulation/balise/telegram/send [put]
|
||||||
func baliseTelegramSend(c *gin.Context) {
|
func baliseTelegramSend(c *gin.Context) {
|
||||||
req := &dto.BaliseReqDto{}
|
req := &dto.BaliseReqDto{}
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
if err := c.ShouldBind(&req); err != nil {
|
||||||
@ -934,7 +888,7 @@ func baliseTelegramSend(c *gin.Context) {
|
|||||||
//
|
//
|
||||||
// @Success 200 {object} string
|
// @Success 200 {object} string
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
// @Failure 500 {object} dto.ErrorDto
|
||||||
// @Router /api/v1/simulation/balisecodec/reset [put]
|
// @Router /api/v1/simulation/balise/reset [put]
|
||||||
func baliseReset(c *gin.Context) {
|
func baliseReset(c *gin.Context) {
|
||||||
//req := &dto.BaliseReqDto{}
|
//req := &dto.BaliseReqDto{}
|
||||||
//if err := c.ShouldBind(&req); err != nil {
|
//if err := c.ShouldBind(&req); err != nil {
|
||||||
@ -942,69 +896,13 @@ func baliseReset(c *gin.Context) {
|
|||||||
//}
|
//}
|
||||||
simulationId := c.Query("simulationId")
|
simulationId := c.Query("simulationId")
|
||||||
simulation := checkDeviceDataAndReturn(simulationId)
|
simulation := checkDeviceDataAndReturn(simulationId)
|
||||||
err := memory.AllBaliseTelegramReset(simulation)
|
err := memory.BaliseReset(simulation)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(sys_error.New(fmt.Sprintf("应答器状态重置操作失败,%s", err.Error()), err))
|
panic(sys_error.New(fmt.Sprintf("应答器状态重置操作失败,%s", err.Error()), err))
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, "ok")
|
c.JSON(http.StatusOK, "ok")
|
||||||
}
|
}
|
||||||
|
|
||||||
// 车库门操作
|
|
||||||
//
|
|
||||||
// @Summary 车库门操作
|
|
||||||
//
|
|
||||||
// @Security JwtAuth
|
|
||||||
//
|
|
||||||
// @Description 车库门操作
|
|
||||||
// @Tags ATS测试仿真Api
|
|
||||||
// @Accept json
|
|
||||||
// @Param Authorization header string true "JWT Token"
|
|
||||||
// @Param CkmOperationReq body request_proto.CkmOperationReq true "车库门操作"
|
|
||||||
//
|
|
||||||
// @Success 200 {object} string
|
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
|
||||||
// @Router /api/v1/simulation/ckm/operation [put]
|
|
||||||
func ckmOperation(c *gin.Context) {
|
|
||||||
req := &request_proto.CkmOperationReq{}
|
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
|
||||||
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
|
|
||||||
}
|
|
||||||
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
|
||||||
var err *sys_error.BusinessError = memory.CkmOperation(simulation, req)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, "ok")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 洗车机操作
|
|
||||||
//
|
|
||||||
// @Summary 洗车机操作
|
|
||||||
//
|
|
||||||
// @Security JwtAuth
|
|
||||||
//
|
|
||||||
// @Description 洗车机操作
|
|
||||||
// @Tags ATS测试仿真Api
|
|
||||||
// @Accept json
|
|
||||||
// @Param Authorization header string true "JWT Token"
|
|
||||||
// @Param XcjOperationReq body request_proto.XcjOperationReq true "洗车机操作"
|
|
||||||
//
|
|
||||||
// @Success 200 {object} string
|
|
||||||
// @Failure 500 {object} dto.ErrorDto
|
|
||||||
// @Router /api/v1/simulation/xcj/operation [put]
|
|
||||||
func xcjOperation(c *gin.Context) {
|
|
||||||
req := &request_proto.XcjOperationReq{}
|
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
|
||||||
panic(dto.ErrorDto{Code: dto.ArgumentParseError, Message: err.Error()})
|
|
||||||
}
|
|
||||||
simulation := checkDeviceDataAndReturn(req.SimulationId)
|
|
||||||
var err *sys_error.BusinessError = memory.XcjOperation(simulation, req)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, "ok")
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取仿真设备数据并返回
|
// 获取仿真设备数据并返回
|
||||||
func checkDeviceDataAndReturn(simId string) *memory.VerifySimulation {
|
func checkDeviceDataAndReturn(simId string) *memory.VerifySimulation {
|
||||||
deviceMemory := ts.FindSimulation(simId)
|
deviceMemory := ts.FindSimulation(simId)
|
||||||
|
@ -21,7 +21,6 @@ func InitUserRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddleware)
|
|||||||
authed := api.Group("/v1/user").Use(authMiddleware.MiddlewareFunc(), middleware.PermissMiddleware)
|
authed := api.Group("/v1/user").Use(authMiddleware.MiddlewareFunc(), middleware.PermissMiddleware)
|
||||||
authed.GET("/paging", pageQueryUser)
|
authed.GET("/paging", pageQueryUser)
|
||||||
authed.GET("/current", findUserInfo)
|
authed.GET("/current", findUserInfo)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 用户注册
|
// 用户注册
|
||||||
|
@ -1,309 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"github.com/spf13/viper"
|
|
||||||
"joylink.club/bj-rtsts-server/bin/config"
|
|
||||||
"joylink.club/bj-rtsts-server/const/balise_const"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/tcp"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
|
||||||
"log/slog"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
const config_name = "example"
|
|
||||||
|
|
||||||
var exampleConfig config.ExampleConfig
|
|
||||||
|
|
||||||
func initConfig() {
|
|
||||||
cnf := viper.New()
|
|
||||||
cnf.SetConfigName(config_name)
|
|
||||||
cnf.SetConfigType("yml")
|
|
||||||
//cnf.AddConfigPath("./bin/config/")
|
|
||||||
//cnf.AddConfigPath("./")
|
|
||||||
cnf.AddConfigPath(".")
|
|
||||||
err := cnf.ReadInConfig()
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("读取配置文件错误: %w", err))
|
|
||||||
}
|
|
||||||
err = cnf.Unmarshal(&exampleConfig)
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Errorf("解析配置文件错误: %w", err))
|
|
||||||
}
|
|
||||||
slog.Info("成功加载配置", "config", exampleConfig)
|
|
||||||
}
|
|
||||||
|
|
||||||
var btmCli udp.UdpClient
|
|
||||||
|
|
||||||
func initBtmTest() {
|
|
||||||
ser := udp.NewServer(fmt.Sprintf("%v:%d", exampleConfig.Btm.LocalIp, exampleConfig.Btm.LocalPort), handleBtmVobcFrames)
|
|
||||||
ser.Listen()
|
|
||||||
btmCli = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Btm.RemoteIp, exampleConfig.Btm.RemotePort))
|
|
||||||
}
|
|
||||||
|
|
||||||
var accClient udp.UdpClient
|
|
||||||
|
|
||||||
func initAccTest() {
|
|
||||||
accClient = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Acc.RemoteIp, exampleConfig.Acc.RemotePort))
|
|
||||||
go testAcc(accClient, 0.54)
|
|
||||||
}
|
|
||||||
|
|
||||||
var speedClient udp.UdpClient
|
|
||||||
|
|
||||||
func initSpeedTest() {
|
|
||||||
speedClient = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Speed.RemoteIp, exampleConfig.Speed.RemotePort))
|
|
||||||
go testSpeed(speedClient, 30)
|
|
||||||
}
|
|
||||||
|
|
||||||
var trainpcClient *tcp.TcpClient
|
|
||||||
|
|
||||||
func initTrainPc() {
|
|
||||||
addr := fmt.Sprintf("%v:%v", exampleConfig.Trainpc.RemoteIp, exampleConfig.Trainpc.RemotePort)
|
|
||||||
|
|
||||||
client2, err := tcp.StartTcpClient(addr, trainPcDataHandle, trainPcConnErr)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("仿真列车pc连接失败", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
trainpcClient = client2
|
|
||||||
time.Sleep(time.Millisecond * 1500)
|
|
||||||
createOrRemoveTrain()
|
|
||||||
circleSendTrainActive()
|
|
||||||
circleSendTrainMockData()
|
|
||||||
//go circleSendTrainSpeedPlace()
|
|
||||||
//sendBtm()
|
|
||||||
}
|
|
||||||
|
|
||||||
func createOrRemoveTrain() {
|
|
||||||
msgs := make([]*message.TrainPcSimBaseMessage, 0)
|
|
||||||
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Data: []byte{0x00}, Type: message.RECIVE_TRAIN_CREATE_REMOVE})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Data: []byte{0x01}, Type: message.RECIVE_TRAIN_CREATE_REMOVE})
|
|
||||||
for _, msg := range msgs {
|
|
||||||
data := msg.Encode()
|
|
||||||
fmt.Println(fmt.Sprintf("发送列车模拟数据:%v,命令码:%v", hex.EncodeToString(data), msg.Data[0]))
|
|
||||||
trainpcClient.Send(data)
|
|
||||||
time.Sleep(time.Millisecond * 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func circleSendTrainActive() {
|
|
||||||
msgs := make([]*message.TrainPcSimBaseMessage, 0)
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Data: []byte{}, Type: message.SENDER_TRAIN_TC_ACTIVE})
|
|
||||||
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Data: []byte{}, Type: message.SENDER_TRAIN_HAND_KEY_FORWARD})
|
|
||||||
|
|
||||||
for _, msg := range msgs {
|
|
||||||
|
|
||||||
actData := msg.Encode()
|
|
||||||
fmt.Println(fmt.Sprintf("发送列车驾驶室激活:%v", hex.EncodeToString(actData)))
|
|
||||||
trainpcClient.Send(actData)
|
|
||||||
time.Sleep(time.Millisecond * 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func circleSendTrainMockData() {
|
|
||||||
msgs := make([]*message.TrainPcSimBaseMessage, 0)
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(0), 1}})
|
|
||||||
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(16), 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(3), 0}})
|
|
||||||
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(3), 0}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(16), 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(45), 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(46), 1}})
|
|
||||||
/* for i := 3; i <= 50; i++ {
|
|
||||||
if i != 2 {
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{byte(i), 0}})
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{14, 0}})
|
|
||||||
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{1, 1}})
|
|
||||||
/*msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{1, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{2, 0}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{12, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{16, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{20, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{3, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{4, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{6, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{7, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{30, 1}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{22, 0}})
|
|
||||||
msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{23, 0}})*/
|
|
||||||
//msgs = append(msgs, &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{3, 0}})
|
|
||||||
|
|
||||||
for _, msg := range msgs {
|
|
||||||
data := msg.Encode()
|
|
||||||
fmt.Println(fmt.Sprintf("发送列车模拟数据:%v,命令码:%v", hex.EncodeToString(data), msg.Data[0]))
|
|
||||||
trainpcClient.Send(data)
|
|
||||||
time.Sleep(time.Millisecond * 1000)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func trainPcDataHandle(n int, data []byte) {
|
|
||||||
hexData := hex.EncodeToString(data[:n])
|
|
||||||
slog.Info(fmt.Sprintf("列车pc仿真接口长度:%v,实际长度:%v,接受数据:%v", len(data), n, hexData))
|
|
||||||
|
|
||||||
}
|
|
||||||
func trainPcConnErr(err error) {
|
|
||||||
|
|
||||||
}
|
|
||||||
func main() {
|
|
||||||
|
|
||||||
initConfig()
|
|
||||||
initBtmTest()
|
|
||||||
//initTrainPc()
|
|
||||||
//initAccTest()
|
|
||||||
//initSpeedTest()
|
|
||||||
|
|
||||||
for {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var testUserBtmMsg = "90007F8181B60B10183280003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"
|
|
||||||
var freeBtmMsg = strings.Repeat("00", balise_const.UserTelegramByteLen)
|
|
||||||
|
|
||||||
func sendPacket(lifeNum uint32, autoId byte) {
|
|
||||||
userMsg, _ := hex.DecodeString(testUserBtmMsg)
|
|
||||||
|
|
||||||
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()*/}
|
|
||||||
sendData := msg.Encode()
|
|
||||||
//fmt.Println("发送btm vobc len:", len(sendData), "报文:", hex.EncodeToString(sendData), "报文序列号:", msg.MsgSerial)
|
|
||||||
time.Sleep(time.Millisecond * 100)
|
|
||||||
err := btmCli.Send(sendData)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(fmt.Sprintf("发送失败%v", err.Error()))
|
|
||||||
}
|
|
||||||
|
|
||||||
/*freeMsg, _ := hex.DecodeString(freeBtmMsg)
|
|
||||||
|
|
||||||
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: message.GetAutoMessageId()}
|
|
||||||
sendData2 := msg2.Encode()
|
|
||||||
fmt.Println("发送btm vobc 空报文11111:", hex.EncodeToString(sendData2), "len:", len(sendData2), "报文序列号:", msg2.MsgSerial, "atoId=", autoId, "报文序列号:", msg2.MsgSerial)
|
|
||||||
btmCli.Send(sendData2)*/
|
|
||||||
}
|
|
||||||
|
|
||||||
func sendPacketFree(lifeNum uint32, autoId byte, msgs byte) {
|
|
||||||
freeMsg, _ := hex.DecodeString(freeBtmMsg)
|
|
||||||
newMsg := msgs + 1
|
|
||||||
if newMsg > 255 {
|
|
||||||
newMsg = 1
|
|
||||||
}
|
|
||||||
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: message.GetAutoMessageId()*/}
|
|
||||||
sendData2 := msg2.Encode()
|
|
||||||
//fmt.Println("发送btm vobc 空报文:", hex.EncodeToString(sendData2), "len:", len(sendData2), "报文序列号:", msg2.MsgSerial, "atoId=", autoId, "报文序列号:", msg2.MsgSerial)
|
|
||||||
time.Sleep(time.Millisecond * 100)
|
|
||||||
err := btmCli.Send(sendData2)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(fmt.Sprintf("发送失败%v", err.Error()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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))
|
|
||||||
if req.FrameStatus == message.REQ_FRAME_STATUS_BOOT && req.MessageType == message.REQ_PACKETS_TYPE_BOOT {
|
|
||||||
//fmt.Println("000000000000000000000000000")
|
|
||||||
sendPacketFree(vobcLife, req.AutoIdFrame, req.MessageSerial)
|
|
||||||
} else if req.FrameStatus == message.REQ_FRAME_STATUS_OK {
|
|
||||||
//帧正确,删除之前发送的数据
|
|
||||||
//fmt.Println("11111111111111111111")
|
|
||||||
|
|
||||||
} else if req.FrameStatus == message.REQ_FRAME_STATUS_ERROR {
|
|
||||||
//帧不正确 重新发送2次,如果2次后仍然不正确,则删除之前发送的数据
|
|
||||||
///**/fmt.Println("22222222222222222")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var btmReceiveTime = time.Now().UnixMilli()
|
|
||||||
var vobcNumLife uint32 = 0
|
|
||||||
|
|
||||||
func handleBtmVobcFrames(cfs []byte) {
|
|
||||||
|
|
||||||
fmt.Println(fmt.Sprintf("收到源数据:%v ,数据长度:%v", hex.EncodeToString(cfs), len(cfs)))
|
|
||||||
frameType, dataText, err := message.BtmVobcDecode(cfs)
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if frameType == message.COMMAND_TYPE {
|
|
||||||
idCommand := &message.BtmVobcIdCommand{}
|
|
||||||
idCommand.Decode(dataText)
|
|
||||||
if vobcNumLife <= 0 {
|
|
||||||
vobcNumLife = idCommand.VobcLifeNum
|
|
||||||
}
|
|
||||||
sendPacketFree(vobcNumLife, idCommand.AutoIdFrame, idCommand.AutoIdFrame)
|
|
||||||
//sendPacket(vobcNumLife, idCommand.AutoIdFrame)
|
|
||||||
} else if frameType == message.REQUEST_TYPE {
|
|
||||||
if vobcNumLife <= 0 {
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
//fmt.Println(fmt.Sprintf("准备发送vobcLife:%v", vobcNumLife))
|
|
||||||
}
|
|
||||||
req := &message.BtmVobcReq{}
|
|
||||||
req.Decode(dataText)
|
|
||||||
//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 {
|
|
||||||
idCommand := &message.BtmVobcIdCommand{}
|
|
||||||
idCommand.Decode(dataText)
|
|
||||||
sendPacket(vobcNumLife, idCommand.AutoIdFrame)
|
|
||||||
} else {
|
|
||||||
|
|
||||||
RequestFramePackets(req, vobcNumLife)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
slog.Error(fmt.Sprintf("btm vobc 解析未知命令帧类型:0x%v,原始数据:%v,长度:%v", strconv.FormatInt(int64(frameType), 16), hex.EncodeToString(cfs), len(cfs)))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func testSpeed(client udp.UdpClient, speed float32) {
|
|
||||||
|
|
||||||
//client = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Speed.RemoteIp, exampleConfig.Speed.RemotePort))
|
|
||||||
ac := message.ElectricMachinery{Speed: speed, WheelDiameter: 800, IsBack: false}
|
|
||||||
var index int64
|
|
||||||
for {
|
|
||||||
data := ac.Encode()
|
|
||||||
//fmt.Println(hex.EncodeToString(data))
|
|
||||||
err := client.Send(data)
|
|
||||||
index++
|
|
||||||
if index%10 == 0 {
|
|
||||||
slog.Info(fmt.Sprintf("发送speed数据,时间戳:%v,发送次数:%v 数据:%v", time.Now().Unix(), index, hex.EncodeToString(data)))
|
|
||||||
ac = message.ElectricMachinery{Speed: 0, WheelDiameter: 800, IsBack: false}
|
|
||||||
client.Send(ac.Encode())
|
|
||||||
break
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("发送数据失败", "err", err)
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 加速度计
|
|
||||||
func testAcc(client udp.UdpClient, acc float32) {
|
|
||||||
|
|
||||||
//client = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Acc.RemoteIp, exampleConfig.Acc.RemotePort))
|
|
||||||
ac := message.Accelerometer{Acc: acc}
|
|
||||||
var index int64
|
|
||||||
for {
|
|
||||||
data := ac.Encode()
|
|
||||||
//fmt.Println(hex.EncodeToString(data))
|
|
||||||
err := client.Send(data)
|
|
||||||
index++
|
|
||||||
if index%10 == 0 {
|
|
||||||
slog.Info(fmt.Sprintf("发送acc数据,时间戳:%v,发送次数:%v 数据:%v", time.Now().Unix(), index, hex.EncodeToString(data)))
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("发送数据失败", "err", err)
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * 11)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
acc:
|
|
||||||
remoteIp: "192.168.1.201"
|
|
||||||
remotePort: 4196
|
|
||||||
speed:
|
|
||||||
remoteIp: "192.168.1.200"
|
|
||||||
remotePort: 4196
|
|
||||||
btm:
|
|
||||||
remoteIp: "192.168.1.199"
|
|
||||||
remotePort: 4196
|
|
||||||
localIp: "192.168.1.150"
|
|
||||||
localPort: 4646
|
|
||||||
trainpc:
|
|
||||||
remoteIp: "192.168.3.211"
|
|
||||||
remotePort: 10007
|
|
||||||
|
|
@ -1,27 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
type ExampleConfig struct {
|
|
||||||
Acc acc
|
|
||||||
Speed speed
|
|
||||||
Btm btm
|
|
||||||
Trainpc trainpc
|
|
||||||
}
|
|
||||||
type acc struct {
|
|
||||||
RemoteIp string
|
|
||||||
RemotePort int
|
|
||||||
}
|
|
||||||
type speed struct {
|
|
||||||
RemoteIp string
|
|
||||||
RemotePort int
|
|
||||||
}
|
|
||||||
type btm struct {
|
|
||||||
RemoteIp string
|
|
||||||
RemotePort int
|
|
||||||
LocalIp string
|
|
||||||
LocalPort int
|
|
||||||
}
|
|
||||||
|
|
||||||
type trainpc struct {
|
|
||||||
RemoteIp string
|
|
||||||
RemotePort int
|
|
||||||
}
|
|
@ -15,7 +15,7 @@ logging:
|
|||||||
# 格式化
|
# 格式化
|
||||||
# format: json
|
# format: json
|
||||||
# 日志文件路径
|
# 日志文件路径
|
||||||
path: /home/joylink/logs/bjrtsts
|
path: /logs/bjrtsts
|
||||||
# 日志文件名
|
# 日志文件名
|
||||||
fileName: bjrtsts.log
|
fileName: bjrtsts.log
|
||||||
# 单个日志文件大小,单位mb,超过会自动滚动
|
# 单个日志文件大小,单位mb,超过会自动滚动
|
||||||
|
@ -1,37 +0,0 @@
|
|||||||
# 服务配置
|
|
||||||
server:
|
|
||||||
# 服务端口
|
|
||||||
port: 9092
|
|
||||||
|
|
||||||
# 数据源
|
|
||||||
datasource:
|
|
||||||
# 数据库访问url
|
|
||||||
dsn: root:Joylink@0503@tcp(172.29.5.167:3306)/bj-rtsts?charset=utf8mb4&parseTime=true&loc=UTC
|
|
||||||
|
|
||||||
# 日志配置
|
|
||||||
logging:
|
|
||||||
# 日志级别
|
|
||||||
level: info
|
|
||||||
# 格式化
|
|
||||||
# format: json
|
|
||||||
# 日志文件路径
|
|
||||||
path: /home/joylink/logs/bjrtsts2
|
|
||||||
# 日志文件名
|
|
||||||
fileName: bjrtsts.log
|
|
||||||
# 单个日志文件大小,单位mb,超过会自动滚动
|
|
||||||
fileMaxSize: 50
|
|
||||||
# 日志文件最大备份数量
|
|
||||||
fileMaxBackups: 100
|
|
||||||
# 日志文件最大保留时间,单位 天
|
|
||||||
maxAge: 30
|
|
||||||
# 是否压缩日志
|
|
||||||
compress: false
|
|
||||||
# 控制台是否输出
|
|
||||||
stdout: false
|
|
||||||
|
|
||||||
# 消息配置
|
|
||||||
messaging:
|
|
||||||
mqtt:
|
|
||||||
address: tcp://172.29.5.168:1883
|
|
||||||
username: rtsts_service
|
|
||||||
password: joylink@0503
|
|
128
config/config.go
128
config/config.go
@ -3,9 +3,10 @@ package config
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
"joylink.club/iot/dto"
|
"joylink.club/iot/dto"
|
||||||
"log/slog"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -59,21 +60,18 @@ type mqtt struct {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// 第三方配置结构
|
// 第三方配置结构
|
||||||
type ThirdPartyConfig struct {
|
type ThridPartyConfig struct {
|
||||||
Id int32 `json:"id"`
|
Id int32 `json:"id"`
|
||||||
Dynamics DynamicsConfig `json:"dynamics" description:"动力学配置"`
|
Dynamics DynamicsConfig `json:"dynamics" description:"动力学配置"`
|
||||||
Vobc VobcConfig `json:"vobc" description:"半实物配置"`
|
Vobc VobcConfig `json:"vobc" description:"半实物配置"`
|
||||||
Interlocks []InterlockConfig `json:"interlock" description:"联锁配置"`
|
Interlocks []InterlockConfig `json:"interlock" description:"联锁配置"`
|
||||||
RsspAxleConfig RsspAxleConfig `json:"rsspAxleCfgs" description:"计轴通信配置"`
|
RsspAxleCfgs []RsspAxleConfig `json:"rsspAxleCfgs" description:"所有联锁集中站计轴RSSP-I配置"`
|
||||||
//ElectricMachinery ElectricMachineryConfig `json:"electricMachinery" description:"电机配置"`
|
ElectricMachinery ElectricMachineryConfig `json:"electricMachinery" description:"电机配置"`
|
||||||
ElectricMachinerys []ElectricMachineryConfig `json:"electricMachinerys" description:"电机配置"`
|
BtmCanet BtmCanetConfig `json:"btmCanet" description:"BTM关联的网关设备CANET配置"`
|
||||||
BtmCanet BtmCanetConfig `json:"btmCanet" description:"BTM关联的网关设备CANET配置"`
|
CidcModbus []CidcModbusConfig `json:"cidcModbus" description:"联锁驱采Modbus接口配置"`
|
||||||
CidcModbus []CidcModbusConfig `json:"cidcModbus" description:"联锁驱采Modbus接口配置"`
|
Radar RadarConfig `json:"radar" description:"车载雷达相关配置"`
|
||||||
Radar RadarConfig `json:"radar" description:"车载雷达相关配置"`
|
Acc AccConfig `json:"acc" description:"车载加速计"`
|
||||||
Acc AccConfig `json:"acc" description:"车载加速计"`
|
PcSimConfig VehiclePCSimConfig `json:"pcSimConfig" description:"车载pc仿真平台通信"`
|
||||||
//PcSimConfig VehiclePCSimConfig `json:"pcSimConfig" description:"车载pc仿真平台通信"`
|
|
||||||
PcSimConfigs []VehiclePCSimConfig `json:"pcSimConfigs" description:"车载pc仿真平台通信"`
|
|
||||||
BtmVobc BtmVobcConfig `json:"btmVobc" description:"Btm Vobc 11号线相关配置"`
|
|
||||||
}
|
}
|
||||||
type RadarConfig struct {
|
type RadarConfig struct {
|
||||||
Open bool `json:"open" description:"是否开启"`
|
Open bool `json:"open" description:"是否开启"`
|
||||||
@ -120,28 +118,16 @@ type VobcConfig struct {
|
|||||||
Open bool `json:"open" description:"是否开启"`
|
Open bool `json:"open" description:"是否开启"`
|
||||||
}
|
}
|
||||||
type InterlockConfig struct {
|
type InterlockConfig struct {
|
||||||
Open bool `json:"open" description:"是否开启"`
|
|
||||||
Ip string `json:"ip" description:"IP配置"`
|
Ip string `json:"ip" description:"IP配置"`
|
||||||
LocalPort int `json:"localPort" description:"本机监听接收端口"`
|
LocalPort int `json:"localPort" description:"本机监听接收端口"`
|
||||||
RemotePort int `json:"remotePort" description:"远端接收采集信息端口"`
|
RemotePort int `json:"remotePort" description:"远端接收采集信息端口"`
|
||||||
|
Open bool `json:"open" description:"是否开启"`
|
||||||
Code string `json:"code" description:"所属集中站"`
|
Code string `json:"code" description:"所属集中站"`
|
||||||
Line string `json:"line" description:"联锁通信协议所属线路"`
|
|
||||||
Period int `json:"period" description:"采集任务执行周期(ms)"`
|
|
||||||
}
|
}
|
||||||
type ElectricMachineryConfig struct {
|
type ElectricMachineryConfig struct {
|
||||||
Ip string `json:"ip" description:"IP配置"`
|
Ip string `json:"ip" description:"IP配置"`
|
||||||
RemotePort int `json:"remotePort" description:"远端接收信息端口"`
|
RemotePort int `json:"remotePort" description:"远端接收信息端口"`
|
||||||
Open bool `json:"open" description:"是否开启"`
|
Open bool `json:"open" description:"是否开启"`
|
||||||
EndPointA bool `json:"endPointA" description:"一号电机"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// BtmVobcConfig 11 号线 BTM vobc 网关设备配置
|
|
||||||
type BtmVobcConfig struct {
|
|
||||||
LocalUdpIp string `json:"LocalUdpIp" description:"本机监听接收UDP ip 配置"`
|
|
||||||
LocalUdpPort int `json:"localUdpPort" description:"本机监听接收UDP端口"`
|
|
||||||
RemoteIp string `json:"remoteIp" description:"btm串口设备IP配置"`
|
|
||||||
RemoteUdpPort int `json:"remoteUdpPort" description:"btm串口设备UDP端口"`
|
|
||||||
Open bool `json:"open" description:"是否开启"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BtmCanetConfig BTM CANET网关设备配置
|
// BtmCanetConfig BTM CANET网关设备配置
|
||||||
@ -152,61 +138,47 @@ type BtmCanetConfig struct {
|
|||||||
Open bool `json:"open" description:"是否开启"`
|
Open bool `json:"open" description:"是否开启"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VehiclePCSimConfig2 struct {
|
// RsspAxleConfig 计轴区段与联锁安全通信配置
|
||||||
TrainEnds bool `json:"trainEnds" description:"列车端点A"`
|
type RsspAxleConfig struct {
|
||||||
|
Open bool `json:"open" description:"是否开启"`
|
||||||
|
City string `json:"city" description:"所属城市"`
|
||||||
|
LineId string `json:"lineId" description:"所属线路"`
|
||||||
|
CentralizedStation string `json:"centralizedStation" description:"所属集中站"`
|
||||||
|
RsspCfg RsspConfig `json:"rsspCfg" description:"安全通道配置"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// RsspConfig CI系统与计轴设备的安全通信协议配置参数
|
||||||
|
// 计轴设备(管理一个集中站的所有计轴器)配置
|
||||||
|
type RsspConfig struct {
|
||||||
|
SrcAddr uint16 `json:"srcAddr" description:"16位源地址,本地地址"` //16位源地址,本地地址
|
||||||
|
DstAddr uint16 `json:"dstAddr" description:"16位目的地址,远程地址"` //16位目的地址,远程地址
|
||||||
|
DataVer1 uint32 `json:"dataVer1" description:"通道1数据版本"` //通道1数据版本
|
||||||
|
DataVer2 uint32 `json:"dataVer2" description:"通道2数据版本"` //通道2数据版本
|
||||||
|
SID1 uint32 `json:"sID1" description:"通道1源标识"` //通道1源标识
|
||||||
|
SID2 uint32 `json:"sID2" description:"通道2源标识"` //通道2源标识
|
||||||
|
SINIT1 uint32 `json:"sINIT1" description:"通道1序列初始"` //通道1序列初始
|
||||||
|
SINIT2 uint32 `json:"sINIT2" description:"通道2序列初始"` //通道2序列初始
|
||||||
|
SendingPeriod uint32 `json:"sendingPeriod" description:"发送周期值"` //接收方每个安全通信会话对应的发送周期值,单位ms
|
||||||
|
SsrRsspTimeout uint32 `json:"ssrRsspTimeout" description:"等待SSR回应的定时器超时值"` //等待SSR回应的定时器超时值,为RsspTimer时间,1=SendingPeriod
|
||||||
|
Mtv uint32 `json:"mtv" description:"最大时序偏差"` //每个安全通信会话可容忍的最大时序偏差,即当前接收的RSD的序列号与上一次RSD的序列号最大允许差值
|
||||||
|
Udl uint32 `json:"udl" description:"RSD应用数据长度配置值"` //每个安全通信会话RSD应用数据长度发送和接收的配置值(支持固定长度和可变长度);0-可变长度,大于0即固定长度
|
||||||
|
DeviceA bool `json:"deviceA" description:"true-A机;false-B机"` //true-A机;false-B机
|
||||||
|
PicType byte `json:"picType" description:"协议交互类别"` //协议交互类别,message.PicType
|
||||||
|
RemoteIp string `json:"remoteIp" description:"远程服务器ip"` //远程服务器ip
|
||||||
|
RemoteUdpPort int `json:"remoteUdpPort" description:"远程服务器端口"` //远程服务器端口
|
||||||
|
LocalUdpPort int `json:"localUdpPort" description:"本地服务器端口"` //本地服务器端口
|
||||||
|
}
|
||||||
|
|
||||||
|
type VehiclePCSimConfig struct {
|
||||||
Open bool `json:"open" description:"是否开启"`
|
Open bool `json:"open" description:"是否开启"`
|
||||||
PcSimIp string `json:"pcSimIp" description:"pc仿真平台通信ip"`
|
PcSimIp string `json:"pcSimIp" description:"pc仿真平台通信ip"`
|
||||||
PcSimPort uint32 `json:"pcSimPort" description:"pc仿真平台通信端口"`
|
PcSimPort uint32 `json:"pcSimPort" description:"pc仿真平台通信端口"`
|
||||||
LocalTestingPort uint32 `json:"localTestingPort" description:"本地测试端口"`
|
LocalTestingPort uint32 `json:"localTestingPort" description:"本地测试端口"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type VehiclePCSimConfig struct {
|
// CheckAddress 检测目标源地址目的地址是否在配置中
|
||||||
Open bool `json:"open" description:"是否开启"`
|
func (c *RsspConfig) CheckAddress(srcAddr uint16, dstAddr uint16) bool {
|
||||||
//TrainEnds bool `json:"trainEnds" description:"列车端点A?"`
|
return true
|
||||||
ConfigName string `json:"configName" description:"连接名称"`
|
|
||||||
OpenA bool `json:"openA" description:"是否开启A端"`
|
|
||||||
APcSimIp string `json:"apcSimIp" description:"pc仿真平台通信ip A端"`
|
|
||||||
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:"本地测试端口"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RsspAxleConfig Rssp计轴通信配置
|
|
||||||
type RsspAxleConfig struct {
|
|
||||||
Open bool `json:"open" description:"开启"`
|
|
||||||
StationCode string `json:"stationCode" description:"集中站编号"`
|
|
||||||
NetAConfig RsspNetConfig `json:"netAConfig" description:"A网配置"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// RsspNetConfig 计轴通信配置
|
|
||||||
type RsspNetConfig struct {
|
|
||||||
RemoteIp string `json:"remoteIp" description:"远端IP"`
|
|
||||||
RemotePort int `json:"remotePort" description:"远端端口"`
|
|
||||||
LocalPort int `json:"localPort" description:"本地端口"`
|
|
||||||
|
|
||||||
RemoteAddr string `json:"sourceAddr" description:"联锁地址(16进制,2字节)"`
|
|
||||||
LocalAddr string `json:"targetAddr" description:"计轴地址(16进制,2字节)"`
|
|
||||||
|
|
||||||
RemoteSid1 string `json:"remoteSid1" description:"联锁SID_1(16进制,4字节)"`
|
|
||||||
RemoteSid2 string `json:"remoteSid2" description:"联锁SID_2(16进制,4字节)"`
|
|
||||||
LocalSid1 string `json:"localSid1" description:"计轴SID_1(16进制,4字节)"`
|
|
||||||
LocalSid2 string `json:"localSid2" description:"计轴SID_2(16进制,4字节)"`
|
|
||||||
|
|
||||||
RemoteSinit1 string `json:"remoteSinit1" description:"联锁SINIT_1(16进制,4字节)"`
|
|
||||||
RemoteSinit2 string `json:"remoteSinit2" description:"联锁SINIT_2(16进制,4字节)"`
|
|
||||||
LocalSinit1 string `json:"localSinit1" description:"计轴SINIT_1(16进制,4字节)"`
|
|
||||||
LocalSinit2 string `json:"localSinit2" description:"计轴SINIT_2(16进制,4字节)"`
|
|
||||||
|
|
||||||
RemoteDataVer1 string `json:"remoteDataVer1" description:"联锁DATAVER_1(16进制,4字节)"`
|
|
||||||
RemoteDataVer2 string `json:"remoteDataVer2" description:"联锁DATAVER_2(16进制,4字节)"`
|
|
||||||
LocalDataVer1 string `json:"localDataVer1" description:"计轴DATAVER_1(16进制,4字节)"`
|
|
||||||
LocalDataVer2 string `json:"localDataVer2" description:"计轴DATAVER_2(16进制,4字节)"`
|
|
||||||
|
|
||||||
MaxDeviation int `json:"maxDeviation" description:"可容忍的最大时序偏差"`
|
|
||||||
WaitSSRTimeout int `json:"waitSSRTimeout" description:"等待SSR回应的定时器超时值(ms)"`
|
|
||||||
Period int `json:"period" description:"RSD发送周期(ms)"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -32,6 +32,6 @@ logging:
|
|||||||
# 消息配置
|
# 消息配置
|
||||||
messaging:
|
messaging:
|
||||||
mqtt:
|
mqtt:
|
||||||
address: tcp://192.168.1.211:1883
|
address: tcp://192.168.0.203:1883
|
||||||
username: rtsts_service
|
username: rtsts_service
|
||||||
password: joylink@0503
|
password: joylink@0503
|
14
docs/docs.go
14
docs/docs.go
@ -3263,7 +3263,7 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/simulation/balisecodec/position/modify": {
|
"/api/v1/simulation/balise/position/modify": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
@ -3312,7 +3312,7 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/simulation/balisecodec/position/reset": {
|
"/api/v1/simulation/balise/position/reset": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
@ -3361,7 +3361,7 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/simulation/balisecodec/reset": {
|
"/api/v1/simulation/balise/reset": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
@ -3408,7 +3408,7 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/simulation/balisecodec/telegram/modify": {
|
"/api/v1/simulation/balise/telegram/modify": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
@ -3457,7 +3457,7 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/simulation/balisecodec/telegram/reset": {
|
"/api/v1/simulation/balise/telegram/reset": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
@ -3506,7 +3506,7 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/simulation/balisecodec/telegram/send": {
|
"/api/v1/simulation/balise/telegram/send": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
@ -3555,7 +3555,7 @@ const docTemplate = `{
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"/api/v1/simulation/balisecodec/telegram/stop": {
|
"/api/v1/simulation/balise/telegram/stop": {
|
||||||
"put": {
|
"put": {
|
||||||
"security": [
|
"security": [
|
||||||
{
|
{
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.33.0
|
// protoc-gen-go v1.32.0
|
||||||
// protoc v4.23.1
|
// protoc v4.23.1
|
||||||
// source: common_data.proto
|
// source: common_data.proto
|
||||||
|
|
||||||
@ -228,7 +228,7 @@ type TrainEndsState struct {
|
|||||||
SpeedSensorEnableB bool `protobuf:"varint,2,opt,name=speedSensorEnableB,proto3" json:"speedSensorEnableB,omitempty"`
|
SpeedSensorEnableB bool `protobuf:"varint,2,opt,name=speedSensorEnableB,proto3" json:"speedSensorEnableB,omitempty"`
|
||||||
// 雷达是否有效
|
// 雷达是否有效
|
||||||
RadarEnable bool `protobuf:"varint,3,opt,name=radarEnable,proto3" json:"radarEnable,omitempty"`
|
RadarEnable bool `protobuf:"varint,3,opt,name=radarEnable,proto3" json:"radarEnable,omitempty"`
|
||||||
// 雷达测速差值(千米/小时)
|
// 雷达测速差值(米/秒)
|
||||||
RadarCheckSpeedDiff float32 `protobuf:"fixed32,4,opt,name=radarCheckSpeedDiff,proto3" json:"radarCheckSpeedDiff,omitempty"`
|
RadarCheckSpeedDiff float32 `protobuf:"fixed32,4,opt,name=radarCheckSpeedDiff,proto3" json:"radarCheckSpeedDiff,omitempty"`
|
||||||
// 雷达检测时间(秒)
|
// 雷达检测时间(秒)
|
||||||
RadarCheckTime int32 `protobuf:"varint,5,opt,name=radarCheckTime,proto3" json:"radarCheckTime,omitempty"`
|
RadarCheckTime int32 `protobuf:"varint,5,opt,name=radarCheckTime,proto3" json:"radarCheckTime,omitempty"`
|
||||||
@ -238,14 +238,10 @@ type TrainEndsState struct {
|
|||||||
AccCheckSpeedDiff float32 `protobuf:"fixed32,7,opt,name=accCheckSpeedDiff,proto3" json:"accCheckSpeedDiff,omitempty"`
|
AccCheckSpeedDiff float32 `protobuf:"fixed32,7,opt,name=accCheckSpeedDiff,proto3" json:"accCheckSpeedDiff,omitempty"`
|
||||||
// 加速度持续时间
|
// 加速度持续时间
|
||||||
AccCheckTime int32 `protobuf:"varint,8,opt,name=accCheckTime,proto3" json:"accCheckTime,omitempty"`
|
AccCheckTime int32 `protobuf:"varint,8,opt,name=accCheckTime,proto3" json:"accCheckTime,omitempty"`
|
||||||
// 速传速度输出(千米/小时)
|
// 速传速度输出(米/秒)
|
||||||
AccOutSpeed int32 `protobuf:"varint,9,opt,name=accOutSpeed,proto3" json:"accOutSpeed,omitempty"`
|
AccOutSpeed int32 `protobuf:"varint,9,opt,name=accOutSpeed,proto3" json:"accOutSpeed,omitempty"`
|
||||||
// 雷达速度输出(千米/小时)
|
// 雷达速度输出(米/秒)
|
||||||
RadarOutSpeed int32 `protobuf:"varint,10,opt,name=radarOutSpeed,proto3" json:"radarOutSpeed,omitempty"`
|
RadarOutSpeed int32 `protobuf:"varint,10,opt,name=radarOutSpeed,proto3" json:"radarOutSpeed,omitempty"`
|
||||||
// 记录雷达设置检测时间的时间点,用于计算周期内的数字
|
|
||||||
RadarCheckTimeOverAt int64 `protobuf:"varint,11,opt,name=radarCheckTimeOverAt,proto3" json:"radarCheckTimeOverAt,omitempty"`
|
|
||||||
// 记录加速度计设置检测时间的时间点,用于计算周期内的数字
|
|
||||||
AccCheckTimeOverAt int64 `protobuf:"varint,12,opt,name=accCheckTimeOverAt,proto3" json:"accCheckTimeOverAt,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TrainEndsState) Reset() {
|
func (x *TrainEndsState) Reset() {
|
||||||
@ -350,20 +346,6 @@ func (x *TrainEndsState) GetRadarOutSpeed() int32 {
|
|||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TrainEndsState) GetRadarCheckTimeOverAt() int64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.RadarCheckTimeOverAt
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TrainEndsState) GetAccCheckTimeOverAt() int64 {
|
|
||||||
if x != nil {
|
|
||||||
return x.AccCheckTimeOverAt
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_common_data_proto protoreflect.FileDescriptor
|
var File_common_data_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_common_data_proto_rawDesc = []byte{
|
var file_common_data_proto_rawDesc = []byte{
|
||||||
@ -406,8 +388,8 @@ var file_common_data_proto_rawDesc = []byte{
|
|||||||
0x01, 0x28, 0x05, 0x52, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x44, 0x12, 0x1a, 0x0a, 0x08,
|
0x01, 0x28, 0x05, 0x52, 0x07, 0x69, 0x64, 0x6c, 0x69, 0x6e, 0x67, 0x44, 0x12, 0x1a, 0x0a, 0x08,
|
||||||
0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
|
0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x18, 0x11, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08,
|
||||||
0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x64,
|
0x73, 0x74, 0x6f, 0x70, 0x53, 0x69, 0x67, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x6c, 0x69, 0x64,
|
||||||
0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x22, 0x88,
|
0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x6c, 0x69, 0x64, 0x65, 0x22, 0xa4,
|
||||||
0x04, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x45, 0x6e, 0x64, 0x73, 0x53, 0x74, 0x61, 0x74,
|
0x03, 0x0a, 0x0e, 0x54, 0x72, 0x61, 0x69, 0x6e, 0x45, 0x6e, 0x64, 0x73, 0x53, 0x74, 0x61, 0x74,
|
||||||
0x65, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72,
|
0x65, 0x12, 0x2e, 0x0a, 0x12, 0x73, 0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72,
|
||||||
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73,
|
0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x41, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x12, 0x73,
|
||||||
0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
0x70, 0x65, 0x65, 0x64, 0x53, 0x65, 0x6e, 0x73, 0x6f, 0x72, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65,
|
||||||
@ -433,17 +415,10 @@ var file_common_data_proto_rawDesc = []byte{
|
|||||||
0x28, 0x05, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x12,
|
0x28, 0x05, 0x52, 0x0b, 0x61, 0x63, 0x63, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64, 0x12,
|
||||||
0x24, 0x0a, 0x0d, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64,
|
0x24, 0x0a, 0x0d, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x74, 0x53, 0x70, 0x65, 0x65, 0x64,
|
||||||
0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x74,
|
0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x72, 0x61, 0x64, 0x61, 0x72, 0x4f, 0x75, 0x74,
|
||||||
0x53, 0x70, 0x65, 0x65, 0x64, 0x12, 0x32, 0x0a, 0x14, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68,
|
0x53, 0x70, 0x65, 0x65, 0x64, 0x42, 0x2f, 0x5a, 0x2d, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b,
|
||||||
0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x18, 0x0b, 0x20,
|
0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d, 0x73,
|
||||||
0x01, 0x28, 0x03, 0x52, 0x14, 0x72, 0x61, 0x64, 0x61, 0x72, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54,
|
0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x12, 0x2e, 0x0a, 0x12, 0x61, 0x63, 0x63,
|
0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x18,
|
|
||||||
0x0c, 0x20, 0x01, 0x28, 0x03, 0x52, 0x12, 0x61, 0x63, 0x63, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54,
|
|
||||||
0x69, 0x6d, 0x65, 0x4f, 0x76, 0x65, 0x72, 0x41, 0x74, 0x42, 0x2f, 0x5a, 0x2d, 0x6a, 0x6f, 0x79,
|
|
||||||
0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73,
|
|
||||||
0x74, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x63, 0x6f,
|
|
||||||
0x6d, 0x6d, 0x6f, 0x6e, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74,
|
|
||||||
0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.33.0
|
// protoc-gen-go v1.32.0
|
||||||
// protoc v4.23.1
|
// protoc v4.23.1
|
||||||
// source: ibpGraphics.proto
|
// source: ibpGraphics.proto
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.33.0
|
// protoc-gen-go v1.32.0
|
||||||
// protoc v4.23.1
|
// protoc v4.23.1
|
||||||
// source: picture.proto
|
// source: picture.proto
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.33.0
|
// protoc-gen-go v1.32.0
|
||||||
// protoc v4.23.1
|
// protoc v4.23.1
|
||||||
// source: pslGraphics.proto
|
// source: pslGraphics.proto
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.33.0
|
// protoc-gen-go v1.32.0
|
||||||
// protoc v4.23.1
|
// protoc v4.23.1
|
||||||
// source: relayCabinetLayoutGraphics.proto
|
// source: relayCabinetLayoutGraphics.proto
|
||||||
|
|
||||||
@ -90,9 +90,8 @@ func (Relay_ModelType) EnumDescriptor() ([]byte, []int) {
|
|||||||
type CjDataItem_PostionType int32
|
type CjDataItem_PostionType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
CjDataItem_Q CjDataItem_PostionType = 0
|
CjDataItem_Q CjDataItem_PostionType = 0
|
||||||
CjDataItem_H CjDataItem_PostionType = 1
|
CjDataItem_H CjDataItem_PostionType = 1
|
||||||
CjDataItem_NONE CjDataItem_PostionType = 2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for CjDataItem_PostionType.
|
// Enum value maps for CjDataItem_PostionType.
|
||||||
@ -100,12 +99,10 @@ var (
|
|||||||
CjDataItem_PostionType_name = map[int32]string{
|
CjDataItem_PostionType_name = map[int32]string{
|
||||||
0: "Q",
|
0: "Q",
|
||||||
1: "H",
|
1: "H",
|
||||||
2: "NONE",
|
|
||||||
}
|
}
|
||||||
CjDataItem_PostionType_value = map[string]int32{
|
CjDataItem_PostionType_value = map[string]int32{
|
||||||
"Q": 0,
|
"Q": 0,
|
||||||
"H": 1,
|
"H": 1,
|
||||||
"NONE": 2,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -312,9 +309,7 @@ type Relay struct {
|
|||||||
Common *CommonInfo `protobuf:"bytes,1,opt,name=common,proto3" json:"common,omitempty"`
|
Common *CommonInfo `protobuf:"bytes,1,opt,name=common,proto3" json:"common,omitempty"`
|
||||||
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` //编号
|
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"` //编号
|
||||||
// string model = 3;//型号
|
// string model = 3;//型号
|
||||||
NewModel Relay_ModelType `protobuf:"varint,4,opt,name=newModel,proto3,enum=relayCabinetGraphicData.Relay_ModelType" json:"newModel,omitempty"` //型号
|
NewModel Relay_ModelType `protobuf:"varint,4,opt,name=newModel,proto3,enum=relayCabinetGraphicData.Relay_ModelType" json:"newModel,omitempty"` //型号
|
||||||
ShowCode string `protobuf:"bytes,5,opt,name=showCode,proto3" json:"showCode,omitempty"` //展示的编号
|
|
||||||
DefaultInitialPosition CjDataItem_PostionType `protobuf:"varint,6,opt,name=defaultInitialPosition,proto3,enum=relayCabinetGraphicData.CjDataItem_PostionType" json:"defaultInitialPosition,omitempty"` //默认初始位置
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Relay) Reset() {
|
func (x *Relay) Reset() {
|
||||||
@ -370,20 +365,6 @@ func (x *Relay) GetNewModel() Relay_ModelType {
|
|||||||
return Relay_Unknown
|
return Relay_Unknown
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Relay) GetShowCode() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.ShowCode
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *Relay) GetDefaultInitialPosition() CjDataItem_PostionType {
|
|
||||||
if x != nil {
|
|
||||||
return x.DefaultInitialPosition
|
|
||||||
}
|
|
||||||
return CjDataItem_Q
|
|
||||||
}
|
|
||||||
|
|
||||||
// 断相保护器
|
// 断相保护器
|
||||||
type PhaseFailureProtector struct {
|
type PhaseFailureProtector struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
@ -568,9 +549,9 @@ type Combinationtype struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
|
Code string `protobuf:"bytes,1,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
// repeated string oldrefRelays = 2;//设备关联的继电器
|
OldrefRelays []string `protobuf:"bytes,2,rep,name=oldrefRelays,proto3" json:"oldrefRelays,omitempty"` //设备关联的继电器
|
||||||
RefRelays []uint32 `protobuf:"varint,3,rep,packed,name=refRelays,proto3" json:"refRelays,omitempty"` //设备关联的继电器
|
RefRelays []uint32 `protobuf:"varint,3,rep,packed,name=refRelays,proto3" json:"refRelays,omitempty"` //设备关联的继电器
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Combinationtype) Reset() {
|
func (x *Combinationtype) Reset() {
|
||||||
@ -612,6 +593,13 @@ func (x *Combinationtype) GetCode() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *Combinationtype) GetOldrefRelays() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.OldrefRelays
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (x *Combinationtype) GetRefRelays() []uint32 {
|
func (x *Combinationtype) GetRefRelays() []uint32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.RefRelays
|
return x.RefRelays
|
||||||
@ -845,9 +833,9 @@ type CjDataItem struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// string oldrelayId = 1;//采集对应的继电器Id
|
OldrelayId string `protobuf:"bytes,1,opt,name=oldrelayId,proto3" json:"oldrelayId,omitempty"` //采集对应的继电器Id
|
||||||
Position CjDataItem_PostionType `protobuf:"varint,2,opt,name=position,proto3,enum=relayCabinetGraphicData.CjDataItem_PostionType" json:"position,omitempty"` //继电器的位置,QH对应着吸合
|
Position CjDataItem_PostionType `protobuf:"varint,2,opt,name=position,proto3,enum=relayCabinetGraphicData.CjDataItem_PostionType" json:"position,omitempty"` //继电器的位置,QH对应着吸合
|
||||||
RelayId uint32 `protobuf:"varint,3,opt,name=relayId,proto3" json:"relayId,omitempty"` //采集对应的继电器Id
|
RelayId uint32 `protobuf:"varint,3,opt,name=relayId,proto3" json:"relayId,omitempty"` //采集对应的继电器Id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *CjDataItem) Reset() {
|
func (x *CjDataItem) Reset() {
|
||||||
@ -882,6 +870,13 @@ func (*CjDataItem) Descriptor() ([]byte, []int) {
|
|||||||
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{11}
|
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{11}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *CjDataItem) GetOldrelayId() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.OldrelayId
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (x *CjDataItem) GetPosition() CjDataItem_PostionType {
|
func (x *CjDataItem) GetPosition() CjDataItem_PostionType {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Position
|
return x.Position
|
||||||
@ -1012,8 +1007,8 @@ type QdData struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
// repeated string oldrefRelays=1;//驱动的继电器Id
|
OldrefRelays []string `protobuf:"bytes,1,rep,name=oldrefRelays,proto3" json:"oldrefRelays,omitempty"` //驱动的继电器Id
|
||||||
RefRelays []uint32 `protobuf:"varint,2,rep,packed,name=refRelays,proto3" json:"refRelays,omitempty"` //驱动的继电器Id
|
RefRelays []uint32 `protobuf:"varint,2,rep,packed,name=refRelays,proto3" json:"refRelays,omitempty"` //驱动的继电器Id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *QdData) Reset() {
|
func (x *QdData) Reset() {
|
||||||
@ -1048,6 +1043,13 @@ func (*QdData) Descriptor() ([]byte, []int) {
|
|||||||
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{14}
|
return file_relayCabinetLayoutGraphics_proto_rawDescGZIP(), []int{14}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *QdData) GetOldrefRelays() []string {
|
||||||
|
if x != nil {
|
||||||
|
return x.OldrefRelays
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (x *QdData) GetRefRelays() []uint32 {
|
func (x *QdData) GetRefRelays() []uint32 {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.RefRelays
|
return x.RefRelays
|
||||||
@ -1112,7 +1114,7 @@ var file_relayCabinetLayoutGraphics_proto_rawDesc = []byte{
|
|||||||
0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e,
|
0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e,
|
||||||
0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d,
|
0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d,
|
||||||
0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09,
|
||||||
0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xb1, 0x03, 0x0a, 0x05, 0x52, 0x65, 0x6c, 0x61, 0x79,
|
0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xac, 0x02, 0x0a, 0x05, 0x52, 0x65, 0x6c, 0x61, 0x79,
|
||||||
0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43,
|
0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43,
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||||
@ -1121,105 +1123,102 @@ var file_relayCabinetLayoutGraphics_proto_rawDesc = []byte{
|
|||||||
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43,
|
0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x28, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43,
|
||||||
0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74,
|
0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74,
|
||||||
0x61, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70,
|
0x61, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x2e, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70,
|
||||||
0x65, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x12, 0x1a, 0x0a, 0x08, 0x73,
|
0x65, 0x52, 0x08, 0x6e, 0x65, 0x77, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x22, 0x97, 0x01, 0x0a, 0x09,
|
||||||
0x68, 0x6f, 0x77, 0x43, 0x6f, 0x64, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x73,
|
0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x6e, 0x6b,
|
||||||
0x68, 0x6f, 0x77, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x67, 0x0a, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75,
|
0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x50, 0x58, 0x43, 0x5f, 0x31,
|
||||||
0x6c, 0x74, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f,
|
0x30, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x50, 0x58, 0x43, 0x5f, 0x31, 0x37,
|
||||||
0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x2f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43,
|
0x30, 0x30, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x4a, 0x58, 0x43, 0x5f, 0x34, 0x38,
|
||||||
|
0x30, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x57, 0x4a, 0x58, 0x43, 0x5f, 0x48, 0x31, 0x32,
|
||||||
|
0x35, 0x5f, 0x38, 0x30, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x58, 0x43, 0x5f, 0x31,
|
||||||
|
0x37, 0x30, 0x30, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x58, 0x43, 0x5f, 0x48, 0x33,
|
||||||
|
0x34, 0x30, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x59, 0x4a, 0x58, 0x43, 0x5f, 0x31, 0x36,
|
||||||
|
0x30, 0x5f, 0x32, 0x36, 0x30, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08, 0x4a, 0x5a, 0x58, 0x43, 0x5f,
|
||||||
|
0x48, 0x31, 0x38, 0x10, 0x08, 0x22, 0x5c, 0x0a, 0x15, 0x50, 0x68, 0x61, 0x73, 0x65, 0x46, 0x61,
|
||||||
|
0x69, 0x6c, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63, 0x74, 0x6f, 0x72, 0x12, 0x2f,
|
||||||
|
0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17,
|
||||||
|
0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d,
|
||||||
|
0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12,
|
||||||
|
0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63,
|
||||||
|
0x6f, 0x64, 0x65, 0x22, 0x57, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x6c, 0x46, 0x61, 0x75,
|
||||||
|
0x6c, 0x74, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||||
|
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
|
||||||
|
0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f,
|
||||||
|
0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
|
||||||
|
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xc1, 0x01, 0x0a,
|
||||||
|
0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x52, 0x65, 0x6c,
|
||||||
|
0x61, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x54, 0x0a, 0x10, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e,
|
||||||
|
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b,
|
||||||
|
0x32, 0x28, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47,
|
||||||
|
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x62, 0x69,
|
||||||
|
0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x52, 0x10, 0x63, 0x6f, 0x6d, 0x62,
|
||||||
|
0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x12, 0x42, 0x0a, 0x0a,
|
||||||
|
0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0e,
|
||||||
|
0x32, 0x22, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x52,
|
||||||
|
0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x66, 0x2e, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65,
|
||||||
|
0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65,
|
||||||
|
0x22, 0x67, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74,
|
||||||
|
0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
|
0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x6c, 0x64, 0x72, 0x65,
|
||||||
|
0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6f,
|
||||||
|
0x6c, 0x64, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x72,
|
||||||
|
0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x09,
|
||||||
|
0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0x7c, 0x0a, 0x0c, 0x55, 0x6e, 0x69,
|
||||||
|
0x71, 0x75, 0x65, 0x49, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x74,
|
||||||
|
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a,
|
||||||
|
0x06, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x6c,
|
||||||
|
0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x1b, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67, 0x73,
|
||||||
|
0x43, 0x6f, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61,
|
||||||
|
0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x62, 0x65, 0x6c, 0x6f,
|
||||||
|
0x6e, 0x67, 0x73, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e,
|
||||||
|
0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5c, 0x0a, 0x04, 0x43, 0x69, 0x43, 0x6a, 0x12,
|
||||||
|
0x18, 0x0a, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05,
|
||||||
|
0x52, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6a, 0x4c,
|
||||||
|
0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x6c, 0x61,
|
||||||
|
0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
|
||||||
|
0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52, 0x06, 0x63,
|
||||||
|
0x6a, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x5a, 0x0a, 0x09, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x53,
|
||||||
|
0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09,
|
||||||
|
0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69, 0x73,
|
||||||
|
0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43,
|
||||||
0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74,
|
0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74,
|
||||||
0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x50, 0x6f, 0x73,
|
0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69, 0x73,
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x52, 0x16, 0x64, 0x65, 0x66, 0x61, 0x75, 0x6c,
|
0x74, 0x22, 0x4b, 0x0a, 0x06, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x09, 0x72,
|
||||||
0x74, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x50, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e,
|
0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x23,
|
||||||
0x22, 0x97, 0x01, 0x0a, 0x09, 0x4d, 0x6f, 0x64, 0x65, 0x6c, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0b,
|
|
||||||
0x0a, 0x07, 0x55, 0x6e, 0x6b, 0x6e, 0x6f, 0x77, 0x6e, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
|
|
||||||
0x50, 0x58, 0x43, 0x5f, 0x31, 0x30, 0x30, 0x30, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x50,
|
|
||||||
0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57, 0x4a,
|
|
||||||
0x58, 0x43, 0x5f, 0x34, 0x38, 0x30, 0x10, 0x03, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x57, 0x4a, 0x58,
|
|
||||||
0x43, 0x5f, 0x48, 0x31, 0x32, 0x35, 0x5f, 0x38, 0x30, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4a,
|
|
||||||
0x57, 0x58, 0x43, 0x5f, 0x31, 0x37, 0x30, 0x30, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4a, 0x57,
|
|
||||||
0x58, 0x43, 0x5f, 0x48, 0x33, 0x34, 0x30, 0x10, 0x06, 0x12, 0x11, 0x0a, 0x0d, 0x4a, 0x59, 0x4a,
|
|
||||||
0x58, 0x43, 0x5f, 0x31, 0x36, 0x30, 0x5f, 0x32, 0x36, 0x30, 0x10, 0x07, 0x12, 0x0c, 0x0a, 0x08,
|
|
||||||
0x4a, 0x5a, 0x58, 0x43, 0x5f, 0x48, 0x31, 0x38, 0x10, 0x08, 0x22, 0x5c, 0x0a, 0x15, 0x50, 0x68,
|
|
||||||
0x61, 0x73, 0x65, 0x46, 0x61, 0x69, 0x6c, 0x75, 0x72, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x65, 0x63,
|
|
||||||
0x74, 0x6f, 0x72, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20,
|
|
||||||
0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74,
|
|
||||||
0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f,
|
|
||||||
0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01,
|
|
||||||
0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0x57, 0x0a, 0x10, 0x53, 0x69, 0x67, 0x6e,
|
|
||||||
0x61, 0x6c, 0x46, 0x61, 0x75, 0x6c, 0x74, 0x41, 0x6c, 0x61, 0x72, 0x6d, 0x12, 0x2f, 0x0a, 0x06,
|
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67,
|
|
||||||
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f,
|
|
||||||
0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a,
|
|
||||||
0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64,
|
|
||||||
0x65, 0x22, 0xc1, 0x01, 0x0a, 0x11, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x6c, 0x61,
|
|
||||||
0x74, 0x65, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18,
|
|
||||||
0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x54, 0x0a, 0x10, 0x63,
|
|
||||||
0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x73, 0x18,
|
|
||||||
0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62,
|
|
||||||
0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e,
|
|
||||||
0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x52,
|
|
||||||
0x10, 0x63, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65,
|
|
||||||
0x73, 0x12, 0x42, 0x0a, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x18,
|
|
||||||
0x06, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x22, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
|
|
||||||
0x61, 0x74, 0x61, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x74, 0x65, 0x64, 0x52, 0x65, 0x66, 0x2e, 0x44,
|
|
||||||
0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x52, 0x0a, 0x64, 0x65, 0x76, 0x69, 0x63,
|
|
||||||
0x65, 0x54, 0x79, 0x70, 0x65, 0x22, 0x43, 0x0a, 0x0f, 0x43, 0x6f, 0x6d, 0x62, 0x69, 0x6e, 0x61,
|
|
||||||
0x74, 0x69, 0x6f, 0x6e, 0x74, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
|
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09,
|
|
||||||
0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52,
|
|
||||||
0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0x7c, 0x0a, 0x0c, 0x55, 0x6e,
|
|
||||||
0x69, 0x71, 0x75, 0x65, 0x49, 0x64, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69,
|
|
||||||
0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x16,
|
|
||||||
0x0a, 0x06, 0x6c, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06,
|
|
||||||
0x6c, 0x69, 0x6e, 0x65, 0x49, 0x64, 0x12, 0x40, 0x0a, 0x1b, 0x62, 0x65, 0x6c, 0x6f, 0x6e, 0x67,
|
|
||||||
0x73, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74,
|
|
||||||
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x1b, 0x62, 0x65, 0x6c,
|
|
||||||
0x6f, 0x6e, 0x67, 0x73, 0x43, 0x6f, 0x6e, 0x63, 0x65, 0x6e, 0x74, 0x72, 0x61, 0x74, 0x69, 0x6f,
|
|
||||||
0x6e, 0x53, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x22, 0x5c, 0x0a, 0x04, 0x43, 0x69, 0x43, 0x6a,
|
|
||||||
0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x05, 0x52, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x63, 0x6a,
|
|
||||||
0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x6c,
|
|
||||||
0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
|
|
||||||
0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52, 0x06,
|
|
||||||
0x63, 0x6a, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x5a, 0x0a, 0x09, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61,
|
|
||||||
0x53, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28,
|
|
||||||
0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69,
|
|
||||||
0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79,
|
|
||||||
0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61,
|
|
||||||
0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69,
|
|
||||||
0x73, 0x74, 0x22, 0x4b, 0x0a, 0x06, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x12, 0x41, 0x0a, 0x09,
|
|
||||||
0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32,
|
|
||||||
0x23, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72,
|
|
||||||
0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61,
|
|
||||||
0x49, 0x74, 0x65, 0x6d, 0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22,
|
|
||||||
0x9a, 0x01, 0x0a, 0x0a, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x4b,
|
|
||||||
0x0a, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e,
|
|
||||||
0x32, 0x2f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47,
|
|
||||||
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74,
|
|
||||||
0x61, 0x49, 0x74, 0x65, 0x6d, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70,
|
|
||||||
0x65, 0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x72,
|
|
||||||
0x65, 0x6c, 0x61, 0x79, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x72, 0x65,
|
|
||||||
0x6c, 0x61, 0x79, 0x49, 0x64, 0x22, 0x25, 0x0a, 0x0b, 0x50, 0x6f, 0x73, 0x74, 0x69, 0x6f, 0x6e,
|
|
||||||
0x54, 0x79, 0x70, 0x65, 0x12, 0x05, 0x0a, 0x01, 0x51, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x48,
|
|
||||||
0x10, 0x01, 0x12, 0x08, 0x0a, 0x04, 0x4e, 0x4f, 0x4e, 0x45, 0x10, 0x02, 0x22, 0x5c, 0x0a, 0x04,
|
|
||||||
0x43, 0x69, 0x51, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x18,
|
|
||||||
0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x64, 0x73, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x3a,
|
|
||||||
0x0a, 0x06, 0x71, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x22,
|
|
||||||
0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61,
|
0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61,
|
||||||
0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x51, 0x64, 0x44, 0x61, 0x74, 0x61, 0x53,
|
0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x49,
|
||||||
0x65, 0x74, 0x52, 0x06, 0x71, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x5a, 0x0a, 0x09, 0x51, 0x64,
|
0x74, 0x65, 0x6d, 0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x22, 0xb0,
|
||||||
0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18,
|
0x01, 0x0a, 0x0a, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61, 0x49, 0x74, 0x65, 0x6d, 0x12, 0x1e, 0x0a,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x39, 0x0a, 0x07, 0x62,
|
0x0a, 0x6f, 0x6c, 0x64, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x49, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28,
|
||||||
0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x72,
|
0x09, 0x52, 0x0a, 0x6f, 0x6c, 0x64, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x49, 0x64, 0x12, 0x4b, 0x0a,
|
||||||
0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68,
|
0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32,
|
||||||
0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x51, 0x64, 0x44, 0x61, 0x74, 0x61, 0x52, 0x07, 0x62,
|
0x2f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74, 0x47, 0x72,
|
||||||
0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x26, 0x0a, 0x06, 0x51, 0x64, 0x44, 0x61, 0x74, 0x61,
|
0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6a, 0x44, 0x61, 0x74, 0x61,
|
||||||
0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x02, 0x20,
|
0x49, 0x74, 0x65, 0x6d, 0x2e, 0x50, 0x6f, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65,
|
||||||
0x03, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x42, 0x2d,
|
0x52, 0x08, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x72, 0x65,
|
||||||
0x5a, 0x2b, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62,
|
0x6c, 0x61, 0x79, 0x49, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x72, 0x65, 0x6c,
|
||||||
0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64,
|
0x61, 0x79, 0x49, 0x64, 0x22, 0x1b, 0x0a, 0x0b, 0x50, 0x6f, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54,
|
||||||
0x74, 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70,
|
0x79, 0x70, 0x65, 0x12, 0x05, 0x0a, 0x01, 0x51, 0x10, 0x00, 0x12, 0x05, 0x0a, 0x01, 0x48, 0x10,
|
||||||
0x72, 0x6f, 0x74, 0x6f, 0x33,
|
0x01, 0x22, 0x5c, 0x0a, 0x04, 0x43, 0x69, 0x51, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x73, 0x43,
|
||||||
|
0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x64, 0x73, 0x43, 0x6f,
|
||||||
|
0x75, 0x6e, 0x74, 0x12, 0x3a, 0x0a, 0x06, 0x71, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20,
|
||||||
|
0x03, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e,
|
||||||
|
0x65, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x51, 0x64,
|
||||||
|
0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x52, 0x06, 0x71, 0x64, 0x4c, 0x69, 0x73, 0x74, 0x22,
|
||||||
|
0x5a, 0x0a, 0x09, 0x51, 0x64, 0x44, 0x61, 0x74, 0x61, 0x53, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04,
|
||||||
|
0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65,
|
||||||
|
0x12, 0x39, 0x0a, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x18, 0x02, 0x20, 0x03, 0x28,
|
||||||
|
0x0b, 0x32, 0x1f, 0x2e, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x43, 0x61, 0x62, 0x69, 0x6e, 0x65, 0x74,
|
||||||
|
0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x51, 0x64, 0x44, 0x61,
|
||||||
|
0x74, 0x61, 0x52, 0x07, 0x62, 0x69, 0x74, 0x4c, 0x69, 0x73, 0x74, 0x22, 0x4a, 0x0a, 0x06, 0x51,
|
||||||
|
0x64, 0x44, 0x61, 0x74, 0x61, 0x12, 0x22, 0x0a, 0x0c, 0x6f, 0x6c, 0x64, 0x72, 0x65, 0x66, 0x52,
|
||||||
|
0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x6f, 0x6c, 0x64,
|
||||||
|
0x72, 0x65, 0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x72, 0x65, 0x66,
|
||||||
|
0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x09, 0x72, 0x65,
|
||||||
|
0x66, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x73, 0x42, 0x2d, 0x5a, 0x2b, 0x6a, 0x6f, 0x79, 0x6c, 0x69,
|
||||||
|
0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73,
|
||||||
|
0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x61,
|
||||||
|
0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -1271,22 +1270,21 @@ var file_relayCabinetLayoutGraphics_proto_depIdxs = []int32{
|
|||||||
18, // 9: relayCabinetGraphicData.RelayCabinet.common:type_name -> graphicData.CommonInfo
|
18, // 9: relayCabinetGraphicData.RelayCabinet.common:type_name -> graphicData.CommonInfo
|
||||||
18, // 10: relayCabinetGraphicData.Relay.common:type_name -> graphicData.CommonInfo
|
18, // 10: relayCabinetGraphicData.Relay.common:type_name -> graphicData.CommonInfo
|
||||||
0, // 11: relayCabinetGraphicData.Relay.newModel:type_name -> relayCabinetGraphicData.Relay.ModelType
|
0, // 11: relayCabinetGraphicData.Relay.newModel:type_name -> relayCabinetGraphicData.Relay.ModelType
|
||||||
1, // 12: relayCabinetGraphicData.Relay.defaultInitialPosition:type_name -> relayCabinetGraphicData.CjDataItem.PostionType
|
18, // 12: relayCabinetGraphicData.PhaseFailureProtector.common:type_name -> graphicData.CommonInfo
|
||||||
18, // 13: relayCabinetGraphicData.PhaseFailureProtector.common:type_name -> graphicData.CommonInfo
|
18, // 13: relayCabinetGraphicData.SignalFaultAlarm.common:type_name -> graphicData.CommonInfo
|
||||||
18, // 14: relayCabinetGraphicData.SignalFaultAlarm.common:type_name -> graphicData.CommonInfo
|
8, // 14: relayCabinetGraphicData.DeviceRelateRelay.combinationtypes:type_name -> relayCabinetGraphicData.Combinationtype
|
||||||
8, // 15: relayCabinetGraphicData.DeviceRelateRelay.combinationtypes:type_name -> relayCabinetGraphicData.Combinationtype
|
19, // 15: relayCabinetGraphicData.DeviceRelateRelay.deviceType:type_name -> graphicData.RelatedRef.DeviceType
|
||||||
19, // 16: relayCabinetGraphicData.DeviceRelateRelay.deviceType:type_name -> graphicData.RelatedRef.DeviceType
|
11, // 16: relayCabinetGraphicData.CiCj.cjList:type_name -> relayCabinetGraphicData.CjDataSet
|
||||||
11, // 17: relayCabinetGraphicData.CiCj.cjList:type_name -> relayCabinetGraphicData.CjDataSet
|
12, // 17: relayCabinetGraphicData.CjDataSet.bitList:type_name -> relayCabinetGraphicData.CjData
|
||||||
12, // 18: relayCabinetGraphicData.CjDataSet.bitList:type_name -> relayCabinetGraphicData.CjData
|
13, // 18: relayCabinetGraphicData.CjData.refRelays:type_name -> relayCabinetGraphicData.CjDataItem
|
||||||
13, // 19: relayCabinetGraphicData.CjData.refRelays:type_name -> relayCabinetGraphicData.CjDataItem
|
1, // 19: relayCabinetGraphicData.CjDataItem.position:type_name -> relayCabinetGraphicData.CjDataItem.PostionType
|
||||||
1, // 20: relayCabinetGraphicData.CjDataItem.position:type_name -> relayCabinetGraphicData.CjDataItem.PostionType
|
15, // 20: relayCabinetGraphicData.CiQd.qdList:type_name -> relayCabinetGraphicData.QdDataSet
|
||||||
15, // 21: relayCabinetGraphicData.CiQd.qdList:type_name -> relayCabinetGraphicData.QdDataSet
|
16, // 21: relayCabinetGraphicData.QdDataSet.bitList:type_name -> relayCabinetGraphicData.QdData
|
||||||
16, // 22: relayCabinetGraphicData.QdDataSet.bitList:type_name -> relayCabinetGraphicData.QdData
|
22, // [22:22] is the sub-list for method output_type
|
||||||
23, // [23:23] is the sub-list for method output_type
|
22, // [22:22] is the sub-list for method input_type
|
||||||
23, // [23:23] is the sub-list for method input_type
|
22, // [22:22] is the sub-list for extension type_name
|
||||||
23, // [23:23] is the sub-list for extension type_name
|
22, // [22:22] is the sub-list for extension extendee
|
||||||
23, // [23:23] is the sub-list for extension extendee
|
0, // [0:22] is the sub-list for field type_name
|
||||||
0, // [0:23] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_relayCabinetLayoutGraphics_proto_init() }
|
func init() { file_relayCabinetLayoutGraphics_proto_init() }
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,6 +1,6 @@
|
|||||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||||
// versions:
|
// versions:
|
||||||
// protoc-gen-go v1.33.0
|
// protoc-gen-go v1.32.0
|
||||||
// protoc v4.23.1
|
// protoc v4.23.1
|
||||||
// source: tccGraphics.proto
|
// source: tccGraphics.proto
|
||||||
|
|
||||||
@ -20,104 +20,52 @@ const (
|
|||||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||||
)
|
)
|
||||||
|
|
||||||
type TccElementColor int32
|
type TccKeyType int32
|
||||||
|
|
||||||
const (
|
const (
|
||||||
TccElementColor_green TccElementColor = 0
|
TccKeyType_driverControllerActivationClint TccKeyType = 0 //司控器激活端
|
||||||
TccElementColor_red TccElementColor = 1
|
TccKeyType_frontAndRearDirectionalControl TccKeyType = 1 //前后方向控制
|
||||||
TccElementColor_blue TccElementColor = 2
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// Enum value maps for TccElementColor.
|
// Enum value maps for TccKeyType.
|
||||||
var (
|
var (
|
||||||
TccElementColor_name = map[int32]string{
|
TccKeyType_name = map[int32]string{
|
||||||
0: "green",
|
0: "driverControllerActivationClint",
|
||||||
1: "red",
|
1: "frontAndRearDirectionalControl",
|
||||||
2: "blue",
|
|
||||||
}
|
}
|
||||||
TccElementColor_value = map[string]int32{
|
TccKeyType_value = map[string]int32{
|
||||||
"green": 0,
|
"driverControllerActivationClint": 0,
|
||||||
"red": 1,
|
"frontAndRearDirectionalControl": 1,
|
||||||
"blue": 2,
|
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
func (x TccElementColor) Enum() *TccElementColor {
|
func (x TccKeyType) Enum() *TccKeyType {
|
||||||
p := new(TccElementColor)
|
p := new(TccKeyType)
|
||||||
*p = x
|
*p = x
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x TccElementColor) String() string {
|
func (x TccKeyType) String() string {
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (TccElementColor) Descriptor() protoreflect.EnumDescriptor {
|
func (TccKeyType) Descriptor() protoreflect.EnumDescriptor {
|
||||||
return file_tccGraphics_proto_enumTypes[0].Descriptor()
|
return file_tccGraphics_proto_enumTypes[0].Descriptor()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (TccElementColor) Type() protoreflect.EnumType {
|
func (TccKeyType) Type() protoreflect.EnumType {
|
||||||
return &file_tccGraphics_proto_enumTypes[0]
|
return &file_tccGraphics_proto_enumTypes[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x TccElementColor) Number() protoreflect.EnumNumber {
|
func (x TccKeyType) Number() protoreflect.EnumNumber {
|
||||||
return protoreflect.EnumNumber(x)
|
return protoreflect.EnumNumber(x)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deprecated: Use TccElementColor.Descriptor instead.
|
// Deprecated: Use TccKeyType.Descriptor instead.
|
||||||
func (TccElementColor) EnumDescriptor() ([]byte, []int) {
|
func (TccKeyType) EnumDescriptor() ([]byte, []int) {
|
||||||
return file_tccGraphics_proto_rawDescGZIP(), []int{0}
|
return file_tccGraphics_proto_rawDescGZIP(), []int{0}
|
||||||
}
|
}
|
||||||
|
|
||||||
type TccKey_TccKeyType int32
|
|
||||||
|
|
||||||
const (
|
|
||||||
TccKey_driverControllerActivationClint TccKey_TccKeyType = 0 //司控器激活端
|
|
||||||
TccKey_frontAndRearDirectionalControl TccKey_TccKeyType = 1 //前后方向控制
|
|
||||||
TccKey_trainDoorMode TccKey_TccKeyType = 2 //列车门模式
|
|
||||||
)
|
|
||||||
|
|
||||||
// Enum value maps for TccKey_TccKeyType.
|
|
||||||
var (
|
|
||||||
TccKey_TccKeyType_name = map[int32]string{
|
|
||||||
0: "driverControllerActivationClint",
|
|
||||||
1: "frontAndRearDirectionalControl",
|
|
||||||
2: "trainDoorMode",
|
|
||||||
}
|
|
||||||
TccKey_TccKeyType_value = map[string]int32{
|
|
||||||
"driverControllerActivationClint": 0,
|
|
||||||
"frontAndRearDirectionalControl": 1,
|
|
||||||
"trainDoorMode": 2,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
func (x TccKey_TccKeyType) Enum() *TccKey_TccKeyType {
|
|
||||||
p := new(TccKey_TccKeyType)
|
|
||||||
*p = x
|
|
||||||
return p
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x TccKey_TccKeyType) String() string {
|
|
||||||
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (TccKey_TccKeyType) Descriptor() protoreflect.EnumDescriptor {
|
|
||||||
return file_tccGraphics_proto_enumTypes[1].Descriptor()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (TccKey_TccKeyType) Type() protoreflect.EnumType {
|
|
||||||
return &file_tccGraphics_proto_enumTypes[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x TccKey_TccKeyType) Number() protoreflect.EnumNumber {
|
|
||||||
return protoreflect.EnumNumber(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use TccKey_TccKeyType.Descriptor instead.
|
|
||||||
func (TccKey_TccKeyType) EnumDescriptor() ([]byte, []int) {
|
|
||||||
return file_tccGraphics_proto_rawDescGZIP(), []int{3, 0}
|
|
||||||
}
|
|
||||||
|
|
||||||
type TccGraphicStorage struct {
|
type TccGraphicStorage struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
@ -128,7 +76,6 @@ type TccGraphicStorage struct {
|
|||||||
TccTexts []*TccText `protobuf:"bytes,3,rep,name=tccTexts,proto3" json:"tccTexts,omitempty"`
|
TccTexts []*TccText `protobuf:"bytes,3,rep,name=tccTexts,proto3" json:"tccTexts,omitempty"`
|
||||||
TccKeys []*TccKey `protobuf:"bytes,4,rep,name=tccKeys,proto3" json:"tccKeys,omitempty"`
|
TccKeys []*TccKey `protobuf:"bytes,4,rep,name=tccKeys,proto3" json:"tccKeys,omitempty"`
|
||||||
TccHandles []*TccHandle `protobuf:"bytes,5,rep,name=tccHandles,proto3" json:"tccHandles,omitempty"`
|
TccHandles []*TccHandle `protobuf:"bytes,5,rep,name=tccHandles,proto3" json:"tccHandles,omitempty"`
|
||||||
TccLights []*TccLight `protobuf:"bytes,6,rep,name=tccLights,proto3" json:"tccLights,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TccGraphicStorage) Reset() {
|
func (x *TccGraphicStorage) Reset() {
|
||||||
@ -198,13 +145,6 @@ func (x *TccGraphicStorage) GetTccHandles() []*TccHandle {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TccGraphicStorage) GetTccLights() []*TccLight {
|
|
||||||
if x != nil {
|
|
||||||
return x.TccLights
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// * TCC按钮
|
// * TCC按钮
|
||||||
type TccButton struct {
|
type TccButton struct {
|
||||||
state protoimpl.MessageState
|
state protoimpl.MessageState
|
||||||
@ -355,9 +295,9 @@ type TccKey struct {
|
|||||||
sizeCache protoimpl.SizeCache
|
sizeCache protoimpl.SizeCache
|
||||||
unknownFields protoimpl.UnknownFields
|
unknownFields protoimpl.UnknownFields
|
||||||
|
|
||||||
Common *CommonInfo `protobuf:"bytes,1,opt,name=common,proto3" json:"common,omitempty"`
|
Common *CommonInfo `protobuf:"bytes,1,opt,name=common,proto3" json:"common,omitempty"`
|
||||||
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
|
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
|
||||||
Type TccKey_TccKeyType `protobuf:"varint,3,opt,name=type,proto3,enum=tccGraphicData.TccKey_TccKeyType" json:"type,omitempty"`
|
Type TccKeyType `protobuf:"varint,3,opt,name=type,proto3,enum=tccGraphicData.TccKeyType" json:"type,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TccKey) Reset() {
|
func (x *TccKey) Reset() {
|
||||||
@ -406,11 +346,11 @@ func (x *TccKey) GetCode() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *TccKey) GetType() TccKey_TccKeyType {
|
func (x *TccKey) GetType() TccKeyType {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Type
|
return x.Type
|
||||||
}
|
}
|
||||||
return TccKey_driverControllerActivationClint
|
return TccKeyType_driverControllerActivationClint
|
||||||
}
|
}
|
||||||
|
|
||||||
// * TCC手柄
|
// * TCC手柄
|
||||||
@ -469,86 +409,6 @@ func (x *TccHandle) GetCode() string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
// * TCC灯
|
|
||||||
type TccLight struct {
|
|
||||||
state protoimpl.MessageState
|
|
||||||
sizeCache protoimpl.SizeCache
|
|
||||||
unknownFields protoimpl.UnknownFields
|
|
||||||
|
|
||||||
Common *CommonInfo `protobuf:"bytes,1,opt,name=common,proto3" json:"common,omitempty"`
|
|
||||||
Code string `protobuf:"bytes,2,opt,name=code,proto3" json:"code,omitempty"`
|
|
||||||
LightColor TccElementColor `protobuf:"varint,3,opt,name=lightColor,proto3,enum=tccGraphicData.TccElementColor" json:"lightColor,omitempty"`
|
|
||||||
ActiveLevel bool `protobuf:"varint,4,opt,name=activeLevel,proto3" json:"activeLevel,omitempty"` //有效电平
|
|
||||||
InitialState bool `protobuf:"varint,5,opt,name=initialState,proto3" json:"initialState,omitempty"` //初始状态,与有效电平对比,如何相同,刚开始打开驾驶台的时候就是亮着的
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TccLight) Reset() {
|
|
||||||
*x = TccLight{}
|
|
||||||
if protoimpl.UnsafeEnabled {
|
|
||||||
mi := &file_tccGraphics_proto_msgTypes[5]
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TccLight) String() string {
|
|
||||||
return protoimpl.X.MessageStringOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*TccLight) ProtoMessage() {}
|
|
||||||
|
|
||||||
func (x *TccLight) ProtoReflect() protoreflect.Message {
|
|
||||||
mi := &file_tccGraphics_proto_msgTypes[5]
|
|
||||||
if protoimpl.UnsafeEnabled && x != nil {
|
|
||||||
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
|
|
||||||
if ms.LoadMessageInfo() == nil {
|
|
||||||
ms.StoreMessageInfo(mi)
|
|
||||||
}
|
|
||||||
return ms
|
|
||||||
}
|
|
||||||
return mi.MessageOf(x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Deprecated: Use TccLight.ProtoReflect.Descriptor instead.
|
|
||||||
func (*TccLight) Descriptor() ([]byte, []int) {
|
|
||||||
return file_tccGraphics_proto_rawDescGZIP(), []int{5}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TccLight) GetCommon() *CommonInfo {
|
|
||||||
if x != nil {
|
|
||||||
return x.Common
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TccLight) GetCode() string {
|
|
||||||
if x != nil {
|
|
||||||
return x.Code
|
|
||||||
}
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TccLight) GetLightColor() TccElementColor {
|
|
||||||
if x != nil {
|
|
||||||
return x.LightColor
|
|
||||||
}
|
|
||||||
return TccElementColor_green
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TccLight) GetActiveLevel() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.ActiveLevel
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (x *TccLight) GetInitialState() bool {
|
|
||||||
if x != nil {
|
|
||||||
return x.InitialState
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var File_tccGraphics_proto protoreflect.FileDescriptor
|
var File_tccGraphics_proto protoreflect.FileDescriptor
|
||||||
|
|
||||||
var file_tccGraphics_proto_rawDesc = []byte{
|
var file_tccGraphics_proto_rawDesc = []byte{
|
||||||
@ -556,7 +416,7 @@ var file_tccGraphics_proto_rawDesc = []byte{
|
|||||||
0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x74, 0x63, 0x63, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
|
0x6f, 0x74, 0x6f, 0x12, 0x0e, 0x74, 0x63, 0x63, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
|
||||||
0x61, 0x74, 0x61, 0x1a, 0x1b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x79, 0x6f,
|
0x61, 0x74, 0x61, 0x1a, 0x1b, 0x73, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x4c, 0x61, 0x79, 0x6f,
|
||||||
0x75, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
0x75, 0x74, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f,
|
||||||
0x22, 0xd5, 0x02, 0x0a, 0x11, 0x54, 0x63, 0x63, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x53,
|
0x22, 0x9d, 0x02, 0x0a, 0x11, 0x54, 0x63, 0x63, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x53,
|
||||||
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73,
|
0x74, 0x6f, 0x72, 0x61, 0x67, 0x65, 0x12, 0x2b, 0x0a, 0x06, 0x63, 0x61, 0x6e, 0x76, 0x61, 0x73,
|
||||||
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
|
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
|
||||||
0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x52, 0x06, 0x63, 0x61, 0x6e,
|
0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x61, 0x6e, 0x76, 0x61, 0x73, 0x52, 0x06, 0x63, 0x61, 0x6e,
|
||||||
@ -574,67 +434,45 @@ var file_tccGraphics_proto_rawDesc = []byte{
|
|||||||
0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x63, 0x63, 0x47,
|
0x6c, 0x65, 0x73, 0x18, 0x05, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x74, 0x63, 0x63, 0x47,
|
||||||
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x63, 0x63, 0x48, 0x61,
|
0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x63, 0x63, 0x48, 0x61,
|
||||||
0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0a, 0x74, 0x63, 0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73,
|
0x6e, 0x64, 0x6c, 0x65, 0x52, 0x0a, 0x74, 0x63, 0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x73,
|
||||||
0x12, 0x36, 0x0a, 0x09, 0x74, 0x63, 0x63, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x06, 0x20,
|
0x22, 0x72, 0x0a, 0x09, 0x54, 0x63, 0x63, 0x42, 0x75, 0x74, 0x74, 0x6f, 0x6e, 0x12, 0x2f, 0x0a,
|
||||||
0x03, 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x74, 0x63, 0x63, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63,
|
0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
|
||||||
0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x63, 0x63, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x52, 0x09, 0x74,
|
0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
||||||
0x63, 0x63, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x22, 0x72, 0x0a, 0x09, 0x54, 0x63, 0x63, 0x42,
|
0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12,
|
||||||
0x75, 0x74, 0x74, 0x6f, 0x6e, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18,
|
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
|
||||||
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
|
0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x73, 0x65,
|
||||||
0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06,
|
0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x69, 0x73, 0x53, 0x65, 0x6c, 0x66, 0x52,
|
||||||
0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02,
|
0x65, 0x73, 0x65, 0x74, 0x22, 0x9a, 0x01, 0x0a, 0x07, 0x54, 0x63, 0x63, 0x54, 0x65, 0x78, 0x74,
|
||||||
0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x69, 0x73,
|
0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b,
|
||||||
0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52,
|
0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43,
|
||||||
0x0b, 0x69, 0x73, 0x53, 0x65, 0x6c, 0x66, 0x52, 0x65, 0x73, 0x65, 0x74, 0x22, 0x9a, 0x01, 0x0a,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
||||||
0x07, 0x54, 0x63, 0x63, 0x54, 0x65, 0x78, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d,
|
0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52,
|
||||||
0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68,
|
0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74,
|
||||||
0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66,
|
0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12,
|
||||||
0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64,
|
0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05,
|
||||||
0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x18, 0x0a,
|
0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x1a, 0x0a, 0x08, 0x66, 0x6f, 0x6e, 0x74, 0x53, 0x69, 0x7a,
|
||||||
0x07, 0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07,
|
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x66, 0x6f, 0x6e, 0x74, 0x53, 0x69, 0x7a,
|
||||||
0x63, 0x6f, 0x6e, 0x74, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72,
|
0x65, 0x22, 0x7d, 0x0a, 0x06, 0x54, 0x63, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x06, 0x63,
|
||||||
0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x63, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x1a, 0x0a,
|
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72,
|
||||||
0x08, 0x66, 0x6f, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52,
|
0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e,
|
||||||
0x08, 0x66, 0x6f, 0x6e, 0x74, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xee, 0x01, 0x0a, 0x06, 0x54, 0x63,
|
0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04,
|
||||||
0x63, 0x4b, 0x65, 0x79, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01,
|
0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65,
|
||||||
0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61,
|
0x12, 0x2e, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x1a,
|
||||||
0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63,
|
0x2e, 0x74, 0x63, 0x63, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e,
|
||||||
0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20,
|
|
||||||
0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x35, 0x0a, 0x04, 0x74, 0x79, 0x70,
|
|
||||||
0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x21, 0x2e, 0x74, 0x63, 0x63, 0x47, 0x72, 0x61,
|
|
||||||
0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x54, 0x63, 0x63, 0x4b, 0x65, 0x79, 0x2e,
|
|
||||||
0x54, 0x63, 0x63, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
0x54, 0x63, 0x63, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65,
|
||||||
0x22, 0x68, 0x0a, 0x0a, 0x54, 0x63, 0x63, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65, 0x12, 0x23,
|
0x22, 0x50, 0x0a, 0x09, 0x54, 0x63, 0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x2f, 0x0a,
|
||||||
0x0a, 0x1f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x6c,
|
0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e,
|
||||||
0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c, 0x69, 0x6e,
|
0x67, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d,
|
||||||
0x74, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x41, 0x6e, 0x64, 0x52,
|
0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12,
|
||||||
0x65, 0x61, 0x72, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c, 0x43, 0x6f,
|
0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f,
|
||||||
0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x10, 0x01, 0x12, 0x11, 0x0a, 0x0d, 0x74, 0x72, 0x61, 0x69, 0x6e,
|
0x64, 0x65, 0x2a, 0x55, 0x0a, 0x0a, 0x54, 0x63, 0x63, 0x4b, 0x65, 0x79, 0x54, 0x79, 0x70, 0x65,
|
||||||
0x44, 0x6f, 0x6f, 0x72, 0x4d, 0x6f, 0x64, 0x65, 0x10, 0x02, 0x22, 0x50, 0x0a, 0x09, 0x54, 0x63,
|
0x12, 0x23, 0x0a, 0x1f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f,
|
||||||
0x63, 0x48, 0x61, 0x6e, 0x64, 0x6c, 0x65, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f,
|
0x6c, 0x6c, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x76, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6c,
|
||||||
0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70, 0x68, 0x69,
|
0x69, 0x6e, 0x74, 0x10, 0x00, 0x12, 0x22, 0x0a, 0x1e, 0x66, 0x72, 0x6f, 0x6e, 0x74, 0x41, 0x6e,
|
||||||
0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e, 0x66, 0x6f,
|
0x64, 0x52, 0x65, 0x61, 0x72, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x61, 0x6c,
|
||||||
0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65,
|
0x43, 0x6f, 0x6e, 0x74, 0x72, 0x6f, 0x6c, 0x10, 0x01, 0x42, 0x2d, 0x5a, 0x2b, 0x6a, 0x6f, 0x79,
|
||||||
0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x22, 0xd6, 0x01, 0x0a,
|
0x6c, 0x69, 0x6e, 0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73,
|
||||||
0x08, 0x54, 0x63, 0x63, 0x4c, 0x69, 0x67, 0x68, 0x74, 0x12, 0x2f, 0x0a, 0x06, 0x63, 0x6f, 0x6d,
|
0x74, 0x73, 0x2d, 0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x64, 0x61,
|
||||||
0x6d, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x61, 0x70,
|
0x74, 0x61, 0x5f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
||||||
0x68, 0x69, 0x63, 0x44, 0x61, 0x74, 0x61, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x49, 0x6e,
|
|
||||||
0x66, 0x6f, 0x52, 0x06, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f,
|
|
||||||
0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x3f,
|
|
||||||
0x0a, 0x0a, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01,
|
|
||||||
0x28, 0x0e, 0x32, 0x1f, 0x2e, 0x74, 0x63, 0x63, 0x47, 0x72, 0x61, 0x70, 0x68, 0x69, 0x63, 0x44,
|
|
||||||
0x61, 0x74, 0x61, 0x2e, 0x54, 0x63, 0x63, 0x45, 0x6c, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x43, 0x6f,
|
|
||||||
0x6c, 0x6f, 0x72, 0x52, 0x0a, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x12,
|
|
||||||
0x20, 0x0a, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x18, 0x04,
|
|
||||||
0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x63, 0x74, 0x69, 0x76, 0x65, 0x4c, 0x65, 0x76, 0x65,
|
|
||||||
0x6c, 0x12, 0x22, 0x0a, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74,
|
|
||||||
0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x69, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x6c,
|
|
||||||
0x53, 0x74, 0x61, 0x74, 0x65, 0x2a, 0x2f, 0x0a, 0x0f, 0x54, 0x63, 0x63, 0x45, 0x6c, 0x65, 0x6d,
|
|
||||||
0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x12, 0x09, 0x0a, 0x05, 0x67, 0x72, 0x65, 0x65,
|
|
||||||
0x6e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x72, 0x65, 0x64, 0x10, 0x01, 0x12, 0x08, 0x0a, 0x04,
|
|
||||||
0x62, 0x6c, 0x75, 0x65, 0x10, 0x02, 0x42, 0x2d, 0x5a, 0x2b, 0x6a, 0x6f, 0x79, 0x6c, 0x69, 0x6e,
|
|
||||||
0x6b, 0x2e, 0x63, 0x6c, 0x75, 0x62, 0x2f, 0x62, 0x6a, 0x2d, 0x72, 0x74, 0x73, 0x74, 0x73, 0x2d,
|
|
||||||
0x73, 0x65, 0x72, 0x76, 0x65, 0x72, 0x2f, 0x64, 0x74, 0x6f, 0x2f, 0x64, 0x61, 0x74, 0x61, 0x5f,
|
|
||||||
0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -649,39 +487,34 @@ func file_tccGraphics_proto_rawDescGZIP() []byte {
|
|||||||
return file_tccGraphics_proto_rawDescData
|
return file_tccGraphics_proto_rawDescData
|
||||||
}
|
}
|
||||||
|
|
||||||
var file_tccGraphics_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
|
var file_tccGraphics_proto_enumTypes = make([]protoimpl.EnumInfo, 1)
|
||||||
var file_tccGraphics_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
|
var file_tccGraphics_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
|
||||||
var file_tccGraphics_proto_goTypes = []interface{}{
|
var file_tccGraphics_proto_goTypes = []interface{}{
|
||||||
(TccElementColor)(0), // 0: tccGraphicData.TccElementColor
|
(TccKeyType)(0), // 0: tccGraphicData.TccKeyType
|
||||||
(TccKey_TccKeyType)(0), // 1: tccGraphicData.TccKey.TccKeyType
|
(*TccGraphicStorage)(nil), // 1: tccGraphicData.TccGraphicStorage
|
||||||
(*TccGraphicStorage)(nil), // 2: tccGraphicData.TccGraphicStorage
|
(*TccButton)(nil), // 2: tccGraphicData.TccButton
|
||||||
(*TccButton)(nil), // 3: tccGraphicData.TccButton
|
(*TccText)(nil), // 3: tccGraphicData.TccText
|
||||||
(*TccText)(nil), // 4: tccGraphicData.TccText
|
(*TccKey)(nil), // 4: tccGraphicData.TccKey
|
||||||
(*TccKey)(nil), // 5: tccGraphicData.TccKey
|
(*TccHandle)(nil), // 5: tccGraphicData.TccHandle
|
||||||
(*TccHandle)(nil), // 6: tccGraphicData.TccHandle
|
(*Canvas)(nil), // 6: graphicData.Canvas
|
||||||
(*TccLight)(nil), // 7: tccGraphicData.TccLight
|
(*CommonInfo)(nil), // 7: graphicData.CommonInfo
|
||||||
(*Canvas)(nil), // 8: graphicData.Canvas
|
|
||||||
(*CommonInfo)(nil), // 9: graphicData.CommonInfo
|
|
||||||
}
|
}
|
||||||
var file_tccGraphics_proto_depIdxs = []int32{
|
var file_tccGraphics_proto_depIdxs = []int32{
|
||||||
8, // 0: tccGraphicData.TccGraphicStorage.canvas:type_name -> graphicData.Canvas
|
6, // 0: tccGraphicData.TccGraphicStorage.canvas:type_name -> graphicData.Canvas
|
||||||
3, // 1: tccGraphicData.TccGraphicStorage.tccButtons:type_name -> tccGraphicData.TccButton
|
2, // 1: tccGraphicData.TccGraphicStorage.tccButtons:type_name -> tccGraphicData.TccButton
|
||||||
4, // 2: tccGraphicData.TccGraphicStorage.tccTexts:type_name -> tccGraphicData.TccText
|
3, // 2: tccGraphicData.TccGraphicStorage.tccTexts:type_name -> tccGraphicData.TccText
|
||||||
5, // 3: tccGraphicData.TccGraphicStorage.tccKeys:type_name -> tccGraphicData.TccKey
|
4, // 3: tccGraphicData.TccGraphicStorage.tccKeys:type_name -> tccGraphicData.TccKey
|
||||||
6, // 4: tccGraphicData.TccGraphicStorage.tccHandles:type_name -> tccGraphicData.TccHandle
|
5, // 4: tccGraphicData.TccGraphicStorage.tccHandles:type_name -> tccGraphicData.TccHandle
|
||||||
7, // 5: tccGraphicData.TccGraphicStorage.tccLights:type_name -> tccGraphicData.TccLight
|
7, // 5: tccGraphicData.TccButton.common:type_name -> graphicData.CommonInfo
|
||||||
9, // 6: tccGraphicData.TccButton.common:type_name -> graphicData.CommonInfo
|
7, // 6: tccGraphicData.TccText.common:type_name -> graphicData.CommonInfo
|
||||||
9, // 7: tccGraphicData.TccText.common:type_name -> graphicData.CommonInfo
|
7, // 7: tccGraphicData.TccKey.common:type_name -> graphicData.CommonInfo
|
||||||
9, // 8: tccGraphicData.TccKey.common:type_name -> graphicData.CommonInfo
|
0, // 8: tccGraphicData.TccKey.type:type_name -> tccGraphicData.TccKeyType
|
||||||
1, // 9: tccGraphicData.TccKey.type:type_name -> tccGraphicData.TccKey.TccKeyType
|
7, // 9: tccGraphicData.TccHandle.common:type_name -> graphicData.CommonInfo
|
||||||
9, // 10: tccGraphicData.TccHandle.common:type_name -> graphicData.CommonInfo
|
10, // [10:10] is the sub-list for method output_type
|
||||||
9, // 11: tccGraphicData.TccLight.common:type_name -> graphicData.CommonInfo
|
10, // [10:10] is the sub-list for method input_type
|
||||||
0, // 12: tccGraphicData.TccLight.lightColor:type_name -> tccGraphicData.TccElementColor
|
10, // [10:10] is the sub-list for extension type_name
|
||||||
13, // [13:13] is the sub-list for method output_type
|
10, // [10:10] is the sub-list for extension extendee
|
||||||
13, // [13:13] is the sub-list for method input_type
|
0, // [0:10] is the sub-list for field type_name
|
||||||
13, // [13:13] is the sub-list for extension type_name
|
|
||||||
13, // [13:13] is the sub-list for extension extendee
|
|
||||||
0, // [0:13] is the sub-list for field type_name
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() { file_tccGraphics_proto_init() }
|
func init() { file_tccGraphics_proto_init() }
|
||||||
@ -751,26 +584,14 @@ func file_tccGraphics_proto_init() {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_tccGraphics_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
|
|
||||||
switch v := v.(*TccLight); i {
|
|
||||||
case 0:
|
|
||||||
return &v.state
|
|
||||||
case 1:
|
|
||||||
return &v.sizeCache
|
|
||||||
case 2:
|
|
||||||
return &v.unknownFields
|
|
||||||
default:
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
type x struct{}
|
type x struct{}
|
||||||
out := protoimpl.TypeBuilder{
|
out := protoimpl.TypeBuilder{
|
||||||
File: protoimpl.DescBuilder{
|
File: protoimpl.DescBuilder{
|
||||||
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
|
||||||
RawDescriptor: file_tccGraphics_proto_rawDesc,
|
RawDescriptor: file_tccGraphics_proto_rawDesc,
|
||||||
NumEnums: 2,
|
NumEnums: 1,
|
||||||
NumMessages: 6,
|
NumMessages: 5,
|
||||||
NumExtensions: 0,
|
NumExtensions: 0,
|
||||||
NumServices: 0,
|
NumServices: 0,
|
||||||
},
|
},
|
||||||
|
@ -40,7 +40,6 @@ type RunConfigSelectOption struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TrainConnTypeConfigDto struct {
|
type TrainConnTypeConfigDto struct {
|
||||||
TypeName string `json:"typeName" form:"typeName"` // 连接名称; //连接名称
|
|
||||||
ConnType state_proto.TrainConnState_TrainConnType `json:"connType" form:"connType"` // NONE = 0 未知连接 ;VOBC = 1; //半实物;PC_SIM = 2; //PC仿真
|
ConnType state_proto.TrainConnState_TrainConnType `json:"connType" form:"connType"` // NONE = 0 未知连接 ;VOBC = 1; //半实物;PC_SIM = 2; //PC仿真
|
||||||
}
|
}
|
||||||
|
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -71,13 +71,7 @@ type AddTrainReqDtoNew struct {
|
|||||||
//车头所在link内的偏移量,单位为mm
|
//车头所在link内的偏移量,单位为mm
|
||||||
HeadOffset int64 `json:"headOffset" form:"headOffset"`
|
HeadOffset int64 `json:"headOffset" form:"headOffset"`
|
||||||
//列车长度
|
//列车长度
|
||||||
TrainLength int64 `json:"trainLength" from:"trainLength"`
|
TrainLength int64 `json:"trainLength" from:"trainLength"`
|
||||||
TrainLoad int32 `json:"trainLoad" from:"trainLoad"`
|
|
||||||
TrainMaxSpeed float32 `json:"trainMaxSpeed" from:"trainMaxSpeed"`
|
|
||||||
TrainMaxAcc float32 `json:"trainMaxAcc" from:"trainMaxAcc"`
|
|
||||||
TrainMaxBrake float32 `json:"trainMaxBrake" from:"trainMaxBrake"`
|
|
||||||
TrainEmergencyBrake float32 `json:"trainEmergencyBrake" from:"trainEmergencyBrake"`
|
|
||||||
TrainCoachNum uint32 `json:"trainCoachNum" from:"trainCoachNum"`
|
|
||||||
// 场景ID
|
// 场景ID
|
||||||
MapId int32 `json:"mapId" from:"mapId"`
|
MapId int32 `json:"mapId" from:"mapId"`
|
||||||
WheelDiameter int32 `json:"wheelDiameter" from:"wheelDiameter"`
|
WheelDiameter int32 `json:"wheelDiameter" from:"wheelDiameter"`
|
||||||
@ -105,15 +99,14 @@ type ConfigTrainEnds struct {
|
|||||||
SpeedSensorEnableA bool `json:"speedSensorEnableA"` // 2端速度传感器是否有效
|
SpeedSensorEnableA bool `json:"speedSensorEnableA"` // 2端速度传感器是否有效
|
||||||
SpeedSensorEnableB bool `json:"speedSensorEnableB"` // 2端速度传感器是否有效
|
SpeedSensorEnableB bool `json:"speedSensorEnableB"` // 2端速度传感器是否有效
|
||||||
RadarEnable bool `json:"radarEnable"` // 雷达是否有效
|
RadarEnable bool `json:"radarEnable"` // 雷达是否有效
|
||||||
RadarCheckSpeedDiff float32 `json:"radarCheckSpeedDiff"` // 雷达测速数值(千米/小时)
|
RadarCheckSpeedDiff float32 `json:"radarCheckSpeedDiff"` // 雷达测速数值
|
||||||
RadarCheckTime int32 `json:"radarCheckTime"` // 雷达检测时间(秒)
|
RadarCheckTime int32 `json:"radarCheckTime"` // 雷达检测时间(秒)
|
||||||
|
|
||||||
AccEnable bool `json:"accEnable"` // 加速计是否有效
|
AccEnable bool `json:"accEnable"` // 加速计是否有效
|
||||||
AccCheckSpeedDiff float32 `json:"accCheckSpeedDiff"` // 加速计速度差
|
AccCheckSpeedDiff float32 `json:"accCheckSpeedDiff"` // 加速计速度差
|
||||||
AccCheckTime int32 `json:"accCheckTime"` // 加速计储蓄时间
|
AccCheckTime int32 `json:"accCheckTime"` // 加速计储蓄时间
|
||||||
AccOutSpeed int32 `json:"accOutSpeed"` // 速传速度输出(千米/小时)
|
AccOutSpeed int32 `json:"accOutSpeed"` // 速传速度输出
|
||||||
RadarOutSpeed int32 `json:"radarOutSpeed"` // 雷达速度输出(千米/小时)
|
RadarOutSpeed int32 `json:"radarOutSpeed"` // 雷达速度输出
|
||||||
|
|
||||||
}
|
}
|
||||||
type ConfigTrainData struct {
|
type ConfigTrainData struct {
|
||||||
//Mass int32 `json:"mass" form:"mass"` // 列车的质量(100=1ton)
|
//Mass int32 `json:"mass" form:"mass"` // 列车的质量(100=1ton)
|
||||||
@ -158,7 +151,6 @@ type TrainConnThirdDto struct {
|
|||||||
SimulationId string `json:"simulationId" form:"simulationId"`
|
SimulationId string `json:"simulationId" form:"simulationId"`
|
||||||
Id string `json:"id" form:"id"` // 列车Id
|
Id string `json:"id" form:"id"` // 列车Id
|
||||||
ConnType state_proto.TrainConnState_TrainConnType `json:"connType" form:"connType"` //连接类型 0=未连接;1=半实物;2= 车载仿真
|
ConnType state_proto.TrainConnState_TrainConnType `json:"connType" form:"connType"` //连接类型 0=未连接;1=半实物;2= 车载仿真
|
||||||
TypeName string `json:"typeName" form:"typeName"` //连接名称
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 为仿真添加测试车请求
|
// 为仿真添加测试车请求
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -17,16 +17,11 @@ type TrainInfoReqDto struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TrainInfoDto struct {
|
type TrainInfoDto struct {
|
||||||
Id int32 `json:"id" form:"id"`
|
Id int32 `json:"id" form:"id"`
|
||||||
Name string `json:"name" form:"name"`
|
Name string `json:"name" form:"name"`
|
||||||
TrainModel int32 `json:"train_model" form:"train_model"`
|
TrainModel int32 `json:"train_model" form:"train_model"`
|
||||||
CarriageLength int32 `json:"carriage_length" form:"carriage_length"`
|
CarriageLength int32 `json:"carriage_length" form:"carriage_length"`
|
||||||
TotalLength int32 `json:"total_length" form:"total_length"`
|
TotalLength int32 `json:"total_length" form:"total_length"`
|
||||||
TrainLoad int32 `json:"train_load" form:"train_load"`
|
|
||||||
TrainMaxSpeed float32 `json:"train_max_speed" form:"train_max_speed"`
|
|
||||||
TrainMaxAcc float32 `json:"train_max_acc" form:"train_max_acc"`
|
|
||||||
TrainMaxBrake float32 `json:"train_max_brake" form:"train_max_brake"`
|
|
||||||
TrainEmergencyBrake float32 `json:"train_emergency_brake" form:"train_emergency_brake"`
|
|
||||||
//MinDiameter int32 `json:"min_diameter" form:"min_diameter"`
|
//MinDiameter int32 `json:"min_diameter" form:"min_diameter"`
|
||||||
//MaxDiameter int32 `json:"max_diameter" form:"max_diameter"`
|
//MaxDiameter int32 `json:"max_diameter" form:"max_diameter"`
|
||||||
TrainSets string `json:"train_sets" form:"train_sets"`
|
TrainSets string `json:"train_sets" form:"train_sets"`
|
||||||
@ -58,18 +53,13 @@ func ConvertDtoFromTrain(t *PublishedDto) *TrainInfoDto {
|
|||||||
message := &data_proto.Train{}
|
message := &data_proto.Train{}
|
||||||
proto.Unmarshal(t.Proto, message)
|
proto.Unmarshal(t.Proto, message)
|
||||||
return &TrainInfoDto{
|
return &TrainInfoDto{
|
||||||
Id: t.ID,
|
Id: t.ID,
|
||||||
Name: t.Name,
|
Name: t.Name,
|
||||||
Description: t.Note,
|
Description: t.Note,
|
||||||
TrainModel: int32(message.TrainModel),
|
TrainModel: int32(message.TrainModel),
|
||||||
CarriageLength: message.CarriageLength,
|
CarriageLength: message.CarriageLength,
|
||||||
TotalLength: message.TotalLength,
|
TotalLength: message.TotalLength,
|
||||||
TrainControlMapId: message.TrainControlMapId,
|
TrainControlMapId: message.TrainControlMapId,
|
||||||
TrainLoad: message.TrainLoad,
|
|
||||||
TrainMaxSpeed: message.TrainMaxSpeed,
|
|
||||||
TrainMaxAcc: message.TrainMaxAcc,
|
|
||||||
TrainMaxBrake: message.TrainMaxBrake,
|
|
||||||
TrainEmergencyBrake: message.TrainEmergencyBrake,
|
|
||||||
//TrainControlMapCode: message.TrainControlMapCode,
|
//TrainControlMapCode: message.TrainControlMapCode,
|
||||||
//MinDiameter: message.MinDiameter,
|
//MinDiameter: message.MinDiameter,
|
||||||
//MaxDiameter: message.MaxDiameter,
|
//MaxDiameter: message.MaxDiameter,
|
||||||
|
@ -1,406 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/balisecodec"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Transponder struct {
|
|
||||||
// 应答器编号
|
|
||||||
Code int
|
|
||||||
// 应答器名称
|
|
||||||
Name string
|
|
||||||
// 应答器类型
|
|
||||||
Type string
|
|
||||||
// 校验码
|
|
||||||
CheckSum string
|
|
||||||
// 830报文
|
|
||||||
Msg830 string
|
|
||||||
// 1023报文
|
|
||||||
Msg1023 string
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
transponderMap := ReadTransponders()
|
|
||||||
// v := transponderMap["FB121_BGZ"]
|
|
||||||
// b1023 := convertToBalise1023(v.Msg1023)
|
|
||||||
// replaced830 := replaceFirst10Bits(convertTo830(v.Msg830))
|
|
||||||
// scrambled830 := scrambling(replaced830, b1023.S)
|
|
||||||
// compare830(scrambled830, b1023.data830)
|
|
||||||
|
|
||||||
// count := 0
|
|
||||||
for _, v := range transponderMap {
|
|
||||||
// slog.Info("transponder", "name", v.Name, "code", v.Code, "checksum", v.CheckSum, "msg830", v.Msg830, "msg1023", v.Msg1023)
|
|
||||||
byte104, err := balisecodec.DecodeByteString(v.Msg1023)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("解码应答器数据失败", "name", v.Name, "code", v.Code, "err", err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
compare104Bytes(byte104, balisecodec.ConvertByteStringToBytes(v.Msg830))
|
|
||||||
// b1023 := convertToBalise1023(v.Msg1023)
|
|
||||||
// source830 := convertTo830(v.Msg830)
|
|
||||||
// // replaced830 := replaceFirst10Bits(source830)
|
|
||||||
// // compare830(reverted830, source830)
|
|
||||||
// descrambled830 := descrambling(b1023.data830, b1023.S)
|
|
||||||
// reverted830 := revertFirst10Bits(descrambled830)
|
|
||||||
// // // scrambled830 := scrambling(replaced830, b1023.S)
|
|
||||||
// compare830(source830, reverted830)
|
|
||||||
// count++
|
|
||||||
// if count >= 10 {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 比较830位数据
|
|
||||||
func compare104Bytes(bytes104 []byte, compare104 []byte) {
|
|
||||||
if len(bytes104) != 104 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
for i := 0; i < 104; i++ {
|
|
||||||
fmt.Printf("%02x\n", bytes104[i])
|
|
||||||
fmt.Printf("%02x\n\n", compare104[i])
|
|
||||||
if bytes104[i] != compare104[i] {
|
|
||||||
slog.Info("error", "index", i, "bytes104", fmt.Sprintf("%02x", bytes104[i]), "compare", fmt.Sprintf("%02x", compare104[i]))
|
|
||||||
panic("104 bytes compare error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Balise1023 struct {
|
|
||||||
bits []byte // 1023报文,1023bit
|
|
||||||
data []byte // 数据位,913bit
|
|
||||||
data830 []byte // 830位数据
|
|
||||||
cb []byte // 控制位,3bit
|
|
||||||
sb []byte // 加扰位,12bit
|
|
||||||
S uint32 // 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
|
||||||
esb []byte // 额外修正位,10bit
|
|
||||||
checkSum []byte // 校验位,85bit
|
|
||||||
}
|
|
||||||
|
|
||||||
func newBalise1023(bits []byte) *Balise1023 {
|
|
||||||
if len(bits) != 1023 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// for i := 0; i < 1023; i++ {
|
|
||||||
// if i%10 == 0 {
|
|
||||||
// println()
|
|
||||||
// }
|
|
||||||
// print(1022-i, ":", bits[i], ",")
|
|
||||||
// }
|
|
||||||
// println()
|
|
||||||
balise1023 := &Balise1023{
|
|
||||||
bits: bits,
|
|
||||||
}
|
|
||||||
balise1023.data = balise1023.getRange(1022, 110)
|
|
||||||
if len(balise1023.data) != 913 {
|
|
||||||
panic("invalid data length")
|
|
||||||
}
|
|
||||||
balise1023.data830 = convert913To830(balise1023.data)
|
|
||||||
balise1023.check11To10()
|
|
||||||
balise1023.cb = balise1023.getRange(109, 107)
|
|
||||||
for i, v := range balise1023.cb {
|
|
||||||
n := 109 - i
|
|
||||||
name := "b" + strconv.Itoa(109-i)
|
|
||||||
slog.Info("cb", name, v)
|
|
||||||
if n == 109 && v == 1 {
|
|
||||||
slog.Error("控制位cb错误:cb109应该为0,实际为1")
|
|
||||||
} else if n == 108 && v == 1 {
|
|
||||||
slog.Error("控制位cb错误:cb108应该为0,实际为1")
|
|
||||||
} else if n == 107 && v == 0 {
|
|
||||||
slog.Error("控制位cb错误:cb107应该为1,实际为0")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
balise1023.sb = balise1023.getRange(106, 95)
|
|
||||||
balise1023.S = calculateS(balise1023.sb)
|
|
||||||
balise1023.esb = balise1023.getRange(94, 85)
|
|
||||||
balise1023.checkSum = balise1023.getRange(84, 0)
|
|
||||||
slog.Info("msg length", "datalen", len(balise1023.data), "cblen", len(balise1023.cb), "sblen", len(balise1023.sb), "esblen", len(balise1023.esb), "checkSumlen", len(balise1023.checkSum))
|
|
||||||
return balise1023
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Balise1023) getRange(start, end int) []byte {
|
|
||||||
if start < 0 || end < 0 || start < end || start > 1022 {
|
|
||||||
panic("invalid range")
|
|
||||||
}
|
|
||||||
return b.bits[1022-start : 1022-(end-1)]
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *Balise1023) check11To10() {
|
|
||||||
b913 := b.data
|
|
||||||
compare := convert830To913(b.data830)
|
|
||||||
for i := 0; i < 913; i++ {
|
|
||||||
if b913[i] != compare[i] {
|
|
||||||
slog.Info("error", "idx", i, "b913", b913[i], "compare", compare[i])
|
|
||||||
panic("10 to 11 bit error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换字节字符串到bit数组,左边为最高有效位(MSB)
|
|
||||||
func convertStringBytesToBits(msg string) []byte {
|
|
||||||
length := len(msg)
|
|
||||||
println("msg:", msg)
|
|
||||||
bytes := make([]byte, length/2)
|
|
||||||
for i := 0; i < length; i += 2 {
|
|
||||||
v, err := strconv.ParseUint(msg[i:i+2], 16, 8)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
bytes[i/2] = byte(v)
|
|
||||||
// slog.Info("i", "byteidx", i/2, "byte", fmt.Sprintf("%02x", v))
|
|
||||||
}
|
|
||||||
// 字节转换为bit数组
|
|
||||||
bits := make([]byte, length/2*8)
|
|
||||||
for i, bt := range bytes {
|
|
||||||
for j := 0; j < 8; j++ {
|
|
||||||
move := 7 - j
|
|
||||||
idx := i*8 + j
|
|
||||||
bits[idx] = (bt >> move) & 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bits
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertTo830(msg string) []byte {
|
|
||||||
length := len(msg)
|
|
||||||
if length != 208 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 字节转换为bit数组
|
|
||||||
bits := convertStringBytesToBits(msg)
|
|
||||||
bits830 := bits[0:830]
|
|
||||||
return bits830
|
|
||||||
}
|
|
||||||
|
|
||||||
func convertToBalise1023(msg string) *Balise1023 {
|
|
||||||
length := len(msg)
|
|
||||||
if length != 256 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 字节转换为bit数组
|
|
||||||
bits := convertStringBytesToBits(msg)
|
|
||||||
bits1023 := bits[0:1023]
|
|
||||||
slog.Info("bits length", "len", len(bits1023))
|
|
||||||
return newBalise1023(bits1023)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,除了第一个10位值,其余值求和,然后循环2的10次方次与其他值求和结果相加后模2的10次方,若结果和第一个10位值相同,则结束,此值即为原始的第一个10位值,将此值替换为第一个10位二进制数组,依然是左边为MSB
|
|
||||||
func revertFirst10Bits(b []byte) []byte {
|
|
||||||
if len(b) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
|
||||||
bits := make([]uint16, 83)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
bits[i] = uint16(balisecodec.ToValLeftMsb(b[i*10 : i*10+10]))
|
|
||||||
// 打印输出
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
fmt.Printf("%01b", b[i*10+j])
|
|
||||||
}
|
|
||||||
print(" ")
|
|
||||||
if i != 0 && i%10 == 9 {
|
|
||||||
println()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
// 将除了第一个10位字整数求和
|
|
||||||
sum := uint64(0)
|
|
||||||
for i := 1; i < 83; i++ {
|
|
||||||
sum += uint64(bits[i])
|
|
||||||
}
|
|
||||||
// 循环2的10次方次与其他值求和结果相加后模2的10次方
|
|
||||||
for i := 0; i < 1024; i++ {
|
|
||||||
test := sum + uint64(i)
|
|
||||||
if test%1024 == uint64(bits[0]) {
|
|
||||||
bits[0] = uint16(i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
slog.Info("还原第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
|
|
||||||
rbits := make([]byte, 830)
|
|
||||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
|
||||||
u0bits := balisecodec.ToBitsLeftMsb(int(bits[0]), 10)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
rbits[i] = u0bits[i]
|
|
||||||
}
|
|
||||||
for i := 10; i < 830; i++ {
|
|
||||||
rbits[i] = b[i]
|
|
||||||
}
|
|
||||||
// compare830(b, rbits)
|
|
||||||
return rbits
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,然后求和后模2的10次方,得到的结果覆盖第一个10位值,然后将整个10位数组转换为二进制数组,依然是左边为MSB
|
|
||||||
func replaceFirst10Bits(b []byte) []byte {
|
|
||||||
if len(b) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
|
||||||
bits := make([]uint16, 83)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
bits[i] = uint16(balisecodec.ToValLeftMsb(b[i*10 : i*10+10]))
|
|
||||||
// 打印输出
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
fmt.Printf("%01b", b[i*10+j])
|
|
||||||
}
|
|
||||||
print(" ")
|
|
||||||
if i != 0 && i%10 == 9 {
|
|
||||||
println()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
// 将每一个10位字整数求和后模2的10次方,得到的结果覆盖第一个10位值
|
|
||||||
sum := uint64(0)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
sum += uint64(bits[i])
|
|
||||||
// fmt.Printf("i=%d, v10=%d, v10b=%010b\n", i, bits[i], bits[i])
|
|
||||||
}
|
|
||||||
bits[0] = uint16(sum % 1024)
|
|
||||||
slog.Info("替换第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
|
|
||||||
rbits := make([]byte, 830)
|
|
||||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
|
||||||
u0bits := balisecodec.ToBitsLeftMsb(int(bits[0]), 10)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
rbits[i] = u0bits[i]
|
|
||||||
}
|
|
||||||
for i := 10; i < 830; i++ {
|
|
||||||
rbits[i] = b[i]
|
|
||||||
}
|
|
||||||
// compare830(b, rbits)
|
|
||||||
return rbits
|
|
||||||
}
|
|
||||||
|
|
||||||
// 由加扰位计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
|
||||||
func calculateS(sb []byte) uint32 {
|
|
||||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
|
||||||
if len(sb) != 12 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
B := balisecodec.ToValLeftMsb(sb)
|
|
||||||
const A uint64 = 2801775573
|
|
||||||
S := uint32((A * uint64(B)) % (1 << 32))
|
|
||||||
slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S))
|
|
||||||
return S
|
|
||||||
}
|
|
||||||
|
|
||||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
|
||||||
// 1. 生成一个32位的线性反馈移位寄存器,其初始状态为S(左边为MSB)
|
|
||||||
// 2. 系数h31,h30,h29,h27,h25和h0等于1(表示连接),所有其他系数都为0(表示不连接)
|
|
||||||
// 3. 然后电路被时钟驱动m-1次,其中m是数据位的数量,同时输入dn的每一位dn(m-1),dn(m-2),...,dn(0),便生成加扰后的码位(在第一个时钟之前读取第一个输出out(m-1))
|
|
||||||
// 4. 生成的加扰码位是dn的每一位与S的最高位的异或值
|
|
||||||
// 5. 生成的加扰码位会根据系数进行异或反馈回S的最低位
|
|
||||||
// 几种可能性:
|
|
||||||
func scrambling(dn []byte, S uint32) []byte {
|
|
||||||
if len(dn) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// const Polynomial = 0x000000AF
|
|
||||||
out := make([]byte, len(dn))
|
|
||||||
t := S // 寄存器初始值
|
|
||||||
for i := 0; i < len(dn); i++ {
|
|
||||||
msb := (t >> 31) & 1
|
|
||||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
|
||||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
|
||||||
xor := uint32(out[i])
|
|
||||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
|
||||||
t = (t << 1) | xor
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
func descrambling(dn []byte, S uint32) []byte {
|
|
||||||
if len(dn) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// const Polynomial = 0x000000AF
|
|
||||||
out := make([]byte, len(dn))
|
|
||||||
t := S // 寄存器初始值
|
|
||||||
for i := 0; i < len(dn); i++ {
|
|
||||||
msb := (t >> 31) & 1
|
|
||||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
|
||||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
|
||||||
xor := uint32(dn[i])
|
|
||||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
|
||||||
t = (t << 1) | xor
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将830位的二进制数组先以10位为一组分别转换为11位并组合
|
|
||||||
func convert830To913(b830 []byte) []byte {
|
|
||||||
if len(b830) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
b913 := make([]byte, 913)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
b11 := balisecodec.To11(b830[i*10 : i*10+10])
|
|
||||||
for j := 0; j < 11; j++ {
|
|
||||||
b913[i*11+j] = b11[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b913
|
|
||||||
}
|
|
||||||
|
|
||||||
func convert913To830(b913 []byte) []byte {
|
|
||||||
if len(b913) != 913 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
b830 := make([]byte, 830)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
b10, err := balisecodec.From11(b913[i*11 : i*11+11])
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
b830[i*10+j] = b10[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b830
|
|
||||||
}
|
|
||||||
|
|
||||||
func compare830(b830 []byte, compare830 []byte) {
|
|
||||||
if len(b830) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
fmt.Printf("%01b", b830[i*10+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
fmt.Printf("%01b", compare830[i*10+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
println()
|
|
||||||
}
|
|
||||||
for i := 0; i < 830; i++ {
|
|
||||||
if b830[i] != compare830[i] {
|
|
||||||
slog.Info("error", "index", i, "b830", b830[i], "compare", compare830[i])
|
|
||||||
panic("830 bit compare error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 以11位为一组比较两个913位的报文
|
|
||||||
func compare913(b913 []byte, b1023 *Balise1023) {
|
|
||||||
if len(b913) != 913 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
compare := b1023.data
|
|
||||||
for i := 0; i < 913; i += 11 {
|
|
||||||
for j := 0; j < 11; j++ {
|
|
||||||
print(b913[i+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
for j := 0; j < 11; j++ {
|
|
||||||
print(compare[i+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
println()
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,156 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log/slog"
|
|
||||||
"runtime/debug"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/xuri/excelize/v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
fileName = "北岗子-应答器报文清单.xlsx"
|
|
||||||
sheetName = "应答器报文清单"
|
|
||||||
codeColumn = "应答器编号"
|
|
||||||
nameColumn = "应答器名称"
|
|
||||||
typeColumn = "类型"
|
|
||||||
checkSumColumn = "校验码"
|
|
||||||
msg830strColumn = "用户报文(830bits)"
|
|
||||||
msg1023strColumn = "报文(1023bits)"
|
|
||||||
)
|
|
||||||
|
|
||||||
var heads []string
|
|
||||||
|
|
||||||
func init() {
|
|
||||||
initHeads()
|
|
||||||
}
|
|
||||||
|
|
||||||
func initHeads() {
|
|
||||||
heads = append(heads, codeColumn)
|
|
||||||
heads = append(heads, nameColumn)
|
|
||||||
heads = append(heads, typeColumn)
|
|
||||||
heads = append(heads, checkSumColumn)
|
|
||||||
heads = append(heads, msg830strColumn)
|
|
||||||
heads = append(heads, msg1023strColumn)
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildHeadIndex(row []string) map[string]int {
|
|
||||||
headIdx := make(map[string]int)
|
|
||||||
for i, column := range row {
|
|
||||||
column = HandleStringSpace(column)
|
|
||||||
if column == codeColumn {
|
|
||||||
headIdx[column] = i
|
|
||||||
} else if column == nameColumn {
|
|
||||||
headIdx[column] = i
|
|
||||||
} else if column == typeColumn {
|
|
||||||
headIdx[column] = i
|
|
||||||
} else if column == checkSumColumn {
|
|
||||||
headIdx[column] = i
|
|
||||||
} else if column == msg830strColumn {
|
|
||||||
headIdx[column] = i
|
|
||||||
} else if column == msg1023strColumn {
|
|
||||||
headIdx[column] = i
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 检查headIndex是否完整
|
|
||||||
if len(headIdx) <= 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
checkHeadsIndex(headIdx, fileName, sheetName, heads)
|
|
||||||
return headIdx
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkHeadsIndex(headIdx map[string]int, fileName, sheetName string, heads []string) {
|
|
||||||
// 检查headIndex是否完整
|
|
||||||
for _, v := range heads {
|
|
||||||
if _, ok := headIdx[v]; !ok {
|
|
||||||
slog.Error("表头缺失", "文件名", fileName, "SheetName", sheetName, "表头", v)
|
|
||||||
panic("课时表头缺失")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadTransponders() map[string]Transponder {
|
|
||||||
return readExcel(fileName, sheetName, readRows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readExcel[T any](fileName, sheetName string, handle func(rows [][]string) map[string]T) map[string]T {
|
|
||||||
f, err := excelize.OpenFile(fileName)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("打开表文件异常", "表名", fileName, "error", err)
|
|
||||||
debug.PrintStack()
|
|
||||||
panic("打开表文件异常")
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if err := f.Close(); err != nil {
|
|
||||||
slog.Error("文件关闭异常", "error", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
rows, err := f.GetRows(sheetName)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("读取Sheet异常", "SheetName", sheetName, "error", err)
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
// fmt.Println(rows)
|
|
||||||
return handle(rows)
|
|
||||||
}
|
|
||||||
|
|
||||||
func readRows(rows [][]string) map[string]Transponder {
|
|
||||||
dataMap := make(map[string]Transponder)
|
|
||||||
var headIdx map[string]int
|
|
||||||
for _, row := range rows {
|
|
||||||
if headIdx == nil {
|
|
||||||
headIdx = buildHeadIndex(row)
|
|
||||||
// if headIdx != nil {
|
|
||||||
// slog.Info("读取到表头索引", "文件名", fileName, "表名", sheetName, "索引", headIdx)
|
|
||||||
// }
|
|
||||||
} else {
|
|
||||||
rowSize := len(row)
|
|
||||||
if rowSize <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if rowSize <= headIdx[msg1023strColumn] {
|
|
||||||
// slog.Info("非数据行", "row", row, "rowIndex", i)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
codeStr := row[headIdx[codeColumn]]
|
|
||||||
if codeStr == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
codeStr = HandleStringSpace(codeStr)
|
|
||||||
code, err := strconv.ParseInt(codeStr, 10, 32)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error("应答器编号错误", "编号", codeStr, "error", err)
|
|
||||||
panic("应答器编号错误")
|
|
||||||
}
|
|
||||||
name := row[headIdx[nameColumn]]
|
|
||||||
if name == "" {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name = HandleStringSpace(name)
|
|
||||||
tp := row[headIdx[typeColumn]]
|
|
||||||
checkSum := row[headIdx[checkSumColumn]]
|
|
||||||
msg830 := row[headIdx[msg830strColumn]]
|
|
||||||
msg1023 := row[headIdx[msg1023strColumn]]
|
|
||||||
dataMap[name] = Transponder{
|
|
||||||
Code: int(code),
|
|
||||||
Name: name,
|
|
||||||
Type: tp,
|
|
||||||
CheckSum: checkSum,
|
|
||||||
Msg830: msg830,
|
|
||||||
Msg1023: msg1023,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
slog.Info("读取结果", "文件名", fileName, "SheetName", sheetName, "总数", len(dataMap))
|
|
||||||
// fmt.Println(dataMap)
|
|
||||||
return dataMap
|
|
||||||
}
|
|
||||||
|
|
||||||
func HandleStringSpace(s string) string {
|
|
||||||
s = strings.ReplaceAll(s, " ", "")
|
|
||||||
s = strings.ReplaceAll(s, "\n", "")
|
|
||||||
return s
|
|
||||||
}
|
|
@ -1,32 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "log/slog"
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
a1 := calculateAvgAcc(136960.88, 24.41978)
|
|
||||||
a2 := calculateAvgAcc(34874, 14.97515)
|
|
||||||
slog.Info("根据位移和时间计算平均加速度", "通号平均加速度", a1, "动力学平均加速度", a2)
|
|
||||||
avt1 := calculateAvgAccByV(6.94444, 24.41978)
|
|
||||||
avt2 := calculateAvgAccByV(6.94444, 14.97515)
|
|
||||||
slog.Info("根据速度和时间计算平均加速度", "通号平均加速度", avt1, "动力学平均加速度", avt2)
|
|
||||||
s1 := calculateS(0.28437766432762146, 24.41978)
|
|
||||||
s2 := calculateS(0.46373090147972107, 14.97515)
|
|
||||||
slog.Info("根据加速度和时间计算位移", "通号最小位移", s1, "动力学最小位移", s2)
|
|
||||||
slog.Info("实际位移", "通号实际位移差", 136960.88-s1, "动力学实际位移差", 34874-s2)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据位移和时间计算平均加速度(初始速度为0)
|
|
||||||
// s单位为mm,t单位为s
|
|
||||||
func calculateAvgAcc(s float32, t float32) float32 {
|
|
||||||
return 2 * s / (t * t) / 1000
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据速度和时间计算平均加速度(初始速度为0)
|
|
||||||
func calculateAvgAccByV(v float32, t float32) float32 {
|
|
||||||
return v / t
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据加速度和时间计算位移(初始速度为0)
|
|
||||||
func calculateS(a float32, t float32) float32 {
|
|
||||||
return 0.5 * a * t * t * 1000
|
|
||||||
}
|
|
@ -1,56 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
// fib_lfsr()
|
|
||||||
galois_lfsr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
|
|
||||||
func fib_lfsr() {
|
|
||||||
startState := uint16(0xACE1)
|
|
||||||
lfsr := startState
|
|
||||||
var bit uint16
|
|
||||||
period := uint64(0)
|
|
||||||
for {
|
|
||||||
slog.Info("fib_lfsr", "bit", fmt.Sprintf("%01b", lfsr&1), "lfsr", fmt.Sprintf("%016b", lfsr))
|
|
||||||
bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1
|
|
||||||
lfsr = (lfsr >> 1) | (bit << 15)
|
|
||||||
period++
|
|
||||||
if period == 15 {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
if lfsr == startState {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println(period)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* taps: 16 14 13 11; feedback polynomial: x^16 + x^14 + x^13 + x^11 + 1 */
|
|
||||||
func galois_lfsr() {
|
|
||||||
startState := uint16(0xACE1)
|
|
||||||
lfsr := startState
|
|
||||||
var bit uint16
|
|
||||||
period := uint64(0)
|
|
||||||
for {
|
|
||||||
slog.Info("galois_lfsr", "bit", fmt.Sprintf("%01b", lfsr&1), "lfsr", fmt.Sprintf("%016b", lfsr))
|
|
||||||
bit = lfsr & 1
|
|
||||||
lfsr >>= 1
|
|
||||||
if bit == 1 {
|
|
||||||
lfsr ^= 0xB400
|
|
||||||
}
|
|
||||||
period++
|
|
||||||
// if period == 15 {
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
if lfsr == startState {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println(period)
|
|
||||||
}
|
|
@ -1,52 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
)
|
|
||||||
|
|
||||||
func main() {
|
|
||||||
d2, d1, d0 := encodeAcc(6.742071875)
|
|
||||||
a := decode2Acc(d2, d1, d0)
|
|
||||||
fmt.Println(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
const G = 9.80665
|
|
||||||
|
|
||||||
func encodeAcc(a float32) (d2, d1, d0 byte) {
|
|
||||||
d2 = 0
|
|
||||||
d1 = 0
|
|
||||||
d0 = 0
|
|
||||||
x := a / G
|
|
||||||
v := uint32(0)
|
|
||||||
for i := 17; i >= 0; i-- {
|
|
||||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
|
||||||
if t > x {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
v |= 1 << i
|
|
||||||
x -= t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Printf("%b, %b\n", v, v<<6)
|
|
||||||
v <<= 6
|
|
||||||
d0 = byte(v)
|
|
||||||
d1 = byte(v >> 8)
|
|
||||||
d2 = byte(v >> 16)
|
|
||||||
fmt.Printf("%b, %b, %b\n", d2, d1, d0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode2Acc(d2, d1, d0 byte) float32 {
|
|
||||||
v := uint32(d2)<<10 | uint32(d1)<<2 | uint32(d0>>6)
|
|
||||||
fmt.Printf("%b\n", v)
|
|
||||||
x := float32(0)
|
|
||||||
for i := 17; i >= 0; i-- {
|
|
||||||
if v&(1<<i) != 0 {
|
|
||||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
|
||||||
x += t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Println(x)
|
|
||||||
return x * G
|
|
||||||
}
|
|
21
go.mod
21
go.mod
@ -4,11 +4,10 @@ go 1.21
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/appleboy/gin-jwt/v2 v2.9.1
|
github.com/appleboy/gin-jwt/v2 v2.9.1
|
||||||
//github.com/eclipse/paho.golang v0.12.0
|
github.com/eclipse/paho.golang v0.12.0
|
||||||
github.com/eclipse/paho.golang v0.21.0
|
|
||||||
github.com/gin-contrib/cors v1.4.0
|
github.com/gin-contrib/cors v1.4.0
|
||||||
github.com/golang/protobuf v1.5.3
|
github.com/golang/protobuf v1.5.3
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.4.0
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0
|
github.com/sagikazarmark/slog-shim v0.1.0
|
||||||
github.com/snksoft/crc v1.1.0
|
github.com/snksoft/crc v1.1.0
|
||||||
github.com/spf13/viper v1.18.1
|
github.com/spf13/viper v1.18.1
|
||||||
@ -41,25 +40,21 @@ require (
|
|||||||
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
github.com/go-sql-driver/mysql v1.7.0 // indirect
|
||||||
github.com/goburrow/serial v0.1.0 // indirect
|
github.com/goburrow/serial v0.1.0 // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.3 // indirect
|
github.com/golang-jwt/jwt/v4 v4.4.3 // indirect
|
||||||
github.com/gorilla/websocket v1.5.1 // indirect
|
github.com/gorilla/websocket v1.5.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
|
||||||
github.com/richardlehane/msoleps v1.0.3 // indirect
|
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/simonvetter/modbus v1.6.0 // indirect
|
github.com/simonvetter/modbus v1.6.0 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
|
|
||||||
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // indirect
|
|
||||||
github.com/yohamta/donburi v1.3.9 // indirect
|
github.com/yohamta/donburi v1.3.9 // indirect
|
||||||
go.uber.org/atomic v1.9.0 // indirect
|
go.uber.org/atomic v1.9.0 // indirect
|
||||||
go.uber.org/multierr v1.9.0 // indirect
|
go.uber.org/multierr v1.9.0 // indirect
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
|
||||||
golang.org/x/mod v0.12.0 // indirect
|
golang.org/x/mod v0.12.0 // indirect
|
||||||
|
golang.org/x/sync v0.5.0 // indirect
|
||||||
golang.org/x/tools v0.13.0 // indirect
|
golang.org/x/tools v0.13.0 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c // indirect
|
gorm.io/datatypes v1.1.1-0.20230130040222-c43177d3cf8c // indirect
|
||||||
@ -97,13 +92,11 @@ require (
|
|||||||
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.11 // indirect
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
golang.org/x/arch v0.3.0 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/crypto v0.19.0 // indirect
|
golang.org/x/crypto v0.16.0 // indirect
|
||||||
golang.org/x/net v0.21.0 // indirect
|
golang.org/x/net v0.19.0 // indirect
|
||||||
golang.org/x/sys v0.17.0 // indirect
|
golang.org/x/sys v0.15.0 // indirect
|
||||||
golang.org/x/text v0.14.0 // indirect
|
golang.org/x/text v0.14.0 // indirect
|
||||||
google.golang.org/protobuf v1.32.0
|
google.golang.org/protobuf v1.32.0
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
)
|
)
|
||||||
|
|
||||||
require github.com/xuri/excelize/v2 v2.8.1
|
|
||||||
|
39
go.sum
39
go.sum
@ -17,8 +17,8 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs
|
|||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/eclipse/paho.golang v0.21.0 h1:cxxEReu+iFbA5RrHfRGxJOh8tXZKDywuehneoeBeyn8=
|
github.com/eclipse/paho.golang v0.12.0 h1:EXQFJbJklDnUqW6lyAknMWRhM2NgpHxwrrL8riUmp3Q=
|
||||||
github.com/eclipse/paho.golang v0.21.0/go.mod h1:GHF6vy7SvDbDHBguaUpfuBkEB5G6j0zKxMG4gbh6QRQ=
|
github.com/eclipse/paho.golang v0.12.0/go.mod h1:TSDCUivu9JnoR9Hl+H7sQMcHkejWH2/xKK1NJGtLbIE=
|
||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||||
@ -83,10 +83,10 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/websocket v1.5.1 h1:gmztn0JnHVt9JZquRuzLw3g4wouNVzKL15iLr/zn/QY=
|
github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc=
|
||||||
github.com/gorilla/websocket v1.5.1/go.mod h1:x3kM2JMyaluk02fnUJpQuwD2dCS5NDG2ZHL0uE0tcaY=
|
github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||||
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8=
|
||||||
@ -153,8 +153,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
|
|||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
|
||||||
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
|
github.com/natefinch/lumberjack v2.0.0+incompatible h1:4QJd3OLAMgj7ph+yZTuX13Ld4UpgHp07nNdFX7mqFfM=
|
||||||
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
|
github.com/natefinch/lumberjack v2.0.0+incompatible/go.mod h1:Wi9p2TTF5DG5oU+6YfsmYQpsTIOm0B1VNzQg9Mw6nPk=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
@ -166,11 +164,6 @@ github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsK
|
|||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
|
||||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
|
||||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
|
||||||
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
|
|
||||||
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
@ -227,12 +220,6 @@ github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6
|
|||||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||||
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53 h1:Chd9DkqERQQuHpXjR/HSV1jLZA6uaoiwwH3vSuF3IW0=
|
|
||||||
github.com/xuri/efp v0.0.0-20231025114914-d1ff6096ae53/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
|
||||||
github.com/xuri/excelize/v2 v2.8.1 h1:pZLMEwK8ep+CLIUWpWmvW8IWE/yxqG0I1xcN6cVMGuQ=
|
|
||||||
github.com/xuri/excelize/v2 v2.8.1/go.mod h1:oli1E4C3Pa5RXg1TBXn4ENCXDV5JUMlBluUhG7c+CEE=
|
|
||||||
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4oGezE1eF9fQWmNiIpSfI4=
|
|
||||||
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
|
||||||
github.com/yohamta/donburi v1.3.9 h1:sYAPaelSnxmoTGjgH9ZlYt4pUKrnwvAv4YGXxLZCK6E=
|
github.com/yohamta/donburi v1.3.9 h1:sYAPaelSnxmoTGjgH9ZlYt4pUKrnwvAv4YGXxLZCK6E=
|
||||||
github.com/yohamta/donburi v1.3.9/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg=
|
github.com/yohamta/donburi v1.3.9/go.mod h1:5QkyraUjkzbMVTD2b8jaPFy1Uwjm/zdFN1c1lZGaezg=
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
@ -250,12 +237,10 @@ golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5y
|
|||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||||
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80=
|
||||||
golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
|
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 h1:GoHiUyI/Tp2nVkLI2mCxVkOjsbSXD66ic0XW0js0R9g=
|
||||||
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
golang.org/x/exp v0.0.0-20230905200255-921286631fa9/go.mod h1:S2oDrQGGwySpoQPVqRShND87VCbxmc6bL1Yd2oYrm6k=
|
||||||
golang.org/x/image v0.14.0 h1:tNgSxAFe3jC4uYqvZdTr84SZoM1KfwdC9SKIFrLjFn4=
|
|
||||||
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc=
|
||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
@ -266,8 +251,8 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||||
@ -285,8 +270,8 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y=
|
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
||||||
|
@ -176,7 +176,6 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
|
|||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE=
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
|
||||||
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
github.com/google/gofuzz v1.0.0 h1:A8PeW59pxE9IoFRqBp37U+mSNaQoZ46F1f0f863XSXw=
|
||||||
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o=
|
||||||
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw=
|
||||||
@ -266,17 +265,12 @@ go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
|
|||||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
|
||||||
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
|
golang.org/x/image v0.1.0 h1:r8Oj8ZA2Xy12/b5KZYj3tuv7NG/fBz3TwQVvpJ9l8Rk=
|
||||||
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
|
golang.org/x/image v0.1.0/go.mod h1:iyPr49SD/G/TBxYVB/9RRtGUT5eNbo2u4NamWeQcD5c=
|
||||||
golang.org/x/image v0.14.0/go.mod h1:HUYqC05R2ZcZ3ejNQsIHQDQiwWM4JBqmm6MKANTp4LE=
|
|
||||||
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303 h1:K4fp1rDuJBz0FCPAWzIJwnzwNEM7S6yobdZzMrZ/Zws=
|
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303 h1:K4fp1rDuJBz0FCPAWzIJwnzwNEM7S6yobdZzMrZ/Zws=
|
||||||
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303/go.mod h1:M32cGdzp91A8Ex9qQtyZinr19EYxzkFqDjW2oyHzTDQ=
|
golang.org/x/mobile v0.0.0-20221012134814-c746ac228303/go.mod h1:M32cGdzp91A8Ex9qQtyZinr19EYxzkFqDjW2oyHzTDQ=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
|
||||||
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE=
|
|
||||||
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
||||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
||||||
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
golang.org/x/term v0.15.0 h1:y/Oo/a/q3IXu26lQgl04j/gjuBDOBlx7X6Om1j2CPW4=
|
||||||
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0=
|
||||||
golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U=
|
|
||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
|
||||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||||
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk=
|
||||||
|
@ -36,11 +36,7 @@ func InitSlog() {
|
|||||||
|
|
||||||
if logging.Stdout {
|
if logging.Stdout {
|
||||||
// 日志输出到控制台
|
// 日志输出到控制台
|
||||||
//slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||||||
// Level: level,
|
|
||||||
// AddSource: false,
|
|
||||||
//})))
|
|
||||||
slog.SetDefault(slog.New(newMyJsonHandler(os.Stdout, &slog.HandlerOptions{
|
|
||||||
Level: level,
|
Level: level,
|
||||||
AddSource: false,
|
AddSource: false,
|
||||||
})))
|
})))
|
||||||
@ -54,11 +50,7 @@ func InitSlog() {
|
|||||||
LocalTime: true, // 日志备份使用本地时间
|
LocalTime: true, // 日志备份使用本地时间
|
||||||
Compress: logging.Compress, // 是否压缩日志
|
Compress: logging.Compress, // 是否压缩日志
|
||||||
}
|
}
|
||||||
//slog.SetDefault(slog.New(slog.NewJSONHandler(lumberJackLogger, &slog.HandlerOptions{
|
slog.SetDefault(slog.New(slog.NewJSONHandler(lumberJackLogger, &slog.HandlerOptions{
|
||||||
// Level: level,
|
|
||||||
// AddSource: false,
|
|
||||||
//})))
|
|
||||||
slog.SetDefault(slog.New(newMyJsonHandler(lumberJackLogger, &slog.HandlerOptions{
|
|
||||||
Level: level,
|
Level: level,
|
||||||
AddSource: false,
|
AddSource: false,
|
||||||
})))
|
})))
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
package logger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"io"
|
|
||||||
"log/slog"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type MyJsonHandler struct {
|
|
||||||
output io.Writer
|
|
||||||
mu sync.Mutex
|
|
||||||
jsonHandler slog.Handler
|
|
||||||
}
|
|
||||||
|
|
||||||
var stackChan = make(chan string, 100)
|
|
||||||
|
|
||||||
func newMyJsonHandler(output io.Writer, opts *slog.HandlerOptions) *MyJsonHandler {
|
|
||||||
if opts == nil {
|
|
||||||
opts = &slog.HandlerOptions{}
|
|
||||||
}
|
|
||||||
ra := opts.ReplaceAttr
|
|
||||||
opts.ReplaceAttr = func(groups []string, a slog.Attr) slog.Attr {
|
|
||||||
if a.Key == "stack" {
|
|
||||||
stackChan <- a.Value.String()
|
|
||||||
return slog.Attr{}
|
|
||||||
} else {
|
|
||||||
if ra != nil {
|
|
||||||
return ra(groups, a)
|
|
||||||
} else {
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &MyJsonHandler{output: output, mu: sync.Mutex{}, jsonHandler: slog.NewJSONHandler(output, opts)}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MyJsonHandler) Enabled(ctx context.Context, level slog.Level) bool {
|
|
||||||
return s.jsonHandler.Enabled(ctx, level)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MyJsonHandler) Handle(ctx context.Context, record slog.Record) error {
|
|
||||||
err := s.jsonHandler.Handle(ctx, record)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case stack := <-stackChan:
|
|
||||||
s.mu.Lock()
|
|
||||||
defer s.mu.Unlock()
|
|
||||||
_, err = s.output.Write([]byte(stack))
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MyJsonHandler) WithAttrs(attrs []slog.Attr) slog.Handler {
|
|
||||||
return s.jsonHandler.WithAttrs(attrs)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *MyJsonHandler) WithGroup(name string) slog.Handler {
|
|
||||||
return s.jsonHandler.WithGroup(name)
|
|
||||||
}
|
|
@ -1,21 +0,0 @@
|
|||||||
package logger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log/slog"
|
|
||||||
"os"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func BenchmarkMyJsonHandler_Handle(b *testing.B) {
|
|
||||||
for i := 0; i < b.N; i++ {
|
|
||||||
//slog.SetDefault(slog.New(slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
|
||||||
// AddSource: false,
|
|
||||||
// Level: nil,
|
|
||||||
//})))
|
|
||||||
slog.SetDefault(slog.New(newMyJsonHandler(os.Stdout, &slog.HandlerOptions{
|
|
||||||
AddSource: false,
|
|
||||||
Level: nil,
|
|
||||||
})))
|
|
||||||
slog.Info("这是一条日志", "error", "错误", "stack", "goroutine 10 [running]:\nruntime/debug.Stack()\n\tD:/develop/Go/go1.21.4/src/runtime/debug/stack.go:24 +0x6b\njoylink.club/bj-rtsts-server/starter.customRecoveryWithSlog.func1.1()\n\tD:/GoProject/rts-sim-testing-service/starter/init.go:126 +0x36f\npanic({0x1f0cb40?, 0x226fd50?})\n\tD:/develop/Go/go1.21.4/src/runtime/panic.go:920 +0x290\njoylink.club/bj-rtsts-server/api.createByProjectId(0xc001a06100)\n\tD:/GoProject/rts-sim-testing-service/api/simulation.go:91 +0x26\ngithub.com/gin-gonic/gin.(*Context).Next(0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 +0x7a\njoylink.club/bj-rtsts-server/middleware.permissionMiddleware.func1(0xc001a06100)\n\tD:/GoProject/rts-sim-testing-service/middleware/auth.go:35 +0x178\ngithub.com/gin-gonic/gin.(*Context).Next(0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 +0x7a\ngithub.com/appleboy/gin-jwt/v2.(*GinJWTMiddleware).middlewareImpl(0xc000504340, 0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/appleboy/gin-jwt/v2@v2.9.1/auth_jwt.go:462 +0x579\ngithub.com/appleboy/gin-jwt/v2.(*GinJWTMiddleware).MiddlewareFunc.func1(0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/appleboy/gin-jwt/v2@v2.9.1/auth_jwt.go:415 +0x26\ngithub.com/gin-gonic/gin.(*Context).Next(0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 +0x7a\njoylink.club/bj-rtsts-server/starter.customRecoveryWithSlog.func1(0xc001a06100)\n\tD:/GoProject/rts-sim-testing-service/starter/init.go:135 +0xef\ngithub.com/gin-gonic/gin.(*Context).Next(0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 +0x7a\ngithub.com/samber/slog-gin.NewWithConfig.func1(0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/samber/slog-gin@v1.1.0/middleware.go:70 +0x13f\ngithub.com/gin-gonic/gin.(*Context).Next(0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/context.go:174 +0x7a\ngithub.com/gin-gonic/gin.(*Engine).handleHTTPRequest(0xc0004d51e0, 0xc001a06100)\n\tC:/Users/thesai/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/gin.go:620 +0x427\ngithub.com/gin-gonic/gin.(*Engine).ServeHTTP(0xc0004d51e0, {0x227e480, 0xc00012aee0}, 0xc001a07100)\n\tC:/Users/thesai/go/pkg/mod/github.com/gin-gonic/gin@v1.9.1/gin.go:576 +0xbc\nnet/http.serverHandler.ServeHTTP({0xc0017f0960}, {0x227e480, 0xc00012aee0}, 0xc001a07100)\n\tD:/develop/Go/go1.21.4/src/net/http/server.go:2938 +0x257\nnet/http.(*conn).serve(0xc0019422d0, {0x2285b38, 0xc001982000})\n\tD:/develop/Go/go1.21.4/src/net/http/server.go:2009 +0x1a39\ncreated by net/http.(*Server).Serve in goroutine 1\n\tD:/develop/Go/go1.21.4/src/net/http/server.go:3086 +0xa25")
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,8 +3,9 @@ package ms_api
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"joylink.club/bj-rtsts-server/sys_error"
|
||||||
)
|
)
|
||||||
|
|
||||||
type MsgTask interface {
|
type MsgTask interface {
|
||||||
@ -51,7 +52,7 @@ mainLoop:
|
|||||||
}
|
}
|
||||||
err := t.fn()
|
err := t.fn()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error(fmt.Sprintf("仿真任务【%s】状态消息收集异常", t.name), err)
|
panic(sys_error.New(fmt.Sprintf("仿真任务【%s】状态消息收集异常", t.name), err))
|
||||||
}
|
}
|
||||||
time.Sleep(t.interval)
|
time.Sleep(t.interval)
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,6 @@ package message_server
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
"joylink.club/bj-rtsts-server/dto/state_proto"
|
||||||
"log/slog"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"joylink.club/bj-rtsts-server/dto/data_proto"
|
"joylink.club/bj-rtsts-server/dto/data_proto"
|
||||||
@ -17,62 +16,54 @@ import (
|
|||||||
|
|
||||||
func NewPSLMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
func NewPSLMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
||||||
mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
|
mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
|
||||||
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]综合门控箱按钮状态", mapId), func() error {
|
||||||
return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]PSL按钮状态", mapId), func() error {
|
for _, box := range mapData.GateBoxs {
|
||||||
for _, psl := range mapData.PslBoxs {
|
did := memory.GetMapElementId(box.Common)
|
||||||
data, err := collectPslStates(vs.World, psl.RefPslMapCode, uidStructure.PslIds[psl.Common.Id].Uid)
|
data_proto, err := collectGateBoxPSLState(vs.World, mapId, box)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error(err.Error())
|
return err
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
sendMsg(vs, mapId, psl.Common.Id, data)
|
mqtt.GetMsgClient().PubPSLState(vs.SimulationId, mapId, did, data_proto)
|
||||||
}
|
|
||||||
for _, psl := range mapData.GarageDoors {
|
|
||||||
data, err := collectPslStates(vs.World, psl.RefPslMapCode, uidStructure.PslIds[psl.Common.Id].Uid)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sendMsg(vs, mapId, psl.Common.Id, data)
|
|
||||||
}
|
|
||||||
for _, psl := range mapData.FloodGates {
|
|
||||||
data, err := collectPslStates(vs.World, psl.RefPslMapCode, uidStructure.PslIds[psl.Common.Id].Uid)
|
|
||||||
if err != nil {
|
|
||||||
slog.Error(err.Error())
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sendMsg(vs, mapId, psl.Common.Id, data)
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}, 200*time.Millisecond)
|
}, 200*time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendMsg(vs *memory.VerifySimulation, mapId int32, pslId uint32, data *state_proto.PushedDevicesStatus) {
|
func collectGateBoxPSLState(world ecs.World, mapId int32, box *data_proto.GatedBox) (*state_proto.PushedDevicesStatus, error) {
|
||||||
err := mqtt.GetMsgClient().PubPSLState(vs.SimulationId, mapId, pslId, data)
|
did := memory.GetMapElementId(box.Common)
|
||||||
if err != nil {
|
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
||||||
slog.Error(fmt.Sprintf("发送PSL状态出错:%s", err.Error()))
|
boxUid := uidStructure.PslIds[did].Uid
|
||||||
|
mkxEntry, ok := entity.GetEntityByUid(world, boxUid)
|
||||||
|
if !ok {
|
||||||
|
return nil, fmt.Errorf("[id:%s]的门控箱实体找不到", boxUid)
|
||||||
}
|
}
|
||||||
}
|
mkx := component.MkxType.Get(mkxEntry)
|
||||||
|
var buttonStateArr []*state_proto.ButtonState
|
||||||
func collectPslStates(world ecs.World, pslMapCode string, pslUid string) (*state_proto.PushedDevicesStatus, error) {
|
if ok {
|
||||||
var btnStates []*state_proto.ButtonState
|
_, pslStorage := memory.QueryGiDataByName[*data_proto.PslGraphicStorage](box.RefGatedBoxMapCode)
|
||||||
_, pslStorage := memory.QueryGiDataByName[*data_proto.PslGraphicStorage](pslMapCode)
|
btnUidMap := make(map[string]uint32, len(pslStorage.PslButtons))
|
||||||
for _, button := range pslStorage.PslButtons {
|
for _, button := range pslStorage.PslButtons {
|
||||||
btnEntry, ok := entity.GetEntityByUid(world, memory.BuildUid(pslUid, button.Code))
|
btnUidMap[boxUid+"_"+button.Code] = memory.GetMapElementId(button.Common)
|
||||||
if !ok {
|
}
|
||||||
slog.Error(fmt.Sprintf("[id:%s]的PSL的按钮[code:%s]对应的实体找不到", pslUid, button.Code))
|
btnArr := []*ecs.Entry{mkx.PCB, mkx.PCBPL, mkx.POB, mkx.POBPL, mkx.PAB, mkx.PABPL, mkx.WRZF, mkx.WRZFPL,
|
||||||
continue
|
mkx.QKQR, mkx.QKQRPL, mkx.MPL, mkx.JXTCPL}
|
||||||
|
for _, btn := range btnArr {
|
||||||
|
if btn == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
btnState := component.BitStateType.Get(btn)
|
||||||
|
buttonStateArr = append(buttonStateArr, &state_proto.ButtonState{
|
||||||
|
Id: btnUidMap[component.UidType.Get(btn).Id],
|
||||||
|
Down: btnState.Val,
|
||||||
|
Active: btnState.Val,
|
||||||
|
//Bypass: btnState.BypassEnable,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
btnStates = append(btnStates, &state_proto.ButtonState{
|
|
||||||
Id: button.Common.Id,
|
|
||||||
Down: component.BitStateType.Get(btnEntry).Val,
|
|
||||||
Active: component.BitStateType.Get(btnEntry).Val,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
return &state_proto.PushedDevicesStatus{
|
return &state_proto.PushedDevicesStatus{
|
||||||
All: true,
|
All: true,
|
||||||
AllStatus: &state_proto.AllDevicesStatus{
|
AllStatus: &state_proto.AllDevicesStatus{
|
||||||
ButtonState: btnStates,
|
ButtonState: buttonStateArr,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -35,15 +35,15 @@ func NewSfpMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//buttonStates, err := collectStationButtonStates(vs.World, mapId)
|
buttonStates, err := collectStationButtonStates(vs.World, mapId)
|
||||||
//if err != nil {
|
if err != nil {
|
||||||
// return err
|
return err
|
||||||
//}
|
}
|
||||||
psdStates, err := collectPsdStates(vs.World, mapId)
|
psdStates, err := collectPsdStates(vs.World, mapId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
sectionStates, err := collectPhysicalSectionStates(vs.World, mapId)
|
sectionStates, err := collectSectionStates(vs.World, mapId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -59,37 +59,17 @@ func NewSfpMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ckmStates, err := collectCkmStates(vs.World, mapId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
fymStates, err := collectFymStates(vs.World, mapId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
xcjStates, err := collectXcjStates(vs.World, mapId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
axleCountingSectionStates, err := collectAxleCountingSectionStates(vs.World, mapId)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
ststes := &state_proto.PushedDevicesStatus{
|
ststes := &state_proto.PushedDevicesStatus{
|
||||||
All: true,
|
All: true,
|
||||||
AllStatus: &state_proto.AllDevicesStatus{
|
AllStatus: &state_proto.AllDevicesStatus{
|
||||||
TrainState: trainState,
|
TrainState: trainState,
|
||||||
SwitchState: turnoutStates,
|
SwitchState: turnoutStates,
|
||||||
SignalState: signalStates,
|
SignalState: signalStates,
|
||||||
//ButtonState: buttonStates,
|
ButtonState: buttonStates,
|
||||||
PsdState: psdStates,
|
PsdState: psdStates,
|
||||||
SectionState: sectionStates,
|
SectionState: sectionStates,
|
||||||
PlatformState: platformStates,
|
PlatformState: platformStates,
|
||||||
BaliseState: baliseStates,
|
BaliseState: baliseStates,
|
||||||
CkmStates: ckmStates,
|
|
||||||
FymStates: fymStates,
|
|
||||||
XcjStates: xcjStates,
|
|
||||||
AxleCountingSection: axleCountingSectionStates,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
err = mqtt.GetMsgClient().PubSfpState(vs.SimulationId, mapId, ststes)
|
err = mqtt.GetMsgClient().PubSfpState(vs.SimulationId, mapId, ststes)
|
||||||
@ -100,105 +80,6 @@ func NewSfpMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
|||||||
}, 1000*time.Millisecond)
|
}, 1000*time.Millisecond)
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectAxleCountingSectionStates(world ecs.World, mapId int32) ([]*state_proto.AxleCountingSectionState, error) {
|
|
||||||
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.AxleCountingSection{})
|
|
||||||
var stateArr []*state_proto.AxleCountingSectionState
|
|
||||||
wd := entity.GetWorldData(world)
|
|
||||||
for _, u := range uidMap {
|
|
||||||
entry := wd.EntityMap[u.Uid]
|
|
||||||
if entry == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
stateArr = append(stateArr, &state_proto.AxleCountingSectionState{
|
|
||||||
Id: u.CommonId,
|
|
||||||
Occupied: component.AxleCountingSectionStateType.Get(entry).Occupied,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return stateArr, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func collectXcjStates(world ecs.World, mapId int32) ([]*state_proto.XcjState, error) {
|
|
||||||
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
|
||||||
var xcjStates []*state_proto.XcjState
|
|
||||||
for _, xcj := range uidStructure.XcjIds {
|
|
||||||
entry, ok := entity.GetEntityByUid(world, xcj.Uid)
|
|
||||||
if ok {
|
|
||||||
state := &state_proto.XcjState{Id: xcj.CommonId}
|
|
||||||
xcjStates = append(xcjStates, state)
|
|
||||||
//设置参数
|
|
||||||
var xcjParam *request_proto.XcjParam
|
|
||||||
if entry.HasComponent(appcomponent.XcjParamType) {
|
|
||||||
xcjParam = appcomponent.XcjParamType.Get(entry)
|
|
||||||
} else {
|
|
||||||
xcjParam = &request_proto.XcjParam{}
|
|
||||||
}
|
|
||||||
state.Param = xcjParam
|
|
||||||
//继电器状态
|
|
||||||
if entry.HasComponent(component.XcjCircuitType) {
|
|
||||||
circuit := component.XcjCircuitType.Get(entry)
|
|
||||||
state.Xqj = component.BitStateType.Get(circuit.XQJ).Val
|
|
||||||
for _, twj := range circuit.TWJList {
|
|
||||||
state.TwjList = append(state.TwjList, component.BitStateType.Get(twj).Val)
|
|
||||||
}
|
|
||||||
state.Tgqj = component.BitStateType.Get(circuit.TGQJ).Val
|
|
||||||
state.Xcjxj = component.BitStateType.Get(circuit.XCJXJ).Val
|
|
||||||
state.Xcyxj = component.BitStateType.Get(circuit.XCYXJ).Val
|
|
||||||
for _, cfj := range circuit.CFJList {
|
|
||||||
state.CfjList = append(state.CfjList, component.BitStateType.Get(cfj).Val)
|
|
||||||
}
|
|
||||||
state.Jtj = component.BitStateType.Get(circuit.JTJ).Val
|
|
||||||
state.Tgyxj = component.BitStateType.Get(circuit.TGYXJ).Val
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return xcjStates, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func collectFymStates(world ecs.World, mapId int32) ([]*state_proto.CkmState, error) {
|
|
||||||
mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
|
|
||||||
return collectCkmOrFymStates(world, mapId, mapData.FloodGates)
|
|
||||||
}
|
|
||||||
|
|
||||||
func collectCkmStates(world ecs.World, mapId int32) ([]*state_proto.CkmState, error) {
|
|
||||||
mapData := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
|
|
||||||
return collectCkmOrFymStates(world, mapId, mapData.GarageDoors)
|
|
||||||
}
|
|
||||||
|
|
||||||
func collectCkmOrFymStates(world ecs.World, mapId int32, gates []*data_proto.GarageDoor) ([]*state_proto.CkmState, error) {
|
|
||||||
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
|
||||||
ckmUidMap := uidStructure.CkmIds
|
|
||||||
var ckmStates []*state_proto.CkmState
|
|
||||||
for _, ckm := range gates {
|
|
||||||
commonId := ckm.Common.Id
|
|
||||||
entry, ok := entity.GetEntityByUid(world, ckmUidMap[commonId].Uid)
|
|
||||||
if ok {
|
|
||||||
mgj := false
|
|
||||||
local := false
|
|
||||||
mplj := false
|
|
||||||
if entry.HasComponent(component.CkmCircuitType) {
|
|
||||||
circuit := component.CkmCircuitType.Get(entry)
|
|
||||||
mgj = component.BitStateType.Get(circuit.MGJ).Val
|
|
||||||
local = component.BitStateType.Get(circuit.MMSJ).Val
|
|
||||||
mplj = component.BitStateType.Get(circuit.MPLJ).Val
|
|
||||||
}
|
|
||||||
var ckmParam *request_proto.CkmParam
|
|
||||||
if entry.HasComponent(appcomponent.CkmParamType) {
|
|
||||||
ckmParam = appcomponent.CkmParamType.Get(entry)
|
|
||||||
} else {
|
|
||||||
ckmParam = &request_proto.CkmParam{}
|
|
||||||
}
|
|
||||||
ckmStates = append(ckmStates, &state_proto.CkmState{
|
|
||||||
Id: commonId,
|
|
||||||
Mgj: mgj,
|
|
||||||
Param: ckmParam,
|
|
||||||
Local: local,
|
|
||||||
Mplj: mplj,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return ckmStates, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 收集应答器状态
|
// 收集应答器状态
|
||||||
func collectBaliseStates(world ecs.World, mapId int32) ([]*state_proto.BaliseState, error) {
|
func collectBaliseStates(world ecs.World, mapId int32) ([]*state_proto.BaliseState, error) {
|
||||||
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
uidStructure := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
||||||
@ -277,7 +158,7 @@ func collectPsdStates(world ecs.World, mapId int32) ([]*state_proto.PsdState, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 收集区段状态
|
// 收集区段状态
|
||||||
func collectPhysicalSectionStates(world ecs.World, mapId int32) ([]*state_proto.SectionState, error) {
|
func collectSectionStates(world ecs.World, mapId int32) ([]*state_proto.SectionState, error) {
|
||||||
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.Section{})
|
uidMap := memory.QueryMapUidMapByType(mapId, &data_proto.Section{})
|
||||||
var sectionArr []*state_proto.SectionState
|
var sectionArr []*state_proto.SectionState
|
||||||
for _, u := range uidMap {
|
for _, u := range uidMap {
|
||||||
@ -297,23 +178,22 @@ func handlerSectionState(w ecs.World, uid string) *state_proto.SectionState {
|
|||||||
//fmt.Printf("id=%s的信号机不存在", uid)
|
//fmt.Printf("id=%s的信号机不存在", uid)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if entry.HasComponent(component.PhysicalSectionManagerType) { //计轴区段
|
if entry.HasComponent(component.PhysicalSectionStateType) { //计轴区段
|
||||||
axleManager := component.PhysicalSectionManagerType.Get(entry)
|
sectionState := &state_proto.SectionState{}
|
||||||
sectionState := &state_proto.SectionState{
|
axleState := component.PhysicalSectionStateType.Get(entry)
|
||||||
Occupied: axleManager.Occupied,
|
sectionState.Occupied = axleState.Occ
|
||||||
AxleFault: entry.HasComponent(component.PhysicalSectionForceOccupied),
|
sectionState.AxleFault = entry.HasComponent(component.AxleSectionFaultTag)
|
||||||
AxleDrst: false,
|
|
||||||
AxlePdrst: axleManager.PDRST,
|
wd := entity.GetWorldData(w)
|
||||||
}
|
sectionModel := wd.Repo.FindPhysicalSection(uid)
|
||||||
sectionState.Occupied = axleManager.Occupied
|
faDcAxleDeviceEntry := entity.FindAxleManageDevice(wd, sectionModel.CentralizedStation())
|
||||||
sectionState.AxleFault = entry.HasComponent(component.PhysicalSectionForceOccupied)
|
if faDcAxleDeviceEntry != nil {
|
||||||
return sectionState
|
faDcAxleDevice := component.AxleManageDeviceType.Get(faDcAxleDeviceEntry)
|
||||||
} else if entry.HasComponent(component.TrackCircuitType) { //轨道电路
|
axleRuntime := faDcAxleDevice.FindAdr(uid)
|
||||||
sectionState := &state_proto.SectionState{
|
if axleRuntime != nil {
|
||||||
Occupied: component.BitStateType.Get(component.TrackCircuitType.Get(entry).GJ).Val,
|
sectionState.AxleDrst = axleRuntime.Drst
|
||||||
AxleFault: false,
|
sectionState.AxlePdrst = axleRuntime.Pdrst
|
||||||
AxleDrst: false,
|
}
|
||||||
AxlePdrst: false,
|
|
||||||
}
|
}
|
||||||
return sectionState
|
return sectionState
|
||||||
}
|
}
|
||||||
@ -458,20 +338,20 @@ func collectTrainStates(vs *memory.VerifySimulation) ([]*state_proto.TrainMapSta
|
|||||||
|
|
||||||
func convertTrainState(v *state_proto.TrainState) *state_proto.TrainMapState {
|
func convertTrainState(v *state_proto.TrainState) *state_proto.TrainMapState {
|
||||||
t := &state_proto.TrainMapState{
|
t := &state_proto.TrainMapState{
|
||||||
Id: v.Id,
|
Id: v.Id,
|
||||||
Up: v.Up,
|
Up: v.Up,
|
||||||
InitialSpeed: v.Speed,
|
InitialSpeed: v.Speed,
|
||||||
TrainLength: v.TrainLength,
|
TrainLength: v.TrainLength,
|
||||||
Show: v.Show,
|
Show: v.Show,
|
||||||
HeadDeviceId: v.HeadDeviceId,
|
HeadDeviceId: v.HeadDeviceId,
|
||||||
HeadOffset: v.HeadOffset,
|
HeadOffset: v.HeadOffset,
|
||||||
DevicePort: v.DevicePort,
|
DevicePort: v.DevicePort,
|
||||||
DriftTo: v.DriftTo,
|
PointTo: v.PointTo,
|
||||||
TrainRunUp: v.TrainRunUp,
|
RunDirection: v.RunDirection,
|
||||||
TrainActiveDirection: v.TrainActiveDirection,
|
HeadDirection: v.HeadDirection,
|
||||||
TrainKilometer: v.TrainKilometer,
|
TrainKilometer: v.TrainKilometer,
|
||||||
ControlDelayTime: v.ControlDelayTime,
|
ControlDelayTime: v.ControlDelayTime,
|
||||||
WheelDiameter: v.WheelDiameter,
|
WheelDiameter: v.WheelDiameter,
|
||||||
// 动力学
|
// 动力学
|
||||||
DynamicHeartbeat: v.DynamicState.Heartbeat,
|
DynamicHeartbeat: v.DynamicState.Heartbeat,
|
||||||
HeadLinkId: v.DynamicState.HeadLinkId,
|
HeadLinkId: v.DynamicState.HeadLinkId,
|
||||||
@ -528,17 +408,15 @@ 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)
|
||||||
convertDynamicConfig(v.TrainEndsB, t.TrainEndsB)
|
convertDynamicConfig(v.TrainEndsB, t.TrainEndsB)
|
||||||
//now := time.Now().Unix()
|
|
||||||
|
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
func convertDynamicConfig(config, dest interface{}) {
|
func convertDynamicConfig(config, dest interface{}) {
|
||||||
configType := reflect.TypeOf(config).Elem()
|
configType := reflect.TypeOf(config).Elem()
|
||||||
for index := 0; index < configType.NumField(); index++ {
|
for index := 0; index < configType.NumField(); index++ {
|
||||||
@ -550,6 +428,17 @@ func convertDynamicConfig(config, dest interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*func convertDynamicConfig(config *common_proto.TrainDynamicConfig, dest *state_proto.TrainDynamicConfigMqtt) {
|
||||||
|
configType := reflect.TypeOf(config).Elem()
|
||||||
|
for index := 0; index < configType.NumField(); index++ {
|
||||||
|
field := configType.Field(index)
|
||||||
|
if field.IsExported() {
|
||||||
|
fieldName := field.Name
|
||||||
|
setVal(config, dest, fieldName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
|
||||||
func setVal(source, dest interface{}, fieldName string) {
|
func setVal(source, dest interface{}, fieldName string) {
|
||||||
destVal := reflect.ValueOf(dest).Elem().FieldByName(fieldName)
|
destVal := reflect.ValueOf(dest).Elem().FieldByName(fieldName)
|
||||||
sourceType := reflect.ValueOf(source).Elem().FieldByName(fieldName)
|
sourceType := reflect.ValueOf(source).Elem().FieldByName(fieldName)
|
||||||
@ -561,10 +450,7 @@ func setVal(source, dest interface{}, fieldName string) {
|
|||||||
debug.PrintStack()
|
debug.PrintStack()
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
if destVal.Kind() == reflect.Invalid {
|
|
||||||
//slog.Warn(fieldName, "赋值失败,源数据类型", sourceType.Kind().String(), "目标数据类型:", destVal.Kind().String())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if destVal.Kind() == reflect.String {
|
if destVal.Kind() == reflect.String {
|
||||||
destVal.Set(reflect.ValueOf(fmt.Sprintf("%v", sourceData)))
|
destVal.Set(reflect.ValueOf(fmt.Sprintf("%v", sourceData)))
|
||||||
} else {
|
} else {
|
||||||
|
@ -10,81 +10,27 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func lowPower(power bool) bool {
|
|
||||||
if power {
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 综合后备盘IBP消息服务
|
// 综合后备盘IBP消息服务
|
||||||
func NewTrainControlMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
func NewTrainControlMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
||||||
|
/* var findMapId int32 = 0
|
||||||
|
for _, d := range vs.MapIds {
|
||||||
|
mapData := memory.QueryGiType(d)
|
||||||
|
if mapData == data_proto.PictureType_TrainControlCab {
|
||||||
|
findMapId = d
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if findMapId == 0 {
|
||||||
|
slog.Error("未找到对应的列城控制图形")
|
||||||
|
return nil
|
||||||
|
}*/
|
||||||
return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]列车控制", mapId), func() error {
|
return ms_api.NewScheduleTask(fmt.Sprintf("地图[%d]列车控制", mapId), func() error {
|
||||||
allTrainMap := &vs.Memory.Status.TrainStateMap
|
allTrainMap := &vs.Memory.Status.TrainStateMap
|
||||||
allTrainMap.Range(func(key, value any) bool {
|
allTrainMap.Range(func(key, value any) bool {
|
||||||
trainId := fmt.Sprintf("%v", key)
|
trainId := fmt.Sprintf("%v", key)
|
||||||
ts := value.(*state_proto.TrainState)
|
ts := value.(*state_proto.TrainState)
|
||||||
ttcc := ts.Tcc
|
err := mqtt.GetMsgClient().PubTrainControlState(vs.SimulationId, trainId, ts.Tcc)
|
||||||
vobc := ts.VobcState
|
|
||||||
lights := make([]*state_proto.TrainControlState_ControlLight, 0)
|
|
||||||
for lightKey, light := range ttcc.LightMaps {
|
|
||||||
switch lightKey {
|
|
||||||
case memory.LIGHT_JJZD:
|
|
||||||
state := lowPower(vobc.LightEmergencyBrakingStatus)
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: state})
|
|
||||||
case memory.LIGHT_QQY:
|
|
||||||
state := lowPower(vobc.LightTractionSafetyCircuit)
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: state})
|
|
||||||
case memory.LIGHT_JSSJH:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.LightDriverActive})
|
|
||||||
case memory.LIGHT_TFZDHJ:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.StopNotAllBrake})
|
|
||||||
case memory.LIGHT_QYYX:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.TractionEffective})
|
|
||||||
case memory.LIGHT_ZDYX:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.BrakeEffective})
|
|
||||||
case memory.LIGHT_TFZDSJ:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.ParkingBrakeStatus})
|
|
||||||
case memory.LIGHT_CYZD:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.MostUseBrake})
|
|
||||||
case memory.LIGHT_ZDGL:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.BrakeQuarantine})
|
|
||||||
|
|
||||||
case memory.LIGHT_LSXH:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.NoSpeedSigle})
|
|
||||||
case memory.LIGHT_ZMYX:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.LeftDoorState})
|
|
||||||
case memory.LIGHT_YMYX:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.RightDoorState})
|
|
||||||
case memory.LIGHT_ZFZSD:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.TurnbackStatus})
|
|
||||||
case memory.LIGHT_BDATPKC:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.LocalAtpControl})
|
|
||||||
case memory.LIGHT_ATOFCZSD:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.LightAtoSend})
|
|
||||||
case memory.LIGHT_ATO_OPEN_LEFT_DOOR:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.AtoOpenLeftDoor})
|
|
||||||
case memory.LIGHT_ATO_OPEN_RIGHT_DOOR:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.AtoOpenRightDoor})
|
|
||||||
case memory.LIGHT_ATO_CLOSE_LEFT_DOOR:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.AtoCloseLeftDoor})
|
|
||||||
case memory.LIGHT_ATO_CLOSE_RIGHT_DOOR:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: vobc.AtoCloseRightDoor})
|
|
||||||
default:
|
|
||||||
lights = append(lights, &state_proto.TrainControlState_ControlLight{Id: light.Id, Val: light.Val})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
buttons := make([]*state_proto.TrainControlState_ControlButton, 0)
|
|
||||||
for _, button := range ttcc.Buttons {
|
|
||||||
buttons = append(buttons, button)
|
|
||||||
}
|
|
||||||
sks := make([]*state_proto.TrainControlState_SwitchKeyChange, 0)
|
|
||||||
for _, sk := range ttcc.SwitchKeyMap {
|
|
||||||
sks = append(sks, sk)
|
|
||||||
}
|
|
||||||
tcc := &state_proto.TrainControlStateMsg{Buttons: buttons, DriverKey: ttcc.DriverKey, SwitchKeys: sks, PushHandler: ttcc.PushHandler, Lights: lights}
|
|
||||||
err := mqtt.GetMsgClient().PubTrainControlState(vs.SimulationId, trainId, tcc)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error("发送列车控制mqtt失败", err)
|
slog.Error("发送列车控制mqtt失败", err)
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@ package middleware
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
|
||||||
"regexp"
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@ -37,16 +36,12 @@ func permissionMiddleware() gin.HandlerFunc {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
path, method := c.Request.URL.Path, c.Request.Method
|
path, method := c.Request.URL.Path, c.Request.Method
|
||||||
if method == http.MethodGet {
|
|
||||||
c.Next()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if validateUserPath(path, method, userAuth.AuthPaths) { // 用户有权限
|
if validateUserPath(path, method, userAuth.AuthPaths) { // 用户有权限
|
||||||
c.Next()
|
c.Next()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
slog.Error("无权限操作请求路径", "path", path, "method", method)
|
slog.Error("无权限操作请求路径", "path", path, "method", method)
|
||||||
panic(sys_error.NewCode("权限不足", 403))
|
panic(sys_error.New("权限不足"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,15 +29,10 @@ func Startup(cmc *MqttOptions) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
ctx := context.Background()
|
cm, err := autopaho.NewConnection(context.Background(), *cc)
|
||||||
cm, err := autopaho.NewConnection(ctx, *cc)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
//添加等待连接,如果连接失败,则等待重连
|
|
||||||
if err = cm.AwaitConnection(ctx); err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
mqttClient = &MqttClient{cc: cc, cm: cm}
|
mqttClient = &MqttClient{cc: cc, cm: cm}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -95,20 +90,6 @@ func (client *MqttClient) pub(topic string, data protoreflect.ProtoMessage) erro
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// 订阅mqtt服务
|
|
||||||
/*func subHandle(p *paho.Publish) {
|
|
||||||
fmt.Println(fmt.Sprintf("%v-%v"), hex.EncodeToString(p.Payload), len(p.Payload))
|
|
||||||
}
|
|
||||||
func (client *MqttClient) SubSimulationState(simulationId string) (*paho.Suback, error) {
|
|
||||||
topIc := GetStateTopic(simulationId)
|
|
||||||
_, err2 := client.cm.Subscribe(context.Background(), &paho.Subscribe{Subscriptions: []paho.SubscribeOptions{{Topic: topIc, QoS: 0}}})
|
|
||||||
if err2 != nil {
|
|
||||||
fmt.Println(err2)
|
|
||||||
}
|
|
||||||
client.cc.Router.RegisterHandler(topIc, subHandle)
|
|
||||||
return nil, nil
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// 发送仿真状态数据
|
// 发送仿真状态数据
|
||||||
func (client *MqttClient) PubSimulationState(simulationId string, msg *state_proto.SimulationStatus) error {
|
func (client *MqttClient) PubSimulationState(simulationId string, msg *state_proto.SimulationStatus) error {
|
||||||
return client.pub(GetStateTopic(simulationId), msg)
|
return client.pub(GetStateTopic(simulationId), msg)
|
||||||
@ -139,6 +120,6 @@ func (client *MqttClient) PubSfpState(simulationId string, mapId int32, msg *sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 发送列车控制状态
|
// 发送列车控制状态
|
||||||
func (client *MqttClient) PubTrainControlState(simulationId string, trainId string, msg *state_proto.TrainControlStateMsg) error {
|
func (client *MqttClient) PubTrainControlState(simulationId string, trainId string, msg *state_proto.TrainControlState) error {
|
||||||
return client.pub(GetTrainControlTopic(simulationId, trainId), msg)
|
return client.pub(GetTrainControlTopic(simulationId, trainId), msg)
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,6 @@ type MqttOptions struct {
|
|||||||
KeepAlive uint16 // 保活时间间隔,单位s,默认为60
|
KeepAlive uint16 // 保活时间间隔,单位s,默认为60
|
||||||
ConnectRetryDelay uint16 // 连接重试延时,单位s,默认为3
|
ConnectRetryDelay uint16 // 连接重试延时,单位s,默认为3
|
||||||
ConnectTimeout uint16 // 连接操作超时,单位s,默认为3
|
ConnectTimeout uint16 // 连接操作超时,单位s,默认为3
|
||||||
route *paho.StandardRouter
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewMqttOptions(address, username, password string) *MqttOptions {
|
func NewMqttOptions(address, username, password string) *MqttOptions {
|
||||||
@ -54,7 +53,6 @@ func (c *MqttOptions) tryInto() (*autopaho.ClientConfig, error) {
|
|||||||
if c.ConnectTimeout == 0 {
|
if c.ConnectTimeout == 0 {
|
||||||
c.ConnectTimeout = 3
|
c.ConnectTimeout = 3
|
||||||
}
|
}
|
||||||
router := paho.NewStandardRouter()
|
|
||||||
cc := &autopaho.ClientConfig{
|
cc := &autopaho.ClientConfig{
|
||||||
BrokerUrls: []*url.URL{
|
BrokerUrls: []*url.URL{
|
||||||
addr,
|
addr,
|
||||||
@ -75,15 +73,8 @@ func (c *MqttOptions) tryInto() (*autopaho.ClientConfig, error) {
|
|||||||
OnServerDisconnect: func(d *paho.Disconnect) {
|
OnServerDisconnect: func(d *paho.Disconnect) {
|
||||||
fmt.Printf("%s 连接断开; reason code: %d,properties: %v\n", c.ClientId, d.ReasonCode, d.Properties)
|
fmt.Printf("%s 连接断开; reason code: %d,properties: %v\n", c.ClientId, d.ReasonCode, d.Properties)
|
||||||
},
|
},
|
||||||
//添加订阅路由功能,以支持订阅
|
|
||||||
OnPublishReceived: []func(paho.PublishReceived) (bool, error){
|
|
||||||
func(pr paho.PublishReceived) (bool, error) {
|
|
||||||
router.Route(pr.Packet.Packet())
|
|
||||||
return true, nil // we assume that the router handles all messages (todo: amend router API)
|
|
||||||
}},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
cc.SetUsernamePassword(c.Username, []byte(c.Password))
|
cc.SetUsernamePassword(c.Username, []byte(c.Password))
|
||||||
c.route = router
|
|
||||||
return cc, nil
|
return cc, nil
|
||||||
}
|
}
|
||||||
|
@ -15,12 +15,12 @@ var (
|
|||||||
basePath, _ = os.Getwd()
|
basePath, _ = os.Getwd()
|
||||||
protoFolder = filepath.Join(basePath, "rts-sim-testing-message", "protos")
|
protoFolder = filepath.Join(basePath, "rts-sim-testing-message", "protos")
|
||||||
protocPath = filepath.Join(basePath, "rts-sim-testing-message", "protoc-23.1", "bin", "win64", "protoc")
|
protocPath = filepath.Join(basePath, "rts-sim-testing-message", "protoc-23.1", "bin", "win64", "protoc")
|
||||||
modulePrefix = "joylink.club/bj-rtsts-server"
|
modulePrefix = "joylink.club/rts-sim-testing-service"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
//先安装以下插件
|
//先安装以下插件
|
||||||
//go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.33.0
|
//go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
|
||||||
|
|
||||||
protoFiles := getProtoFiles()
|
protoFiles := getProtoFiles()
|
||||||
// 编译proto文件为Go文件
|
// 编译proto文件为Go文件
|
@ -1 +1 @@
|
|||||||
Subproject commit 073f5e3156b66343ff283ba3530b4d3d63ca4461
|
Subproject commit 21ca336b0ce32cec941685d2d37feb9d69c92970
|
@ -1 +1 @@
|
|||||||
Subproject commit a6293366a132680309a62855d4c4e19546ba3aa8
|
Subproject commit 0e19775ba6eae193bd5e7156d8f33ae6bc704023
|
@ -1,10 +1,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/config"
|
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"joylink.club/bj-rtsts-server/db/dbquery"
|
"joylink.club/bj-rtsts-server/db/dbquery"
|
||||||
@ -36,31 +33,8 @@ func ListProjectRunConfigQuery() []*dto.ProjectRunConfigDto {
|
|||||||
return dto.ConvertToRunConfigFromSlice(records)
|
return dto.ConvertToRunConfigFromSlice(records)
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkRunConfig(jsonConfigStr string) *sys_error.BusinessError {
|
|
||||||
var configMap config.ThirdPartyConfig
|
|
||||||
err := json.Unmarshal([]byte(jsonConfigStr), &configMap)
|
|
||||||
if err != nil {
|
|
||||||
return sys_error.New("运行环境序列化错误", err)
|
|
||||||
}
|
|
||||||
checkSameMap := make(map[string]bool)
|
|
||||||
for _, simConfig := range configMap.PcSimConfigs {
|
|
||||||
if simConfig.ConfigName == "" || len(strings.TrimSpace(simConfig.ConfigName)) == 0 {
|
|
||||||
return sys_error.New(fmt.Sprintf("车载运行配置名称不能为空 "), err)
|
|
||||||
}
|
|
||||||
if checkSameMap[simConfig.ConfigName] {
|
|
||||||
return sys_error.New(fmt.Sprintf("车载运行配置重复的名称:%v", simConfig.ConfigName), err)
|
|
||||||
}
|
|
||||||
checkSameMap[simConfig.ConfigName] = true
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 创建项目运行环境
|
// 创建项目运行环境
|
||||||
func CreateProjectRunConfig(dd *dto.ProjectRunConfigReqDto) bool {
|
func CreateProjectRunConfig(dd *dto.ProjectRunConfigReqDto) bool {
|
||||||
if checkErr := checkRunConfig(dd.ConfigContent); checkErr != nil {
|
|
||||||
panic(checkErr)
|
|
||||||
}
|
|
||||||
|
|
||||||
d := model.ProjectRunConfig{
|
d := model.ProjectRunConfig{
|
||||||
Name: dd.Name,
|
Name: dd.Name,
|
||||||
Description: dd.Description,
|
Description: dd.Description,
|
||||||
@ -68,7 +42,6 @@ func CreateProjectRunConfig(dd *dto.ProjectRunConfigReqDto) bool {
|
|||||||
CreateTime: time.Now(),
|
CreateTime: time.Now(),
|
||||||
UpdateTime: time.Now(),
|
UpdateTime: time.Now(),
|
||||||
}
|
}
|
||||||
|
|
||||||
err := dbquery.ProjectRunConfig.Save(&d)
|
err := dbquery.ProjectRunConfig.Save(&d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(sys_error.New("保存失败,数据库错误请联系运维人员", err))
|
panic(sys_error.New("保存失败,数据库错误请联系运维人员", err))
|
||||||
@ -102,9 +75,6 @@ func QueryRunConfig(id int32) *dto.ProjectRunConfigDto {
|
|||||||
|
|
||||||
// 更新项目运行环境
|
// 更新项目运行环境
|
||||||
func UpdateProjectRunConfig(id int32, dd *dto.ProjectRunConfigReqDto) bool {
|
func UpdateProjectRunConfig(id int32, dd *dto.ProjectRunConfigReqDto) bool {
|
||||||
if checkErr := checkRunConfig(dd.ConfigContent); checkErr != nil {
|
|
||||||
panic(checkErr)
|
|
||||||
}
|
|
||||||
findOldQuery := dbquery.ProjectRunConfig
|
findOldQuery := dbquery.ProjectRunConfig
|
||||||
oldD, err := findOldQuery.Where(findOldQuery.ID.Eq(id)).Debug().First()
|
oldD, err := findOldQuery.Where(findOldQuery.ID.Eq(id)).Debug().First()
|
||||||
if oldD == nil || err != nil {
|
if oldD == nil || err != nil {
|
||||||
|
@ -79,15 +79,10 @@ func TrainConfigToProtoConvert(t *dto.ConfigTrainData) *common_proto.TrainDynami
|
|||||||
// 转成列车proto
|
// 转成列车proto
|
||||||
func convertTrainDtoToProto(t *dto.TrainInfoDto) []byte {
|
func convertTrainDtoToProto(t *dto.TrainInfoDto) []byte {
|
||||||
message := &data_proto.Train{
|
message := &data_proto.Train{
|
||||||
TrainModel: data_proto.Train_TrainModel(t.TrainModel),
|
TrainModel: data_proto.Train_TrainModel(t.TrainModel),
|
||||||
CarriageLength: t.CarriageLength,
|
CarriageLength: t.CarriageLength,
|
||||||
TotalLength: t.TotalLength,
|
TotalLength: t.TotalLength,
|
||||||
TrainControlMapId: t.TrainControlMapId,
|
TrainControlMapId: t.TrainControlMapId,
|
||||||
TrainMaxSpeed: t.TrainMaxSpeed,
|
|
||||||
TrainLoad: t.TrainLoad,
|
|
||||||
TrainMaxAcc: t.TrainMaxAcc,
|
|
||||||
TrainMaxBrake: t.TrainMaxBrake,
|
|
||||||
TrainEmergencyBrake: t.TrainEmergencyBrake,
|
|
||||||
//TrainControlMapCode: t.TrainControlMapCode,
|
//TrainControlMapCode: t.TrainControlMapCode,
|
||||||
//MinDiameter: t.MinDiameter,
|
//MinDiameter: t.MinDiameter,
|
||||||
//MaxDiameter: t.MaxDiameter,
|
//MaxDiameter: t.MaxDiameter,
|
||||||
|
@ -86,11 +86,7 @@ func initServer() *gin.Engine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
c.Error(be)
|
c.Error(be)
|
||||||
statusCode := http.StatusInternalServerError
|
c.JSON(http.StatusInternalServerError, &dto.ErrorDto{
|
||||||
if be.ErrorCode > 0 {
|
|
||||||
statusCode = http.StatusForbidden
|
|
||||||
}
|
|
||||||
c.JSON(statusCode, &dto.ErrorDto{
|
|
||||||
Tip: be.UserMsg,
|
Tip: be.UserMsg,
|
||||||
Message: be.Error(),
|
Message: be.Error(),
|
||||||
})
|
})
|
||||||
@ -126,7 +122,11 @@ func customRecoveryWithSlog(logger *slog.Logger, stack bool, recovery gin.Recove
|
|||||||
}
|
}
|
||||||
|
|
||||||
if stack {
|
if stack {
|
||||||
logger.Error("请求处理Panic异常", "error", err, "stack", string(debug.Stack()))
|
logger.Error("请求处理Panic异常",
|
||||||
|
"error", err,
|
||||||
|
"stack", string(debug.Stack()),
|
||||||
|
)
|
||||||
|
debug.PrintStack()
|
||||||
} else {
|
} else {
|
||||||
logger.Error("请求处理Panic异常",
|
logger.Error("请求处理Panic异常",
|
||||||
"error", err,
|
"error", err,
|
||||||
|
@ -10,8 +10,7 @@ type BusinessError struct {
|
|||||||
// 用户提示信息
|
// 用户提示信息
|
||||||
UserMsg string
|
UserMsg string
|
||||||
// 错误信息传递(用于开发回溯定位,不给用户展示)
|
// 错误信息传递(用于开发回溯定位,不给用户展示)
|
||||||
Errors []string
|
Errors []string
|
||||||
ErrorCode int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 新建业务错误
|
// 新建业务错误
|
||||||
@ -35,26 +34,7 @@ func New(userMsg string, errs ...error) *BusinessError {
|
|||||||
// Errors: convert(errs),
|
// Errors: convert(errs),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func NewCode(userMsg string, errCode int, errs ...error) *BusinessError {
|
|
||||||
if len(errs) == 1 {
|
|
||||||
be, ok := errs[0].(*BusinessError)
|
|
||||||
if ok {
|
|
||||||
be.prependUserMsg(userMsg)
|
|
||||||
return be
|
|
||||||
} else {
|
|
||||||
return &BusinessError{
|
|
||||||
UserMsg: userMsg,
|
|
||||||
ErrorCode: errCode,
|
|
||||||
Errors: []string{errs[0].Error()},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return &BusinessError{
|
|
||||||
UserMsg: userMsg,
|
|
||||||
ErrorCode: errCode,
|
|
||||||
// Errors: convert(errs),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func IsBusinessError(err error) bool {
|
func IsBusinessError(err error) bool {
|
||||||
_, ok := err.(*BusinessError)
|
_, ok := err.(*BusinessError)
|
||||||
return ok
|
return ok
|
||||||
|
304
third_party/acc/acc_server_test.go
vendored
304
third_party/acc/acc_server_test.go
vendored
@ -5,14 +5,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
"math"
|
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAccUdp(t *testing.T) {
|
func TestAccUdp(t *testing.T) {
|
||||||
|
|
||||||
fmt.Println("准备启动ACC服务...")
|
fmt.Println("准备启动ACC服务...")
|
||||||
addr := fmt.Sprintf("%v:%v", "127.0.0.1", "9998")
|
addr := fmt.Sprintf("%v:%v", "127.0.0.1", "8899")
|
||||||
server := udp.NewServer(addr, handle)
|
server := udp.NewServer(addr, handle)
|
||||||
server.Listen()
|
server.Listen()
|
||||||
select {}
|
select {}
|
||||||
@ -24,305 +23,6 @@ func handle(d []byte) {
|
|||||||
if err == nil {
|
if err == nil {
|
||||||
|
|
||||||
jsonD, _ := json.Marshal(ri)
|
jsonD, _ := json.Marshal(ri)
|
||||||
fmt.Println("接受数据:", string(jsonD))
|
fmt.Println(string(jsonD))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func TestAcc(t *testing.T) {
|
|
||||||
d2, d1, d0 := encodeAcc(6.742071875)
|
|
||||||
a := decode2Acc(d2, d1, d0)
|
|
||||||
fmt.Println(a)
|
|
||||||
}
|
|
||||||
|
|
||||||
const G = 9.80665
|
|
||||||
|
|
||||||
func encodeAcc(a float32) (d2, d1, d0 byte) {
|
|
||||||
d2 = 0
|
|
||||||
d1 = 0
|
|
||||||
d0 = 0
|
|
||||||
x := a / G
|
|
||||||
fmt.Println(x)
|
|
||||||
v := uint32(0)
|
|
||||||
for i := 17; i >= 0; i-- {
|
|
||||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
|
||||||
if t > x {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
v |= 1 << i
|
|
||||||
x -= t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Printf("%b, %b\n", v, v<<6)
|
|
||||||
v <<= 6
|
|
||||||
d0 = byte(v)
|
|
||||||
d1 = byte(v >> 8)
|
|
||||||
d2 = byte(v >> 16)
|
|
||||||
fmt.Printf("%b, %b, %b\n", d2, d1, d0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode2Acc(d2, d1, d0 byte) float32 {
|
|
||||||
v := uint32(d2)<<10 | uint32(d1)<<2 | uint32(d0>>6)
|
|
||||||
fmt.Printf("%b\n", v)
|
|
||||||
x := float32(0)
|
|
||||||
for i := 17; i >= 0; i-- {
|
|
||||||
if v&(1<<i) != 0 {
|
|
||||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
|
||||||
x += t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Println(x)
|
|
||||||
return x * G
|
|
||||||
}
|
|
||||||
|
|
||||||
func setBit(b uint32, bitNum uint32, value uint32) uint32 {
|
|
||||||
if value != 0 && value != 1 {
|
|
||||||
panic("value must be 0 or 1")
|
|
||||||
}
|
|
||||||
mask := uint32(1 << bitNum) // 创建掩码
|
|
||||||
b &= ^(mask) // 清除位
|
|
||||||
b |= (mask & (value << bitNum))
|
|
||||||
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
func setBit2(b byte, bitNum int, value byte) byte {
|
|
||||||
if value != 0 && value != 1 {
|
|
||||||
panic("value must be 0 or 1")
|
|
||||||
}
|
|
||||||
mask := byte(1 << uint(bitNum)) // 创建掩码
|
|
||||||
b &= ^(mask) // 清除位
|
|
||||||
b |= (mask & (value << uint(bitNum)))
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
func encode(accSpeed float32) (d2, d1, d0 byte) {
|
|
||||||
//var accCode uint32 = math.Float32bits(accSpeed) >> 8
|
|
||||||
var accCode uint32 = 0
|
|
||||||
var sum float32 = accSpeed
|
|
||||||
for i := 17; i >= 0; i-- {
|
|
||||||
flag := float32(1 / math.Pow(2, float64(17-i)))
|
|
||||||
//更改对应bit位数据
|
|
||||||
if flag > sum {
|
|
||||||
//大于加速度,设置对应的bit为0
|
|
||||||
accCode = setBit(accCode, uint32(i), 0)
|
|
||||||
} else {
|
|
||||||
//设置对应的bit位1
|
|
||||||
accCode = setBit(accCode, uint32(i), 1)
|
|
||||||
sum = sum - flag
|
|
||||||
}
|
|
||||||
fmt.Println(i, flag, fmt.Sprintf("%032b", accCode), sum)
|
|
||||||
}
|
|
||||||
accCode = accCode << 8 //数据向左移动8位,取后3个字节
|
|
||||||
d2 = byte(accCode >> 16) //取出d2数据
|
|
||||||
d1 = byte(accCode >> 8 << 8) // & 0xff //取出d1
|
|
||||||
d0 = byte(accCode << 20) //& 0xf //取出d0高2位
|
|
||||||
|
|
||||||
//d2 = byte(accCode >> 16) //取出d2数据
|
|
||||||
//d1 = byte(accCode << 8 >> 8) //取出d1
|
|
||||||
//d0 = byte(accCode << 16) //取出d0高2位
|
|
||||||
|
|
||||||
return d2, d1, d0
|
|
||||||
}
|
|
||||||
func decode(d2, d1, d0 byte) float32 {
|
|
||||||
accCode := uint32(d2)<<16 | uint32(d1)<<8 | uint32(d0)>>4
|
|
||||||
|
|
||||||
// 因为编码时进行了左移8位的操作,所以这里需要右移回来
|
|
||||||
accCode >>= 8
|
|
||||||
|
|
||||||
// 重建浮点数
|
|
||||||
var accSpeed float32
|
|
||||||
for i := 0; i <= 17; i++ {
|
|
||||||
bitValue := accCode & (1 << uint32(i))
|
|
||||||
if bitValue != 0 {
|
|
||||||
// 如果该位为1,则累加相应的值到accSpeed
|
|
||||||
accSpeed += float32(1 / math.Pow(2, float64(17-i)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return accSpeed
|
|
||||||
}
|
|
||||||
func TestAccSpeed(t *testing.T) {
|
|
||||||
|
|
||||||
speed := float32(0.54 / G)
|
|
||||||
fmt.Println("输入acc加速度g", speed)
|
|
||||||
d2, d1, d0 := encode(speed)
|
|
||||||
decode(d2, d1, d0)
|
|
||||||
accSpeed := decode(d2, d1, d0)
|
|
||||||
fmt.Println("输出速度:", accSpeed*G, "加速度:", accSpeed)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCode66(t *testing.T) {
|
|
||||||
var accSpeed float32 = 0.44 / 9.8
|
|
||||||
fmt.Println(accSpeed)
|
|
||||||
//生成4字节返回数据
|
|
||||||
var accCode uint32 = 0
|
|
||||||
var sum float32 = 0
|
|
||||||
for i := 16; i >= 0; i-- {
|
|
||||||
flag := float32(1 / math.Pow(2, float64(17-i)))
|
|
||||||
//更改对应bit位数据
|
|
||||||
if flag > accSpeed {
|
|
||||||
//大于加速度,设置对应的bit为0
|
|
||||||
accCode = setBit(accCode, uint32(i), 0)
|
|
||||||
} else {
|
|
||||||
//设置对应的bit位1
|
|
||||||
accCode = setBit(accCode, uint32(i), 1)
|
|
||||||
if sum+flag > accSpeed {
|
|
||||||
//累加和超过accCode停止
|
|
||||||
break
|
|
||||||
}
|
|
||||||
sum = sum + flag
|
|
||||||
}
|
|
||||||
fmt.Println(i, flag, fmt.Sprintf("%b", accCode), sum)
|
|
||||||
}
|
|
||||||
//因为获取但是18位数据,这里向左移动14位(获取之前设置的bit数据)
|
|
||||||
fmt.Println(fmt.Sprintf("%032b", accCode))
|
|
||||||
fmt.Println(math.Float32frombits(accCode&0xffffc000) / 0x80000000)
|
|
||||||
accCode = accCode << 14
|
|
||||||
fmt.Println(fmt.Sprintf("%032b", accCode))
|
|
||||||
fmt.Println(float32(accCode) / 0x80000000)
|
|
||||||
}
|
|
||||||
func TestCode5(t *testing.T) {
|
|
||||||
|
|
||||||
var accSpeed float32 = (0.54 / 9.8) * 2
|
|
||||||
bbc := math.Float32bits(accSpeed)
|
|
||||||
fmt.Println(accSpeed, bbc, fmt.Sprintf("%08b", bbc), float32(bbc))
|
|
||||||
d2 := byte(bbc) & 0xFF
|
|
||||||
d1 := byte((bbc << 8) & 0xFF)
|
|
||||||
d0 := byte((bbc << 16) & 0xFF)
|
|
||||||
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d2))
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d1))
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d0))
|
|
||||||
result := (uint32(d2) << 16) | (uint32(d1) << 8) | (uint32(d0))
|
|
||||||
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", result), float32(result)/float32(0xFFFFFF), math.Float32frombits(result))
|
|
||||||
//arr := []byte{d2, d1, d0}
|
|
||||||
//var sum float32 = 0
|
|
||||||
//isBreak := false
|
|
||||||
//index := 1
|
|
||||||
//for i := 0; i < len(arr); i++ {
|
|
||||||
// d := arr[i]
|
|
||||||
//
|
|
||||||
//}
|
|
||||||
/* for i := 22; i >= 0; i-- {
|
|
||||||
d := float32(1 / math.Pow(2, float64(17-i)))
|
|
||||||
if isBreak {
|
|
||||||
result = setBit(result, uint32(i), 1)
|
|
||||||
|
|
||||||
} else {
|
|
||||||
if d > accSpeed {
|
|
||||||
result = setBit(result, uint32(i), 0)
|
|
||||||
} else if d < accSpeed {
|
|
||||||
result = setBit(result, uint32(i), 1)
|
|
||||||
if sum+d > accSpeed {
|
|
||||||
isBreak = true
|
|
||||||
//break
|
|
||||||
} else {
|
|
||||||
sum += d
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Println(i, i, d, "--------", fmt.Sprintf("%8b", result), result, sum)
|
|
||||||
}*/
|
|
||||||
//aas := math.Float32frombits(result)
|
|
||||||
//fmt.Println(aas)
|
|
||||||
result = result & 0xffffc000
|
|
||||||
fmt.Println(result, float32(result)/dd, fmt.Sprintf("%08b", result))
|
|
||||||
fmt.Println(math.Float32frombits(result) / dd)
|
|
||||||
}
|
|
||||||
func TestCode3(t *testing.T) {
|
|
||||||
var accSpeed float32 = 0.54 / 9.8
|
|
||||||
bbc := math.Float32bits(accSpeed)
|
|
||||||
fmt.Println(accSpeed, bbc, fmt.Sprintf("%08b", math.Float32bits(accSpeed)))
|
|
||||||
|
|
||||||
d2 := byte(bbc) & 0xFF
|
|
||||||
d1 := byte((bbc << 8) & 0xFF)
|
|
||||||
d0 := byte((bbc << 16) & 0xFF)
|
|
||||||
//result := (uint32(d2) << 16) | (uint32(d1) << 8) | (uint32(d0))
|
|
||||||
|
|
||||||
//d0 := byte(bbc & 0xFF)
|
|
||||||
// 提取 D1 字节
|
|
||||||
//d1 := byte((bbc >> 8) & 0xFF)
|
|
||||||
// 提取 D2 字节
|
|
||||||
//d2 := byte((bbc >> 16) & 0xFF)
|
|
||||||
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d2))
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d1))
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d0))
|
|
||||||
fmt.Println("----------------------------")
|
|
||||||
d2 = setBit2(d2, 7, 0)
|
|
||||||
d2 = setBit2(d2, 6, 0)
|
|
||||||
d2 = setBit2(d2, 5, 0)
|
|
||||||
d2 = setBit2(d2, 4, 0)
|
|
||||||
d2 = setBit2(d2, 3, 0)
|
|
||||||
d2 = setBit2(d2, 2, 0)
|
|
||||||
d2 = setBit2(d2, 1, 0)
|
|
||||||
d2 = setBit2(d2, 0, 1)
|
|
||||||
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d2))
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d1))
|
|
||||||
fmt.Println(fmt.Sprintf("%08b", d0))
|
|
||||||
var result uint32
|
|
||||||
|
|
||||||
//arr := []byte{d2, d1, d0}
|
|
||||||
//buf := bytes.NewBuffer(arr)
|
|
||||||
//binary.Read(buf, binary.BigEndian, &result)
|
|
||||||
result = (uint32(d2) << 16) | (uint32(d1) << 8) | (uint32(d0))
|
|
||||||
aas := math.Float32frombits(result)
|
|
||||||
fmt.Println(aas)
|
|
||||||
result = result & 0xffffc000
|
|
||||||
fmt.Println(result, fmt.Sprintf("%08b", result))
|
|
||||||
fmt.Println(aas / dd)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCode2(t *testing.T) {
|
|
||||||
var accSpeed float32 = 0.54 / 9.8
|
|
||||||
fmt.Println(accSpeed)
|
|
||||||
var acc uint32 = math.Float32bits(0)
|
|
||||||
var sum float32 = 0
|
|
||||||
bit := 13
|
|
||||||
for i := 16; i >= 1; i-- {
|
|
||||||
d := float32(1 / math.Pow(2, float64(17-i)))
|
|
||||||
if d > accSpeed {
|
|
||||||
acc = setBit(acc, uint32(i+bit), 0)
|
|
||||||
} else if d < accSpeed {
|
|
||||||
acc = setBit(acc, uint32(i+bit), 1)
|
|
||||||
if sum+d > accSpeed {
|
|
||||||
break
|
|
||||||
} else {
|
|
||||||
sum += d
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fmt.Println(i, i+bit, d, "--------", fmt.Sprintf("%8b", acc), acc, sum)
|
|
||||||
}
|
|
||||||
|
|
||||||
//d2 := byte(acc >> 24)
|
|
||||||
//d1 := byte((acc << 8) >> 24)
|
|
||||||
//d0 := byte((bbc << 16) >> 24)
|
|
||||||
//arr := []byte{d2, d1, 0, 0}
|
|
||||||
//u3 := binary.BigEndian.Uint32(arr)
|
|
||||||
u3 := acc & 0xffffc000
|
|
||||||
fmt.Println(u3, sum)
|
|
||||||
aas := math.Float32frombits(u3) / 0x80000000
|
|
||||||
fmt.Println(aas)
|
|
||||||
}
|
|
||||||
|
|
||||||
const dd = 0x80000000
|
|
||||||
|
|
||||||
func encodeDecimal(decimal float64) ([]byte, []byte) {
|
|
||||||
// 将小数转换为二进制形式
|
|
||||||
binary := fmt.Sprintf("%.15f", decimal)
|
|
||||||
|
|
||||||
// 提取二进制小数部分
|
|
||||||
binaryDecimal := binary[2:]
|
|
||||||
|
|
||||||
// 左对齐并添加零
|
|
||||||
paddedBinaryDecimal := fmt.Sprintf("%015s", binaryDecimal)
|
|
||||||
|
|
||||||
// 将二进制小数转换为字节数组
|
|
||||||
d2 := []byte(paddedBinaryDecimal[:8])
|
|
||||||
d1 := []byte(paddedBinaryDecimal[8:])
|
|
||||||
|
|
||||||
return d2, d1
|
|
||||||
}
|
|
||||||
|
65
third_party/acc/acc_vobc.go
vendored
65
third_party/acc/acc_vobc.go
vendored
@ -2,14 +2,11 @@ package acc
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/config"
|
"joylink.club/bj-rtsts-server/config"
|
||||||
"joylink.club/bj-rtsts-server/dto/common_proto"
|
|
||||||
"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/udp"
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
"log/slog"
|
|
||||||
"math"
|
"math"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@ -18,8 +15,6 @@ import (
|
|||||||
type AccVobc interface {
|
type AccVobc interface {
|
||||||
Start(accManager AccVobcManager)
|
Start(accManager AccVobcManager)
|
||||||
Stop()
|
Stop()
|
||||||
SendAcc(acc *message.Accelerometer)
|
|
||||||
TrainAccSender(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type AccVobcManager interface {
|
type AccVobcManager interface {
|
||||||
@ -32,6 +27,11 @@ var (
|
|||||||
singleObj *accVobcService
|
singleObj *accVobcService
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
accInterval = 15
|
||||||
|
accSpeedUnit = 9.8
|
||||||
|
)
|
||||||
|
|
||||||
func Default() AccVobc {
|
func Default() AccVobc {
|
||||||
defer initLock.Unlock()
|
defer initLock.Unlock()
|
||||||
initLock.Lock()
|
initLock.Lock()
|
||||||
@ -50,59 +50,15 @@ type accVobcService struct {
|
|||||||
func (acc *accVobcService) Start(accManager AccVobcManager) {
|
func (acc *accVobcService) Start(accManager AccVobcManager) {
|
||||||
config := accManager.GetRunAccConfig()
|
config := accManager.GetRunAccConfig()
|
||||||
if config.RemoteIp == "" || config.RemotePort <= 0 || !config.Open {
|
if config.RemoteIp == "" || config.RemotePort <= 0 || !config.Open {
|
||||||
return
|
|
||||||
}
|
}
|
||||||
acc.vobcClient = udp.NewClient(fmt.Sprintf("%v:%v", config.RemoteIp, config.RemotePort))
|
acc.vobcClient = udp.NewClient(fmt.Sprintf("%v:%v", config.RemoteIp, config.RemotePort))
|
||||||
|
ctx, cancleFunc := context.WithCancel(context.Background())
|
||||||
|
acc.controlContext = cancleFunc
|
||||||
acc.radarVobcManager = accManager
|
acc.radarVobcManager = accManager
|
||||||
|
go acc.sendTask(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (avs *accVobcService) SendAcc(acc *message.Accelerometer) {
|
func (acc *accVobcService) sendTask(ctx context.Context) {
|
||||||
if avs.vobcClient != nil {
|
|
||||||
data := acc.Encode()
|
|
||||||
hexStr := hex.EncodeToString(data)
|
|
||||||
slog.Info("发送 加速度消息数据:", hexStr)
|
|
||||||
err := avs.vobcClient.Send(data)
|
|
||||||
if err != nil {
|
|
||||||
slog.Info("发送 加速度消息数据失败:", hexStr)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//avs.vobcClient.Send(acc.BuildCanData())
|
|
||||||
}
|
|
||||||
func (avs *accVobcService) TrainAccSender(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) {
|
|
||||||
if trainState.VobcState.Tc1Active && trainState.TrainEndsA.AccEnable {
|
|
||||||
s := parseAccSpeedData(info.Acceleration, trainState.TrainEndsA)
|
|
||||||
avs.SendAcc(&message.Accelerometer{Acc: s})
|
|
||||||
} else if trainState.VobcState.Tc2Active && trainState.TrainEndsB.AccEnable {
|
|
||||||
s := parseAccSpeedData(info.Acceleration, trainState.TrainEndsB)
|
|
||||||
avs.SendAcc(&message.Accelerometer{Acc: s})
|
|
||||||
} else {
|
|
||||||
avs.SendAcc(&message.Accelerometer{Acc: 0})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseAccSpeedData(accSpeed float32, trainEndState *common_proto.TrainEndsState) float32 {
|
|
||||||
//如果差值速度和速度输出都填写,那么就以速度输出为优先
|
|
||||||
//如果动力学速度-差值速度小于0,呢么输出的就是0(不能小于0)
|
|
||||||
|
|
||||||
trainEndState.AccCheckTime = int32(trainEndState.AccCheckTimeOverAt - time.Now().Unix())
|
|
||||||
if trainEndState.AccCheckTime <= 0 {
|
|
||||||
//判断雷达检测时间是否到期
|
|
||||||
trainEndState.AccCheckTime = 0
|
|
||||||
if trainEndState.AccCheckTimeOverAt != 0 {
|
|
||||||
trainEndState.AccCheckSpeedDiff = 0
|
|
||||||
return accSpeed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if trainEndState.AccCheckSpeedDiff > 0 {
|
|
||||||
//如果雷达检测速度差值填写,那么就以速度差值为主
|
|
||||||
return float32(math.Abs(float64(accSpeed - trainEndState.AccCheckSpeedDiff)))
|
|
||||||
} else {
|
|
||||||
return accSpeed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/*func (acc *accVobcService) sendTask(ctx context.Context) {
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
@ -111,14 +67,13 @@ func parseAccSpeedData(accSpeed float32, trainEndState *common_proto.TrainEndsSt
|
|||||||
}
|
}
|
||||||
trainStatus := acc.radarVobcManager.FindAccTrain()
|
trainStatus := acc.radarVobcManager.FindAccTrain()
|
||||||
if trainStatus != nil {
|
if trainStatus != nil {
|
||||||
// 发送加速度信息
|
|
||||||
speedAcc := trainStatus.DynamicState.Acceleration
|
speedAcc := trainStatus.DynamicState.Acceleration
|
||||||
t := speedAcc / accSpeedUnit
|
t := speedAcc / accSpeedUnit
|
||||||
acc.vobcClient.SendMsg(&message.Accelerometer{Acc: math.Float32bits(t)})
|
acc.vobcClient.SendMsg(&message.Accelerometer{Acc: math.Float32bits(t)})
|
||||||
}
|
}
|
||||||
time.Sleep(time.Millisecond * accInterval)
|
time.Sleep(time.Millisecond * accInterval)
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
|
|
||||||
func (acc *accVobcService) Stop() {
|
func (acc *accVobcService) Stop() {
|
||||||
if acc.controlContext != nil {
|
if acc.controlContext != nil {
|
||||||
|
61
third_party/axle_device/beijing12/msg/common.go
vendored
61
third_party/axle_device/beijing12/msg/common.go
vendored
@ -1,61 +0,0 @@
|
|||||||
package msg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
ProtocolType_Sync = 0x01
|
|
||||||
ProtocolType_NoSync = 0x02
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
MessageType_A = 0x80
|
|
||||||
MessageType_B = 0x81
|
|
||||||
MessageType_SSE = 0x90
|
|
||||||
MessageType_SSR = 0x91
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
CRC_POLY_1 = 0x100D4E63 //通道1的CRC多项式
|
|
||||||
CRC_POLY_2 = 0x8CE56011 //通道2的CRC多项式
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
SCW_1 = 0xAE390B5A //通道1的SCW
|
|
||||||
SCW_2 = 0xC103589C //通道2的SCW
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
T_POLY_1 uint32 = 0x0FC22F87 //通道1的时间戳生成多项式
|
|
||||||
T_POLY_2 uint32 = 0xC3E887E1 //通道2的时间戳生成多项式
|
|
||||||
)
|
|
||||||
|
|
||||||
const Twait_sse = 3 //默认sse等待回应的周期数
|
|
||||||
|
|
||||||
func GetMessageType(data []byte) byte {
|
|
||||||
return data[1]
|
|
||||||
}
|
|
||||||
|
|
||||||
type MsgHeader struct {
|
|
||||||
ProtocolType byte //协议交互类别
|
|
||||||
MessageType byte //报文类型
|
|
||||||
SourceAddr uint16 //源地址
|
|
||||||
TargetAddr uint16 //目的地址
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MsgHeader) encode() []byte {
|
|
||||||
var data []byte
|
|
||||||
data = append(data, m.ProtocolType)
|
|
||||||
data = append(data, m.MessageType)
|
|
||||||
data = binary.LittleEndian.AppendUint16(data, m.SourceAddr)
|
|
||||||
data = binary.LittleEndian.AppendUint16(data, m.TargetAddr)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m *MsgHeader) decode(data []byte) error {
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
err := binary.Read(buf, binary.LittleEndian, m)
|
|
||||||
return err
|
|
||||||
}
|
|
142
third_party/axle_device/beijing12/msg/rsd.go
vendored
142
third_party/axle_device/beijing12/msg/rsd.go
vendored
@ -1,142 +0,0 @@
|
|||||||
package msg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 实时安全数据消息
|
|
||||||
type RsdMsg struct {
|
|
||||||
MsgHeader
|
|
||||||
SeqNum uint32 //序列号
|
|
||||||
UserDataLen uint16 //用户数据包字节总数+8
|
|
||||||
Svc1 uint32 //CRC1^SID1^T1(N)^SCW1
|
|
||||||
Svc2 uint32 //CRC2^SID2^T2(N)^SCW2
|
|
||||||
|
|
||||||
UserData []byte //用户数据包
|
|
||||||
|
|
||||||
Tail uint16 //报文尾 CRC16
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RsdMsg) Encode() []byte {
|
|
||||||
data := r.MsgHeader.encode()
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, r.SeqNum)
|
|
||||||
data = binary.LittleEndian.AppendUint16(data, r.UserDataLen)
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, r.Svc1)
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, r.Svc2)
|
|
||||||
data = append(data, r.UserData...)
|
|
||||||
r.Tail = message.Rssp_I_Crc16(data)
|
|
||||||
data = binary.LittleEndian.AppendUint16(data, r.Tail)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (r *RsdMsg) Decode(data []byte) error {
|
|
||||||
err := r.MsgHeader.decode(data)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
buf := bytes.NewBuffer(data[6:]) //去掉报文头的6个字节
|
|
||||||
fields := []any{&r.SeqNum, &r.UserDataLen, &r.Svc1, &r.Svc2}
|
|
||||||
for _, field := range fields {
|
|
||||||
err := binary.Read(buf, binary.LittleEndian, field)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
r.UserData = data[len(data)-buf.Len() : len(data)-2]
|
|
||||||
r.Tail = binary.LittleEndian.Uint16(data[len(data)-2:])
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// RsdMsgBuilder 用来构建RSD,将无需用户赋值的字段去掉了
|
|
||||||
type RsdMsgBuilder struct {
|
|
||||||
MsgHeader
|
|
||||||
SeqNum uint32
|
|
||||||
Svc1 uint32
|
|
||||||
Svc2 uint32
|
|
||||||
UserData []byte
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *RsdMsgBuilder) Build() *RsdMsg {
|
|
||||||
return &RsdMsg{
|
|
||||||
MsgHeader: b.MsgHeader,
|
|
||||||
SeqNum: b.SeqNum,
|
|
||||||
UserDataLen: uint16(len(b.UserData) + 8),
|
|
||||||
Svc1: b.Svc1,
|
|
||||||
Svc2: b.Svc2,
|
|
||||||
UserData: b.UserData,
|
|
||||||
Tail: message.Rssp_I_Crc16(b.UserData),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *RsdMsgBuilder) Encode() []byte {
|
|
||||||
return b.Build().Encode()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CmdInfos 来自联锁的数据帧
|
|
||||||
type CmdInfos []*cmdInfo
|
|
||||||
|
|
||||||
func (f *CmdInfos) Decode(data []byte) error {
|
|
||||||
for _, b := range data {
|
|
||||||
cmdInfo := &cmdInfo{}
|
|
||||||
cmdInfo.decode(b)
|
|
||||||
*f = append(*f, cmdInfo)
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// StateInfos 发给联锁的数据帧
|
|
||||||
type StateInfos []*StateInfo
|
|
||||||
|
|
||||||
func (t StateInfos) Encode() []byte {
|
|
||||||
var data []byte
|
|
||||||
for _, info := range t {
|
|
||||||
data = append(data, info.encode()...)
|
|
||||||
}
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type cmdInfo struct {
|
|
||||||
PRST bool //不使用
|
|
||||||
RST bool //不使用
|
|
||||||
DRST bool //直接复位 位索引5
|
|
||||||
RRST bool //不使用
|
|
||||||
RSTR bool //不使用
|
|
||||||
PDRST bool //预复位 位索引2
|
|
||||||
PRRST bool //不使用
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *cmdInfo) decode(data byte) {
|
|
||||||
c.DRST = (data>>5)&1 == 1
|
|
||||||
c.PDRST = (data>>2)&1 == 1
|
|
||||||
}
|
|
||||||
|
|
||||||
type StateInfo struct {
|
|
||||||
CLR bool //计轴出清 位索引0-7(0字节的7位)
|
|
||||||
OCC bool //计轴占用 0-6
|
|
||||||
RAC bool //计轴复位反馈 1-6
|
|
||||||
RJO bool //运营原因拒绝计轴复位 1-5
|
|
||||||
RJT bool //技术原因拒绝计轴复位 1-4
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *StateInfo) encode() []byte {
|
|
||||||
var b0 byte
|
|
||||||
var b1 byte
|
|
||||||
if s.CLR {
|
|
||||||
b0 = b0 | 1<<7
|
|
||||||
}
|
|
||||||
if s.OCC {
|
|
||||||
b0 = b0 | 1<<6
|
|
||||||
}
|
|
||||||
if s.RAC {
|
|
||||||
b1 = b1 | 1<<6
|
|
||||||
}
|
|
||||||
if s.RJO {
|
|
||||||
b1 = b1 | 1<<5
|
|
||||||
}
|
|
||||||
if s.RJT {
|
|
||||||
b1 = b1 | 1<<4
|
|
||||||
}
|
|
||||||
return []byte{b0, b1}
|
|
||||||
}
|
|
30
third_party/axle_device/beijing12/msg/sse.go
vendored
30
third_party/axle_device/beijing12/msg/sse.go
vendored
@ -1,30 +0,0 @@
|
|||||||
package msg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SseMsg struct {
|
|
||||||
MsgHeader
|
|
||||||
SeqNum uint32 // 序列号
|
|
||||||
SeqEnq1 uint32 //时序校正请求通道1 SID_1^T_1(NE)
|
|
||||||
SeqEnq2 uint32 // 时序校正请求通道2 SID_2^T_2(NE)
|
|
||||||
Tail uint16 //报文位 CRC16
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SseMsg) Encode() []byte {
|
|
||||||
data := s.MsgHeader.encode()
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, s.SeqNum)
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, s.SeqEnq1)
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, s.SeqEnq2)
|
|
||||||
s.Tail = message.Rssp_I_Crc16(data)
|
|
||||||
data = binary.LittleEndian.AppendUint16(data, s.Tail)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SseMsg) Decode(data []byte) error {
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
return binary.Read(buf, binary.LittleEndian, s)
|
|
||||||
}
|
|
34
third_party/axle_device/beijing12/msg/ssr.go
vendored
34
third_party/axle_device/beijing12/msg/ssr.go
vendored
@ -1,34 +0,0 @@
|
|||||||
package msg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
type SsrMsg struct {
|
|
||||||
MsgHeader
|
|
||||||
SeqNumSsr uint32 // 应答方的序列号
|
|
||||||
SeqNumSse uint32 // 请求方的序列号
|
|
||||||
SeqInit1 uint32 // 时序初始化通道1 SEQENQ_1^SID_1^T_1(NR)^DATAVER_1
|
|
||||||
SeqInit2 uint32 // 时序初始化通道2 SEQENQ_2^SID_2^T_2(NR)^DATAVER_2
|
|
||||||
DataVer byte // 数据版本号 预留固定值0x01
|
|
||||||
Tail uint16 // 报文位 CRC16
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SsrMsg) Encode() []byte {
|
|
||||||
data := s.MsgHeader.encode()
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, s.SeqNumSsr)
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, s.SeqNumSse)
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, s.SeqInit1)
|
|
||||||
data = binary.LittleEndian.AppendUint32(data, s.SeqInit2)
|
|
||||||
data = append(data, s.DataVer)
|
|
||||||
s.Tail = message.Rssp_I_Crc16(data)
|
|
||||||
data = binary.LittleEndian.AppendUint16(data, s.Tail)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SsrMsg) Decode(data []byte) error {
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
return binary.Read(buf, binary.LittleEndian, s)
|
|
||||||
}
|
|
650
third_party/axle_device/beijing12/service.go
vendored
650
third_party/axle_device/beijing12/service.go
vendored
@ -1,650 +0,0 @@
|
|||||||
package beijing12
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/config"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/sys_error"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/axle_device/beijing12/msg"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/tpapi"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
|
||||||
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
|
||||||
"joylink.club/rtsssimulation/component"
|
|
||||||
"joylink.club/rtsssimulation/entity"
|
|
||||||
"joylink.club/rtsssimulation/fi"
|
|
||||||
"joylink.club/rtsssimulation/repository/model/proto"
|
|
||||||
"log/slog"
|
|
||||||
"runtime/debug"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ( //日志
|
|
||||||
logTag = "[北京12号线计轴通信]"
|
|
||||||
privateLogger *slog.Logger
|
|
||||||
loggerInit sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
// key-集中站编号
|
|
||||||
var contextMap = make(map[string]*serviceContext)
|
|
||||||
var mu = sync.Mutex{}
|
|
||||||
|
|
||||||
type serviceContext struct {
|
|
||||||
sim *memory.VerifySimulation
|
|
||||||
config config.RsspAxleConfig
|
|
||||||
server udp.UdpServer
|
|
||||||
client udp.UdpClient
|
|
||||||
cancelFunc context.CancelFunc
|
|
||||||
ciSectionIndexConfigs []*proto.CiSectionCodePoint
|
|
||||||
sectionStateMap map[string]*fi.PhysicalSectionState //存储预复位/复位请求的返回结果
|
|
||||||
state tpapi.ThirdPartyApiServiceState // 服务状态(用于展示)
|
|
||||||
|
|
||||||
remoteAddr uint16 //联锁地址 从配置中的16进制字符串转来的
|
|
||||||
localAddr uint16 //计轴地址 从配置中的16进制字符串转来的
|
|
||||||
remoteSid1 uint32 //联锁SID1 从配置中的16进制字符串转来的
|
|
||||||
remoteSid2 uint32 //联锁SID2 从配置中的16进制字符串转来的
|
|
||||||
localSid1 uint32 //计轴SID1 从配置中的16进制字符串转来的
|
|
||||||
localSid2 uint32 //计轴SID2 从配置中的16进制字符串转来的
|
|
||||||
remoteSinit1 uint32 //联锁SINIT1 从配置中的16进制字符串转来的
|
|
||||||
remoteSinit2 uint32 //联锁SINIT2 从配置中的16进制字符串转来的
|
|
||||||
localSinit1 uint32 //计轴SINT1 从配置中的16进制字符串转来的
|
|
||||||
localSinit2 uint32 //计轴SINT2 从配置中的16进制字符串转来的
|
|
||||||
remoteDataVer1 uint32 //联锁DATAVER1 从配置中的16进制字符串转来的
|
|
||||||
remoteDataVer2 uint32 //联锁DATAVER2 从配置中的16进制字符串转来的
|
|
||||||
localDataVer1 uint32 //计轴DATAVER1 从配置中的16进制字符串转来的
|
|
||||||
localDataVer2 uint32 //计轴DATAVER2 从配置中的16进制字符串转来的
|
|
||||||
msgChan <-chan []byte //消息队列
|
|
||||||
seqNum uint32 //当前的序列号
|
|
||||||
lastSeqParam1 uint32 //最近一次的有效时序参数 remoteSinit1~+[remoteSid1^t1(n)]
|
|
||||||
lastSeqParam2 uint32 //最近一次的有效时序参数 remoteSinit2~+[remoteSid2^t2(n)]
|
|
||||||
lfsr1 *lfsr //用来计算时间戳的lfsr
|
|
||||||
lfsr2 *lfsr //用来计算时间戳的lfsr
|
|
||||||
sseMsg *msg.SseMsg //发送出去的时序校验请求
|
|
||||||
sseWaitTimer <-chan time.Time //sse超时定时器
|
|
||||||
precSinit1 uint32 // 用来从SSR消息的SeqInit中提取时序参数
|
|
||||||
precSinit2 uint32 // 用来从SSR消息的SeqInit中提取时序参数
|
|
||||||
}
|
|
||||||
|
|
||||||
func CollectAllServices() []tpapi.ThirdPartyApiService {
|
|
||||||
var services []tpapi.ThirdPartyApiService
|
|
||||||
for _, service := range contextMap {
|
|
||||||
services = append(services, service)
|
|
||||||
}
|
|
||||||
return services
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) Type() state_proto.SimulationThirdPartyApiService_Type {
|
|
||||||
return state_proto.SimulationThirdPartyApiService_AxleSection
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) State() tpapi.ThirdPartyApiServiceState {
|
|
||||||
return s.state
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) FindAppendApiService() []tpapi.ThirdPartyApiService {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) TrueService() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) ServiceDesc() string {
|
|
||||||
return logTag
|
|
||||||
}
|
|
||||||
|
|
||||||
func Start(simulation *memory.VerifySimulation) {
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
//检查服务启动条件
|
|
||||||
rsspConfig := simulation.GetRunConfig().RsspAxleConfig
|
|
||||||
if !rsspConfig.Open {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if contextMap[rsspConfig.StationCode] != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]服务已启动", logTag, rsspConfig.StationCode)))
|
|
||||||
}
|
|
||||||
station := simulation.Repo.FindStationByStationName(rsspConfig.StationCode)
|
|
||||||
if station == nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]不存在", logTag, rsspConfig.StationCode)))
|
|
||||||
}
|
|
||||||
ref := simulation.Repo.GetCentralizedStationRef(station.Id())
|
|
||||||
if ref == nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]关联数据不存在", logTag, rsspConfig.StationCode)))
|
|
||||||
}
|
|
||||||
if len(ref.SectionCodePoints) == 0 {
|
|
||||||
logger().Warn(fmt.Sprintf("集中站[%s]无区段编码数据,服务不启动", rsspConfig.StationCode))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//初始化服务上下文
|
|
||||||
serviceCtx := initServiceContext(rsspConfig, ref, simulation)
|
|
||||||
//准备启动服务
|
|
||||||
msgChan := make(chan []byte, 100)
|
|
||||||
serviceCtx.msgChan = msgChan
|
|
||||||
netAConfig := rsspConfig.NetAConfig
|
|
||||||
server := udp.NewServer(fmt.Sprintf(":%d", netAConfig.LocalPort), func(b []byte) {
|
|
||||||
//logger().Info(fmt.Sprintf("收到数据:%x", b))
|
|
||||||
msgChan <- b
|
|
||||||
})
|
|
||||||
client := udp.NewClient(fmt.Sprintf("%s:%d", netAConfig.RemoteIp, netAConfig.RemotePort))
|
|
||||||
err := server.Listen()
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]服务启动失败", logTag, rsspConfig.StationCode)))
|
|
||||||
} else {
|
|
||||||
logger().Info(fmt.Sprintf("监听[:%d]", netAConfig.LocalPort))
|
|
||||||
}
|
|
||||||
serviceCtx.server = server
|
|
||||||
serviceCtx.client = client
|
|
||||||
cancelCtx, cancelFunc := context.WithCancel(context.Background())
|
|
||||||
serviceCtx.cancelFunc = cancelFunc
|
|
||||||
serviceCtx.runCollectTask(cancelCtx)
|
|
||||||
serviceCtx.runHandleMsgTask(cancelCtx)
|
|
||||||
contextMap[rsspConfig.StationCode] = serviceCtx
|
|
||||||
}
|
|
||||||
|
|
||||||
func initServiceContext(rsspConfig config.RsspAxleConfig, ref *proto.CentralizedStationRef, simulation *memory.VerifySimulation) *serviceContext {
|
|
||||||
sourceAddr, err := strconv.ParseUint(rsspConfig.NetAConfig.RemoteAddr, 16, 16)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析源地址[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.RemoteAddr)))
|
|
||||||
}
|
|
||||||
targetAddr, err := strconv.ParseUint(rsspConfig.NetAConfig.LocalAddr, 16, 16)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析目的地址[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.LocalAddr)))
|
|
||||||
}
|
|
||||||
remoteSid1, err := strconv.ParseUint(rsspConfig.NetAConfig.RemoteSid1, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析联锁SID1[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.RemoteSid1)))
|
|
||||||
}
|
|
||||||
remoteSid2, err := strconv.ParseUint(rsspConfig.NetAConfig.RemoteSid2, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析联锁SID2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.RemoteSid2)))
|
|
||||||
}
|
|
||||||
localSid1, err := strconv.ParseUint(rsspConfig.NetAConfig.LocalSid1, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析计轴SID1[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.LocalSid1)))
|
|
||||||
}
|
|
||||||
localSid2, err := strconv.ParseUint(rsspConfig.NetAConfig.LocalSid2, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析计轴SID2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.LocalSid2)))
|
|
||||||
}
|
|
||||||
remoteSinit1, err := strconv.ParseUint(rsspConfig.NetAConfig.RemoteSinit1, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析联锁SINT1[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.RemoteSinit1)))
|
|
||||||
}
|
|
||||||
remoteSinit2, err := strconv.ParseUint(rsspConfig.NetAConfig.RemoteSinit2, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析联锁SINT2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.RemoteSinit2)))
|
|
||||||
}
|
|
||||||
localSinit1, err := strconv.ParseUint(rsspConfig.NetAConfig.LocalSinit1, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析计轴SINT1[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.LocalSinit1)))
|
|
||||||
}
|
|
||||||
localSinit2, err := strconv.ParseUint(rsspConfig.NetAConfig.LocalSinit2, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析计轴SINT2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.LocalSinit2)))
|
|
||||||
}
|
|
||||||
remoteDataVer1, err := strconv.ParseUint(rsspConfig.NetAConfig.RemoteDataVer1, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析联锁DATAVER_1[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.RemoteDataVer1)))
|
|
||||||
}
|
|
||||||
remoteDataVer2, err := strconv.ParseUint(rsspConfig.NetAConfig.RemoteDataVer2, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析联锁DATAVER_2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.RemoteDataVer2)))
|
|
||||||
}
|
|
||||||
localDataVer1, err := strconv.ParseUint(rsspConfig.NetAConfig.LocalDataVer1, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析计轴DATAVER_1[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.LocalDataVer1)))
|
|
||||||
}
|
|
||||||
localDataVer2, err := strconv.ParseUint(rsspConfig.NetAConfig.LocalDataVer2, 16, 32)
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s集中站[%s]解析计轴DATAVER_2[%s]出错", logTag, rsspConfig.StationCode, rsspConfig.NetAConfig.LocalDataVer2)))
|
|
||||||
}
|
|
||||||
//服务初始化及启动
|
|
||||||
serviceCtx := &serviceContext{
|
|
||||||
sim: simulation,
|
|
||||||
config: rsspConfig,
|
|
||||||
ciSectionIndexConfigs: ref.SectionCodePoints,
|
|
||||||
sectionStateMap: make(map[string]*fi.PhysicalSectionState),
|
|
||||||
|
|
||||||
remoteAddr: uint16(sourceAddr),
|
|
||||||
localAddr: uint16(targetAddr),
|
|
||||||
|
|
||||||
remoteSid1: uint32(remoteSid1),
|
|
||||||
remoteSid2: uint32(remoteSid2),
|
|
||||||
localSid1: uint32(localSid1),
|
|
||||||
localSid2: uint32(localSid2),
|
|
||||||
|
|
||||||
remoteSinit1: uint32(remoteSinit1),
|
|
||||||
remoteSinit2: uint32(remoteSinit2),
|
|
||||||
localSinit1: uint32(localSinit1),
|
|
||||||
localSinit2: uint32(localSinit2),
|
|
||||||
|
|
||||||
remoteDataVer1: uint32(remoteDataVer1),
|
|
||||||
remoteDataVer2: uint32(remoteDataVer2),
|
|
||||||
localDataVer1: uint32(localDataVer1),
|
|
||||||
localDataVer2: uint32(localDataVer2),
|
|
||||||
|
|
||||||
lfsr1: &lfsr{value: uint32(localSid1), poly: msg.T_POLY_1},
|
|
||||||
lfsr2: &lfsr{value: uint32(localSid2), poly: msg.T_POLY_2},
|
|
||||||
|
|
||||||
precSinit1: calculatePrecSinit(uint32(remoteSinit1), uint32(localSid1), uint32(remoteDataVer1)),
|
|
||||||
precSinit2: calculatePrecSinit(uint32(remoteSinit2), uint32(localSid2), uint32(remoteDataVer2)),
|
|
||||||
}
|
|
||||||
return serviceCtx
|
|
||||||
}
|
|
||||||
|
|
||||||
func calculatePrecSinit(remoteSinit uint32, localSid uint32, remoteDataVer uint32) uint32 {
|
|
||||||
l1 := lfsr{value: remoteSinit, poly: msg.T_POLY_1}
|
|
||||||
l1.add(localSid ^ remoteDataVer)
|
|
||||||
valueTmp := l1.value
|
|
||||||
l1.load(0).post(valueTmp)
|
|
||||||
return l1.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func Stop(simulation *memory.VerifySimulation) {
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
rsspConfig := simulation.GetRunConfig().RsspAxleConfig
|
|
||||||
serviceCtx := contextMap[rsspConfig.StationCode]
|
|
||||||
if serviceCtx == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
serviceCtx.stop()
|
|
||||||
delete(contextMap, rsspConfig.StationCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) stop() {
|
|
||||||
if s.server != nil {
|
|
||||||
s.server.Close()
|
|
||||||
}
|
|
||||||
if s.client != nil {
|
|
||||||
s.client.Close()
|
|
||||||
}
|
|
||||||
s.cancelFunc()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) runCollectTask(ctx context.Context) {
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
logger().Error("状态收集任务出错,记录后重启", "error", err, "stack", string(debug.Stack()))
|
|
||||||
s.runCollectTask(ctx)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for range time.Tick(time.Duration(s.config.NetAConfig.Period) * time.Millisecond) {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
frame := s.collect()
|
|
||||||
data := frame.Encode()
|
|
||||||
err := s.client.Send(data)
|
|
||||||
if err != nil {
|
|
||||||
s.state = tpapi.ThirdPartyState_Broken
|
|
||||||
logger().Error("发送状态数据失败", "error", err)
|
|
||||||
} else {
|
|
||||||
s.state = tpapi.ThirdPartyState_Normal
|
|
||||||
//logger().Info(fmt.Sprintf("发送数据:%x", data))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) collect() *msg.RsdMsgBuilder {
|
|
||||||
worldData := entity.GetWorldData(s.sim.World)
|
|
||||||
stateInfos := msg.StateInfos{}
|
|
||||||
for _, cfg := range s.ciSectionIndexConfigs {
|
|
||||||
entry := worldData.EntityMap[cfg.SectionId]
|
|
||||||
if entry == nil {
|
|
||||||
logger().Error(fmt.Sprintf("没有id[%s]的区段实体", cfg.SectionId))
|
|
||||||
}
|
|
||||||
am := component.PhysicalSectionManagerType.Get(entry)
|
|
||||||
stateInfo := &msg.StateInfo{
|
|
||||||
CLR: !am.Occupied,
|
|
||||||
OCC: am.Occupied,
|
|
||||||
}
|
|
||||||
stateInfos = append(stateInfos, stateInfo)
|
|
||||||
//预复位/复位驱动反馈状态
|
|
||||||
state := s.sectionStateMap[cfg.SectionId]
|
|
||||||
delete(s.sectionStateMap, cfg.SectionId)
|
|
||||||
if state != nil {
|
|
||||||
stateInfo.RAC = state.Rac
|
|
||||||
stateInfo.RJO = state.Rjo
|
|
||||||
stateInfo.RJT = state.Rjt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
userData := []byte{0x00} //检查字节
|
|
||||||
userData = append(userData, stateInfos.Encode()...)
|
|
||||||
//更新序列号及时间戳
|
|
||||||
s.seqNum++
|
|
||||||
s.lfsr1.add(0)
|
|
||||||
s.lfsr2.add(0)
|
|
||||||
//构建消息
|
|
||||||
builder := &msg.RsdMsgBuilder{
|
|
||||||
MsgHeader: msg.MsgHeader{
|
|
||||||
ProtocolType: msg.ProtocolType_Sync,
|
|
||||||
MessageType: msg.MessageType_B, //从抓包数据里看到的
|
|
||||||
SourceAddr: s.localAddr,
|
|
||||||
TargetAddr: s.remoteAddr,
|
|
||||||
},
|
|
||||||
SeqNum: s.seqNum,
|
|
||||||
Svc1: s.calculateSvc1(userData),
|
|
||||||
Svc2: s.calculateSvc2(userData),
|
|
||||||
UserData: userData,
|
|
||||||
}
|
|
||||||
return builder
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) calculateSvc1(userData []byte) uint32 {
|
|
||||||
return message.Rssp_I_Crc32C1(userData) ^ s.localSid1 ^ s.lfsr1.value ^ msg.SCW_1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) calculateSvc2(userData []byte) uint32 {
|
|
||||||
return message.Rssp_I_Crc32C2(userData) ^ s.localSid2 ^ s.lfsr2.value ^ msg.SCW_2
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) runHandleMsgTask(ctx context.Context) {
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
logger().Error("消息处理任务出错,记录后重启", "error", err, "stack", string(debug.Stack()))
|
|
||||||
s.runHandleMsgTask(ctx)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for {
|
|
||||||
if len(s.msgChan) > 10 {
|
|
||||||
logger().Warn(fmt.Sprintf("消息处理耗时过长,消息队列长度:%d", len(s.msgChan)))
|
|
||||||
}
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
case <-s.sseWaitTimer: //SSE消息等待超时
|
|
||||||
s.sseMsg = nil
|
|
||||||
case data := <-s.msgChan:
|
|
||||||
messageType := msg.GetMessageType(data)
|
|
||||||
switch messageType {
|
|
||||||
case msg.MessageType_A, msg.MessageType_B:
|
|
||||||
s.handleRsdMsg(data)
|
|
||||||
case msg.MessageType_SSE:
|
|
||||||
s.handleSseMsg(data)
|
|
||||||
case msg.MessageType_SSR:
|
|
||||||
s.handleSsrMsg(data)
|
|
||||||
default:
|
|
||||||
logger().Warn(fmt.Sprintf("未知的消息类型[%x]", messageType))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) handleRsdMsg(data []byte) {
|
|
||||||
if s.sseMsg != nil { //正在时序校正过程中
|
|
||||||
return
|
|
||||||
}
|
|
||||||
rsdMsg := &msg.RsdMsg{}
|
|
||||||
err := rsdMsg.Decode(data)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("解析RSD数据出错", "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//校验
|
|
||||||
validateResult := s.validateRsdMsg(rsdMsg, data)
|
|
||||||
if validateResult == 0 {
|
|
||||||
return
|
|
||||||
} else if validateResult == 2 {
|
|
||||||
//开启时序校正流程
|
|
||||||
logger().Error("时序校验失败,开始时序校正")
|
|
||||||
s.startSeeProgress()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//流程处理
|
|
||||||
cmdInfos := msg.CmdInfos{}
|
|
||||||
err = cmdInfos.Decode(rsdMsg.UserData[1:]) //用户数据第一个字节是[检查字节]
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("解析命令信息出错", "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//驱动
|
|
||||||
for i, cmdInfo := range cmdInfos {
|
|
||||||
sectionIndexConfig := s.ciSectionIndexConfigs[i]
|
|
||||||
if cmdInfo.PDRST {
|
|
||||||
state, err := fi.PhysicalSectionPdrstDrive(s.sim.World, sectionIndexConfig.SectionId)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("计轴预复位驱动出错", "error", err)
|
|
||||||
}
|
|
||||||
s.sectionStateMap[sectionIndexConfig.SectionId] = state
|
|
||||||
}
|
|
||||||
if cmdInfo.DRST {
|
|
||||||
state, err := fi.PhysicalSectionDrstDrive(s.sim.World, sectionIndexConfig.SectionId)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("计轴复位驱动出错", "error", err)
|
|
||||||
}
|
|
||||||
s.sectionStateMap[sectionIndexConfig.SectionId] = state
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) handleSseMsg(data []byte) {
|
|
||||||
sseMsg := &msg.SseMsg{}
|
|
||||||
err := sseMsg.Decode(data)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("解析SSE数据出错", "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//校验
|
|
||||||
if !s.validateSseMsg(sseMsg) {
|
|
||||||
logger().Error("SSE数据校验失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger().Info(fmt.Sprintf("SSE数据通过校验:%x", data))
|
|
||||||
//回复
|
|
||||||
ssrMsg := msg.SsrMsg{
|
|
||||||
MsgHeader: msg.MsgHeader{
|
|
||||||
ProtocolType: msg.ProtocolType_Sync,
|
|
||||||
MessageType: msg.MessageType_SSR,
|
|
||||||
SourceAddr: s.localAddr,
|
|
||||||
TargetAddr: s.remoteAddr,
|
|
||||||
},
|
|
||||||
SeqNumSsr: s.seqNum,
|
|
||||||
SeqNumSse: sseMsg.SeqNum,
|
|
||||||
SeqInit1: s.calculateSeqInit1(sseMsg.SeqEnq1),
|
|
||||||
SeqInit2: s.calculateSeqInit2(sseMsg.SeqEnq2),
|
|
||||||
DataVer: 0x01,
|
|
||||||
}
|
|
||||||
ssrBytes := ssrMsg.Encode()
|
|
||||||
err = s.client.Send(ssrBytes)
|
|
||||||
if err != nil {
|
|
||||||
s.state = tpapi.ThirdPartyState_Broken
|
|
||||||
logger().Error("发送SSR数据失败", "error", err)
|
|
||||||
} else {
|
|
||||||
s.state = tpapi.ThirdPartyState_Normal
|
|
||||||
logger().Info(fmt.Sprintf("发送SSR数据:%x", ssrBytes))
|
|
||||||
//更新本地数据
|
|
||||||
s.lastSeqParam1 = (&lfsr{value: s.remoteSinit1, poly: msg.T_POLY_1}).add(sseMsg.SeqEnq1)
|
|
||||||
s.lastSeqParam2 = (&lfsr{value: s.remoteSinit2, poly: msg.T_POLY_2}).add(sseMsg.SeqEnq2)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) handleSsrMsg(data []byte) {
|
|
||||||
if s.sseMsg == nil { //不在时序校正过程中
|
|
||||||
logger().Warn("不在时序校正流程中,丢弃SSR数据")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ssrMsg := &msg.SsrMsg{}
|
|
||||||
err := ssrMsg.Decode(data)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("解析SSR数据出错", "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//校验
|
|
||||||
if !s.validateSsrMsg(ssrMsg) {
|
|
||||||
logger().Error("SSR数据校验失败")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger().Info("SSR数据通过校验")
|
|
||||||
//完成校正时序(precSinit~+t_e == Sinit_r~+(sid_r^t_r))
|
|
||||||
s.lastSeqParam1 = (&lfsr{value: s.precSinit1, poly: msg.T_POLY_1}).add(ssrMsg.SeqInit1 ^ (s.sseMsg.SeqEnq1 ^ s.localSid1))
|
|
||||||
s.lastSeqParam2 = (&lfsr{value: s.precSinit2, poly: msg.T_POLY_2}).add(ssrMsg.SeqInit2 ^ (s.sseMsg.SeqEnq2 ^ s.localSid2))
|
|
||||||
s.sseMsg = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 启动SSE流程
|
|
||||||
func (s *serviceContext) startSeeProgress() {
|
|
||||||
sseMsg := &msg.SseMsg{
|
|
||||||
MsgHeader: msg.MsgHeader{
|
|
||||||
ProtocolType: msg.ProtocolType_Sync,
|
|
||||||
MessageType: msg.MessageType_SSE,
|
|
||||||
SourceAddr: s.localAddr,
|
|
||||||
TargetAddr: s.remoteAddr,
|
|
||||||
},
|
|
||||||
SeqNum: s.seqNum,
|
|
||||||
SeqEnq1: s.calculateSeqEnq1(),
|
|
||||||
SeqEnq2: s.calculateSeqEnq2(),
|
|
||||||
}
|
|
||||||
sseBytes := sseMsg.Encode()
|
|
||||||
err := s.client.Send(sseBytes)
|
|
||||||
if err != nil {
|
|
||||||
s.state = tpapi.ThirdPartyState_Broken
|
|
||||||
logger().Error("发送SSE数据失败", "error", err)
|
|
||||||
} else {
|
|
||||||
s.state = tpapi.ThirdPartyState_Normal
|
|
||||||
logger().Info(fmt.Sprintf("发送SSE数据:%x", sseBytes))
|
|
||||||
s.sseMsg = sseMsg
|
|
||||||
s.sseWaitTimer = time.After(time.Duration(s.config.NetAConfig.Period*msg.Twait_sse) * time.Millisecond)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 校验RSD消息
|
|
||||||
// return 0-时序校验之外的失败 1-成功 2-时序异常
|
|
||||||
func (s *serviceContext) validateRsdMsg(rsdMsg *msg.RsdMsg, data []byte) int {
|
|
||||||
if rsdMsg.SourceAddr != s.remoteAddr {
|
|
||||||
logger().Error(fmt.Sprintf("源地址[%x]不正确[%s]", rsdMsg.SourceAddr, s.config.NetAConfig.RemoteAddr))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if rsdMsg.TargetAddr != s.localAddr {
|
|
||||||
logger().Error(fmt.Sprintf("目的地址[%x]不正确[%s]", rsdMsg.TargetAddr, s.config.NetAConfig.LocalAddr))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if len(rsdMsg.UserData)-1 != len(s.ciSectionIndexConfigs) { //用户数据第一个字节是[检查字节]
|
|
||||||
logger().Error(fmt.Sprintf("命令数据长度[%d]与配置长度[%d]不符", len(rsdMsg.UserData), len(s.ciSectionIndexConfigs)))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if message.Rssp_I_Crc16(data[:len(data)-2]) != rsdMsg.Tail {
|
|
||||||
logger().Error(fmt.Sprintf("报文尾验证失败"))
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
if !s.validateSvc1(rsdMsg.Svc1, rsdMsg.UserData) {
|
|
||||||
logger().Error(fmt.Sprintf("SVC1[%x]校验未通过", rsdMsg.Svc1))
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
if !s.validateSvc2(rsdMsg.Svc2, rsdMsg.UserData) {
|
|
||||||
logger().Error(fmt.Sprintf("SVC2[%x]校验未通过", rsdMsg.Svc2))
|
|
||||||
return 2
|
|
||||||
}
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) validateSseMsg(sseMsg *msg.SseMsg) bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) validateSsrMsg(ssrMsg *msg.SsrMsg) bool {
|
|
||||||
if s.sseMsg.SeqNum != ssrMsg.SeqNumSse {
|
|
||||||
logger().Error(fmt.Sprintf("SSR的时序号[%d]与请求方不符[%d]", ssrMsg.SeqNumSse, s.sseMsg.SeqNum))
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) validateSvc1(svc uint32, userData []byte) bool {
|
|
||||||
return s.validateSvc(svc, msg.SCW_1, message.Rssp_I_Crc32C1(userData), s.remoteSid1, s.remoteSinit1, &s.lastSeqParam1, msg.T_POLY_1)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) validateSvc2(svc uint32, userData []byte) bool {
|
|
||||||
return s.validateSvc(svc, msg.SCW_2, message.Rssp_I_Crc32C2(userData), s.remoteSid2, s.remoteSinit2, &s.lastSeqParam2, msg.T_POLY_2)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) validateSvc(svc uint32, scw uint32, crc1 uint32, sid uint32, sinit uint32, lastSeqParam *uint32, tPoly uint32) bool {
|
|
||||||
seqParam := crc1 ^ svc ^ scw
|
|
||||||
for i := 0; i <= s.config.NetAConfig.MaxDeviation; i++ {
|
|
||||||
seqLfsr := lfsr{value: *lastSeqParam, poly: tPoly}
|
|
||||||
constLfsr := lfsr{value: sinit, poly: tPoly}
|
|
||||||
constLfsr.add(sid)
|
|
||||||
for j := 0; j < i; j++ {
|
|
||||||
seqLfsr.add(0)
|
|
||||||
constLfsr.add(0)
|
|
||||||
}
|
|
||||||
if seqLfsr.add(seqParam) == constLfsr.add(sid) {
|
|
||||||
*lastSeqParam = seqLfsr.load(sinit).add(seqParam)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) calculateSeqEnq1() uint32 {
|
|
||||||
return s.localSid1 ^ s.lfsr1.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) calculateSeqEnq2() uint32 {
|
|
||||||
return s.localSid2 ^ s.lfsr2.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) calculateSeqInit1(seqEnq1 uint32) uint32 {
|
|
||||||
return seqEnq1 ^ s.localSid1 ^ s.localDataVer1 ^ s.lfsr1.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) calculateSeqInit2(seqEnq2 uint32) uint32 {
|
|
||||||
return seqEnq2 ^ s.localSid2 ^ s.localDataVer2 ^ s.lfsr2.value
|
|
||||||
}
|
|
||||||
|
|
||||||
type lfsr struct {
|
|
||||||
value uint32
|
|
||||||
poly uint32 //时间戳生成多项式
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *lfsr) load(value uint32) *lfsr {
|
|
||||||
l.value = value
|
|
||||||
return l
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *lfsr) add(x uint32) uint32 {
|
|
||||||
l.value = l.value ^ x
|
|
||||||
var carry bool
|
|
||||||
for i := 0; i < 32; i++ {
|
|
||||||
carry = l.value&0x80000000 != 0
|
|
||||||
l.value = l.value << 1
|
|
||||||
if carry {
|
|
||||||
l.value ^= l.poly
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return l.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *lfsr) post(x uint32) uint32 {
|
|
||||||
|
|
||||||
var carry bool
|
|
||||||
for i := 0; i < 32; i++ {
|
|
||||||
carry = x&1 == 1
|
|
||||||
if carry {
|
|
||||||
x ^= l.poly
|
|
||||||
}
|
|
||||||
x = x >> 1
|
|
||||||
if carry {
|
|
||||||
x |= 0x80000000
|
|
||||||
}
|
|
||||||
}
|
|
||||||
l.value ^= x
|
|
||||||
return l.value
|
|
||||||
}
|
|
||||||
|
|
||||||
func logger() *slog.Logger {
|
|
||||||
loggerInit.Do(func() {
|
|
||||||
privateLogger = slog.Default().With("tag", logTag)
|
|
||||||
})
|
|
||||||
return privateLogger
|
|
||||||
}
|
|
@ -1,19 +0,0 @@
|
|||||||
package beijing12
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/axle_device/beijing12/msg"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Test_serviceContext_calculateSvc1(t *testing.T) {
|
|
||||||
serviceCtx := &serviceContext{
|
|
||||||
localSid1: 0x7665986c,
|
|
||||||
localSid2: 0x67da286e,
|
|
||||||
lfsr1: &lfsr{value: uint32(0x7665986c), poly: msg.T_POLY_1},
|
|
||||||
lfsr2: &lfsr{value: uint32(0x67da286e), poly: msg.T_POLY_2},
|
|
||||||
}
|
|
||||||
userData := []byte{00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00}
|
|
||||||
fmt.Printf("%x\n", serviceCtx.calculateSvc1(userData))
|
|
||||||
fmt.Printf("%x\n", serviceCtx.calculateSvc2(userData))
|
|
||||||
}
|
|
129
third_party/axle_device/rssp_axle.go
vendored
Normal file
129
third_party/axle_device/rssp_axle.go
vendored
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package axle_device
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"log/slog"
|
||||||
|
"runtime/debug"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
//计轴设备与联锁系统安全通信应用层实现
|
||||||
|
|
||||||
|
type RsspAxle interface {
|
||||||
|
//Start 启动计轴设备与联锁系统安全通信服务
|
||||||
|
Start(amm AxleMessageManager) error
|
||||||
|
//Stop 停止计轴设备与联锁系统安全通信服务
|
||||||
|
Stop()
|
||||||
|
}
|
||||||
|
|
||||||
|
type rsspAxle struct {
|
||||||
|
//所属城市
|
||||||
|
city string
|
||||||
|
//所属线路
|
||||||
|
lineId string
|
||||||
|
//所属集中站
|
||||||
|
centralizedStation string
|
||||||
|
//接收方每个安全通信会话对应的发送周期值,单位ms
|
||||||
|
sendingPeriod uint32
|
||||||
|
//主安全通道
|
||||||
|
rsspChannel *RsspChannel
|
||||||
|
//收到应用层消息回调
|
||||||
|
messageManager AxleMessageManager
|
||||||
|
//发送区段状态任务
|
||||||
|
cancelSendStatus context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitRsspAxle(cfg *config.RsspAxleConfig) RsspAxle {
|
||||||
|
ra := &rsspAxle{}
|
||||||
|
//
|
||||||
|
ra.city = cfg.City
|
||||||
|
ra.lineId = cfg.LineId
|
||||||
|
ra.centralizedStation = cfg.CentralizedStation
|
||||||
|
ra.sendingPeriod = cfg.RsspCfg.SendingPeriod
|
||||||
|
//
|
||||||
|
mrc := &RsspChannel{}
|
||||||
|
ra.rsspChannel = mrc.Init(&cfg.RsspCfg)
|
||||||
|
//
|
||||||
|
return ra
|
||||||
|
}
|
||||||
|
|
||||||
|
// rssp 安全层执行
|
||||||
|
func (s *rsspAxle) rcvCmdMsg(data []byte) {
|
||||||
|
msg := &message.SectionCmdMsgPack{}
|
||||||
|
msg.Decode(data)
|
||||||
|
s.messageManager.HandleSectionCmdMsg(s.city, s.lineId, s.centralizedStation, msg)
|
||||||
|
}
|
||||||
|
func (s *rsspAxle) Start(amm AxleMessageManager) error {
|
||||||
|
s.messageManager = amm
|
||||||
|
//设置安全通道层
|
||||||
|
if s.rsspChannel != nil {
|
||||||
|
s.rsspChannel.handleUserData = s.rcvCmdMsg
|
||||||
|
s.rsspChannel.Start()
|
||||||
|
}
|
||||||
|
//
|
||||||
|
sendContext, sendCancel := context.WithCancel(context.Background())
|
||||||
|
go s.periodRun(sendContext)
|
||||||
|
s.cancelSendStatus = sendCancel
|
||||||
|
//
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
func (s *rsspAxle) Stop() {
|
||||||
|
if s.rsspChannel != nil {
|
||||||
|
s.rsspChannel.Stop()
|
||||||
|
}
|
||||||
|
//
|
||||||
|
if s.cancelSendStatus != nil {
|
||||||
|
s.cancelSendStatus()
|
||||||
|
}
|
||||||
|
s.messageManager = nil
|
||||||
|
}
|
||||||
|
func (s *rsspAxle) periodRun(runContext context.Context) {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
defer func() {
|
||||||
|
if e := recover(); e != nil {
|
||||||
|
slog.Error(fmt.Sprintf("[%s-%s-%s]定时发送计轴区段状态任务异常", s.city, s.lineId, s.centralizedStation), "error", e, "stack", string(debug.Stack()))
|
||||||
|
debug.PrintStack()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-runContext.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
//slog.Debug("计轴设备periodRun")
|
||||||
|
if s.messageManager == nil {
|
||||||
|
slog.Warn(fmt.Sprintf("[%s-%s-%s]定时发送计轴区段状态任务因messageManager不存在退出", s.city, s.lineId, s.centralizedStation))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//收集区段状态
|
||||||
|
sectionStatusMsg, e := s.messageManager.CollectSectionStatus(s.city, s.lineId, s.centralizedStation)
|
||||||
|
if e == nil {
|
||||||
|
if sectionStatusMsg != nil {
|
||||||
|
msgPack := &message.SectionStatusMsgPack{}
|
||||||
|
msgPack.Ck = 0 //暂时无用
|
||||||
|
msgPack.Sms = sectionStatusMsg
|
||||||
|
s.sendStatusMsg(msgPack)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
slog.Warn(e.Error())
|
||||||
|
}
|
||||||
|
//
|
||||||
|
time.Sleep(time.Duration(s.sendingPeriod) * time.Millisecond)
|
||||||
|
//更新周期性参数
|
||||||
|
s.rsspChannel.NextPeriod()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送计轴区段状态给联锁
|
||||||
|
func (s *rsspAxle) sendStatusMsg(msg *message.SectionStatusMsgPack) {
|
||||||
|
data := msg.Encode()
|
||||||
|
//向主通道发送
|
||||||
|
if s.rsspChannel != nil {
|
||||||
|
//slog.Debug("计轴设备发送SectionStatusMsgPack", "区段状态个数", len(msg.Sms), "packLen", len(data))
|
||||||
|
s.rsspChannel.SendUserData(data)
|
||||||
|
}
|
||||||
|
}
|
65
third_party/axle_device/rssp_axle_manage.go
vendored
Normal file
65
third_party/axle_device/rssp_axle_manage.go
vendored
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
package axle_device
|
||||||
|
|
||||||
|
import (
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"log/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
//联锁集中站计轴与联锁通信管理
|
||||||
|
|
||||||
|
type AxleMessageManager interface {
|
||||||
|
GetLineAllRsspAxleCfgs() []config.RsspAxleConfig
|
||||||
|
//HandleSectionCmdMsg 计轴设备接收到联锁发送来的控制命令
|
||||||
|
HandleSectionCmdMsg(city string, lineId string, centralizedStation string, msg *message.SectionCmdMsgPack)
|
||||||
|
//CollectSectionStatus 收集仿真中计轴区段状态
|
||||||
|
CollectSectionStatus(city string, lineId string, centralizedStation string) ([]*message.SectionStatusMsg, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
var allRsspAxleServices []RsspAxle
|
||||||
|
|
||||||
|
func StartLineAllRsspAxleServices(ram AxleMessageManager) {
|
||||||
|
allRsspAxleServices = nil
|
||||||
|
cfgs := ram.GetLineAllRsspAxleCfgs()
|
||||||
|
//cfgs = getTestConfig() //测试用
|
||||||
|
for _, cfg := range cfgs {
|
||||||
|
if cfg.Open {
|
||||||
|
as := InitRsspAxle(&cfg)
|
||||||
|
allRsspAxleServices = append(allRsspAxleServices, as)
|
||||||
|
as.Start(ram)
|
||||||
|
slog.Debug("启动计轴设备", "city", cfg.City, "lineId", cfg.LineId, "CentralizedStation", cfg.CentralizedStation)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func StopLineAllRsspAxleServices() {
|
||||||
|
for _, as := range allRsspAxleServices {
|
||||||
|
as.Stop()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 测试用
|
||||||
|
func getTestConfig() []config.RsspAxleConfig {
|
||||||
|
cfg := &config.RsspAxleConfig{}
|
||||||
|
cfg.Open = true
|
||||||
|
cfg.City = "北京"
|
||||||
|
cfg.LineId = "12"
|
||||||
|
cfg.CentralizedStation = "酒仙桥"
|
||||||
|
cfg.RsspCfg.SrcAddr = 0x02
|
||||||
|
cfg.RsspCfg.DstAddr = 0x01
|
||||||
|
cfg.RsspCfg.DataVer1 = 0x0011
|
||||||
|
cfg.RsspCfg.DataVer2 = 0x0012
|
||||||
|
cfg.RsspCfg.SID1 = 0x10000000
|
||||||
|
cfg.RsspCfg.SID2 = 0x00000001
|
||||||
|
cfg.RsspCfg.SINIT1 = 0x01
|
||||||
|
cfg.RsspCfg.SINIT2 = 0x02
|
||||||
|
cfg.RsspCfg.SendingPeriod = 500
|
||||||
|
cfg.RsspCfg.SsrRsspTimeout = 3
|
||||||
|
cfg.RsspCfg.Mtv = 3
|
||||||
|
cfg.RsspCfg.DeviceA = false
|
||||||
|
cfg.RsspCfg.PicType = message.PIC_MASTER
|
||||||
|
cfg.RsspCfg.RemoteIp = "192.168.3.5"
|
||||||
|
cfg.RsspCfg.RemoteUdpPort = 7777
|
||||||
|
cfg.RsspCfg.LocalUdpPort = 6666
|
||||||
|
//
|
||||||
|
return []config.RsspAxleConfig{*cfg}
|
||||||
|
}
|
315
third_party/axle_device/rssp_channel.go
vendored
Normal file
315
third_party/axle_device/rssp_channel.go
vendored
Normal file
@ -0,0 +1,315 @@
|
|||||||
|
package axle_device
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 铁路信号安全通信协议实现
|
||||||
|
|
||||||
|
// HandleUserData 回调应用层
|
||||||
|
type HandleUserData func([]byte)
|
||||||
|
|
||||||
|
// RsspChannel 实现rssp通信
|
||||||
|
type RsspChannel struct {
|
||||||
|
//udp
|
||||||
|
udpServer udp.UdpServer
|
||||||
|
//udp
|
||||||
|
udpClient udp.UdpClient
|
||||||
|
//回调应用层
|
||||||
|
handleUserData HandleUserData
|
||||||
|
//rssp安全通信配置
|
||||||
|
config *config.RsspConfig
|
||||||
|
//rssp时钟
|
||||||
|
rsspTimer *RsspTimer
|
||||||
|
//批次编号,发送序列号
|
||||||
|
sn *message.RsspSn
|
||||||
|
//安全通道1时间戳
|
||||||
|
ch1Ts *message.RsspLFSR
|
||||||
|
//安全通道2时间戳
|
||||||
|
ch2Ts *message.RsspLFSR
|
||||||
|
//最近一次接收到的报文的安全通道1时间戳
|
||||||
|
rcvCh1Ts uint32
|
||||||
|
//最近一次接收到的报文的安全通道2时间戳
|
||||||
|
rcvCh2Ts uint32
|
||||||
|
//最近一次接收到的报文的序列号
|
||||||
|
rcvSn uint32
|
||||||
|
//时序校验请求发送记录
|
||||||
|
sendSseRecord *SseFireRecord
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RsspChannel) SetRcvUserDataCallback(handleUserData HandleUserData) {
|
||||||
|
s.handleUserData = handleUserData
|
||||||
|
}
|
||||||
|
func (s *RsspChannel) Init(config *config.RsspConfig) *RsspChannel {
|
||||||
|
s.config = config
|
||||||
|
s.rsspTimer = &RsspTimer{t: 0}
|
||||||
|
s.sn = message.NewRsspSn(1)
|
||||||
|
s.ch1Ts = message.NewRsspLFSR(message.RSSP_I_C1_TS, 32, s.config.SID1, false)
|
||||||
|
s.ch2Ts = message.NewRsspLFSR(message.RSSP_I_C2_TS, 32, s.config.SID2, false)
|
||||||
|
return s
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start 启动安全通道
|
||||||
|
func (s *RsspChannel) Start() {
|
||||||
|
//
|
||||||
|
s.udpServer = udp.NewServer(fmt.Sprintf(":%d", s.config.LocalUdpPort), s.handleRsspMsg)
|
||||||
|
s.udpServer.Listen()
|
||||||
|
//
|
||||||
|
s.udpClient = udp.NewClient(fmt.Sprintf("%s:%d", s.config.RemoteIp, s.config.RemoteUdpPort))
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop 关闭安全通道
|
||||||
|
func (s *RsspChannel) Stop() {
|
||||||
|
if s.udpServer != nil {
|
||||||
|
s.udpServer.Close()
|
||||||
|
}
|
||||||
|
if s.udpClient != nil {
|
||||||
|
s.udpClient.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// RsspTimer rssp时钟,每一个tick周期为config.SendingPeriod
|
||||||
|
type RsspTimer struct {
|
||||||
|
t uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *RsspTimer) tick() {
|
||||||
|
s.t++
|
||||||
|
}
|
||||||
|
func (s *RsspTimer) now() uint64 {
|
||||||
|
return s.t
|
||||||
|
}
|
||||||
|
|
||||||
|
// SseFireRecord 发送时序校验请求的记录
|
||||||
|
type SseFireRecord struct {
|
||||||
|
send *message.RsspSse //已经发送的时序校验请求
|
||||||
|
rsspTime uint64 //发送时序校验请求时的rssp时间
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SseFireRecord) record(send *message.RsspSse, rsspTime uint64) {
|
||||||
|
s.send = send
|
||||||
|
s.rsspTime = rsspTime
|
||||||
|
}
|
||||||
|
func (s *SseFireRecord) clear() {
|
||||||
|
s.send = nil
|
||||||
|
s.rsspTime = 0
|
||||||
|
}
|
||||||
|
func (s *SseFireRecord) hasRecord() bool {
|
||||||
|
return s.send != nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理接收到的rssp报文
|
||||||
|
// 注意本函数由udp socket 协程执行
|
||||||
|
func (s *RsspChannel) handleRsspMsg(pack []byte) {
|
||||||
|
slog.Debug("接收到RSSP报文", "len", len(pack))
|
||||||
|
//报文头校验
|
||||||
|
head := &message.RsspHead{}
|
||||||
|
if !head.Parse(pack) { //解析报文头失败
|
||||||
|
slog.Debug("丢弃接收的RSSP报文:解析报文头失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !message.RsspHeadMcCheck(head) { //报文类别检测未通过
|
||||||
|
slog.Debug("丢弃接收的RSSP报文:报文类别检测未通过")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !message.RsspHeadPicCheck(head) { //协议交互类别检测未通过
|
||||||
|
slog.Debug("丢弃接收的RSSP报文:协议交互类别检测未通过")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !s.config.CheckAddress(head.Sa, head.Da) { //校验报文头中源地址和目的地址是否包含在已配置列表中
|
||||||
|
slog.Debug("丢弃接收的RSSP报文:报文头中源地址或目的地址不在在已配置列表中")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//报文尾校验
|
||||||
|
if !message.RsspPackCrc16Check(pack) { //整个报文crc16校验未通过
|
||||||
|
slog.Debug("丢弃接收的RSSP报文:报文尾CRC16校验未通过")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//解析得到RSD、SSE或SRE
|
||||||
|
rssp := message.ParseRsspPack(head, pack)
|
||||||
|
if rssp == nil { //解析具体rssp包失败
|
||||||
|
slog.Debug("丢弃接收的RSSP报文:解析具体类别包失败")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//处理接收到的具体类别RSSP包
|
||||||
|
switch rssp.Type() {
|
||||||
|
case message.RSD_A:
|
||||||
|
fallthrough
|
||||||
|
case message.RSD_B:
|
||||||
|
s.handleRsspRsd(rssp.(*message.RsspRsd))
|
||||||
|
case message.SSE:
|
||||||
|
s.handleRsspSse(rssp.(*message.RsspSse))
|
||||||
|
case message.SSR:
|
||||||
|
s.handleRsspSsr(rssp.(*message.RsspSsr))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 处理接收到的实时安全数据 RSD
|
||||||
|
func (s *RsspChannel) handleRsspRsd(rsd *message.RsspRsd) {
|
||||||
|
//slog.Debug("接收到的实时安全数据 RSD")
|
||||||
|
//如果为备机发送来的安全数据
|
||||||
|
if s.config.PicType == message.PIC_SLAVE { //备安全通道
|
||||||
|
slog.Debug("丢弃接收的RSSP-RSD报文:舍弃在备安全通道中接收到的安全数据")
|
||||||
|
//备安全通道收到安全数据,表示该物理通道连接正常
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//如果为主机发送来的安全数据
|
||||||
|
if s.config.PicType == message.PIC_MASTER { //主安全通道
|
||||||
|
if !rsd.IsMaster() {
|
||||||
|
slog.Debug("丢弃接收的RSSP-RSD报文:舍弃在主安全通道中收到的非主机发送来的安全数据")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//序列号校验
|
||||||
|
//接收的序列号小于最近一次有效序列号,则触发SSE时序校验
|
||||||
|
if rsd.Sn < s.rcvSn {
|
||||||
|
slog.Debug("丢弃接收的RSSP-RSD报文:当前接收RSD的序列号小于最近一次接收的RSD的序列号,触发SSE")
|
||||||
|
s.fireSse(rsd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dSn := rsd.Sn - s.rcvSn
|
||||||
|
if dSn > s.config.Mtv {
|
||||||
|
slog.Debug("丢弃接收的RSSP-RSD报文:当前接收RSD的序列号与最近一次接收的RSD的序列号差值过大,触发SSE")
|
||||||
|
s.fireSse(rsd)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//SVC校验
|
||||||
|
c1Crc32 := message.Rssp_I_Crc32C1(rsd.Sad)
|
||||||
|
c1SidTs := c1Crc32 ^ rsd.Svc1 ^ message.RSSP_I_C1_SCW //T(n)
|
||||||
|
//
|
||||||
|
c2Crc32 := message.Rssp_I_Crc32C2(rsd.Sad)
|
||||||
|
c2SidTs := c2Crc32 ^ rsd.Svc2 ^ message.RSSP_I_C2_SCW //T(n)
|
||||||
|
//todo ... SVC校验待完善
|
||||||
|
_ = c1SidTs
|
||||||
|
_ = c2SidTs
|
||||||
|
//校验通过
|
||||||
|
//记录本次接收RSD的序列号和安全校验通道时间戳
|
||||||
|
s.rcvSn = rsd.Sn
|
||||||
|
s.rcvCh1Ts = c1SidTs ^ s.config.SID1
|
||||||
|
s.rcvCh2Ts = c2SidTs ^ s.config.SID2
|
||||||
|
//通知应用层接收应用数据
|
||||||
|
s.handleUserData(rsd.Sad)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 触发时序校正请求
|
||||||
|
func (s *RsspChannel) fireSse(rsd *message.RsspRsd) {
|
||||||
|
s.sendSseRecord = &SseFireRecord{send: s.sendSse(), rsspTime: s.rsspTimer.now()}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接收到时序校正请求
|
||||||
|
func (s *RsspChannel) handleRsspSse(sse *message.RsspSse) {
|
||||||
|
if s.config.PicType != message.PIC_MASTER {
|
||||||
|
slog.Debug("丢弃接收的RSSP-SSE报文:在非主安全通道中收到时序校正请求SSE")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//发送时序校正响应
|
||||||
|
s.sendSsr(sse)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 接收到时序校正应答
|
||||||
|
func (s *RsspChannel) handleRsspSsr(ssr *message.RsspSsr) {
|
||||||
|
//SSR校验
|
||||||
|
if !s.sendSseRecord.hasRecord() {
|
||||||
|
slog.Debug("丢弃接收的RSSP-SSR报文:未发起过SSE时序校正请求")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.rsspTimer.t-s.sendSseRecord.rsspTime > uint64(s.config.SsrRsspTimeout) {
|
||||||
|
slog.Debug("丢弃接收的RSSP-SSR报文:等待SSE响应超时")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if ssr.SeSn != s.sendSseRecord.send.Sn {
|
||||||
|
slog.Debug("丢弃接收的RSSP-SSR报文:SSR与SSE不对应")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
//恢复时序?
|
||||||
|
s.rcvSn = ssr.SrSn
|
||||||
|
s.rcvCh1Ts = ssr.Tic1 ^ s.sendSseRecord.send.SeqEnq1 ^ s.config.SID1 ^ s.config.DataVer1
|
||||||
|
s.rcvCh2Ts = ssr.Tic2 ^ s.sendSseRecord.send.SeqEnq2 ^ s.config.SID2 ^ s.config.DataVer2
|
||||||
|
}
|
||||||
|
|
||||||
|
// NextPeriod 刷新与周期有关的:将序列号和时间戳更新到下一个值
|
||||||
|
func (s *RsspChannel) NextPeriod() {
|
||||||
|
s.sn.GetAndAdd()
|
||||||
|
s.ch1Ts.GetAndMove()
|
||||||
|
s.ch2Ts.GetAndMove()
|
||||||
|
s.rsspTimer.tick()
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送时序校正应答
|
||||||
|
func (s *RsspChannel) sendSsr(sse *message.RsspSse) {
|
||||||
|
ssr := &message.RsspSsr{}
|
||||||
|
//
|
||||||
|
ssr.Pic = message.PIC_MASTER
|
||||||
|
ssr.Mc = message.SSR
|
||||||
|
ssr.Sa = s.config.SrcAddr
|
||||||
|
ssr.Da = s.config.DstAddr
|
||||||
|
ssr.SrSn = s.sn.Get() //当前序列号
|
||||||
|
ssr.SeSn = sse.Sn
|
||||||
|
ssr.Tic1 = sse.SeqEnq1 ^ s.config.SID1 ^ s.ch1Ts.Get() ^ s.config.DataVer1
|
||||||
|
ssr.Tic2 = sse.SeqEnq2 ^ s.config.SID2 ^ s.ch2Ts.Get() ^ s.config.DataVer2
|
||||||
|
ssr.Dvn = 0x01 //预留固定值
|
||||||
|
//
|
||||||
|
rsspPack := ssr.Encode()
|
||||||
|
s.sendPack(rsspPack)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 发送时序校正请求
|
||||||
|
func (s *RsspChannel) sendSse() *message.RsspSse {
|
||||||
|
sse := &message.RsspSse{}
|
||||||
|
//
|
||||||
|
sse.Pic = message.PIC_MASTER
|
||||||
|
sse.Mc = message.SSE
|
||||||
|
sse.Sa = s.config.SrcAddr
|
||||||
|
sse.Da = s.config.DstAddr
|
||||||
|
//时序校正请求,把最近一次接收到的报文中的序列号时间戳发送给发送方
|
||||||
|
sse.Sn = s.rcvSn
|
||||||
|
sse.SeqEnq1 = s.createSeqNeq(s.config.SID1, s.rcvCh1Ts)
|
||||||
|
sse.SeqEnq2 = s.createSeqNeq(s.config.SID2, s.rcvCh2Ts)
|
||||||
|
//
|
||||||
|
rsspPack := sse.Encode()
|
||||||
|
s.sendPack(rsspPack)
|
||||||
|
//
|
||||||
|
return sse
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendUserData 发送用户数据,即通过rssp安全通道发送应用层数据,通过rssp的RSD报文发送
|
||||||
|
func (s *RsspChannel) SendUserData(userData []byte) {
|
||||||
|
rsd := &message.RsspRsd{}
|
||||||
|
rsd.Pic = s.config.PicType
|
||||||
|
if s.config.DeviceA {
|
||||||
|
rsd.Mc = message.RSD_A
|
||||||
|
} else {
|
||||||
|
rsd.Mc = message.RSD_B
|
||||||
|
}
|
||||||
|
rsd.Sa = s.config.SrcAddr
|
||||||
|
rsd.Da = s.config.DstAddr
|
||||||
|
//
|
||||||
|
rsd.Sn = s.sn.Get()
|
||||||
|
rsd.Sdl = uint16(len(userData) + 8)
|
||||||
|
//安全校验通道SVC_1
|
||||||
|
crc_c1 := message.Rssp_I_Crc32C1(userData)
|
||||||
|
rsd.Svc1 = s.createSvcCode(crc_c1, s.config.SID1, s.ch1Ts.Get(), message.RSSP_I_C1_SCW)
|
||||||
|
//安全校验通道SVC_2
|
||||||
|
crc_c2 := message.Rssp_I_Crc32C2(userData)
|
||||||
|
rsd.Svc1 = s.createSvcCode(crc_c2, s.config.SID2, s.ch2Ts.Get(), message.RSSP_I_C2_SCW)
|
||||||
|
rsd.Sad = userData
|
||||||
|
//
|
||||||
|
rsspPack := rsd.Encode()
|
||||||
|
s.sendPack(rsspPack)
|
||||||
|
}
|
||||||
|
func (s *RsspChannel) createSvcCode(crc32 uint32, sid uint32, ts uint32, scw uint32) uint32 {
|
||||||
|
return crc32 ^ sid ^ ts ^ scw
|
||||||
|
}
|
||||||
|
func (s *RsspChannel) createSeqNeq(sid uint32, ts uint32) uint32 {
|
||||||
|
return sid ^ ts
|
||||||
|
}
|
||||||
|
|
||||||
|
// 通过网络发送数据
|
||||||
|
func (s *RsspChannel) sendPack(rsspPack []byte) {
|
||||||
|
s.udpClient.Send(rsspPack)
|
||||||
|
}
|
29
third_party/balise/codec.go
vendored
Normal file
29
third_party/balise/codec.go
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
package balise
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
|
||||||
|
// 应答器数据编解码器
|
||||||
|
type Codec interface {
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
Bytes1023 = 128
|
||||||
|
Bytes341 = 43
|
||||||
|
)
|
||||||
|
|
||||||
|
// 解码应答器数据,1023/341位解码
|
||||||
|
// bys - 128/43字节数据
|
||||||
|
// return - 830/210位数据
|
||||||
|
func Decode(bys []byte) ([]int, error) {
|
||||||
|
size := len(bys)
|
||||||
|
|
||||||
|
if size == Bytes1023 {
|
||||||
|
// 1023应答器解码
|
||||||
|
return nil, nil
|
||||||
|
} else if size == Bytes341 {
|
||||||
|
// 341应答器解码
|
||||||
|
return nil, nil
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("不支持的应答器类型")
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package balisecodec
|
package balise
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -113,99 +113,30 @@ var ConvWords = []uint16{
|
|||||||
var convWordMap = make(map[uint16]int, 1024)
|
var convWordMap = make(map[uint16]int, 1024)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
if len(ConvWords) != 1024 {
|
|
||||||
panic(fmt.Errorf("ConvWords长度不是1024, len=%d", len(ConvWords)))
|
|
||||||
}
|
|
||||||
// 检查,前512个字的累加和为267528,所有1024个字的累加和为1048064
|
|
||||||
sum1 := 0
|
|
||||||
sum2 := 0
|
|
||||||
for i := 0; i < 1024; i++ {
|
|
||||||
if i < 512 {
|
|
||||||
sum1 += int(ConvWords[i])
|
|
||||||
}
|
|
||||||
sum2 += int(ConvWords[i])
|
|
||||||
}
|
|
||||||
if sum1 != 267528 {
|
|
||||||
panic(fmt.Errorf("前512个字的累加和不是267528, sum1=%d", sum1))
|
|
||||||
}
|
|
||||||
if sum2 != 1048064 {
|
|
||||||
panic(fmt.Errorf("所有1024个字的累加和不是1048064, sum2=%d", sum2))
|
|
||||||
}
|
|
||||||
// 检查,后一个字比前一个字大
|
|
||||||
for i := 1; i < 1024; i++ {
|
|
||||||
if ConvWords[i] <= ConvWords[i-1] {
|
|
||||||
panic(fmt.Errorf("第%d个字比第%d个字小, %04o <= %04o", i, i-1, ConvWords[i], ConvWords[i-1]))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i, v := range ConvWords {
|
for i, v := range ConvWords {
|
||||||
convWordMap[v] = i
|
convWordMap[v] = i
|
||||||
//fmt.Printf("%04o: %d\n", v, i)
|
|
||||||
// slog.Info("构建10位到11位转换置换字", "i", i, "v", v)
|
|
||||||
}
|
}
|
||||||
// 检查:翻转有效字的所有位能形成另一个有效字
|
|
||||||
for _, v := range ConvWords {
|
|
||||||
rv := revertBits(v)
|
|
||||||
_, ok := convWordMap[rv]
|
|
||||||
if !ok {
|
|
||||||
panic(fmt.Errorf("构建10位到11位转换置换字失败, v=%04o, rv=%04o", v, rv))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 翻转11位bit数组
|
|
||||||
func revertBits(word uint16) uint16 {
|
|
||||||
bits11 := ToBitsLeftMsb(int(word), 11)
|
|
||||||
revert := make([]byte, 11)
|
|
||||||
for i := 0; i < 11; i++ {
|
|
||||||
if bits11[i] == 1 {
|
|
||||||
revert[i] = 0
|
|
||||||
} else {
|
|
||||||
revert[i] = 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
rw := ToValLeftMsb(revert)
|
|
||||||
// slog.Info("反转11位bit数组", "word", fmt.Sprintf("%04o", word), "bits11", bits11, "revert", revert, "revertWord", fmt.Sprintf("%04o", rw))
|
|
||||||
return rw
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// bit数组转换为数字,左边为最高有效位
|
// bit数组转换为数字,左边为最高有效位
|
||||||
// v - 0/1数组,数组的每个值都只能是0或1
|
// v - 0/1数组,数组的每个值都只能是0或1
|
||||||
func ToValLeftMsb(v []byte) uint16 {
|
func ToVal(v []int) uint16 {
|
||||||
if len(v) > 15 {
|
if len(v) > 15 {
|
||||||
panic(fmt.Errorf("不支持15位以上"))
|
panic(fmt.Errorf("不支持15位以上"))
|
||||||
}
|
}
|
||||||
val := uint16(0)
|
val := uint16(0)
|
||||||
l := len(v)
|
l := len(v)
|
||||||
//elems := make([]string, l)
|
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
//elems[i] = fmt.Sprintf("%d", v[i])
|
|
||||||
if v[i] == 1 {
|
if v[i] == 1 {
|
||||||
val += (1 << (l - i - 1))
|
val += (1 << (l - i - 1))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// slog.Info("ToValLeftMsb", "len", l, "v", strings.Join(elems, ""), "val", fmt.Sprintf("%04o", val))
|
|
||||||
return val
|
|
||||||
}
|
|
||||||
|
|
||||||
// bit数组转换为数字,右边为最高有效位
|
|
||||||
// v - 0/1数组,数组的每个值都只能是0或1
|
|
||||||
func ToValRightMsb(v []byte) uint16 {
|
|
||||||
if len(v) > 15 {
|
|
||||||
panic(fmt.Errorf("不支持15位以上"))
|
|
||||||
}
|
|
||||||
val := uint16(0)
|
|
||||||
l := len(v)
|
|
||||||
for i := 0; i < l; i++ {
|
|
||||||
if v[i] == 1 {
|
|
||||||
val += (1 << i)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数字转换为bit数组,左边为最高有效位
|
// 数字转换为bit数组,左边为最高有效位
|
||||||
func ToBitsLeftMsb(val int, count int) []byte {
|
func ToBits(val int, count int) []int {
|
||||||
bs := make([]byte, count)
|
bs := make([]int, count)
|
||||||
for i := 0; i < count; i++ {
|
for i := 0; i < count; i++ {
|
||||||
tmp := 1 << (count - 1 - i)
|
tmp := 1 << (count - 1 - i)
|
||||||
if (val & (tmp)) == (tmp) {
|
if (val & (tmp)) == (tmp) {
|
||||||
@ -217,42 +148,26 @@ func ToBitsLeftMsb(val int, count int) []byte {
|
|||||||
return bs
|
return bs
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数字转换为bit数组,右边为最高有效位
|
|
||||||
func ToBitsRightMsb(val int, count int) []byte {
|
|
||||||
bs := make([]byte, count)
|
|
||||||
for i := 0; i < count; i++ {
|
|
||||||
tmp := 1 << i
|
|
||||||
if (val & (tmp)) == (tmp) {
|
|
||||||
bs[i] = 1
|
|
||||||
} else {
|
|
||||||
bs[i] = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return bs
|
|
||||||
}
|
|
||||||
|
|
||||||
// 11位字转换回10位字
|
// 11位字转换回10位字
|
||||||
func From11(b11 []byte) ([]byte, error) {
|
func From11(b11 []int) ([]int, error) {
|
||||||
v11 := ToValLeftMsb(b11)
|
v11 := ToVal(b11)
|
||||||
v10, ok := convWordMap[v11]
|
v10, ok := convWordMap[uint16(v11)]
|
||||||
// slog.Info("11位字转换回10位字", "v11", fmt.Sprintf("%04o", v11), "v11b", fmt.Sprintf("%011b", v11), "v10", v10, "ok", ok, "v10bits", fmt.Sprintf("%010b", v10), "to10Bits", ToBitsLeftMsb(v10, 10))
|
|
||||||
if ok {
|
if ok {
|
||||||
return ToBitsLeftMsb(v10, 10), nil
|
return ToBits(v10, 10), nil
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("错误的11位字,word11=%04o", v11)
|
return nil, fmt.Errorf("错误的11位字")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10位字转换为11位字
|
// 10位字转换为11位字
|
||||||
func To11(b10 []byte) []byte {
|
func To11(b10 []int) []int {
|
||||||
if len(b10) != 10 {
|
if len(b10) != 10 {
|
||||||
panic(fmt.Errorf("应答器编码10位字转换为11位字参数异常: 位数不是10, len=%d", len(b10)))
|
panic(fmt.Errorf("应答器编码10位字转换为11位字参数异常: 位数不是10, len=%d", len(b10)))
|
||||||
}
|
}
|
||||||
v10 := ToValLeftMsb(b10)
|
v10 := ToVal(b10)
|
||||||
if v10 > 1023 {
|
if v10 > 1023 {
|
||||||
panic(fmt.Errorf("应答器编码10位字转换为11位字参数异常: 10位字转为整数不能大于1023, v10=%d", v10))
|
panic(fmt.Errorf("应答器编码10位字转换为11位字参数异常: 10位字转为整数不能大于1023, v10=%d", v10))
|
||||||
}
|
}
|
||||||
v11 := ConvWords[v10]
|
v11 := ConvWords[v10]
|
||||||
// slog.Info("10位字转换为11位字", "v10", v10, "v10b", fmt.Sprintf("%010b", v10), "v11", fmt.Sprintf("%04o", v11), "v11bits", fmt.Sprintf("%011b", v11), "to11Bits", ToBitsLeftMsb(int(v11), 11))
|
return ToBits(int(v11), 11)
|
||||||
return ToBitsLeftMsb(int(v11), 11)
|
|
||||||
}
|
}
|
@ -1,10 +1,10 @@
|
|||||||
package balisecodec_test
|
package balise_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"joylink.club/bj-rtsts-server/third_party/balisecodec"
|
"joylink.club/bj-rtsts-server/third_party/balise"
|
||||||
)
|
)
|
||||||
|
|
||||||
var by830 = []int{
|
var by830 = []int{
|
||||||
@ -18,27 +18,27 @@ var by830 = []int{
|
|||||||
|
|
||||||
func TestConvList(t *testing.T) {
|
func TestConvList(t *testing.T) {
|
||||||
// 数量
|
// 数量
|
||||||
assert.Equal(t, 1024, len(balisecodec.ConvWords))
|
assert.Equal(t, 1024, len(balise.ConvWords))
|
||||||
// 后面的数比前面大
|
// 后面的数比前面大
|
||||||
for i := 0; i < 1023; i++ {
|
for i := 0; i < 1023; i++ {
|
||||||
assert.Less(t, balisecodec.ConvWords[i], balisecodec.ConvWords[i+1])
|
assert.Less(t, balise.ConvWords[i], balise.ConvWords[i+1])
|
||||||
}
|
}
|
||||||
// 前512项和
|
// 前512项和
|
||||||
sum_q := 0
|
sum_q := 0
|
||||||
for i := 0; i < 512; i++ {
|
for i := 0; i < 512; i++ {
|
||||||
sum_q += int(balisecodec.ConvWords[i])
|
sum_q += int(balise.ConvWords[i])
|
||||||
}
|
}
|
||||||
assert.Equal(t, 267528, sum_q)
|
assert.Equal(t, 267528, sum_q)
|
||||||
// 后512项和
|
// 后512项和
|
||||||
sum_b := 0
|
sum_b := 0
|
||||||
for i := 512; i < 1024; i++ {
|
for i := 512; i < 1024; i++ {
|
||||||
sum_b += int(balisecodec.ConvWords[i])
|
sum_b += int(balise.ConvWords[i])
|
||||||
}
|
}
|
||||||
// 总1024项和
|
// 总1024项和
|
||||||
assert.Equal(t, 1048064, sum_q+sum_b)
|
assert.Equal(t, 1048064, sum_q+sum_b)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTo11(t *testing.T) {
|
func TestTo11(t *testing.T) {
|
||||||
b10 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
b10 := []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
|
||||||
balisecodec.To11(b10)
|
balise.To11(b10)
|
||||||
}
|
}
|
177
third_party/balisecodec/codec.go
vendored
177
third_party/balisecodec/codec.go
vendored
@ -1,177 +0,0 @@
|
|||||||
package balisecodec
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 应答器数据编解码器
|
|
||||||
type Codec interface {
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
Bytes1023 = 128
|
|
||||||
)
|
|
||||||
|
|
||||||
func Decode(byte128 []byte) ([]byte, error) {
|
|
||||||
if len(byte128) != Bytes1023 {
|
|
||||||
return nil, buildError("应答器报文长度错误, 期望长度为128字节")
|
|
||||||
}
|
|
||||||
bits1023 := convertTo1023Bits(byte128)
|
|
||||||
// 检查控制位
|
|
||||||
err := checkCb(bits1023)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 检查913位数据,并将913位数据转换为830位数据
|
|
||||||
data913 := getRange(bits1023, 1022, 110)
|
|
||||||
scrambled830, err := convert913To830(data913)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// 根据加扰位计算得到加扰器初始值S
|
|
||||||
S := calculateS(getRange(bits1023, 106, 95))
|
|
||||||
// 解扰
|
|
||||||
descrambled830 := descrambling(scrambled830, S)
|
|
||||||
// 还原第一个10位值
|
|
||||||
reverted830 := revertFirst10Bits(descrambled830)
|
|
||||||
// 转换为左边为最高有效位(MSB)的字节数组
|
|
||||||
byte104 := toBytes(reverted830)
|
|
||||||
return byte104, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解码应答器数据,1023/341位解码
|
|
||||||
// msg - 128字节数据
|
|
||||||
// return - 830/210位数据
|
|
||||||
func DecodeByteString(msg string) ([]byte, error) {
|
|
||||||
length := len(msg)
|
|
||||||
if length != 256 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 字节转换为字节数组
|
|
||||||
slog.Debug("待解码的1023应答器报文", "msg", msg)
|
|
||||||
bytes := ConvertByteStringToBytes(msg)
|
|
||||||
return Decode(bytes)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换字节(16进制)字符串为字节数组
|
|
||||||
func ConvertByteStringToBytes(msg string) []byte {
|
|
||||||
bytes, err := hex.DecodeString(msg)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return bytes
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将830位补末尾补1到832位,然后转换为左边为最高有效位(MSB)的字节数组
|
|
||||||
func toBytes(reverted830 []byte) []byte {
|
|
||||||
reverted830 = append(reverted830, 1, 1)
|
|
||||||
byte104 := make([]byte, 104)
|
|
||||||
for i := 0; i < 104; i++ {
|
|
||||||
byte104[i] = byte(ToValLeftMsb(reverted830[i*8 : i*8+8]))
|
|
||||||
}
|
|
||||||
return byte104
|
|
||||||
}
|
|
||||||
|
|
||||||
func buildError(msg string) error {
|
|
||||||
return fmt.Errorf("应答器1023解码错误:%s", msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 检查控制位
|
|
||||||
func checkCb(bits1023 []byte) error {
|
|
||||||
cb := getRange(bits1023, 109, 107)
|
|
||||||
for i, v := range cb {
|
|
||||||
n := 109 - i
|
|
||||||
//name := "b" + strconv.Itoa(109-i)
|
|
||||||
//slog.Info("cb", name, v)
|
|
||||||
if n == 109 && v == 1 {
|
|
||||||
return buildError("控制位cb错误,b109应该为0,实际为1")
|
|
||||||
} else if n == 108 && v == 1 {
|
|
||||||
return buildError("控制位cb错误,b108应该为0,实际为1")
|
|
||||||
} else if n == 107 && v == 0 {
|
|
||||||
return buildError("控制位cb错误,b107应该为1,实际为0")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func getRange(bits []byte, start, end int) []byte {
|
|
||||||
if start < 0 || end < 0 || start < end || start > 1022 {
|
|
||||||
panic("invalid range")
|
|
||||||
}
|
|
||||||
return bits[1022-start : 1022-(end-1)]
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换128字节数据为1023位数据
|
|
||||||
func convertTo1023Bits(byte128 []byte) []byte {
|
|
||||||
if len(byte128) != 128 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 字节转换为bit数组
|
|
||||||
bits := make([]byte, 1024)
|
|
||||||
for i, bt := range byte128 {
|
|
||||||
for j := 0; j < 8; j++ {
|
|
||||||
move := 7 - j
|
|
||||||
idx := i*8 + j
|
|
||||||
bits[idx] = (bt >> move) & 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
bits1023 := bits[0:1023]
|
|
||||||
return bits1023
|
|
||||||
}
|
|
||||||
|
|
||||||
// 由加扰位计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
|
||||||
func calculateS(sb []byte) uint32 {
|
|
||||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
|
||||||
if len(sb) != 12 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
B := ToValLeftMsb(sb)
|
|
||||||
const A uint64 = 2801775573
|
|
||||||
S := uint32((A * uint64(B)) % (1 << 32))
|
|
||||||
//slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S))
|
|
||||||
return S
|
|
||||||
}
|
|
||||||
|
|
||||||
// 以11位为一组比较两个913位的报文
|
|
||||||
func compare913(b913 []byte, compare []byte) {
|
|
||||||
if len(b913) != 913 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
for i := 0; i < 913; i += 11 {
|
|
||||||
for j := 0; j < 11; j++ {
|
|
||||||
print(b913[i+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
for j := 0; j < 11; j++ {
|
|
||||||
print(compare[i+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
println()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 比较830位数据
|
|
||||||
func compare830(b830 []byte, compare830 []byte) {
|
|
||||||
if len(b830) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
fmt.Printf("%01b", b830[i*10+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
fmt.Printf("%01b", compare830[i*10+j])
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
println()
|
|
||||||
}
|
|
||||||
for i := 0; i < 830; i++ {
|
|
||||||
if b830[i] != compare830[i] {
|
|
||||||
slog.Info("error", "index", i, "b830", b830[i], "compare", compare830[i])
|
|
||||||
panic("830 bit compare error")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
83
third_party/balisecodec/decode.go
vendored
83
third_party/balisecodec/decode.go
vendored
@ -1,83 +0,0 @@
|
|||||||
package balisecodec
|
|
||||||
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,除了第一个10位值,其余值求和,然后循环2的10次方次与其他值求和结果相加后模2的10次方,若结果和第一个10位值相同,则结束,此值即为原始的第一个10位值,将此值替换为第一个10位二进制数组,依然是左边为MSB
|
|
||||||
func revertFirst10Bits(b []byte) []byte {
|
|
||||||
if len(b) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
|
||||||
w10s := make([]uint16, 83)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
w10s[i] = uint16(ToValLeftMsb(b[i*10 : i*10+10]))
|
|
||||||
//// 打印输出
|
|
||||||
//for j := 0; j < 10; j++ {
|
|
||||||
// fmt.Printf("%01b", b[i*10+j])
|
|
||||||
//}
|
|
||||||
//print(" ")
|
|
||||||
//if i != 0 && i%10 == 9 {
|
|
||||||
// println()
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
//println()
|
|
||||||
// 将除了第一个10位字整数求和
|
|
||||||
sum := uint64(0)
|
|
||||||
for i := 1; i < 83; i++ {
|
|
||||||
sum += uint64(w10s[i])
|
|
||||||
}
|
|
||||||
// 循环2的10次方次与其他值求和结果相加后模2的10次方
|
|
||||||
for i := 0; i < 1024; i++ {
|
|
||||||
test := sum + uint64(i)
|
|
||||||
if test%1024 == uint64(w10s[0]) {
|
|
||||||
w10s[0] = uint16(i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//slog.Info("还原第一个10位值", "sum", sum, "bits[0]", w10s[0], "bits[0]b", fmt.Sprintf("%010b", w10s[0]))
|
|
||||||
bits := make([]byte, 830)
|
|
||||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
|
||||||
u0bits := ToBitsLeftMsb(int(w10s[0]), 10)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
bits[i] = u0bits[i]
|
|
||||||
}
|
|
||||||
for i := 10; i < 830; i++ {
|
|
||||||
bits[i] = b[i]
|
|
||||||
}
|
|
||||||
return bits
|
|
||||||
}
|
|
||||||
|
|
||||||
// 解扰,由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行解扰
|
|
||||||
func descrambling(dn []byte, S uint32) []byte {
|
|
||||||
if len(dn) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// const Polynomial = 0x000000AF
|
|
||||||
out := make([]byte, len(dn))
|
|
||||||
t := S // 寄存器初始值
|
|
||||||
for i := 0; i < len(dn); i++ {
|
|
||||||
msb := (t >> 31) & 1
|
|
||||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
|
||||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
|
||||||
xor := uint32(dn[i])
|
|
||||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
|
||||||
t = (t << 1) | xor
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// 转换913位数据为830位数据
|
|
||||||
func convert913To830(b913 []byte) ([]byte, error) {
|
|
||||||
if len(b913) != 913 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
b830 := make([]byte, 830)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
b10, err := From11(b913[i*11 : i*11+11])
|
|
||||||
if err != nil {
|
|
||||||
return nil, buildError(err.Error())
|
|
||||||
}
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
b830[i*10+j] = b10[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b830, nil
|
|
||||||
}
|
|
86
third_party/balisecodec/encode.go
vendored
86
third_party/balisecodec/encode.go
vendored
@ -1,86 +0,0 @@
|
|||||||
package balisecodec
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组,然后求和后模2的10次方,得到的结果覆盖第一个10位值,然后将整个10位数组转换为二进制数组,依然是左边为MSB
|
|
||||||
func replaceFirst10Bits(b []byte) []byte {
|
|
||||||
if len(b) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位(MSB)的无符号整数数组
|
|
||||||
bits := make([]uint16, 83)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
bits[i] = uint16(ToValLeftMsb(b[i*10 : i*10+10]))
|
|
||||||
// 打印输出
|
|
||||||
for j := 0; j < 10; j++ {
|
|
||||||
fmt.Printf("%01b", b[i*10+j])
|
|
||||||
}
|
|
||||||
print(" ")
|
|
||||||
if i != 0 && i%10 == 9 {
|
|
||||||
println()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
println()
|
|
||||||
// 将每一个10位字整数求和后模2的10次方,得到的结果覆盖第一个10位值
|
|
||||||
sum := uint64(0)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
sum += uint64(bits[i])
|
|
||||||
// fmt.Printf("i=%d, v10=%d, v10b=%010b\n", i, bits[i], bits[i])
|
|
||||||
}
|
|
||||||
bits[0] = uint16(sum % 1024)
|
|
||||||
slog.Info("替换第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
|
|
||||||
rbits := make([]byte, 830)
|
|
||||||
// 将整个10位数组转换为二进制数组,依然是MSB
|
|
||||||
u0bits := ToBitsLeftMsb(int(bits[0]), 10)
|
|
||||||
for i := 0; i < 10; i++ {
|
|
||||||
rbits[i] = u0bits[i]
|
|
||||||
}
|
|
||||||
for i := 10; i < 830; i++ {
|
|
||||||
rbits[i] = b[i]
|
|
||||||
}
|
|
||||||
// compare830(b, rbits)
|
|
||||||
return rbits
|
|
||||||
}
|
|
||||||
|
|
||||||
// 由加扰计算得到的S,作为初始状态为S的32位线性反馈移位寄存器对数据进行加扰
|
|
||||||
// 1. 生成一个32位的线性反馈移位寄存器,其初始状态为S(左边为MSB)
|
|
||||||
// 2. 系数h31,h30,h29,h27,h25和h0等于1(表示连接),所有其他系数都为0(表示不连接)
|
|
||||||
// 3. 然后电路被时钟驱动m-1次,其中m是数据位的数量,同时输入dn的每一位dn(m-1),dn(m-2),...,dn(0),便生成加扰后的码位(在第一个时钟之前读取第一个输出out(m-1))
|
|
||||||
// 4. 生成的加扰码位是dn的每一位与S的最高位的异或值
|
|
||||||
// 5. 生成的加扰码位会根据系数进行异或反馈回S的最低位
|
|
||||||
// 几种可能性:
|
|
||||||
func scrambling(dn []byte, S uint32) []byte {
|
|
||||||
if len(dn) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
// const Polynomial = 0x000000AF
|
|
||||||
out := make([]byte, len(dn))
|
|
||||||
t := S // 寄存器初始值
|
|
||||||
for i := 0; i < len(dn); i++ {
|
|
||||||
msb := (t >> 31) & 1
|
|
||||||
out[i] = (dn[i] ^ byte(msb)) & 1
|
|
||||||
// fmt.Printf("i=%d, t=%032b, msb=%d, dn=%d, out=%d\n", i, t, msb, dn[i], out[i])
|
|
||||||
xor := uint32(out[i])
|
|
||||||
t = (xor << 30) ^ (xor << 29) ^ (xor << 28) ^ (xor << 26) ^ (xor << 24) ^ t
|
|
||||||
t = (t << 1) | xor
|
|
||||||
}
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将830位的二进制数组先以10位为一组分别转换为11位并组合
|
|
||||||
func convert830To913(b830 []byte) []byte {
|
|
||||||
if len(b830) != 830 {
|
|
||||||
panic("invalid length")
|
|
||||||
}
|
|
||||||
b913 := make([]byte, 913)
|
|
||||||
for i := 0; i < 83; i++ {
|
|
||||||
b11 := To11(b830[i*10 : i*10+10])
|
|
||||||
for j := 0; j < 11; j++ {
|
|
||||||
b913[i*11+j] = b11[j]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return b913
|
|
||||||
}
|
|
76
third_party/can_btm/balise_btm.go
vendored
76
third_party/can_btm/balise_btm.go
vendored
@ -3,6 +3,7 @@ package can_btm
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/config"
|
"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/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/udp"
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
@ -10,6 +11,7 @@ import (
|
|||||||
"joylink.club/rtsssimulation/entity"
|
"joylink.club/rtsssimulation/entity"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"sort"
|
"sort"
|
||||||
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -44,7 +46,7 @@ type btmCanetClient struct {
|
|||||||
//最近一次车载ATP系统查询帧CRC16校验结果,true-校验通过
|
//最近一次车载ATP系统查询帧CRC16校验结果,true-校验通过
|
||||||
atpReqCrc16Check bool
|
atpReqCrc16Check bool
|
||||||
//btm系统时间,每次接收到ATP查询请求帧时同步一次时间
|
//btm系统时间,每次接收到ATP查询请求帧时同步一次时间
|
||||||
btmTime BtmClock
|
btmTime btmClock
|
||||||
//数据流水号
|
//数据流水号
|
||||||
dsn byte
|
dsn byte
|
||||||
//重发的数据
|
//重发的数据
|
||||||
@ -53,14 +55,31 @@ type btmCanetClient struct {
|
|||||||
baliseDetector *BaliseDetector
|
baliseDetector *BaliseDetector
|
||||||
}
|
}
|
||||||
|
|
||||||
type BtmClock struct {
|
func (s *btmCanetClient) GetState() state_proto.BTMState {
|
||||||
BtmTk uint32 //与ATP系统同步的时间ms
|
detector := s.baliseDetector
|
||||||
SysTk time.Time //本地系统时间
|
var telegram string
|
||||||
|
info := detector.eq[len(detector.eq)-1]
|
||||||
|
if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 {
|
||||||
|
telegram = fmt.Sprintf("%X", info.telegram)
|
||||||
|
} else {
|
||||||
|
telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
|
||||||
|
}
|
||||||
|
return state_proto.BTMState{
|
||||||
|
DataSerialNumber: uint32(s.dsn),
|
||||||
|
BaliseCount: uint32(detector.baliseCounter),
|
||||||
|
MessageCounter: uint32(detector.messageCounter),
|
||||||
|
Telegram: telegram,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type btmClock struct {
|
||||||
|
btmTk uint32 //与ATP系统同步的时间ms
|
||||||
|
sysTk time.Time //本地系统时间
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取以btmTk为基准的当前时间ms
|
// 获取以btmTk为基准的当前时间ms
|
||||||
func (c *BtmClock) TkNow() uint32 {
|
func (c *btmClock) tkNow() uint32 {
|
||||||
return c.BtmTk + uint32(time.Now().UnixMilli()-c.SysTk.UnixMilli())
|
return c.btmTk + uint32(time.Now().UnixMilli()-c.sysTk.UnixMilli())
|
||||||
}
|
}
|
||||||
|
|
||||||
type BtmCanetClient interface {
|
type BtmCanetClient interface {
|
||||||
@ -68,7 +87,8 @@ type BtmCanetClient interface {
|
|||||||
Stop()
|
Stop()
|
||||||
//HandleTrainHeadPositionInfo 处理收到列车位置信息
|
//HandleTrainHeadPositionInfo 处理收到列车位置信息
|
||||||
HandleTrainHeadPositionInfo(w ecs.World, h *TrainHeadPositionInfo)
|
HandleTrainHeadPositionInfo(w ecs.World, h *TrainHeadPositionInfo)
|
||||||
HandleTrainHeadPositionInfoForTrain(w ecs.World, train *state_proto.TrainState, h *TrainHeadPositionInfo)
|
//获取BTM显示状态
|
||||||
|
GetState() state_proto.BTMState
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -77,33 +97,13 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Default() BtmCanetClient {
|
func Default() BtmCanetClient {
|
||||||
defer btmClientLocker.Unlock()
|
|
||||||
btmClientLocker.Lock()
|
btmClientLocker.Lock()
|
||||||
|
defer btmClientLocker.Unlock()
|
||||||
if btmClient == nil {
|
if btmClient == nil {
|
||||||
btmClient = &btmCanetClient{baliseDetector: &BaliseDetector{}}
|
btmClient = &btmCanetClient{baliseDetector: &BaliseDetector{}}
|
||||||
}
|
}
|
||||||
return btmClient
|
return btmClient
|
||||||
}
|
}
|
||||||
func (s *btmCanetClient) HandleTrainHeadPositionInfoForTrain(w ecs.World, train *state_proto.TrainState, h *TrainHeadPositionInfo) {
|
|
||||||
wd := entity.GetWorldData(w)
|
|
||||||
repo := wd.Repo
|
|
||||||
h2 := &TrainHeadPositionInfo{
|
|
||||||
TrainId: h.TrainId,
|
|
||||||
Up: h.Up,
|
|
||||||
Link: h.OldLink,
|
|
||||||
LinkOffset: h.OldLinkOffset,
|
|
||||||
Speed: h.Speed,
|
|
||||||
Acceleration: h.Acceleration}
|
|
||||||
s.baliseDetector.newDetect(wd, repo, h, h2, train.BtmBaliseCacheA, h.IsLine12, false, "11")
|
|
||||||
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, h *TrainHeadPositionInfo) {
|
func (s *btmCanetClient) HandleTrainHeadPositionInfo(w ecs.World, h *TrainHeadPositionInfo) {
|
||||||
@ -143,9 +143,6 @@ func (s *btmCanetClient) Stop() {
|
|||||||
s.udpClient.Close()
|
s.udpClient.Close()
|
||||||
s.udpClient = nil
|
s.udpClient = nil
|
||||||
}
|
}
|
||||||
for d := range s.baliseDetector.eq {
|
|
||||||
s.baliseDetector.eq[d] = nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
func (s *btmCanetClient) handleCanetFrames(cfs []byte) {
|
func (s *btmCanetClient) handleCanetFrames(cfs []byte) {
|
||||||
defer func() {
|
defer func() {
|
||||||
@ -209,8 +206,8 @@ func (s *btmCanetClient) dealWithAptReq(f *message.CanetFrame) {
|
|||||||
//处理查询请求
|
//处理查询请求
|
||||||
//slog.Debug(fmt.Sprintf("处理查询请求:%s", atpReq.String()))
|
//slog.Debug(fmt.Sprintf("处理查询请求:%s", atpReq.String()))
|
||||||
//
|
//
|
||||||
s.btmTime.BtmTk = atpReq.Time
|
s.btmTime.btmTk = atpReq.Time
|
||||||
s.btmTime.SysTk = now
|
s.btmTime.sysTk = now
|
||||||
s.atpReqSn = atpReq.FId.ID4
|
s.atpReqSn = atpReq.FId.ID4
|
||||||
s.atpReqCrc16Check = atpReq.Crc16CheckOk
|
s.atpReqCrc16Check = atpReq.Crc16CheckOk
|
||||||
s.baliseDetector.powerAmplifierSwitch = atpReq.PowerAmplifierTurnOn
|
s.baliseDetector.powerAmplifierSwitch = atpReq.PowerAmplifierTurnOn
|
||||||
@ -266,7 +263,7 @@ func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
|
|||||||
statusF.BaliseCounter = byte(btmStatus.BaliseCounter)
|
statusF.BaliseCounter = byte(btmStatus.BaliseCounter)
|
||||||
statusF.MessageCounter = byte(btmStatus.MessageCounter)
|
statusF.MessageCounter = byte(btmStatus.MessageCounter)
|
||||||
statusF.PowerAmplifierOn = btmStatus.PowerAmplifierOn
|
statusF.PowerAmplifierOn = btmStatus.PowerAmplifierOn
|
||||||
statusF.TkTimeA = s.btmTime.TkNow()
|
statusF.TkTimeA = s.btmTime.tkNow()
|
||||||
statusF.PowerAmplifierFailure = btmStatus.PowerAmplifierFault
|
statusF.PowerAmplifierFailure = btmStatus.PowerAmplifierFault
|
||||||
statusF.DetailedCode = 0
|
statusF.DetailedCode = 0
|
||||||
if btmStatus.AboveBalise {
|
if btmStatus.AboveBalise {
|
||||||
@ -274,17 +271,16 @@ func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
|
|||||||
}
|
}
|
||||||
statusF.AtpReqCrcCheckWrong = !s.atpReqCrc16Check
|
statusF.AtpReqCrcCheckWrong = !s.atpReqCrc16Check
|
||||||
statusF.Dsn = s.dsn
|
statusF.Dsn = s.dsn
|
||||||
|
|
||||||
s.dsnAdd1()
|
s.dsnAdd1()
|
||||||
//
|
//
|
||||||
//true-收到应答器报文
|
//true-收到应答器报文
|
||||||
isRcvTelegram := sb != nil && len(sb.telegram) > 0
|
isRcvTelegram := sb != nil && len(sb.telegram) > 0
|
||||||
if isRcvTelegram { //当收到应答器报文时响应:时间同步帧、状态应答帧、数据帧
|
if isRcvTelegram { //当收到应答器报文时响应:时间同步帧、状态应答帧、数据帧
|
||||||
statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(statusF, sb.telegram, false, s.btmTime.TkNow(), s.btmTime.TkNow(), s.btmTime.TkNow())
|
statusDataCf, statusDataCfOk := message.CreateBtmRspFramesData(statusF, sb.telegram, false, s.btmTime.tkNow(), s.btmTime.tkNow(), s.btmTime.tkNow())
|
||||||
if statusDataCfOk {
|
if statusDataCfOk {
|
||||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
|
||||||
timeSyncF.T2 = s.btmTime.BtmTk
|
timeSyncF.T2 = s.btmTime.btmTk
|
||||||
timeSyncF.T3 = s.btmTime.TkNow()
|
timeSyncF.T3 = s.btmTime.tkNow()
|
||||||
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
||||||
//
|
//
|
||||||
s.resendData = newResendData(statusDataCf)
|
s.resendData = newResendData(statusDataCf)
|
||||||
@ -294,8 +290,8 @@ func (s *btmCanetClient) rspToAtp(sb *BtmAntennaScanningBaliseInfo) {
|
|||||||
}
|
}
|
||||||
} else { //当未收到应答器报文时响应:时间同步帧、状态应答帧
|
} else { //当未收到应答器报文时响应:时间同步帧、状态应答帧
|
||||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(s.atpReqSn)
|
||||||
timeSyncF.T2 = s.btmTime.BtmTk
|
timeSyncF.T2 = s.btmTime.btmTk
|
||||||
timeSyncF.T3 = s.btmTime.TkNow()
|
timeSyncF.T3 = s.btmTime.tkNow()
|
||||||
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
s.sendCanetFrame(timeSyncF.Encode().Encode())
|
||||||
//
|
//
|
||||||
statusCf := statusF.Encode().Encode()
|
statusCf := statusF.Encode().Encode()
|
||||||
|
250
third_party/can_btm/balise_detection.go
vendored
250
third_party/can_btm/balise_detection.go
vendored
@ -2,7 +2,6 @@ package can_btm
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"joylink.club/rtsssimulation/component"
|
"joylink.club/rtsssimulation/component"
|
||||||
"joylink.club/rtsssimulation/fi"
|
"joylink.club/rtsssimulation/fi"
|
||||||
"joylink.club/rtsssimulation/repository"
|
"joylink.club/rtsssimulation/repository"
|
||||||
@ -28,26 +27,20 @@ type BtmAntennaRunningInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
//BtmAntennaOffsetHead = int64(1000) //车载BTM天线距车头端点的距离,mm
|
BtmAntennaOffsetHead = int64(1000) //车载BTM天线距车头端点的距离,mm
|
||||||
BtmAntennaOffsetHead = int64(0) //车载BTM天线距车头端点的距离,mm
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// TrainHeadPositionInfo 列车车头运行位置信息
|
// TrainHeadPositionInfo 列车车头运行位置信息
|
||||||
type TrainHeadPositionInfo = fi.TrainHeadPositionInfo
|
type TrainHeadPositionInfo = fi.TrainHeadPositionInfo
|
||||||
type BtmAntennaToBaliseInfo struct {
|
type BtmAntennaToBaliseInfo struct {
|
||||||
Distance int64 //BTM天线中心到应答器的距离,mm
|
Distance int64 //BTM天线中心到应答器的距离,mm
|
||||||
BaliseId string //应答器id
|
BaliseId string //应答器id
|
||||||
BaliseType proto.Transponder_Type //应答器类型
|
|
||||||
}
|
}
|
||||||
type BtmAntennaScanningBaliseInfo struct {
|
type BtmAntennaScanningBaliseInfo struct {
|
||||||
BaliseId string //应答器id
|
BaliseId string //应答器id
|
||||||
Time time.Time //应答器预计被BTM天线激活的时刻
|
Time time.Time //应答器预计被BTM天线激活的时刻
|
||||||
active bool //true-激活过,即列车扫过
|
active bool //true-激活过,即列车扫过
|
||||||
telegram []byte //应答器用户报文
|
telegram []byte //应答器报文
|
||||||
telegram128 []byte //应答器报文
|
|
||||||
Distance int64 //BTM天线中心到应答器的距离,mm
|
|
||||||
BaliseType proto.Transponder_Type //应答器类型
|
|
||||||
IsSend bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaliseDetector 车载BTM天线,应答器探测器
|
// BaliseDetector 车载BTM天线,应答器探测器
|
||||||
@ -74,47 +67,9 @@ func (t *BaliseDetector) tryRebind(th *TrainHeadPositionInfo) {
|
|||||||
t.clearExpectedBalise()
|
t.clearExpectedBalise()
|
||||||
t.baliseCounter = 0
|
t.baliseCounter = 0
|
||||||
t.messageCounter = 0
|
t.messageCounter = 0
|
||||||
//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, isLine12, show bool, id string) {
|
|
||||||
//BTM天线中心点运行信息
|
|
||||||
curAntennaRi := t.createBtmAntennaRunningInfo(wd, repo, th) //目前车头
|
|
||||||
curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, th2) //上次车头
|
|
||||||
var startBalises []*repository.Transponder
|
|
||||||
if th.Link != th2.Link {
|
|
||||||
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi.LinkOffset)
|
|
||||||
} else {
|
|
||||||
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
|
|
||||||
}
|
|
||||||
balises := make([]*repository.Transponder, 0)
|
|
||||||
for _, balise := range startBalises {
|
|
||||||
find := false
|
|
||||||
for _, transponder := range balises {
|
|
||||||
if transponder.Id() == balise.Id() {
|
|
||||||
find = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !find {
|
|
||||||
balises = append(balises, balise)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(balises) > 0 {
|
|
||||||
balise := balises[0]
|
|
||||||
telegram, utel := t.rcvTelegram(wd, balise.Id())
|
|
||||||
/*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))
|
|
||||||
}*/
|
|
||||||
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) {
|
func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Repository, th *TrainHeadPositionInfo) {
|
||||||
t.tryRebind(th)
|
t.tryRebind(th)
|
||||||
@ -126,17 +81,14 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
|
|||||||
curAntennaRi := t.createBtmAntennaRunningInfo(wd, repo, th)
|
curAntennaRi := t.createBtmAntennaRunningInfo(wd, repo, th)
|
||||||
//预测BTM天线到最近一个应答器的时刻
|
//预测BTM天线到最近一个应答器的时刻
|
||||||
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
|
||||||
|
//slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt)
|
||||||
telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId)
|
|
||||||
|
|
||||||
//记录即将经过的应答器
|
//记录即将经过的应答器
|
||||||
if t.addExpectedBalise(curExpect) {
|
if t.addExpectedBalise(curExpect) {
|
||||||
t.baliseCounterAdd1() //应答器计数器
|
t.baliseCounterAdd1() //应答器计数器
|
||||||
|
telegram := t.rcvTelegram(wd, curExpect.BaliseId)
|
||||||
if len(telegram) > 0 {
|
if len(telegram) > 0 {
|
||||||
curExpect.telegram = utel
|
curExpect.telegram = telegram
|
||||||
curExpect.telegram128 = telegram
|
|
||||||
t.baliseMessageCounterAdd1() //报文计数器
|
t.baliseMessageCounterAdd1() //报文计数器
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -145,7 +97,6 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
|
|||||||
} else {
|
} else {
|
||||||
t.aboveBalise = false
|
t.aboveBalise = false
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 应答器计数器加1,[0,255]
|
// 应答器计数器加1,[0,255]
|
||||||
@ -164,43 +115,15 @@ func (t *BaliseDetector) baliseMessageCounterAdd1() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func BaliseCounterAdd(counter uint32, isLine12 bool) byte {
|
|
||||||
c := byte(counter)
|
|
||||||
c++
|
|
||||||
if c > 255 {
|
|
||||||
c = 1
|
|
||||||
if isLine12 {
|
|
||||||
c = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
// BTM天线接收应答器报文(线程不安全)
|
// BTM天线接收应答器报文(线程不安全)
|
||||||
func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) ([]byte, []byte) {
|
func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) []byte {
|
||||||
|
entry, ok := wd.EntityMap[baliseId]
|
||||||
if entry, ok := wd.EntityMap[baliseId]; ok {
|
if ok {
|
||||||
workedState := component.BaliseWorkStateType.Get(entry)
|
if component.BaliseWorkStateType.Get(entry).Work {
|
||||||
fixBalise := component.BaliseFixedTelegramType.Get(entry)
|
return component.BaliseFixedTelegramType.Get(entry).Telegram
|
||||||
if entry.HasComponent(component.BaliseVariableTelegramType) {
|
|
||||||
baliseVar := component.BaliseVariableTelegramType.Get(entry)
|
|
||||||
if !workedState.Work {
|
|
||||||
return fixBalise.Telegram, fixBalise.UserTelegram
|
|
||||||
} else if baliseVar.UserTelegram == nil || len(baliseVar.UserTelegram) == 0 {
|
|
||||||
//slog.Warn(fmt.Sprintf("BTM天线未接受到应答器可变报文,即将使用对应的固定报文, baliseId: %v", baliseId))
|
|
||||||
return fixBalise.Telegram, fixBalise.UserTelegram
|
|
||||||
} else {
|
|
||||||
return baliseVar.Telegram, baliseVar.UserTelegram
|
|
||||||
}
|
|
||||||
} else if workedState.Work {
|
|
||||||
return fixBalise.Telegram, fixBalise.UserTelegram
|
|
||||||
} else {
|
|
||||||
//slog.Warn(fmt.Sprintf("BTM天线未接受到应答器报文,应答器未工作 baliseId: %v", baliseId))
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
//slog.Warn(fmt.Sprintf("BTM天线接收应答器报文,未找到 baliseId: %v", baliseId))
|
|
||||||
}
|
}
|
||||||
return nil, nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// true-新增;false-更新
|
// true-新增;false-更新
|
||||||
@ -216,17 +139,10 @@ func (t *BaliseDetector) addExpectedBalise(curExpect *BtmAntennaScanningBaliseIn
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//检查是否已经记录过
|
//检查是否已经记录过
|
||||||
|
eq := t.eq[len(t.eq)-1]
|
||||||
for _, tt := range t.eq {
|
if eq != nil && eq.BaliseId == curExpect.BaliseId {
|
||||||
if tt != nil && tt.BaliseId == curExpect.BaliseId {
|
return false
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* eq := t.eq[len(t.eq)-1]
|
|
||||||
if eq != nil && eq.BaliseId == curExpect.BaliseId {
|
|
||||||
return false
|
|
||||||
}*/
|
|
||||||
//左移
|
//左移
|
||||||
for i := 1; i < len(t.eq); i++ {
|
for i := 1; i < len(t.eq); i++ {
|
||||||
t.eq[i-1] = t.eq[i]
|
t.eq[i-1] = t.eq[i]
|
||||||
@ -268,10 +184,8 @@ func (t *BaliseDetector) timeScanNearestBalise(curTime time.Time, wd *component.
|
|||||||
curAc := float64(ba.Acceleration)
|
curAc := float64(ba.Acceleration)
|
||||||
s := float64(expectedBalise.Distance) / 1000
|
s := float64(expectedBalise.Distance) / 1000
|
||||||
st, ok := t.calculateBtmAntennaScanNextBaliseTime(curTime, curV, curAc, s)
|
st, ok := t.calculateBtmAntennaScanNextBaliseTime(curTime, curV, curAc, s)
|
||||||
|
|
||||||
if ok {
|
if ok {
|
||||||
|
return &BtmAntennaScanningBaliseInfo{BaliseId: expectedBalise.BaliseId, Time: st}
|
||||||
return &BtmAntennaScanningBaliseInfo{BaliseId: expectedBalise.BaliseId, Time: st, Distance: expectedBalise.Distance, BaliseType: expectedBalise.BaliseType}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@ -293,57 +207,6 @@ func (t *BaliseDetector) calculateBtmAntennaScanNextBaliseTime(curTime time.Time
|
|||||||
return curTime, false
|
return curTime, false
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取车载BTM天线中心点运行方向最近的1个应答器
|
|
||||||
func (t *BaliseDetector) findBaliseWillScanByBtmAntenna2(wd *component.WorldData, repo *repository.Repository, ba *BtmAntennaRunningInfo) *BtmAntennaToBaliseInfo {
|
|
||||||
//BTM天线中心点所在轨道
|
|
||||||
baLink := repo.FindLink(ba.LinkId)
|
|
||||||
rs1 := t.searchBalisesFromLinkPosition(repo, ba.LinkId, ba.Up, ba.LinkOffset)
|
|
||||||
if ba.Up {
|
|
||||||
if len(rs1) > 0 {
|
|
||||||
rs := rs1[0]
|
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs.Id(), Distance: rs.LinkPosition().Offset() - ba.LinkOffset, BaliseType: rs.BaliseType()}
|
|
||||||
} else {
|
|
||||||
nextLinkPort := t.getNextLink(wd, repo, ba.LinkId, ba.Up)
|
|
||||||
if nextLinkPort != nil {
|
|
||||||
if nextLinkPort.IsPortA() {
|
|
||||||
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), true, 0)
|
|
||||||
if len(rs2) > 0 {
|
|
||||||
rs := rs2[0]
|
|
||||||
|
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs.Id(), Distance: baLink.Length() - ba.LinkOffset + rs.LinkPosition().Offset(), BaliseType: rs.BaliseType()}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), false, nextLinkPort.Link().Length())
|
|
||||||
if len(rs2) > 0 {
|
|
||||||
rs := rs2[0]
|
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs.Id(), Distance: baLink.Length() - ba.LinkOffset + nextLinkPort.Link().Length() - rs.LinkPosition().Offset(), BaliseType: rs.BaliseType()}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if len(rs1) > 0 {
|
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs1[0].Id(), Distance: ba.LinkOffset - rs1[0].LinkPosition().Offset()}
|
|
||||||
} else {
|
|
||||||
nextLinkPort := t.getNextLink(wd, repo, ba.LinkId, ba.Up)
|
|
||||||
if nextLinkPort != nil {
|
|
||||||
if nextLinkPort.IsPortA() {
|
|
||||||
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), true, 0)
|
|
||||||
if len(rs2) > 0 {
|
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs2[0].Id(), Distance: ba.LinkOffset + rs2[0].LinkPosition().Offset()}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), false, nextLinkPort.Link().Length())
|
|
||||||
if len(rs2) > 0 {
|
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs2[0].Id(), Distance: ba.LinkOffset + nextLinkPort.Link().Length() - rs2[0].LinkPosition().Offset()}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// 获取车载BTM天线中心点运行方向最近的1个应答器
|
// 获取车载BTM天线中心点运行方向最近的1个应答器
|
||||||
func (t *BaliseDetector) findBaliseWillScanByBtmAntenna(wd *component.WorldData, repo *repository.Repository, ba *BtmAntennaRunningInfo) *BtmAntennaToBaliseInfo {
|
func (t *BaliseDetector) findBaliseWillScanByBtmAntenna(wd *component.WorldData, repo *repository.Repository, ba *BtmAntennaRunningInfo) *BtmAntennaToBaliseInfo {
|
||||||
//BTM天线中心点所在轨道
|
//BTM天线中心点所在轨道
|
||||||
@ -351,23 +214,19 @@ func (t *BaliseDetector) findBaliseWillScanByBtmAntenna(wd *component.WorldData,
|
|||||||
rs1 := t.searchBalisesFromLinkPosition(repo, ba.LinkId, ba.Up, ba.LinkOffset)
|
rs1 := t.searchBalisesFromLinkPosition(repo, ba.LinkId, ba.Up, ba.LinkOffset)
|
||||||
if ba.Up {
|
if ba.Up {
|
||||||
if len(rs1) > 0 {
|
if len(rs1) > 0 {
|
||||||
rs := rs1[0]
|
return &BtmAntennaToBaliseInfo{BaliseId: rs1[0].Id(), Distance: rs1[0].LinkPosition().Offset() - ba.LinkOffset}
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs.Id(), Distance: rs.LinkPosition().Offset() - ba.LinkOffset, BaliseType: rs.BaliseType()}
|
|
||||||
} else {
|
} else {
|
||||||
nextLinkPort := t.getNextLink(wd, repo, ba.LinkId, ba.Up)
|
nextLinkPort := t.getNextLink(wd, repo, ba.LinkId, ba.Up)
|
||||||
if nextLinkPort != nil {
|
if nextLinkPort != nil {
|
||||||
if nextLinkPort.IsPortA() {
|
if nextLinkPort.IsPortA() {
|
||||||
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), true, 0)
|
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), true, 0)
|
||||||
if len(rs2) > 0 {
|
if len(rs2) > 0 {
|
||||||
rs := rs2[0]
|
return &BtmAntennaToBaliseInfo{BaliseId: rs2[0].Id(), Distance: baLink.Length() - ba.LinkOffset + rs2[0].LinkPosition().Offset()}
|
||||||
|
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs.Id(), Distance: baLink.Length() - ba.LinkOffset + rs.LinkPosition().Offset(), BaliseType: rs.BaliseType()}
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), false, nextLinkPort.Link().Length())
|
rs2 := t.searchBalisesFromLinkPosition(repo, nextLinkPort.Link().Id(), false, nextLinkPort.Link().Length())
|
||||||
if len(rs2) > 0 {
|
if len(rs2) > 0 {
|
||||||
rs := rs2[0]
|
return &BtmAntennaToBaliseInfo{BaliseId: rs2[0].Id(), Distance: baLink.Length() - ba.LinkOffset + nextLinkPort.Link().Length() - rs2[0].LinkPosition().Offset()}
|
||||||
return &BtmAntennaToBaliseInfo{BaliseId: rs.Id(), Distance: baLink.Length() - ba.LinkOffset + nextLinkPort.Link().Length() - rs.LinkPosition().Offset(), BaliseType: rs.BaliseType()}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -395,39 +254,6 @@ func (t *BaliseDetector) findBaliseWillScanByBtmAntenna(wd *component.WorldData,
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *BaliseDetector) searchBalisesFromBetweenLinkPosition(repo *repository.Repository, up bool, linkId string, fromOffset int64, toOffset int64) []*repository.Transponder {
|
|
||||||
rs := repo.ResponderListByLink(linkId)
|
|
||||||
balises := make([]*repository.Transponder, 0)
|
|
||||||
if up {
|
|
||||||
sort.SliceStable(rs, func(i, j int) bool {
|
|
||||||
return rs[i].LinkPosition().Offset() < rs[j].LinkPosition().Offset()
|
|
||||||
})
|
|
||||||
for _, r := range rs {
|
|
||||||
|
|
||||||
if r.LinkPosition().Offset() >= fromOffset && r.LinkPosition().Offset() <= toOffset {
|
|
||||||
//slog.Info(fmt.Sprintf("up id:%v,offset:%v,from:%v,to:%v", r.Id(), r.LinkPosition().Offset(), fromOffset, toOffset))
|
|
||||||
balises = append(balises, r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
sort.SliceStable(rs, func(i, j int) bool {
|
|
||||||
return rs[j].LinkPosition().Offset() < rs[i].LinkPosition().Offset()
|
|
||||||
})
|
|
||||||
for _, r := range rs {
|
|
||||||
//slog.Info(fmt.Sprintf("down id:%v,offset:%v,from:%v,to:%v", r.Id(), r.LinkPosition().Offset(), fromOffset, toOffset))
|
|
||||||
if r.LinkPosition().Offset() <= toOffset {
|
|
||||||
cha := int64(math.Abs(float64(toOffset - fromOffset)))
|
|
||||||
cha2 := int64(math.Abs(float64(toOffset - r.LinkPosition().Offset())))
|
|
||||||
if cha2 <= cha {
|
|
||||||
balises = append(balises, r)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return balises
|
|
||||||
}
|
|
||||||
|
|
||||||
// up-在轨道上的搜索方向
|
// up-在轨道上的搜索方向
|
||||||
func (t *BaliseDetector) searchBalisesFromLinkPosition(repo *repository.Repository, linkId string, up bool, fromOffset int64) []*repository.Transponder {
|
func (t *BaliseDetector) searchBalisesFromLinkPosition(repo *repository.Repository, linkId string, up bool, fromOffset int64) []*repository.Transponder {
|
||||||
rs := repo.ResponderListByLink(linkId)
|
rs := repo.ResponderListByLink(linkId)
|
||||||
@ -455,34 +281,6 @@ func (t *BaliseDetector) searchBalisesFromLinkPosition(repo *repository.Reposito
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 列车车头端点运行信息转换为车载BTM天线中心点运行信息
|
// 列车车头端点运行信息转换为车载BTM天线中心点运行信息
|
||||||
func (t *BaliseDetector) createBtmAntennaRunningInfo2(wd *component.WorldData, isSameLink bool, repo *repository.Repository, head *TrainHeadPositionInfo) *BtmAntennaRunningInfo {
|
|
||||||
headLink := repo.FindLink(head.Link)
|
|
||||||
if head.Up {
|
|
||||||
if isSameLink { //车头与BTM天线在同一个轨道上
|
|
||||||
return &BtmAntennaRunningInfo{Up: head.Up, LinkId: head.Link, LinkOffset: head.LinkOffset + int64(math.Abs(float64(BtmAntennaOffsetHead))), Speed: head.Speed, Acceleration: head.Acceleration}
|
|
||||||
} else { //车头与BTM天线在同一个轨道上
|
|
||||||
nextLinkPort := t.getNextLink(wd, repo, head.Link, !head.Up)
|
|
||||||
nextLink := nextLinkPort.Link()
|
|
||||||
if nextLinkPort.IsPortA() {
|
|
||||||
return &BtmAntennaRunningInfo{Up: false, LinkId: nextLink.Id(), LinkOffset: BtmAntennaOffsetHead - head.LinkOffset, Speed: head.Speed, Acceleration: head.Acceleration}
|
|
||||||
} else {
|
|
||||||
return &BtmAntennaRunningInfo{Up: true, LinkId: nextLink.Id(), LinkOffset: nextLink.Length() - (BtmAntennaOffsetHead - head.LinkOffset), Speed: head.Speed, Acceleration: head.Acceleration}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if isSameLink { //车头与BTM天线在同一个轨道上
|
|
||||||
return &BtmAntennaRunningInfo{Up: head.Up, LinkId: head.Link, LinkOffset: head.LinkOffset + BtmAntennaOffsetHead, Speed: head.Speed, Acceleration: head.Acceleration}
|
|
||||||
} else {
|
|
||||||
nextLinkPort := t.getNextLink(wd, repo, head.Link, !head.Up)
|
|
||||||
nextLink := nextLinkPort.Link()
|
|
||||||
if nextLinkPort.IsPortA() {
|
|
||||||
return &BtmAntennaRunningInfo{Up: false, LinkId: nextLink.Id(), LinkOffset: BtmAntennaOffsetHead - headLink.Length() + head.LinkOffset, Speed: head.Speed, Acceleration: head.Acceleration}
|
|
||||||
} else {
|
|
||||||
return &BtmAntennaRunningInfo{Up: true, LinkId: nextLink.Id(), LinkOffset: nextLink.Length() - (BtmAntennaOffsetHead - headLink.Length() + head.LinkOffset), Speed: head.Speed, Acceleration: head.Acceleration}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (t *BaliseDetector) createBtmAntennaRunningInfo(wd *component.WorldData, repo *repository.Repository, head *TrainHeadPositionInfo) *BtmAntennaRunningInfo {
|
func (t *BaliseDetector) createBtmAntennaRunningInfo(wd *component.WorldData, repo *repository.Repository, head *TrainHeadPositionInfo) *BtmAntennaRunningInfo {
|
||||||
headLink := repo.FindLink(head.Link)
|
headLink := repo.FindLink(head.Link)
|
||||||
if head.Up {
|
if head.Up {
|
||||||
|
121
third_party/can_btm/train_balise_cache.go
vendored
121
third_party/can_btm/train_balise_cache.go
vendored
@ -1,121 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
}
|
|
65
third_party/dynamics/dynamics.go
vendored
65
third_party/dynamics/dynamics.go
vendored
@ -5,7 +5,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"net/http"
|
"net/http"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
@ -21,8 +20,6 @@ import (
|
|||||||
|
|
||||||
type DynamicsMessageManager interface {
|
type DynamicsMessageManager interface {
|
||||||
CollectDynamicsTurnoutInfo() *message.DynamicsTurnoutInfo
|
CollectDynamicsTurnoutInfo() *message.DynamicsTurnoutInfo
|
||||||
|
|
||||||
CollectTrainControlState() []message.TrainControlMsg
|
|
||||||
HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo)
|
HandleDynamicsTrainInfo(info *message.DynamicsTrainInfo)
|
||||||
GetDynamicsRunConfig() *config.DynamicsConfig
|
GetDynamicsRunConfig() *config.DynamicsConfig
|
||||||
GetDynamicsRunRepository() *message.LineBaseInfo
|
GetDynamicsRunRepository() *message.LineBaseInfo
|
||||||
@ -44,8 +41,6 @@ type Dynamics interface {
|
|||||||
|
|
||||||
// 发送列车控制消息
|
// 发送列车控制消息
|
||||||
SendTrainControlMessage(b []byte)
|
SendTrainControlMessage(b []byte)
|
||||||
|
|
||||||
SendTrainControl(cm *message.TrainControlMsg)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _default *dynamics
|
var _default *dynamics
|
||||||
@ -94,16 +89,8 @@ func (d *dynamics) updateState(state tpapi.ThirdPartyApiServiceState) {
|
|||||||
func (d *dynamics) State() tpapi.ThirdPartyApiServiceState {
|
func (d *dynamics) State() tpapi.ThirdPartyApiServiceState {
|
||||||
return d.state
|
return d.state
|
||||||
}
|
}
|
||||||
func (d *dynamics) FindAppendApiService() []tpapi.ThirdPartyApiService {
|
|
||||||
return nil
|
func (d *dynamics) Name() string {
|
||||||
}
|
|
||||||
func (d *dynamics) Type() state_proto.SimulationThirdPartyApiService_Type {
|
|
||||||
return state_proto.SimulationThirdPartyApiService_Dynamics
|
|
||||||
}
|
|
||||||
func (d *dynamics) TrueService() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
func (d *dynamics) ServiceDesc() string {
|
|
||||||
return Name
|
return Name
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -142,7 +129,6 @@ func (d *dynamics) requestStartSimulation(base *message.LineBaseInfo) error {
|
|||||||
}
|
}
|
||||||
url := d.buildUrl("/api/start/")
|
url := d.buildUrl("/api/start/")
|
||||||
data, _ := json.Marshal(base)
|
data, _ := json.Marshal(base)
|
||||||
slog.Info(string(data))
|
|
||||||
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
|
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return sys_error.New("动力学开始仿真请求发送错误", err)
|
return sys_error.New("动力学开始仿真请求发送错误", err)
|
||||||
@ -181,7 +167,6 @@ func (d *dynamics) RequestAddTrain(info *message.InitTrainInfo) error {
|
|||||||
}
|
}
|
||||||
url := d.buildUrl("/api/aerodynamics/init/train/")
|
url := d.buildUrl("/api/aerodynamics/init/train/")
|
||||||
data, _ := json.Marshal(info)
|
data, _ := json.Marshal(info)
|
||||||
//fmt.Println(string(data))
|
|
||||||
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
|
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("动力学添加列车请求异常: %v", err)
|
return fmt.Errorf("动力学添加列车请求异常: %v", err)
|
||||||
@ -220,7 +205,6 @@ func (d *dynamics) TrainOperationConfig(req *message.TrainOperationConfig) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
data, _ := json.Marshal(req)
|
data, _ := json.Marshal(req)
|
||||||
//fmt.Println(string(data))
|
|
||||||
url := d.buildUrl("/api/config/")
|
url := d.buildUrl("/api/config/")
|
||||||
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
|
resp, err := d.httpClient.Post(url, "application/json", bytes.NewBuffer(data))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -260,24 +244,11 @@ func (d *dynamics) Start(manager DynamicsMessageManager) error {
|
|||||||
}
|
}
|
||||||
ctx, cancle := context.WithCancel(context.Background())
|
ctx, cancle := context.WithCancel(context.Background())
|
||||||
go d.sendTurnoutStateTask(ctx)
|
go d.sendTurnoutStateTask(ctx)
|
||||||
go d.sendTrainControlStateTask(ctx)
|
|
||||||
d.turnoutTaskCancel = cancle
|
d.turnoutTaskCancel = cancle
|
||||||
d.updateState(tpapi.ThirdPartyState_Normal)
|
d.updateState(tpapi.ThirdPartyState_Normal)
|
||||||
d.udpDelayRecorder.Start()
|
d.udpDelayRecorder.Start()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (d *dynamics) trainControl(ctx context.Context) {
|
|
||||||
for {
|
|
||||||
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
|
|
||||||
time.Sleep(time.Second * 5)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 初始化客户端、服务等信息
|
// 初始化客户端、服务等信息
|
||||||
func (d *dynamics) initDynamics() error {
|
func (d *dynamics) initDynamics() error {
|
||||||
@ -330,32 +301,10 @@ func (d *dynamics) Stop() {
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
// 道岔消息发送间隔,单位ms
|
// 道岔消息发送间隔,单位ms
|
||||||
TurnoutMessageSendInterval = 50
|
TurnoutMessageSendInterval = 50
|
||||||
TrainControlMessageSendInterval = 15
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var turnoutStateLifeSignal uint16 //道岔消息生命信号
|
var turnoutStateLifeSignal uint16 //道岔消息生命信号
|
||||||
// 定时发送列车控制状态
|
|
||||||
func (d *dynamics) sendTrainControlStateTask(ctx context.Context) {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
slog.Error("定时发送列车控制状态任务异常", "error", err, "stack", string(debug.Stack()))
|
|
||||||
debug.PrintStack()
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
tccs := d.manager.CollectTrainControlState()
|
|
||||||
for _, tcc := range tccs {
|
|
||||||
d.SendTrainControl(&tcc)
|
|
||||||
}
|
|
||||||
time.Sleep(time.Millisecond * TrainControlMessageSendInterval)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定时发送道岔状态任务
|
// 定时发送道岔状态任务
|
||||||
func (d *dynamics) sendTurnoutStateTask(ctx context.Context) {
|
func (d *dynamics) sendTurnoutStateTask(ctx context.Context) {
|
||||||
@ -380,11 +329,5 @@ func (d *dynamics) sendTurnoutStateTask(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (d *dynamics) SendTrainControlMessage(b []byte) {
|
func (d *dynamics) SendTrainControlMessage(b []byte) {
|
||||||
if d.trainControlUdpClient != nil {
|
d.trainControlUdpClient.Send(b)
|
||||||
d.trainControlUdpClient.Send(b)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
func (d *dynamics) SendTrainControl(cm *message.TrainControlMsg) {
|
|
||||||
d.SendTrainControlMessage(cm.Encode())
|
|
||||||
}
|
}
|
||||||
|
@ -1,11 +1,7 @@
|
|||||||
package electrical_machinery
|
package electrical_machinery
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/dto/common_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"log/slog"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"joylink.club/bj-rtsts-server/config"
|
"joylink.club/bj-rtsts-server/config"
|
||||||
@ -13,30 +9,22 @@ import (
|
|||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
|
||||||
PointA = iota + 1
|
|
||||||
PointB
|
|
||||||
)
|
|
||||||
|
|
||||||
// 电机转速UDP
|
// 电机转速UDP
|
||||||
type ElectricMachinery interface {
|
type ElectricMachinery interface {
|
||||||
Start(manager ElectricMachineryMessageManager) // 启动电机转速UDP消息处理
|
Start(manager ElectricMachineryMessageManager) // 启动电机转速UDP消息处理
|
||||||
Stop() // 停止电机转速消息处理
|
Stop() // 停止电机转速消息处理
|
||||||
SendElectricMachineryMessage(emMap map[int]*message.ElectricMachinery) // 发送电机转速消息
|
SendElectricMachineryMessage(info *message.ElectricMachinery) // 发送电机转速消息
|
||||||
SendElectricMachineryMessage2(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) // 发送电机转速消息
|
|
||||||
ClearOrRemoveTrain(trainState *state_proto.TrainState)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ElectricMachineryMessageManager interface {
|
type ElectricMachineryMessageManager interface {
|
||||||
GetElectricMachineryRunConfig() []config.ElectricMachineryConfig // 获取电机转速参数
|
GetElectricMachineryRunConfig() *config.ElectricMachineryConfig // 获取电机转速参数
|
||||||
}
|
}
|
||||||
|
|
||||||
type electricalMachineryImpl struct {
|
type electricalMachineryImpl struct {
|
||||||
//electricalMachineryUdpClient udp.UdpClient
|
electricalMachineryUdpClient udp.UdpClient
|
||||||
|
|
||||||
electricalMachineryUdpClientMap map[int]udp.UdpClient
|
manager ElectricMachineryMessageManager
|
||||||
manager ElectricMachineryMessageManager
|
runConfig *config.ElectricMachineryConfig
|
||||||
runConfig []config.ElectricMachineryConfig
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *electricalMachineryImpl) Start(manager ElectricMachineryMessageManager) {
|
func (s *electricalMachineryImpl) Start(manager ElectricMachineryMessageManager) {
|
||||||
@ -47,13 +35,7 @@ func (s *electricalMachineryImpl) Start(manager ElectricMachineryMessageManager)
|
|||||||
panic("启动电机转速消息服务错误: 存在正在运行的任务")
|
panic("启动电机转速消息服务错误: 存在正在运行的任务")
|
||||||
}
|
}
|
||||||
s.runConfig = manager.GetElectricMachineryRunConfig()
|
s.runConfig = manager.GetElectricMachineryRunConfig()
|
||||||
allNotOpen := true
|
if s.runConfig == nil || s.runConfig.Ip == "" || !s.runConfig.Open {
|
||||||
for _, c := range s.runConfig {
|
|
||||||
if &c != nil && c.Open {
|
|
||||||
allNotOpen = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if allNotOpen {
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// 初始化客户端、服务端
|
// 初始化客户端、服务端
|
||||||
@ -65,95 +47,21 @@ func (s *electricalMachineryImpl) Stop() {
|
|||||||
initMutex.Lock()
|
initMutex.Lock()
|
||||||
defer initMutex.Unlock()
|
defer initMutex.Unlock()
|
||||||
_default = nil
|
_default = nil
|
||||||
//if s.electricalMachineryUdpClient != nil {
|
if s.electricalMachineryUdpClient != nil {
|
||||||
// s.electricalMachineryUdpClient.Close()
|
s.electricalMachineryUdpClient.Close()
|
||||||
//}
|
|
||||||
for _, c := range s.electricalMachineryUdpClientMap {
|
|
||||||
if &c != nil {
|
|
||||||
c.Close()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
s.manager = nil
|
s.manager = nil
|
||||||
}
|
}
|
||||||
func (s *electricalMachineryImpl) ClearOrRemoveTrain(trainState *state_proto.TrainState) {
|
|
||||||
collectSpeedMap := initEMMsg(trainState)
|
|
||||||
if trainState.VobcState.Tc1Active {
|
|
||||||
collectSpeed(0, 0, trainState.TrainEndsA, collectSpeedMap)
|
|
||||||
|
|
||||||
} else if trainState.VobcState.Tc2Active {
|
func (s *electricalMachineryImpl) SendElectricMachineryMessage(info *message.ElectricMachinery) {
|
||||||
collectSpeed(0, 0, trainState.TrainEndsB, collectSpeedMap)
|
if s.electricalMachineryUdpClient == nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
// 更新电机转速
|
s.electricalMachineryUdpClient.Send(info.Encode())
|
||||||
s.SendElectricMachineryMessage(collectSpeedMap)
|
|
||||||
}
|
|
||||||
func (s *electricalMachineryImpl) SendElectricMachineryMessage(emMap map[int]*message.ElectricMachinery) {
|
|
||||||
for key, em := range emMap {
|
|
||||||
client := s.electricalMachineryUdpClientMap[key]
|
|
||||||
if client != nil {
|
|
||||||
data := em.Encode()
|
|
||||||
hexStr := hex.EncodeToString(data)
|
|
||||||
slog.Info("发送电机转速消息key", hexStr)
|
|
||||||
err := client.Send(data)
|
|
||||||
if err != nil {
|
|
||||||
slog.Info("发送电机转速消息失败key", hexStr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (s *electricalMachineryImpl) SendElectricMachineryMessage2(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) {
|
|
||||||
collectSpeedMap := initEMMsg(trainState)
|
|
||||||
if trainState.VobcState.Tc1Active {
|
|
||||||
collectSpeed(info.HeadSpeed1, info.HeadSpeed2, trainState.TrainEndsA, collectSpeedMap)
|
|
||||||
|
|
||||||
} else if trainState.VobcState.Tc2Active {
|
|
||||||
collectSpeed(info.TailSpeed1, info.TailSpeed2, trainState.TrainEndsB, collectSpeedMap)
|
|
||||||
}
|
|
||||||
// 更新电机转速
|
|
||||||
s.SendElectricMachineryMessage(collectSpeedMap)
|
|
||||||
}
|
|
||||||
func collectSpeed(speed1, speed2 float32, endP *common_proto.TrainEndsState, resultMap map[int]*message.ElectricMachinery) {
|
|
||||||
pa := resultMap[PointA]
|
|
||||||
pb := resultMap[PointB]
|
|
||||||
if endP.SpeedSensorEnableA || endP.SpeedSensorEnableB {
|
|
||||||
if endP.AccOutSpeed > 0 {
|
|
||||||
pa.Speed = float32(endP.AccOutSpeed) / 3.6
|
|
||||||
pb.Speed = float32(endP.AccOutSpeed) / 3.6
|
|
||||||
} else {
|
|
||||||
if endP.SpeedSensorEnableA {
|
|
||||||
pa.Speed = speed1
|
|
||||||
}
|
|
||||||
if endP.SpeedSensorEnableB {
|
|
||||||
pb.Speed = speed2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func initEMMsg(trainState *state_proto.TrainState) map[int]*message.ElectricMachinery {
|
|
||||||
|
|
||||||
collectSpeedMap := map[int]*message.ElectricMachinery{
|
|
||||||
PointA: {
|
|
||||||
Speed: 0,
|
|
||||||
WheelDiameter: trainState.WheelDiameter,
|
|
||||||
IsBack: trainState.VobcState.DirectionBackward},
|
|
||||||
PointB: {Speed: 0,
|
|
||||||
WheelDiameter: trainState.WheelDiameter,
|
|
||||||
IsBack: trainState.VobcState.DirectionBackward},
|
|
||||||
}
|
|
||||||
return collectSpeedMap
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *electricalMachineryImpl) initElectricalMachinery() {
|
func (s *electricalMachineryImpl) initElectricalMachinery() {
|
||||||
s.electricalMachineryUdpClientMap = map[int]udp.UdpClient{}
|
s.electricalMachineryUdpClient = udp.NewClient(fmt.Sprintf("%v:%v", s.runConfig.Ip, s.runConfig.RemotePort))
|
||||||
for _, c := range s.runConfig {
|
|
||||||
if &c != nil && c.Ip != "" && c.Open {
|
|
||||||
ep := PointA
|
|
||||||
if !c.EndPointA {
|
|
||||||
ep = PointB
|
|
||||||
}
|
|
||||||
s.electricalMachineryUdpClientMap[ep] = udp.NewClient(fmt.Sprintf("%v:%v", c.Ip, c.RemotePort))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var _default ElectricMachinery
|
var _default ElectricMachinery
|
||||||
|
@ -1,25 +0,0 @@
|
|||||||
package electrical_machinery
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
|
||||||
"testing"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestServer(t *testing.T) {
|
|
||||||
udpServer := udp.NewServer(fmt.Sprintf("127.0.0.1:%d", 9999), handleCanetFrames)
|
|
||||||
udpServer.Listen()
|
|
||||||
select {}
|
|
||||||
}
|
|
||||||
func handleCanetFrames(d []byte) {
|
|
||||||
msg := &message.ElectricMachinery{}
|
|
||||||
msg.Decode(d)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestOther(t *testing.T) {
|
|
||||||
dd := 1714024680 - time.Now().Unix()
|
|
||||||
fmt.Println(dd)
|
|
||||||
fmt.Println(int32(dd))
|
|
||||||
}
|
|
10
third_party/example/main.go
vendored
10
third_party/example/main.go
vendored
@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/balisecodec"
|
"joylink.club/bj-rtsts-server/third_party/balise"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TestMsg struct {
|
type TestMsg struct {
|
||||||
@ -40,19 +40,19 @@ func main() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
// time.Sleep(time.Second * 60)
|
// time.Sleep(time.Second * 60)
|
||||||
// for i, v := range balisecodec.ConvWords {
|
// for i, v := range balise.ConvWords {
|
||||||
// fmt.Printf("0%o,", v)
|
// fmt.Printf("0%o,", v)
|
||||||
// if i%10 == 9 {
|
// if i%10 == 9 {
|
||||||
// fmt.Println()
|
// fmt.Println()
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
v10 := balisecodec.ToValLeftMsb([]byte{
|
v10 := balise.ToVal([]int{
|
||||||
1, 1, 1,
|
1, 1, 1,
|
||||||
1, 1, 1, 1,
|
1, 1, 1, 1,
|
||||||
1, 1, 1, 1,
|
1, 1, 1, 1,
|
||||||
1, 1, 1, 1})
|
1, 1, 1, 1})
|
||||||
fmt.Println(v10)
|
fmt.Println(v10)
|
||||||
bs := balisecodec.ToBitsLeftMsb(1982, 11)
|
bs := balise.ToBits(1982, 11)
|
||||||
fmt.Println(bs)
|
fmt.Println(bs)
|
||||||
// fmt.Printf("%o\n", balisecodec.ConvWords[511])
|
// fmt.Printf("%o\n", balise.ConvWords[511])
|
||||||
}
|
}
|
||||||
|
155
third_party/example/rssp/ci/ci_server.go
vendored
Normal file
155
third_party/example/rssp/ci/ci_server.go
vendored
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
package ci
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/axle_device"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"sort"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
type CiServer interface {
|
||||||
|
Start()
|
||||||
|
Stop()
|
||||||
|
//SendSectionReset 向计轴设备发送计轴命令
|
||||||
|
SendSectionReset(sectionId string, drst bool, pdrst bool)
|
||||||
|
//HandleSectionStatus 收到来自计轴设备的物理区段状态
|
||||||
|
HandleSectionStatus(status []*message.SectionStatusMsg)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 北京12号线酒仙桥集中站物理区段码表
|
||||||
|
var codePointMap = map[int]string{0: "北京_12_酒仙桥_9G", 1: "北京_12_酒仙桥_1DG", 2: "北京_12_酒仙桥_11G", 3: "北京_12_酒仙桥_13G", 4: "北京_12_酒仙桥_15G", 5: "北京_12_酒仙桥_6G", 6: "北京_12_酒仙桥_8G", 7: "北京_12_酒仙桥_2DG", 8: "北京_12_酒仙桥_10G", 9: "北京_12_酒仙桥_12G", 10: "北京_12_酒仙桥_14G"}
|
||||||
|
var idRowMap = make(map[string]int)
|
||||||
|
var sectionCmds []*message.SectionCmdMsg
|
||||||
|
var cmdsLock = sync.Mutex{}
|
||||||
|
|
||||||
|
// rssp 测试
|
||||||
|
type ciServer struct {
|
||||||
|
//所属城市
|
||||||
|
city string
|
||||||
|
//所属线路
|
||||||
|
lineId string
|
||||||
|
//所属集中站
|
||||||
|
centralizedStation string
|
||||||
|
//接收方每个安全通信会话对应的发送周期值,单位ms
|
||||||
|
sendingPeriod uint32
|
||||||
|
//主安全通道
|
||||||
|
rsspChannel *axle_device.RsspChannel
|
||||||
|
//
|
||||||
|
cancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ciServer) HandleSectionStatus(status []*message.SectionStatusMsg) {
|
||||||
|
if len(codePointMap) != len(status) {
|
||||||
|
fmt.Println("==>>接收到的区段状态与码表不对应:", "codePointsLen=", len(codePointMap), ",statusLen=", len(status))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Println("==>>接收到的区段状态----------------------------------------------------------------------------i")
|
||||||
|
for row, state := range status {
|
||||||
|
sectionId := codePointMap[row]
|
||||||
|
fmt.Printf("==>>[%d]区段[%s]状态: Clr=%t Occ=%t Rac=%t Rjo=%t Rjt=%t\n", row, sectionId, state.Clr, state.Occ, state.Rac, state.Rjo, state.Rjt)
|
||||||
|
}
|
||||||
|
fmt.Println("==>>接收到的区段状态----------------------------------------------------------------------------o")
|
||||||
|
}
|
||||||
|
func (s *ciServer) periodRun(runContext context.Context) {
|
||||||
|
defer func() {
|
||||||
|
fmt.Println("==>>CI Server 周期运行退出 ...")
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-runContext.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
s.doSendSectionCmdMsg()
|
||||||
|
time.Sleep(time.Duration(s.sendingPeriod) * time.Millisecond)
|
||||||
|
//更新周期性参数
|
||||||
|
s.rsspChannel.NextPeriod()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (s *ciServer) doSendSectionCmdMsg() {
|
||||||
|
if s.rsspChannel != nil {
|
||||||
|
data := s.collectSectionCmdsData()
|
||||||
|
fmt.Println("==>>CI发送区段指令数据", ",len=", len(data))
|
||||||
|
s.rsspChannel.SendUserData(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (s *ciServer) collectSectionCmdsData() []byte {
|
||||||
|
defer func() {
|
||||||
|
cmdsLock.Unlock()
|
||||||
|
}()
|
||||||
|
cmdsLock.Lock()
|
||||||
|
//
|
||||||
|
data := (&message.SectionCmdMsgPack{Ck: 0x80, Scs: sectionCmds}).Encode()
|
||||||
|
return data
|
||||||
|
}
|
||||||
|
|
||||||
|
// SendSectionReset 发送区段复位指令
|
||||||
|
func (s *ciServer) SendSectionReset(sectionId string, drst bool, pdrst bool) {
|
||||||
|
defer func() {
|
||||||
|
cmdsLock.Unlock()
|
||||||
|
}()
|
||||||
|
cmdsLock.Lock()
|
||||||
|
//
|
||||||
|
sec := sectionCmds[idRowMap[sectionId]]
|
||||||
|
sec.Drst = drst
|
||||||
|
sec.Pdrst = pdrst
|
||||||
|
}
|
||||||
|
|
||||||
|
type rowId struct {
|
||||||
|
row int
|
||||||
|
id string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *ciServer) Start() {
|
||||||
|
s.rsspChannel.SetRcvUserDataCallback(s.rcvUserData)
|
||||||
|
s.rsspChannel.Start()
|
||||||
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
|
go s.periodRun(ctx)
|
||||||
|
s.cancel = cancel
|
||||||
|
}
|
||||||
|
func (s *ciServer) Stop() {
|
||||||
|
if s.rsspChannel != nil {
|
||||||
|
s.rsspChannel.Stop()
|
||||||
|
s.rsspChannel = nil
|
||||||
|
}
|
||||||
|
if s.cancel != nil {
|
||||||
|
s.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func (s *ciServer) rcvUserData(data []byte) {
|
||||||
|
fmt.Println("==>>CI接收到区段状态数据", ",len=", len(data))
|
||||||
|
msg := &message.SectionStatusMsgPack{}
|
||||||
|
msg.Decode(data)
|
||||||
|
s.HandleSectionStatus(msg.Sms)
|
||||||
|
}
|
||||||
|
func NewRsspCiServer(cfg *config.RsspAxleConfig) CiServer {
|
||||||
|
ra := &ciServer{}
|
||||||
|
//
|
||||||
|
ra.city = cfg.City
|
||||||
|
ra.lineId = cfg.LineId
|
||||||
|
ra.centralizedStation = cfg.CentralizedStation
|
||||||
|
ra.sendingPeriod = cfg.RsspCfg.SendingPeriod
|
||||||
|
//
|
||||||
|
mrc := &axle_device.RsspChannel{}
|
||||||
|
ra.rsspChannel = mrc.Init(&cfg.RsspCfg)
|
||||||
|
//
|
||||||
|
return ra
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitCiServerCodePoints() {
|
||||||
|
var ris []*rowId
|
||||||
|
for row, id := range codePointMap {
|
||||||
|
idRowMap[id] = row
|
||||||
|
ris = append(ris, &rowId{row: row, id: id})
|
||||||
|
}
|
||||||
|
sort.SliceStable(ris, func(i, j int) bool {
|
||||||
|
return ris[i].row < ris[j].row
|
||||||
|
})
|
||||||
|
for range ris {
|
||||||
|
sectionCmds = append(sectionCmds, &message.SectionCmdMsg{Drst: false, Pdrst: false})
|
||||||
|
}
|
||||||
|
}
|
46
third_party/example/rssp/main.go
vendored
Normal file
46
third_party/example/rssp/main.go
vendored
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/example/rssp/ci"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
// message.InitRsspCrcTable()
|
||||||
|
ci.InitCiServerCodePoints()
|
||||||
|
//
|
||||||
|
cfg := &config.RsspAxleConfig{}
|
||||||
|
cfg.City = "北京"
|
||||||
|
cfg.LineId = "12"
|
||||||
|
cfg.CentralizedStation = "酒仙桥"
|
||||||
|
cfg.RsspCfg.SrcAddr = 0x01
|
||||||
|
cfg.RsspCfg.DstAddr = 0x02
|
||||||
|
cfg.RsspCfg.DataVer1 = 0x0011
|
||||||
|
cfg.RsspCfg.DataVer2 = 0x0012
|
||||||
|
cfg.RsspCfg.SID1 = 0x10000000
|
||||||
|
cfg.RsspCfg.SID2 = 0x00000001
|
||||||
|
cfg.RsspCfg.SINIT1 = 0x01
|
||||||
|
cfg.RsspCfg.SINIT2 = 0x02
|
||||||
|
cfg.RsspCfg.SendingPeriod = 500
|
||||||
|
cfg.RsspCfg.SsrRsspTimeout = 3
|
||||||
|
cfg.RsspCfg.Mtv = 3
|
||||||
|
cfg.RsspCfg.DeviceA = true
|
||||||
|
cfg.RsspCfg.PicType = message.PIC_MASTER
|
||||||
|
cfg.RsspCfg.RemoteIp = "192.168.3.5"
|
||||||
|
cfg.RsspCfg.RemoteUdpPort = 6666
|
||||||
|
cfg.RsspCfg.LocalUdpPort = 7777
|
||||||
|
//
|
||||||
|
ciServer := ci.NewRsspCiServer(cfg)
|
||||||
|
ciServer.Start()
|
||||||
|
fmt.Println("==>>ci server ...")
|
||||||
|
for {
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
ciServer.SendSectionReset("北京_12_酒仙桥_9G", true, false)
|
||||||
|
}
|
||||||
|
//
|
||||||
|
time.Sleep(3600 * time.Second)
|
||||||
|
}
|
399
third_party/interlock/beijing11/msg.go
vendored
399
third_party/interlock/beijing11/msg.go
vendored
@ -1,399 +0,0 @@
|
|||||||
package beijing11
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"github.com/snksoft/crc"
|
|
||||||
)
|
|
||||||
|
|
||||||
const ( //不知道对不对,问也不回,先瞎写吧
|
|
||||||
ON = 0x55 //按钮-按下;道岔-定位;屏蔽门-关门;计轴区段-占用
|
|
||||||
OFF = 0xAA //按钮-抬起;道岔-反位;屏蔽门-开门;计轴区段-出清
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
SignalAspect_No = 0x99 //灭灯,这个值目前未知,先用一个应该没被使用的值占位
|
|
||||||
SignalAspect_H = 0x01 //红灯
|
|
||||||
SignalAspect_L = 0x04 //绿灯
|
|
||||||
SignalAspect_U = 0x02 //黄灯
|
|
||||||
SignalAspect_HU = 0x03 //红黄
|
|
||||||
SignalAspect_B = 0x08 //白灯
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetStateByte(state bool) byte {
|
|
||||||
if state {
|
|
||||||
return ON
|
|
||||||
} else {
|
|
||||||
return OFF
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FromInterlockFrame 来自联锁的数据帧
|
|
||||||
type FromInterlockFrame struct {
|
|
||||||
Len uint16
|
|
||||||
InterlockCode uint16 //联锁编号(联锁->轨旁:OC的编号,轨旁->联锁:联锁站编号)
|
|
||||||
WaysideCode uint16 //轨旁编号
|
|
||||||
TurnoutData *DeviceData //道岔数据
|
|
||||||
PSDData *DeviceData //屏蔽门数据
|
|
||||||
ESBData *ESBData //紧急停车按钮数据
|
|
||||||
HoldTrainData *HoldTrainData //扣车按钮数据
|
|
||||||
SignalData *DeviceData //信号机数据
|
|
||||||
AxleSectionData *DeviceData //计轴区段数据
|
|
||||||
WrzfData *DeviceData //无人折返数据
|
|
||||||
FymData *DeviceData //防淹门数据
|
|
||||||
SPKSData *SPKSData //SPKS数据
|
|
||||||
CkmData *DeviceData //车库门数据
|
|
||||||
//XcjData *DeviceData //洗车机数据
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *FromInterlockFrame) Decode(data []byte) error {
|
|
||||||
f.Len = binary.BigEndian.Uint16(data[1:3])
|
|
||||||
//if int(f.Len) != len(data)-3 {
|
|
||||||
// return errors.New(fmt.Sprintf("%s数据长度不对[%d:%d]", logTag, f.Len, len(data)-3))
|
|
||||||
//}
|
|
||||||
f.InterlockCode = binary.BigEndian.Uint16(data[3:5])
|
|
||||||
f.WaysideCode = binary.BigEndian.Uint16(data[5:7])
|
|
||||||
|
|
||||||
turnoutData, i := decodeDeviceData(data, 7)
|
|
||||||
f.TurnoutData = turnoutData
|
|
||||||
psdData, i := decodeDeviceData(data, i)
|
|
||||||
f.PSDData = psdData
|
|
||||||
esbData, i := decodeESBData(data, i)
|
|
||||||
f.ESBData = esbData
|
|
||||||
holdTrainData, i := decodeHoldTrainData(data, i)
|
|
||||||
f.HoldTrainData = holdTrainData
|
|
||||||
signalData, i := decodeDeviceData(data, i)
|
|
||||||
f.SignalData = signalData
|
|
||||||
axleSectionData, i := decodeDeviceData(data, i)
|
|
||||||
f.AxleSectionData = axleSectionData
|
|
||||||
wrzfData, i := decodeDeviceData(data, i)
|
|
||||||
f.WrzfData = wrzfData
|
|
||||||
fymData, i := decodeDeviceData(data, i)
|
|
||||||
f.FymData = fymData
|
|
||||||
spksData, i := decodeSPKSData(data, i)
|
|
||||||
f.SPKSData = spksData
|
|
||||||
ckmData, i := decodeDeviceData(data, i)
|
|
||||||
f.CkmData = ckmData
|
|
||||||
//xcjData, i := decodeDeviceData(data, i)
|
|
||||||
//f.XcjData = xcjData
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeDeviceData(data []byte, index uint16) (*DeviceData, uint16) {
|
|
||||||
data = data[index:]
|
|
||||||
num := binary.BigEndian.Uint16(data[0:2])
|
|
||||||
i := 2 + 3*num
|
|
||||||
data = data[2:i]
|
|
||||||
var cmdList []*DeviceCmd
|
|
||||||
for i := 0; i < len(data); i += 3 {
|
|
||||||
cmdList = append(cmdList, &DeviceCmd{
|
|
||||||
Id: binary.BigEndian.Uint16(data[i : i+2]),
|
|
||||||
Cmd: data[i+2],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
deviceData := &DeviceData{
|
|
||||||
Num: num,
|
|
||||||
CmdList: cmdList,
|
|
||||||
}
|
|
||||||
return deviceData, index + i
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeESBData(data []byte, index uint16) (*ESBData, uint16) {
|
|
||||||
data = data[index:]
|
|
||||||
num := binary.BigEndian.Uint16(data[0:2])
|
|
||||||
nextIndex := 2 + 4*num
|
|
||||||
data = data[2:nextIndex]
|
|
||||||
var cmdList []*ESBCmd
|
|
||||||
for i := 0; i < len(data); i += 4 {
|
|
||||||
cmdList = append(cmdList, &ESBCmd{
|
|
||||||
Id: binary.BigEndian.Uint16(data[i : i+2]),
|
|
||||||
JjtcCmd: data[i+2],
|
|
||||||
JjtcplCmd: data[i+3],
|
|
||||||
//JjtcfmqCmd: data[i+4],
|
|
||||||
//Ess1Cmd: data[i+5],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
deviceData := &ESBData{
|
|
||||||
Num: num,
|
|
||||||
CmdList: cmdList,
|
|
||||||
}
|
|
||||||
return deviceData, index + nextIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeHoldTrainData(data []byte, index uint16) (*HoldTrainData, uint16) {
|
|
||||||
data = data[index:]
|
|
||||||
num := binary.BigEndian.Uint16(data[0:2])
|
|
||||||
nextIndex := 2 + 6*num
|
|
||||||
data = data[2:nextIndex]
|
|
||||||
var cmdList []*HoldTrainCmd
|
|
||||||
for i := 0; i < len(data); i += 6 {
|
|
||||||
cmdList = append(cmdList, &HoldTrainCmd{
|
|
||||||
Id: binary.BigEndian.Uint16(data[i : i+2]),
|
|
||||||
KcCmd: data[i+2],
|
|
||||||
KcplCmd: data[i+3],
|
|
||||||
Kc2Cmd: data[i+4],
|
|
||||||
Kcpl2Cmd: data[i+5],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
deviceData := &HoldTrainData{
|
|
||||||
Num: num,
|
|
||||||
CmdList: cmdList,
|
|
||||||
}
|
|
||||||
return deviceData, index + nextIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
func decodeSPKSData(data []byte, index uint16) (*SPKSData, uint16) {
|
|
||||||
data = data[index:]
|
|
||||||
num := binary.BigEndian.Uint16(data[0:2])
|
|
||||||
nextIndex := 2 + 4*num
|
|
||||||
data = data[2:nextIndex]
|
|
||||||
var cmdList []*SPKSCmd
|
|
||||||
for i := 0; i < len(data); i += 4 {
|
|
||||||
cmdList = append(cmdList, &SPKSCmd{
|
|
||||||
Id: binary.BigEndian.Uint16(data[i : i+2]),
|
|
||||||
SPKSCmd: data[i+2],
|
|
||||||
SPKSPLCmd: data[i+3],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
deviceData := &SPKSData{
|
|
||||||
Num: num,
|
|
||||||
CmdList: cmdList,
|
|
||||||
}
|
|
||||||
return deviceData, index + nextIndex
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeviceData struct {
|
|
||||||
Num uint16 //设备数量
|
|
||||||
CmdList []*DeviceCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
type ESBData struct {
|
|
||||||
Num uint16 //紧急停车按钮的数量
|
|
||||||
CmdList []*ESBCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
type HoldTrainData struct {
|
|
||||||
Num uint16 //扣车的数量
|
|
||||||
CmdList []*HoldTrainCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
type SPKSData struct {
|
|
||||||
Num uint16 //SPKS的数量
|
|
||||||
CmdList []*SPKSCmd
|
|
||||||
}
|
|
||||||
|
|
||||||
type ESBCmd struct {
|
|
||||||
Id uint16 //紧急停车ID
|
|
||||||
JjtcCmd byte //紧急停车按钮命令
|
|
||||||
JjtcplCmd byte //紧急停车旁路按钮命令
|
|
||||||
//JjtcfmqCmd byte //紧急停车蜂鸣器命令
|
|
||||||
//Ess1Cmd byte //Ess1指示灯状态
|
|
||||||
}
|
|
||||||
|
|
||||||
type HoldTrainCmd struct {
|
|
||||||
Id uint16 //扣车ID
|
|
||||||
KcCmd byte //扣车命令
|
|
||||||
KcplCmd byte //扣车旁路命令
|
|
||||||
Kc2Cmd byte //2号扣车命令
|
|
||||||
Kcpl2Cmd byte //2号扣车旁路命令
|
|
||||||
}
|
|
||||||
|
|
||||||
type SPKSCmd struct {
|
|
||||||
Id uint16 //SPKS ID
|
|
||||||
SPKSCmd byte //SPKS按钮
|
|
||||||
SPKSPLCmd byte //SPKSPL按钮
|
|
||||||
}
|
|
||||||
|
|
||||||
type DeviceCmd struct {
|
|
||||||
Id uint16 //设备ID
|
|
||||||
Cmd byte //设备命令
|
|
||||||
}
|
|
||||||
|
|
||||||
// ToInterlockFrame 发往联锁的数据帧
|
|
||||||
type ToInterlockFrame struct {
|
|
||||||
WaysideCode uint16
|
|
||||||
InterlockCode uint16
|
|
||||||
TurnoutStates []*TurnoutState //道岔状态
|
|
||||||
PsdStates []*PSDState //屏蔽门状态
|
|
||||||
ESBStates []*ESBState //紧急停车按钮状态
|
|
||||||
//HoldTrainData []*HoldTrainState //扣车按钮状态(数量0)
|
|
||||||
SignalStates []*SignalState //信号机状态
|
|
||||||
AxleSectionStates []*AxleSectionState //计轴区段状态
|
|
||||||
//WrzfData []*WrzfState //无人折返状态(数量0)
|
|
||||||
//FymData []*FymState //防淹门状态(数量0)
|
|
||||||
SPKSStates []*SPKSState //SPKS状态
|
|
||||||
//CkmData []*CkmState //车库门状态(数量0)
|
|
||||||
//XcjData []*XcjState //洗车机状态(无)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (t *ToInterlockFrame) encode() []byte {
|
|
||||||
data := make([]byte, 0, 128)
|
|
||||||
data = append(data, 0x83) //报文类型
|
|
||||||
data = append(data, 0, 0) //报文长度占位
|
|
||||||
data = binary.BigEndian.AppendUint16(data, t.WaysideCode)
|
|
||||||
data = binary.BigEndian.AppendUint16(data, t.InterlockCode)
|
|
||||||
//道岔
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(len(t.TurnoutStates)))
|
|
||||||
for _, state := range t.TurnoutStates {
|
|
||||||
data = state.encode(data)
|
|
||||||
}
|
|
||||||
//屏蔽门
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(len(t.PsdStates)))
|
|
||||||
for _, state := range t.PsdStates {
|
|
||||||
data = state.encode(data)
|
|
||||||
}
|
|
||||||
//紧急停车
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(len(t.ESBStates)))
|
|
||||||
for _, state := range t.ESBStates {
|
|
||||||
data = state.encode(data)
|
|
||||||
}
|
|
||||||
//扣车,数量0
|
|
||||||
data = binary.BigEndian.AppendUint16(data, 0)
|
|
||||||
//信号机状态
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(len(t.SignalStates)))
|
|
||||||
for _, state := range t.SignalStates {
|
|
||||||
data = state.encode(data)
|
|
||||||
}
|
|
||||||
//计轴区段
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(len(t.AxleSectionStates)))
|
|
||||||
for _, state := range t.AxleSectionStates {
|
|
||||||
data = state.encode(data)
|
|
||||||
}
|
|
||||||
//无人折返,数量0
|
|
||||||
data = binary.BigEndian.AppendUint16(data, 0)
|
|
||||||
//防淹门,数量0
|
|
||||||
data = binary.BigEndian.AppendUint16(data, 0)
|
|
||||||
//SPKS
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(len(t.SPKSStates)))
|
|
||||||
for _, state := range t.SPKSStates {
|
|
||||||
data = state.encode(data)
|
|
||||||
}
|
|
||||||
//填充字节
|
|
||||||
fillSlice := make([]byte, 19)
|
|
||||||
fillSlice[2] = 1
|
|
||||||
data = append(data, fillSlice...)
|
|
||||||
//CRC32
|
|
||||||
data = binary.BigEndian.AppendUint32(data, crc32(data[3:]))
|
|
||||||
//填充报文长度
|
|
||||||
binary.BigEndian.PutUint16(data[1:3], uint16(len(data)-7))
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type TurnoutState struct {
|
|
||||||
Id uint16 //道岔ID
|
|
||||||
State byte //道岔的采集状态
|
|
||||||
//Alarm byte //道岔的报警状态
|
|
||||||
//Current1 byte //转辙机1电流值,单位A
|
|
||||||
//Current2 byte //转辙机2电流值,单位A
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *TurnoutState) encode(data []byte) []byte {
|
|
||||||
data = binary.BigEndian.AppendUint16(data, s.Id)
|
|
||||||
data = append(data, s.State /*, s.Alarm, s.Current1, s.Current2*/)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type PSDState struct {
|
|
||||||
Id uint16 //屏蔽门ID
|
|
||||||
State byte //屏蔽门开关门状态
|
|
||||||
Hsjc byte //互锁解除状态
|
|
||||||
PCB byte //PCB状态
|
|
||||||
POB byte //POB状态
|
|
||||||
DPB byte //DPB状态
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *PSDState) encode(data []byte) []byte {
|
|
||||||
data = binary.BigEndian.AppendUint16(data, s.Id)
|
|
||||||
data = append(data, s.State, s.Hsjc, s.PCB, s.POB, s.DPB)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type ESBState struct {
|
|
||||||
Id uint16 //紧急停车ID
|
|
||||||
State byte //紧急停车按钮状态
|
|
||||||
PlState byte //紧急停车按钮旁路状态
|
|
||||||
//ESS byte //ESS状态(按下55,抬起aa)(解析驱动数据,没有此状态对应的驱动)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *ESBState) encode(data []byte) []byte {
|
|
||||||
data = binary.BigEndian.AppendUint16(data, s.Id)
|
|
||||||
data = append(data, s.State, s.PlState)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type HoldTrainState struct {
|
|
||||||
Id uint16 //扣车ID
|
|
||||||
State byte //扣车按钮状态(按下55,抬起aa)
|
|
||||||
PlState byte //扣车按钮旁路状态(按下55,抬起aa)
|
|
||||||
State2 byte //2号扣车按钮状态(55开启,aa关闭)
|
|
||||||
PlState2 byte //2号扣车按钮旁路状态(55开启,aa关闭)
|
|
||||||
}
|
|
||||||
|
|
||||||
type SignalState struct {
|
|
||||||
Id uint16 //信号机ID
|
|
||||||
State byte //信号机的采集状态
|
|
||||||
//Current byte //信号机当前亮灯的电流值
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SignalState) encode(data []byte) []byte {
|
|
||||||
data = binary.BigEndian.AppendUint16(data, s.Id)
|
|
||||||
data = append(data, s.State /*s.Current*/)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type AxleSectionState struct {
|
|
||||||
Id uint16 //计轴区段Id
|
|
||||||
State byte //计轴区段的采集状态
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *AxleSectionState) encode(data []byte) []byte {
|
|
||||||
data = binary.BigEndian.AppendUint16(data, s.Id)
|
|
||||||
data = append(data, s.State)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type WrzfState struct {
|
|
||||||
Id uint16 //无人折返ID
|
|
||||||
State byte //无人折返的采集状态
|
|
||||||
}
|
|
||||||
|
|
||||||
type FymState struct {
|
|
||||||
Id uint16 //防淹门ID
|
|
||||||
OpenAndLock byte //防淹门打开锁闭状态
|
|
||||||
CloseReq byte //防淹门关闭请求状态
|
|
||||||
}
|
|
||||||
|
|
||||||
type SPKSState struct {
|
|
||||||
Id uint16 //SPKS ID
|
|
||||||
State byte //SPKS按钮状态
|
|
||||||
PlState byte //SPKSPL按钮状态
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *SPKSState) encode(data []byte) []byte {
|
|
||||||
data = binary.BigEndian.AppendUint16(data, s.Id)
|
|
||||||
data = append(data, s.State, s.PlState)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
type CkmState struct {
|
|
||||||
Id uint16 //车库门ID
|
|
||||||
State byte //车库门采集状态
|
|
||||||
ModeState byte //车库门模式状态
|
|
||||||
FaultState byte //车库门故障状态
|
|
||||||
}
|
|
||||||
|
|
||||||
type XcjState struct {
|
|
||||||
Id uint16 //洗车机ID
|
|
||||||
Ready byte //洗车机就绪状态
|
|
||||||
ResponseConfirm byte //回复确认状态
|
|
||||||
GoState1 byte //出发状态1
|
|
||||||
GoState2 byte //出发状态2
|
|
||||||
StopState byte //急停状态
|
|
||||||
BackConfirm 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))
|
|
||||||
}
|
|
193
third_party/interlock/beijing11/msg_test.go
vendored
193
third_party/interlock/beijing11/msg_test.go
vendored
@ -1,193 +0,0 @@
|
|||||||
package beijing11
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/util/myreader"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestFromInterlockFrame_Decode(t *testing.T) {
|
|
||||||
str := "58bea4c65e0e583f5bdedc310800450000c9d0770000801100003d0b0a0d3d0b7814413c40d800b5fcfd8200a63c0363010003000400000500000900000200040000080000020004aaaa0008aaaa0000000f000d06000e01000f060010060021060023060011060012060026060027010013060014010022060024060025060010001300001400001500001600001700001800001900001a00002c00002d00002e00002f00003000003100003200003300000000000004000daaaa000eaaaa000faaaa0010aaaa00000000000000000000000058f24545"
|
|
||||||
data, err := hex.DecodeString(str)
|
|
||||||
if err != nil {
|
|
||||||
t.Fatal(err)
|
|
||||||
}
|
|
||||||
if data[0] != 0x82 {
|
|
||||||
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(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 := "583f5bdedc3158bea4c65e0e080045000172b52c4000401188173d0b78143d0b0a0d40d8413c015ebe7f83014f63013c0200030004010005010009020006000202eeaaaaaa000302eeaaaaaa000402eeaaaaaa000602eeaaaaaa000702eeaaaaaa000802eeaaaaaa00060002aaaa0003aaaa0004aaaa0006aaaa0007aaaa0008aaaa0000001b000800000900000a00000b00000c00000d06000e01000f06001006001106001206001306001401001c00001d00001e00001f00002000002106002206002306002406002506002606002701002800002b00001e000b00000c00000d00000e00000f00001000001100001200001300001400001500001600001700001800001900001a00002600002700002800002900002a00002b00002c00002d00002e00002f0000300000310000320000330000000000000c0005aaaa0006aaaa0007aaaa0008aaaa0009aaaa000aaaaa000baaaa000caaaa000daaaa000eaaaa000faaaa0010aaaa00000100000000000000000000000000000000328ef0af"
|
|
||||||
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("【屏蔽门】")
|
|
||||||
}
|
|
||||||
{ //紧急停车按钮
|
|
||||||
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】")
|
|
||||||
}
|
|
||||||
//CRC32
|
|
||||||
fmt.Printf("%x【CRC32】\n", reader.ReadBytes(reader.Len()))
|
|
||||||
}
|
|
52
third_party/interlock/beijing11/repo.go
vendored
52
third_party/interlock/beijing11/repo.go
vendored
@ -1,52 +0,0 @@
|
|||||||
package beijing11
|
|
||||||
|
|
||||||
// StationDeviceIndexTable 联锁站设备索引表
|
|
||||||
type StationDeviceIndexTable struct {
|
|
||||||
//StationName string //地图数据中车站的Code属性
|
|
||||||
//InterlockCode uint16 //通信数据中的“联锁编号”
|
|
||||||
TurnoutMap map[uint16]*Row //key-联锁编号
|
|
||||||
PsdMap map[uint16]*Row //key-联锁编号
|
|
||||||
EsbMap map[uint16]*Row //key-联锁编号
|
|
||||||
HoldTrainMap map[uint16]*Row //key-联锁编号
|
|
||||||
SignalMap map[uint16]*Row //key-联锁编号
|
|
||||||
AxleSectionMap map[uint16]*Row //key-联锁编号
|
|
||||||
WrzfMap map[uint16]*Row //key-联锁编号
|
|
||||||
FymMap map[uint16]*Row //key-联锁编号
|
|
||||||
SpksMap map[uint16]*Row //key-联锁编号
|
|
||||||
CkmMap map[uint16]*Row //key-联锁编号
|
|
||||||
XcjMap map[uint16]*Row //key-联锁编号
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewStationDeviceIndexTable( /*stationName string, interlockIndex uint16*/ ) *StationDeviceIndexTable {
|
|
||||||
return &StationDeviceIndexTable{
|
|
||||||
//StationName: stationName,
|
|
||||||
//InterlockCode: 0x3C00 + interlockIndex,
|
|
||||||
TurnoutMap: make(map[uint16]*Row),
|
|
||||||
PsdMap: make(map[uint16]*Row),
|
|
||||||
EsbMap: make(map[uint16]*Row),
|
|
||||||
HoldTrainMap: make(map[uint16]*Row),
|
|
||||||
SignalMap: make(map[uint16]*Row),
|
|
||||||
AxleSectionMap: make(map[uint16]*Row),
|
|
||||||
WrzfMap: make(map[uint16]*Row),
|
|
||||||
FymMap: make(map[uint16]*Row),
|
|
||||||
SpksMap: make(map[uint16]*Row),
|
|
||||||
CkmMap: make(map[uint16]*Row),
|
|
||||||
XcjMap: make(map[uint16]*Row),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type Row struct {
|
|
||||||
interlockCode uint16 //所属联锁站编号
|
|
||||||
commonId uint32 //地图中设备的ID
|
|
||||||
uid string //模型仓库中的设备模型ID
|
|
||||||
index uint16 //联锁通信中的设备ID
|
|
||||||
relateDeviceMap map[string]string //此设备关联的其它设备 key-查找设备所用的标识,val-uid
|
|
||||||
}
|
|
||||||
|
|
||||||
const ( //屏蔽门相关的继电器
|
|
||||||
POB = "POB"
|
|
||||||
PCB = "PCB"
|
|
||||||
DPB = "DPB"
|
|
||||||
S = "S" //屏蔽门短编组开门继电器索引
|
|
||||||
L = "L" //屏蔽门长编组开门继电器索引
|
|
||||||
)
|
|
744
third_party/interlock/beijing11/service.go
vendored
744
third_party/interlock/beijing11/service.go
vendored
@ -1,744 +0,0 @@
|
|||||||
// Package beijing11 北京11号线联锁通信
|
|
||||||
package beijing11
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/config"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/data_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/tpapi"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
|
||||||
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
|
||||||
"joylink.club/rtsssimulation/component"
|
|
||||||
"joylink.club/rtsssimulation/entity"
|
|
||||||
"joylink.club/rtsssimulation/fi"
|
|
||||||
"log/slog"
|
|
||||||
"math"
|
|
||||||
"net"
|
|
||||||
"runtime/debug"
|
|
||||||
"sort"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
logTag = "[北京11号线联锁通信]"
|
|
||||||
privateLogger *slog.Logger
|
|
||||||
loggerInit sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
mu = sync.Mutex{} //启动任务时使用,避免重复启动任务
|
|
||||||
serviceContextMap = make(map[string]*serviceContext) //每个集中站的服务上下文,key-集中站code
|
|
||||||
waysideCode uint16 = 0x6301
|
|
||||||
)
|
|
||||||
|
|
||||||
type serviceContext struct {
|
|
||||||
cancelFunc context.CancelFunc //用来结束各个协程的函数
|
|
||||||
ioAddr *net.UDPAddr //向联锁发送数据的客户端
|
|
||||||
server udp.UdpServer //接收联锁数据的服务端(同时也是向联锁发送数据的udp客户端)
|
|
||||||
sim *memory.VerifySimulation //启动服务所使用的仿真
|
|
||||||
iConfig config.InterlockConfig //启动服务使用的联锁配置
|
|
||||||
deviceTable *StationDeviceIndexTable //联锁站的设备ID表,key-车站名
|
|
||||||
toInterlockFrames []*ToInterlockFrame //发给联锁的消息,因为需要按车站划分范围、排序,故将数据提前整理好,仅替换设备状态
|
|
||||||
state tpapi.ThirdPartyApiServiceState //服务状态(用于展示)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CollectAllServices() []tpapi.ThirdPartyApiService {
|
|
||||||
var services []tpapi.ThirdPartyApiService
|
|
||||||
for _, service := range serviceContextMap {
|
|
||||||
services = append(services, service)
|
|
||||||
}
|
|
||||||
return services
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) Type() state_proto.SimulationThirdPartyApiService_Type {
|
|
||||||
return state_proto.SimulationThirdPartyApiService_CI
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) State() tpapi.ThirdPartyApiServiceState {
|
|
||||||
return s.state
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) FindAppendApiService() []tpapi.ThirdPartyApiService {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) TrueService() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) ServiceDesc() string {
|
|
||||||
return logTag
|
|
||||||
}
|
|
||||||
|
|
||||||
func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimulation) {
|
|
||||||
if interlockConfig.Ip == "" || !interlockConfig.Open {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
//制表
|
|
||||||
table, toInterlockFrames := preprocessingData(simulation, interlockConfig.Code)
|
|
||||||
if table == nil { //当前仿真内没有11号线联锁通信所需数据
|
|
||||||
return
|
|
||||||
}
|
|
||||||
serviceCtx := serviceContextMap[interlockConfig.Code]
|
|
||||||
if serviceCtx != nil {
|
|
||||||
panic(fmt.Sprintf("%s重复启动联锁站[%s]通信服务", logTag, interlockConfig.Code))
|
|
||||||
}
|
|
||||||
//仿真IO地址
|
|
||||||
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())
|
|
||||||
serviceCtx = &serviceContext{
|
|
||||||
cancelFunc: cancelFunc,
|
|
||||||
ioAddr: ioAddr,
|
|
||||||
sim: simulation,
|
|
||||||
iConfig: interlockConfig,
|
|
||||||
deviceTable: table,
|
|
||||||
toInterlockFrames: toInterlockFrames,
|
|
||||||
}
|
|
||||||
//UDP服务端
|
|
||||||
server := udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), serviceCtx.handleDriveMsg)
|
|
||||||
serviceCtx.server = server
|
|
||||||
err = server.Listen()
|
|
||||||
if err != nil {
|
|
||||||
panic(fmt.Sprintf("%s启动UDP服务失败:%s", logTag, err))
|
|
||||||
}
|
|
||||||
|
|
||||||
serviceCtx.runCollectTask(ctx)
|
|
||||||
serviceContextMap[interlockConfig.Code] = serviceCtx
|
|
||||||
}
|
|
||||||
|
|
||||||
func Stop(stationCode string) {
|
|
||||||
mu.Lock()
|
|
||||||
defer mu.Unlock()
|
|
||||||
serviceContext := serviceContextMap[stationCode]
|
|
||||||
if serviceContext != nil {
|
|
||||||
serviceContext.cancelFunc()
|
|
||||||
if serviceContext.server != nil {
|
|
||||||
serviceContext.server.Close()
|
|
||||||
}
|
|
||||||
delete(serviceContextMap, stationCode)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) handleDriveMsg(data []byte) {
|
|
||||||
logger().Info(fmt.Sprintf("收到消息:%x", data))
|
|
||||||
frame := &FromInterlockFrame{}
|
|
||||||
err := frame.Decode(data)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("解析数据出错", "error", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
wd := entity.GetWorldData(s.sim.World)
|
|
||||||
for _, cmd := range frame.TurnoutData.CmdList {
|
|
||||||
uid := s.deviceTable.TurnoutMap[cmd.Id].uid
|
|
||||||
if cmd.Cmd == 0x01 {
|
|
||||||
err = fi.DriveTurnoutDCOn(s.sim.World, uid)
|
|
||||||
} else if cmd.Cmd == 0x02 {
|
|
||||||
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)
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{ //采集状态赋值
|
|
||||||
signalAspectMap := make(map[uint16]byte)
|
|
||||||
for _, cmd := range frame.SignalData.CmdList {
|
|
||||||
signalAspectMap[cmd.Id] = cmd.Cmd
|
|
||||||
}
|
|
||||||
for _, interlockFrame := range s.toInterlockFrames {
|
|
||||||
for _, state := range interlockFrame.SignalStates {
|
|
||||||
state.State = signalAspectMap[state.Id]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func preprocessingData(sim *memory.VerifySimulation, stationCode string) (*StationDeviceIndexTable, []*ToInterlockFrame) {
|
|
||||||
for _, mapId := range sim.MapIds {
|
|
||||||
giType := memory.QueryGiType(mapId)
|
|
||||||
if giType != data_proto.PictureType_StationLayout {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
stationGi := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
|
|
||||||
if stationGi.LianSuoData == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
frameMap := make(map[uint16]*ToInterlockFrame)
|
|
||||||
frameSlice := make([]*ToInterlockFrame, 0, 2)
|
|
||||||
getFrame := func(interlockCode uint16) *ToInterlockFrame {
|
|
||||||
frame := frameMap[interlockCode]
|
|
||||||
if frame == nil {
|
|
||||||
frame = &ToInterlockFrame{InterlockCode: interlockCode, WaysideCode: waysideCode}
|
|
||||||
frameMap[interlockCode] = frame
|
|
||||||
frameSlice = append(frameSlice, frame)
|
|
||||||
}
|
|
||||||
return frame
|
|
||||||
}
|
|
||||||
|
|
||||||
uids := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
|
||||||
table := NewStationDeviceIndexTable()
|
|
||||||
stationMap := make(map[uint32]uint16)
|
|
||||||
for _, station := range stationGi.LianSuoData.Stations {
|
|
||||||
stationMap[station.Id] = uint16(0x3c00 + station.Index)
|
|
||||||
}
|
|
||||||
//道岔
|
|
||||||
for _, data := range stationGi.LianSuoData.Switchs {
|
|
||||||
if data.Index <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, station := range uids.TurnoutIds[data.Id].CentralizedStations {
|
|
||||||
interlockCode := stationMap[station.Common.Id]
|
|
||||||
if interlockCode != 0 {
|
|
||||||
frame := getFrame(interlockCode)
|
|
||||||
frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{Id: uint16(data.Index)})
|
|
||||||
table.TurnoutMap[uint16(data.Index)] = &Row{
|
|
||||||
interlockCode: interlockCode,
|
|
||||||
commonId: data.Id,
|
|
||||||
uid: uids.TurnoutIds[data.Id].Uid,
|
|
||||||
index: uint16(data.Index),
|
|
||||||
relateDeviceMap: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//屏蔽门
|
|
||||||
for _, data := range stationGi.LianSuoData.ScreenDoors {
|
|
||||||
if data.Index <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
relateDeviceMap := make(map[string]string)
|
|
||||||
wd := entity.GetWorldData(sim.World)
|
|
||||||
entry := wd.EntityMap[uids.PsdIds[data.Id].Uid]
|
|
||||||
circuit := component.PsdCircuitType.Get(entry)
|
|
||||||
var s, l int32 = math.MaxInt32, 0
|
|
||||||
var sRelayId, lRelayId string
|
|
||||||
for i, relay := range circuit.KMJMap {
|
|
||||||
if i <= s {
|
|
||||||
s = i
|
|
||||||
sRelayId = component.UidType.Get(relay).Id
|
|
||||||
}
|
|
||||||
if i >= l {
|
|
||||||
l = i
|
|
||||||
lRelayId = component.UidType.Get(relay).Id
|
|
||||||
}
|
|
||||||
}
|
|
||||||
relateDeviceMap[S] = sRelayId
|
|
||||||
relateDeviceMap[L] = lRelayId
|
|
||||||
for _, station := range uids.PsdIds[data.Id].CentralizedStations {
|
|
||||||
interlockCode := stationMap[station.Common.Id]
|
|
||||||
if interlockCode != 0 {
|
|
||||||
frame := getFrame(interlockCode)
|
|
||||||
frame.PsdStates = append(frame.PsdStates, &PSDState{Id: uint16(data.Index)})
|
|
||||||
for _, mkx := range sim.Repo.MkxList() {
|
|
||||||
if mkx.Psd().Id() == uids.PsdIds[data.Id].Uid {
|
|
||||||
relateDeviceMap[POB] = mkx.Pobj().Id()
|
|
||||||
relateDeviceMap[PCB] = mkx.Pcbj().Id()
|
|
||||||
relateDeviceMap[DPB] = mkx.Pabj().Id()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
table.PsdMap[uint16(data.Index)] = &Row{
|
|
||||||
interlockCode: interlockCode,
|
|
||||||
commonId: data.Id,
|
|
||||||
uid: uids.PsdIds[data.Id].Uid,
|
|
||||||
index: uint16(data.Index),
|
|
||||||
relateDeviceMap: relateDeviceMap,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//紧急停车
|
|
||||||
for _, data := range stationGi.LianSuoData.EsbButtons {
|
|
||||||
if data.Index <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, station := range uids.EsbIds[data.Id].CentralizedStations {
|
|
||||||
interlockCode := stationMap[station.Common.Id]
|
|
||||||
if interlockCode != 0 {
|
|
||||||
frame := getFrame(interlockCode)
|
|
||||||
frame.ESBStates = append(frame.ESBStates, &ESBState{Id: uint16(data.Index)})
|
|
||||||
table.EsbMap[uint16(data.Index)] = &Row{
|
|
||||||
interlockCode: interlockCode,
|
|
||||||
commonId: data.Id,
|
|
||||||
uid: uids.EsbIds[data.Id].Uid,
|
|
||||||
index: uint16(data.Index),
|
|
||||||
relateDeviceMap: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//扣车,实际数据中数量为0
|
|
||||||
//信号机
|
|
||||||
for _, data := range stationGi.LianSuoData.Signals {
|
|
||||||
if data.Index <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, station := range uids.SignalIds[data.Id].CentralizedStations {
|
|
||||||
interlockCode := stationMap[station.Common.Id]
|
|
||||||
if interlockCode != 0 {
|
|
||||||
frame := getFrame(interlockCode)
|
|
||||||
frame.SignalStates = append(frame.SignalStates, &SignalState{Id: uint16(data.Index)})
|
|
||||||
table.SignalMap[uint16(data.Index)] = &Row{
|
|
||||||
interlockCode: interlockCode,
|
|
||||||
commonId: data.Id,
|
|
||||||
uid: uids.SignalIds[data.Id].Uid,
|
|
||||||
index: uint16(data.Index),
|
|
||||||
relateDeviceMap: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
{ //临时补充一个信号机
|
|
||||||
table.SignalMap[40] = &Row{
|
|
||||||
interlockCode: 0x3c02,
|
|
||||||
commonId: 0,
|
|
||||||
uid: "",
|
|
||||||
index: 40,
|
|
||||||
relateDeviceMap: nil,
|
|
||||||
}
|
|
||||||
frame := getFrame(0x3c02)
|
|
||||||
frame.SignalStates = append(frame.SignalStates, &SignalState{Id: 40})
|
|
||||||
}
|
|
||||||
//计轴区段
|
|
||||||
for _, data := range stationGi.LianSuoData.AcSections {
|
|
||||||
if data.Index <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
sectionModule := sim.Repo.FindAxleCountingSection(uids.AxleCountingSectionIds[data.Id].Uid)
|
|
||||||
for _, station := range sectionModule.PhysicalSection().CentralizedStation() {
|
|
||||||
//目前没发现一个计轴区段属于两个联锁区的情况,暂不处理
|
|
||||||
interlockCode := stationMap[sim.UidMap[station.Id()].CommonId]
|
|
||||||
if interlockCode != 0 {
|
|
||||||
frame := getFrame(interlockCode)
|
|
||||||
frame.AxleSectionStates = append(frame.AxleSectionStates, &AxleSectionState{Id: uint16(data.Index)})
|
|
||||||
table.AxleSectionMap[uint16(data.Index)] = &Row{
|
|
||||||
interlockCode: interlockCode,
|
|
||||||
commonId: data.Id,
|
|
||||||
uid: uids.AxleCountingSectionIds[data.Id].Uid,
|
|
||||||
index: uint16(data.Index),
|
|
||||||
relateDeviceMap: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//无人折返,实际数据中数量为0
|
|
||||||
//防淹门,实际数据中数量为0
|
|
||||||
//人员防护
|
|
||||||
for _, data := range stationGi.LianSuoData.SpksSwitchs {
|
|
||||||
if data.Index <= 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, station := range uids.SpksIds[data.Id].CentralizedStations {
|
|
||||||
interlockCode := stationMap[station.Common.Id]
|
|
||||||
if interlockCode != 0 {
|
|
||||||
frame := getFrame(interlockCode)
|
|
||||||
frame.SPKSStates = append(frame.SPKSStates, &SPKSState{Id: uint16(data.Index)})
|
|
||||||
table.SpksMap[uint16(data.Index)] = &Row{
|
|
||||||
interlockCode: interlockCode,
|
|
||||||
commonId: data.Id,
|
|
||||||
uid: uids.SpksIds[data.Id].Uid,
|
|
||||||
index: uint16(data.Index),
|
|
||||||
relateDeviceMap: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//车库门,实际数据中数量为0
|
|
||||||
//洗车机,实际数据中没有
|
|
||||||
//按设备id大小排序
|
|
||||||
for _, frame := range frameSlice {
|
|
||||||
sort.Slice(frame.TurnoutStates, func(i, j int) bool {
|
|
||||||
return frame.TurnoutStates[i].Id < frame.TurnoutStates[j].Id
|
|
||||||
})
|
|
||||||
sort.Slice(frame.PsdStates, func(i, j int) bool {
|
|
||||||
return frame.PsdStates[i].Id < frame.PsdStates[j].Id
|
|
||||||
})
|
|
||||||
sort.Slice(frame.ESBStates, func(i, j int) bool {
|
|
||||||
return frame.ESBStates[i].Id < frame.ESBStates[j].Id
|
|
||||||
})
|
|
||||||
sort.Slice(frame.SignalStates, func(i, j int) bool {
|
|
||||||
return frame.SignalStates[i].Id < frame.SignalStates[j].Id
|
|
||||||
})
|
|
||||||
sort.Slice(frame.AxleSectionStates, func(i, j int) bool {
|
|
||||||
return frame.AxleSectionStates[i].Id < frame.AxleSectionStates[j].Id
|
|
||||||
})
|
|
||||||
sort.Slice(frame.SPKSStates, func(i, j int) bool {
|
|
||||||
return frame.SPKSStates[i].Id < frame.SPKSStates[j].Id
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
return table, frameSlice
|
|
||||||
}
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) runCollectTask(ctx context.Context) {
|
|
||||||
go func() {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
logger().Error("状态收集任务出错,记录后重启", "error", err, "stack", string(debug.Stack()))
|
|
||||||
s.runCollectTask(ctx)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for range time.Tick(time.Duration(s.iConfig.Period) * time.Millisecond) {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
s.collectDeviceState()
|
|
||||||
for _, frame := range s.toInterlockFrames {
|
|
||||||
data := frame.encode()
|
|
||||||
_, err := s.server.WriteToUdp(data, s.ioAddr)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error("向联锁发送数据失败", "error", err)
|
|
||||||
s.state = tpapi.ThirdPartyState_Broken
|
|
||||||
} else {
|
|
||||||
logger().Info(fmt.Sprintf("向联锁发送数据:%x", data))
|
|
||||||
s.state = tpapi.ThirdPartyState_Broken
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *serviceContext) collectDeviceState() {
|
|
||||||
wd := entity.GetWorldData(s.sim.World)
|
|
||||||
for _, frame := range s.toInterlockFrames {
|
|
||||||
//道岔
|
|
||||||
for _, state := range frame.TurnoutStates {
|
|
||||||
row := s.deviceTable.TurnoutMap[state.Id]
|
|
||||||
entry := wd.EntityMap[row.uid]
|
|
||||||
tp := component.TurnoutPositionType.Get(entry)
|
|
||||||
var stateByte byte
|
|
||||||
if entry.HasComponent(component.TurnoutFaultCiqdType) {
|
|
||||||
stateByte = 0xff
|
|
||||||
} else {
|
|
||||||
if tp.Dw {
|
|
||||||
stateByte = 0x01
|
|
||||||
} else if tp.Fw {
|
|
||||||
stateByte = 0x02
|
|
||||||
} else {
|
|
||||||
stateByte = 0x08
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
state.State = stateByte
|
|
||||||
}
|
|
||||||
//屏蔽门
|
|
||||||
for _, state := range frame.PsdStates {
|
|
||||||
row := s.deviceTable.PsdMap[state.Id]
|
|
||||||
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))
|
|
||||||
}
|
|
||||||
var stateByte byte
|
|
||||||
if psdState.Close {
|
|
||||||
stateByte = 0x02
|
|
||||||
} else {
|
|
||||||
stateByte = 0x01
|
|
||||||
}
|
|
||||||
var hsjc byte
|
|
||||||
if psdState.InterlockRelease {
|
|
||||||
hsjc = 0xff
|
|
||||||
} else {
|
|
||||||
hsjc = 0xee
|
|
||||||
}
|
|
||||||
|
|
||||||
state.State = stateByte
|
|
||||||
state.Hsjc = hsjc
|
|
||||||
state.PCB = mkxBytes[0]
|
|
||||||
state.POB = mkxBytes[1]
|
|
||||||
state.DPB = mkxBytes[2]
|
|
||||||
}
|
|
||||||
//紧急停车
|
|
||||||
for _, state := range frame.ESBStates {
|
|
||||||
row := s.deviceTable.EsbMap[state.Id]
|
|
||||||
esb := s.sim.Repo.FindEsb(row.uid)
|
|
||||||
relay := wd.EntityMap[esb.RelayId()]
|
|
||||||
pla := wd.EntityMap[esb.PlaId()]
|
|
||||||
|
|
||||||
state.State = GetStateByte(!component.BitStateType.Get(relay).Val)
|
|
||||||
state.PlState = GetStateByte(component.BitStateType.Get(pla).Val)
|
|
||||||
}
|
|
||||||
////信号机
|
|
||||||
//for _, state := range frame.SignalStates {
|
|
||||||
// row := s.deviceTable.SignalMap[state.Id]
|
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// state.State = stateByte
|
|
||||||
//}
|
|
||||||
//计轴区段
|
|
||||||
for _, state := range frame.AxleSectionStates {
|
|
||||||
row := s.deviceTable.AxleSectionMap[state.Id]
|
|
||||||
entry := wd.EntityMap[row.uid]
|
|
||||||
sectionState := component.AxleCountingSectionStateType.Get(entry)
|
|
||||||
var stateByte byte = 0x00
|
|
||||||
if sectionState.Occupied {
|
|
||||||
stateByte = 0x40
|
|
||||||
}
|
|
||||||
|
|
||||||
state.State = stateByte
|
|
||||||
}
|
|
||||||
//SPKS
|
|
||||||
for _, state := range frame.SPKSStates {
|
|
||||||
row := s.deviceTable.SpksMap[state.Id]
|
|
||||||
spks := s.sim.Repo.FindSpks(row.uid)
|
|
||||||
relay := wd.EntityMap[spks.Relay()]
|
|
||||||
pla := wd.EntityMap[spks.PlaId()]
|
|
||||||
|
|
||||||
state.State = GetStateByte(!component.BitStateType.Get(relay).Val)
|
|
||||||
state.PlState = GetStateByte(component.BitStateType.Get(pla).Val)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func logger() *slog.Logger {
|
|
||||||
loggerInit.Do(func() {
|
|
||||||
privateLogger = slog.Default().With("tag", logTag)
|
|
||||||
})
|
|
||||||
return privateLogger
|
|
||||||
}
|
|
267
third_party/interlock/beijing12/interlock.go
vendored
267
third_party/interlock/beijing12/interlock.go
vendored
@ -1,267 +0,0 @@
|
|||||||
// Package beijing12 北京12号线联锁通信
|
|
||||||
package beijing12
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/data_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/dto/state_proto"
|
|
||||||
"joylink.club/bj-rtsts-server/sys_error"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/balisecodec"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/tcp"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/tpapi"
|
|
||||||
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
|
||||||
"joylink.club/rtsssimulation/fi"
|
|
||||||
"joylink.club/rtsssimulation/repository"
|
|
||||||
"log/slog"
|
|
||||||
"runtime/debug"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"joylink.club/bj-rtsts-server/config"
|
|
||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
|
||||||
)
|
|
||||||
|
|
||||||
var ( //日志
|
|
||||||
logTag = "[北京12号线联锁通信]"
|
|
||||||
privateLogger *slog.Logger
|
|
||||||
loggerInit sync.Once
|
|
||||||
)
|
|
||||||
|
|
||||||
// 联锁代理通信接口
|
|
||||||
type InterlockMessageManager interface {
|
|
||||||
CollectInterlockRelayInfo(code string) *message.InterlockSendMsgPkg
|
|
||||||
HandleInterlockDriverInfo(code string, b []byte)
|
|
||||||
}
|
|
||||||
|
|
||||||
var interlockMap = make(map[string]*interlockProxy)
|
|
||||||
var initMutex sync.Mutex
|
|
||||||
|
|
||||||
func Start(c config.InterlockConfig, simulation *memory.VerifySimulation, baliseList []*repository.Transponder) {
|
|
||||||
initMutex.Lock()
|
|
||||||
defer initMutex.Unlock()
|
|
||||||
proxy := &interlockProxy{
|
|
||||||
runConfig: c,
|
|
||||||
indexBalise: make(map[byte]map[byte]*repository.Transponder),
|
|
||||||
fromCIBytes: make([]byte, 0, fromCIBytesLen),
|
|
||||||
}
|
|
||||||
//构建应答器的索引映射
|
|
||||||
for _, mapId := range simulation.MapIds {
|
|
||||||
giType := memory.QueryGiType(mapId)
|
|
||||||
if giType != data_proto.PictureType_StationLayout {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
uids := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
|
||||||
for _, baliseRelationship := range uids.TransponderIds {
|
|
||||||
balise := simulation.Repo.FindTransponder(baliseRelationship.Uid)
|
|
||||||
if balise.LeuIndex() == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, station := range baliseRelationship.CentralizedStations {
|
|
||||||
if station.StationName != c.Code {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
leuIndex := byte(balise.LeuIndex())
|
|
||||||
if proxy.indexBalise[leuIndex] == nil {
|
|
||||||
proxy.indexBalise[leuIndex] = make(map[byte]*repository.Transponder)
|
|
||||||
}
|
|
||||||
proxy.indexBalise[leuIndex][byte(balise.IndexInLeu())] = balise
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
proxy.Start(simulation)
|
|
||||||
interlockMap[c.Code] = proxy
|
|
||||||
}
|
|
||||||
|
|
||||||
func Stop(c config.InterlockConfig) {
|
|
||||||
proxy := interlockMap[c.Code]
|
|
||||||
if proxy != nil {
|
|
||||||
proxy.Stop()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type interlockProxy struct {
|
|
||||||
tcpClient *tcp.TcpClient
|
|
||||||
|
|
||||||
simulation *memory.VerifySimulation
|
|
||||||
collectInfoTaskCancel context.CancelFunc
|
|
||||||
runConfig config.InterlockConfig
|
|
||||||
|
|
||||||
// 按索引存储的应答器,leu索引-leu内索引
|
|
||||||
indexBalise map[byte]map[byte]*repository.Transponder
|
|
||||||
// 联锁发送的数据过长,多个包才能凑成完成报文
|
|
||||||
fromCIBytes []byte
|
|
||||||
// 序列号
|
|
||||||
serialNumber uint8
|
|
||||||
|
|
||||||
state tpapi.ThirdPartyApiServiceState // 服务状态(用于展示)
|
|
||||||
}
|
|
||||||
|
|
||||||
func CollectAllServices() []tpapi.ThirdPartyApiService {
|
|
||||||
var services []tpapi.ThirdPartyApiService
|
|
||||||
for _, service := range interlockMap {
|
|
||||||
services = append(services, service)
|
|
||||||
}
|
|
||||||
return services
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) Type() state_proto.SimulationThirdPartyApiService_Type {
|
|
||||||
return state_proto.SimulationThirdPartyApiService_CI
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) State() tpapi.ThirdPartyApiServiceState {
|
|
||||||
return i.state
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) FindAppendApiService() []tpapi.ThirdPartyApiService {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) TrueService() bool {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) ServiceDesc() string {
|
|
||||||
return logTag
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) Start(simulation *memory.VerifySimulation) {
|
|
||||||
if i.runConfig.Ip == "" || !i.runConfig.Open {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if simulation == nil {
|
|
||||||
panic(fmt.Sprintf("%s启动联锁消息服务错误: InterlockMessageManager不能为nil", logTag))
|
|
||||||
}
|
|
||||||
if i.simulation != nil {
|
|
||||||
panic(fmt.Sprintf("%s启动联锁消息服务错误: 存在正在运行的任务", logTag))
|
|
||||||
}
|
|
||||||
i.initInterlockProxy()
|
|
||||||
ctx, cancel := context.WithCancel(context.Background())
|
|
||||||
go i.collectInfoStateTask(ctx)
|
|
||||||
i.collectInfoTaskCancel = cancel
|
|
||||||
i.simulation = simulation
|
|
||||||
}
|
|
||||||
|
|
||||||
// 定时发送采集电路状态任务
|
|
||||||
func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
logger().Error(logTag+"定时发送采集状态任务异常", "error", err, "stack", string(debug.Stack()))
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
for range time.Tick(time.Duration(i.runConfig.Period) * time.Millisecond) {
|
|
||||||
select {
|
|
||||||
case <-ctx.Done():
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
collectInfoState := i.simulation.CollectInterlockRelayInfo(i.runConfig.Code)
|
|
||||||
if collectInfoState != nil {
|
|
||||||
i.serialNumber++
|
|
||||||
collectInfoState.SetSerialNumber(i.serialNumber)
|
|
||||||
err := i.tcpClient.Send(collectInfoState.Encode())
|
|
||||||
if err != nil {
|
|
||||||
logger().Error(fmt.Sprintf("向联锁发送继电器状态失败:%s", err))
|
|
||||||
i.state = tpapi.ThirdPartyState_Broken
|
|
||||||
} else {
|
|
||||||
i.state = tpapi.ThirdPartyState_Normal
|
|
||||||
//logger().Info(fmt.Sprintf("向联锁发送继电器数据成功:%x", collectInfoState.Encode()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) Stop() {
|
|
||||||
initMutex.Lock()
|
|
||||||
defer initMutex.Unlock()
|
|
||||||
delete(interlockMap, i.runConfig.Code)
|
|
||||||
i.collectInfoTaskCancel()
|
|
||||||
if i.tcpClient != nil {
|
|
||||||
i.tcpClient.Close()
|
|
||||||
}
|
|
||||||
if i.collectInfoTaskCancel != nil {
|
|
||||||
i.collectInfoTaskCancel()
|
|
||||||
}
|
|
||||||
i.simulation = nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) initInterlockProxy() {
|
|
||||||
client, err := tcp.StartTcpClient(fmt.Sprintf("%s:%d", i.runConfig.Ip, i.runConfig.RemotePort), i.handleFromCiData, func(err error) {
|
|
||||||
logger().Error(fmt.Sprintf("TCP客户端读取数据出错,终止通信服务:%s", err))
|
|
||||||
i.Stop()
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
panic(sys_error.New(fmt.Sprintf("%s启动TCP客户端失败", logTag), err))
|
|
||||||
}
|
|
||||||
i.tcpClient = client
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *interlockProxy) handleFromCiData(n int, data []byte) {
|
|
||||||
data = data[:n]
|
|
||||||
//logger().Info(fmt.Sprintf("收到联锁驱动及应答器报文数据,长度%d", n))
|
|
||||||
if len(i.fromCIBytes) != 0 { //报文头已经存进去了
|
|
||||||
i.fromCIBytes = append(i.fromCIBytes, data...)
|
|
||||||
if len(i.fromCIBytes) < fromCIBytesLen { //当存储的报文长度不足预期长度
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else if bytes.HasPrefix(data, []byte{0xff, 0xff}) { //判断是否是报文头
|
|
||||||
i.fromCIBytes = append(i.fromCIBytes, data...)
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//处理联锁报文
|
|
||||||
msg := &fromCiMsg{}
|
|
||||||
err := msg.decode(i.fromCIBytes)
|
|
||||||
//logger().Info(fmt.Sprintf("解析完整联锁驱动及应答器报文数据:%x", i.fromCIBytes))
|
|
||||||
i.fromCIBytes = i.fromCIBytes[:0] //清空联锁报文存储
|
|
||||||
if err != nil {
|
|
||||||
logger().Error(fmt.Sprintf("解析来自CI的数据出错:%s", err.Error()))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//处理驱动数据
|
|
||||||
if i.simulation != nil {
|
|
||||||
//logger().Info(fmt.Sprintf("解析出的驱动数据:%x", msg.driveData))
|
|
||||||
station := i.simulation.Repo.FindStationByStationName(i.runConfig.Code)
|
|
||||||
if station != nil {
|
|
||||||
i.simulation.HandleInterlockDriverInfo(station.Id(), msg.driveData)
|
|
||||||
} else {
|
|
||||||
logger().Error(fmt.Sprintf("没有找到名为%s的车站", i.runConfig.Code))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//处理应答器数据
|
|
||||||
for _, datum := range msg.baliseTelegramData {
|
|
||||||
indexBalise2 := i.indexBalise[datum.leuIndex]
|
|
||||||
if indexBalise2 == nil {
|
|
||||||
//logger().Error(fmt.Sprintf("没有leuIndex[%d]的应答器", datum.leuIndex))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
balise := indexBalise2[datum.index]
|
|
||||||
if balise == nil {
|
|
||||||
//logger().Error(fmt.Sprintf("没有leuIndex[%d]leu内索引[%d]的应答器", datum.leuIndex, datum.index))
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
userTelegram, err := balisecodec.Decode(datum.telegram)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error(fmt.Sprintf("解析应答器报文[%x]出错:%s", datum.telegram, err.Error()))
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
//logger().Info(fmt.Sprintf("解析出应答器[%s]的可变报文", balise.Id()))
|
|
||||||
}
|
|
||||||
err = fi.BaliseUpdateVariableTelegram(i.simulation.World, balise.Id(), datum.telegram, userTelegram, false)
|
|
||||||
if err != nil {
|
|
||||||
logger().Error(fmt.Sprintf("更新leuIndex[%d]leu内索引[%d]的应答器[%s]数据出错:%s", datum.leuIndex, datum.index, balise.Id(), err.Error()))
|
|
||||||
} else {
|
|
||||||
//logger().Info(fmt.Sprintf("更新leuIndex[%d]leu内索引[%d]的应答器[%s]数据成功", datum.leuIndex, datum.index, balise.Id()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func logger() *slog.Logger {
|
|
||||||
loggerInit.Do(func() {
|
|
||||||
privateLogger = slog.Default().With("tag", logTag)
|
|
||||||
})
|
|
||||||
return privateLogger
|
|
||||||
}
|
|
79
third_party/interlock/beijing12/msg.go
vendored
79
third_party/interlock/beijing12/msg.go
vendored
@ -1,79 +0,0 @@
|
|||||||
package beijing12
|
|
||||||
|
|
||||||
import (
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
"joylink.club/bj-rtsts-server/sys_error"
|
|
||||||
"joylink.club/bj-rtsts-server/util/myreader"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 后续如果有其它线路还用此协议,需要将这些常量做成配置
|
|
||||||
const (
|
|
||||||
syncZoneStateLen = 1289 //同步区状态字节数
|
|
||||||
driveDataLen = 14 //驱动数据长度
|
|
||||||
baliseTelegramDataSize = 28 //应答器报文数据个数
|
|
||||||
baliseTelegramMsgLen = 131 //应答器报文数据长度
|
|
||||||
)
|
|
||||||
|
|
||||||
// 来自联锁的报文字节长度
|
|
||||||
var fromCIBytesLen = 8 + syncZoneStateLen + driveDataLen + baliseTelegramMsgLen*baliseTelegramDataSize
|
|
||||||
|
|
||||||
// fromCiMsg 来自联锁的消息
|
|
||||||
type fromCiMsg struct {
|
|
||||||
head1 byte // 包头1 0xFF
|
|
||||||
head2 byte // 包头2 0xFF
|
|
||||||
typeCode byte // 类型码
|
|
||||||
seqNum byte // 序列号
|
|
||||||
reserve []byte // 预留2字节
|
|
||||||
syncZoneState []byte // 同步区状态(目前不用处理)
|
|
||||||
driveData []byte // 驱动数据
|
|
||||||
baliseTelegramData []*baliseTelegramMsg // 应答器报文数据
|
|
||||||
tail []byte // 包尾 0x0000
|
|
||||||
}
|
|
||||||
|
|
||||||
// driveDataLen 表示驱动数据字节数;baliseTelegramDataLen 表示应答器报文数据个数
|
|
||||||
func (f *fromCiMsg) decode(data []byte) error {
|
|
||||||
if len(data) != fromCIBytesLen {
|
|
||||||
return errors.New(fmt.Sprintf("%s联锁数据长度期望值[%d],实际值[%d]", logTag, fromCIBytesLen, len(data)))
|
|
||||||
}
|
|
||||||
reader := myreader.NewReader(data)
|
|
||||||
f.head1 = reader.ReadByte()
|
|
||||||
f.head2 = reader.ReadByte()
|
|
||||||
f.typeCode = reader.ReadByte()
|
|
||||||
f.seqNum = reader.ReadByte()
|
|
||||||
f.reserve = reader.ReadBytes(2)
|
|
||||||
f.syncZoneState = reader.ReadBytes(syncZoneStateLen)
|
|
||||||
f.driveData = reader.ReadBytes(driveDataLen)
|
|
||||||
for i := 0; i < baliseTelegramDataSize; i++ {
|
|
||||||
baliseBytes := reader.ReadBytes(baliseTelegramMsgLen)
|
|
||||||
baliseMsg := &baliseTelegramMsg{}
|
|
||||||
err := baliseMsg.decode(baliseBytes)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
f.baliseTelegramData = append(f.baliseTelegramData, baliseMsg)
|
|
||||||
}
|
|
||||||
f.tail = reader.ReadBytes(2)
|
|
||||||
if reader.Err != nil {
|
|
||||||
return errors.New(fmt.Sprintf("读取字节出错:%s", reader.Err))
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type baliseTelegramMsg struct {
|
|
||||||
leuIndex byte // LEU索引
|
|
||||||
index byte // LEU内部应答器的索引
|
|
||||||
reserve byte // 预留
|
|
||||||
telegram []byte // 应答器报文 128字节
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *baliseTelegramMsg) decode(data []byte) error {
|
|
||||||
if len(data) != 131 {
|
|
||||||
return sys_error.New(fmt.Sprintf("%s应答器报文数据长度不对:%d", logTag, len(data)))
|
|
||||||
}
|
|
||||||
b.leuIndex = data[0]
|
|
||||||
b.index = data[1]
|
|
||||||
b.reserve = data[2]
|
|
||||||
b.telegram = data[3:]
|
|
||||||
return nil
|
|
||||||
}
|
|
20
third_party/interlock/beijing12/msg_test.go
vendored
20
third_party/interlock/beijing12/msg_test.go
vendored
File diff suppressed because one or more lines are too long
133
third_party/interlock/interlock.go
vendored
Normal file
133
third_party/interlock/interlock.go
vendored
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package interlock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"runtime/debug"
|
||||||
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 联锁代理通信接口
|
||||||
|
type InterlockMessageManager interface {
|
||||||
|
CollectInterlockRelayInfo(code string) *message.InterlockSendMsgPkg
|
||||||
|
HandleInterlockDriverInfo(code string, b []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 联锁接口
|
||||||
|
type InterlockProxy interface {
|
||||||
|
// 启动联锁消息功能
|
||||||
|
Start(manager InterlockMessageManager)
|
||||||
|
// 停止联锁消息功能
|
||||||
|
Stop()
|
||||||
|
// 发送联锁采集消息
|
||||||
|
SendCollectMessage(b []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
var interlockMap = make(map[string]InterlockProxy)
|
||||||
|
var initMutex sync.Mutex
|
||||||
|
|
||||||
|
func Default(c *config.InterlockConfig) InterlockProxy {
|
||||||
|
initMutex.Lock()
|
||||||
|
defer initMutex.Unlock()
|
||||||
|
if interlockMap[c.Code] == nil {
|
||||||
|
interlockMap[c.Code] = &interlockProxy{runConfig: c}
|
||||||
|
}
|
||||||
|
return interlockMap[c.Code]
|
||||||
|
}
|
||||||
|
|
||||||
|
type interlockProxy struct {
|
||||||
|
driveInfoUdpServer udp.UdpServer
|
||||||
|
sendCollectUdpClient udp.UdpClient
|
||||||
|
|
||||||
|
manager InterlockMessageManager
|
||||||
|
collectInfoTaskCancel context.CancelFunc
|
||||||
|
runConfig *config.InterlockConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驱动信息进行转发
|
||||||
|
func (i *interlockProxy) handleDriverInfo(b []byte) {
|
||||||
|
handler := i.manager
|
||||||
|
if handler != nil {
|
||||||
|
handler.HandleInterlockDriverInfo(i.runConfig.Code, b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *interlockProxy) Start(manager InterlockMessageManager) {
|
||||||
|
if i.runConfig == nil || i.runConfig.Ip == "" || !i.runConfig.Open {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if manager == nil {
|
||||||
|
panic("启动联锁消息服务错误: InterlockMessageManager不能为nil")
|
||||||
|
}
|
||||||
|
if i.manager != nil {
|
||||||
|
panic("启动联锁消息服务错误: 存在正在运行的任务")
|
||||||
|
}
|
||||||
|
i.manager = manager
|
||||||
|
// 初始化客户端、服务端
|
||||||
|
i.initInterlockProxy()
|
||||||
|
ctx, cancle := context.WithCancel(context.Background())
|
||||||
|
go i.collectInfoStateTask(ctx)
|
||||||
|
i.collectInfoTaskCancel = cancle
|
||||||
|
}
|
||||||
|
|
||||||
|
// 采集电路状态发送间隔,单位ms
|
||||||
|
const InterlockMessageSendInterval = 50
|
||||||
|
|
||||||
|
// 序列号
|
||||||
|
var serialNumber uint8
|
||||||
|
|
||||||
|
// 定时发送采集电路状态任务
|
||||||
|
func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
slog.Error("定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack()))
|
||||||
|
debug.PrintStack()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
collectInfoState := i.manager.CollectInterlockRelayInfo(i.runConfig.Code)
|
||||||
|
if collectInfoState != nil {
|
||||||
|
serialNumber++
|
||||||
|
collectInfoState.SetSerialNumber(serialNumber)
|
||||||
|
i.sendCollectUdpClient.SendMsg(collectInfoState)
|
||||||
|
}
|
||||||
|
time.Sleep(time.Millisecond * InterlockMessageSendInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *interlockProxy) Stop() {
|
||||||
|
initMutex.Lock()
|
||||||
|
defer initMutex.Unlock()
|
||||||
|
delete(interlockMap, i.runConfig.Code)
|
||||||
|
if i.sendCollectUdpClient != nil {
|
||||||
|
i.sendCollectUdpClient.Close()
|
||||||
|
}
|
||||||
|
if i.driveInfoUdpServer != nil {
|
||||||
|
i.driveInfoUdpServer.Close()
|
||||||
|
}
|
||||||
|
if i.collectInfoTaskCancel != nil {
|
||||||
|
i.collectInfoTaskCancel()
|
||||||
|
}
|
||||||
|
i.manager = nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *interlockProxy) SendCollectMessage(b []byte) {
|
||||||
|
i.sendCollectUdpClient.Send(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *interlockProxy) initInterlockProxy() {
|
||||||
|
i.sendCollectUdpClient = udp.NewClient(fmt.Sprintf("%v:%v", i.runConfig.Ip, i.runConfig.RemotePort))
|
||||||
|
i.driveInfoUdpServer = udp.NewServer(fmt.Sprintf(":%d", i.runConfig.LocalPort), i.handleDriverInfo)
|
||||||
|
i.driveInfoUdpServer.Listen()
|
||||||
|
}
|
102
third_party/message/accelerometer.go
vendored
102
third_party/message/accelerometer.go
vendored
@ -1,113 +1,49 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
accHeader = 0xA6
|
accHeader = 0xA6
|
||||||
uaidDefault = 0x71
|
uaidDefault = 0x1C
|
||||||
G = 9.80665
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type Accelerometer struct {
|
type Accelerometer struct {
|
||||||
Acc float32
|
Acc uint32
|
||||||
Aux byte
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeAcc(a float32) (d2, d1, d0 byte) {
|
|
||||||
d2 = 0
|
|
||||||
d1 = 0
|
|
||||||
d0 = 0
|
|
||||||
x := a / G
|
|
||||||
//fmt.Println(x)
|
|
||||||
v := uint32(0)
|
|
||||||
for i := 16; i >= 0; i-- {
|
|
||||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
|
||||||
if t > x {
|
|
||||||
continue
|
|
||||||
} else {
|
|
||||||
v |= 1 << i
|
|
||||||
x -= t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//fmt.Printf("%b, %b\n", v, v<<6)
|
|
||||||
v <<= 6
|
|
||||||
d0 = byte(v)
|
|
||||||
d1 = byte(v >> 8)
|
|
||||||
d2 = byte(v >> 16)
|
|
||||||
|
|
||||||
//accCode := v << 8 //数据向左移动8位,取后3个字节
|
|
||||||
//d2 = byte(accCode >> 16) //取出d2数据
|
|
||||||
//d1 = byte(accCode >> 8 << 8) // & 0xff //取出d1
|
|
||||||
//d0 = byte(accCode << 20) //& 0xf //取出d0高2位
|
|
||||||
|
|
||||||
//fmt.Printf("%b, %b, %b\n", d2, d1, d0)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func decode2Acc(d2, d1, d0 byte) float32 {
|
|
||||||
v := uint32(d2)<<10 | uint32(d1)<<2 | uint32(d0>>6)
|
|
||||||
fmt.Printf("%b\n", v)
|
|
||||||
x := float32(0)
|
|
||||||
for i := 17; i >= 0; i-- {
|
|
||||||
if v&(1<<i) != 0 {
|
|
||||||
t := float32(1.0 / math.Pow(2, float64(17-i)))
|
|
||||||
x += t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//fmt.Println(x)
|
|
||||||
return x * G
|
|
||||||
}
|
|
||||||
|
|
||||||
func (acc *Accelerometer) BuildCanData() []byte {
|
|
||||||
accData := acc.Encode()
|
|
||||||
appData := make([]byte, 0)
|
|
||||||
appData = append(appData, accData...)
|
|
||||||
appData = append(appData, byte(0))
|
|
||||||
canId := CanFrameId{ID1: 0xff, ID2: 0xff, ID3: 0xff, ID4: 0xff}
|
|
||||||
canNet := &CanetFrame{FF: false, RTR: false, CanLen: 7, CanId: canId, CanData: appData}
|
|
||||||
return canNet.Encode()
|
|
||||||
}
|
|
||||||
func (acc *Accelerometer) Encode() []byte {
|
func (acc *Accelerometer) Encode() []byte {
|
||||||
d2, d1, d0 := encodeAcc(acc.Acc)
|
|
||||||
if acc.Acc > 0 {
|
|
||||||
setBit(d2, 7, 0)
|
|
||||||
} else {
|
|
||||||
setBit(d2, 7, 1)
|
|
||||||
}
|
|
||||||
data := make([]byte, 0)
|
data := make([]byte, 0)
|
||||||
data = append(data, accHeader)
|
data = append(data, accHeader)
|
||||||
data = append(data, uaidDefault)
|
data = append(data, uaidDefault)
|
||||||
data = append(data, d0)
|
acc.Acc = acc.Acc | 0x0000FF
|
||||||
data = append(data, d1)
|
data = binary.LittleEndian.AppendUint32(data, acc.Acc)
|
||||||
data = append(data, d2)
|
|
||||||
data = append(data, byte(0))
|
|
||||||
cs := checkSum(data)
|
cs := checkSum(data)
|
||||||
data = append(data, cs)
|
data = append(data, ^cs+1)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkSum(data []byte) byte {
|
func checkSum(data []byte) byte {
|
||||||
var sum uint16 = 0
|
var sum byte = 0
|
||||||
|
|
||||||
for _, d := range data {
|
for _, d := range data {
|
||||||
sum += uint16(d)
|
sum += d
|
||||||
}
|
}
|
||||||
highByte := byte(sum >> 8) // 取高8位
|
return sum
|
||||||
lowByte := byte(sum) // 取低8位
|
|
||||||
secondSum := highByte + lowByte // 再次累加
|
|
||||||
|
|
||||||
//inverse := ^secondSum
|
|
||||||
return ^secondSum
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (acc *Accelerometer) Decode(Packet []byte) error {
|
func (acc *Accelerometer) Decode(data []byte) error {
|
||||||
if len(Packet) < 7 {
|
if len(data) < 7 {
|
||||||
return fmt.Errorf("")
|
return fmt.Errorf("")
|
||||||
}
|
}
|
||||||
decode2Acc(Packet[4], Packet[3], Packet[2])
|
buf := bytes.NewBuffer(data)
|
||||||
|
_, _ = buf.ReadByte()
|
||||||
|
_, _ = buf.ReadByte()
|
||||||
|
var dataInt uint32 = 0
|
||||||
|
binary.Read(buf, binary.LittleEndian, &dataInt)
|
||||||
|
//newData := math.Float32frombits(dataInt & 0xffffc000)
|
||||||
|
acc.Acc = dataInt & 0xffffc000
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
94
third_party/message/btm_data.go
vendored
94
third_party/message/btm_data.go
vendored
@ -1,94 +0,0 @@
|
|||||||
package message
|
|
||||||
|
|
||||||
import "encoding/binary"
|
|
||||||
|
|
||||||
//数据帧(0x80+扩展类型),一个CAN帧只能存储8个字节,对于一个应答器报文,分片到多个CAN数据帧中
|
|
||||||
|
|
||||||
// BtmDataMessageFrame 数据帧-应答器报文
|
|
||||||
// offset = [0x00,0x0c] 共13个即可用于存储应答器报文的共104个字节
|
|
||||||
// BtmDataMessageTimeAFrame 数据帧-时间戳A
|
|
||||||
// offset = 0x0d
|
|
||||||
// BtmDataMessageTimeBFrame 数据帧-时间戳B
|
|
||||||
// offset = 0x0e
|
|
||||||
// BtmDataMessageEndFrame 数据帧-结束
|
|
||||||
// offset = 0x7f
|
|
||||||
const (
|
|
||||||
DATA_TIME_A_OFFSET = 0x0d
|
|
||||||
DATA_TIME_B_OFFSET = 0x0e
|
|
||||||
DATA_END_OFFSET = 0x7f
|
|
||||||
)
|
|
||||||
|
|
||||||
type BtmDataMessageAtpFrame struct {
|
|
||||||
//帧ID
|
|
||||||
FId CanFrameId
|
|
||||||
//8字节,应答器报文片段
|
|
||||||
Message []byte
|
|
||||||
}
|
|
||||||
type BtmDataMessageAtpTimeAndEndFrame struct {
|
|
||||||
//帧ID
|
|
||||||
FId CanFrameId
|
|
||||||
//时间戳A
|
|
||||||
Time uint32
|
|
||||||
//CRC
|
|
||||||
Crc32 uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateBtmDataMessageDataAtpFrame(sn byte, offset byte) *BtmDataMessageAtpFrame {
|
|
||||||
return &BtmDataMessageAtpFrame{
|
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *BtmDataMessageAtpFrame) Encode() *BtmHeadFrame {
|
|
||||||
cf := &BtmHeadFrame{}
|
|
||||||
cf.CanId = f.FId
|
|
||||||
cf.CanLen = 8
|
|
||||||
|
|
||||||
dataBuf := make([]byte, 0, 8)
|
|
||||||
for _, data := range f.Message {
|
|
||||||
dataBuf = append(dataBuf, data)
|
|
||||||
}
|
|
||||||
cf.CanData = dataBuf
|
|
||||||
return cf
|
|
||||||
}
|
|
||||||
func (f *BtmDataMessageAtpFrame) Decode(cf *BtmHeadFrame) bool {
|
|
||||||
f.FId = cf.CanId
|
|
||||||
//
|
|
||||||
reader := NewCanBitsReader(cf.CanData, 8)
|
|
||||||
//
|
|
||||||
f.Message = make([]byte, 0, 8)
|
|
||||||
for c := 0; c < 8; c++ {
|
|
||||||
data, ok := reader.ReadByte()
|
|
||||||
if !ok {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
f.Message = append(f.Message, data)
|
|
||||||
}
|
|
||||||
//
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
/////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
func (atp *BtmDataMessageAtpTimeAndEndFrame) Encode() *BtmHeadFrame {
|
|
||||||
cf := &BtmHeadFrame{}
|
|
||||||
cf.CanId = atp.FId
|
|
||||||
cf.CanLen = 8
|
|
||||||
data := make([]byte, 0)
|
|
||||||
data = binary.BigEndian.AppendUint32(data, atp.Time)
|
|
||||||
data = binary.BigEndian.AppendUint32(data, atp.Crc32)
|
|
||||||
cf.CanData = data
|
|
||||||
return cf
|
|
||||||
}
|
|
||||||
|
|
||||||
func CreateBtmDataMessageTimeAtpFrame(sn byte, offset byte) *BtmDataMessageAtpTimeAndEndFrame {
|
|
||||||
return &BtmDataMessageAtpTimeAndEndFrame{FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+offset, sn)}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////
|
|
||||||
|
|
||||||
func BtmDataMessageEndAtpFrame(sn byte) *BtmDataMessageAtpTimeAndEndFrame {
|
|
||||||
return &BtmDataMessageAtpTimeAndEndFrame{
|
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0xff, sn),
|
|
||||||
}
|
|
||||||
}
|
|
67
third_party/message/btm_net.go
vendored
67
third_party/message/btm_net.go
vendored
@ -1,67 +0,0 @@
|
|||||||
package message
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"strings"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CanetFrame USR-CANET200_V1.0.7 设备 以太网-CAN 透传协议帧(12字节)
|
|
||||||
type BtmHeadFrame struct {
|
|
||||||
CanLen byte //CAN帧数据长度[0,8],CanData中有效数据字节数
|
|
||||||
CanId CanFrameId //CAN帧ID
|
|
||||||
CanData []byte //CAN帧数据,8字节
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewBtmHeadFrame(buf []byte) *BtmHeadFrame {
|
|
||||||
cf := &BtmHeadFrame{}
|
|
||||||
cf.Decode(buf)
|
|
||||||
return cf
|
|
||||||
}
|
|
||||||
func (p *BtmHeadFrame) Encode() []byte {
|
|
||||||
buf := make([]byte, 0)
|
|
||||||
//CAN 帧ID
|
|
||||||
frameId := uint32(p.CanId.ID1)<<21 | uint32(p.CanId.ID2)<<13 | uint32(p.CanId.ID3)<<5 | uint32(p.CanId.ID4)
|
|
||||||
buf = binary.BigEndian.AppendUint32(buf, frameId)
|
|
||||||
//CAN 帧数据
|
|
||||||
if len(p.CanData) != 8 {
|
|
||||||
panic(fmt.Sprintf("len(p.CanData)!=8 datalen:%v", len(p.CanData)))
|
|
||||||
}
|
|
||||||
buf = append(buf, p.CanData...)
|
|
||||||
return buf
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *BtmHeadFrame) Decode(buf []byte) {
|
|
||||||
bb := bytes.NewBuffer(buf)
|
|
||||||
var idSource uint32
|
|
||||||
binary.Read(bb, binary.BigEndian, &idSource)
|
|
||||||
data := make([]byte, bb.Len())
|
|
||||||
_, err := bb.Read(data)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
b1 := byte((idSource >> 21) & 0xFF)
|
|
||||||
b2 := byte((idSource >> 13) & 0xFF)
|
|
||||||
b3 := byte((idSource >> 5) & 0xFF)
|
|
||||||
b4 := byte(idSource & 0x1F)
|
|
||||||
|
|
||||||
p.CanId.ID1 = b1
|
|
||||||
p.CanId.ID2 = b2
|
|
||||||
p.CanId.ID3 = b3
|
|
||||||
p.CanId.ID4 = b4
|
|
||||||
p.CanData = data
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *BtmHeadFrame) String() string {
|
|
||||||
sb := strings.Builder{}
|
|
||||||
sb.WriteString(fmt.Sprintf("CanetFrame CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x", p.CanLen,
|
|
||||||
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
|
|
||||||
sb.WriteString("CanData = ")
|
|
||||||
for _, d := range p.CanData {
|
|
||||||
sb.WriteString(fmt.Sprintf(" 0x%0x ", d))
|
|
||||||
}
|
|
||||||
return sb.String()
|
|
||||||
}
|
|
347
third_party/message/btm_vobc_data.go
vendored
347
third_party/message/btm_vobc_data.go
vendored
@ -1,347 +0,0 @@
|
|||||||
package message
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
|
||||||
"fmt"
|
|
||||||
"github.com/snksoft/crc"
|
|
||||||
"log/slog"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
TRAIN_BTM_ENDA = 0x75E1
|
|
||||||
TRAIN_BTM_ENDB = 0x75E2
|
|
||||||
ID_COMMAND_TYPE = 0xF8 //命令帧
|
|
||||||
REQT_TYPE = 0xE6 //请求帧
|
|
||||||
|
|
||||||
)
|
|
||||||
|
|
||||||
const (
|
|
||||||
COMMAND_TYPE = 0x90 //ID 命令帧 VOBC→BTM20 字节
|
|
||||||
REQUEST_TYPE = 0x91 //请求帧 VOBC→BTM34 字节
|
|
||||||
MESSAGE_TYPE = 0x92 //报文帧 BTM→VOBC 135 字节
|
|
||||||
FREE_MESSAGE_TYPE = 0x94 //空闲帧 BTM→VOBC 135 字节
|
|
||||||
)
|
|
||||||
|
|
||||||
var PACKAGE_HEAD = []byte{0xFF, 0xFE}
|
|
||||||
var PACKAGE_END = []byte{0xFF, 0xFD}
|
|
||||||
|
|
||||||
func BtmVobcDecode(packData []byte) (byte, []byte, error) {
|
|
||||||
head := packData[:2]
|
|
||||||
end := packData[len(packData)-2:]
|
|
||||||
|
|
||||||
if !bytes.Equal(head, PACKAGE_HEAD) || !bytes.Equal(end, PACKAGE_END) {
|
|
||||||
slog.Error("btm vobc 数据包头或包尾尾错误", hex.EncodeToString(packData))
|
|
||||||
return 0, nil, fmt.Errorf("btm vobc 数据包头或包尾尾错误")
|
|
||||||
}
|
|
||||||
data := packData[2 : len(packData)-2]
|
|
||||||
command := data[0]
|
|
||||||
if command != ID_COMMAND_TYPE && command != REQT_TYPE {
|
|
||||||
slog.Error("btm vobc 解析未知命令帧", strconv.FormatInt(int64(command), 16), command)
|
|
||||||
return 0, nil, fmt.Errorf("btm vobc 解析未知命令帧")
|
|
||||||
}
|
|
||||||
dataText := data[1:]
|
|
||||||
if command == ID_COMMAND_TYPE {
|
|
||||||
|
|
||||||
frameType := dataText[0]
|
|
||||||
return frameType, dataText, nil
|
|
||||||
} else if command == REQT_TYPE {
|
|
||||||
newDatatext, _ := TranslateFromFFFE(dataText)
|
|
||||||
rssp := &RsspRsd{}
|
|
||||||
rsspErr := rssp.Decode(newDatatext)
|
|
||||||
if rsspErr != nil {
|
|
||||||
//slog.Error("解析请求帧rssp-i失败,元数据:", hex.EncodeToString(cfs), "错误信息:", rsspErr.Error())
|
|
||||||
return 0, nil, fmt.Errorf("解析请求帧rssp-i失败")
|
|
||||||
}
|
|
||||||
return rssp.Sad[0], rssp.Sad, nil
|
|
||||||
}
|
|
||||||
return 0, nil, fmt.Errorf("btm vobc 解析未知命令帧")
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
WAIT_FF_C1 = 0x00
|
|
||||||
WAIT_FF_C2 = 0x01
|
|
||||||
WAIT_NO_FF = 0x02
|
|
||||||
WAIT_FF_POS = 0x03
|
|
||||||
ABNORMAL_STATE = 0x04
|
|
||||||
|
|
||||||
/*FFFE数据接收状态*/
|
|
||||||
COM_WAIT_START_FF = 0x00
|
|
||||||
COM_WAIT_START_FE = 0x01
|
|
||||||
COM_WAIT_STOP_FF = 0x02
|
|
||||||
COM_WAIT_STOP_FD = 0x03
|
|
||||||
)
|
|
||||||
|
|
||||||
/*
|
|
||||||
func SourceDataDecode(packData []byte) []BaseBtmVobc {
|
|
||||||
data, _ := TranslateFromFFFE(packData)
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func parseData(buf *bytes.Buffer) {
|
|
||||||
h1, _ := buf.ReadByte()
|
|
||||||
h2, _ := buf.ReadByte()
|
|
||||||
if bytes.Equal(PACKAGE_HEAD, []byte{h1, h2}) {
|
|
||||||
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 {
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
func parseIdFrame(frame byte, data []byte) BtmVobcIdCommand {
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
dataLen, _ := buf.ReadByte()
|
|
||||||
dsn, _ := buf.ReadByte()
|
|
||||||
var btmId uint16
|
|
||||||
var vobcId uint16
|
|
||||||
var vobcLifeId uint32
|
|
||||||
var yuliu [5]byte
|
|
||||||
var crc32 uint32
|
|
||||||
binary.Read(buf, binary.BigEndian, &btmId)
|
|
||||||
binary.Read(buf, binary.BigEndian, &vobcId)
|
|
||||||
binary.Read(buf, binary.BigEndian, &vobcLifeId)
|
|
||||||
binary.Read(buf, binary.BigEndian, &yuliu)
|
|
||||||
binary.Read(buf, binary.BigEndian, &crc32)
|
|
||||||
return BtmVobcIdCommand{BaseBtmVobc: BaseBtmVobc{Frame: frame, FrameLen: dataLen, AutoIdFrame: dsn, Crc32: crc32}}
|
|
||||||
}
|
|
||||||
|
|
||||||
type BaseBtmVobc struct {
|
|
||||||
Frame byte //帧类型
|
|
||||||
FrameLen byte //帧长定义为 TEXT+CRC32,ID 命令帧为 20 字节;
|
|
||||||
AutoIdFrame byte // 无论何时传输数据,该数都在 1-255 范围内递增,在错误重传时也是递增的,255 之后是 1,不使用 0;
|
|
||||||
Crc32 uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func baseDecode(d []byte) (BaseBtmVobc, *bytes.Buffer) {
|
|
||||||
buf := bytes.NewBuffer(d)
|
|
||||||
|
|
||||||
frame, _ := buf.ReadByte()
|
|
||||||
frameLen, _ := buf.ReadByte()
|
|
||||||
autoIdFrame, _ := buf.ReadByte()
|
|
||||||
crc32 := binary.BigEndian.Uint32(d[len(d)-4:])
|
|
||||||
|
|
||||||
return BaseBtmVobc{Frame: frame, FrameLen: frameLen, Crc32: crc32, AutoIdFrame: autoIdFrame}, buf
|
|
||||||
}
|
|
||||||
func baseEncode(source []byte) []byte {
|
|
||||||
data := make([]byte, 0)
|
|
||||||
crc32 := crc.CalculateCRC(crc.CRC32, source)
|
|
||||||
newSource := binary.BigEndian.AppendUint32(source, uint32(crc32))
|
|
||||||
|
|
||||||
f2 := make([]byte, len(newSource)*2)
|
|
||||||
lens := aa(newSource, f2)
|
|
||||||
fffeData := f2[:lens]
|
|
||||||
data = append(data, PACKAGE_HEAD...)
|
|
||||||
data = append(data, fffeData...)
|
|
||||||
data = append(data, PACKAGE_END...)
|
|
||||||
return data
|
|
||||||
}
|
|
||||||
|
|
||||||
// ID 命令帧的正文
|
|
||||||
type BtmVobcIdCommand struct {
|
|
||||||
BaseBtmVobc
|
|
||||||
BtmId uint16 //VOBC 向 BTM 分配的 ID,暂定 0x75E1 或者0x75A2,其他无效;
|
|
||||||
VobcId uint16 //暂定 0x5511,其他无效
|
|
||||||
VobcLifeNum uint32 //7~10 1~FFFFFFFF,0 不使用
|
|
||||||
yuliu []byte //11-15 预留字节
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BtmVobcIdCommand) Decode(data []byte) {
|
|
||||||
base, buf := baseDecode(data)
|
|
||||||
b.BaseBtmVobc = base
|
|
||||||
var btmId uint16
|
|
||||||
var vobcId uint16
|
|
||||||
var lifeNum uint32
|
|
||||||
binary.Read(buf, binary.BigEndian, &btmId)
|
|
||||||
binary.Read(buf, binary.BigEndian, &vobcId)
|
|
||||||
binary.Read(buf, binary.BigEndian, &lifeNum)
|
|
||||||
|
|
||||||
b.BtmId = btmId
|
|
||||||
b.VobcId = vobcId
|
|
||||||
b.VobcLifeNum = lifeNum
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
REQ_FRAME_STATUS_OK = 0x06
|
|
||||||
REQ_FRAME_STATUS_ERROR = 0x15
|
|
||||||
REQ_FRAME_STATUS_BOOT = 0x00
|
|
||||||
|
|
||||||
REQ_PACKETS_TYPE_FREE = 0x05
|
|
||||||
REQ_PACKETS_TYPE_MSG = 0x0A
|
|
||||||
REQ_PACKETS_TYPE_BOOT = 0x00
|
|
||||||
)
|
|
||||||
|
|
||||||
// 请求帧的正文
|
|
||||||
type BtmVobcReq struct {
|
|
||||||
BaseBtmVobc
|
|
||||||
FrameStatus byte //帧正确/不正确 06h:帧正确15h:不正确00h:开机状态填00 其它无效
|
|
||||||
MessageType byte // 空闲/报文数据 05h:空闲0Ah:报文数据00h:开机状态填00 其它无效
|
|
||||||
MessageSerial byte //报文序列号 1-255;开机时使用0
|
|
||||||
yuliu []byte //预留字节(10 字节)
|
|
||||||
VobcLifeNum uint32 // VOBC 周期号 1~FFFFFFFF,0 不使用
|
|
||||||
TimeStamp []byte //年月日时分秒各占一个字节
|
|
||||||
Speed uint16 //速度 单位:cm/s
|
|
||||||
VobcLifeWalkDistance uint16 //VOBC 周期走行距离 单位:cm
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BtmVobcReq) Decode(data []byte) {
|
|
||||||
base, buf := baseDecode(data)
|
|
||||||
|
|
||||||
b.BaseBtmVobc = base
|
|
||||||
|
|
||||||
b.FrameStatus, _ = buf.ReadByte()
|
|
||||||
b.MessageType, _ = buf.ReadByte()
|
|
||||||
b.MessageSerial, _ = buf.ReadByte()
|
|
||||||
var tyuli = make([]byte, 10)
|
|
||||||
buf.Read(tyuli)
|
|
||||||
//b.yuliu = data[5:15]
|
|
||||||
var lifeNum uint32
|
|
||||||
ts := make([]byte, 6)
|
|
||||||
var speed uint16
|
|
||||||
var walkDis uint16
|
|
||||||
binary.Read(buf, binary.BigEndian, &lifeNum)
|
|
||||||
buf.Read(ts)
|
|
||||||
binary.Read(buf, binary.BigEndian, &speed)
|
|
||||||
binary.Read(buf, binary.BigEndian, &walkDis)
|
|
||||||
b.VobcLifeNum = lifeNum
|
|
||||||
b.TimeStamp = ts
|
|
||||||
b.Speed = speed
|
|
||||||
b.VobcLifeWalkDistance = walkDis
|
|
||||||
}
|
|
||||||
|
|
||||||
var lock sync.Mutex
|
|
||||||
|
|
||||||
const (
|
|
||||||
btm_status_ok = 0x00
|
|
||||||
btm_status_warn = 0x04
|
|
||||||
)
|
|
||||||
|
|
||||||
var mesage_yuliu = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0} //11~19 预留
|
|
||||||
var yuliu3 = []byte{0, 0, 0, 0, 0, 0} //8~13 保留
|
|
||||||
|
|
||||||
const (
|
|
||||||
BTM_STSTUS_NORMAL = 0x00
|
|
||||||
BTM_STSTUS_WARN = 0x04
|
|
||||||
)
|
|
||||||
|
|
||||||
// 报文帧的正文
|
|
||||||
type BtmVobcMessage struct {
|
|
||||||
BaseBtmVobc
|
|
||||||
FontTtl uint16 //前沿 TTL 时间 单位为 ms,溢出为0xffff,高字节在前;车体及应答器器地面环境理想情况下误差小于 5ms
|
|
||||||
MsgSerial byte //报文序列号 1-255;不使用 0
|
|
||||||
BtmStatus byte //BTM 工作状态 00H-工作正常;04H-警告 BTM 有轻微故障(单套故障,整机能工作),向BDMS 汇报;FFH-BTM 故障,不能正常工作;在MMI进行故障提示并向ATS 汇报
|
|
||||||
Enter1 byte //1 通道好码率 0~100
|
|
||||||
Enter2 byte //2 通道好码率 0~100
|
|
||||||
DecodeTime uint16 //解码时间:从包络前沿到解码成功的时间,单位0.1ms。
|
|
||||||
yuliu []byte //11~19 预留 填 0
|
|
||||||
BackTtl uint16 //后沿 TTL 时间单位为 ms,溢出为0xffff,高字节在前;车体及应答器器地面环境理想情况下误差小于 5ms.
|
|
||||||
BtmMsg []byte //22~125 应答器报文
|
|
||||||
ResponseTime byte //0~150,其他非法,单位0.1ms 误差小于 3ms
|
|
||||||
VobcLifeNum uint32 //VOBC 周期号 1~FFFFFFFF,0 不使用。
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BtmVobcMessage) Encode() []byte {
|
|
||||||
|
|
||||||
data := make([]byte, 0)
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(MESSAGE_TYPE))
|
|
||||||
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, b.FontTtl)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.MsgSerial)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.BtmStatus)
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(100)) //b.Enter1
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(100)) //b.Enter2
|
|
||||||
binary.Write(buf, binary.BigEndian, b.DecodeTime)
|
|
||||||
binary.Write(buf, binary.BigEndian, mesage_yuliu)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.BackTtl)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.BtmMsg)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.ResponseTime)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.VobcLifeNum)
|
|
||||||
|
|
||||||
return baseEncode(buf.Bytes())
|
|
||||||
}
|
|
||||||
|
|
||||||
type BtmVobcMsgFree struct {
|
|
||||||
BaseBtmVobc
|
|
||||||
//yuliu1 byte
|
|
||||||
//yuliu2 byte
|
|
||||||
MsgSerial byte //1-255;开机时为0
|
|
||||||
BtmStatus byte //BTM 工作状态 00H-工作正常;04H-警告 BTM 有轻微故障(单套故障,整机能工作),向BDMS 汇报;FFH-BTM 故障,不能正常工作;在MMI 进行故障提示并向ATS 汇报
|
|
||||||
WorkTemperature byte
|
|
||||||
//yuliu3 []byte //8~13 保留 填 0
|
|
||||||
|
|
||||||
//0-1 位 功放 1 电流状态 功放电流状态:“1”-欠流;“2”- 过流 ;“3”-正常(欠流和过流仅作为功放状态参考)
|
|
||||||
//2-3 位 功放 1 电压状态 功放电压状态:“1”-欠压;“2”- 过压 ;“3”-正常(欠压和过压仅作为功放状态参考)
|
|
||||||
//4-5 位 (预留) 功放 2 电流状态 功放电流状态:“1”-欠流;“2”- 过流 ;“3”-正常(欠流和过流仅作为功放状态参考)
|
|
||||||
//6-7 位 功放 2 电压状 功放电压状态:“1”-欠压;“2”- 过压 ;“3”-正常(欠压和过压仅作为功放状态参考)
|
|
||||||
//8-9 位 天线 1 状态 天线 1 状态:“1”-故障;“3”-正常。
|
|
||||||
//10-11 位 线缆 1 状态 线缆 1 状态:“1”-开路;“2”-短路;“3”-正常。
|
|
||||||
//12-13 位 (预留) 天线 2 状态 天线 2 状态:“1”-故障;“3”-正常。
|
|
||||||
//14-15 位 (预留) 线缆 2 状态 线缆 2 状态:“1”-开路;“2”-短路;“3”-正常。
|
|
||||||
Fun1 uint16 //第 14-15 字节(功放板、天线状态)
|
|
||||||
//第 0 位 上行自检码检测通道 1 状态:“1”-正常;“0”-故障。(故障时,检查处理器板和接收板)
|
|
||||||
//第 1 位 上行自检码检测通道 2 状态:“1”-正常;“0”-故障。(故障时,检查处理器板和接收板)
|
|
||||||
//第 2 位 FSK 连接线状态通道 1状态:“1”-正常;“0”-故障。
|
|
||||||
//第 3 位 FSK 连接线状态通道 2状态:“1”-正常;“0”-故障。
|
|
||||||
//第 4-5 位 保留 保留
|
|
||||||
//第 6-7 位 接收板状态 状态:“0”-双通道故障;“1”-单通道故障;“3”-正常第
|
|
||||||
//8-15位保留 保留
|
|
||||||
Fun2 uint16 //第 16-17 字节(接收板状态)
|
|
||||||
//第 0-1 位 通 道 1-24V 状态 状态:“1”-过压;“2”-欠压;“3”-正常;(欠压和过压仅作为电源板状态参考)
|
|
||||||
//第 2-3 位 通 道 2-24V 状态 状态:“1”-过压;“2”-欠压;“3”-正常;(欠压和过压仅作为电源板状态参考)
|
|
||||||
//第 4 位 通 道 1-23V 状态 状态:“1”-正常;“0”-故障。
|
|
||||||
//第 5 位 通 道 2-23V 状态 状态:“1”-正常;“0”-故障。
|
|
||||||
//第 6-13位保留 保留
|
|
||||||
//第 14-15位 电源板状态 电源板状态:“0”-故障;“1”-单通道故障;“2”-单通道故障;“3”- 正常。
|
|
||||||
Fun3 uint16 //第 18-19 字节(电源板状态)
|
|
||||||
//第 0-1 位 板卡 ID 槽位号 “0”-1 号板卡;“1”-2 号板卡;“2”-3 号板卡;“3”-4 号板卡机箱正面从右往左顺序为处理器板1,2,3(预留),4(预留),同一个通信周期只有一个板卡报警
|
|
||||||
//第 2-3 位 工作温度状态 “0”-过高;“1”-温度报警;“2”-未知;“3”-正常。
|
|
||||||
//其他位保留 注:保留位全部为1
|
|
||||||
Fun4 uint16 //第 20-21 字节(处理器板)
|
|
||||||
|
|
||||||
FreeMsg []byte //22~125 空闲数据 全填 00H
|
|
||||||
RespTime byte //响应时间 0~150,其他非法,单位0.1ms
|
|
||||||
VobcLifeNum uint32 //VOBC 周期号 1~FFFFFFFF,0 不使用。
|
|
||||||
}
|
|
||||||
|
|
||||||
func (b *BtmVobcMsgFree) Encode() []byte {
|
|
||||||
data := make([]byte, 0)
|
|
||||||
buf := bytes.NewBuffer(data)
|
|
||||||
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(FREE_MESSAGE_TYPE))
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(0x87))
|
|
||||||
|
|
||||||
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, b.MsgSerial)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.BtmStatus)
|
|
||||||
//binary.Write(buf, binary.BigEndian, b.WorkTemperature)
|
|
||||||
binary.Write(buf, binary.BigEndian, byte(35))
|
|
||||||
binary.Write(buf, binary.BigEndian, yuliu3)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.Fun1)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.Fun2)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.Fun3)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.Fun4)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.FreeMsg)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.RespTime)
|
|
||||||
binary.Write(buf, binary.BigEndian, b.VobcLifeNum)
|
|
||||||
|
|
||||||
return baseEncode(buf.Bytes())
|
|
||||||
}
|
|
283
third_party/message/btm_vobc_translate_fffe.go
vendored
283
third_party/message/btm_vobc_translate_fffe.go
vendored
@ -1,283 +0,0 @@
|
|||||||
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
|
|
||||||
}
|
|
51
third_party/message/can_atp_req.go
vendored
51
third_party/message/can_atp_req.go
vendored
@ -1,8 +1,6 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"strings"
|
"strings"
|
||||||
@ -70,14 +68,6 @@ type AtpRequestFrame struct {
|
|||||||
Crc16 uint16
|
Crc16 uint16
|
||||||
//解码时CRC16校验结果,true-校验通过
|
//解码时CRC16校验结果,true-校验通过
|
||||||
Crc16CheckOk bool
|
Crc16CheckOk bool
|
||||||
//IsTrainPcSim bool
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *AtpRequestFrame) IsResend() bool {
|
|
||||||
if f.ResendRequest == 2 {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewAtpRequestFrame 创建ATP查询帧
|
// NewAtpRequestFrame 创建ATP查询帧
|
||||||
@ -99,44 +89,6 @@ func (f *AtpRequestFrame) String() string {
|
|||||||
sb.WriteString(fmt.Sprintf(",Crc16CheckOk = %t", f.Crc16CheckOk))
|
sb.WriteString(fmt.Sprintf(",Crc16CheckOk = %t", f.Crc16CheckOk))
|
||||||
return sb.String()
|
return sb.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *AtpRequestFrame) Decode2(cf *BtmHeadFrame) bool {
|
|
||||||
f.FId = cf.CanId
|
|
||||||
buf := bytes.NewBuffer(cf.CanData)
|
|
||||||
if d, err := buf.ReadByte(); err == nil {
|
|
||||||
f.Speed = uint16(d << 4)
|
|
||||||
rr := byte(0)
|
|
||||||
rr = setBit(rr, 0, GetBit(d, 4))
|
|
||||||
rr = setBit(rr, 1, GetBit(d, 5))
|
|
||||||
f.ResendRequest = rr
|
|
||||||
f.PowerAmplifierControlledByAtp = true
|
|
||||||
f.PowerAmplifierTurnOn = true
|
|
||||||
if rr == 2 {
|
|
||||||
slog.Error(fmt.Sprintf("获取ATP请求帧数据:%b,rr :=%v ,result:%v id1:%v,id2:%v,id3:%v,id4:%v", d, rr, rr, f.FId.ID1, f.FId.ID2, f.FId.ID3, f.FId.ID4))
|
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if d, err := buf.ReadByte(); err == nil {
|
|
||||||
f.Speed |= uint16(d)
|
|
||||||
}
|
|
||||||
var time uint32
|
|
||||||
binary.Read(buf, binary.BigEndian, &time)
|
|
||||||
f.Time = time
|
|
||||||
var crc uint16
|
|
||||||
binary.Read(buf, binary.BigEndian, &crc)
|
|
||||||
f.Crc16 = crc
|
|
||||||
timeArr := make([]byte, 4)
|
|
||||||
binary.BigEndian.PutUint32(timeArr, time)
|
|
||||||
crc16 := Can_Crc16BtmReq(timeArr)
|
|
||||||
f.Crc16CheckOk = f.Crc16 == crc16
|
|
||||||
if !f.Crc16CheckOk {
|
|
||||||
slog.Debug("解码AtpRequestFrame,CRC16校验未通过!!")
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
|
|
||||||
}
|
|
||||||
func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
|
func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
|
||||||
f.FId = cf.CanId
|
f.FId = cf.CanId
|
||||||
//
|
//
|
||||||
@ -193,7 +145,7 @@ func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
|
|||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
crc16 := Can_Crc16BtmReq(timeArr)
|
crc16 := Can_Crc16(timeArr)
|
||||||
t1 := uint32(timeArr[0])
|
t1 := uint32(timeArr[0])
|
||||||
t2 := uint32(timeArr[1])
|
t2 := uint32(timeArr[1])
|
||||||
t3 := uint32(timeArr[2])
|
t3 := uint32(timeArr[2])
|
||||||
@ -226,7 +178,6 @@ func (f *AtpRequestFrame) Decode(cf *CanetFrame) bool {
|
|||||||
}
|
}
|
||||||
func (f *AtpRequestFrame) Encode() *CanetFrame {
|
func (f *AtpRequestFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
|
29
third_party/message/can_btm_data.go
vendored
29
third_party/message/can_btm_data.go
vendored
@ -18,18 +18,17 @@ func NewBtmDataMessageFrame(sn byte, offset byte) *BtmDataMessageFrame {
|
|||||||
}
|
}
|
||||||
func (f *BtmDataMessageFrame) Encode() *CanetFrame {
|
func (f *BtmDataMessageFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
cf.RTR = false
|
cf.RTR = false
|
||||||
//
|
//
|
||||||
writer := NewCanBitsWriter(8)
|
writer := NewCanBitsWriter(8)
|
||||||
|
//
|
||||||
for _, data := range f.Message {
|
for _, data := range f.Message {
|
||||||
writer.AddByte(data)
|
writer.AddByte(data)
|
||||||
}
|
}
|
||||||
cf.CanData = writer.(CanBusData).GetData()
|
cf.CanData = writer.(CanBusData).GetData()
|
||||||
|
|
||||||
//
|
//
|
||||||
return cf
|
return cf
|
||||||
}
|
}
|
||||||
@ -68,31 +67,29 @@ func NewBtmDataMessageTimeAFrame(sn byte) *BtmDataMessageTimeAFrame {
|
|||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x0d, sn),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame {
|
func (f *BtmDataMessageTimeAFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
cf.RTR = false
|
cf.RTR = false
|
||||||
|
//
|
||||||
writer := NewCanBitsWriter(8)
|
writer := NewCanBitsWriter(8)
|
||||||
|
//
|
||||||
byteMsk := uint32(0x00_00_00_ff)
|
byteMsk := uint32(0x00_00_00_ff)
|
||||||
|
//
|
||||||
writer.AddByte(byte((f.TimeA >> 24) & byteMsk))
|
writer.AddByte(byte((f.TimeA >> 24) & byteMsk))
|
||||||
writer.AddByte(byte((f.TimeA >> 16) & byteMsk))
|
writer.AddByte(byte((f.TimeA >> 16) & byteMsk))
|
||||||
writer.AddByte(byte((f.TimeA >> 8) & byteMsk))
|
writer.AddByte(byte((f.TimeA >> 8) & byteMsk))
|
||||||
writer.AddByte(byte(f.TimeA & byteMsk))
|
writer.AddByte(byte(f.TimeA & byteMsk))
|
||||||
|
//
|
||||||
writer.AddByte(byte((f.Crc32A >> 24) & byteMsk))
|
writer.AddByte(byte((f.Crc32A >> 24) & byteMsk))
|
||||||
writer.AddByte(byte((f.Crc32A >> 16) & byteMsk))
|
writer.AddByte(byte((f.Crc32A >> 16) & byteMsk))
|
||||||
writer.AddByte(byte((f.Crc32A >> 8) & byteMsk))
|
writer.AddByte(byte((f.Crc32A >> 8) & byteMsk))
|
||||||
writer.AddByte(byte(f.Crc32A & byteMsk))
|
writer.AddByte(byte(f.Crc32A & byteMsk))
|
||||||
|
//
|
||||||
cf.CanData = writer.(CanBusData).GetData()
|
cf.CanData = writer.(CanBusData).GetData()
|
||||||
|
//
|
||||||
return cf
|
return cf
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -180,21 +177,21 @@ func (f *BtmDataMessageTimeBFrame) Encode() *CanetFrame {
|
|||||||
cf.RTR = false
|
cf.RTR = false
|
||||||
//
|
//
|
||||||
writer := NewCanBitsWriter(8)
|
writer := NewCanBitsWriter(8)
|
||||||
|
//
|
||||||
byteMsk := uint32(0x00_00_00_ff)
|
byteMsk := uint32(0x00_00_00_ff)
|
||||||
|
//
|
||||||
writer.AddByte(byte((f.TimeB >> 24) & byteMsk))
|
writer.AddByte(byte((f.TimeB >> 24) & byteMsk))
|
||||||
writer.AddByte(byte((f.TimeB >> 16) & byteMsk))
|
writer.AddByte(byte((f.TimeB >> 16) & byteMsk))
|
||||||
writer.AddByte(byte((f.TimeB >> 8) & byteMsk))
|
writer.AddByte(byte((f.TimeB >> 8) & byteMsk))
|
||||||
writer.AddByte(byte(f.TimeB & byteMsk))
|
writer.AddByte(byte(f.TimeB & byteMsk))
|
||||||
|
//
|
||||||
writer.AddByte(byte((f.Crc32B >> 24) & byteMsk))
|
writer.AddByte(byte((f.Crc32B >> 24) & byteMsk))
|
||||||
writer.AddByte(byte((f.Crc32B >> 16) & byteMsk))
|
writer.AddByte(byte((f.Crc32B >> 16) & byteMsk))
|
||||||
writer.AddByte(byte((f.Crc32B >> 8) & byteMsk))
|
writer.AddByte(byte((f.Crc32B >> 8) & byteMsk))
|
||||||
writer.AddByte(byte(f.Crc32B & byteMsk))
|
writer.AddByte(byte(f.Crc32B & byteMsk))
|
||||||
|
//
|
||||||
cf.CanData = writer.(CanBusData).GetData()
|
cf.CanData = writer.(CanBusData).GetData()
|
||||||
|
//
|
||||||
return cf
|
return cf
|
||||||
}
|
}
|
||||||
func (f *BtmDataMessageTimeBFrame) Decode(cf *CanetFrame) bool {
|
func (f *BtmDataMessageTimeBFrame) Decode(cf *CanetFrame) bool {
|
||||||
@ -274,10 +271,8 @@ func NewBtmDataMessageEndFrame(sn byte) *BtmDataMessageEndFrame {
|
|||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, 0x80+0x7f, sn),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *BtmDataMessageEndFrame) Encode() *CanetFrame {
|
func (f *BtmDataMessageEndFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
|
106
third_party/message/can_btm_rsp.go
vendored
106
third_party/message/can_btm_rsp.go
vendored
@ -1,115 +1,20 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import "log/slog"
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
|
||||||
"log/slog"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 返回应答器数据帧(数据帧 + timeA+timeB+结束帧)
|
//BTM与ATP之间为双向通信,ATP(主)定时发送请求帧,BTM(从)在未接收到应答器报文时回复状态应答器帧和时间同步帧,在接收到应答器报文时回复所有帧
|
||||||
func CreateBtmAtpDataRspFramesData(statusRsp *BtmHeadFrame, msg []byte, msgPackError, haxBaliseData bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32) ([]byte, bool) {
|
|
||||||
sn := statusRsp.CanId.ID4
|
|
||||||
//应答器整个是16个数据帧,其中报文占13帧,timeA,timeB 占2帧,最后是结束帧
|
|
||||||
//数据
|
|
||||||
dms := make([]*BtmDataMessageAtpFrame, 13)
|
|
||||||
for mr := 0x00; mr <= 0x0c; mr++ {
|
|
||||||
dms[mr] = CreateBtmDataMessageDataAtpFrame(sn, byte(mr))
|
|
||||||
dms[mr].Message = make([]byte, 8) //8字节数组,默认值0
|
|
||||||
//
|
|
||||||
if !msgPackError {
|
|
||||||
mi := mr * 8
|
|
||||||
if mi < len(msg) { //数据帧中有<=8个字节数据
|
|
||||||
if mi+7 < len(msg) {
|
|
||||||
dms[mr].Message = msg[mi : mi+8]
|
|
||||||
} else {
|
|
||||||
for i, d := range msg[mi:] {
|
|
||||||
dms[mr].Message[i] = d
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { //BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF”
|
|
||||||
for c := 0; c < 8; c++ {
|
|
||||||
dms[mr].Message[c] = 0xff
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dtA := createTimeA(sn, DATA_TIME_A_OFFSET, msgTimeA, msgPackError, msg, haxBaliseData)
|
|
||||||
dtB := createTimeA(sn, DATA_TIME_B_OFFSET, msgTimeB, msgPackError, msg, haxBaliseData)
|
|
||||||
dtACf := dtA.Encode()
|
|
||||||
dtBCf := dtB.Encode()
|
|
||||||
|
|
||||||
//结束帧
|
// CreateBtmRspFramesData 数据帧与状态应答帧同时发送给ATP
|
||||||
|
|
||||||
end := createDataAtpEnd(sn, tkTimeB, statusRsp.CanData, msg, dtACf.CanData, dtBCf.CanData)
|
|
||||||
|
|
||||||
endCf := end.Encode()
|
|
||||||
rt := make([]byte, 0) //17*12
|
|
||||||
for _, dmCf := range dms {
|
|
||||||
rt = append(rt, dmCf.Encode().Encode()...)
|
|
||||||
}
|
|
||||||
rt = append(rt, dtACf.Encode()...)
|
|
||||||
rt = append(rt, dtBCf.Encode()...)
|
|
||||||
rt = append(rt, endCf.Encode()...)
|
|
||||||
if len(rt) != 192 {
|
|
||||||
slog.Warn(fmt.Sprintf("len(rt)!=192 实际数据长度:%v", len(rt)))
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
return rt, true
|
|
||||||
}
|
|
||||||
|
|
||||||
func createDataAtpEnd(sn byte, time uint32, statusData, msg, dtAData, dtBData []byte) *BtmDataMessageAtpTimeAndEndFrame {
|
|
||||||
end := BtmDataMessageEndAtpFrame(sn)
|
|
||||||
end.Time = time
|
|
||||||
crc32cData := make([]byte, 0)
|
|
||||||
|
|
||||||
crc32cData = append(crc32cData, statusData...)
|
|
||||||
crc32cData = append(crc32cData, msg...)
|
|
||||||
crc32cData = append(crc32cData, dtAData...)
|
|
||||||
crc32cData = append(crc32cData, dtBData...)
|
|
||||||
crc32cData = binary.BigEndian.AppendUint32(crc32cData, end.Time)
|
|
||||||
end.Crc32 = Can_Crc32(crc32cData)
|
|
||||||
|
|
||||||
return end
|
|
||||||
}
|
|
||||||
|
|
||||||
func createTimeA(sn, offset byte, time uint32, msgPackError bool, msg []byte, hasBaliseData bool) *BtmDataMessageAtpTimeAndEndFrame {
|
|
||||||
tf := CreateBtmDataMessageTimeAtpFrame(sn, offset)
|
|
||||||
tf.Time = time
|
|
||||||
if !msgPackError {
|
|
||||||
var crcData []byte
|
|
||||||
crcData = append(crcData, msg...)
|
|
||||||
crcData = binary.BigEndian.AppendUint32(crcData, time)
|
|
||||||
if !hasBaliseData {
|
|
||||||
tf.Crc32 = 0
|
|
||||||
} else {
|
|
||||||
if offset == DATA_TIME_A_OFFSET {
|
|
||||||
tf.Crc32 = Can_Crc32A(crcData) //CRC32A的校验范围是:报文+时间戳B
|
|
||||||
|
|
||||||
} else {
|
|
||||||
tf.Crc32 = Can_Crc32B(crcData) //CRC32B的校验范围是:报文+时间戳B
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else { //BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF”
|
|
||||||
tf.Crc32 = 0xff_ff_ff_ff
|
|
||||||
}
|
|
||||||
return tf
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateBtmRspFramesData BTM与ATP之间为双向通信,ATP(主)定时发送请求帧,BTM(从)在未接收到应答器报文时回复状态应答器帧和时间同步帧,在接收到应答器报文时回复所有帧
|
|
||||||
//
|
|
||||||
// 数据帧与状态应答帧同时发送给ATP
|
|
||||||
//
|
|
||||||
// 共17帧,17X12个字节,每个帧12字节
|
// 共17帧,17X12个字节,每个帧12字节
|
||||||
// msg - 应答器报文
|
// msg - 应答器报文
|
||||||
// msgPackError - true BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF”
|
// msgPackError - true BTM解包发生错误,则数据帧及CRC32A/B全填“0xFF”
|
||||||
func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32) ([]byte, bool) {
|
func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackError bool, msgTimeA uint32, msgTimeB uint32, tkTimeB uint32) ([]byte, bool) {
|
||||||
/* if len(msg) > 104 { //数据帧最多存储13*8个字节
|
if len(msg) > 104 { //数据帧最多存储13*8个字节
|
||||||
return nil, false
|
return nil, false
|
||||||
}*/
|
}
|
||||||
//最近一次ATP查询请求序列号
|
//最近一次ATP查询请求序列号
|
||||||
sn := statusRsp.FId.ID4
|
sn := statusRsp.FId.ID4
|
||||||
//13个BtmDataMessageFrame [0x00,0x0c]
|
//13个BtmDataMessageFrame [0x00,0x0c]
|
||||||
//数据
|
|
||||||
dms := make([]*BtmDataMessageFrame, 13)
|
dms := make([]*BtmDataMessageFrame, 13)
|
||||||
for mr := 0x00; mr <= 0x0c; mr++ {
|
for mr := 0x00; mr <= 0x0c; mr++ {
|
||||||
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr))
|
dms[mr] = NewBtmDataMessageFrame(sn, byte(mr))
|
||||||
@ -191,6 +96,5 @@ func CreateBtmRspFramesData(statusRsp *BtmStatusRspFrame, msg []byte, msgPackErr
|
|||||||
slog.Warn("len(rt)!=221")
|
slog.Warn("len(rt)!=221")
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
|
|
||||||
return rt, true
|
return rt, true
|
||||||
}
|
}
|
||||||
|
31
third_party/message/can_btm_status_rsp.go
vendored
31
third_party/message/can_btm_status_rsp.go
vendored
@ -1,7 +1,6 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -33,8 +32,6 @@ type BtmStatusRspFrame struct {
|
|||||||
func NewBtmStatusRspFrame(sn byte) *BtmStatusRspFrame {
|
func NewBtmStatusRspFrame(sn byte) *BtmStatusRspFrame {
|
||||||
return &BtmStatusRspFrame{
|
return &BtmStatusRspFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_STATUS_RSP, sn),
|
||||||
//FId: *NewCanFrameId(0x00, 0x00, 0x05, sn),
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
|
func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
|
||||||
@ -114,33 +111,6 @@ func (f *BtmStatusRspFrame) Decode(cf *CanetFrame) bool {
|
|||||||
//
|
//
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *BtmStatusRspFrame) EncodeBtmAtp() *BtmHeadFrame {
|
|
||||||
cf := &BtmHeadFrame{}
|
|
||||||
cf.CanId = f.FId
|
|
||||||
cf.CanLen = 8
|
|
||||||
data := make([]byte, 0)
|
|
||||||
data = append(data, f.Dsn)
|
|
||||||
data = append(data, f.BaliseCounter)
|
|
||||||
data = append(data, f.MessageCounter)
|
|
||||||
var state byte = 0
|
|
||||||
if f.PowerAmplifierOn {
|
|
||||||
state = setBit(state, 7, 1)
|
|
||||||
}
|
|
||||||
if f.AtpReqCrcCheckWrong {
|
|
||||||
state = setBit(state, 6, 1)
|
|
||||||
}
|
|
||||||
if f.PowerAmplifierFailure {
|
|
||||||
state = setBit(state, 5, 1)
|
|
||||||
}
|
|
||||||
if f.AntennaFault {
|
|
||||||
state = setBit(state, 4, 1)
|
|
||||||
}
|
|
||||||
data = append(data, state)
|
|
||||||
data = binary.BigEndian.AppendUint32(data, f.TkTimeA)
|
|
||||||
cf.CanData = data
|
|
||||||
return cf
|
|
||||||
}
|
|
||||||
func (f *BtmStatusRspFrame) Encode() *CanetFrame {
|
func (f *BtmStatusRspFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
@ -152,7 +122,6 @@ func (f *BtmStatusRspFrame) Encode() *CanetFrame {
|
|||||||
writer.AddByte(f.Dsn)
|
writer.AddByte(f.Dsn)
|
||||||
writer.AddByte(f.BaliseCounter)
|
writer.AddByte(f.BaliseCounter)
|
||||||
writer.AddByte(f.MessageCounter)
|
writer.AddByte(f.MessageCounter)
|
||||||
|
|
||||||
//
|
//
|
||||||
if f.PowerAmplifierOn {
|
if f.PowerAmplifierOn {
|
||||||
writer.AddBits(1, 1)
|
writer.AddBits(1, 1)
|
||||||
|
16
third_party/message/can_btm_time_sync_rsp.go
vendored
16
third_party/message/can_btm_time_sync_rsp.go
vendored
@ -1,7 +1,6 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@ -21,8 +20,6 @@ type BtmTimeSyncCheckFrame struct {
|
|||||||
func NewBtmTimeSyncCheckFrame(sn byte) *BtmTimeSyncCheckFrame {
|
func NewBtmTimeSyncCheckFrame(sn byte) *BtmTimeSyncCheckFrame {
|
||||||
return &BtmTimeSyncCheckFrame{
|
return &BtmTimeSyncCheckFrame{
|
||||||
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn),
|
FId: *NewCanFrameId(CAN_ADDR_RSP_ATP, CAN_ADDR_RSP_BTM, CAN_FRAME_TIME_SYNC_RSP, sn),
|
||||||
//FId: *NewCanFrameId(0x00, 0x00, 0x35, sn),
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -77,21 +74,8 @@ func (f *BtmTimeSyncCheckFrame) Decode(cf *CanetFrame) bool {
|
|||||||
//
|
//
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *BtmTimeSyncCheckFrame) EncodeBtmAtp() *BtmHeadFrame {
|
|
||||||
cf := &BtmHeadFrame{}
|
|
||||||
cf.CanId = f.FId
|
|
||||||
cf.CanLen = 8
|
|
||||||
data := make([]byte, 0)
|
|
||||||
data = binary.BigEndian.AppendUint32(data, f.T2)
|
|
||||||
data = binary.BigEndian.AppendUint32(data, f.T3)
|
|
||||||
cf.CanData = data
|
|
||||||
|
|
||||||
return cf
|
|
||||||
}
|
|
||||||
func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame {
|
func (f *BtmTimeSyncCheckFrame) Encode() *CanetFrame {
|
||||||
cf := &CanetFrame{}
|
cf := &CanetFrame{}
|
||||||
|
|
||||||
cf.CanId = f.FId
|
cf.CanId = f.FId
|
||||||
cf.CanLen = 8
|
cf.CanLen = 8
|
||||||
cf.FF = true
|
cf.FF = true
|
||||||
|
66
third_party/message/can_bus.go
vendored
66
third_party/message/can_bus.go
vendored
@ -1,8 +1,6 @@
|
|||||||
package message
|
package message
|
||||||
|
|
||||||
import (
|
import "github.com/snksoft/crc"
|
||||||
"github.com/snksoft/crc"
|
|
||||||
)
|
|
||||||
|
|
||||||
/////////////////////CAN串行总线 bit 流处理 ////////////////////////
|
/////////////////////CAN串行总线 bit 流处理 ////////////////////////
|
||||||
|
|
||||||
@ -201,53 +199,47 @@ const (
|
|||||||
CAN_BITS_LEN8 = byte(0b1111_1111)
|
CAN_BITS_LEN8 = byte(0b1111_1111)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
///////////////////// CRC ////////////////////////
|
||||||
|
|
||||||
|
// const (
|
||||||
|
// CAN_CRC16_ATPREQ = 0x11021
|
||||||
|
// CAN_CRC32 = 0x04C11DB7
|
||||||
|
// )
|
||||||
|
|
||||||
var (
|
var (
|
||||||
CAN_CRC16 = crc.CCITT
|
CAN_CRC16 = crc.CCITT
|
||||||
CAN_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x4A503DF1, Init: 0x00FF0000, ReflectIn: false, ReflectOut: false, FinalXor: 0x000000}
|
CAN_CRC32 = &crc.Parameters{Width: 32, Polynomial: 0x4A503DF1, Init: 0x00FF0000, ReflectIn: true, ReflectOut: true, FinalXor: 0xFFFFFFFF}
|
||||||
ATP_TIMEA = crc.CRC32
|
|
||||||
ATP_TIMEB = crc.Castagnoli
|
|
||||||
ATP_REQ = crc.XMODEM
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func Can_Crc16(data []byte) uint16 {
|
func Can_Crc16(data []byte) uint16 {
|
||||||
return uint16(crc.CalculateCRC(CAN_CRC16, data))
|
return uint16(crc.CalculateCRC(CAN_CRC16, data))
|
||||||
}
|
}
|
||||||
func Can_Crc16BtmReq(data []byte) uint16 {
|
|
||||||
return uint16(crc.CalculateCRC(ATP_REQ, data))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Can_Crc32(data []byte) uint32 {
|
func Can_Crc32(data []byte) uint32 {
|
||||||
return uint32(crc.CalculateCRC(CAN_CRC32, data))
|
return uint32(crc.CalculateCRC(CAN_CRC32, data))
|
||||||
}
|
}
|
||||||
func Can_Crc32A(data []byte) uint32 {
|
|
||||||
return uint32(crc.CalculateCRC(ATP_TIMEA, data))
|
|
||||||
}
|
|
||||||
func Can_Crc32B(data []byte) uint32 {
|
|
||||||
return uint32(crc.CalculateCRC(ATP_TIMEB, data))
|
|
||||||
}
|
|
||||||
|
|
||||||
//var (
|
// var (
|
||||||
// crc16AtpReqTable []uint32 = nil
|
// crc16AtpReqTable []uint32 = nil
|
||||||
// crc32CanTable []uint32 = nil
|
// crc32CanTable []uint32 = nil
|
||||||
//)
|
// )
|
||||||
|
|
||||||
// func CreateCanCrcTable() {
|
// func CreateCanCrcTable() {
|
||||||
// if crc16AtpReqTable == nil {
|
// if crc16AtpReqTable == nil {
|
||||||
// crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false)
|
// crc16AtpReqTable = CreateCrcTable(CAN_CRC16_ATPREQ, 16, false)
|
||||||
// }
|
// }
|
||||||
// if crc32CanTable == nil {
|
// if crc32CanTable == nil {
|
||||||
// crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false)
|
// crc32CanTable = CreateCrcTable(CAN_CRC32, 32, false)
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
//
|
// func calculateAtpReqCrc16(data []byte) uint16 {
|
||||||
// func calculateAtpReqCrc16(data []byte) uint16 {
|
// crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable)
|
||||||
// crc := CrcTableBased(data, 16, 0, false, false, 0, crc16AtpReqTable)
|
// return uint16(crc)
|
||||||
// return uint16(crc)
|
// }
|
||||||
// }
|
// func calculateCanCrc32(data []byte) uint32 {
|
||||||
//func calculateCanCrc32(data []byte) uint32 {
|
// crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable)
|
||||||
// crc := CrcTableBased(data, 32, 0xFF_FF_FF_FF, false, false, 0, crc32CanTable)
|
// return crc
|
||||||
// return crc
|
// }
|
||||||
//}
|
|
||||||
|
|
||||||
// // CRC32A的校验范围是:报文+时间戳A
|
// // CRC32A的校验范围是:报文+时间戳A
|
||||||
// func calculateDataRspCrc32A(data []byte) uint32 {
|
// func calculateDataRspCrc32A(data []byte) uint32 {
|
||||||
|
9
third_party/message/can_net.go
vendored
9
third_party/message/can_net.go
vendored
@ -13,7 +13,6 @@ type CanetFrame struct {
|
|||||||
CanLen byte //CAN帧数据长度[0,8],CanData中有效数据字节数
|
CanLen byte //CAN帧数据长度[0,8],CanData中有效数据字节数
|
||||||
CanId CanFrameId //CAN帧ID
|
CanId CanFrameId //CAN帧ID
|
||||||
CanData []byte //CAN帧数据,8字节
|
CanData []byte //CAN帧数据,8字节
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewCanetFrame(buf []byte) *CanetFrame {
|
func NewCanetFrame(buf []byte) *CanetFrame {
|
||||||
@ -21,9 +20,8 @@ func NewCanetFrame(buf []byte) *CanetFrame {
|
|||||||
cf.Decode(buf)
|
cf.Decode(buf)
|
||||||
return cf
|
return cf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *CanetFrame) Encode() []byte {
|
func (p *CanetFrame) Encode() []byte {
|
||||||
buf := make([]byte, 0)
|
buf := make([]byte, 0, 13)
|
||||||
//canet200帧信息
|
//canet200帧信息
|
||||||
b1 := byte(0x00)
|
b1 := byte(0x00)
|
||||||
if p.FF {
|
if p.FF {
|
||||||
@ -39,7 +37,6 @@ func (p *CanetFrame) Encode() []byte {
|
|||||||
buf = append(buf, p.CanId.ID2)
|
buf = append(buf, p.CanId.ID2)
|
||||||
buf = append(buf, p.CanId.ID3)
|
buf = append(buf, p.CanId.ID3)
|
||||||
buf = append(buf, p.CanId.ID4<<3)
|
buf = append(buf, p.CanId.ID4<<3)
|
||||||
|
|
||||||
//CAN 帧数据
|
//CAN 帧数据
|
||||||
if len(p.CanData) != 8 {
|
if len(p.CanData) != 8 {
|
||||||
panic("len(p.CanData)!=8")
|
panic("len(p.CanData)!=8")
|
||||||
@ -47,11 +44,11 @@ func (p *CanetFrame) Encode() []byte {
|
|||||||
buf = append(buf, p.CanData...)
|
buf = append(buf, p.CanData...)
|
||||||
return buf
|
return buf
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *CanetFrame) Decode(buf []byte) {
|
func (p *CanetFrame) Decode(buf []byte) {
|
||||||
if len(buf) != 13 {
|
if len(buf) != 13 {
|
||||||
panic("len(buf)!=13")
|
panic("len(buf)!=13")
|
||||||
}
|
}
|
||||||
|
//
|
||||||
p.FF = buf[0]&0x80 == 0x80
|
p.FF = buf[0]&0x80 == 0x80
|
||||||
p.RTR = buf[0]&0x40 == 0x40
|
p.RTR = buf[0]&0x40 == 0x40
|
||||||
p.CanLen = buf[0] & 0x0f
|
p.CanLen = buf[0] & 0x0f
|
||||||
@ -65,7 +62,7 @@ func (p *CanetFrame) Decode(buf []byte) {
|
|||||||
}
|
}
|
||||||
func (p *CanetFrame) String() string {
|
func (p *CanetFrame) String() string {
|
||||||
sb := strings.Builder{}
|
sb := strings.Builder{}
|
||||||
sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x", p.FF, p.RTR, p.CanLen,
|
sb.WriteString(fmt.Sprintf("CanetFrame FF = %t, RTR = %t, CanLen = %d, ID1 = 0x%0x, ID2 = 0x%0x, ID3 = 0x%0x, ID4 = 0x%0x,", p.FF, p.RTR, p.CanLen,
|
||||||
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
|
p.CanId.ID1, p.CanId.ID2, p.CanId.ID3, p.CanId.ID4))
|
||||||
sb.WriteString("CanData = ")
|
sb.WriteString("CanData = ")
|
||||||
for _, d := range p.CanData {
|
for _, d := range p.CanData {
|
||||||
|
31
third_party/message/dynamics.go
vendored
31
third_party/message/dynamics.go
vendored
@ -3,7 +3,6 @@ package message
|
|||||||
import (
|
import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"math"
|
"math"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DynamicsTurnoutInfo struct {
|
type DynamicsTurnoutInfo struct {
|
||||||
@ -78,15 +77,11 @@ type DynamicsTrainInfo struct {
|
|||||||
//此次计算所使用的半实物消息的生命信号
|
//此次计算所使用的半实物消息的生命信号
|
||||||
VobcLifeSignal uint16
|
VobcLifeSignal uint16
|
||||||
//位移(mm)
|
//位移(mm)
|
||||||
Displacement float32
|
Displacement uint16
|
||||||
TrainActToMax bool
|
|
||||||
TrainActToMin bool
|
|
||||||
UpdateTime int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 解析动力学的列车信息
|
// 解析动力学的列车信息
|
||||||
func (t *DynamicsTrainInfo) Decode(buf []byte) error {
|
func (t *DynamicsTrainInfo) Decode(buf []byte) error {
|
||||||
|
|
||||||
t.LifeSignal = binary.BigEndian.Uint16(buf[0:2])
|
t.LifeSignal = binary.BigEndian.Uint16(buf[0:2])
|
||||||
t.Number = buf[2]
|
t.Number = buf[2]
|
||||||
t.Len = binary.BigEndian.Uint32(buf[3:7])
|
t.Len = binary.BigEndian.Uint32(buf[3:7])
|
||||||
@ -94,19 +89,8 @@ func (t *DynamicsTrainInfo) Decode(buf []byte) error {
|
|||||||
t.LinkOffset = binary.BigEndian.Uint32(buf[8:12])
|
t.LinkOffset = binary.BigEndian.Uint32(buf[8:12])
|
||||||
t.Slope = binary.BigEndian.Uint16(buf[12:14])
|
t.Slope = binary.BigEndian.Uint16(buf[12:14])
|
||||||
b := buf[14]
|
b := buf[14]
|
||||||
t.UpSlope = IsTrueForByte(GetBit(b, 7))
|
t.UpSlope = (b & (1 << 7)) != 0
|
||||||
t.Up = IsTrueForByte(GetBit(b, 6))
|
t.Up = (b & (1 << 6)) != 0
|
||||||
t.TrainActToMax = IsTrueForByte(GetBit(b, 4))
|
|
||||||
t.TrainActToMin = IsTrueForByte(GetBit(b, 5))
|
|
||||||
|
|
||||||
//t.UpSlope = (b & (1 << 7)) != 0
|
|
||||||
//t.Up = (b & (1 << 6)) != 0
|
|
||||||
//t.TrainActToMax = (b & (1 << 5)) != 0
|
|
||||||
//t.TrainActToMin = (b & (1 << 4)) != 0
|
|
||||||
|
|
||||||
//t.TrainActToMax = (b & (1 << 4)) != 0
|
|
||||||
//t.TrainActToMin = (b & (1 << 5)) != 0
|
|
||||||
|
|
||||||
t.TotalResistance = int32(binary.BigEndian.Uint32(buf[16:20]))
|
t.TotalResistance = int32(binary.BigEndian.Uint32(buf[16:20]))
|
||||||
t.AirResistance = int32(binary.BigEndian.Uint32(buf[20:24]))
|
t.AirResistance = int32(binary.BigEndian.Uint32(buf[20:24]))
|
||||||
t.SlopeResistance = int32(binary.BigEndian.Uint32(buf[24:28]))
|
t.SlopeResistance = int32(binary.BigEndian.Uint32(buf[24:28]))
|
||||||
@ -120,13 +104,6 @@ func (t *DynamicsTrainInfo) Decode(buf []byte) error {
|
|||||||
t.TailRadarSpeed = math.Float32frombits(binary.BigEndian.Uint32(buf[56:60]))
|
t.TailRadarSpeed = math.Float32frombits(binary.BigEndian.Uint32(buf[56:60]))
|
||||||
t.Acceleration = math.Float32frombits(binary.BigEndian.Uint32(buf[60:64]))
|
t.Acceleration = math.Float32frombits(binary.BigEndian.Uint32(buf[60:64]))
|
||||||
t.VobcLifeSignal = binary.BigEndian.Uint16(buf[64:66])
|
t.VobcLifeSignal = binary.BigEndian.Uint16(buf[64:66])
|
||||||
|
t.Displacement = binary.BigEndian.Uint16(buf[66:68])
|
||||||
//tt := binary.BigEndian.Uint16(buf[66:68])
|
|
||||||
//t.Displacement = float32(tt)
|
|
||||||
|
|
||||||
dirBin := binary.BigEndian.Uint32(buf[66:70])
|
|
||||||
t.Displacement = math.Float32frombits(dirBin)
|
|
||||||
|
|
||||||
t.UpdateTime = time.Now().UnixMilli()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user