Compare commits
12 Commits
fc6b51cc24
...
272274a5c4
Author | SHA1 | Date | |
---|---|---|---|
|
272274a5c4 | ||
85d5781122 | |||
3da710891e | |||
d706a42b1b | |||
f1efd5a2f2 | |||
2d38a7bd63 | |||
844560ae1e | |||
5fa5345981 | |||
|
58ebf3842a | ||
|
6a0a47083f | ||
|
bedb2bf413 | ||
|
961b9dc5ff |
@ -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)
|
||||||
@ -246,8 +246,9 @@ func addTrain(c *gin.Context) {
|
|||||||
Id: fmt.Sprintf("%v", req.TrainId),
|
Id: fmt.Sprintf("%v", req.TrainId),
|
||||||
HeadDeviceId: req.Id,
|
HeadDeviceId: req.Id,
|
||||||
HeadOffset: req.HeadOffset,
|
HeadOffset: req.HeadOffset,
|
||||||
DevicePort: req.DevicePort,
|
//HeadOffset: 93211,
|
||||||
TrainRunUp: req.RunDirection,
|
DevicePort: req.DevicePort,
|
||||||
|
TrainRunUp: req.RunDirection,
|
||||||
//RunDirection: req.RunDirection,
|
//RunDirection: req.RunDirection,
|
||||||
TrainLength: req.TrainLength,
|
TrainLength: req.TrainLength,
|
||||||
WheelDiameter: req.WheelDiameter,
|
WheelDiameter: req.WheelDiameter,
|
||||||
@ -749,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 {
|
||||||
@ -778,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 {
|
||||||
@ -807,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 {
|
||||||
@ -836,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 {
|
||||||
@ -865,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 {
|
||||||
@ -894,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 {
|
||||||
@ -923,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 {
|
||||||
|
@ -1,7 +1,6 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/binary"
|
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
@ -79,11 +78,6 @@ func initTrainPc() {
|
|||||||
//sendBtm()
|
//sendBtm()
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
|
||||||
e1 = 0x1e
|
|
||||||
aa = 0x17
|
|
||||||
)
|
|
||||||
|
|
||||||
func createOrRemoveTrain() {
|
func createOrRemoveTrain() {
|
||||||
msgs := make([]*message.TrainPcSimBaseMessage, 0)
|
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{0x00}, Type: message.RECIVE_TRAIN_CREATE_REMOVE})
|
||||||
@ -146,45 +140,10 @@ func circleSendTrainMockData() {
|
|||||||
time.Sleep(time.Millisecond * 1000)
|
time.Sleep(time.Millisecond * 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func sendBtm() {
|
|
||||||
source := "eb3305d543eb3211000005ea000000010000082b7989eb321100003573000000010000257ce38eeb3211000005d90000000100002731a483eb3211000005c8000000010000322d6b8aeb32110000356200000001000033976df1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1"
|
|
||||||
data, _ := hex.DecodeString(source)
|
|
||||||
trainpcClient.Send(data)
|
|
||||||
}
|
|
||||||
func circleSendTrainSpeedPlace() {
|
|
||||||
for {
|
|
||||||
data := make([]byte, 0)
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(2))
|
|
||||||
//data = binary.BigEndian.AppendUint16(data, uint16(1))
|
|
||||||
//data = binary.BigEndian.AppendUint16(data, uint16(0))
|
|
||||||
//data = binary.BigEndian.AppendUint16(data, uint16(0))
|
|
||||||
//data = binary.BigEndian.AppendUint32(data, uint32(940))
|
|
||||||
//data = binary.BigEndian.AppendUint32(data, uint32(940))
|
|
||||||
data = binary.BigEndian.AppendUint32(data, uint32(0))
|
|
||||||
data = binary.BigEndian.AppendUint32(data, uint32(0))
|
|
||||||
data = binary.BigEndian.AppendUint32(data, uint32(940))
|
|
||||||
data = binary.BigEndian.AppendUint32(data, uint32(940))
|
|
||||||
now := time.Now().UTC()
|
|
||||||
sec := now.Unix()
|
|
||||||
data = binary.BigEndian.AppendUint32(data, uint32(27797))
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(now.UnixMilli()-sec*1000))
|
|
||||||
ss := "eb011d000200000000000000000000000000000000000017af0299ffff"
|
|
||||||
data, _ = hex.DecodeString(ss)
|
|
||||||
//bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
|
|
||||||
//dataCode := bm.Encode()
|
|
||||||
//fmt.Println(fmt.Sprintf("发送列车位置信息:%v", hex.EncodeToString(data)))
|
|
||||||
trainpcClient.Send(data)
|
|
||||||
//dd := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{3, 0}}
|
|
||||||
//trainpcClient.Send(dd.Encode())
|
|
||||||
time.Sleep(time.Millisecond * 80)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func trainPcDataHandle(n int, data []byte) {
|
func trainPcDataHandle(n int, data []byte) {
|
||||||
hexData := hex.EncodeToString(data[:n])
|
hexData := hex.EncodeToString(data[:n])
|
||||||
slog.Info(fmt.Sprintf("列车pc仿真接口长度:%v,实际长度:%v,接受数据:%v", len(data), n, hexData))
|
slog.Info(fmt.Sprintf("列车pc仿真接口长度:%v,实际长度:%v,接受数据:%v", len(data), n, hexData))
|
||||||
//source := "eb3211000005ea000000010000082b7989eb321100003573000000010000257ce38eeb3211000005d90000000100002731a483eb3211000005c8000000010000322d6b8aeb32110000356200000001000033976df1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1eb3179000005fb000000010000060390007f8182fd8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc02edeb31790000358400000001000007b990007f819ac20b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcefe4eb31790000070d00000001000008f690007f8183868b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc72a9eb3179000035950000000100000a3390007f819aca8b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc5487eb31790000071e000000010000279b90007f81838f0b10183280003ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffcddd1"
|
|
||||||
//data2, _ := hex.DecodeString(source)
|
|
||||||
//trainpcClient.Send(data2)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
func trainPcConnErr(err error) {
|
func trainPcConnErr(err error) {
|
||||||
|
@ -126,6 +126,7 @@ type InterlockConfig struct {
|
|||||||
RemotePort int `json:"remotePort" description:"远端接收采集信息端口"`
|
RemotePort int `json:"remotePort" description:"远端接收采集信息端口"`
|
||||||
Code string `json:"code" description:"所属集中站"`
|
Code string `json:"code" description:"所属集中站"`
|
||||||
Line string `json:"line" 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配置"`
|
||||||
|
14
docs/docs.go
14
docs/docs.go
@ -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": [
|
||||||
{
|
{
|
||||||
|
@ -3222,8 +3222,8 @@ type Transponder struct {
|
|||||||
FixedTelegram string `protobuf:"bytes,11,opt,name=fixedTelegram,proto3" json:"fixedTelegram,omitempty"` //应答器固定报文
|
FixedTelegram string `protobuf:"bytes,11,opt,name=fixedTelegram,proto3" json:"fixedTelegram,omitempty"` //应答器固定报文
|
||||||
FixedUserTelegram string `protobuf:"bytes,12,opt,name=fixedUserTelegram,proto3" json:"fixedUserTelegram,omitempty"` //应答器固定用户报文
|
FixedUserTelegram string `protobuf:"bytes,12,opt,name=fixedUserTelegram,proto3" json:"fixedUserTelegram,omitempty"` //应答器固定用户报文
|
||||||
OriginalCode string `protobuf:"bytes,13,opt,name=originalCode,proto3" json:"originalCode,omitempty"` //应答器原编号(厂商提供数据编号)
|
OriginalCode string `protobuf:"bytes,13,opt,name=originalCode,proto3" json:"originalCode,omitempty"` //应答器原编号(厂商提供数据编号)
|
||||||
LeuIndex uint32 `protobuf:"varint,14,opt,name=leuIndex,proto3" json:"leuIndex,omitempty"` //LEU索引
|
LeuIndex uint32 `protobuf:"varint,14,opt,name=leuIndex,proto3" json:"leuIndex,omitempty"` //应答器所属LEU的索引
|
||||||
LeuInsideIndex uint32 `protobuf:"varint,15,opt,name=leuInsideIndex,proto3" json:"leuInsideIndex,omitempty"` // LEU内部索引
|
LeuInsideIndex uint32 `protobuf:"varint,15,opt,name=leuInsideIndex,proto3" json:"leuInsideIndex,omitempty"` // 应答器在LEU内部的索引
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *Transponder) Reset() {
|
func (x *Transponder) Reset() {
|
||||||
|
File diff suppressed because it is too large
Load Diff
406
example/balise_1023_830/main.go
Normal file
406
example/balise_1023_830/main.go
Normal file
@ -0,0 +1,406 @@
|
|||||||
|
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()
|
||||||
|
}
|
||||||
|
}
|
156
example/balise_1023_830/read_excel.go
Normal file
156
example/balise_1023_830/read_excel.go
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
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
|
||||||
|
}
|
32
example/ex1/main.go
Normal file
32
example/ex1/main.go
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
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
|
||||||
|
}
|
56
example/lfsr/main.go
Normal file
56
example/lfsr/main.go
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
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)
|
||||||
|
}
|
52
example/test/main.go
Normal file
52
example/test/main.go
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
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
|
||||||
|
}
|
7
go.mod
7
go.mod
@ -46,10 +46,15 @@ require (
|
|||||||
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
|
||||||
@ -101,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
|
||||||
|
17
go.sum
17
go.sum
@ -153,6 +153,8 @@ 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=
|
||||||
@ -164,6 +166,11 @@ 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=
|
||||||
@ -220,10 +227,14 @@ 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/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=
|
||||||
@ -243,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=
|
||||||
|
@ -266,6 +266,7 @@ 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.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||||
|
@ -35,10 +35,10 @@ 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
|
||||||
@ -74,10 +74,10 @@ func NewSfpMs(vs *memory.VerifySimulation, mapId int32) ms_api.MsgTask {
|
|||||||
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,
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 3182e867c12d73bd4c75182459d3b9fae670653c
|
Subproject commit 51702238da69fcf28d7c07ddccfc6e240222456e
|
@ -1 +1 @@
|
|||||||
Subproject commit 0c2a7613104f859e83091d1f6379e6e2fa1990ad
|
Subproject commit a5ebb6869d51969e5887f1dfceaffe8fcdc27312
|
29
third_party/balise/codec.go
vendored
29
third_party/balise/codec.go
vendored
@ -1,29 +0,0 @@
|
|||||||
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("不支持的应答器类型")
|
|
||||||
}
|
|
||||||
}
|
|
178
third_party/balisecodec/codec.go
vendored
Normal file
178
third_party/balisecodec/codec.go
vendored
Normal file
@ -0,0 +1,178 @@
|
|||||||
|
package balisecodec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/hex"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 应答器数据编解码器
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,4 @@
|
|||||||
package balise
|
package balisecodec
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
@ -113,14 +113,83 @@ 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 ToVal(v []int) uint16 {
|
func ToValLeftMsb(v []byte) uint16 {
|
||||||
|
if len(v) > 15 {
|
||||||
|
panic(fmt.Errorf("不支持15位以上"))
|
||||||
|
}
|
||||||
|
val := uint16(0)
|
||||||
|
l := len(v)
|
||||||
|
//elems := make([]string, l)
|
||||||
|
for i := 0; i < l; i++ {
|
||||||
|
//elems[i] = fmt.Sprintf("%d", v[i])
|
||||||
|
if v[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 {
|
if len(v) > 15 {
|
||||||
panic(fmt.Errorf("不支持15位以上"))
|
panic(fmt.Errorf("不支持15位以上"))
|
||||||
}
|
}
|
||||||
@ -128,15 +197,15 @@ func ToVal(v []int) uint16 {
|
|||||||
l := len(v)
|
l := len(v)
|
||||||
for i := 0; i < l; i++ {
|
for i := 0; i < l; i++ {
|
||||||
if v[i] == 1 {
|
if v[i] == 1 {
|
||||||
val += (1 << (l - i - 1))
|
val += (1 << i)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return val
|
return val
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数字转换为bit数组,左边为最高有效位
|
// 数字转换为bit数组,左边为最高有效位
|
||||||
func ToBits(val int, count int) []int {
|
func ToBitsLeftMsb(val int, count int) []byte {
|
||||||
bs := make([]int, count)
|
bs := make([]byte, 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) {
|
||||||
@ -148,26 +217,42 @@ func ToBits(val int, count int) []int {
|
|||||||
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 []int) ([]int, error) {
|
func From11(b11 []byte) ([]byte, error) {
|
||||||
v11 := ToVal(b11)
|
v11 := ToValLeftMsb(b11)
|
||||||
v10, ok := convWordMap[uint16(v11)]
|
v10, ok := convWordMap[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 ToBits(v10, 10), nil
|
return ToBitsLeftMsb(v10, 10), nil
|
||||||
} else {
|
} else {
|
||||||
return nil, fmt.Errorf("错误的11位字")
|
return nil, fmt.Errorf("错误的11位字,word11=%04o", v11)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 10位字转换为11位字
|
// 10位字转换为11位字
|
||||||
func To11(b10 []int) []int {
|
func To11(b10 []byte) []byte {
|
||||||
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 := ToVal(b10)
|
v10 := ToValLeftMsb(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]
|
||||||
return ToBits(int(v11), 11)
|
// 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 ToBitsLeftMsb(int(v11), 11)
|
||||||
}
|
}
|
@ -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,27 +18,27 @@ 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)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestTo11(t *testing.T) {
|
func TestTo11(t *testing.T) {
|
||||||
b10 := []int{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)
|
||||||
}
|
}
|
88
third_party/balisecodec/decode.go
vendored
Normal file
88
third_party/balisecodec/decode.go
vendored
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
package balisecodec
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 将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
Normal file
86
third_party/balisecodec/encode.go
vendored
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
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
|
||||||
|
}
|
63
third_party/can_btm/balise_btm.go
vendored
63
third_party/can_btm/balise_btm.go
vendored
@ -55,33 +55,62 @@ type btmCanetClient struct {
|
|||||||
baliseDetector *BaliseDetector
|
baliseDetector *BaliseDetector
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *btmCanetClient) GetState() state_proto.BTMState {
|
func (s *btmCanetClient) FindNotSendState() (state_proto.BTMState, bool) {
|
||||||
|
s.baliseDetector.eqLock.Lock()
|
||||||
|
defer s.baliseDetector.eqLock.Unlock()
|
||||||
detector := s.baliseDetector
|
detector := s.baliseDetector
|
||||||
|
for _, info := range detector.eq {
|
||||||
|
if info != nil && !info.IsSend {
|
||||||
|
info.IsSend = true
|
||||||
|
return s.getStateFromDeta(info, uint32(detector.baliseCounter), uint32(detector.messageCounter), detector.aboveBalise), true
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return state_proto.BTMState{}, false
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
func (s *btmCanetClient) GetAllData() {
|
||||||
|
detector := s.baliseDetector
|
||||||
|
for _, info := range detector.eq {
|
||||||
|
slog.Info("获取应答器信息 id:%v,是否发送:%v", info.BaliseId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
func (s *btmCanetClient) getStateFromDeta(info *BtmAntennaScanningBaliseInfo, bc, mc uint32, aboveBalise bool) state_proto.BTMState {
|
||||||
var telegram string
|
var telegram string
|
||||||
var tel128 string
|
var tel128 string
|
||||||
info := detector.eq[len(detector.eq)-1]
|
var dis int64
|
||||||
|
var baliseId string
|
||||||
|
|
||||||
if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 {
|
if /*detector.aboveBalise &&*/ info != nil && len(info.telegram) != 0 {
|
||||||
telegram = fmt.Sprintf("%X", info.telegram)
|
telegram = fmt.Sprintf("%X", info.telegram)
|
||||||
tel128 = fmt.Sprintf("%X", info.telegram128)
|
tel128 = fmt.Sprintf("%X", info.telegram128)
|
||||||
|
dis = info.Distance
|
||||||
|
baliseId = info.BaliseId
|
||||||
} else {
|
} else {
|
||||||
telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
|
telegram = strings.Repeat("00", balise_const.UserTelegramByteLen)
|
||||||
tel128 = strings.Repeat("00", balise_const.TelegramByteLen)
|
tel128 = strings.Repeat("00", balise_const.TelegramByteLen)
|
||||||
}
|
}
|
||||||
var dis int64
|
|
||||||
if info != nil {
|
|
||||||
dis = info.Distance
|
|
||||||
}
|
|
||||||
return state_proto.BTMState{
|
return state_proto.BTMState{
|
||||||
|
BaliseId: baliseId,
|
||||||
DataSerialNumber: uint32(s.dsn),
|
DataSerialNumber: uint32(s.dsn),
|
||||||
BaliseCount: uint32(detector.baliseCounter),
|
BaliseCount: bc,
|
||||||
MessageCounter: uint32(detector.messageCounter),
|
MessageCounter: mc,
|
||||||
Telegram: telegram,
|
Telegram: telegram,
|
||||||
Telegram128: tel128,
|
Telegram128: tel128,
|
||||||
Distance: dis,
|
Distance: dis,
|
||||||
AboveBalise: detector.aboveBalise,
|
AboveBalise: aboveBalise,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (s *btmCanetClient) GetState() state_proto.BTMState {
|
||||||
|
detector := s.baliseDetector
|
||||||
|
info := detector.eq[len(detector.eq)-1]
|
||||||
|
return s.getStateFromDeta(info, uint32(detector.baliseCounter), uint32(detector.messageCounter), detector.aboveBalise)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
type BtmClock struct {
|
type BtmClock struct {
|
||||||
BtmTk uint32 //与ATP系统同步的时间ms
|
BtmTk uint32 //与ATP系统同步的时间ms
|
||||||
@ -100,6 +129,8 @@ type BtmCanetClient interface {
|
|||||||
HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state_proto.VobcBtmState, h *TrainHeadPositionInfo)
|
HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state_proto.VobcBtmState, h *TrainHeadPositionInfo)
|
||||||
//获取BTM显示状态 + btm最新的状态
|
//获取BTM显示状态 + btm最新的状态
|
||||||
GetState() state_proto.BTMState
|
GetState() state_proto.BTMState
|
||||||
|
//GetAllData()
|
||||||
|
FindNotSendState() (state_proto.BTMState, bool)
|
||||||
}
|
}
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -121,7 +152,16 @@ func (s *btmCanetClient) HandleTrainHeadPositionInfo(w ecs.World, vobcBtm *state
|
|||||||
//slog.Debug(h.String())
|
//slog.Debug(h.String())
|
||||||
wd := entity.GetWorldData(w)
|
wd := entity.GetWorldData(w)
|
||||||
repo := wd.Repo
|
repo := wd.Repo
|
||||||
s.baliseDetector.detect(wd, repo, h, vobcBtm)
|
|
||||||
|
//s.baliseDetector.detect(wd, repo, h, vobcBtm)
|
||||||
|
h2 := &TrainHeadPositionInfo{
|
||||||
|
TrainId: h.TrainId,
|
||||||
|
Up: h.Up,
|
||||||
|
Link: h.OldLink,
|
||||||
|
LinkOffset: h.OldLinkOffset,
|
||||||
|
Speed: h.Speed,
|
||||||
|
Acceleration: h.Acceleration}
|
||||||
|
s.baliseDetector.detect2(wd, repo, h, h2, vobcBtm)
|
||||||
}
|
}
|
||||||
func (s *btmCanetClient) Start(bcm BtmCanetManager) {
|
func (s *btmCanetClient) Start(bcm BtmCanetManager) {
|
||||||
s.bcm = bcm
|
s.bcm = bcm
|
||||||
@ -154,6 +194,9 @@ 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() {
|
||||||
|
162
third_party/can_btm/balise_detection.go
vendored
162
third_party/can_btm/balise_detection.go
vendored
@ -28,7 +28,8 @@ type BtmAntennaRunningInfo struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
BtmAntennaOffsetHead = int64(1000) //车载BTM天线距车头端点的距离,mm
|
//BtmAntennaOffsetHead = int64(1000) //车载BTM天线距车头端点的距离,mm
|
||||||
|
BtmAntennaOffsetHead = int64(0) //车载BTM天线距车头端点的距离,mm
|
||||||
)
|
)
|
||||||
|
|
||||||
// TrainHeadPositionInfo 列车车头运行位置信息
|
// TrainHeadPositionInfo 列车车头运行位置信息
|
||||||
@ -46,6 +47,7 @@ type BtmAntennaScanningBaliseInfo struct {
|
|||||||
telegram128 []byte //应答器报文
|
telegram128 []byte //应答器报文
|
||||||
Distance int64 //BTM天线中心到应答器的距离,mm
|
Distance int64 //BTM天线中心到应答器的距离,mm
|
||||||
BaliseType proto.Transponder_Type //应答器类型
|
BaliseType proto.Transponder_Type //应答器类型
|
||||||
|
IsSend bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// BaliseDetector 车载BTM天线,应答器探测器
|
// BaliseDetector 车载BTM天线,应答器探测器
|
||||||
@ -76,6 +78,86 @@ func (t *BaliseDetector) tryRebind(th *TrainHeadPositionInfo) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *BaliseDetector) detect2(wd *component.WorldData, repo *repository.Repository, th, th2 *TrainHeadPositionInfo, vobcBtm *state_proto.VobcBtmState) {
|
||||||
|
t.tryRebind(th)
|
||||||
|
|
||||||
|
//BTM天线中心点运行信息
|
||||||
|
curAntennaRi := t.createBtmAntennaRunningInfo(wd, repo, th) //目前车头
|
||||||
|
curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, th2) //上次车头
|
||||||
|
var startBalises []*repository.Transponder
|
||||||
|
var endBalises []*repository.Transponder
|
||||||
|
//startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi2.LinkId, th2.LinkOffset, th.LinkOffset)
|
||||||
|
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi2.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
|
||||||
|
//endBalises = t.searchBalisesFromBetweenLinkPosition(repo, !th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset)
|
||||||
|
/* if th.Up {
|
||||||
|
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi2.LinkId, curAntennaRi2.LinkOffset, curAntennaRi.LinkOffset)
|
||||||
|
endBalises = t.searchBalisesFromBetweenLinkPosition(repo, !th.Up, curAntennaRi.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset)
|
||||||
|
} else {
|
||||||
|
startBalises = t.searchBalisesFromBetweenLinkPosition(repo, th.Up, curAntennaRi2.LinkId, curAntennaRi.LinkOffset, curAntennaRi2.LinkOffset)
|
||||||
|
endBalises = 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)
|
||||||
|
//slog.Info(fmt.Sprintf("start baliseId:%v,Distance:%v,up:%v", balisecodec.Id(), balisecodec.LinkPosition(), curAntennaRi.Up))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, balise := range endBalises {
|
||||||
|
find := false
|
||||||
|
for _, transponder := range balises {
|
||||||
|
if transponder.Id() == balise.Id() {
|
||||||
|
find = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !find {
|
||||||
|
//slog.Info(fmt.Sprintf("end baliseId:%v,Distance:%v,up:%v", balisecodec.Id(), balisecodec.LinkPosition(), curAntennaRi.Up))
|
||||||
|
balises = append(balises, balise)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(balises) > 0 {
|
||||||
|
balise := balises[0]
|
||||||
|
baliseInfo := &BtmAntennaScanningBaliseInfo{BaliseId: balise.Id(), BaliseType: balise.BaliseType()}
|
||||||
|
/*uuid := uuid2.NewString()
|
||||||
|
for _, transponder := range balises {
|
||||||
|
slog.Info(fmt.Sprintf("uid :%v,baliseId:%v,Distance:%v,up:%v", uuid, transponder.Id(), baliseInfo.Distance, curAntennaRi.Up))
|
||||||
|
}*/
|
||||||
|
|
||||||
|
telegram, utel := t.rcvTelegram2(wd, balise.Id())
|
||||||
|
if utel != nil && t.addExpectedBalise(baliseInfo) {
|
||||||
|
t.baliseCounterAdd1() //应答器计数器
|
||||||
|
if len(telegram) > 0 {
|
||||||
|
baliseInfo.telegram = utel
|
||||||
|
baliseInfo.telegram128 = telegram
|
||||||
|
t.baliseMessageCounterAdd1() //报文计数器
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t.aboveBalise = true
|
||||||
|
} else {
|
||||||
|
t.aboveBalise = false
|
||||||
|
}
|
||||||
|
|
||||||
|
/* curAntennaRi2 := t.createBtmAntennaRunningInfo(wd, repo, &TrainHeadPositionInfo{TrainId: th.TrainId,
|
||||||
|
Up: !th.Up,
|
||||||
|
Link: th.Link,
|
||||||
|
LinkOffset: th.LinkOffset,
|
||||||
|
Speed: th.Speed,
|
||||||
|
Acceleration: th.Acceleration})
|
||||||
|
curExpect2 := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi2)
|
||||||
|
if curExpect2 != nil && curExpect2.Distance > 20 {
|
||||||
|
btm_vobc.Default().UpdateTrainLeave(vobcBtm, curExpect2.BaliseId, curTime.UnixMilli())
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
|
||||||
func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Repository, th *TrainHeadPositionInfo, vobcBtm *state_proto.VobcBtmState) {
|
func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Repository, th *TrainHeadPositionInfo, vobcBtm *state_proto.VobcBtmState) {
|
||||||
t.tryRebind(th)
|
t.tryRebind(th)
|
||||||
//if !t.powerAmplifierSwitch { //天线功率放大器未开启,不进行探测
|
//if !t.powerAmplifierSwitch { //天线功率放大器未开启,不进行探测
|
||||||
@ -88,7 +170,9 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
|
|||||||
curExpect := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi)
|
curExpect := t.timeScanNearestBalise(curTime, wd, repo, curAntennaRi)
|
||||||
|
|
||||||
if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms
|
if curExpect != nil && curExpect.Time.UnixMilli()-curTime.UnixMilli() < 20 { //20ms
|
||||||
|
//if curExpect != nil && curExpect.Distance < 80 { //20ms
|
||||||
//slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt)
|
//slog.Debug("将要激活应答器", "BaliseId", curExpect.BaliseId, "ActiveTime", dt)
|
||||||
|
//slog.Info(fmt.Sprintf("baliseId:%v,Distance:%v,up:%v", curExpect.BaliseId, curExpect.Distance, curAntennaRi.Up))
|
||||||
telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId)
|
telegram, utel := t.rcvTelegram(wd, curExpect.BaliseId)
|
||||||
|
|
||||||
if curExpect.Distance <= 50 {
|
if curExpect.Distance <= 50 {
|
||||||
@ -101,7 +185,6 @@ func (t *BaliseDetector) detect(wd *component.WorldData, repo *repository.Reposi
|
|||||||
curExpect.telegram = utel
|
curExpect.telegram = utel
|
||||||
curExpect.telegram128 = telegram
|
curExpect.telegram128 = telegram
|
||||||
t.baliseMessageCounterAdd1() //报文计数器
|
t.baliseMessageCounterAdd1() //报文计数器
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//BTM天线即将经过应答器
|
//BTM天线即将经过应答器
|
||||||
@ -138,6 +221,32 @@ func (t *BaliseDetector) baliseMessageCounterAdd1() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BTM天线接收应答器报文(线程不安全)
|
||||||
|
func (t *BaliseDetector) rcvTelegram2(wd *component.WorldData, baliseId string) ([]byte, []byte) {
|
||||||
|
|
||||||
|
if entry, ok := wd.EntityMap[baliseId]; ok {
|
||||||
|
workedState := component.BaliseWorkStateType.Get(entry)
|
||||||
|
if !workedState.Work {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//hasVar := entry.HasComponent(component.BaliseVariableTelegramType)
|
||||||
|
//hexFix := entry.HasComponent(component.BaliseFixedTelegramType)
|
||||||
|
|
||||||
|
if entry.HasComponent(component.BaliseVariableTelegramType) {
|
||||||
|
baliseVar := component.BaliseVariableTelegramType.Get(entry)
|
||||||
|
//slog.Info(fmt.Sprintf("find_baliseId:%v ,work:%v,var:%v,fix:%v,tel:%v,usertel:%v", baliseId, workedState.Work, hasVar, hexFix, hex.EncodeToString(baliseVar.Telegram), hex.EncodeToString(baliseVar.UserTelegram)))
|
||||||
|
return baliseVar.Telegram, baliseVar.UserTelegram
|
||||||
|
} else if entry.HasComponent(component.BaliseFixedTelegramType) {
|
||||||
|
fixBalise := component.BaliseFixedTelegramType.Get(entry)
|
||||||
|
//slog.Info(fmt.Sprintf("find_baliseId:%v ,work:%v,var:%v,fix:%v,tel:%v,usertel:%v", baliseId, workedState.Work, hasVar, hexFix, hex.EncodeToString(tel), hex.EncodeToString(utel)))
|
||||||
|
return fixBalise.Telegram, fixBalise.UserTelegram
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
// BTM天线接收应答器报文(线程不安全)
|
// BTM天线接收应答器报文(线程不安全)
|
||||||
func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) ([]byte, []byte) {
|
func (t *BaliseDetector) rcvTelegram(wd *component.WorldData, baliseId string) ([]byte, []byte) {
|
||||||
entry, ok := wd.EntityMap[baliseId]
|
entry, ok := wd.EntityMap[baliseId]
|
||||||
@ -165,10 +274,17 @@ func (t *BaliseDetector) addExpectedBalise(curExpect *BtmAntennaScanningBaliseIn
|
|||||||
// }
|
// }
|
||||||
//}
|
//}
|
||||||
//检查是否已经记录过
|
//检查是否已经记录过
|
||||||
eq := t.eq[len(t.eq)-1]
|
|
||||||
if eq != nil && eq.BaliseId == curExpect.BaliseId {
|
for _, tt := range t.eq {
|
||||||
return false
|
if tt != nil && tt.BaliseId == curExpect.BaliseId {
|
||||||
|
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]
|
||||||
@ -210,7 +326,9 @@ 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, Distance: expectedBalise.Distance, BaliseType: expectedBalise.BaliseType}
|
return &BtmAntennaScanningBaliseInfo{BaliseId: expectedBalise.BaliseId, Time: st, Distance: expectedBalise.Distance, BaliseType: expectedBalise.BaliseType}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -284,6 +402,39 @@ 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 {
|
||||||
|
|
||||||
|
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)
|
||||||
@ -302,6 +453,7 @@ func (t *BaliseDetector) searchBalisesFromLinkPosition(repo *repository.Reposito
|
|||||||
return rs[j].LinkPosition().Offset() < rs[i].LinkPosition().Offset()
|
return rs[j].LinkPosition().Offset() < rs[i].LinkPosition().Offset()
|
||||||
})
|
})
|
||||||
for i, r := range rs {
|
for i, r := range rs {
|
||||||
|
//slog.Info(fmt.Sprintf("id:%v,offset:%v,from:%v", r.Id(), r.LinkPosition().Offset(), fromOffset))
|
||||||
if r.LinkPosition().Offset() <= fromOffset {
|
if r.LinkPosition().Offset() <= fromOffset {
|
||||||
return rs[i:]
|
return rs[i:]
|
||||||
}
|
}
|
||||||
|
2
third_party/dynamics/dynamics.go
vendored
2
third_party/dynamics/dynamics.go
vendored
@ -141,7 +141,7 @@ 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)
|
||||||
fmt.Println(string(data))
|
//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 sys_error.New("动力学开始仿真请求发送错误", err)
|
return sys_error.New("动力学开始仿真请求发送错误", err)
|
||||||
|
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/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.ToVal([]int{
|
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.ToBits(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])
|
||||||
}
|
}
|
||||||
|
180
third_party/interlock/beijing11/msg.go
vendored
180
third_party/interlock/beijing11/msg.go
vendored
@ -4,11 +4,24 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const ( //不知道对不对,问也不回,先瞎写吧
|
||||||
|
ON = 0x55 //按钮-按下;道岔-定位;屏蔽门-关门;计轴区段-占用
|
||||||
|
OFF = 0xAA //按钮-抬起;道岔-反位;屏蔽门-开门;计轴区段-出清
|
||||||
|
)
|
||||||
|
|
||||||
|
func GetStateByte(state bool) byte {
|
||||||
|
if state {
|
||||||
|
return ON
|
||||||
|
} else {
|
||||||
|
return OFF
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FromInterlockFrame 来自联锁的数据帧
|
// FromInterlockFrame 来自联锁的数据帧
|
||||||
type FromInterlockFrame struct {
|
type FromInterlockFrame struct {
|
||||||
Len uint16
|
Len uint16
|
||||||
InterlockCode uint16 //联锁ID
|
InterlockCode uint16 //联锁编号(联锁->轨旁:OC的编号,轨旁->联锁:联锁站编号)
|
||||||
WaysideCode uint16 //轨旁ID
|
WaysideCode uint16 //轨旁编号
|
||||||
TurnoutData *DeviceData //道岔数据
|
TurnoutData *DeviceData //道岔数据
|
||||||
PSDData *DeviceData //屏蔽门数据
|
PSDData *DeviceData //屏蔽门数据
|
||||||
ESBData *ESBData //紧急停车按钮数据
|
ESBData *ESBData //紧急停车按钮数据
|
||||||
@ -187,75 +200,66 @@ type DeviceCmd struct {
|
|||||||
|
|
||||||
// ToInterlockFrame 发往联锁的数据帧
|
// ToInterlockFrame 发往联锁的数据帧
|
||||||
type ToInterlockFrame struct {
|
type ToInterlockFrame struct {
|
||||||
Len uint16
|
WaysideCode uint16
|
||||||
WaysideCode uint16
|
InterlockCode uint16
|
||||||
InterlockCode uint16
|
TurnoutStates []*TurnoutState //道岔状态
|
||||||
TurnoutData *ToInterlockTurnoutData //道岔数据
|
PsdStates []*PSDState //屏蔽门状态
|
||||||
PSDData *ToInterlockPSDData //屏蔽门数据
|
ESBStates []*ESBState //紧急停车按钮状态
|
||||||
ESBData *ToInterlockESBData //紧急停车按钮数据
|
//HoldTrainData []*HoldTrainState //扣车按钮状态(数量0)
|
||||||
HoldTrainData *ToInterlockHoldTrainData //扣车按钮数据
|
SignalStates []*SignalState //信号机状态
|
||||||
SignalData *ToInterlockSignalData //信号机数据
|
AxleSectionStates []*AxleSectionState //计轴区段状态
|
||||||
AxleSectionData *ToInterlockAxleSectionData //计轴区段数据
|
//WrzfData []*WrzfState //无人折返状态(数量0)
|
||||||
WrzfData *ToInterlockWrzfData //无人折返数据
|
//FymData []*FymState //防淹门状态(数量0)
|
||||||
FymData *ToInterlockFymData //防淹门数据
|
SPKSStates []*SPKSState //SPKS状态
|
||||||
SPKSData *ToInterlockSPKSData //SPKS数据
|
//CkmData []*CkmState //车库门状态(数量0)
|
||||||
CkmData *ToInterlockCkmData //车库门数据
|
//XcjData []*XcjState //洗车机状态(无)
|
||||||
XcjData *ToInterlockXcjData //洗车机数据
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type ToInterlockTurnoutData struct {
|
func (t *ToInterlockFrame) encode() []byte {
|
||||||
Num uint16 //该联锁集中区包含的道岔数量
|
data := make([]byte, 0, 128)
|
||||||
StateList []*TurnoutState
|
data = append(data, 0x83) //报文类型
|
||||||
}
|
data = append(data, 0, 0) //报文长度占位
|
||||||
|
data = binary.BigEndian.AppendUint16(data, t.WaysideCode)
|
||||||
type ToInterlockPSDData struct {
|
data = binary.BigEndian.AppendUint16(data, t.InterlockCode)
|
||||||
Num uint16 //该联锁集中区包含的屏蔽门数量
|
//道岔
|
||||||
StateList []*PSDState
|
data = binary.BigEndian.AppendUint16(data, uint16(len(t.TurnoutStates)))
|
||||||
}
|
for _, state := range t.TurnoutStates {
|
||||||
|
data = state.encode(data)
|
||||||
type ToInterlockESBData struct {
|
}
|
||||||
Num uint16 //紧急停车按钮数量
|
//屏蔽门
|
||||||
StateList []*ESBState
|
data = binary.BigEndian.AppendUint16(data, uint16(len(t.PsdStates)))
|
||||||
}
|
for _, state := range t.PsdStates {
|
||||||
|
data = state.encode(data)
|
||||||
type ToInterlockHoldTrainData struct {
|
}
|
||||||
Num uint16 //扣车数量
|
//紧急停车
|
||||||
StateList []*HoldTrainState
|
data = binary.BigEndian.AppendUint16(data, uint16(len(t.ESBStates)))
|
||||||
}
|
for _, state := range t.ESBStates {
|
||||||
|
data = state.encode(data)
|
||||||
type ToInterlockSignalData struct {
|
}
|
||||||
Num uint16 //该联锁集中区信号机的数量
|
//扣车,数量0
|
||||||
StateList []*SignalState
|
data = binary.BigEndian.AppendUint16(data, 0)
|
||||||
}
|
//信号机状态
|
||||||
|
binary.BigEndian.AppendUint16(data, uint16(len(t.SignalStates)))
|
||||||
type ToInterlockAxleSectionData struct {
|
for _, state := range t.SignalStates {
|
||||||
Num uint16 //该联锁集中区计轴区段的数量
|
data = state.encode(data)
|
||||||
StateList []*AxleSectionState
|
}
|
||||||
}
|
//计轴区段
|
||||||
|
binary.BigEndian.AppendUint16(data, uint16(len(t.AxleSectionStates)))
|
||||||
type ToInterlockWrzfData struct {
|
for _, state := range t.AxleSectionStates {
|
||||||
Num uint16 //该联锁集中区无人折返的数量
|
data = state.encode(data)
|
||||||
StateList []*WrzfState
|
}
|
||||||
}
|
//无人折返,数量0
|
||||||
|
data = binary.BigEndian.AppendUint16(data, 0)
|
||||||
type ToInterlockFymData struct {
|
//防淹门,数量0
|
||||||
Num uint16 //该联锁集中区防<E58CBA><E998B2>门的数量
|
data = binary.BigEndian.AppendUint16(data, 0)
|
||||||
StateList []*FymState
|
//SPKS
|
||||||
}
|
data = binary.BigEndian.AppendUint16(data, uint16(len(t.SPKSStates)))
|
||||||
|
for _, state := range t.SPKSStates {
|
||||||
type ToInterlockSPKSData struct {
|
data = state.encode(data)
|
||||||
Num uint16 //SPKS数量
|
}
|
||||||
StateList []*SPKSState
|
//车库门,数量0
|
||||||
}
|
data = binary.BigEndian.AppendUint16(data, 0)
|
||||||
|
return data
|
||||||
type ToInterlockCkmData struct {
|
|
||||||
Num uint16 //车库门数量
|
|
||||||
StateList []*CkmState
|
|
||||||
}
|
|
||||||
|
|
||||||
type ToInterlockXcjData struct {
|
|
||||||
Num uint16 //洗车机数量
|
|
||||||
StateList []*XcjState
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type TurnoutState struct {
|
type TurnoutState struct {
|
||||||
@ -266,6 +270,12 @@ type TurnoutState struct {
|
|||||||
Current2 byte //转辙机2电流值,单位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 {
|
type PSDState struct {
|
||||||
Id uint16 //屏蔽门ID
|
Id uint16 //屏蔽门ID
|
||||||
State byte //屏蔽门开关门状态
|
State byte //屏蔽门开关门状态
|
||||||
@ -275,11 +285,23 @@ type PSDState struct {
|
|||||||
DPB byte //DPB状态
|
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 {
|
type ESBState struct {
|
||||||
Id uint16 //紧急停车ID
|
Id uint16 //紧急停车ID
|
||||||
State byte //紧急停车按钮状态
|
State byte //紧急停车按钮状态
|
||||||
PlState byte //紧急停车按钮旁路状态
|
PlState byte //紧急停车按钮旁路状态
|
||||||
ESS byte //ESS状态(按下55,抬起aa)
|
//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 {
|
type HoldTrainState struct {
|
||||||
@ -296,11 +318,23 @@ type SignalState struct {
|
|||||||
Current 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 {
|
type AxleSectionState struct {
|
||||||
Id uint16 //计轴区段Id
|
Id uint16 //计轴区段Id
|
||||||
State byte //计轴区段的采集状态
|
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 {
|
type WrzfState struct {
|
||||||
Id uint16 //无人折返ID
|
Id uint16 //无人折返ID
|
||||||
State byte //无人折返的采集状态
|
State byte //无人折返的采集状态
|
||||||
@ -318,6 +352,12 @@ type SPKSState struct {
|
|||||||
PlState byte //SPKSPL按钮状态
|
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 {
|
type CkmState struct {
|
||||||
Id uint16 //车库门ID
|
Id uint16 //车库门ID
|
||||||
State byte //车库门采集状态
|
State byte //车库门采集状态
|
||||||
|
2
third_party/interlock/beijing11/msg_test.go
vendored
2
third_party/interlock/beijing11/msg_test.go
vendored
@ -43,7 +43,7 @@ func TestFromInterlockFrame_Decode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
marshal, _ := json.Marshal(f)
|
marshal, _ := json.Marshal(f)
|
||||||
fmt.Println(string(marshal))
|
fmt.Println(string(marshal))
|
||||||
//if f.InterlockCode != interlockCode {
|
//if f.WaysideCode != interlockCode {
|
||||||
// t.Error()
|
// t.Error()
|
||||||
//}
|
//}
|
||||||
//if f.WaysideCode != waysideCode {
|
//if f.WaysideCode != waysideCode {
|
||||||
|
70
third_party/interlock/beijing11/repo.go
vendored
70
third_party/interlock/beijing11/repo.go
vendored
@ -1,35 +1,49 @@
|
|||||||
package beijing11
|
package beijing11
|
||||||
|
|
||||||
// StationDeviceIndexRepo 联锁站设备索引映射
|
// StationDeviceIndexTable 联锁站设备索引表
|
||||||
// key为联锁编号,val为uid
|
type StationDeviceIndexTable struct {
|
||||||
type StationDeviceIndexRepo struct {
|
StationName string //地图数据中车站的Code属性
|
||||||
StationName string
|
WaysideCode string //通信数据中的“轨旁编号”
|
||||||
TurnoutMap map[uint32]string
|
TurnoutMap map[uint16]*Row
|
||||||
PsdMap map[uint32]string
|
PsdMap map[uint16]*Row
|
||||||
EsbMap map[uint32]string
|
EsbMap map[uint16]*Row
|
||||||
HoldTrainMap map[uint32]string
|
HoldTrainMap map[uint16]*Row
|
||||||
SignalMap map[uint32]string
|
SignalMap map[uint16]*Row
|
||||||
AxleSectionMap map[uint32]string
|
AxleSectionMap map[uint16]*Row
|
||||||
WrzfMap map[uint32]string
|
WrzfMap map[uint16]*Row
|
||||||
FymMap map[uint32]string
|
FymMap map[uint16]*Row
|
||||||
SpksMap map[uint32]string
|
SpksMap map[uint16]*Row
|
||||||
CkmMap map[uint32]string
|
CkmMap map[uint16]*Row
|
||||||
XcjMap map[uint32]string
|
XcjMap map[uint16]*Row
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewStationDeviceIndexRepo() *StationDeviceIndexRepo {
|
func NewStationDeviceIndexTable() *StationDeviceIndexTable {
|
||||||
return &StationDeviceIndexRepo{
|
return &StationDeviceIndexTable{
|
||||||
StationName: "",
|
StationName: "",
|
||||||
TurnoutMap: make(map[uint32]string),
|
WaysideCode: "",
|
||||||
PsdMap: make(map[uint32]string),
|
TurnoutMap: make(map[uint16]*Row),
|
||||||
EsbMap: make(map[uint32]string),
|
PsdMap: make(map[uint16]*Row),
|
||||||
HoldTrainMap: make(map[uint32]string),
|
EsbMap: make(map[uint16]*Row),
|
||||||
SignalMap: make(map[uint32]string),
|
HoldTrainMap: make(map[uint16]*Row),
|
||||||
AxleSectionMap: make(map[uint32]string),
|
SignalMap: make(map[uint16]*Row),
|
||||||
WrzfMap: make(map[uint32]string),
|
AxleSectionMap: make(map[uint16]*Row),
|
||||||
FymMap: make(map[uint32]string),
|
WrzfMap: make(map[uint16]*Row),
|
||||||
SpksMap: make(map[uint32]string),
|
FymMap: make(map[uint16]*Row),
|
||||||
CkmMap: make(map[uint32]string),
|
SpksMap: make(map[uint16]*Row),
|
||||||
XcjMap: make(map[uint32]string),
|
CkmMap: make(map[uint16]*Row),
|
||||||
|
XcjMap: make(map[uint16]*Row),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Row struct {
|
||||||
|
commonId uint32 //地图中设备的ID
|
||||||
|
uid string //模型仓库中的设备模型ID
|
||||||
|
index uint16 //联锁通信中的设备ID
|
||||||
|
relateDeviceMap map[string]string //此设备关联的其它设备 key-查找设备所用的标识,val-uid
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
POB = "POB"
|
||||||
|
PCB = "PCB"
|
||||||
|
DPB = "DPB"
|
||||||
|
)
|
||||||
|
416
third_party/interlock/beijing11/service.go
vendored
416
third_party/interlock/beijing11/service.go
vendored
@ -2,133 +2,345 @@
|
|||||||
package beijing11
|
package beijing11
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"joylink.club/bj-rtsts-server/config"
|
"joylink.club/bj-rtsts-server/config"
|
||||||
"joylink.club/bj-rtsts-server/dto/data_proto"
|
"joylink.club/bj-rtsts-server/dto/data_proto"
|
||||||
"joylink.club/bj-rtsts-server/third_party/udp"
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
"joylink.club/bj-rtsts-server/ts/simulation/wayside/memory"
|
||||||
|
"joylink.club/rtsssimulation/component"
|
||||||
|
"joylink.club/rtsssimulation/entity"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const logTag = "[北京11号线联锁通信]"
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
initMutex = sync.Mutex{}
|
logTag = "[北京11号线联锁通信]"
|
||||||
running = false
|
privateLogger *slog.Logger
|
||||||
server udp.UdpServer
|
loggerInit sync.Once
|
||||||
sim *memory.VerifySimulation //启动服务所使用的仿真
|
|
||||||
iConfig *config.InterlockConfig //启动服务使用的联锁配置
|
|
||||||
//联锁区设备的联锁编号与uid的映射
|
|
||||||
stationMap map[string]*StationDeviceIndexRepo
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
var (
|
||||||
memory.RegisterListener(func(uidStructure *memory.StationUidStructure, data *data_proto.RtssGraphicStorage) {
|
mu = sync.Mutex{} //启动任务时使用,避免重复启动任务
|
||||||
//if data.LianSuoData == nil {
|
serviceContextMap = make(map[string]*serviceContext) //每个集中站的服务上下文,key-集中站code
|
||||||
// return
|
)
|
||||||
//}
|
|
||||||
////初始化所有集中站设备映射结构体;建立车站和集中站的comId映射关系
|
type serviceContext struct {
|
||||||
//station_concentration_map := make(map[uint32]uint32)
|
cancelFunc context.CancelFunc //用来结束各个协程的函数
|
||||||
//for _, station := range data.Stations {
|
client udp.UdpClient //向联锁发送数据的客户端
|
||||||
// if station.ConcentrationStations {
|
server udp.UdpServer //接收联锁数据的服务端
|
||||||
// stationMap[station.StationName] = NewStationDeviceIndexRepo()
|
sim *memory.VerifySimulation //启动服务所使用的仿真
|
||||||
// for _, manageStation := range station.ManageStations {
|
iConfig config.InterlockConfig //启动服务使用的联锁配置
|
||||||
// station_concentration_map[manageStation] = station.Common.Id
|
deviceTable *StationDeviceIndexTable //联锁站的设备ID表,key-车站名
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
////建立站台和集中站的comId映射
|
|
||||||
//platform_station_map := make(map[uint32]uint32)
|
|
||||||
//for _, platform := range data.Platforms {
|
|
||||||
// platform_station_map[platform.Common.Id] = station_concentration_map[platform.RefStationId]
|
|
||||||
//}
|
|
||||||
////填充
|
|
||||||
//stationIdMap := uidStructure.StationIds
|
|
||||||
////道岔
|
|
||||||
//turnoutUidMap := uidStructure.TurnoutIds
|
|
||||||
//turnoutIndexMap := make(map[uint32]uint32)
|
|
||||||
//for _, turnout := range data.LianSuoData.Switchs {
|
|
||||||
// turnoutIndexMap[turnout.Id] = turnout.Index
|
|
||||||
//}
|
|
||||||
//for _, turnout := range data.Turnouts {
|
|
||||||
// for _, stationComId := range turnout.CentralizedStations {
|
|
||||||
// stationIdStruct := stationIdMap[stationComId]
|
|
||||||
// stationDeviceIndexRepo := stationMap[stationIdStruct.Code]
|
|
||||||
// index := turnoutIndexMap[turnout.Common.Id]
|
|
||||||
// stationDeviceIndexRepo.TurnoutMap[index] = turnoutUidMap[turnout.Common.Id].Uid
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
////屏蔽门
|
|
||||||
//psdUidMap := uidStructure.PsdIds
|
|
||||||
//psdIndexMap := make(map[uint32]uint32)
|
|
||||||
//for _, psd := range data.LianSuoData.ScreenDoors {
|
|
||||||
// psdIndexMap[psd.Id] = psd.Index
|
|
||||||
//}
|
|
||||||
//for _, psd := range data.ScreenDoors {
|
|
||||||
// stationComId := platform_station_map[psd.RefPlatformId]
|
|
||||||
// stationIdStruct := stationIdMap[stationComId]
|
|
||||||
// stationDeviceIndexRepo := stationMap[stationIdStruct.Code]
|
|
||||||
// index := psdIndexMap[psd.Common.Id]
|
|
||||||
// stationDeviceIndexRepo.PsdMap[index] = psdUidMap[psd.Common.Id].Uid
|
|
||||||
//}
|
|
||||||
////紧急停车
|
|
||||||
//uidStructure.
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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
|
||||||
}
|
}
|
||||||
if running {
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
//制表
|
||||||
|
table := makeTable(simulation, interlockConfig.Code)
|
||||||
|
if table == nil { //当前仿真内没有11号线联锁通信所需数据
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
initMutex.Lock()
|
serviceCtx := serviceContextMap[interlockConfig.Code]
|
||||||
defer initMutex.Unlock()
|
if serviceCtx != nil {
|
||||||
if running {
|
panic(fmt.Sprintf("%s重复启动联锁站[%s]通信服务", logTag, interlockConfig.Code))
|
||||||
return
|
|
||||||
}
|
}
|
||||||
//UDP通信设施
|
//UDP客户端
|
||||||
server = udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), func(b []byte) {
|
client := udp.NewClient(fmt.Sprintf("%s:%d", interlockConfig.Ip, interlockConfig.RemotePort))
|
||||||
slog.Info(fmt.Sprintf("%s收到消息:%x", logTag, b))
|
|
||||||
frame := &FromInterlockFrame{}
|
ctx, cancelFunc := context.WithCancel(context.Background())
|
||||||
err := frame.Decode(b)
|
serviceCtx = &serviceContext{
|
||||||
if err != nil {
|
cancelFunc: cancelFunc,
|
||||||
slog.Error(fmt.Sprintf("%s解析数据出错:%s", logTag, err))
|
client: client,
|
||||||
} else {
|
sim: simulation,
|
||||||
marshal, err := json.Marshal(frame)
|
iConfig: interlockConfig,
|
||||||
if err != nil {
|
deviceTable: table,
|
||||||
slog.Error(fmt.Sprintf("%s解析为json出错:%s", logTag, err))
|
}
|
||||||
} else {
|
//UDP服务端
|
||||||
slog.Info(fmt.Sprintf("%s解析为json:%s", logTag, string(marshal)))
|
server := udp.NewServer(fmt.Sprintf(":%d", interlockConfig.LocalPort), serviceCtx.handleDriveMsg)
|
||||||
}
|
serviceCtx.server = server
|
||||||
}
|
|
||||||
})
|
|
||||||
err := server.Listen()
|
err := server.Listen()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(fmt.Sprintf("%s启动UDP服务失败:%s", logTag, err))
|
panic(fmt.Sprintf("%s启动UDP服务失败:%s", logTag, err))
|
||||||
}
|
}
|
||||||
running = true
|
|
||||||
sim = simulation
|
serviceCtx.runCollectTask(ctx)
|
||||||
iConfig = interlockConfig
|
serviceContextMap[interlockConfig.Code] = serviceCtx
|
||||||
}
|
}
|
||||||
|
|
||||||
func Stop() {
|
func (s *serviceContext) handleDriveMsg(data []byte) {
|
||||||
initMutex.Lock()
|
logger().Info(fmt.Sprintf("收到消息:%x", data))
|
||||||
defer initMutex.Unlock()
|
frame := &FromInterlockFrame{}
|
||||||
running = false
|
err := frame.Decode(data)
|
||||||
if server != nil {
|
if err != nil {
|
||||||
server.Close()
|
logger().Error("解析数据出错", "error", err)
|
||||||
server = nil
|
return
|
||||||
|
}
|
||||||
|
//for _, cmd := range frame.TurnoutData.CmdList {
|
||||||
|
// uid := s.deviceTable.TurnoutMap[cmd.Id].uid
|
||||||
|
// fi.turn
|
||||||
|
//}
|
||||||
|
}
|
||||||
|
|
||||||
|
func Stop(stationCode string) {
|
||||||
|
mu.Lock()
|
||||||
|
defer mu.Unlock()
|
||||||
|
context := serviceContextMap[stationCode]
|
||||||
|
if context != nil {
|
||||||
|
if context.client != nil {
|
||||||
|
context.client.Close()
|
||||||
|
}
|
||||||
|
if context.server != nil {
|
||||||
|
context.server.Close()
|
||||||
|
}
|
||||||
|
delete(serviceContextMap, stationCode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//func CollectRelayInfo() *FromInterlockFrame {
|
func makeTable(sim *memory.VerifySimulation, stationCode string) *StationDeviceIndexTable {
|
||||||
// sim.World
|
for _, mapId := range sim.MapIds {
|
||||||
//}
|
giType := memory.QueryGiType(mapId)
|
||||||
//
|
if giType != data_proto.PictureType_StationLayout {
|
||||||
//func HandleDriveInfo(frame *FromInterlockFrame) {
|
continue
|
||||||
//
|
}
|
||||||
//}
|
stationGi := memory.QueryGiData[*data_proto.RtssGraphicStorage](mapId)
|
||||||
|
if stationGi.LianSuoData == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
uids := memory.QueryUidStructure[*memory.StationUidStructure](mapId)
|
||||||
|
table := NewStationDeviceIndexTable()
|
||||||
|
//道岔
|
||||||
|
for _, data := range stationGi.LianSuoData.Switchs {
|
||||||
|
for _, station := range uids.TurnoutIds[data.Id].CentralizedStations {
|
||||||
|
if station.Code == stationCode {
|
||||||
|
table.TurnoutMap[uint16(data.Id)] = &Row{
|
||||||
|
commonId: data.Id,
|
||||||
|
uid: uids.TurnoutIds[data.Id].Uid,
|
||||||
|
index: uint16(data.Index),
|
||||||
|
relateDeviceMap: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//屏蔽门
|
||||||
|
for _, data := range stationGi.LianSuoData.ScreenDoors {
|
||||||
|
for _, station := range uids.PsdIds[data.Id].CentralizedStations {
|
||||||
|
if station.Code == stationCode {
|
||||||
|
relateDeviceMap := make(map[string]string)
|
||||||
|
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.Id)] = &Row{
|
||||||
|
commonId: data.Id,
|
||||||
|
uid: uids.PsdIds[data.Id].Uid,
|
||||||
|
index: uint16(data.Index),
|
||||||
|
relateDeviceMap: relateDeviceMap,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//紧急停车
|
||||||
|
for _, data := range stationGi.LianSuoData.EsbButtons {
|
||||||
|
for _, station := range uids.EsbIds[data.Id].CentralizedStations {
|
||||||
|
if station.Code == stationCode {
|
||||||
|
table.EsbMap[uint16(data.Id)] = &Row{
|
||||||
|
commonId: data.Id,
|
||||||
|
uid: uids.EsbIds[data.Id].Uid,
|
||||||
|
index: uint16(data.Index),
|
||||||
|
relateDeviceMap: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//扣车,实际数据中数量为0
|
||||||
|
//信号机
|
||||||
|
for _, data := range stationGi.LianSuoData.Signals {
|
||||||
|
for _, station := range uids.SignalIds[data.Id].CentralizedStations {
|
||||||
|
if station.Code == stationCode {
|
||||||
|
table.SignalMap[uint16(data.Id)] = &Row{
|
||||||
|
commonId: data.Id,
|
||||||
|
uid: uids.SignalIds[data.Id].Uid,
|
||||||
|
index: uint16(data.Index),
|
||||||
|
relateDeviceMap: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//计轴区段
|
||||||
|
for _, data := range stationGi.LianSuoData.Sections {
|
||||||
|
for _, station := range uids.PhysicalSectionIds[data.Id].CentralizedStations {
|
||||||
|
if station.Code == stationCode {
|
||||||
|
table.AxleSectionMap[uint16(data.Id)] = &Row{
|
||||||
|
commonId: data.Id,
|
||||||
|
uid: uids.PhysicalSectionIds[data.Id].Uid,
|
||||||
|
index: uint16(data.Index),
|
||||||
|
relateDeviceMap: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//无人折返,实际数据中数量为0
|
||||||
|
//防淹门,实际数据中数量为0
|
||||||
|
//人员防护
|
||||||
|
for _, data := range stationGi.LianSuoData.SpksSwitchs {
|
||||||
|
for _, station := range uids.SpksIds[data.Id].CentralizedStations {
|
||||||
|
if station.Code == stationCode {
|
||||||
|
table.SpksMap[uint16(data.Id)] = &Row{
|
||||||
|
commonId: data.Id,
|
||||||
|
uid: uids.SpksIds[data.Id].Uid,
|
||||||
|
index: uint16(data.Index),
|
||||||
|
relateDeviceMap: nil,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//车库门,实际数据中数量为0
|
||||||
|
//洗车机,实际数据中没有
|
||||||
|
return table
|
||||||
|
}
|
||||||
|
return 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(nil)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}()
|
||||||
|
for range time.Tick(time.Duration(s.iConfig.Period) * time.Millisecond) {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
frame := s.collectDeviceState()
|
||||||
|
err := s.client.Send(frame.encode())
|
||||||
|
if err != nil {
|
||||||
|
logger().Error("向联锁发送数据失败", "error", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *serviceContext) collectDeviceState() *ToInterlockFrame {
|
||||||
|
wd := entity.GetWorldData(s.sim.World)
|
||||||
|
frame := &ToInterlockFrame{}
|
||||||
|
//道岔
|
||||||
|
for _, row := range s.deviceTable.TurnoutMap {
|
||||||
|
entry := wd.EntityMap[row.uid]
|
||||||
|
pos := component.TurnoutPositionType.Get(entry)
|
||||||
|
state := GetStateByte(pos.Db)
|
||||||
|
var current1 byte
|
||||||
|
var current2 byte
|
||||||
|
if entry.HasComponent(component.TurnoutZzjType) {
|
||||||
|
zzjList := component.TurnoutZzjType.Get(entry).ZzjList
|
||||||
|
for i, zzj := range zzjList {
|
||||||
|
speed := component.FixedPositionTransformType.Get(zzj).Speed
|
||||||
|
if speed != 0 {
|
||||||
|
switch i {
|
||||||
|
case 0:
|
||||||
|
current1 = 100
|
||||||
|
case 1:
|
||||||
|
current2 = 100
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame.TurnoutStates = append(frame.TurnoutStates, &TurnoutState{
|
||||||
|
Id: row.index,
|
||||||
|
State: state,
|
||||||
|
Alarm: 0,
|
||||||
|
Current1: current1,
|
||||||
|
Current2: current2,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//屏蔽门
|
||||||
|
for _, row := range s.deviceTable.PsdMap {
|
||||||
|
entry := wd.EntityMap[row.uid]
|
||||||
|
psdState := component.PsdStateType.Get(entry)
|
||||||
|
mkxBytes := make([]byte, 0, 3)
|
||||||
|
for _, mkxRelayUid := range []string{row.relateDeviceMap[POB], row.relateDeviceMap[PCB], row.relateDeviceMap[DPB]} {
|
||||||
|
if mkxRelayUid == "" {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mkxBytes = append(mkxBytes, GetStateByte(component.BitStateType.Get(wd.EntityMap[mkxRelayUid]).Val))
|
||||||
|
}
|
||||||
|
frame.PsdStates = append(frame.PsdStates, &PSDState{
|
||||||
|
Id: row.index,
|
||||||
|
State: GetStateByte(psdState.Close),
|
||||||
|
Hsjc: GetStateByte(psdState.InterlockRelease),
|
||||||
|
PCB: mkxBytes[0],
|
||||||
|
POB: mkxBytes[1],
|
||||||
|
DPB: mkxBytes[2],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//紧急停车
|
||||||
|
for _, row := range s.deviceTable.EsbMap {
|
||||||
|
esb := s.sim.Repo.FindEsb(row.uid)
|
||||||
|
relay := wd.EntityMap[esb.RelayId()]
|
||||||
|
pla := wd.EntityMap[esb.PlaId()]
|
||||||
|
frame.ESBStates = append(frame.ESBStates, &ESBState{
|
||||||
|
Id: row.index,
|
||||||
|
State: GetStateByte(!component.BitStateType.Get(relay).Val),
|
||||||
|
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//信号机
|
||||||
|
for _, row := range s.deviceTable.SignalMap {
|
||||||
|
entry := wd.EntityMap[row.uid]
|
||||||
|
lights := component.SignalLightsType.Get(entry)
|
||||||
|
var current byte
|
||||||
|
for _, light := range lights.Lights {
|
||||||
|
if component.BitStateType.Get(light).Val {
|
||||||
|
current = 100
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
frame.SignalStates = append(frame.SignalStates, &SignalState{
|
||||||
|
Id: row.index,
|
||||||
|
State: 1, //目前还不知道每种显示对应什么字节,先这样
|
||||||
|
Current: current,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//计轴区段
|
||||||
|
for _, row := range s.deviceTable.AxleSectionMap {
|
||||||
|
entry := wd.EntityMap[row.uid]
|
||||||
|
axleManager := component.AxleManagerType.Get(entry)
|
||||||
|
frame.AxleSectionStates = append(frame.AxleSectionStates, &AxleSectionState{
|
||||||
|
Id: row.index,
|
||||||
|
State: GetStateByte(axleManager.Occupied),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//SPKS
|
||||||
|
for _, row := range s.deviceTable.SpksMap {
|
||||||
|
spks := s.sim.Repo.FindSpks(row.uid)
|
||||||
|
relay := wd.EntityMap[spks.Relay()]
|
||||||
|
pla := wd.EntityMap[spks.PlaId()]
|
||||||
|
frame.SPKSStates = append(frame.SPKSStates, &SPKSState{
|
||||||
|
Id: row.index,
|
||||||
|
State: GetStateByte(component.BitStateType.Get(relay).Val),
|
||||||
|
PlState: GetStateByte(component.BitStateType.Get(pla).Val),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return frame
|
||||||
|
}
|
||||||
|
|
||||||
|
func logger() *slog.Logger {
|
||||||
|
loggerInit.Do(func() {
|
||||||
|
privateLogger = slog.Default().With("tag", logTag)
|
||||||
|
})
|
||||||
|
return privateLogger
|
||||||
|
}
|
||||||
|
58
third_party/interlock/beijing12/interlock.go
vendored
58
third_party/interlock/beijing12/interlock.go
vendored
@ -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()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
11
third_party/message/dynamics.go
vendored
11
third_party/message/dynamics.go
vendored
@ -78,7 +78,7 @@ type DynamicsTrainInfo struct {
|
|||||||
//此次计算所使用的半实物消息的生命信号
|
//此次计算所使用的半实物消息的生命信号
|
||||||
VobcLifeSignal uint16
|
VobcLifeSignal uint16
|
||||||
//位移(mm)
|
//位移(mm)
|
||||||
Displacement uint16
|
Displacement float32
|
||||||
TrainActToMax bool
|
TrainActToMax bool
|
||||||
TrainActToMin bool
|
TrainActToMin bool
|
||||||
UpdateTime int64
|
UpdateTime int64
|
||||||
@ -86,6 +86,7 @@ type DynamicsTrainInfo struct {
|
|||||||
|
|
||||||
// 解析动力学的列车信息
|
// 解析动力学的列车信息
|
||||||
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])
|
||||||
@ -119,7 +120,13 @@ 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()
|
t.UpdateTime = time.Now().UnixMilli()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
2
third_party/message/radar.go
vendored
2
third_party/message/radar.go
vendored
@ -30,7 +30,7 @@ type RadarInfo struct {
|
|||||||
Tail byte
|
Tail byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewRadarSender(speed float32, forward bool, displacement uint16) *RadarInfo {
|
func NewRadarSender(speed float32, forward bool, displacement float32) *RadarInfo {
|
||||||
state := &RadarState{SwModel1: 1, SwModel0: 1, calculateBit: 1, signalQualityBit: 1, BlackoutBit: 0, DirectionState: 1, Direction: IsTrue(forward)}
|
state := &RadarState{SwModel1: 1, SwModel0: 1, calculateBit: 1, signalQualityBit: 1, BlackoutBit: 0, DirectionState: 1, Direction: IsTrue(forward)}
|
||||||
ri := &RadarInfo{State: state}
|
ri := &RadarInfo{State: state}
|
||||||
ri.RealSpeed = uint16(math.Abs(float64(speed*3.6) / fixed_speed))
|
ri.RealSpeed = uint16(math.Abs(float64(speed*3.6) / fixed_speed))
|
||||||
|
41
third_party/message/train_pc_sim_message.go
vendored
41
third_party/message/train_pc_sim_message.go
vendored
@ -121,35 +121,36 @@ func AtpLowPowerByte(d byte) bool {
|
|||||||
|
|
||||||
// 列车速度位置报告
|
// 列车速度位置报告
|
||||||
type TrainSpeedPlaceReportMsg struct {
|
type TrainSpeedPlaceReportMsg struct {
|
||||||
PulseCount1 uint32
|
PulseCount1 float32
|
||||||
PulseCount2 uint32
|
PulseCount2 float32
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tp *TrainSpeedPlaceReportMsg) ParsePulseCount1(s1, s2 uint32) {
|
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir uint16, s1, runRange uint32) []byte {
|
||||||
tp.PulseCount1 += s1
|
|
||||||
tp.PulseCount2 += s2
|
|
||||||
}
|
|
||||||
func (tp *TrainSpeedPlaceReportMsg) Encode(runDir bool, s1, s2 uint32) []byte {
|
|
||||||
data := make([]byte, 0)
|
data := make([]byte, 0)
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(IsTrue(runDir)))
|
|
||||||
|
data = binary.BigEndian.AppendUint16(data, runDir)
|
||||||
|
|
||||||
|
data = binary.BigEndian.AppendUint32(data, s1)
|
||||||
data = binary.BigEndian.AppendUint32(data, s1)
|
data = binary.BigEndian.AppendUint32(data, s1)
|
||||||
data = binary.BigEndian.AppendUint32(data, s2)
|
|
||||||
data = binary.BigEndian.AppendUint32(data, tp.PulseCount1)
|
|
||||||
data = binary.BigEndian.AppendUint32(data, tp.PulseCount2)
|
|
||||||
now := time.Now().UTC()
|
|
||||||
// 将时间转换为毫秒
|
|
||||||
millis := now.UnixNano() / int64(time.Millisecond)
|
|
||||||
millisStr := strconv.Itoa(int(millis))
|
|
||||||
strs := []rune(millisStr)
|
|
||||||
|
|
||||||
second, _ := strconv.Atoi(string(strs[:len(strs)-3]))
|
data = binary.BigEndian.AppendUint32(data, runRange)
|
||||||
mm, _ := strconv.Atoi(string(strs[len(strs)-3:]))
|
data = binary.BigEndian.AppendUint32(data, runRange)
|
||||||
data = binary.BigEndian.AppendUint32(data, uint32(second))
|
|
||||||
data = binary.BigEndian.AppendUint16(data, uint16(mm))
|
|
||||||
|
|
||||||
|
sec, ms := tp.time()
|
||||||
|
data = binary.BigEndian.AppendUint32(data, sec)
|
||||||
|
data = binary.BigEndian.AppendUint16(data, ms)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (tp *TrainSpeedPlaceReportMsg) time() (uint32, uint16) {
|
||||||
|
now := time.Now().UnixMilli()
|
||||||
|
timeNowStr := strconv.Itoa(int(now))
|
||||||
|
timeStrs := []rune(timeNowStr)
|
||||||
|
sec, _ := strconv.Atoi(string(timeStrs[5:10]))
|
||||||
|
ms, _ := strconv.Atoi(string(timeStrs[10:]))
|
||||||
|
return uint32(sec), uint16(ms)
|
||||||
|
}
|
||||||
|
|
||||||
func (tp *TrainSpeedPlaceReportMsg) Decode(d []byte) {
|
func (tp *TrainSpeedPlaceReportMsg) Decode(d []byte) {
|
||||||
buf := bytes.NewBuffer(d)
|
buf := bytes.NewBuffer(d)
|
||||||
var runDir uint16
|
var runDir uint16
|
||||||
|
110
third_party/train_pc_sim/train_pc_sim.go
vendored
110
third_party/train_pc_sim/train_pc_sim.go
vendored
@ -37,7 +37,7 @@ type TrainPcSim interface {
|
|||||||
SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool)
|
SendTrainDirection(train *state_proto.TrainState, trainForward, trainBackward bool)
|
||||||
//发送应答器信息数据
|
//发送应答器信息数据
|
||||||
SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte)
|
SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte)
|
||||||
SendBaliseData2(train *state_proto.TrainState, msgType byte, data []string)
|
|
||||||
//发布列车控制的相关事件
|
//发布列车控制的相关事件
|
||||||
//PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent)
|
//PublishTrainControlEvent(train *state_proto.TrainState, events []TrainControlEvent)
|
||||||
|
|
||||||
@ -48,8 +48,7 @@ type TrainPcSim interface {
|
|||||||
CreateOrRemoveTrain(train *state_proto.TrainState, isCreate bool) error
|
CreateOrRemoveTrain(train *state_proto.TrainState, isCreate bool) error
|
||||||
// TrainPluseCount 计算列车脉冲
|
// TrainPluseCount 计算列车脉冲
|
||||||
TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32)
|
TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32)
|
||||||
ResetPluseCount(sta *state_proto.TrainState)
|
|
||||||
//FindAllThirdPartState() []tpapi.ThirdPartyApiService
|
|
||||||
DsnAddAndReturn() byte
|
DsnAddAndReturn() byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -74,7 +73,8 @@ type TrainPcSimManage interface {
|
|||||||
type trainPcSimService struct {
|
type trainPcSimService struct {
|
||||||
state tpapi.ThirdPartyApiServiceState
|
state tpapi.ThirdPartyApiServiceState
|
||||||
newPcSimclientMap map[string]*TrainPcReciverData
|
newPcSimclientMap map[string]*TrainPcReciverData
|
||||||
cancleContext context.CancelFunc
|
cancleContextFun context.CancelFunc
|
||||||
|
context context.Context
|
||||||
trainPcSimManage TrainPcSimManage
|
trainPcSimManage TrainPcSimManage
|
||||||
configs []config.VehiclePCSimConfig
|
configs []config.VehiclePCSimConfig
|
||||||
btmDsn uint8
|
btmDsn uint8
|
||||||
@ -137,44 +137,70 @@ func (d *trainPcSimService) findAllThirdPartState() []tpapi.ThirdPartyApiService
|
|||||||
return services
|
return services
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 速度(单位mm/s)对应的脉冲数:速度*200/pi/840;
|
||||||
|
// 里程(单位mm)对应的脉冲:总里程*200/pi/840
|
||||||
func pluseCountSpeed(wheelDiameter int32, speedMeter float32) uint32 {
|
func pluseCountSpeed(wheelDiameter int32, speedMeter float32) uint32 {
|
||||||
s1 := speedMeter * 1000
|
|
||||||
pluseCountData := s1 * 200 / math.Pi / float32(wheelDiameter)
|
|
||||||
|
|
||||||
|
pluseCountData := speedMeter * 200 / math.Pi / float32(wheelDiameter)
|
||||||
return uint32(pluseCountData)
|
return uint32(pluseCountData)
|
||||||
}
|
}
|
||||||
func (d *trainPcSimService) ResetPluseCount(sta *state_proto.TrainState) {
|
|
||||||
if sd, err := d.findTrainConn(sta); err == nil {
|
func (d *trainPcSimService) pluseSpeed(sta *state_proto.TrainState) (uint32, float32) {
|
||||||
sd.speedPlace.PulseCount1 = 0
|
defer initLock.Unlock()
|
||||||
sd.speedPlace.PulseCount2 = 0
|
initLock.Lock()
|
||||||
|
var sum float32 = 0
|
||||||
|
pcLen := len(sta.PluseCount.PulseCount3)
|
||||||
|
if pcLen == 0 {
|
||||||
|
return 0, 0
|
||||||
}
|
}
|
||||||
|
for _, f := range sta.PluseCount.PulseCount3 {
|
||||||
|
sum += f
|
||||||
|
}
|
||||||
|
d.TrainPluseCountReset(sta)
|
||||||
|
speed := sum / float32(pcLen)
|
||||||
|
return pluseCountSpeed(sta.WheelDiameter, speed*1000), speed
|
||||||
|
|
||||||
}
|
}
|
||||||
func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
|
func (d *trainPcSimService) TrainPluseCount(sta *state_proto.TrainState, h1, h2, t1, t2 float32) {
|
||||||
defer initLock.Unlock()
|
defer initLock.Unlock()
|
||||||
initLock.Lock()
|
initLock.Lock()
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-d.context.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if sd, err := d.findTrainConn(sta); err == nil {
|
||||||
|
sd.speedPlace.PulseCount1 += sta.DynamicState.Displacement
|
||||||
|
//sd.speedPlace.PulseCount1 += float32(uint32(h1 * 10))
|
||||||
|
sd.speedPlace.PulseCount2 = sd.speedPlace.PulseCount1
|
||||||
|
}
|
||||||
if sta.TrainRunUp {
|
if sta.TrainRunUp {
|
||||||
if sta.TrainEndsA.SpeedSensorEnableA {
|
if sta.TrainEndsA.SpeedSensorEnableA {
|
||||||
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, h1)
|
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, h1)
|
||||||
|
sta.PluseCount.PulseCount3 = append(sta.PluseCount.PulseCount3, h1)
|
||||||
}
|
}
|
||||||
if sta.TrainEndsA.SpeedSensorEnableB {
|
if sta.TrainEndsA.SpeedSensorEnableB {
|
||||||
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, h2)
|
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, h2)
|
||||||
|
sta.PluseCount.PulseCount4 = append(sta.PluseCount.PulseCount3, h2)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if sta.TrainEndsB.SpeedSensorEnableA {
|
if sta.TrainEndsB.SpeedSensorEnableA {
|
||||||
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, t1)
|
sta.PluseCount.PulseCount1 = pluseCountSpeed(sta.WheelDiameter, t1)
|
||||||
|
sta.PluseCount.PulseCount3 = append(sta.PluseCount.PulseCount3, t1)
|
||||||
}
|
}
|
||||||
if sta.TrainEndsB.SpeedSensorEnableB {
|
if sta.TrainEndsB.SpeedSensorEnableB {
|
||||||
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, t2)
|
sta.PluseCount.PulseCount2 = pluseCountSpeed(sta.WheelDiameter, t2)
|
||||||
|
sta.PluseCount.PulseCount4 = append(sta.PluseCount.PulseCount3, t2)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) TrainPluseCountReset(sta *state_proto.TrainState) {
|
func (d *trainPcSimService) TrainPluseCountReset(sta *state_proto.TrainState) {
|
||||||
defer initLock.Unlock()
|
|
||||||
initLock.Lock()
|
|
||||||
sta.PluseCount.PulseCount1 = 0
|
sta.PluseCount.PulseCount1 = 0
|
||||||
sta.PluseCount.PulseCount2 = 0
|
sta.PluseCount.PulseCount2 = 0
|
||||||
|
sta.PluseCount.PulseCount3 = make([]float32, 0)
|
||||||
|
sta.PluseCount.PulseCount4 = make([]float32, 0)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) newCloseAllConn() {
|
func (d *trainPcSimService) newCloseAllConn() {
|
||||||
@ -191,6 +217,7 @@ func (d *trainPcSimService) newCloseConn(clientKey string) {
|
|||||||
rd.tcpClient = nil
|
rd.tcpClient = nil
|
||||||
rd.train = nil
|
rd.train = nil
|
||||||
rd.speedPlace = nil
|
rd.speedPlace = nil
|
||||||
|
rd.trainInit = false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,9 +286,9 @@ func (d *trainPcSimService) Start(pcSimManage TrainPcSimManage) {
|
|||||||
|
|
||||||
d.configs = configs
|
d.configs = configs
|
||||||
ctx, ctxFun := context.WithCancel(context.Background())
|
ctx, ctxFun := context.WithCancel(context.Background())
|
||||||
d.cancleContext = ctxFun
|
d.cancleContextFun = ctxFun
|
||||||
|
d.context = ctx
|
||||||
d.trainPcSimManage = pcSimManage
|
d.trainPcSimManage = pcSimManage
|
||||||
//d.connTrainPcSim(ctx)
|
|
||||||
go d.sendTrainLocationAndSpeedTask(ctx)
|
go d.sendTrainLocationAndSpeedTask(ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,9 +296,9 @@ func (d *trainPcSimService) Stop() {
|
|||||||
for _, data := range d.newPcSimclientMap {
|
for _, data := range d.newPcSimclientMap {
|
||||||
data.updateState(tpapi.ThirdPartyState_Closed)
|
data.updateState(tpapi.ThirdPartyState_Closed)
|
||||||
}
|
}
|
||||||
if d.cancleContext != nil {
|
if d.cancleContextFun != nil {
|
||||||
d.cancleContext()
|
d.cancleContextFun()
|
||||||
d.cancleContext = nil
|
d.cancleContextFun = nil
|
||||||
}
|
}
|
||||||
d.newCloseAllConn()
|
d.newCloseAllConn()
|
||||||
}
|
}
|
||||||
@ -303,13 +330,13 @@ func (d *trainPcSimService) CreateOrRemoveTrain(train *state_proto.TrainState, i
|
|||||||
func (d *trainPcSimService) initTrain(rd *TrainPcReciverData, train *state_proto.TrainState, isCreate bool, trains *message.TrainPcSimBaseMessage) error {
|
func (d *trainPcSimService) initTrain(rd *TrainPcReciverData, train *state_proto.TrainState, isCreate bool, trains *message.TrainPcSimBaseMessage) error {
|
||||||
msgs := make([]message.TrainPcSimBaseMessage, 0)
|
msgs := make([]message.TrainPcSimBaseMessage, 0)
|
||||||
sendMsg := make([]byte, 0)
|
sendMsg := make([]byte, 0)
|
||||||
|
rd.speedPlace = &message.TrainSpeedPlaceReportMsg{}
|
||||||
|
train.PluseCount = &state_proto.SensorSpeedPulseCount{}
|
||||||
|
rd.train = train
|
||||||
|
tcc := train.Tcc
|
||||||
|
tcc.LineInitTimeStamp12 = 0
|
||||||
|
tcc.Line12ConnErr = false
|
||||||
if isCreate {
|
if isCreate {
|
||||||
rd.speedPlace = &message.TrainSpeedPlaceReportMsg{}
|
|
||||||
train.PluseCount = &state_proto.SensorSpeedPulseCount{}
|
|
||||||
rd.train = train
|
|
||||||
tcc := train.Tcc
|
|
||||||
tcc.LineInitTimeStamp12 = 0
|
|
||||||
tcc.Line12ConnErr = false
|
|
||||||
tmpMsgs := d.trainPcSimManage.ObtainTrainDigitalMockData(train)
|
tmpMsgs := d.trainPcSimManage.ObtainTrainDigitalMockData(train)
|
||||||
msgs = append(msgs, tmpMsgs...)
|
msgs = append(msgs, tmpMsgs...)
|
||||||
msgs = append(msgs, message.TrainPcSimBaseMessage{Data: []byte{0x00}, Type: message.RECIVE_TRAIN_DOOR_MODE}) //门模式
|
msgs = append(msgs, message.TrainPcSimBaseMessage{Data: []byte{0x00}, Type: message.RECIVE_TRAIN_DOOR_MODE}) //门模式
|
||||||
@ -317,7 +344,7 @@ func (d *trainPcSimService) initTrain(rd *TrainPcReciverData, train *state_proto
|
|||||||
} else {
|
} else {
|
||||||
train.VobcState.Tc1Active = false
|
train.VobcState.Tc1Active = false
|
||||||
train.VobcState.Tc2Active = false
|
train.VobcState.Tc2Active = false
|
||||||
tcc := train.Tcc
|
|
||||||
for _, key := range tcc.DriverKey {
|
for _, key := range tcc.DriverKey {
|
||||||
key.Val = false
|
key.Val = false
|
||||||
}
|
}
|
||||||
@ -358,20 +385,22 @@ func (d *trainPcSimService) sendTrainLocationAndSpeedTask(ctx context.Context) {
|
|||||||
connState = tpapi.ThirdPartyState_Broken
|
connState = tpapi.ThirdPartyState_Broken
|
||||||
}
|
}
|
||||||
trainClient.updateState(connState)
|
trainClient.updateState(connState)
|
||||||
s1, s2 := train.PluseCount.PulseCount1, train.PluseCount.PulseCount2
|
s1, _ := d.pluseSpeed(train)
|
||||||
trainClient.speedPlace.ParsePulseCount1(s1, s2)
|
runDir := uint16(2)
|
||||||
data := trainClient.speedPlace.Encode(train.TrainRunUp, s1, s2)
|
if train.Tcc.DirKey.Val == 1 {
|
||||||
|
runDir = 1
|
||||||
|
}
|
||||||
|
disPluse := pluseCountSpeed(train.WheelDiameter, trainClient.speedPlace.PulseCount1)
|
||||||
|
data := trainClient.speedPlace.Encode(runDir, s1, disPluse)
|
||||||
bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
|
bm := &message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_LOCATION_INFO, Data: data}
|
||||||
d.TrainPluseCountReset(train)
|
|
||||||
dataCode := bm.Encode()
|
dataCode := bm.Encode()
|
||||||
//slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,s1: %v,s2: %v,c2: %v,c2: %v,发送数据:%v", train.Id, s1, s2, trainClient.speedPlace.PulseCount1, trainClient.speedPlace.PulseCount2, hex.EncodeToString(dataCode)))
|
//slog.Info(fmt.Sprintf("发送列车速度位置,列车:%v,列车速度:%v,计数脉冲: %v,累计里程: %v ,发送数据:%v", train.Id, speed, s1, trainClient.speedPlace.PulseCount1, hex.EncodeToString(dataCode)))
|
||||||
err := trainClient.tcpClient.Send(dataCode)
|
err := trainClient.tcpClient.Send(dataCode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode)))
|
slog.Error(fmt.Sprintf("发送列车速度位置失败,列车:%v,发送数据:%v", train.Id, hex.EncodeToString(dataCode)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
time.Sleep(time.Millisecond * 80)
|
time.Sleep(time.Millisecond * 80)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -489,25 +518,6 @@ func (d *trainPcSimService) SendTrainDirection(train *state_proto.TrainState, tr
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (d *trainPcSimService) SendBaliseData2(train *state_proto.TrainState, msgType byte, data []string) {
|
|
||||||
trainClient, trainDataErr := d.findTrainConn(train)
|
|
||||||
if trainDataErr != nil {
|
|
||||||
slog.Error(fmt.Sprintf("发送列车PC仿真应答器信息失败2,未找到列车连接,trainId:%v", train.Id))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, hexData := range data {
|
|
||||||
dd, _ := hex.DecodeString(hexData)
|
|
||||||
msg := &message.TrainPcSimBaseMessage{Type: msgType, Data: dd}
|
|
||||||
|
|
||||||
da := msg.Encode()
|
|
||||||
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%X,数据:%v", msgType, hex.EncodeToString(da)))
|
|
||||||
err := trainClient.tcpClient.Send(da)
|
|
||||||
if err != nil {
|
|
||||||
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte) {
|
func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgType byte, data []byte) {
|
||||||
trainClient, trainDataErr := d.findTrainConn(train)
|
trainClient, trainDataErr := d.findTrainConn(train)
|
||||||
if trainDataErr != nil {
|
if trainDataErr != nil {
|
||||||
@ -519,7 +529,7 @@ func (d *trainPcSimService) SendBaliseData(train *state_proto.TrainState, msgTyp
|
|||||||
msg.Data = data
|
msg.Data = data
|
||||||
|
|
||||||
da := msg.Encode()
|
da := msg.Encode()
|
||||||
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%x,源数据长度:%v,数据:%v", msgType, len(data), hex.EncodeToString(da)))
|
//slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息,数据类型:0x%x,源数据长度:%v,数据:%v", msgType, len(data), hex.EncodeToString(da)))
|
||||||
err := trainClient.tcpClient.Send(da)
|
err := trainClient.tcpClient.Send(da)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da)))
|
slog.Info(fmt.Sprintf("发送列车PC仿真应答器信息失败,数据:%v", hex.EncodeToString(da)))
|
||||||
|
@ -99,7 +99,7 @@ func findTrainTccGraphicDataHandler(tccG *data_proto.TccGraphicStorage, id uint3
|
|||||||
}
|
}
|
||||||
|
|
||||||
func initTrainVobc(trainLoad int64, trainIsUp bool) (*state_proto.TrainVobcState, uint32) {
|
func initTrainVobc(trainLoad int64, trainIsUp bool) (*state_proto.TrainVobcState, uint32) {
|
||||||
vobc := &state_proto.TrainVobcState{TrainLoad: int64(trainLoad), BrakingStatus: true, BrakeForce: 100, DirectionForward: true,
|
vobc := &state_proto.TrainVobcState{TrainLoad: int64(trainLoad), BrakingStatus: true, BrakeForce: DEFAULT_BRAKE_FORCE * 100, DirectionForward: true,
|
||||||
AllDoorClose: true, ObstacleCheckBtn: true, RightDoorCloseCommand: true, LeftDoorCloseCommand: true, BrakeHeavyFault: true, AtpCutSwitch: true,
|
AllDoorClose: true, ObstacleCheckBtn: true, RightDoorCloseCommand: true, LeftDoorCloseCommand: true, BrakeHeavyFault: true, AtpCutSwitch: true,
|
||||||
ConfirmBtn: true, AtpPowerOnBtn: true,
|
ConfirmBtn: true, AtpPowerOnBtn: true,
|
||||||
}
|
}
|
||||||
@ -116,7 +116,7 @@ func initTrainVobc(trainLoad int64, trainIsUp bool) (*state_proto.TrainVobcState
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 初始化列车控制数据
|
// 初始化列车控制数据
|
||||||
func initTrainTcc(vs *VerifySimulation, runDir bool, breaking int32) *state_proto.TrainControlState {
|
func initTrainTcc(vs *VerifySimulation) *state_proto.TrainControlState {
|
||||||
var tccGI *data_proto.TccGraphicStorage
|
var tccGI *data_proto.TccGraphicStorage
|
||||||
for _, id := range vs.MapIds {
|
for _, id := range vs.MapIds {
|
||||||
if QueryGiType(id) == data_proto.PictureType_TrainControlCab {
|
if QueryGiType(id) == data_proto.PictureType_TrainControlCab {
|
||||||
|
@ -13,59 +13,60 @@ import (
|
|||||||
"joylink.club/rtsssimulation/repository"
|
"joylink.club/rtsssimulation/repository"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 地图数据处理方法。目前用于不同通信协议所需数据的预处理
|
|
||||||
type MapDataHandler func(uidStructure *StationUidStructure, data *data_proto.RtssGraphicStorage)
|
|
||||||
|
|
||||||
var mapDataHandlerList = make([]MapDataHandler, 0)
|
|
||||||
|
|
||||||
func RegisterListener(handler MapDataHandler) {
|
|
||||||
mapDataHandlerList = append(mapDataHandlerList, handler)
|
|
||||||
}
|
|
||||||
|
|
||||||
var giUidMap sync.Map
|
var giUidMap sync.Map
|
||||||
|
|
||||||
type elementIdStructure struct {
|
// 设备的联系
|
||||||
|
type DeviceRelationship struct {
|
||||||
CommonId uint32
|
CommonId uint32
|
||||||
Code string
|
Code string
|
||||||
Uid string
|
Uid string
|
||||||
|
//设备所属集中站(此字段暂时仅给急需的设备赋值了)
|
||||||
|
CentralizedStations []*data_proto.Station
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *DeviceRelationship) GetCentralizedStations() []*data_proto.Station {
|
||||||
|
if d == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return d.CentralizedStations
|
||||||
}
|
}
|
||||||
|
|
||||||
// 列车控制
|
// 列车控制
|
||||||
type TccUidStructure struct {
|
type TccUidStructure struct {
|
||||||
ButtonIds map[uint32]*elementIdStructure
|
ButtonIds map[uint32]*DeviceRelationship
|
||||||
Keys map[uint32]*elementIdStructure
|
Keys map[uint32]*DeviceRelationship
|
||||||
Handler map[uint32]*elementIdStructure
|
Handler map[uint32]*DeviceRelationship
|
||||||
}
|
}
|
||||||
|
|
||||||
// 数组为Index为 common.ButtonCode, index, uid
|
// 数组为Index为 common.ButtonCode, index, uid
|
||||||
type StationUidStructure struct {
|
type StationUidStructure struct {
|
||||||
AxlePointIds map[uint32]*elementIdStructure
|
AxlePointIds map[uint32]*DeviceRelationship
|
||||||
TurnoutIds map[uint32]*elementIdStructure
|
TurnoutIds map[uint32]*DeviceRelationship
|
||||||
PhysicalSectionIds map[uint32]*elementIdStructure
|
PhysicalSectionIds map[uint32]*DeviceRelationship
|
||||||
SignalIds map[uint32]*elementIdStructure
|
SignalIds map[uint32]*DeviceRelationship
|
||||||
TransponderIds map[uint32]*elementIdStructure
|
TransponderIds map[uint32]*DeviceRelationship
|
||||||
SlopeIds map[uint32]*elementIdStructure
|
SlopeIds map[uint32]*DeviceRelationship
|
||||||
CurvatureIds map[uint32]*elementIdStructure
|
CurvatureIds map[uint32]*DeviceRelationship
|
||||||
ButtonIds map[uint32]*elementIdStructure
|
EsbIds map[uint32]*DeviceRelationship
|
||||||
StationIds map[uint32]*elementIdStructure
|
StationIds map[uint32]*DeviceRelationship
|
||||||
PlatformIds map[uint32]*elementIdStructure
|
PlatformIds map[uint32]*DeviceRelationship
|
||||||
PsdIds map[uint32]*elementIdStructure
|
PsdIds map[uint32]*DeviceRelationship
|
||||||
PslIds map[uint32]*elementIdStructure
|
PslIds map[uint32]*DeviceRelationship
|
||||||
SpksSwitchIds map[uint32]*elementIdStructure
|
SpksIds map[uint32]*DeviceRelationship
|
||||||
IbpIds map[uint32]*elementIdStructure
|
IbpIds map[uint32]*DeviceRelationship
|
||||||
CkmIds map[uint32]*elementIdStructure
|
CkmIds map[uint32]*DeviceRelationship
|
||||||
XcjIds map[uint32]*elementIdStructure
|
XcjIds map[uint32]*DeviceRelationship
|
||||||
}
|
}
|
||||||
|
|
||||||
type RelayUidStructure struct {
|
type RelayUidStructure struct {
|
||||||
RelayIds map[uint32]*elementIdStructure
|
RelayIds map[uint32]*DeviceRelationship
|
||||||
}
|
}
|
||||||
|
|
||||||
type IBPUidStructure struct {
|
type IBPUidStructure struct {
|
||||||
IbpButtonIds map[uint32]*elementIdStructure
|
IbpButtonIds map[uint32]*DeviceRelationship
|
||||||
IbpAlarmIds map[uint32]*elementIdStructure
|
IbpAlarmIds map[uint32]*DeviceRelationship
|
||||||
IbpKeyIds map[uint32]*elementIdStructure
|
IbpKeyIds map[uint32]*DeviceRelationship
|
||||||
IbpLightIds map[uint32]*elementIdStructure
|
IbpLightIds map[uint32]*DeviceRelationship
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取继电器的关联关系
|
// 获取继电器的关联关系
|
||||||
@ -93,10 +94,11 @@ func getMapELementCode(id uint32, code ...string) string {
|
|||||||
return strconv.Itoa(int(id))
|
return strconv.Itoa(int(id))
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取关联的车站名
|
// 获取车站信息
|
||||||
func handleRefStationName(stationMap map[uint32]*data_proto.Station, sid []uint32) []string {
|
func findStationInfos(stationMap map[uint32]*data_proto.Station, stationIds []uint32) ([]string, []*data_proto.Station) {
|
||||||
var stationNames []string
|
var stationNames []string
|
||||||
for _, id := range sid {
|
var stations []*data_proto.Station
|
||||||
|
for _, id := range stationIds {
|
||||||
if id == 0 {
|
if id == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -104,8 +106,9 @@ func handleRefStationName(stationMap map[uint32]*data_proto.Station, sid []uint3
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
stationNames = append(stationNames, stationMap[id].StationName)
|
stationNames = append(stationNames, stationMap[id].StationName)
|
||||||
|
stations = append(stations, stationMap[id])
|
||||||
}
|
}
|
||||||
return stationNames
|
return stationNames, stations
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取UID的前缀信息
|
// 获取UID的前缀信息
|
||||||
@ -249,22 +252,22 @@ func filterOtherLineDevice(data *data_proto.RtssGraphicStorage) {
|
|||||||
// 初始化平面布置图 UID
|
// 初始化平面布置图 UID
|
||||||
func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure {
|
func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure {
|
||||||
gus := &StationUidStructure{
|
gus := &StationUidStructure{
|
||||||
AxlePointIds: make(map[uint32]*elementIdStructure, len(data.AxleCountings)),
|
AxlePointIds: make(map[uint32]*DeviceRelationship, len(data.AxleCountings)),
|
||||||
TurnoutIds: make(map[uint32]*elementIdStructure, len(data.Turnouts)),
|
TurnoutIds: make(map[uint32]*DeviceRelationship, len(data.Turnouts)),
|
||||||
PhysicalSectionIds: make(map[uint32]*elementIdStructure, len(data.Section)),
|
PhysicalSectionIds: make(map[uint32]*DeviceRelationship, len(data.Section)),
|
||||||
SignalIds: make(map[uint32]*elementIdStructure, len(data.Signals)),
|
SignalIds: make(map[uint32]*DeviceRelationship, len(data.Signals)),
|
||||||
TransponderIds: make(map[uint32]*elementIdStructure, len(data.Transponders)),
|
TransponderIds: make(map[uint32]*DeviceRelationship, len(data.Transponders)),
|
||||||
SlopeIds: make(map[uint32]*elementIdStructure, len(data.Slopes)),
|
SlopeIds: make(map[uint32]*DeviceRelationship, len(data.Slopes)),
|
||||||
CurvatureIds: make(map[uint32]*elementIdStructure, len(data.Curvatures)),
|
CurvatureIds: make(map[uint32]*DeviceRelationship, len(data.Curvatures)),
|
||||||
ButtonIds: make(map[uint32]*elementIdStructure, len(data.EsbButtons)),
|
EsbIds: make(map[uint32]*DeviceRelationship, len(data.EsbButtons)),
|
||||||
StationIds: make(map[uint32]*elementIdStructure, len(data.Stations)),
|
StationIds: make(map[uint32]*DeviceRelationship, len(data.Stations)),
|
||||||
PlatformIds: make(map[uint32]*elementIdStructure, len(data.Platforms)),
|
PlatformIds: make(map[uint32]*DeviceRelationship, len(data.Platforms)),
|
||||||
PsdIds: make(map[uint32]*elementIdStructure, len(data.ScreenDoors)),
|
PsdIds: make(map[uint32]*DeviceRelationship, len(data.ScreenDoors)),
|
||||||
PslIds: make(map[uint32]*elementIdStructure, len(data.GateBoxs)),
|
PslIds: make(map[uint32]*DeviceRelationship, len(data.GateBoxs)),
|
||||||
//SpksSwitchIds: make(map[uint32]*elementIdStructure, len(data.SpksSwitchs)),
|
SpksIds: make(map[uint32]*DeviceRelationship, len(data.SpksSwitchs)),
|
||||||
IbpIds: make(map[uint32]*elementIdStructure, len(data.IbpBoxs)),
|
IbpIds: make(map[uint32]*DeviceRelationship, len(data.IbpBoxs)),
|
||||||
CkmIds: make(map[uint32]*elementIdStructure, len(data.GarageDoors)),
|
CkmIds: make(map[uint32]*DeviceRelationship, len(data.GarageDoors)),
|
||||||
XcjIds: make(map[uint32]*elementIdStructure, len(data.CarWashings)),
|
XcjIds: make(map[uint32]*DeviceRelationship, len(data.CarWashings)),
|
||||||
}
|
}
|
||||||
city, lineId, _ := getUIdPrefix(data.UniqueIdPrefix)
|
city, lineId, _ := getUIdPrefix(data.UniqueIdPrefix)
|
||||||
// 处理车站信息
|
// 处理车站信息
|
||||||
@ -273,81 +276,140 @@ func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure {
|
|||||||
eid := GetMapElementId(s.Common)
|
eid := GetMapElementId(s.Common)
|
||||||
stationName := getMapELementCode(eid, s.StationName, s.Code)
|
stationName := getMapELementCode(eid, s.StationName, s.Code)
|
||||||
stationMap[eid] = s
|
stationMap[eid] = s
|
||||||
gus.StationIds[eid] = &elementIdStructure{
|
gus.StationIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: stationName,
|
Code: stationName,
|
||||||
Uid: GenerateElementUid(city, lineId, nil, stationName),
|
Uid: BuildUid(city, lineId, stationName),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, station := range data.Stations {
|
||||||
|
if station.ConcentrationStations {
|
||||||
|
for _, subStation := range station.ManageStations {
|
||||||
|
gus.StationIds[subStation].CentralizedStations = append(gus.StationIds[subStation].CentralizedStations, station)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化计轴信息
|
// 初始化计轴信息
|
||||||
for _, a := range data.AxleCountings {
|
for _, a := range data.AxleCountings {
|
||||||
eid := GetMapElementId(a.Common)
|
eid := GetMapElementId(a.Common)
|
||||||
code := getMapELementCode(eid, a.Code)
|
code := getMapELementCode(eid, a.Code)
|
||||||
stationNames := handleRefStationName(stationMap, a.CentralizedStations)
|
cenStationNames, cenStations := findStationInfos(stationMap, a.CentralizedStations)
|
||||||
gus.AxlePointIds[eid] = &elementIdStructure{
|
gus.AxlePointIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: code,
|
Code: code,
|
||||||
Uid: GenerateElementUid(city, lineId, stationNames, code),
|
Uid: GenerateElementUid(city, lineId, cenStationNames, code),
|
||||||
|
CentralizedStations: cenStations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化道岔信息
|
// 初始化道岔信息
|
||||||
for _, t := range data.Turnouts {
|
for _, t := range data.Turnouts {
|
||||||
eid := GetMapElementId(t.Common)
|
eid := GetMapElementId(t.Common)
|
||||||
code := getMapELementCode(eid, t.Code)
|
code := getMapELementCode(eid, t.Code)
|
||||||
stationNames := handleRefStationName(stationMap, t.CentralizedStations)
|
cenStationNames, cenStations := findStationInfos(stationMap, t.CentralizedStations)
|
||||||
gus.TurnoutIds[eid] = &elementIdStructure{
|
gus.TurnoutIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: code,
|
Code: code,
|
||||||
Uid: GenerateElementUid(city, lineId, stationNames, code),
|
Uid: GenerateElementUid(city, lineId, cenStationNames, code),
|
||||||
|
CentralizedStations: cenStations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化物理区段信息
|
// 初始化物理区段信息
|
||||||
for _, s := range data.Section {
|
for _, s := range data.Section {
|
||||||
eid := GetMapElementId(s.Common)
|
eid := GetMapElementId(s.Common)
|
||||||
code := getMapELementCode(eid, s.Code)
|
code := getMapELementCode(eid, s.Code)
|
||||||
stationNames := handleRefStationName(stationMap, s.CentralizedStations)
|
cenStationNames, cenStations := findStationInfos(stationMap, s.CentralizedStations)
|
||||||
gus.PhysicalSectionIds[eid] = &elementIdStructure{
|
gus.PhysicalSectionIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: code,
|
Code: code,
|
||||||
Uid: GenerateElementUid(city, lineId, stationNames, code),
|
Uid: GenerateElementUid(city, lineId, cenStationNames, code),
|
||||||
|
CentralizedStations: cenStations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化信号机信息
|
// 初始化信号机信息
|
||||||
for _, s := range data.Signals {
|
for _, s := range data.Signals {
|
||||||
eid := GetMapElementId(s.Common)
|
eid := GetMapElementId(s.Common)
|
||||||
code := getMapELementCode(eid, s.Code)
|
code := getMapELementCode(eid, s.Code)
|
||||||
stationNames := handleRefStationName(stationMap, s.CentralizedStations)
|
cenStationNames, cenStations := findStationInfos(stationMap, s.CentralizedStations)
|
||||||
gus.SignalIds[eid] = &elementIdStructure{
|
gus.SignalIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: code,
|
Code: code,
|
||||||
Uid: GenerateElementUid(city, lineId, stationNames, code),
|
Uid: GenerateElementUid(city, lineId, cenStationNames, code),
|
||||||
|
CentralizedStations: cenStations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化应答器
|
// 初始化应答器
|
||||||
for _, t := range data.Transponders {
|
for _, t := range data.Transponders {
|
||||||
eid := GetMapElementId(t.Common)
|
eid := GetMapElementId(t.Common)
|
||||||
code := getMapELementCode(eid, t.Code)
|
code := getMapELementCode(eid, t.Code)
|
||||||
stationNames := handleRefStationName(stationMap, t.CentralizedStations)
|
cenStationNames, cenStations := findStationInfos(stationMap, t.CentralizedStations)
|
||||||
gus.TransponderIds[eid] = &elementIdStructure{
|
gus.TransponderIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: code,
|
Code: code,
|
||||||
Uid: GenerateElementUid(city, lineId, stationNames, code),
|
Uid: GenerateElementUid(city, lineId, cenStationNames, code),
|
||||||
|
CentralizedStations: cenStations,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化坡度
|
// 初始化坡度
|
||||||
for _, s := range data.Slopes {
|
for _, s := range data.Slopes {
|
||||||
eid := GetMapElementId(s.Common)
|
eid := GetMapElementId(s.Common)
|
||||||
gus.SlopeIds[eid] = &elementIdStructure{
|
gus.SlopeIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Uid: GenerateElementUid(city, lineId, nil, strconv.Itoa(int(eid))),
|
Uid: BuildUid(city, lineId, strconv.Itoa(int(eid))),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化曲线
|
// 初始化曲线
|
||||||
for _, c := range data.Curvatures {
|
for _, c := range data.Curvatures {
|
||||||
eid := GetMapElementId(c.Common)
|
eid := GetMapElementId(c.Common)
|
||||||
gus.CurvatureIds[eid] = &elementIdStructure{
|
gus.CurvatureIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Uid: GenerateElementUid(city, lineId, nil, strconv.Itoa(int(eid))),
|
Uid: BuildUid(city, lineId, strconv.Itoa(int(eid))),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 站台
|
||||||
|
platformMap := make(map[uint32]*data_proto.Platform)
|
||||||
|
for _, platform := range data.Platforms {
|
||||||
|
comId := platform.Common.Id
|
||||||
|
platformMap[comId] = platform
|
||||||
|
gus.PlatformIds[comId] = &DeviceRelationship{
|
||||||
|
CommonId: comId,
|
||||||
|
Code: platform.Code,
|
||||||
|
Uid: BuildUid(city, lineId, platform.Code),
|
||||||
|
CentralizedStations: gus.StationIds[platform.RefStationId].GetCentralizedStations(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 屏蔽门
|
||||||
|
for _, door := range data.ScreenDoors {
|
||||||
|
station := stationMap[platformMap[door.RefPlatformId].GetRefStationId()]
|
||||||
|
if station == nil { //线路数据有问题
|
||||||
|
slog.Error(fmt.Sprintf("线路[%s]屏蔽门[%s]关联关系有问题", lineId, door.Code))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
comId := door.Common.Id
|
||||||
|
gus.PsdIds[comId] = &DeviceRelationship{
|
||||||
|
CommonId: comId,
|
||||||
|
Code: door.Code,
|
||||||
|
Uid: BuildUid(city, lineId, station.StationName, door.Code),
|
||||||
|
CentralizedStations: gus.PlatformIds[door.RefPlatformId].GetCentralizedStations(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 紧急停车
|
||||||
|
for _, esb := range data.EsbButtons {
|
||||||
|
comId := esb.Common.Id
|
||||||
|
gus.EsbIds[comId] = &DeviceRelationship{
|
||||||
|
CommonId: comId,
|
||||||
|
Code: esb.Code,
|
||||||
|
Uid: BuildUid(city, lineId, gus.PlatformIds[esb.RefStand].Code, esb.Code),
|
||||||
|
CentralizedStations: gus.PlatformIds[esb.RefStand].GetCentralizedStations(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// SPKS
|
||||||
|
for _, spks := range data.SpksSwitchs {
|
||||||
|
commonId := spks.Common.Id
|
||||||
|
gus.SpksIds[commonId] = &DeviceRelationship{
|
||||||
|
CommonId: commonId,
|
||||||
|
Code: spks.Code,
|
||||||
|
Uid: BuildUid(city, lineId, gus.PlatformIds[spks.RefStand].Code, spks.Code),
|
||||||
|
CentralizedStations: gus.PlatformIds[spks.RefStand].GetCentralizedStations(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//处理车站关联的组合信息
|
//处理车站关联的组合信息
|
||||||
@ -360,62 +422,25 @@ func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 初始化站场图按钮
|
|
||||||
for _, b := range data.EsbButtons {
|
|
||||||
eid := GetMapElementId(b.Common)
|
|
||||||
p := refMap[eid]
|
|
||||||
code := b.Code
|
|
||||||
if p != nil {
|
|
||||||
code = p.deviceCode + "_" + p.typeCode + "_" + b.Code
|
|
||||||
}
|
|
||||||
gus.ButtonIds[eid] = &elementIdStructure{
|
|
||||||
CommonId: eid,
|
|
||||||
Code: b.Code,
|
|
||||||
Uid: GenerateElementUid(city, lineId, nil, code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 站台
|
|
||||||
platformMap := make(map[uint32]*data_proto.Platform)
|
|
||||||
for _, platform := range data.Platforms {
|
|
||||||
eid := GetMapElementId(platform.Common)
|
|
||||||
platformMap[eid] = platform
|
|
||||||
gus.PlatformIds[eid] = &elementIdStructure{
|
|
||||||
CommonId: eid,
|
|
||||||
Code: platform.Code,
|
|
||||||
Uid: GenerateElementUid(city, lineId, nil, platform.Code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// 屏蔽门
|
|
||||||
for _, door := range data.ScreenDoors {
|
|
||||||
station := stationMap[platformMap[door.RefPlatformId].GetRefStationId()]
|
|
||||||
if station == nil { //线路数据有问题
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
eid := GetMapElementId(door.Common)
|
|
||||||
gus.PsdIds[eid] = &elementIdStructure{
|
|
||||||
CommonId: eid,
|
|
||||||
Code: door.Code,
|
|
||||||
Uid: GenerateElementUid(city, lineId, []string{station.StationName}, door.Code),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// PSL
|
// PSL
|
||||||
for _, box := range data.PslBoxs {
|
for _, box := range data.PslBoxs {
|
||||||
stationName := stationMap[platformMap[box.RefPlatformId].RefStationId].StationName
|
stationName := stationMap[platformMap[box.RefPlatformId].RefStationId].StationName
|
||||||
eid := GetMapElementId(box.Common)
|
eid := GetMapElementId(box.Common)
|
||||||
gus.PslIds[eid] = &elementIdStructure{
|
gus.PslIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: box.Code,
|
Code: box.Code,
|
||||||
Uid: GenerateElementUid(city, lineId, []string{stationName}, box.Code),
|
Uid: BuildUid(city, lineId, stationName, box.Code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// IBP
|
// IBP
|
||||||
for _, box := range data.IbpBoxs {
|
for _, box := range data.IbpBoxs {
|
||||||
stationName := stationMap[box.RefStationId].StationName
|
stationName := stationMap[box.RefStationId].StationName
|
||||||
eid := GetMapElementId(box.Common)
|
eid := GetMapElementId(box.Common)
|
||||||
gus.IbpIds[eid] = &elementIdStructure{
|
gus.IbpIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: box.Code,
|
Code: box.Code,
|
||||||
Uid: GenerateElementUid(city, lineId, []string{stationName}, box.Code),
|
Uid: BuildUid(city, lineId, stationName, box.Code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 车库门
|
// 车库门
|
||||||
@ -429,27 +454,23 @@ func initStationUid(data *data_proto.RtssGraphicStorage) *StationUidStructure {
|
|||||||
// 洗车机
|
// 洗车机
|
||||||
for _, xcj := range data.CarWashings {
|
for _, xcj := range data.CarWashings {
|
||||||
eid := GetMapElementId(xcj.Common)
|
eid := GetMapElementId(xcj.Common)
|
||||||
gus.XcjIds[eid] = &elementIdStructure{
|
gus.XcjIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: xcj.Code,
|
Code: xcj.Code,
|
||||||
Uid: GenerateElementUid(city, lineId, nil, xcj.Code),
|
Uid: BuildUid(city, lineId, xcj.Code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//通信协议预处理所需数据
|
|
||||||
for _, handler := range mapDataHandlerList {
|
|
||||||
handler(gus, data)
|
|
||||||
}
|
|
||||||
return gus
|
return gus
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillCkmInfo(ckm *data_proto.GarageDoor, gus *StationUidStructure, city string, lineId string) {
|
func fillCkmInfo(ckm *data_proto.GarageDoor, gus *StationUidStructure, city string, lineId string) {
|
||||||
eid := GetMapElementId(ckm.Common)
|
eid := GetMapElementId(ckm.Common)
|
||||||
gus.CkmIds[eid] = &elementIdStructure{
|
gus.CkmIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: ckm.Code,
|
Code: ckm.Code,
|
||||||
Uid: GenerateElementUid(city, lineId, nil, ckm.Code),
|
Uid: BuildUid(city, lineId, ckm.Code),
|
||||||
}
|
}
|
||||||
gus.PslIds[eid] = &elementIdStructure{
|
gus.PslIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: ckm.Code,
|
Code: ckm.Code,
|
||||||
Uid: BuildUid(city, lineId, ckm.Code, "PSL"),
|
Uid: BuildUid(city, lineId, ckm.Code, "PSL"),
|
||||||
@ -458,22 +479,22 @@ func fillCkmInfo(ckm *data_proto.GarageDoor, gus *StationUidStructure, city stri
|
|||||||
|
|
||||||
// 初始化列车控制
|
// 初始化列车控制
|
||||||
func initTccUid(tcc *data_proto.TccGraphicStorage) *TccUidStructure {
|
func initTccUid(tcc *data_proto.TccGraphicStorage) *TccUidStructure {
|
||||||
tc := &TccUidStructure{ButtonIds: make(map[uint32]*elementIdStructure), Keys: make(map[uint32]*elementIdStructure), Handler: make(map[uint32]*elementIdStructure)}
|
tc := &TccUidStructure{ButtonIds: make(map[uint32]*DeviceRelationship), Keys: make(map[uint32]*DeviceRelationship), Handler: make(map[uint32]*DeviceRelationship)}
|
||||||
|
|
||||||
for _, d := range tcc.TccButtons {
|
for _, d := range tcc.TccButtons {
|
||||||
id := GetMapElementId(d.Common)
|
id := GetMapElementId(d.Common)
|
||||||
tc.ButtonIds[id] = &elementIdStructure{CommonId: id,
|
tc.ButtonIds[id] = &DeviceRelationship{CommonId: id,
|
||||||
Code: d.Code}
|
Code: d.Code}
|
||||||
}
|
}
|
||||||
for _, d := range tcc.TccKeys {
|
for _, d := range tcc.TccKeys {
|
||||||
id := GetMapElementId(d.Common)
|
id := GetMapElementId(d.Common)
|
||||||
tc.Keys[id] = &elementIdStructure{CommonId: id,
|
tc.Keys[id] = &DeviceRelationship{CommonId: id,
|
||||||
Code: d.Code}
|
Code: d.Code}
|
||||||
|
|
||||||
}
|
}
|
||||||
for _, d := range tcc.TccHandles {
|
for _, d := range tcc.TccHandles {
|
||||||
id := GetMapElementId(d.Common)
|
id := GetMapElementId(d.Common)
|
||||||
tc.Handler[id] = &elementIdStructure{CommonId: id,
|
tc.Handler[id] = &DeviceRelationship{CommonId: id,
|
||||||
Code: d.Code}
|
Code: d.Code}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -483,7 +504,7 @@ func initTccUid(tcc *data_proto.TccGraphicStorage) *TccUidStructure {
|
|||||||
// 初始化继电器柜 UID
|
// 初始化继电器柜 UID
|
||||||
func initRelayCabinetUid(data *data_proto.RelayCabinetGraphicStorage) *RelayUidStructure {
|
func initRelayCabinetUid(data *data_proto.RelayCabinetGraphicStorage) *RelayUidStructure {
|
||||||
rus := &RelayUidStructure{
|
rus := &RelayUidStructure{
|
||||||
RelayIds: make(map[uint32]*elementIdStructure, len(data.Relays)),
|
RelayIds: make(map[uint32]*DeviceRelationship, len(data.Relays)),
|
||||||
}
|
}
|
||||||
// 继电器所属设备
|
// 继电器所属设备
|
||||||
refMap := make(map[uint32]*deviceRelateUidPriex, len(data.Relays))
|
refMap := make(map[uint32]*deviceRelateUidPriex, len(data.Relays))
|
||||||
@ -507,14 +528,16 @@ func initRelayCabinetUid(data *data_proto.RelayCabinetGraphicStorage) *RelayUidS
|
|||||||
if p != nil {
|
if p != nil {
|
||||||
code = p.deviceCode + "_" + p.typeCode + "_" + r.Code
|
code = p.deviceCode + "_" + p.typeCode + "_" + r.Code
|
||||||
}
|
}
|
||||||
stationArr := []string{station}
|
var uid string
|
||||||
if p != nil && (p.isStation || p.isPSD) {
|
if p != nil && (p.isStation || p.isPSD) {
|
||||||
stationArr = nil
|
uid = BuildUid(city, lineId, code)
|
||||||
|
} else {
|
||||||
|
uid = BuildUid(city, lineId, station, code)
|
||||||
}
|
}
|
||||||
rus.RelayIds[eid] = &elementIdStructure{
|
rus.RelayIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: r.Code,
|
Code: r.Code,
|
||||||
Uid: GenerateElementUid(city, lineId, stationArr, code),
|
Uid: uid,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, r := range data.PhaseFailureProtectors {
|
for _, r := range data.PhaseFailureProtectors {
|
||||||
@ -524,14 +547,14 @@ func initRelayCabinetUid(data *data_proto.RelayCabinetGraphicStorage) *RelayUidS
|
|||||||
if p != nil {
|
if p != nil {
|
||||||
code = p.deviceCode + "_" + p.typeCode + "_" + r.Code
|
code = p.deviceCode + "_" + p.typeCode + "_" + r.Code
|
||||||
}
|
}
|
||||||
stationArr := []string{station}
|
stationName := station
|
||||||
if p != nil && (p.isStation || p.isPSD) {
|
if p != nil && (p.isStation || p.isPSD) {
|
||||||
stationArr = nil
|
stationName = ""
|
||||||
}
|
}
|
||||||
rus.RelayIds[eid] = &elementIdStructure{
|
rus.RelayIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: r.Code,
|
Code: r.Code,
|
||||||
Uid: GenerateElementUid(city, lineId, stationArr, code),
|
Uid: BuildUid(city, lineId, stationName, code),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rus
|
return rus
|
||||||
@ -540,10 +563,10 @@ func initRelayCabinetUid(data *data_proto.RelayCabinetGraphicStorage) *RelayUidS
|
|||||||
// 初始化IBP地图UID
|
// 初始化IBP地图UID
|
||||||
func initIBPUid(data *data_proto.IBPGraphicStorage) *IBPUidStructure {
|
func initIBPUid(data *data_proto.IBPGraphicStorage) *IBPUidStructure {
|
||||||
rus := &IBPUidStructure{
|
rus := &IBPUidStructure{
|
||||||
IbpButtonIds: make(map[uint32]*elementIdStructure),
|
IbpButtonIds: make(map[uint32]*DeviceRelationship),
|
||||||
IbpAlarmIds: make(map[uint32]*elementIdStructure),
|
IbpAlarmIds: make(map[uint32]*DeviceRelationship),
|
||||||
IbpKeyIds: make(map[uint32]*elementIdStructure),
|
IbpKeyIds: make(map[uint32]*DeviceRelationship),
|
||||||
IbpLightIds: make(map[uint32]*elementIdStructure),
|
IbpLightIds: make(map[uint32]*DeviceRelationship),
|
||||||
}
|
}
|
||||||
//处理继电器关联信息
|
//处理继电器关联信息
|
||||||
refMap := make(map[uint32]string)
|
refMap := make(map[uint32]string)
|
||||||
@ -564,7 +587,7 @@ func initIBPUid(data *data_proto.IBPGraphicStorage) *IBPUidStructure {
|
|||||||
// 处理按钮Uid
|
// 处理按钮Uid
|
||||||
for _, d := range data.IbpButtons {
|
for _, d := range data.IbpButtons {
|
||||||
eid := GetMapElementId(d.Common)
|
eid := GetMapElementId(d.Common)
|
||||||
rus.IbpButtonIds[eid] = &elementIdStructure{
|
rus.IbpButtonIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: d.Code,
|
Code: d.Code,
|
||||||
Uid: "button_" + codeFun(eid, d.Code),
|
Uid: "button_" + codeFun(eid, d.Code),
|
||||||
@ -573,7 +596,7 @@ func initIBPUid(data *data_proto.IBPGraphicStorage) *IBPUidStructure {
|
|||||||
// 处理钥匙Uid
|
// 处理钥匙Uid
|
||||||
for _, d := range data.IbpKeys {
|
for _, d := range data.IbpKeys {
|
||||||
eid := GetMapElementId(d.Common)
|
eid := GetMapElementId(d.Common)
|
||||||
rus.IbpKeyIds[eid] = &elementIdStructure{
|
rus.IbpKeyIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: d.Code,
|
Code: d.Code,
|
||||||
Uid: "key_" + codeFun(eid, d.Code),
|
Uid: "key_" + codeFun(eid, d.Code),
|
||||||
@ -582,7 +605,7 @@ func initIBPUid(data *data_proto.IBPGraphicStorage) *IBPUidStructure {
|
|||||||
// 处理报警器Uid
|
// 处理报警器Uid
|
||||||
for _, d := range data.IbpAlarms {
|
for _, d := range data.IbpAlarms {
|
||||||
eid := GetMapElementId(d.Common)
|
eid := GetMapElementId(d.Common)
|
||||||
rus.IbpAlarmIds[eid] = &elementIdStructure{
|
rus.IbpAlarmIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: d.Code,
|
Code: d.Code,
|
||||||
Uid: "alarm_" + codeFun(eid, d.Code),
|
Uid: "alarm_" + codeFun(eid, d.Code),
|
||||||
@ -591,7 +614,7 @@ func initIBPUid(data *data_proto.IBPGraphicStorage) *IBPUidStructure {
|
|||||||
// 处理指示灯Uid
|
// 处理指示灯Uid
|
||||||
for _, d := range data.IbpLights {
|
for _, d := range data.IbpLights {
|
||||||
eid := GetMapElementId(d.Common)
|
eid := GetMapElementId(d.Common)
|
||||||
rus.IbpLightIds[eid] = &elementIdStructure{
|
rus.IbpLightIds[eid] = &DeviceRelationship{
|
||||||
CommonId: eid,
|
CommonId: eid,
|
||||||
Code: d.Code,
|
Code: d.Code,
|
||||||
Uid: "light_" + codeFun(eid, d.Code),
|
Uid: "light_" + codeFun(eid, d.Code),
|
||||||
@ -601,12 +624,12 @@ func initIBPUid(data *data_proto.IBPGraphicStorage) *IBPUidStructure {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 构建仿真内所有地图UID映射信号布置图ID,这里为了解决多地图时根据UID反向寻找,避免多次循环地图,直接获取平面布置图元素
|
// 构建仿真内所有地图UID映射信号布置图ID,这里为了解决多地图时根据UID反向寻找,避免多次循环地图,直接获取平面布置图元素
|
||||||
func buildRepositoryAllUidsMap(mapIds []int32, repo *repository.Repository) map[string]*elementIdStructure {
|
func buildRepositoryAllUidsMap(mapIds []int32, repo *repository.Repository) map[string]*DeviceRelationship {
|
||||||
mapLen := len(repo.CheckPointList()) + len(repo.PhysicalSectionList()) + len(repo.SignalList()) +
|
mapLen := len(repo.CheckPointList()) + len(repo.PhysicalSectionList()) + len(repo.SignalList()) +
|
||||||
len(repo.TurnoutList()) + len(repo.ResponderList()) + len(repo.SlopeList()) +
|
len(repo.TurnoutList()) + len(repo.ResponderList()) + len(repo.SlopeList()) +
|
||||||
len(repo.SectionalCurvatureList())
|
len(repo.SectionalCurvatureList())
|
||||||
allUidMap := make(map[string]*elementIdStructure, mapLen)
|
allUidMap := make(map[string]*DeviceRelationship, mapLen)
|
||||||
saveToAllUidMap := func(es map[uint32]*elementIdStructure) {
|
saveToAllUidMap := func(es map[uint32]*DeviceRelationship) {
|
||||||
for _, e := range es {
|
for _, e := range es {
|
||||||
allUidMap[e.Uid] = e
|
allUidMap[e.Uid] = e
|
||||||
}
|
}
|
||||||
@ -625,8 +648,8 @@ func buildRepositoryAllUidsMap(mapIds []int32, repo *repository.Repository) map[
|
|||||||
saveToAllUidMap(u.TurnoutIds)
|
saveToAllUidMap(u.TurnoutIds)
|
||||||
saveToAllUidMap(u.SlopeIds)
|
saveToAllUidMap(u.SlopeIds)
|
||||||
saveToAllUidMap(u.CurvatureIds)
|
saveToAllUidMap(u.CurvatureIds)
|
||||||
saveToAllUidMap(u.ButtonIds)
|
saveToAllUidMap(u.EsbIds)
|
||||||
saveToAllUidMap(u.SpksSwitchIds)
|
saveToAllUidMap(u.SpksIds)
|
||||||
saveToAllUidMap(u.StationIds)
|
saveToAllUidMap(u.StationIds)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -644,7 +667,7 @@ func QueryUidStructure[T *StationUidStructure | *RelayUidStructure | *IBPUidStru
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 获取设备类型获取对应字段
|
// 获取设备类型获取对应字段
|
||||||
func getUidMapByType(uidData any, m interface{}) map[uint32]*elementIdStructure {
|
func getUidMapByType(uidData any, m interface{}) map[uint32]*DeviceRelationship {
|
||||||
switch m.(type) {
|
switch m.(type) {
|
||||||
case *data_proto.AxleCounting:
|
case *data_proto.AxleCounting:
|
||||||
return (uidData.(*StationUidStructure)).AxlePointIds
|
return (uidData.(*StationUidStructure)).AxlePointIds
|
||||||
@ -663,11 +686,11 @@ func getUidMapByType(uidData any, m interface{}) map[uint32]*elementIdStructure
|
|||||||
case *data_proto.Relay:
|
case *data_proto.Relay:
|
||||||
return (uidData.(*RelayUidStructure)).RelayIds
|
return (uidData.(*RelayUidStructure)).RelayIds
|
||||||
case *data_proto.EsbButton:
|
case *data_proto.EsbButton:
|
||||||
return (uidData.(*StationUidStructure)).ButtonIds
|
return (uidData.(*StationUidStructure)).EsbIds
|
||||||
case *data_proto.Station:
|
case *data_proto.Station:
|
||||||
return (uidData.(*StationUidStructure)).StationIds
|
return (uidData.(*StationUidStructure)).StationIds
|
||||||
case *data_proto.SpksSwitch:
|
case *data_proto.SpksSwitch:
|
||||||
return (uidData.(*StationUidStructure)).SpksSwitchIds
|
return (uidData.(*StationUidStructure)).SpksIds
|
||||||
case *data_proto.ScreenDoor:
|
case *data_proto.ScreenDoor:
|
||||||
return (uidData.(*StationUidStructure)).PsdIds
|
return (uidData.(*StationUidStructure)).PsdIds
|
||||||
case *data_proto.PslBox:
|
case *data_proto.PslBox:
|
||||||
@ -684,7 +707,7 @@ func getUidMapByType(uidData any, m interface{}) map[uint32]*elementIdStructure
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 根据地图ID跟设备类型获取UID集合
|
// 根据地图ID跟设备类型获取UID集合
|
||||||
func QueryMapUidMapByType(mapId int32, m interface{}) map[uint32]*elementIdStructure {
|
func QueryMapUidMapByType(mapId int32, m interface{}) map[uint32]*DeviceRelationship {
|
||||||
uidData, ok := giUidMap.Load(mapId)
|
uidData, ok := giUidMap.Load(mapId)
|
||||||
if !ok {
|
if !ok {
|
||||||
panic(&dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("地图【id:%d】不存在uid缓存", mapId)})
|
panic(&dto.ErrorDto{Code: dto.DataNotExist, Message: fmt.Sprintf("地图【id:%d】不存在uid缓存", mapId)})
|
||||||
|
@ -22,10 +22,19 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
DEFULAT_TRAIN_LOAD = 160
|
//列车总质量(吨)
|
||||||
DEFAULT_BRAKE_FORCE = 19040
|
DEFULAT_TRAIN_LOAD = 160
|
||||||
|
//通号最大制动力是-1.21
|
||||||
|
DEFAULT_BRAKE_FORCE = DEFULAT_TRAIN_LOAD * 1000 * 1.21 / 1000
|
||||||
|
//通号最大加速度是0.97
|
||||||
|
DEFAULT_TRAIN_TRACTION = DEFULAT_TRAIN_LOAD * 1000 * 0.97 / 1000 //千牛
|
||||||
|
DEFAULT_TRAIN_WORK = 2880 * 1000
|
||||||
|
DEFAULT_TRAIN_STARTED_SPEED = 0.003
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func culTrainTractionF(sta *state_proto.TrainState) {
|
||||||
|
|
||||||
|
}
|
||||||
func CreateMsgTrainConfig(trainId int, trainLen int64, configTrainData dto.ConfigTrainData) *message.TrainOperationConfig {
|
func CreateMsgTrainConfig(trainId int, trainLen int64, configTrainData dto.ConfigTrainData) *message.TrainOperationConfig {
|
||||||
return &message.TrainOperationConfig{TrainIndex: trainId, Length: int(trainLen),
|
return &message.TrainOperationConfig{TrainIndex: trainId, Length: int(trainLen),
|
||||||
DavisParamA: configTrainData.DavisParamA, DavisParamB: configTrainData.DavisParamB,
|
DavisParamA: configTrainData.DavisParamA, DavisParamB: configTrainData.DavisParamB,
|
||||||
@ -51,7 +60,7 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
|
|||||||
}
|
}
|
||||||
//向动力学发送初始化请求
|
//向动力学发送初始化请求
|
||||||
trainIndex, _ := strconv.ParseUint(status.Id, 10, 16)
|
trainIndex, _ := strconv.ParseUint(status.Id, 10, 16)
|
||||||
slog.Debug("添加列车", "trainIndex", trainIndex, "HeadDeviceId", status.HeadDeviceId, "HeadOffset", status.HeadOffset)
|
//slog.Debug("添加列车", "trainIndex", trainIndex, "HeadDeviceId", status.HeadDeviceId, "HeadOffset", status.HeadOffset)
|
||||||
// 映射link、偏移量、运行方向
|
// 映射link、偏移量、运行方向
|
||||||
var uid string
|
var uid string
|
||||||
if status.DevicePort == "" {
|
if status.DevicePort == "" {
|
||||||
@ -95,7 +104,7 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
|
|||||||
createOrUpdateStateDynamicConfig(status, configTrainData, trainEndsA, trainEndsB)
|
createOrUpdateStateDynamicConfig(status, configTrainData, trainEndsA, trainEndsB)
|
||||||
tl := configTrainData.TrainLoad
|
tl := configTrainData.TrainLoad
|
||||||
if tl <= 0 {
|
if tl <= 0 {
|
||||||
tl = DEFULAT_TRAIN_LOAD
|
tl = DEFULAT_TRAIN_LOAD * 100
|
||||||
}
|
}
|
||||||
|
|
||||||
vobc, _ := initTrainVobc(int64(tl), status.TrainRunUp)
|
vobc, _ := initTrainVobc(int64(tl), status.TrainRunUp)
|
||||||
@ -103,9 +112,9 @@ func AddTrainStateNew(vs *VerifySimulation, status *state_proto.TrainState, conf
|
|||||||
|
|
||||||
//status.TrainActiveDirection = trainActDir
|
//status.TrainActiveDirection = trainActDir
|
||||||
|
|
||||||
status.Tcc = initTrainTcc(vs, status.TrainRunUp, DEFAULT_BRAKE_FORCE)
|
status.Tcc = initTrainTcc(vs)
|
||||||
status.VobcBtm = &state_proto.VobcBtmState{TelegramState: make([]*state_proto.VobcBtmState_TelegramState, 0), History: make(map[uint32]*state_proto.VobcBtmState_VobcBtmHistoryState)}
|
status.VobcBtm = &state_proto.VobcBtmState{TelegramState: make([]*state_proto.VobcBtmState_TelegramState, 0), History: make(map[uint32]*state_proto.VobcBtmState_VobcBtmHistoryState)}
|
||||||
slog.Debug("列车初始化", "trainIndex", trainIndex, "linkId", linkId, "loffset", loffset)
|
//slog.Debug("列车初始化", "trainIndex", trainIndex, "linkId", linkId, "loffset", loffset)
|
||||||
linkIdInt, _ := strconv.Atoi(linkId)
|
linkIdInt, _ := strconv.Atoi(linkId)
|
||||||
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
|
err := dynamics.Default().RequestAddTrain(&message.InitTrainInfo{
|
||||||
TrainIndex: uint16(trainIndex),
|
TrainIndex: uint16(trainIndex),
|
||||||
@ -311,7 +320,7 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
|
|||||||
//pointTO 指的是是否ab,或是否到岔心
|
//pointTO 指的是是否ab,或是否到岔心
|
||||||
_, pointTo := QueryDirectionAndABByDevice(vs.Repo, id, port, info.Up)
|
_, pointTo := QueryDirectionAndABByDevice(vs.Repo, id, port, info.Up)
|
||||||
|
|
||||||
//slog.Debug("处理动力学转换后的消息", "number", info.Number, "up", info.Up, "Link", info.Link, "车头位置", id, "偏移", offset, "是否上行", runDirection, "是否ab", pointTo, "t1Dir:", info.TrainActToMax, "t2Dir:", info.TrainActToMin)
|
//slog.Debug("处理动力学转换后的消息", "number", info.Number, "up", info.Up, "Link", info.Link, "车头位置", id, "偏移", offset, "是否上行", true, "是否ab", pointTo, "t1Dir:", info.TrainActToMax, "t2Dir:", info.TrainActToMin)
|
||||||
trainHeadActUp := true
|
trainHeadActUp := true
|
||||||
if info.TrainActToMax || info.TrainActToMin {
|
if info.TrainActToMax || info.TrainActToMin {
|
||||||
if info.TrainActToMin {
|
if info.TrainActToMin {
|
||||||
@ -326,12 +335,22 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
|
|||||||
panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2))
|
panic(sys_error.New("动力学传输数据:列车车尾位置计算出错", e2))
|
||||||
}
|
}
|
||||||
//slog.Debug("车尾位置", tailDeviceId, "偏移", tailDeviceOffset, "所在设备端", tailDevicePort)
|
//slog.Debug("车尾位置", tailDeviceId, "偏移", tailDeviceOffset, "所在设备端", tailDevicePort)
|
||||||
updateTrainBtmPosition(vs, info, sta, outLinkId, outLinkOffset)
|
|
||||||
// 修改world中的列车位置
|
// 修改world中的列车位置
|
||||||
handleTrainPositionFromDynamic(vs, info, sta, outLinkId, outLinkOffset, tailLinkId, tailLinkOffset)
|
handleTrainPositionFromDynamic(vs, info, sta, outLinkId, outLinkOffset, tailLinkId, tailLinkOffset)
|
||||||
//修改列车激活方向
|
//修改列车激活方向
|
||||||
updateTrainActiveDirFromDynamic(vs, info, sta, id, port, trainHeadActUp)
|
updateTrainActiveDirFromDynamic(vs, info, sta, id, port, trainHeadActUp)
|
||||||
|
if sta.OldLinkOffset == 0 {
|
||||||
|
sta.OldLinkOffset = outLinkOffset
|
||||||
|
sta.OldLink = outLinkId
|
||||||
|
}
|
||||||
|
updateTrainBtmPosition(vs, info, sta, outLinkId, outLinkOffset)
|
||||||
|
//slog.Info(fmt.Sprintf("动力学,当前速度(米/秒):%v,加速度:%v,位移距离:%v", info.Speed, info.Acceleration, info.Displacement))
|
||||||
|
if sta.OldLink != outLinkId {
|
||||||
|
sta.OldLink = outLinkId
|
||||||
|
}
|
||||||
|
if sta.OldLinkOffset != outLinkOffset {
|
||||||
|
sta.OldLinkOffset = outLinkOffset
|
||||||
|
}
|
||||||
sta.HeadDeviceId = vs.GetComIdByUid(id)
|
sta.HeadDeviceId = vs.GetComIdByUid(id)
|
||||||
sta.DevicePort = port
|
sta.DevicePort = port
|
||||||
sta.HeadOffset = offset
|
sta.HeadOffset = offset
|
||||||
@ -364,7 +383,8 @@ func UpdateTrainStateByDynamics(vs *VerifySimulation, trainId string, info *mess
|
|||||||
sta.DynamicState.TailRadarSpeed = speedParse(info.TailRadarSpeed)
|
sta.DynamicState.TailRadarSpeed = speedParse(info.TailRadarSpeed)
|
||||||
sta.DynamicState.Acceleration = info.Acceleration
|
sta.DynamicState.Acceleration = info.Acceleration
|
||||||
|
|
||||||
sta.DynamicState.Displacement = int32(info.Displacement)
|
sta.DynamicState.Displacement = info.Displacement
|
||||||
|
//slog.Info(fmt.Sprintf("动力学返回速度:%v,位移:%v,加速度:%v,time:%v", info.Speed, info.Displacement, info.Acceleration, time.Now().UnixMilli()))
|
||||||
pluseCount(sta, info.HeadSpeed1, info.HeadSpeed2, info.TailSpeed1, info.TailSpeed2)
|
pluseCount(sta, info.HeadSpeed1, info.HeadSpeed2, info.TailSpeed1, info.TailSpeed2)
|
||||||
return sta
|
return sta
|
||||||
}
|
}
|
||||||
@ -388,17 +408,23 @@ func updateTrainActiveDirFromDynamic(vs *VerifySimulation, info *message.Dynamic
|
|||||||
// 根据列车位置修改列车应答器
|
// 根据列车位置修改列车应答器
|
||||||
func updateTrainBtmPosition(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64) {
|
func updateTrainBtmPosition(vs *VerifySimulation, info *message.DynamicsTrainInfo, sta *state_proto.TrainState, outLinkId string, outLinkOffset int64) {
|
||||||
// 更新BTM中列车位置信息
|
// 更新BTM中列车位置信息
|
||||||
|
//isup := sta.TrainActiveDirection == 1
|
||||||
|
|
||||||
can_btm.Default().HandleTrainHeadPositionInfo(vs.World, sta.VobcBtm, &fi.TrainHeadPositionInfo{
|
can_btm.Default().HandleTrainHeadPositionInfo(vs.World, sta.VobcBtm, &fi.TrainHeadPositionInfo{
|
||||||
TrainId: sta.Id,
|
TrainId: sta.Id,
|
||||||
Up: info.Up,
|
Up: info.Up,
|
||||||
Link: outLinkId,
|
Link: outLinkId,
|
||||||
LinkOffset: outLinkOffset,
|
LinkOffset: outLinkOffset,
|
||||||
Speed: info.Speed,
|
Speed: info.Speed,
|
||||||
Acceleration: info.Acceleration,
|
Acceleration: info.Acceleration,
|
||||||
|
OldLinkOffset: sta.OldLinkOffset,
|
||||||
|
OldLink: sta.OldLink,
|
||||||
})
|
})
|
||||||
state := can_btm.Default().GetState()
|
state := can_btm.Default().GetState()
|
||||||
//fmt.Println(state.Telegram)
|
if sta.BtmState == nil || sta.BtmState.BaliseId != state.BaliseId {
|
||||||
sta.BtmState = &state
|
sta.BtmState = &state
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 根据动力学修改列车位置
|
// 根据动力学修改列车位置
|
||||||
@ -459,7 +485,7 @@ func removeTrain(vs *VerifySimulation, trainId string, train *state_proto.TrainS
|
|||||||
vobc.TractionStatus = false
|
vobc.TractionStatus = false
|
||||||
vobc.BrakingStatus = true
|
vobc.BrakingStatus = true
|
||||||
vobc.TractionForce = 0
|
vobc.TractionForce = 0
|
||||||
vobc.BrakeForce = DEFAULT_BRAKE_FORCE
|
vobc.BrakeForce = int64(DEFAULT_BRAKE_FORCE * 100)
|
||||||
}
|
}
|
||||||
train.Show = false
|
train.Show = false
|
||||||
|
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,7 @@ type VerifySimulation struct {
|
|||||||
//Rtss仿真世界的
|
//Rtss仿真世界的
|
||||||
World ecs.World
|
World ecs.World
|
||||||
//设备UID映射 key-uid
|
//设备UID映射 key-uid
|
||||||
UidMap map[string]*elementIdStructure
|
UidMap map[string]*DeviceRelationship
|
||||||
// 运行环境配置
|
// 运行环境配置
|
||||||
runConfig *config.ThirdPartyConfig
|
runConfig *config.ThirdPartyConfig
|
||||||
}
|
}
|
||||||
@ -114,26 +114,6 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRun
|
|||||||
return verifySimulation, nil
|
return verifySimulation, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// // 启动
|
|
||||||
// func (s *VerifySimulation) Start() {
|
|
||||||
// s.runState = state_proto.SimulationStatus_START
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 销毁
|
|
||||||
// func (s *VerifySimulation) Destroy() {
|
|
||||||
// s.runState = state_proto.SimulationStatus_DESTROY
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 暂停
|
|
||||||
// func (s *VerifySimulation) Pause() {
|
|
||||||
// s.runState = state_proto.SimulationStatus_PAUSE
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // 获取状态
|
|
||||||
// func (s *VerifySimulation) GetRunState() state_proto.SimulationStatus_SimulationState {
|
|
||||||
// return s.runState
|
|
||||||
// }
|
|
||||||
|
|
||||||
// 获取仿真世界信息
|
// 获取仿真世界信息
|
||||||
func (s *VerifySimulation) GetComIdByUid(uid string) uint32 {
|
func (s *VerifySimulation) GetComIdByUid(uid string) uint32 {
|
||||||
es := s.UidMap
|
es := s.UidMap
|
||||||
@ -185,7 +165,7 @@ func (s *VerifySimulation) GetBtmVobcConfig() config.BtmVobcConfig {
|
|||||||
|
|
||||||
// GetSectionCodePoints 获取集中站的区段码表
|
// GetSectionCodePoints 获取集中站的区段码表
|
||||||
func (s *VerifySimulation) GetSectionCodePoints(city string, lineId string, centralizedStation string) []*proto.CiSectionCodePoint {
|
func (s *VerifySimulation) GetSectionCodePoints(city string, lineId string, centralizedStation string) []*proto.CiSectionCodePoint {
|
||||||
stationUid := GenerateElementUid(city, lineId, nil, centralizedStation)
|
stationUid := BuildUid(city, lineId, centralizedStation)
|
||||||
ref := s.Repo.GetCentralizedStationRef(stationUid)
|
ref := s.Repo.GetCentralizedStationRef(stationUid)
|
||||||
if ref == nil {
|
if ref == nil {
|
||||||
return nil
|
return nil
|
||||||
@ -196,7 +176,7 @@ func (s *VerifySimulation) GetSectionCodePoints(city string, lineId string, cent
|
|||||||
|
|
||||||
// CollectSectionStatus 收集仿真中计轴区段状态
|
// CollectSectionStatus 收集仿真中计轴区段状态
|
||||||
func (s *VerifySimulation) CollectSectionStatus(city string, lineId string, centralizedStation string) ([]*message.SectionStatusMsg, error) {
|
func (s *VerifySimulation) CollectSectionStatus(city string, lineId string, centralizedStation string) ([]*message.SectionStatusMsg, error) {
|
||||||
stationUid := GenerateElementUid(city, lineId, nil, centralizedStation)
|
stationUid := BuildUid(city, lineId, centralizedStation)
|
||||||
//
|
//
|
||||||
codePoints := s.GetSectionCodePoints(city, lineId, centralizedStation)
|
codePoints := s.GetSectionCodePoints(city, lineId, centralizedStation)
|
||||||
if len(codePoints) <= 0 {
|
if len(codePoints) <= 0 {
|
||||||
@ -419,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)
|
||||||
@ -682,7 +640,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
city := relayGi.UniqueIdPrefix.City
|
city := relayGi.UniqueIdPrefix.City
|
||||||
lineId := relayGi.UniqueIdPrefix.LineId
|
lineId := relayGi.UniqueIdPrefix.LineId
|
||||||
station := relayGi.UniqueIdPrefix.BelongsConcentrationStation
|
station := relayGi.UniqueIdPrefix.BelongsConcentrationStation
|
||||||
stationUid := GenerateElementUid(city, lineId, nil, station)
|
stationUid := BuildUid(city, lineId, station)
|
||||||
relayMap := make(map[string]*proto.Relay)
|
relayMap := make(map[string]*proto.Relay)
|
||||||
for _, relay := range relayGi.Relays {
|
for _, relay := range relayGi.Relays {
|
||||||
rid := GetMapElementId(relay.Common)
|
rid := GetMapElementId(relay.Common)
|
||||||
@ -751,7 +709,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
for _, relationship := range relayGi.DeviceRelateRelayList {
|
for _, relationship := range relayGi.DeviceRelateRelayList {
|
||||||
switch relationship.DeviceType {
|
switch relationship.DeviceType {
|
||||||
case data_proto.RelatedRef_Turnout:
|
case data_proto.RelatedRef_Turnout:
|
||||||
turnout := turnoutMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
|
turnout := turnoutMap[BuildUid(city, lineId, station, relationship.Code)]
|
||||||
if turnout == nil {
|
if turnout == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -770,7 +728,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
case data_proto.RelatedRef_signal:
|
case data_proto.RelatedRef_signal:
|
||||||
signal := signalMap[GenerateElementUid(city, lineId, []string{station}, relationship.Code)]
|
signal := signalMap[BuildUid(city, lineId, station, relationship.Code)]
|
||||||
if signal == nil {
|
if signal == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -793,7 +751,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
ComponentIds: componentIds,
|
ComponentIds: componentIds,
|
||||||
})
|
})
|
||||||
case data_proto.RelatedRef_station:
|
case data_proto.RelatedRef_station:
|
||||||
station := stationMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
|
station := stationMap[BuildUid(city, lineId, relationship.Code)]
|
||||||
if station == nil {
|
if station == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -811,7 +769,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
station.ElectronicGroup = append(station.ElectronicGroup, d)
|
station.ElectronicGroup = append(station.ElectronicGroup, d)
|
||||||
}
|
}
|
||||||
case data_proto.RelatedRef_ScreenDoor:
|
case data_proto.RelatedRef_ScreenDoor:
|
||||||
psd, ok := psdMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
|
psd, ok := psdMap[BuildUid(city, lineId, relationship.Code)]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -855,7 +813,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
}
|
}
|
||||||
case data_proto.RelatedRef_GarageDoor, data_proto.RelatedRef_FloodGate: //车库门||防淹门
|
case data_proto.RelatedRef_GarageDoor, data_proto.RelatedRef_FloodGate: //车库门||防淹门
|
||||||
{
|
{
|
||||||
ckm, ok := ckmMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
|
ckm, ok := ckmMap[BuildUid(city, lineId, relationship.Code)]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -876,7 +834,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
}
|
}
|
||||||
case data_proto.RelatedRef_CarWashing:
|
case data_proto.RelatedRef_CarWashing:
|
||||||
{
|
{
|
||||||
xcj, ok := xcjMap[GenerateElementUid(city, lineId, nil, relationship.Code)]
|
xcj, ok := xcjMap[BuildUid(city, lineId, relationship.Code)]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -968,7 +926,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
mkx.PcbjId = relay.Id
|
mkx.PcbjId = relay.Id
|
||||||
} else if strings.Contains(relay.GetCode(), "POB") {
|
} else if strings.Contains(relay.GetCode(), "POB") {
|
||||||
mkx.PobjId = relay.Id
|
mkx.PobjId = relay.Id
|
||||||
} else if strings.Contains(relay.GetCode(), "PAB") || strings.Contains(relay.GetCode(), "PDB") {
|
} else if strings.Contains(relay.GetCode(), "PAB") || strings.Contains(relay.GetCode(), "DPB") || strings.Contains(relay.GetCode(), "PDB") {
|
||||||
mkx.PabjId = relay.Id
|
mkx.PabjId = relay.Id
|
||||||
} else if strings.Contains(relay.GetCode(), "WRZF") {
|
} else if strings.Contains(relay.GetCode(), "WRZF") {
|
||||||
mkx.WrzfjId = relay.Id
|
mkx.WrzfjId = relay.Id
|
||||||
@ -981,7 +939,7 @@ func buildAndRelateElectronicComponent(repo *proto.Repository, relayGi *data_pro
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 处理该集中站采集、驱动配置信息
|
// 处理该集中站采集、驱动配置信息
|
||||||
centralizedStationId := GenerateElementUid(city, lineId, nil, station)
|
centralizedStationId := BuildUid(city, lineId, station)
|
||||||
ref := queryCentralizedStationRef(centralizedStationId, repo)
|
ref := queryCentralizedStationRef(centralizedStationId, repo)
|
||||||
ref.CjList = append(ref.CjList, handlerRelayGiCj(relayUidStructure, centralizedStationId, relayGi.CiCjList)...)
|
ref.CjList = append(ref.CjList, handlerRelayGiCj(relayUidStructure, centralizedStationId, relayGi.CiCjList)...)
|
||||||
sortQcTable(ref.CjList)
|
sortQcTable(ref.CjList)
|
||||||
@ -1301,19 +1259,19 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic
|
|||||||
SameTrend: data.SameTrend,
|
SameTrend: data.SameTrend,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
// 初始化站场图按钮
|
//// 初始化站场图按钮
|
||||||
for _, data := range storage.EsbButtons {
|
//for _, data := range storage.EsbButtons {
|
||||||
repo.Buttons = append(repo.Buttons, &proto.Button{
|
// repo.Buttons = append(repo.Buttons, &proto.Button{
|
||||||
Id: uidsMap.ButtonIds[GetMapElementId(data.Common)].Uid,
|
// Id: uidsMap.EsbIds[GetMapElementId(data.Common)].Uid,
|
||||||
Code: data.Code,
|
// Code: data.Code,
|
||||||
ButtonType: proto.Button_Reset_Press,
|
// ButtonType: proto.Button_Reset_Press,
|
||||||
})
|
// })
|
||||||
}
|
//}
|
||||||
// 车站关联关系
|
//// 车站关联关系
|
||||||
relateMap := make(map[string]*data_proto.StationRelateDevice)
|
//relateMap := make(map[string]*data_proto.StationRelateDevice)
|
||||||
for _, data := range storage.StationRelateDeviceList {
|
//for _, data := range storage.StationRelateDeviceList {
|
||||||
relateMap[data.Code] = data
|
// relateMap[data.Code] = data
|
||||||
}
|
//}
|
||||||
// 处理车站信息
|
// 处理车站信息
|
||||||
repoStationMap := make(map[uint32]*proto.Station)
|
repoStationMap := make(map[uint32]*proto.Station)
|
||||||
for _, data := range storage.Stations {
|
for _, data := range storage.Stations {
|
||||||
@ -1322,26 +1280,26 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic
|
|||||||
Code: data.StationName,
|
Code: data.StationName,
|
||||||
}
|
}
|
||||||
repoStationMap[GetMapElementId(data.Common)] = station
|
repoStationMap[GetMapElementId(data.Common)] = station
|
||||||
// 关联车站的设备
|
//// 关联车站的设备
|
||||||
refs, ok := relateMap[station.Code]
|
//refs, ok := relateMap[station.Code]
|
||||||
if ok {
|
//if ok {
|
||||||
for _, c := range refs.Combinationtypes {
|
// for _, c := range refs.Combinationtypes {
|
||||||
group := &proto.ElectronicGroup{Code: c.Code}
|
// group := &proto.ElectronicGroup{Code: c.Code}
|
||||||
for _, d := range c.RefDevices {
|
// for _, d := range c.RefDevices {
|
||||||
var comp *proto.ElectronicComponent
|
// var comp *proto.ElectronicComponent
|
||||||
if uidsMap.ButtonIds[d] != nil { // 目前只处理按钮
|
// if uidsMap.EsbIds[d] != nil { // 目前只处理按钮
|
||||||
comp = &proto.ElectronicComponent{
|
// comp = &proto.ElectronicComponent{
|
||||||
Id: uidsMap.ButtonIds[d].Uid,
|
// Id: uidsMap.EsbIds[d].Uid,
|
||||||
DeviceType: proto.DeviceType_DeviceType_Button,
|
// DeviceType: proto.DeviceType_DeviceType_Button,
|
||||||
}
|
// }
|
||||||
} else {
|
// } else {
|
||||||
continue
|
// continue
|
||||||
}
|
// }
|
||||||
group.Components = append(group.Components, comp)
|
// group.Components = append(group.Components, comp)
|
||||||
}
|
// }
|
||||||
station.ElectronicGroup = append(station.ElectronicGroup, group)
|
// station.ElectronicGroup = append(station.ElectronicGroup, group)
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
//// 处理车站关联IBP的设备
|
//// 处理车站关联IBP的设备
|
||||||
//handlerIBPDeviceToStation(station, repo, data.RefIbpMapCode)
|
//handlerIBPDeviceToStation(station, repo, data.RefIbpMapCode)
|
||||||
repo.Stations = append(repo.Stations, station)
|
repo.Stations = append(repo.Stations, station)
|
||||||
@ -1360,6 +1318,14 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic
|
|||||||
Id: uidsMap.PlatformIds[platformId].Uid,
|
Id: uidsMap.PlatformIds[platformId].Uid,
|
||||||
Code: data.Code,
|
Code: data.Code,
|
||||||
}
|
}
|
||||||
|
switch data.Type {
|
||||||
|
case data_proto.Platform_up:
|
||||||
|
platform.Direction = proto.Platform_Up
|
||||||
|
case data_proto.Platform_down:
|
||||||
|
platform.Direction = proto.Platform_Down
|
||||||
|
case data_proto.Platform_Unknown:
|
||||||
|
platform.Direction = proto.Platform_Unknown
|
||||||
|
}
|
||||||
repo.Platforms = append(repo.Platforms, platform)
|
repo.Platforms = append(repo.Platforms, platform)
|
||||||
platform.StationId = uidsMap.StationIds[data.RefStationId].Uid
|
platform.StationId = uidsMap.StationIds[data.RefStationId].Uid
|
||||||
platform.PhysicalSectionId = uidsMap.PhysicalSectionIds[data.RefSectionId].Uid
|
platform.PhysicalSectionId = uidsMap.PhysicalSectionIds[data.RefSectionId].Uid
|
||||||
@ -1447,6 +1413,21 @@ func fillProtoRepository(repo *proto.Repository, storage *data_proto.RtssGraphic
|
|||||||
}
|
}
|
||||||
repo.Xcjs = append(repo.Xcjs, xcj)
|
repo.Xcjs = append(repo.Xcjs, xcj)
|
||||||
}
|
}
|
||||||
|
//ESB
|
||||||
|
for _, data := range storage.EsbButtons {
|
||||||
|
repo.Esbs = append(repo.Esbs, &proto.Esb{
|
||||||
|
Id: uidsMap.EsbIds[data.Common.Id].Uid,
|
||||||
|
PlatformId: uidsMap.PlatformIds[data.RefStand].Uid,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
//SPKS
|
||||||
|
for _, data := range storage.SpksSwitchs {
|
||||||
|
repo.Spkss = append(repo.Spkss, &proto.Spks{
|
||||||
|
Id: uidsMap.SpksIds[data.Common.Id].Uid,
|
||||||
|
Code: data.Code,
|
||||||
|
PlatformId: uidsMap.PlatformIds[data.RefStand].Uid,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fillCkmOrFym(repo *proto.Repository, doors []*data_proto.GarageDoor, uidsMap *StationUidStructure) {
|
func fillCkmOrFym(repo *proto.Repository, doors []*data_proto.GarageDoor, uidsMap *StationUidStructure) {
|
||||||
|
@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
uuid2 "github.com/google/uuid"
|
||||||
"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/const/balise_const"
|
||||||
"joylink.club/bj-rtsts-server/dto/data_proto"
|
"joylink.club/bj-rtsts-server/dto/data_proto"
|
||||||
@ -15,6 +16,7 @@ import (
|
|||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim"
|
train_pc_sim "joylink.club/bj-rtsts-server/third_party/train_pc_sim"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
|
"math"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@ -50,7 +52,7 @@ func ControlTrainUpdate(s *VerifySimulation, ct *request_proto.TrainControl) {
|
|||||||
//此处先注释,根据现场调试情况 2024-4-16
|
//此处先注释,根据现场调试情况 2024-4-16
|
||||||
train_pc_sim.Default().SendTrainDirection(sta, sta.VobcState.DirectionForward, sta.VobcState.DirectionBackward)
|
train_pc_sim.Default().SendTrainDirection(sta, sta.VobcState.DirectionForward, sta.VobcState.DirectionBackward)
|
||||||
} else if ct.ControlType == request_proto.TrainControl_HANDLER {
|
} else if ct.ControlType == request_proto.TrainControl_HANDLER {
|
||||||
if vobc.Tc1Active && vobc.Tc2Active {
|
if !vobc.Tc1Active && !vobc.Tc2Active {
|
||||||
panic(sys_error.New("TC1和TC2都未激活不能搬动牵引制动手柄 "))
|
panic(sys_error.New("TC1和TC2都未激活不能搬动牵引制动手柄 "))
|
||||||
}
|
}
|
||||||
oldTraction := sta.VobcState.TractionForce
|
oldTraction := sta.VobcState.TractionForce
|
||||||
@ -138,8 +140,11 @@ func controlEBBtn(vobc *state_proto.TrainVobcState, active bool, tccBtn *state_p
|
|||||||
tccBtn.Passed = active
|
tccBtn.Passed = active
|
||||||
vobc.EmergencyBrakingStatus = true
|
vobc.EmergencyBrakingStatus = true
|
||||||
vobc.TractionForce = 0
|
vobc.TractionForce = 0
|
||||||
vobc.BrakeForce = DEFAULT_BRAKE_FORCE
|
vobc.BrakeForce = int64(DEFAULT_BRAKE_FORCE * 100)
|
||||||
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 0}}, {Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, 1}}}
|
vobc.BrakingStatus = true
|
||||||
|
return []message.TrainPcSimBaseMessage{
|
||||||
|
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 0}},
|
||||||
|
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, 1}}}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -402,27 +407,31 @@ func trainControlHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.Train
|
|||||||
slog.Error("未找到对应的牵引制动手柄设备deviceId:", deviceId)
|
slog.Error("未找到对应的牵引制动手柄设备deviceId:", deviceId)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
/*trainStart := false
|
||||||
|
if tcc.PushHandler.Val <= 0 {
|
||||||
|
trainStart = true
|
||||||
|
} else if tcc.PushHandler.Val > 0 {
|
||||||
|
|
||||||
|
}*/
|
||||||
jjzdBtn := tcc.Buttons[JJZD]
|
jjzdBtn := tcc.Buttons[JJZD]
|
||||||
vobc.TractionStatus = false
|
vobc.TractionStatus = false
|
||||||
vobc.TractionForce = 0
|
vobc.TractionForce = 0
|
||||||
vobc.BrakingStatus = false
|
vobc.BrakingStatus = false
|
||||||
vobc.BrakeForce = 0
|
vobc.BrakeForce = 0
|
||||||
vobc.MaintainBrakeStatus = false
|
vobc.MaintainBrakeStatus = false
|
||||||
|
notBreak := byte(0)
|
||||||
var zeroState byte = 0
|
var zeroState byte = 0
|
||||||
var brakeState byte = 0
|
var brakeState byte = 0
|
||||||
|
|
||||||
if request.Val > 0 {
|
if request.Val > 0 {
|
||||||
vobc.TractionStatus = true
|
vobc.TractionStatus = true
|
||||||
vobc.TractionForce = int64(request.Val * 180)
|
vobc.TractionForce = int64(float32(request.Val)/100*DEFAULT_TRAIN_TRACTION) * 100
|
||||||
|
notBreak = 1
|
||||||
} else if request.Val < 0 {
|
} else if request.Val < 0 {
|
||||||
vobc.BrakingStatus = true
|
vobc.BrakingStatus = true
|
||||||
vobc.BrakeForce = int64(-request.Val * 180)
|
vobc.BrakeForce = int64(math.Abs(float64(request.Val))/100*DEFAULT_BRAKE_FORCE) * 100
|
||||||
vobc.EmergencyBrakingStatus = false
|
vobc.EmergencyBrakingStatus = false
|
||||||
jjzdBtn.Passed = false
|
jjzdBtn.Passed = false
|
||||||
brakeState = 1
|
brakeState = 0
|
||||||
} else {
|
} else {
|
||||||
zeroState = 1
|
zeroState = 1
|
||||||
}
|
}
|
||||||
@ -433,7 +442,8 @@ func trainControlHandle(vobc *state_proto.TrainVobcState, tcc *state_proto.Train
|
|||||||
|
|
||||||
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.HANDLE_TO_ZERO, zeroState}},
|
return []message.TrainPcSimBaseMessage{{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.HANDLE_TO_ZERO, zeroState}},
|
||||||
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, brakeState}},
|
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_BRAKE_STATE, brakeState}},
|
||||||
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 1}}}
|
/*{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, 1}},*/
|
||||||
|
{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, notBreak}}}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *VerifySimulation) GetConnTrain2() []*state_proto.TrainState {
|
func (s *VerifySimulation) GetConnTrain2() []*state_proto.TrainState {
|
||||||
@ -491,13 +501,22 @@ func (s *VerifySimulation) reportTrainMockInitMsg(train *state_proto.TrainState,
|
|||||||
if trainInit {
|
if trainInit {
|
||||||
if data1 == 0 {
|
if data1 == 0 {
|
||||||
tcc.Line12ConnErr = true
|
tcc.Line12ConnErr = true
|
||||||
slog.Warn("接受atp模拟量数据,data[4]=0,模拟断开")
|
|
||||||
}
|
}
|
||||||
if state == 0 {
|
if state == 0 {
|
||||||
train_pc_sim.Default().ResetPluseCount(train)
|
|
||||||
jjzdBtn := tcc.Buttons[JJZD]
|
jjzdBtn := tcc.Buttons[JJZD]
|
||||||
ebTce := controlEBBtn(vobc, true, jjzdBtn)
|
ebTce := controlEBBtn(vobc, true, jjzdBtn)
|
||||||
tce = append(tce, ebTce...)
|
tce = append(tce, ebTce...)
|
||||||
|
} else if message.GetBit(data1, 0) == 0 {
|
||||||
|
|
||||||
|
jjzdBtn := tcc.Buttons[JJZD]
|
||||||
|
ebTce := controlEBBtn(vobc, true, jjzdBtn)
|
||||||
|
tce = append(tce, ebTce...)
|
||||||
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.OUTER_EMERGENCY_BRAKE, state}})
|
||||||
|
tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.TRAIN_TRACTION_CUTED, 1}})
|
||||||
|
//tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{message.NOT_BREAK, 0}})
|
||||||
|
//tce = append(tce, message.TrainPcSimBaseMessage{Type: message.SENDER_TRAIN_OUTR_INFO, Data: []byte{0x38, 0}})
|
||||||
|
//tce = append(tce, message.TrainPcSimBaseMessage{Type: message.RECIVE_TRAIN_HAND_KEY_CANCLE_FORWARD})
|
||||||
|
//tce = append(tce, message.TrainPcSimBaseMessage{Type: message.RECIVE_TRAIN_HAND_KEY_BACKWARD})
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
initResult = true
|
initResult = true
|
||||||
@ -535,6 +554,9 @@ func (s *VerifySimulation) TrainPcSimDigitalOutInfoHandle(train *state_proto.Tra
|
|||||||
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
|
trainPcSimDigitalOutInfoHandleCode23_16(data[2], vobc)
|
||||||
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
|
trainPcSimDigitalOutInfoHandleCode31_24(data[1], vobc)
|
||||||
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
|
trainPcSimDigitalOutInfoHandleCode39_32(data[0], vobc)
|
||||||
|
/* if !vobc.EmergencyBrakingStatus {
|
||||||
|
train_pc_sim.Default().ResetPlusePlace(train)
|
||||||
|
}*/
|
||||||
return initResult
|
return initResult
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -676,17 +698,19 @@ func (s *VerifySimulation) TrainPcSimMockInfo(train *state_proto.TrainState, dat
|
|||||||
|
|
||||||
// 4.4.4. 车载输出BTM查询同步帧报文内容(0x04)
|
// 4.4.4. 车载输出BTM查询同步帧报文内容(0x04)
|
||||||
func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []byte) {
|
func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []byte) {
|
||||||
//time.Sleep(time.Millisecond * 50)
|
|
||||||
slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧报文内容:%v", hex.EncodeToString(data)))
|
uuid := uuid2.NewString()
|
||||||
|
ts := time.Now().UnixMilli()
|
||||||
|
//slog.Info(fmt.Sprintf("收到车载输出BTM查询同步帧uuid:%v,时间:%v, 报文内容:%v", uuid, ts, hex.EncodeToString(data)))
|
||||||
if len(data) < 12 {
|
if len(data) < 12 {
|
||||||
slog.Error("列车btm查询报文长度错误:", len(data))
|
slog.Error("列车btm查询报文长度错误:", len(data))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if train.BtmState == nil {
|
if train.BtmState == nil {
|
||||||
slog.Warn(fmt.Sprintf("列车暂时未获取到应答器信息,无法进行btm查询列车id:%v", train.Id))
|
slog.Warn(fmt.Sprintf("列车暂时未获取到应答器信息,无法进行btm查询列车id:%v", train.Id))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
notSendBtm, ok := can_btm.Default().FindNotSendState()
|
||||||
trainAtm := message.NewBtmHeadFrame(data)
|
trainAtm := message.NewBtmHeadFrame(data)
|
||||||
atpReq := &message.AtpRequestFrame{}
|
atpReq := &message.AtpRequestFrame{}
|
||||||
|
|
||||||
@ -697,14 +721,20 @@ func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []b
|
|||||||
|
|
||||||
cl := clock(atpReq)
|
cl := clock(atpReq)
|
||||||
dsn := train_pc_sim.Default().DsnAddAndReturn()
|
dsn := train_pc_sim.Default().DsnAddAndReturn()
|
||||||
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl, dsn)
|
//btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, train.BtmState, atpReq, cl, dsn)
|
||||||
|
btmRepFrame := createBtmStatus(trainAtm.CanId.ID4, ¬SendBtm, atpReq, cl, dsn)
|
||||||
//slog.Info(fmt.Sprintf("id1:%x,id2:%x,id3:%x,id4:%x,resendRequest:%v,reqTime:%v,dsn:%v", trainAtm.CanId.ID1, trainAtm.CanId.ID2, trainAtm.CanId.ID3, trainAtm.CanId.ID4, atpReq.ResendRequest, atpReq.Time, dsn))
|
//slog.Info(fmt.Sprintf("id1:%x,id2:%x,id3:%x,id4:%x,resendRequest:%v,reqTime:%v,dsn:%v", trainAtm.CanId.ID1, trainAtm.CanId.ID2, trainAtm.CanId.ID3, trainAtm.CanId.ID4, atpReq.ResendRequest, atpReq.Time, dsn))
|
||||||
if atpReq.ResendRequest == 2 {
|
if atpReq.ResendRequest == 2 {
|
||||||
|
slog.Info(fmt.Sprintf("rrrrrrrrrrrrrrrrr:%v", atpReq.String()))
|
||||||
//重新发送
|
//重新发送
|
||||||
if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 {
|
//if len(train.BtmState.BaliseTelegramForPcSimResend) > 0 {
|
||||||
dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend)
|
if len(notSendBtm.BaliseTelegramForPcSimResend) > 0 {
|
||||||
|
slog.Info(fmt.Sprintf("rrrrrrrrrrrrrrrrr111111111:%v", atpReq.String()))
|
||||||
|
//dd, _ := hex.DecodeString(train.BtmState.BaliseTelegramForPcSimResend)
|
||||||
|
dd, _ := hex.DecodeString(notSendBtm.BaliseTelegramForPcSimResend)
|
||||||
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, dd)
|
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_HAS_DATA, dd)
|
||||||
} else {
|
} else {
|
||||||
|
slog.Info(fmt.Sprintf("rrrrrrrrrrrrrrrrr2222222222222:%v", atpReq.String()))
|
||||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
|
||||||
timeSyncF.T2 = cl.BtmTk
|
timeSyncF.T2 = cl.BtmTk
|
||||||
timeSyncF.T3 = cl.TkNow()
|
timeSyncF.T3 = cl.TkNow()
|
||||||
@ -714,18 +744,31 @@ func (s *VerifySimulation) TrainBtmQuery(train *state_proto.TrainState, data []b
|
|||||||
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
|
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
|
timeSyncF := message.NewBtmTimeSyncCheckFrame(trainAtm.CanId.ID4)
|
||||||
timeSyncF.T2 = cl.BtmTk
|
timeSyncF.T2 = cl.BtmTk
|
||||||
timeSyncF.T3 = cl.TkNow()
|
timeSyncF.T3 = cl.TkNow()
|
||||||
telCount := strings.Count(train.BtmState.Telegram, "00")
|
//telCount := strings.Count(train.BtmState.Telegram, "00")
|
||||||
if telCount >= balise_const.UserTelegramByteLen {
|
telCount := strings.Count(notSendBtm.Telegram, "00")
|
||||||
|
//if telCount >= balise_const.UserTelegramByteLen || train.BtmState.IsSend {
|
||||||
|
if !ok && (notSendBtm.Telegram == "" || telCount >= balise_const.UserTelegramByteLen) {
|
||||||
|
//slog.Info(fmt.Sprintf("准备发送无数据应答器id:%v", train.BtmState.BaliseId))
|
||||||
queryData := make([]byte, 0)
|
queryData := make([]byte, 0)
|
||||||
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
|
queryData = append(queryData, btmRepFrame.EncodeBtmAtp().Encode()...)
|
||||||
queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
|
queryData = append(queryData, timeSyncF.EncodeBtmAtp().Encode()...)
|
||||||
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
|
train_pc_sim.Default().SendBaliseData(train, message.RECIVE_TRAIN_BTM_NOT_DATA, queryData)
|
||||||
} else {
|
//train.BtmState.IsSend = true
|
||||||
|
} else /*if !train.BtmState.IsSend*/
|
||||||
|
if !notSendBtm.IsSend {
|
||||||
|
slog.Info(fmt.Sprintf("准备发送应答id:%v,uuid :%v,接受时间:%v,发送时间:%v , 数据:%v 经过:%v,解报文:%v", notSendBtm.BaliseId, uuid, ts, time.Now().UnixMilli(), notSendBtm.Telegram, notSendBtm.BaliseCount, notSendBtm.MessageCounter))
|
||||||
|
//slog.Info(fmt.Sprintf("准备发送应答id:%v,uuid :%v,消耗时间:%v , 数据:%v", train.BtmState.BaliseId, uuid, ts-time.Now().UnixMilli(), train.BtmState.Telegram))
|
||||||
|
/* defer func() {
|
||||||
|
train.BtmState.IsSend = true
|
||||||
|
}()*/
|
||||||
//有数据
|
//有数据
|
||||||
aliseData, _ := hex.DecodeString(train.BtmState.Telegram)
|
//aliseData, _ := hex.DecodeString(train.BtmState.Telegram)
|
||||||
|
aliseData, _ := hex.DecodeString(notSendBtm.Telegram)
|
||||||
|
|
||||||
stateRepFrame := btmRepFrame.EncodeBtmAtp()
|
stateRepFrame := btmRepFrame.EncodeBtmAtp()
|
||||||
statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, cl.BtmTk, cl.BtmTk, cl.BtmTk)
|
statusDataCf, statusDataCfOk := message.CreateBtmAtpDataRspFramesData(stateRepFrame, aliseData, false, cl.BtmTk, cl.BtmTk, cl.BtmTk)
|
||||||
if statusDataCfOk {
|
if statusDataCfOk {
|
||||||
|
@ -52,6 +52,7 @@ func CreateSimulation(projectId int32, mapIds []int32, runConfig *dto.ProjectRun
|
|||||||
}
|
}
|
||||||
if !e {
|
if !e {
|
||||||
verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig)
|
verifySimulation, err := memory.CreateSimulation(projectId, mapIds, runConfig)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
@ -121,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)
|
||||||
@ -153,14 +154,13 @@ 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()
|
beijing11.Stop(c.Code)
|
||||||
default:
|
default:
|
||||||
beijing12.Stop(c)
|
beijing12.Stop(c)
|
||||||
}
|
}
|
||||||
|
BIN
北岗子-应答器报文清单.xlsx
Normal file
BIN
北岗子-应答器报文清单.xlsx
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user