159 lines
4.2 KiB
Go
159 lines
4.2 KiB
Go
// Package beijing12 北京12号线联锁通信
|
||
package beijing12
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"joylink.club/bj-rtsts-server/third_party/tcp"
|
||
"log/slog"
|
||
"runtime/debug"
|
||
"sync"
|
||
"time"
|
||
|
||
"joylink.club/bj-rtsts-server/config"
|
||
"joylink.club/bj-rtsts-server/third_party/message"
|
||
)
|
||
|
||
const logTag = "[北京12号线联锁通信]"
|
||
|
||
// 联锁代理通信接口
|
||
type InterlockMessageManager interface {
|
||
CollectInterlockRelayInfo(code string) *message.InterlockSendMsgPkg
|
||
HandleInterlockDriverInfo(code string, b []byte)
|
||
}
|
||
|
||
// 联锁接口
|
||
type InterlockProxy interface {
|
||
// 启动联锁消息功能
|
||
Start(manager InterlockMessageManager)
|
||
// 停止联锁消息功能
|
||
Stop()
|
||
}
|
||
|
||
var interlockMap = make(map[string]InterlockProxy)
|
||
var initMutex sync.Mutex
|
||
|
||
//func Default(c *config.InterlockConfig) InterlockProxy {
|
||
// initMutex.Lock()
|
||
// defer initMutex.Unlock()
|
||
// if interlockMap[c.Code] == nil {
|
||
// interlockMap[c.Code] = &interlockProxy{runConfig: c}
|
||
// }
|
||
// return interlockMap[c.Code]
|
||
//}
|
||
|
||
func Start(c *config.InterlockConfig, manager InterlockMessageManager) {
|
||
proxy := &interlockProxy{runConfig: c}
|
||
proxy.Start(manager)
|
||
interlockMap[c.Code] = proxy
|
||
}
|
||
|
||
func Stop(c *config.InterlockConfig) {
|
||
proxy := interlockMap[c.Code]
|
||
if proxy != nil {
|
||
proxy.Stop()
|
||
}
|
||
}
|
||
|
||
type interlockProxy struct {
|
||
tcpClient *tcp.TcpClient
|
||
|
||
manager InterlockMessageManager
|
||
collectInfoTaskCancel context.CancelFunc
|
||
runConfig *config.InterlockConfig
|
||
}
|
||
|
||
// 驱动信息进行转发
|
||
func (i *interlockProxy) handleDriverInfo(b []byte) {
|
||
slog.Info(fmt.Sprintf("%s收到联锁驱动继电器数据:%x", logTag, b))
|
||
handler := i.manager
|
||
if handler != nil {
|
||
handler.HandleInterlockDriverInfo(i.runConfig.Code, b)
|
||
}
|
||
}
|
||
|
||
func (i *interlockProxy) Start(manager InterlockMessageManager) {
|
||
if i.runConfig == nil || i.runConfig.Ip == "" || !i.runConfig.Open {
|
||
return
|
||
}
|
||
if manager == nil {
|
||
panic(fmt.Sprintf("%s启动联锁消息服务错误: InterlockMessageManager不能为nil", logTag))
|
||
}
|
||
if i.manager != nil {
|
||
panic(fmt.Sprintf("%s启动联锁消息服务错误: 存在正在运行的任务", logTag))
|
||
}
|
||
i.initInterlockProxy()
|
||
ctx, cancel := context.WithCancel(context.Background())
|
||
go i.collectInfoStateTask(ctx)
|
||
i.collectInfoTaskCancel = cancel
|
||
i.manager = manager
|
||
}
|
||
|
||
// 采集电路状态发送间隔,单位ms
|
||
const InterlockMessageSendInterval = 300
|
||
|
||
// 序列号
|
||
var serialNumber uint8
|
||
|
||
// 定时发送采集电路状态任务
|
||
func (i *interlockProxy) collectInfoStateTask(ctx context.Context) {
|
||
defer func() {
|
||
if err := recover(); err != nil {
|
||
slog.Error(logTag+"定时发送道岔状态任务异常", "error", err, "stack", string(debug.Stack()))
|
||
debug.PrintStack()
|
||
}
|
||
}()
|
||
for {
|
||
select {
|
||
case <-ctx.Done():
|
||
return
|
||
default:
|
||
}
|
||
collectInfoState := i.manager.CollectInterlockRelayInfo(i.runConfig.Code)
|
||
if collectInfoState != nil {
|
||
serialNumber++
|
||
collectInfoState.SetSerialNumber(serialNumber)
|
||
err := i.tcpClient.Send(collectInfoState.Encode())
|
||
if err != nil {
|
||
slog.Error(fmt.Sprintf("%s向联锁发送继电器状态失败:%s", logTag, err))
|
||
} else {
|
||
slog.Info(fmt.Sprintf("%s向联锁发送继电器数据成功:%x", logTag, collectInfoState.Encode()))
|
||
}
|
||
}
|
||
time.Sleep(time.Millisecond * InterlockMessageSendInterval)
|
||
}
|
||
}
|
||
|
||
func (i *interlockProxy) Stop() {
|
||
initMutex.Lock()
|
||
defer initMutex.Unlock()
|
||
delete(interlockMap, i.runConfig.Code)
|
||
i.collectInfoTaskCancel()
|
||
if i.tcpClient != nil {
|
||
i.tcpClient.Close()
|
||
}
|
||
if i.collectInfoTaskCancel != nil {
|
||
i.collectInfoTaskCancel()
|
||
}
|
||
i.manager = nil
|
||
}
|
||
|
||
func (i *interlockProxy) initInterlockProxy() {
|
||
client, err := tcp.StartTcpClient(fmt.Sprintf("%s:%d", i.runConfig.Ip, i.runConfig.RemotePort), i.handleDriveInfo, func(err error) {
|
||
slog.Error(fmt.Sprintf("%sTCP客户端读取数据出错,终止通信服务:%s", logTag, err))
|
||
i.Stop()
|
||
})
|
||
if err != nil {
|
||
panic(fmt.Sprintf("%s启动TCP客户端失败:%s", logTag, err))
|
||
}
|
||
i.tcpClient = client
|
||
}
|
||
|
||
func (i *interlockProxy) handleDriveInfo(n int, data []byte) {
|
||
data = data[:n]
|
||
slog.Info(fmt.Sprintf("%s收到联锁驱动继电器数据:%x", logTag, data))
|
||
if i.manager != nil {
|
||
i.manager.HandleInterlockDriverInfo(i.runConfig.Code, data)
|
||
}
|
||
}
|