【联锁消息处理】
This commit is contained in:
parent
65fb469738
commit
735e46893b
@ -21,6 +21,7 @@ import (
|
|||||||
"joylink.club/bj-rtsts-server/third_party/message"
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
"joylink.club/bj-rtsts-server/third_party/semi_physical_train"
|
"joylink.club/bj-rtsts-server/third_party/semi_physical_train"
|
||||||
"joylink.club/ecs"
|
"joylink.club/ecs"
|
||||||
|
"joylink.club/rtsssimulation/fi"
|
||||||
"joylink.club/rtsssimulation/repository"
|
"joylink.club/rtsssimulation/repository"
|
||||||
"joylink.club/rtsssimulation/repository/model/proto"
|
"joylink.club/rtsssimulation/repository/model/proto"
|
||||||
)
|
)
|
||||||
@ -391,14 +392,30 @@ func (s *VerifySimulation) HandleSemiPhysicalTrainControlMsg(b []byte) {
|
|||||||
|
|
||||||
// 处理接到的联锁消息
|
// 处理接到的联锁消息
|
||||||
func (s *VerifySimulation) HandleDriverInfo(b []byte) {
|
func (s *VerifySimulation) HandleDriverInfo(b []byte) {
|
||||||
|
driverMsg := message.NewInterlockReceiveMsgPkg(0, 128, 8*131)
|
||||||
|
driverMsg.Decode(b)
|
||||||
|
driveState := driverMsg.DriveInfo
|
||||||
|
for x, lenght := 0, len(driveState); x < lenght/32; x++ {
|
||||||
|
for y := 0; y < 32; y++ {
|
||||||
|
fi.DriveCircuitStateChange(s.World, x, y, driveState[x*32+y])
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//// 采集联锁中的继电器消息
|
// 采集联锁中的继电器消息
|
||||||
//func (s *VerifySimulation) CollectRelayInfo() *message.InterlockSendMsgPkg {
|
func (s *VerifySimulation) CollectRelayInfo() *message.InterlockSendMsgPkg {
|
||||||
//
|
msg := &message.InterlockSendMsgPkg{}
|
||||||
// return nil
|
relayArr := make([]string, 256)
|
||||||
//}
|
for index, id := range relayArr {
|
||||||
|
if index%2 == 0 {
|
||||||
|
msg.Info = append(msg.Info, fi.CollectXQCircuitState(s.World, id))
|
||||||
|
} else {
|
||||||
|
msg.Info = append(msg.Info, fi.CollectLXCircuitState(s.World, id))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return msg
|
||||||
|
}
|
||||||
|
|
||||||
func buildProtoRepository(mapIds []int32) (*proto.Repository, error) {
|
func buildProtoRepository(mapIds []int32) (*proto.Repository, error) {
|
||||||
repo := &proto.Repository{}
|
repo := &proto.Repository{}
|
||||||
|
@ -18,6 +18,12 @@ vobc:
|
|||||||
localPort: 10000
|
localPort: 10000
|
||||||
remotePort: 4000
|
remotePort: 4000
|
||||||
open: true
|
open: true
|
||||||
|
# interlock
|
||||||
|
interlock:
|
||||||
|
ip: 10.60.1.59
|
||||||
|
localPort: 10000
|
||||||
|
remotePort: 4000
|
||||||
|
open: true
|
||||||
|
|
||||||
# 数据源
|
# 数据源
|
||||||
datasource:
|
datasource:
|
||||||
|
@ -20,6 +20,7 @@ type AppConfig struct {
|
|||||||
Messaging messaging
|
Messaging messaging
|
||||||
Dynamics dynamics
|
Dynamics dynamics
|
||||||
Vobc vobc
|
Vobc vobc
|
||||||
|
Interlock interlock
|
||||||
}
|
}
|
||||||
type server struct {
|
type server struct {
|
||||||
Port int
|
Port int
|
||||||
@ -63,6 +64,13 @@ type vobc struct {
|
|||||||
Open bool
|
Open bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type interlock struct {
|
||||||
|
Ip string
|
||||||
|
LocalPort int
|
||||||
|
RemotePort int
|
||||||
|
Open bool
|
||||||
|
}
|
||||||
|
|
||||||
var Config AppConfig
|
var Config AppConfig
|
||||||
|
|
||||||
var SimulationId_prefix = (func() string {
|
var SimulationId_prefix = (func() string {
|
||||||
|
@ -18,6 +18,13 @@ vobc:
|
|||||||
localPort: 10000
|
localPort: 10000
|
||||||
remotePort: 4000
|
remotePort: 4000
|
||||||
open: false
|
open: false
|
||||||
|
# interlock
|
||||||
|
interlock:
|
||||||
|
ip: 10.60.1.59
|
||||||
|
localPort: 10000
|
||||||
|
remotePort: 4000
|
||||||
|
open: false
|
||||||
|
|
||||||
|
|
||||||
# 数据源
|
# 数据源
|
||||||
datasource:
|
datasource:
|
||||||
|
@ -18,7 +18,13 @@ vobc:
|
|||||||
localPort: 10000
|
localPort: 10000
|
||||||
remotePort: 4000
|
remotePort: 4000
|
||||||
open: true
|
open: true
|
||||||
|
# interlock
|
||||||
|
interlock:
|
||||||
|
ip: 10.60.1.59
|
||||||
|
localPort: 10000
|
||||||
|
remotePort: 4000
|
||||||
|
open: true
|
||||||
|
|
||||||
# 数据源
|
# 数据源
|
||||||
datasource:
|
datasource:
|
||||||
# 数据库访问url
|
# 数据库访问url
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 3c65650745096e41bb008c74db31aa943e41285a
|
Subproject commit af7cb83fa8e983fb1dabf4179fd0a7692e20bb16
|
120
third_party/interlock/interlock.go
vendored
Normal file
120
third_party/interlock/interlock.go
vendored
Normal file
@ -0,0 +1,120 @@
|
|||||||
|
package interlock
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"runtime/debug"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"joylink.club/bj-rtsts-server/config"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/message"
|
||||||
|
"joylink.club/bj-rtsts-server/third_party/udp"
|
||||||
|
)
|
||||||
|
|
||||||
|
// 联锁代理通信接口
|
||||||
|
type InterlockMessageManager interface {
|
||||||
|
CollectRelayInfo() *message.InterlockSendMsgPkg
|
||||||
|
HandleDriverInfo(b []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 联锁接口
|
||||||
|
type InterlockProxy interface {
|
||||||
|
// 启动联锁消息功能
|
||||||
|
Start(manager InterlockMessageManager)
|
||||||
|
// 停止联锁消息功能
|
||||||
|
Stop()
|
||||||
|
// 发送联锁采集消息
|
||||||
|
SendCollectMessage(b []byte)
|
||||||
|
}
|
||||||
|
|
||||||
|
var _default InterlockProxy
|
||||||
|
|
||||||
|
func Default() InterlockProxy {
|
||||||
|
if !config.Config.Interlock.Open { // TODO
|
||||||
|
panic("联锁接口模块未开启")
|
||||||
|
}
|
||||||
|
return _default
|
||||||
|
}
|
||||||
|
|
||||||
|
type interlockProxy struct {
|
||||||
|
driveInfoUdpServer udp.UdpServer
|
||||||
|
sendCollectUdpClient udp.UdpClient
|
||||||
|
|
||||||
|
manager InterlockMessageManager
|
||||||
|
collectInfoTaskCancel context.CancelFunc
|
||||||
|
}
|
||||||
|
|
||||||
|
// 驱动信息进行转发
|
||||||
|
func (d *interlockProxy) handleDriverInfo(b []byte) {
|
||||||
|
handler := d.manager
|
||||||
|
if handler != nil {
|
||||||
|
handler.HandleDriverInfo(b)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *interlockProxy) Start(manager InterlockMessageManager) {
|
||||||
|
if manager == nil {
|
||||||
|
panic("启动联锁消息服务错误: InterlockMessageManager不能为nil")
|
||||||
|
}
|
||||||
|
if d.manager != nil {
|
||||||
|
panic("启动联锁消息服务错误: 存在正在运行的任务")
|
||||||
|
}
|
||||||
|
d.manager = manager
|
||||||
|
ctx, cancle := context.WithCancel(context.Background())
|
||||||
|
go d.collectInfoStateTask(ctx)
|
||||||
|
d.collectInfoTaskCancel = cancle
|
||||||
|
}
|
||||||
|
|
||||||
|
const (
|
||||||
|
// 采集电路状态发送间隔,单位ms
|
||||||
|
InterlockMessageSendInterval = 50
|
||||||
|
)
|
||||||
|
|
||||||
|
// 定时发送采集电路状态任务
|
||||||
|
func (d *interlockProxy) collectInfoStateTask(ctx context.Context) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
slog.Error("定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack()))
|
||||||
|
debug.PrintStack()
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
collectInfoStates := d.manager.CollectRelayInfo()
|
||||||
|
d.sendCollectUdpClient.SendMsg(collectInfoStates)
|
||||||
|
time.Sleep(time.Millisecond * InterlockMessageSendInterval)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *interlockProxy) Stop() {
|
||||||
|
if d.collectInfoTaskCancel != nil {
|
||||||
|
d.collectInfoTaskCancel()
|
||||||
|
d.manager = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *interlockProxy) SendCollectMessage(b []byte) {
|
||||||
|
d.sendCollectUdpClient.Send(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newInterlockProxy() *interlockProxy {
|
||||||
|
d := &interlockProxy{
|
||||||
|
sendCollectUdpClient: udp.NewClient(fmt.Sprintf("%v:%v", config.Config.Interlock.Ip, config.Config.Interlock.RemotePort)),
|
||||||
|
}
|
||||||
|
d.driveInfoUdpServer = udp.NewServer(fmt.Sprintf(":%d", config.Config.Interlock.LocalPort), d.handleDriverInfo)
|
||||||
|
d.driveInfoUdpServer.Listen()
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
|
||||||
|
func Init() {
|
||||||
|
if !config.Config.Interlock.Open { // TODO
|
||||||
|
return
|
||||||
|
}
|
||||||
|
slog.Info("初始化联锁接口模块")
|
||||||
|
_default = newInterlockProxy()
|
||||||
|
}
|
47
third_party/message/interlock.go
vendored
47
third_party/message/interlock.go
vendored
@ -52,27 +52,49 @@ func (t *InterlockMsgPkgTail) Decode(buf []byte) error {
|
|||||||
// 发送给联锁的采集数据
|
// 发送给联锁的采集数据
|
||||||
type InterlockSendMsgPkg struct {
|
type InterlockSendMsgPkg struct {
|
||||||
Header *InterlockMsgPkgHeader // 包头
|
Header *InterlockMsgPkgHeader // 包头
|
||||||
Info []byte // 发给联锁的状态数据
|
Info []bool // 发给联锁的状态数据
|
||||||
Tail *InterlockMsgPkgTail // 包尾
|
Tail *InterlockMsgPkgTail // 包尾
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var boolsToByteArrLen int = 8
|
||||||
|
|
||||||
func (m *InterlockSendMsgPkg) Encode() []byte {
|
func (m *InterlockSendMsgPkg) Encode() []byte {
|
||||||
var data []byte
|
var data []byte
|
||||||
data = append(data, m.Header.Encode()...)
|
data = append(data, m.Header.Encode()...)
|
||||||
data = append(data, m.Info...)
|
for index, length, cycles := 0, len(m.Info), len(m.Info)/boolsToByteArrLen; index < cycles; index++ {
|
||||||
|
startIndex := index * boolsToByteArrLen
|
||||||
|
toByteArr := [8]bool{}
|
||||||
|
for i := 0; i < boolsToByteArrLen && startIndex < length; i++ {
|
||||||
|
startIndex = startIndex + i
|
||||||
|
toByteArr[i] = m.Info[startIndex+i]
|
||||||
|
}
|
||||||
|
data = append(data, boolsToByte(toByteArr))
|
||||||
|
}
|
||||||
data = append(data, m.Tail.Encode()...)
|
data = append(data, m.Tail.Encode()...)
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bool数组转byte
|
||||||
|
func boolsToByte(flags [8]bool) byte {
|
||||||
|
var result uint8
|
||||||
|
for _, b := range flags {
|
||||||
|
result <<= 1
|
||||||
|
if b {
|
||||||
|
result |= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
// 收到联锁发来的驱动数据
|
// 收到联锁发来的驱动数据
|
||||||
type InterlockReceiveMsgPkg struct {
|
type InterlockReceiveMsgPkg struct {
|
||||||
toagent_len int32
|
toagent_len int32
|
||||||
et_out_num int32
|
et_out_num int32
|
||||||
tcc_output_len int32
|
tcc_output_len int32
|
||||||
Header *InterlockMsgPkgHeader // 包头
|
Header *InterlockMsgPkgHeader // 包头
|
||||||
syncZone []byte // 同步区状态
|
SyncZone []bool // 同步区状态
|
||||||
driveInfo []byte // 驱动数据
|
DriveInfo []bool // 驱动数据
|
||||||
tccInfo []byte // 应答器报文
|
TccInfo []bool // 应答器报文
|
||||||
Tail *InterlockMsgPkgTail // 包尾
|
Tail *InterlockMsgPkgTail // 包尾
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -94,16 +116,25 @@ func (t *InterlockReceiveMsgPkg) Decode(buf []byte) error {
|
|||||||
// 同步区状态
|
// 同步区状态
|
||||||
preIndex = lastIndex
|
preIndex = lastIndex
|
||||||
lastIndex = lastIndex + t.toagent_len
|
lastIndex = lastIndex + t.toagent_len
|
||||||
t.syncZone = buf[preIndex:lastIndex]
|
t.parseByte(t.SyncZone, buf, preIndex, lastIndex)
|
||||||
// 驱动数据
|
// 驱动数据
|
||||||
preIndex = lastIndex
|
preIndex = lastIndex
|
||||||
lastIndex = lastIndex + t.et_out_num
|
lastIndex = lastIndex + t.et_out_num
|
||||||
t.driveInfo = buf[preIndex:lastIndex]
|
t.parseByte(t.DriveInfo, buf, preIndex, lastIndex)
|
||||||
// 应答器报文
|
// 应答器报文
|
||||||
preIndex = lastIndex
|
preIndex = lastIndex
|
||||||
lastIndex = lastIndex + t.tcc_output_len
|
lastIndex = lastIndex + t.tcc_output_len
|
||||||
t.tccInfo = buf[preIndex:lastIndex]
|
t.parseByte(t.TccInfo, buf, preIndex, lastIndex)
|
||||||
// 包尾
|
// 包尾
|
||||||
t.Tail.Decode(buf)
|
t.Tail.Decode(buf)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *InterlockReceiveMsgPkg) parseByte(r []bool, buf []byte, start, end int32) {
|
||||||
|
for i := start; i < end; i++ {
|
||||||
|
b := buf[i]
|
||||||
|
for bit := 7; bit >= 0; bit-- {
|
||||||
|
r = append(r, (b&(1<<bit)) != 0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user