[补充]12号线联锁通信应答器数据解析;

[修改]联锁配置中的车站编号不再改为车站uid
This commit is contained in:
thesai 2024-08-08 13:23:25 +08:00
parent 2d38a7bd63
commit f1efd5a2f2
18 changed files with 104 additions and 111 deletions

View File

@ -48,13 +48,13 @@ func InitSimulationRouter(api *gin.RouterGroup, authMiddleware *jwt.GinJWTMiddle
authed.GET("/:id/getMapKilometerRange", getMapKilometerRange) authed.GET("/:id/getMapKilometerRange", getMapKilometerRange)
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("/balisecodec/position/modify", balisePositionModify)
authed.PUT("/balise/position/reset", balisePositionReset) authed.PUT("/balisecodec/position/reset", balisePositionReset)
authed.PUT("/balise/telegram/modify", baliseTelegramModify) authed.PUT("/balisecodec/telegram/modify", baliseTelegramModify)
authed.PUT("/balise/telegram/reset", baliseTelegramReset) authed.PUT("/balisecodec/telegram/reset", baliseTelegramReset)
authed.PUT("/balise/telegram/stop", baliseTelegramStop) authed.PUT("/balisecodec/telegram/stop", baliseTelegramStop)
authed.PUT("/balise/telegram/send", baliseTelegramSend) authed.PUT("/balisecodec/telegram/send", baliseTelegramSend)
authed.PUT("/balise/reset", baliseReset) authed.PUT("/balisecodec/reset", baliseReset)
authed.PUT("/ckm/operation", ckmOperation) authed.PUT("/ckm/operation", ckmOperation)
authed.PUT("/xcj/operation", xcjOperation) authed.PUT("/xcj/operation", xcjOperation)
//authed.POST("/bypass/operation", bypassBtnOrKeyOperation) //authed.POST("/bypass/operation", bypassBtnOrKeyOperation)
@ -750,7 +750,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/balise/position/modify [put] // @Router /api/v1/simulation/balisecodec/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 {
@ -779,7 +779,7 @@ 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/balise/position/reset [put] // @Router /api/v1/simulation/balisecodec/position/reset [put]
func balisePositionReset(c *gin.Context) { func balisePositionReset(c *gin.Context) {
req := &dto.BaliseReqDto{} req := &dto.BaliseReqDto{}
if err := c.ShouldBind(&req); err != nil { if err := c.ShouldBind(&req); err != nil {
@ -808,7 +808,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/balise/telegram/modify [put] // @Router /api/v1/simulation/balisecodec/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 {
@ -837,7 +837,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/balise/telegram/reset [put] // @Router /api/v1/simulation/balisecodec/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 {
@ -866,7 +866,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/balise/telegram/stop [put] // @Router /api/v1/simulation/balisecodec/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 {
@ -895,7 +895,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/balise/telegram/send [put] // @Router /api/v1/simulation/balisecodec/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 {
@ -924,7 +924,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/balise/reset [put] // @Router /api/v1/simulation/balisecodec/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 {

View File

@ -3263,7 +3263,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/simulation/balise/position/modify": { "/api/v1/simulation/balisecodec/position/modify": {
"put": { "put": {
"security": [ "security": [
{ {
@ -3312,7 +3312,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/simulation/balise/position/reset": { "/api/v1/simulation/balisecodec/position/reset": {
"put": { "put": {
"security": [ "security": [
{ {
@ -3361,7 +3361,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/simulation/balise/reset": { "/api/v1/simulation/balisecodec/reset": {
"put": { "put": {
"security": [ "security": [
{ {
@ -3408,7 +3408,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/simulation/balise/telegram/modify": { "/api/v1/simulation/balisecodec/telegram/modify": {
"put": { "put": {
"security": [ "security": [
{ {
@ -3457,7 +3457,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/simulation/balise/telegram/reset": { "/api/v1/simulation/balisecodec/telegram/reset": {
"put": { "put": {
"security": [ "security": [
{ {
@ -3506,7 +3506,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/simulation/balise/telegram/send": { "/api/v1/simulation/balisecodec/telegram/send": {
"put": { "put": {
"security": [ "security": [
{ {
@ -3555,7 +3555,7 @@ const docTemplate = `{
} }
} }
}, },
"/api/v1/simulation/balise/telegram/stop": { "/api/v1/simulation/balisecodec/telegram/stop": {
"put": { "put": {
"security": [ "security": [
{ {

View File

@ -5,7 +5,7 @@ import (
"log/slog" "log/slog"
"strconv" "strconv"
"joylink.club/bj-rtsts-server/third_party/balise" "joylink.club/bj-rtsts-server/third_party/balisecodec"
) )
type Transponder struct { type Transponder struct {
@ -34,12 +34,12 @@ func main() {
// count := 0 // count := 0
for _, v := range transponderMap { for _, v := range transponderMap {
// slog.Info("transponder", "name", v.Name, "code", v.Code, "checksum", v.CheckSum, "msg830", v.Msg830, "msg1023", v.Msg1023) // slog.Info("transponder", "name", v.Name, "code", v.Code, "checksum", v.CheckSum, "msg830", v.Msg830, "msg1023", v.Msg1023)
byte104, err := balise.DecodeByteString(v.Msg1023) byte104, err := balisecodec.DecodeByteString(v.Msg1023)
if err != nil { if err != nil {
slog.Error("解码应答器数据失败", "name", v.Name, "code", v.Code, "err", err) slog.Error("解码应答器数据失败", "name", v.Name, "code", v.Code, "err", err)
continue continue
} }
compare104Bytes(byte104, balise.ConvertByteStringToBytes(v.Msg830)) compare104Bytes(byte104, balisecodec.ConvertByteStringToBytes(v.Msg830))
// b1023 := convertToBalise1023(v.Msg1023) // b1023 := convertToBalise1023(v.Msg1023)
// source830 := convertTo830(v.Msg830) // source830 := convertTo830(v.Msg830)
// // replaced830 := replaceFirst10Bits(source830) // // replaced830 := replaceFirst10Bits(source830)
@ -197,7 +197,7 @@ func revertFirst10Bits(b []byte) []byte {
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位MSB的无符号整数数组 // 将830位的二进制数组以10位为单位组成一个左边为最高有效位MSB的无符号整数数组
bits := make([]uint16, 83) bits := make([]uint16, 83)
for i := 0; i < 83; i++ { for i := 0; i < 83; i++ {
bits[i] = uint16(balise.ToValLeftMsb(b[i*10 : i*10+10])) bits[i] = uint16(balisecodec.ToValLeftMsb(b[i*10 : i*10+10]))
// 打印输出 // 打印输出
for j := 0; j < 10; j++ { for j := 0; j < 10; j++ {
fmt.Printf("%01b", b[i*10+j]) fmt.Printf("%01b", b[i*10+j])
@ -224,7 +224,7 @@ func revertFirst10Bits(b []byte) []byte {
slog.Info("还原第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0])) slog.Info("还原第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
rbits := make([]byte, 830) rbits := make([]byte, 830)
// 将整个10位数组转换为二进制数组依然是MSB // 将整个10位数组转换为二进制数组依然是MSB
u0bits := balise.ToBitsLeftMsb(int(bits[0]), 10) u0bits := balisecodec.ToBitsLeftMsb(int(bits[0]), 10)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
rbits[i] = u0bits[i] rbits[i] = u0bits[i]
} }
@ -243,7 +243,7 @@ func replaceFirst10Bits(b []byte) []byte {
// 将830位的二进制数组以10位为单位组成一个左边为最高有效位MSB的无符号整数数组 // 将830位的二进制数组以10位为单位组成一个左边为最高有效位MSB的无符号整数数组
bits := make([]uint16, 83) bits := make([]uint16, 83)
for i := 0; i < 83; i++ { for i := 0; i < 83; i++ {
bits[i] = uint16(balise.ToValLeftMsb(b[i*10 : i*10+10])) bits[i] = uint16(balisecodec.ToValLeftMsb(b[i*10 : i*10+10]))
// 打印输出 // 打印输出
for j := 0; j < 10; j++ { for j := 0; j < 10; j++ {
fmt.Printf("%01b", b[i*10+j]) fmt.Printf("%01b", b[i*10+j])
@ -264,7 +264,7 @@ func replaceFirst10Bits(b []byte) []byte {
slog.Info("替换第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0])) slog.Info("替换第一个10位值", "sum", sum, "bits[0]", bits[0], "bits[0]b", fmt.Sprintf("%010b", bits[0]))
rbits := make([]byte, 830) rbits := make([]byte, 830)
// 将整个10位数组转换为二进制数组依然是MSB // 将整个10位数组转换为二进制数组依然是MSB
u0bits := balise.ToBitsLeftMsb(int(bits[0]), 10) u0bits := balisecodec.ToBitsLeftMsb(int(bits[0]), 10)
for i := 0; i < 10; i++ { for i := 0; i < 10; i++ {
rbits[i] = u0bits[i] rbits[i] = u0bits[i]
} }
@ -281,7 +281,7 @@ func calculateS(sb []byte) uint32 {
if len(sb) != 12 { if len(sb) != 12 {
panic("invalid length") panic("invalid length")
} }
B := balise.ToValLeftMsb(sb) B := balisecodec.ToValLeftMsb(sb)
const A uint64 = 2801775573 const A uint64 = 2801775573
S := uint32((A * uint64(B)) % (1 << 32)) S := uint32((A * uint64(B)) % (1 << 32))
slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S)) slog.Info("由12位加扰位计算得到整数S", "B", B, "S", S, "Sb", fmt.Sprintf("%032b", S))
@ -338,7 +338,7 @@ func convert830To913(b830 []byte) []byte {
} }
b913 := make([]byte, 913) b913 := make([]byte, 913)
for i := 0; i < 83; i++ { for i := 0; i < 83; i++ {
b11 := balise.To11(b830[i*10 : i*10+10]) b11 := balisecodec.To11(b830[i*10 : i*10+10])
for j := 0; j < 11; j++ { for j := 0; j < 11; j++ {
b913[i*11+j] = b11[j] b913[i*11+j] = b11[j]
} }
@ -352,7 +352,7 @@ func convert913To830(b913 []byte) []byte {
} }
b830 := make([]byte, 830) b830 := make([]byte, 830)
for i := 0; i < 83; i++ { for i := 0; i < 83; i++ {
b10, err := balise.From11(b913[i*11 : i*11+11]) b10, err := balisecodec.From11(b913[i*11 : i*11+11])
if err != nil { if err != nil {
panic(err) panic(err)
} }

3
go.mod
View File

@ -54,7 +54,6 @@ require (
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/efp v0.0.0-20231025114914-d1ff6096ae53 // indirect
github.com/xuri/excelize/v2 v2.8.1 // indirect
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 // 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
@ -107,4 +106,4 @@ require (
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
) )
require github.com/yousifnimah/Cryptx v1.0.1 require github.com/xuri/excelize/v2 v2.8.1

4
go.sum
View File

@ -235,8 +235,6 @@ github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05 h1:qhbILQo1K3mphbwKh1vNm4
github.com/xuri/nfp v0.0.0-20230919160717-d98342af3f05/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ= 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/yousifnimah/Cryptx v1.0.1 h1:oZbB6CjvqOzkmoghsncb3/4sV2As8nqOJCjZPd08Xdw=
github.com/yousifnimah/Cryptx v1.0.1/go.mod h1:vmpiwqtg+fR+KaAisCdz2+6k30jWb+/X7EyUysDKh0U=
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=
go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE= go.uber.org/atomic v1.9.0 h1:ECmE8Bn/WFTYwEW/bpKD3M8VtR/zQVbavAoalC1PYyE=
go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
@ -256,6 +254,8 @@ golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo=
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
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=

@ -1 +1 @@
Subproject commit efa7d1655ed781512c8b0ce56685954fa3cc9903 Subproject commit ae5ee2729ef4024e55b1656e82f917f71ab5183f

View File

@ -1,6 +1,7 @@
package balise package balisecodec
import ( import (
"encoding/hex"
"fmt" "fmt"
"log/slog" "log/slog"
"strconv" "strconv"
@ -57,15 +58,9 @@ func DecodeByteString(msg string) ([]byte, error) {
// 转换字节16进制字符串为字节数组 // 转换字节16进制字符串为字节数组
func ConvertByteStringToBytes(msg string) []byte { func ConvertByteStringToBytes(msg string) []byte {
length := len(msg) bytes, err := hex.DecodeString(msg)
bytes := make([]byte, length/2) if err != nil {
for i := 0; i < length; i += 2 { panic(err)
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))
} }
return bytes return bytes
} }

View File

@ -1,4 +1,4 @@
package balise package balisecodec
import ( import (
"fmt" "fmt"
@ -139,7 +139,7 @@ func init() {
} }
for i, v := range ConvWords { for i, v := range ConvWords {
convWordMap[v] = i convWordMap[v] = i
fmt.Printf("%04o: %d\n", v, i) //fmt.Printf("%04o: %d\n", v, i)
// slog.Info("构建10位到11位转换置换字", "i", i, "v", v) // slog.Info("构建10位到11位转换置换字", "i", i, "v", v)
} }
// 检查:翻转有效字的所有位能形成另一个有效字 // 检查:翻转有效字的所有位能形成另一个有效字

View File

@ -1,10 +1,10 @@
package balise_test package balisecodec_test
import ( import (
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"joylink.club/bj-rtsts-server/third_party/balise" "joylink.club/bj-rtsts-server/third_party/balisecodec"
) )
var by830 = []int{ var by830 = []int{
@ -18,21 +18,21 @@ var by830 = []int{
func TestConvList(t *testing.T) { func TestConvList(t *testing.T) {
// 数量 // 数量
assert.Equal(t, 1024, len(balise.ConvWords)) assert.Equal(t, 1024, len(balisecodec.ConvWords))
// 后面的数比前面大 // 后面的数比前面大
for i := 0; i < 1023; i++ { for i := 0; i < 1023; i++ {
assert.Less(t, balise.ConvWords[i], balise.ConvWords[i+1]) assert.Less(t, balisecodec.ConvWords[i], balisecodec.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(balise.ConvWords[i]) sum_q += int(balisecodec.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(balise.ConvWords[i]) sum_b += int(balisecodec.ConvWords[i])
} }
// 总1024项和 // 总1024项和
assert.Equal(t, 1048064, sum_q+sum_b) assert.Equal(t, 1048064, sum_q+sum_b)
@ -40,5 +40,5 @@ func TestConvList(t *testing.T) {
func TestTo11(t *testing.T) { func TestTo11(t *testing.T) {
b10 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1} b10 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 1}
balise.To11(b10) balisecodec.To11(b10)
} }

View File

@ -1,4 +1,4 @@
package balise package balisecodec
import ( import (
"fmt" "fmt"

View File

@ -1,4 +1,4 @@
package balise package balisecodec
import ( import (
"fmt" "fmt"

View File

@ -109,7 +109,7 @@ func (t *BaliseDetector) detect2(wd *component.WorldData, repo *repository.Repos
} }
if !find { if !find {
balises = append(balises, balise) balises = append(balises, balise)
//slog.Info(fmt.Sprintf("start baliseId:%v,Distance:%v,up:%v", balise.Id(), balise.LinkPosition(), curAntennaRi.Up)) //slog.Info(fmt.Sprintf("start baliseId:%v,Distance:%v,up:%v", balisecodec.Id(), balisecodec.LinkPosition(), curAntennaRi.Up))
} }
} }
for _, balise := range endBalises { for _, balise := range endBalises {
@ -121,7 +121,7 @@ func (t *BaliseDetector) detect2(wd *component.WorldData, repo *repository.Repos
} }
} }
if !find { if !find {
//slog.Info(fmt.Sprintf("end baliseId:%v,Distance:%v,up:%v", balise.Id(), balise.LinkPosition(), curAntennaRi.Up)) //slog.Info(fmt.Sprintf("end baliseId:%v,Distance:%v,up:%v", balisecodec.Id(), balisecodec.LinkPosition(), curAntennaRi.Up))
balises = append(balises, balise) balises = append(balises, balise)
} }
} }

View File

@ -4,7 +4,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"joylink.club/bj-rtsts-server/third_party/balise" "joylink.club/bj-rtsts-server/third_party/balisecodec"
) )
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 balise.ConvWords { // for i, v := range balisecodec.ConvWords {
// fmt.Printf("0%o,", v) // fmt.Printf("0%o,", v)
// if i%10 == 9 { // if i%10 == 9 {
// fmt.Println() // fmt.Println()
// } // }
// } // }
v10 := balise.ToValLeftMsb([]byte{ v10 := balisecodec.ToValLeftMsb([]byte{
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 := balise.ToBitsLeftMsb(1982, 11) bs := balisecodec.ToBitsLeftMsb(1982, 11)
fmt.Println(bs) fmt.Println(bs)
// fmt.Printf("%o\n", balise.ConvWords[511]) // fmt.Printf("%o\n", balisecodec.ConvWords[511])
} }

View File

@ -32,12 +32,12 @@ type serviceContext struct {
client udp.UdpClient //向联锁发送数据的客户端 client udp.UdpClient //向联锁发送数据的客户端
server udp.UdpServer //接收联锁数据的服务端 server udp.UdpServer //接收联锁数据的服务端
sim *memory.VerifySimulation //启动服务所使用的仿真 sim *memory.VerifySimulation //启动服务所使用的仿真
iConfig *config.InterlockConfig //启动服务使用的联锁配置 iConfig config.InterlockConfig //启动服务使用的联锁配置
deviceTable *StationDeviceIndexTable //联锁站的设备ID表key-车站名 deviceTable *StationDeviceIndexTable //联锁站的设备ID表key-车站名
} }
func Start(interlockConfig *config.InterlockConfig, simulation *memory.VerifySimulation) { func Start(interlockConfig config.InterlockConfig, simulation *memory.VerifySimulation) {
if interlockConfig == nil || interlockConfig.Ip == "" || !interlockConfig.Open { if interlockConfig.Ip == "" || !interlockConfig.Open {
return return
} }
mu.Lock() mu.Lock()

View File

@ -5,7 +5,9 @@ import (
"bytes" "bytes"
"context" "context"
"fmt" "fmt"
"joylink.club/bj-rtsts-server/dto/data_proto"
"joylink.club/bj-rtsts-server/sys_error" "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/tcp"
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory" "joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
"joylink.club/rtsssimulation/fi" "joylink.club/rtsssimulation/fi"
@ -51,7 +53,7 @@ var initMutex sync.Mutex
// return interlockMap[c.Code] // return interlockMap[c.Code]
//} //}
func Start(c *config.InterlockConfig, simulation *memory.VerifySimulation, baliseList []*repository.Transponder) { func Start(c config.InterlockConfig, simulation *memory.VerifySimulation, baliseList []*repository.Transponder) {
initMutex.Lock() initMutex.Lock()
defer initMutex.Unlock() defer initMutex.Unlock()
proxy := &interlockProxy{ proxy := &interlockProxy{
@ -59,21 +61,36 @@ func Start(c *config.InterlockConfig, simulation *memory.VerifySimulation, balis
indexBalise: make(map[byte]map[byte]*repository.Transponder), indexBalise: make(map[byte]map[byte]*repository.Transponder),
fromCIBytes: make([]byte, 0, fromCIBytesLen), fromCIBytes: make([]byte, 0, fromCIBytesLen),
} }
for _, balise := range simulation.Repo.TransponderList() { //构建应答器的索引映射
if balise.LeuIndex() == 0 { for _, mapId := range simulation.MapIds {
giType := memory.QueryGiType(mapId)
if giType != data_proto.PictureType_StationLayout {
continue continue
} }
leuIndex := byte(balise.LeuIndex()) uids := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
if proxy.indexBalise[leuIndex] == nil { for _, baliseRelationship := range uids.TransponderIds {
proxy.indexBalise[leuIndex] = make(map[byte]*repository.Transponder) 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.indexBalise[leuIndex][byte(balise.IndexInLeu())] = balise
} }
proxy.Start(simulation) proxy.Start(simulation)
interlockMap[c.Code] = proxy interlockMap[c.Code] = proxy
} }
func Stop(c *config.InterlockConfig) { func Stop(c config.InterlockConfig) {
proxy := interlockMap[c.Code] proxy := interlockMap[c.Code]
if proxy != nil { if proxy != nil {
proxy.Stop() proxy.Stop()
@ -85,7 +102,7 @@ type interlockProxy struct {
simulation *memory.VerifySimulation simulation *memory.VerifySimulation
collectInfoTaskCancel context.CancelFunc collectInfoTaskCancel context.CancelFunc
runConfig *config.InterlockConfig runConfig config.InterlockConfig
// 按索引存储的应答器leu索引-leu内索引 // 按索引存储的应答器leu索引-leu内索引
indexBalise map[byte]map[byte]*repository.Transponder indexBalise map[byte]map[byte]*repository.Transponder
@ -96,7 +113,7 @@ type interlockProxy struct {
} }
func (i *interlockProxy) Start(simulation *memory.VerifySimulation) { func (i *interlockProxy) Start(simulation *memory.VerifySimulation) {
if i.runConfig == nil || i.runConfig.Ip == "" || !i.runConfig.Open { if i.runConfig.Ip == "" || !i.runConfig.Open {
return return
} }
if simulation == nil { if simulation == nil {
@ -112,17 +129,14 @@ func (i *interlockProxy) Start(simulation *memory.VerifySimulation) {
i.simulation = simulation i.simulation = simulation
} }
// 采集电路状态发送间隔,单位ms
const InterlockMessageSendInterval = 300
// 定时发送采集电路状态任务 // 定时发送采集电路状态任务
func (i *interlockProxy) collectInfoStateTask(ctx context.Context) { func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
defer func() { defer func() {
if err := recover(); err != nil { if err := recover(); err != nil {
logger().Error(logTag+"定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack())) logger().Error(logTag+"定时发送采集状态任务异常", "error", err, "stack", string(debug.Stack()))
} }
}() }()
for { for range time.Tick(time.Duration(i.runConfig.Period) * time.Millisecond) {
select { select {
case <-ctx.Done(): case <-ctx.Done():
return return
@ -139,7 +153,6 @@ func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
logger().Info(fmt.Sprintf("向联锁发送继电器数据成功:%x", collectInfoState.Encode())) logger().Info(fmt.Sprintf("向联锁发送继电器数据成功:%x", collectInfoState.Encode()))
} }
} }
time.Sleep(time.Millisecond * InterlockMessageSendInterval)
} }
} }
@ -208,9 +221,18 @@ func (i *interlockProxy) handleFromCiData(n int, data []byte) {
logger().Error(fmt.Sprintf("没有leuIndex[%d]leu内索引[%d]的应答器", datum.leuIndex, datum.index)) logger().Error(fmt.Sprintf("没有leuIndex[%d]leu内索引[%d]的应答器", datum.leuIndex, datum.index))
continue continue
} }
err := fi.BaliseUpdateVariableTelegram(i.simulation.World, balise.Id(), datum.telegram, false) userTelegram, err := balisecodec.Decode(datum.telegram)
if err != nil { if err != nil {
logger().Error(fmt.Sprintf("更新leuIndex[%d]leu内索引[%d]的应答器数据出错:%s", datum.leuIndex, datum.index, err.Error())) 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()))
} }
} }
} }

View File

@ -254,7 +254,7 @@ func baliseTelegramReset(simulation *VerifySimulation, balise *repository.Transp
if err != nil { if err != nil {
return sys_error.New("重置应答器报文失败", err) return sys_error.New("重置应答器报文失败", err)
} }
err = fi.BaliseUpdateVariableTelegram(simulation.World, balise.Id(), []byte{}, false) err = fi.BaliseUpdateVariableTelegram(simulation.World, balise.Id(), []byte{}, []byte{}, false)
if err != nil { if err != nil {
return sys_error.New("重置应答器报文失败", err) return sys_error.New("重置应答器报文失败", err)
} }

View File

@ -399,28 +399,6 @@ func (s *VerifySimulation) GetSemiPhysicalRunConfig() *config.VobcConfig {
return &s.runConfig.Vobc return &s.runConfig.Vobc
} }
// 获取所有联锁配置唯一Code
func (s *VerifySimulation) GetInterlockCodes() []*config.InterlockConfig {
stationMap := make(map[string]string)
for _, station := range s.Repo.StationList() {
stationMap[station.GetCode()] = station.Id()
}
var configs []*config.InterlockConfig
for _, c := range s.runConfig.Interlocks {
if stationMap[c.Code] == "" || !c.Open {
continue
}
configs = append(configs, &config.InterlockConfig{
Code: stationMap[c.Code],
Ip: c.Ip,
RemotePort: c.RemotePort,
Open: c.Open,
Line: c.Line,
})
}
return configs
}
// 处理接到的联锁消息 // 处理接到的联锁消息
func (s *VerifySimulation) HandleInterlockDriverInfo(code string, driveBytes []byte) { func (s *VerifySimulation) HandleInterlockDriverInfo(code string, driveBytes []byte) {
wd := entity.GetWorldData(s.World) wd := entity.GetWorldData(s.World)

View File

@ -122,7 +122,7 @@ func runThirdParty(s *memory.VerifySimulation) error {
// 半实物启动 // 半实物启动
semi_physical_train.Default().Start(s) semi_physical_train.Default().Start(s)
// 联锁启动 // 联锁启动
for _, c := range s.GetInterlockCodes() { for _, c := range s.GetRunConfig().Interlocks {
switch c.Line { switch c.Line {
case "11": case "11":
beijing11.Start(c, s) beijing11.Start(c, s)
@ -154,11 +154,10 @@ func runThirdParty(s *memory.VerifySimulation) error {
// 停止仿真 // 停止仿真
func stopThirdParty(s *memory.VerifySimulation) { func stopThirdParty(s *memory.VerifySimulation) {
// 停止半实物 // 停止半实物
semi_physical_train.Default().Stop() semi_physical_train.Default().Stop()
// 联锁启动 // 联锁启动
for _, c := range s.GetInterlockCodes() { for _, c := range s.GetRunConfig().Interlocks {
switch c.Line { switch c.Line {
case "11": case "11":
beijing11.Stop(c.Code) beijing11.Stop(c.Code)