rts-sim-testing-service/third_party/interlock/interlock.go

121 lines
2.8 KiB
Go
Raw Normal View History

2023-10-24 10:57:04 +08:00
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()
}