Merge branch 'develop' into local-test
All checks were successful
local-test分支打包构建docker并发布运行 / Docker-Build (push) Successful in 1m43s
All checks were successful
local-test分支打包构建docker并发布运行 / Docker-Build (push) Successful in 1m43s
This commit is contained in:
commit
3dcafa50e8
@ -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
|
||||
|
@ -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")
|
||||
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
|
||||
}
|
||||
|
||||
} else {
|
||||
slog.Warn("从cannet接收数据,未满足条件‘len(cfs) > 0 && len(cfs)%13 == 0‘", "len(cfs)", len(cfs), "16:", hex.EncodeToString(cfs))
|
||||
}
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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
|
@ -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
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 189cabea725167f98c15d0971ee20d01b044ce05
|
||||
Subproject commit fed626ac4b0d1b2696026438d32fe812ebd00ac2
|
19
third_party/acc/acc_vobc.go
vendored
19
third_party/acc/acc_vobc.go
vendored
@ -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) {
|
||||
|
38
third_party/btm_vobc/btm_vobc.go
vendored
Normal file
38
third_party/btm_vobc/btm_vobc.go
vendored
Normal file
@ -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() {
|
||||
|
||||
}
|
41
third_party/btm_vobc/btm_vobc_test.go
vendored
Normal file
41
third_party/btm_vobc/btm_vobc_test.go
vendored
Normal file
@ -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))
|
||||
}
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
44
third_party/message/accelerometer.go
vendored
44
third_party/message/accelerometer.go
vendored
@ -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
|
||||
}
|
||||
|
270
third_party/message/btm_vobc_data.go
vendored
Normal file
270
third_party/message/btm_vobc_data.go
vendored
Normal file
@ -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())
|
||||
}
|
3
third_party/radar/radar_vobc.go
vendored
3
third_party/radar/radar_vobc.go
vendored
@ -66,7 +66,10 @@ func (rv *radarVobc) Start(radar RadarVobcManager) {
|
||||
|
||||
// sendRadarInfo 发送速度,位移计数 给vobc
|
||||
func (rv *radarVobc) SendMsg(ri *message.RadarInfo) {
|
||||
if rv.vobcClient != nil {
|
||||
rv.vobcClient.Send(ri.Encode())
|
||||
|
||||
}
|
||||
}
|
||||
func (rv *radarVobc) TrainSpeedSender(info *message.DynamicsTrainInfo, trainState *state_proto.TrainState) {
|
||||
forward := trainState.VobcState.DirectionForward
|
||||
|
Loading…
Reference in New Issue
Block a user