From d529c283f2d6b1c023d0b844125ee3800d58f824 Mon Sep 17 00:00:00 2001 From: tiger_zhou Date: Wed, 29 May 2024 11:48:04 +0800 Subject: [PATCH] =?UTF-8?q?=E6=97=A5=E5=BF=97=E8=B0=83=E6=95=B4=E5=8F=8A?= =?UTF-8?q?=E7=8E=B0=E5=9C=BA=E6=B5=8B=E8=AF=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 + bin/acc_conn-example.go | 124 ++++---- bin/config/example.yml | 5 + bin/config/example_config.go | 7 + rts-sim-testing-message | 2 +- third_party/acc/acc_vobc.go | 19 +- third_party/btm_vobc/btm_vobc.go | 38 +++ third_party/btm_vobc/btm_vobc_test.go | 41 +++ .../electrical_machinery.go | 10 +- third_party/message/accelerometer.go | 44 +-- third_party/message/btm_vobc_data.go | 270 ++++++++++++++++++ third_party/radar/radar_vobc.go | 5 +- 12 files changed, 477 insertions(+), 93 deletions(-) create mode 100644 third_party/btm_vobc/btm_vobc.go create mode 100644 third_party/btm_vobc/btm_vobc_test.go create mode 100644 third_party/message/btm_vobc_data.go diff --git a/README.md b/README.md index d6ceb7f..c8f36b3 100644 --- a/README.md +++ b/README.md @@ -23,3 +23,8 @@ - 在 service 目录下添加具体的业务逻辑(数据库查询) - 设置 go 代理 go env -w GOPROXY=https://goproxy.cn,direct - 运行 go mod download / go mod tidy + +# windows 编译linux环境 +- go env -w GOOS=linux +- go build -o appname +- go env -w GOOS=windows diff --git a/bin/acc_conn-example.go b/bin/acc_conn-example.go index 2420d1a..3639c72 100644 --- a/bin/acc_conn-example.go +++ b/bin/acc_conn-example.go @@ -5,10 +5,12 @@ import ( "fmt" "github.com/spf13/viper" "joylink.club/bj-rtsts-server/bin/config" + "joylink.club/bj-rtsts-server/const/balise_const" "joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/udp" "log/slog" - "sort" + "strconv" + "strings" "time" ) @@ -34,76 +36,74 @@ func initConfig() { slog.Info("成功加载配置", "config", exampleConfig) } +var btmCli udp.UdpClient + +func initBtmTest() { + ser := udp.NewServer(fmt.Sprintf("%v:%d", exampleConfig.Btm.LocalIp, exampleConfig.Btm.LocalPort), handleBtmVobcFrames) + ser.Listen() + btmCli = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Btm.RemoteIp, exampleConfig.Btm.RemotePort)) +} + +var accClient udp.UdpClient + +func initAccTest() { + accClient = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Acc.RemoteIp, exampleConfig.Acc.RemotePort)) + go testAcc(accClient, 0.54) +} + +var speedClient udp.UdpClient + +func initSpeedTest() { + speedClient = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Speed.RemoteIp, exampleConfig.Speed.RemotePort)) + go testSpeed(speedClient, 30) +} func main() { initConfig() - accClient := udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Acc.RemoteIp, exampleConfig.Acc.RemotePort)) - go testAcc(accClient, 0.54) - //btm server 接受数据测试 - ser := udp.NewServer(fmt.Sprintf("192.168.1.150:%d", 4646), handleCanetFrames) - ser.Listen() - fmt.Println(ser, "===========") + initBtmTest() + //initAccTest() + //initSpeedTest() - //speedClient := udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Speed.RemoteIp, exampleConfig.Speed.RemotePort)) - //go testSpeed(speedClient, 30) select {} } -func handleCanetFrames(cfs []byte) { - defer func() { - if e := recover(); e != nil { - slog.Debug(fmt.Sprintf("handleCanetFrames异常[%s]", e)) - } - }() +var testUserBtmMsg = "90007F8181B60B10183280003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" +var freeBtmMsg = strings.Repeat("00", balise_const.UserTelegramByteLen) - //一个cannet 帧 13字节 - if len(cfs) > 0 && len(cfs)%13 == 0 { - cfSum := len(cfs) / 13 - dms := make([]*message.CanetFrame, 0, 16) //13个应答器报文数据帧+TimeA帧+TimeB帧+结束帧 - for cfi := 0; cfi < cfSum; cfi++ { - cfStart := cfi * 13 - cf := message.NewCanetFrame(cfs[cfStart:cfStart+13], false) - // - switch cf.CanFrameType() { - case message.CfReq: - fmt.Println(message.CfReq) - case message.CfStatusRsp: - fmt.Println(message.CfStatusRsp) - case message.CfTimeSync: - fmt.Println(message.CfTimeSync) - case message.CfMsg: - fallthrough - case message.CfMsgTimeA: - fallthrough - case message.CfMsgTimeB: - fallthrough - case message.CfMsgEnd: - dms = append(dms, cf) - default: - slog.Warn("CanetFrame帧没有具体对应的应用帧", "CannetFrame", cf.String()) - } //switch - } //for - //将数据包按ID3即0x80+offset由小到大排序 - sort.SliceStable(dms, func(i, j int) bool { - return dms[i].CanId.ID3 < dms[j].CanId.ID3 - }) - //有数据帧,但是不足16帧 - if len(dms) > 0 { - if len(dms) != 16 { - slog.Warn("接收到数据帧,但数据帧数量不足16帧") - } else { - slog.Warn("接收到数据帧,但数据帧数量不足16帧111111") - } - } - - } else { - slog.Warn("从cannet接收数据,未满足条件‘len(cfs) > 0 && len(cfs)%13 == 0‘", "len(cfs)", len(cfs), "16:", hex.EncodeToString(cfs)) +func handleBtmVobcFrames(cfs []byte) { + frameType, dataText, err := message.BtmVobcDecode(cfs) + if err != nil { + return } + if frameType == message.COMMAND_TYPE { + idCommand := &message.BtmVobcIdCommand{} + idCommand.Decode(dataText) + + //userMsg, _ := hex.DecodeString(testUserBtmMsg) + + //msg := &message.BtmVobcMessage{FontTtl: 5, BtmStatus: 0x00, DecodeTime: 10, BackTtl: 4, BtmMsg: userMsg, ResponseTime: 10, + // VobcLifeNum: idCommand.VobcLifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: idCommand.AutoIdFrame}} + //sendData := msg.Encode() + //fmt.Println("发送btm vobc len:", len(sendData), "报文:", hex.EncodeToString(sendData), "报文序列号:", msg.MsgSerial) + //btmCli.Send(sendData) + + freeMsg, _ := hex.DecodeString(freeBtmMsg) + msg2 := &message.BtmVobcMsgFree{BtmStatus: 0x00, WorkTemperature: 10, Fun1: uint16(0), Fun2: uint16(0), Fun3: uint16(0), Fun4: uint16(0), + FreeMsg: freeMsg, RespTime: 20, VobcLifeNum: idCommand.VobcLifeNum, BaseBtmVobc: message.BaseBtmVobc{AutoIdFrame: idCommand.AutoIdFrame}} + sendData2 := msg2.Encode() + fmt.Println("发送btm vobc 空报文:", hex.EncodeToString(sendData2), "len:", len(sendData2), "报文序列号:", msg2.MsgSerial, "atoId=", idCommand.AutoIdFrame) + btmCli.Send(sendData2) + } else if frameType == message.REQUEST_TYPE { + req := &message.BtmVobcReq{} + req.Decode(dataText) + fmt.Println(req, "========================") + } else { + slog.Error("btm vobc 解析未知命令帧类型", strconv.FormatInt(int64(frameType), 16), frameType, "原始数据:", hex.EncodeToString(cfs), "长度:", len(cfs)) + return + } + } -func recive() { - fmt.Println("11111111111111111") - _ = udp.NewServer(fmt.Sprintf(":%d", 4196), handleCanetFrames) -} + func testSpeed(client udp.UdpClient, speed float32) { //client = udp.NewClient(fmt.Sprintf("%v:%v", exampleConfig.Speed.RemoteIp, exampleConfig.Speed.RemotePort)) @@ -146,7 +146,7 @@ func testAcc(client udp.UdpClient, acc float32) { if err != nil { slog.Error("发送数据失败", "err", err) } - time.Sleep(time.Millisecond * 500) + time.Sleep(time.Millisecond * 11) } } diff --git a/bin/config/example.yml b/bin/config/example.yml index b4cc183..575bfe2 100644 --- a/bin/config/example.yml +++ b/bin/config/example.yml @@ -4,3 +4,8 @@ acc: speed: remoteIp: "192.168.1.200" remotePort: 4196 +btm: + remoteIp: "192.168.1.199" + remotePort: 4196 + localIp: "192.168.1.150" + localPort: 4646 \ No newline at end of file diff --git a/bin/config/example_config.go b/bin/config/example_config.go index 6b454ef..4892598 100644 --- a/bin/config/example_config.go +++ b/bin/config/example_config.go @@ -3,6 +3,7 @@ package config type ExampleConfig struct { Acc acc Speed speed + Btm btm } type acc struct { RemoteIp string @@ -12,3 +13,9 @@ type speed struct { RemoteIp string RemotePort int } +type btm struct { + RemoteIp string + RemotePort int + LocalIp string + LocalPort int +} diff --git a/rts-sim-testing-message b/rts-sim-testing-message index 189cabe..fed626a 160000 --- a/rts-sim-testing-message +++ b/rts-sim-testing-message @@ -1 +1 @@ -Subproject commit 189cabea725167f98c15d0971ee20d01b044ce05 +Subproject commit fed626ac4b0d1b2696026438d32fe812ebd00ac2 diff --git a/third_party/acc/acc_vobc.go b/third_party/acc/acc_vobc.go index f7126af..6c7423b 100644 --- a/third_party/acc/acc_vobc.go +++ b/third_party/acc/acc_vobc.go @@ -2,12 +2,14 @@ package acc import ( "context" + "encoding/hex" "fmt" "joylink.club/bj-rtsts-server/config" "joylink.club/bj-rtsts-server/dto/common_proto" "joylink.club/bj-rtsts-server/dto/state_proto" "joylink.club/bj-rtsts-server/third_party/message" "joylink.club/bj-rtsts-server/third_party/udp" + "log/slog" "math" "sync" "time" @@ -30,11 +32,6 @@ var ( singleObj *accVobcService ) -/*const ( - accInterval = 15 - accSpeedUnit = 9.8 -)*/ - func Default() AccVobc { defer initLock.Unlock() initLock.Lock() @@ -59,8 +56,16 @@ func (acc *accVobcService) Start(accManager AccVobcManager) { } func (avs *accVobcService) SendAcc(acc *message.Accelerometer) { - - avs.vobcClient.Send(acc.Encode()) + if avs.vobcClient != nil { + data := acc.Encode() + hexStr := hex.EncodeToString(data) + slog.Info("发送 加速度消息数据:", hexStr) + err := avs.vobcClient.Send(data) + if err != nil { + slog.Info("发送 加速度消息数据失败:", hexStr) + return + } + } //avs.vobcClient.Send(acc.BuildCanData()) } func (avs *accVobcService) TrainAccSender(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) { diff --git a/third_party/btm_vobc/btm_vobc.go b/third_party/btm_vobc/btm_vobc.go new file mode 100644 index 0000000..d7f37c1 --- /dev/null +++ b/third_party/btm_vobc/btm_vobc.go @@ -0,0 +1,38 @@ +package btm_vobc + +import ( + "context" + "sync" +) + +type BtmVobcManage interface { +} +type BtmVobcService interface { + Start() + Stop() +} +type BtmVobcClient struct { + calFun context.CancelFunc +} + +var ( + btmVobcLocker sync.Mutex + btmVobcClient *BtmVobcClient +) + +func Default() BtmVobcService { + defer btmVobcLocker.Unlock() + + btmVobcLocker.Lock() + if btmVobcClient == nil { + btmVobcClient = &BtmVobcClient{} + } + return btmVobcClient +} +func (b *BtmVobcClient) Start() { + //ctx, calFun := context.WithCancel(context.Background()) + +} +func (b *BtmVobcClient) Stop() { + +} diff --git a/third_party/btm_vobc/btm_vobc_test.go b/third_party/btm_vobc/btm_vobc_test.go new file mode 100644 index 0000000..4877ae1 --- /dev/null +++ b/third_party/btm_vobc/btm_vobc_test.go @@ -0,0 +1,41 @@ +package btm_vobc + +import ( + "bytes" + "encoding/hex" + "fmt" + "sync/atomic" + "testing" +) + +const ( + code1 = "fffef890149e75e15511000006230000000000d4da14ebfffd" + code2 = "fffee601804f004d00800600002a004984ec6f4e902ef6912284000000000000000000000000000000067e000000000000411b0000f5bbee397698fffd" +) + +var message_id atomic.Uint32 + +func TestDecode(t *testing.T) { + fmt.Println(code1[:4]) + d, _ := hex.DecodeString(code1) + fmt.Println(d[:2]) + dd := d[2 : len(d)-2] + fmt.Println(hex.EncodeToString(dd)) + fmt.Println(bytes.Equal(d[:2], []byte{0xff, 0xfe})) + fmt.Println(message_id.Load()) +} + +func TestMsg(t *testing.T) { + + index := 1 + for i := 22; i <= 125; i++ { + fmt.Println(index) + index++ + } +} + +func TestBytes(t *testing.T) { + s := "90007F8181B60B10183280003FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" + d, _ := hex.DecodeString(s) + fmt.Println(len(d)) +} diff --git a/third_party/electrical_machinery/electrical_machinery.go b/third_party/electrical_machinery/electrical_machinery.go index d98b128..a4f6442 100644 --- a/third_party/electrical_machinery/electrical_machinery.go +++ b/third_party/electrical_machinery/electrical_machinery.go @@ -1,6 +1,7 @@ package electrical_machinery import ( + "encoding/hex" "fmt" "joylink.club/bj-rtsts-server/dto/common_proto" "joylink.club/bj-rtsts-server/dto/state_proto" @@ -48,7 +49,7 @@ func (s *electricalMachineryImpl) Start(manager ElectricMachineryMessageManager) s.runConfig = manager.GetElectricMachineryRunConfig() allNotOpen := true for _, c := range s.runConfig { - if &c == nil || c.Ip == "" || !c.Open { + if &c != nil && c.Open { allNotOpen = false } } @@ -79,9 +80,12 @@ func (s *electricalMachineryImpl) SendElectricMachineryMessage(emMap map[int]*me for key, em := range emMap { client := s.electricalMachineryUdpClientMap[key] if client != nil { - err := client.Send(em.Encode()) + data := em.Encode() + hexStr := hex.EncodeToString(data) + slog.Info("发送电机转速消息key", hexStr) + err := client.Send(data) if err != nil { - slog.Error(err.Error()) + slog.Info("发送电机转速消息失败key", hexStr) } } } diff --git a/third_party/message/accelerometer.go b/third_party/message/accelerometer.go index 9291977..87fac1f 100644 --- a/third_party/message/accelerometer.go +++ b/third_party/message/accelerometer.go @@ -7,7 +7,7 @@ import ( const ( accHeader = 0xA6 - uaidDefault = 0x1C + uaidDefault = 0x71 G = 9.80665 ) @@ -16,12 +16,6 @@ type Accelerometer struct { Aux byte } -const ( - FullScaleG = 0x80000000 // 1g的Q31表示 - DataMask = 0xC0 // 最高2位是数据位 - ReadingMask = 0xFFFFC000 // 屏蔽标志位和编码位 -) - func encodeAcc(a float32) (d2, d1, d0 byte) { d2 = 0 d1 = 0 @@ -29,7 +23,7 @@ func encodeAcc(a float32) (d2, d1, d0 byte) { x := a / G //fmt.Println(x) v := uint32(0) - for i := 17; i >= 0; i-- { + for i := 16; i >= 0; i-- { t := float32(1.0 / math.Pow(2, float64(17-i))) if t > x { continue @@ -43,6 +37,12 @@ func encodeAcc(a float32) (d2, d1, d0 byte) { d0 = byte(v) d1 = byte(v >> 8) d2 = byte(v >> 16) + + //accCode := v << 8 //数据向左移动8位,取后3个字节 + //d2 = byte(accCode >> 16) //取出d2数据 + //d1 = byte(accCode >> 8 << 8) // & 0xff //取出d1 + //d0 = byte(accCode << 20) //& 0xf //取出d0高2位 + //fmt.Printf("%b, %b, %b\n", d2, d1, d0) return } @@ -72,36 +72,42 @@ func (acc *Accelerometer) BuildCanData() []byte { } func (acc *Accelerometer) Encode() []byte { d2, d1, d0 := encodeAcc(acc.Acc) + if acc.Acc > 0 { + setBit(d2, 7, 0) + } else { + setBit(d2, 7, 1) + } data := make([]byte, 0) data = append(data, accHeader) data = append(data, uaidDefault) data = append(data, d0) data = append(data, d1) data = append(data, d2) - data = append(data, acc.Aux) + data = append(data, byte(0)) cs := checkSum(data) - data = append(data, ^cs+1) + data = append(data, cs) return data } func checkSum(data []byte) byte { - var sum byte = 0 + var sum uint16 = 0 + for _, d := range data { - sum += d + sum += uint16(d) } - return sum + highByte := byte(sum >> 8) // 取高8位 + lowByte := byte(sum) // 取低8位 + secondSum := highByte + lowByte // 再次累加 + + //inverse := ^secondSum + return ^secondSum } func (acc *Accelerometer) Decode(Packet []byte) error { if len(Packet) < 7 { return fmt.Errorf("") } - data := uint32(Packet[4])<<16 | uint32(Packet[3])<<8 | uint32(Packet[2]) - // 应用屏蔽以移除标志位和编码位 - data &= ReadingMask - // 将Q31值转换为float32加速度值(g) - acceleration := float32(float32(data) * (1.0 / float32(FullScaleG))) + decode2Acc(Packet[4], Packet[3], Packet[2]) - fmt.Println(acceleration) return nil } diff --git a/third_party/message/btm_vobc_data.go b/third_party/message/btm_vobc_data.go new file mode 100644 index 0000000..24e34f3 --- /dev/null +++ b/third_party/message/btm_vobc_data.go @@ -0,0 +1,270 @@ +package message + +import ( + "bytes" + "encoding/binary" + "encoding/hex" + "fmt" + "github.com/snksoft/crc" + "log/slog" + "strconv" + "sync" +) + +const ( + TRAIN_BTM_ENDA = 0x75E1 + TRAIN_BTM_ENDB = 0x75E2 + ID_COMMAND_TYPE = 0xF8 //命令帧 + REQT_TYPE = 0xE6 //请求帧 + +) + +const ( + COMMAND_TYPE = 0x90 //ID 命令帧 VOBC→BTM20 字节 + REQUEST_TYPE = 0x91 //请求帧 VOBC→BTM34 字节 + MESSAGE_TYPE = 0x92 //报文帧 BTM→VOBC 135 字节 + FREE_MESSAGE_TYPE = 0x94 //空闲帧 BTM→VOBC 135 字节 +) + +var PACKAGE_HEAD = []byte{0xFF, 0xFE} +var PACKAGE_END = []byte{0xFF, 0xFD} + +func BtmVobcDecode(packData []byte) (byte, []byte, error) { + head := packData[:2] + end := packData[len(packData)-2:] + if !bytes.Equal(head, PACKAGE_HEAD) || !bytes.Equal(end, PACKAGE_END) { + slog.Error("btm vobc 数据包头或包尾尾错误", hex.EncodeToString(packData)) + return 0, nil, fmt.Errorf("btm vobc 数据包头或包尾尾错误") + } + data := packData[2 : len(packData)-2] + command := data[0] + if command != ID_COMMAND_TYPE && command != REQT_TYPE { + slog.Error("btm vobc 解析未知命令帧", strconv.FormatInt(int64(command), 16), command) + return 0, nil, fmt.Errorf("btm vobc 解析未知命令帧") + } + dataText := data[1:] + frameType := dataText[0] + return frameType, dataText, nil + /* if frameType == COMMAND_TYPE { + + } else if frameType == REQUEST_TYPE { + + } else { + slog.Error("btm vobc 解析未知命令帧类型", strconv.FormatInt(int64(frameType), 16)) + return + }*/ +} + +type BaseBtmVobc struct { + Frame byte //帧类型 + FrameLen byte //帧长定义为 TEXT+CRC32,ID 命令帧为 20 字节; + AutoIdFrame byte // 无论何时传输数据,该数都在 1-255 范围内递增,在错误重传时也是递增的,255 之后是 1,不使用 0; + Crc32 uint32 +} + +func baseDecode(d []byte) (BaseBtmVobc, []byte) { + frame := d[0] + frameLen := d[1] + autoIdFrame := d[2] + crc32 := binary.BigEndian.Uint32(d[len(d)-4:]) + realData := d[3 : len(d)-4] + return BaseBtmVobc{Frame: frame, FrameLen: frameLen, Crc32: crc32, AutoIdFrame: autoIdFrame}, realData +} +func baseEncode(source []byte) []byte { + data := make([]byte, 0) + crc32 := crc.CalculateCRC(crc.CRC32, source) + newSource := binary.BigEndian.AppendUint32(source, uint32(crc32)) + data = append(data, PACKAGE_HEAD...) + data = append(data, newSource...) + data = append(data, PACKAGE_END...) + return data +} + +// ID 命令帧的正文 +type BtmVobcIdCommand struct { + BaseBtmVobc + BtmId uint16 //VOBC 向 BTM 分配的 ID,暂定 0x75E1 或者0x75A2,其他无效; + VobcId uint16 //暂定 0x5511,其他无效 + VobcLifeNum uint32 //7~10 1~FFFFFFFF,0 不使用 + yuliu []byte //11-15 预留字节 +} + +func (b *BtmVobcIdCommand) Decode(data []byte) { + base, realData := baseDecode(data) + b.BaseBtmVobc = base + b.BtmId = binary.BigEndian.Uint16(realData[0:2]) + b.VobcId = binary.BigEndian.Uint16(realData[2:4]) + b.VobcLifeNum = binary.BigEndian.Uint32(realData[4:8]) +} + +// 请求帧的正文 +type BtmVobcReq struct { + BaseBtmVobc + FrameStatus byte //帧正确/不正确 06h:帧正确15h:不正确00h:开机状态填00 其它无效 + MessageType byte // 空闲/报文数据 05h:空闲0Ah:报文数据00h:开机状态填00 其它无效 + MessageSerial byte //报文序列号 1-255;开机时使用0 + yuliu []byte //预留字节(10 字节) + VobcLifeNum uint32 // VOBC 周期号 1~FFFFFFFF,0 不使用 + TimeStamp []byte //年月日时分秒各占一个字节 + Speed uint16 //速度 单位:cm/s + VobcLifeWalkDistance uint16 //VOBC 周期走行距离 单位:cm +} + +func (b *BtmVobcReq) Decode(data []byte) { + base, realData := baseDecode(data) + b.BaseBtmVobc = base + b.FrameStatus = realData[0] + b.MessageType = realData[1] + b.MessageSerial = realData[2] + b.yuliu = realData[3:13] + b.VobcLifeNum = binary.BigEndian.Uint32(realData[13:17]) + b.TimeStamp = realData[17:25] + b.Speed = binary.BigEndian.Uint16(realData[25:26]) + b.VobcLifeWalkDistance = binary.BigEndian.Uint16(realData[26:27]) +} + +var MESSAGE_AUTO_ID byte = 1 +var MESSAGE_SERIAL byte = 1 +var lock sync.Mutex + +func getAutoId() byte { + defer lock.Unlock() + lock.Lock() + if MESSAGE_AUTO_ID <= 0 { + MESSAGE_AUTO_ID = 1 + } else if MESSAGE_AUTO_ID > 255 { + MESSAGE_AUTO_ID = 1 + } + MESSAGE_AUTO_ID += 1 + return MESSAGE_AUTO_ID +} + +func getAutoMessageId() byte { + + defer lock.Unlock() + lock.Lock() + if MESSAGE_SERIAL <= 0 { + MESSAGE_SERIAL = 1 + } else if MESSAGE_SERIAL > 255 { + MESSAGE_SERIAL = 1 + } + MESSAGE_SERIAL += 1 + return MESSAGE_SERIAL +} + +const ( + btm_status_ok = 0x00 + btm_status_warn = 0x04 +) + +var mesage_yuliu = []byte{0, 0, 0, 0, 0, 0, 0, 0, 0} + +// 报文帧的正文 +type BtmVobcMessage struct { + BaseBtmVobc + FontTtl uint16 //前沿 TTL 时间 单位为 ms,溢出为0xffff,高字节在前;车体及应答器器地面环境理想情况下误差小于 5ms + MsgSerial byte //报文序列号 1-255;不使用 0 + BtmStatus byte //BTM 工作状态 00H-工作正常;04H-警告 BTM 有轻微故障(单套故障,整机能工作),向BDMS 汇报;FFH-BTM 故障,不能正常工作;在MMI进行故障提示并向ATS 汇报 + Enter1 byte //1 通道好码率 0~100 + Enter2 byte //2 通道好码率 0~100 + DecodeTime uint16 //解码时间:从包络前沿到解码成功的时间,单位0.1ms。 + yuliu []byte //11~19 预留 填 0 + BackTtl uint16 //后沿 TTL 时间单位为 ms,溢出为0xffff,高字节在前;车体及应答器器地面环境理想情况下误差小于 5ms. + BtmMsg []byte //22~125 应答器报文 + ResponseTime byte //0~150,其他非法,单位0.1ms 误差小于 3ms + VobcLifeNum uint32 //VOBC 周期号 1~FFFFFFFF,0 不使用。 +} + +func (b *BtmVobcMessage) Encode() []byte { + + data := make([]byte, 0) + buf := bytes.NewBuffer(data) + b.MsgSerial = getAutoMessageId() + binary.Write(buf, binary.BigEndian, byte(MESSAGE_TYPE)) + binary.Write(buf, binary.BigEndian, byte(0x87)) + binary.Write(buf, binary.BigEndian, b.AutoIdFrame) + //binary.Write(buf, binary.BigEndian, getAutoId()) + binary.Write(buf, binary.BigEndian, b.FontTtl) + binary.Write(buf, binary.BigEndian, b.MsgSerial) + binary.Write(buf, binary.BigEndian, b.BtmStatus) + binary.Write(buf, binary.BigEndian, byte(100)) //b.Enter1 + binary.Write(buf, binary.BigEndian, byte(100)) //b.Enter2 + binary.Write(buf, binary.BigEndian, b.DecodeTime) + binary.Write(buf, binary.BigEndian, mesage_yuliu) + binary.Write(buf, binary.BigEndian, b.BackTtl) + binary.Write(buf, binary.BigEndian, b.BtmMsg) + binary.Write(buf, binary.BigEndian, b.ResponseTime) + binary.Write(buf, binary.BigEndian, b.VobcLifeNum) + + return baseEncode(buf.Bytes()) +} + +var yuliu3 = []byte{0, 0, 0, 0, 0, 0} + +type BtmVobcMsgFree struct { + BaseBtmVobc + //yuliu1 byte + //yuliu2 byte + MsgSerial byte //1-255;开机时为0 + BtmStatus byte //BTM 工作状态 00H-工作正常;04H-警告 BTM 有轻微故障(单套故障,整机能工作),向BDMS 汇报;FFH-BTM 故障,不能正常工作;在MMI 进行故障提示并向ATS 汇报 + WorkTemperature byte + //yuliu3 []byte //8~13 保留 填 0 + + //0-1 位 功放 1 电流状态 功放电流状态:“1”-欠流;“2”- 过流 ;“3”-正常(欠流和过流仅作为功放状态参考) + //2-3 位 功放 1 电压状态 功放电压状态:“1”-欠压;“2”- 过压 ;“3”-正常(欠压和过压仅作为功放状态参考) + //4-5 位 (预留) 功放 2 电流状态 功放电流状态:“1”-欠流;“2”- 过流 ;“3”-正常(欠流和过流仅作为功放状态参考) + //6-7 位 功放 2 电压状 功放电压状态:“1”-欠压;“2”- 过压 ;“3”-正常(欠压和过压仅作为功放状态参考) + //8-9 位 天线 1 状态 天线 1 状态:“1”-故障;“3”-正常。 + //10-11 位 线缆 1 状态 线缆 1 状态:“1”-开路;“2”-短路;“3”-正常。 + //12-13 位 (预留) 天线 2 状态 天线 2 状态:“1”-故障;“3”-正常。 + //14-15 位 (预留) 线缆 2 状态 线缆 2 状态:“1”-开路;“2”-短路;“3”-正常。 + Fun1 uint16 //第 14-15 字节(功放板、天线状态) + //第 0 位 上行自检码检测通道 1 状态:“1”-正常;“0”-故障。(故障时,检查处理器板和接收板) + //第 1 位 上行自检码检测通道 2 状态:“1”-正常;“0”-故障。(故障时,检查处理器板和接收板) + //第 2 位 FSK 连接线状态通道 1状态:“1”-正常;“0”-故障。 + //第 3 位 FSK 连接线状态通道 2状态:“1”-正常;“0”-故障。 + //第 4-5 位 保留 保留 + //第 6-7 位 接收板状态 状态:“0”-双通道故障;“1”-单通道故障;“3”-正常第 + //8-15位保留 保留 + Fun2 uint16 //第 16-17 字节(接收板状态) + //第 0-1 位 通 道 1-24V 状态 状态:“1”-过压;“2”-欠压;“3”-正常;(欠压和过压仅作为电源板状态参考) + //第 2-3 位 通 道 2-24V 状态 状态:“1”-过压;“2”-欠压;“3”-正常;(欠压和过压仅作为电源板状态参考) + //第 4 位 通 道 1-23V 状态 状态:“1”-正常;“0”-故障。 + //第 5 位 通 道 2-23V 状态 状态:“1”-正常;“0”-故障。 + //第 6-13位保留 保留 + //第 14-15位 电源板状态 电源板状态:“0”-故障;“1”-单通道故障;“2”-单通道故障;“3”- 正常。 + Fun3 uint16 //第 18-19 字节(电源板状态) + //第 0-1 位 板卡 ID 槽位号 “0”-1 号板卡;“1”-2 号板卡;“2”-3 号板卡;“3”-4 号板卡机箱正面从右往左顺序为处理器板1,2,3(预留),4(预留),同一个通信周期只有一个板卡报警 + //第 2-3 位 工作温度状态 “0”-过高;“1”-温度报警;“2”-未知;“3”-正常。 + //其他位保留 注:保留位全部为1 + Fun4 uint16 //第 20-21 字节(处理器板) + + FreeMsg []byte //22~125 空闲数据 全填 00H + RespTime byte //响应时间 0~150,其他非法,单位0.1ms + VobcLifeNum uint32 //VOBC 周期号 1~FFFFFFFF,0 不使用。 +} + +func (b *BtmVobcMsgFree) Encode() []byte { + data := make([]byte, 0) + buf := bytes.NewBuffer(data) + b.MsgSerial = getAutoMessageId() + binary.Write(buf, binary.BigEndian, byte(FREE_MESSAGE_TYPE)) + binary.Write(buf, binary.BigEndian, byte(0x87)) + //binary.Write(buf, binary.BigEndian, getAutoId()) + binary.Write(buf, binary.BigEndian, b.AutoIdFrame) + binary.Write(buf, binary.BigEndian, byte(0)) //保留 + binary.Write(buf, binary.BigEndian, byte(0)) //保留 + binary.Write(buf, binary.BigEndian, b.MsgSerial) + binary.Write(buf, binary.BigEndian, b.BtmStatus) + binary.Write(buf, binary.BigEndian, b.WorkTemperature) + binary.Write(buf, binary.BigEndian, yuliu3) + binary.Write(buf, binary.BigEndian, b.Fun1) + binary.Write(buf, binary.BigEndian, b.Fun2) + binary.Write(buf, binary.BigEndian, b.Fun3) + binary.Write(buf, binary.BigEndian, b.Fun4) + binary.Write(buf, binary.BigEndian, b.FreeMsg) + binary.Write(buf, binary.BigEndian, b.RespTime) + binary.Write(buf, binary.BigEndian, b.VobcLifeNum) + + return baseEncode(buf.Bytes()) +} diff --git a/third_party/radar/radar_vobc.go b/third_party/radar/radar_vobc.go index db11ef2..d3766c4 100644 --- a/third_party/radar/radar_vobc.go +++ b/third_party/radar/radar_vobc.go @@ -66,7 +66,10 @@ func (rv *radarVobc) Start(radar RadarVobcManager) { // sendRadarInfo 发送速度,位移计数 给vobc func (rv *radarVobc) SendMsg(ri *message.RadarInfo) { - rv.vobcClient.Send(ri.Encode()) + if rv.vobcClient != nil { + rv.vobcClient.Send(ri.Encode()) + + } } func (rv *radarVobc) TrainSpeedSender(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) { forward := trainState.VobcState.DirectionForward