rts-sim-testing-service/third_party/example/rssp/ci/ci_server.go
2023-11-14 17:57:54 +08:00

156 lines
4.3 KiB
Go

package ci
import (
"context"
"fmt"
"joylink.club/bj-rtsts-server/config"
"joylink.club/bj-rtsts-server/third_party/axle_device"
"joylink.club/bj-rtsts-server/third_party/message"
"sort"
"sync"
"time"
)
type CiServer interface {
Start()
Stop()
//SendSectionReset 向计轴设备发送计轴命令
SendSectionReset(sectionId string, drst bool, pdrst bool)
//HandleSectionStatus 收到来自计轴设备的物理区段状态
HandleSectionStatus(status []*message.SectionStatusMsg)
}
// 北京12号线酒仙桥集中站物理区段码表
var codePointMap = map[int]string{0: "北京_12_酒仙桥_9G", 1: "北京_12_酒仙桥_1DG", 2: "北京_12_酒仙桥_11G", 3: "北京_12_酒仙桥_13G", 4: "北京_12_酒仙桥_15G", 5: "北京_12_酒仙桥_6G", 6: "北京_12_酒仙桥_8G", 7: "北京_12_酒仙桥_2DG", 8: "北京_12_酒仙桥_10G", 9: "北京_12_酒仙桥_12G", 10: "北京_12_酒仙桥_14G"}
var idRowMap = make(map[string]int)
var sectionCmds []*message.SectionCmdMsg
var cmdsLock = sync.Mutex{}
// rssp 测试
type ciServer struct {
//所属城市
city string
//所属线路
lineId string
//所属集中站
centralizedStation string
//接收方每个安全通信会话对应的发送周期值,单位ms
sendingPeriod uint32
//主安全通道
rsspChannel *axle_device.RsspChannel
//
cancel context.CancelFunc
}
func (s *ciServer) HandleSectionStatus(status []*message.SectionStatusMsg) {
if len(codePointMap) != len(status) {
fmt.Println("==>>接收到的区段状态与码表不对应:", "codePointsLen=", len(codePointMap), ",statusLen=", len(status))
return
}
fmt.Println("==>>接收到的区段状态----------------------------------------------------------------------------i")
for row, state := range status {
sectionId := codePointMap[row]
fmt.Printf("==>>[%d]区段[%s]状态: Clr=%t Occ=%t Rac=%t Rjo=%t Rjt=%t\n", row, sectionId, state.Clr, state.Occ, state.Rac, state.Rjo, state.Rjt)
}
fmt.Println("==>>接收到的区段状态----------------------------------------------------------------------------o")
}
func (s *ciServer) periodRun(runContext context.Context) {
defer func() {
fmt.Println("==>>CI Server 周期运行退出 ...")
}()
for {
select {
case <-runContext.Done():
return
default:
}
s.doSendSectionCmdMsg()
time.Sleep(time.Duration(s.sendingPeriod) * time.Millisecond)
//更新周期性参数
s.rsspChannel.NextPeriod()
}
}
func (s *ciServer) doSendSectionCmdMsg() {
if s.rsspChannel != nil {
data := s.collectSectionCmdsData()
fmt.Println("==>>CI发送区段指令数据", ",len=", len(data))
s.rsspChannel.SendUserData(data)
}
}
func (s *ciServer) collectSectionCmdsData() []byte {
defer func() {
cmdsLock.Unlock()
}()
cmdsLock.Lock()
//
data := (&message.SectionCmdMsgPack{Ck: 0x80, Scs: sectionCmds}).Encode()
return data
}
// SendSectionReset 发送区段复位指令
func (s *ciServer) SendSectionReset(sectionId string, drst bool, pdrst bool) {
defer func() {
cmdsLock.Unlock()
}()
cmdsLock.Lock()
//
sec := sectionCmds[idRowMap[sectionId]]
sec.Drst = drst
sec.Pdrst = pdrst
}
type rowId struct {
row int
id string
}
func (s *ciServer) Start() {
s.rsspChannel.SetRcvUserDataCallback(s.rcvUserData)
s.rsspChannel.Start()
ctx, cancel := context.WithCancel(context.Background())
go s.periodRun(ctx)
s.cancel = cancel
}
func (s *ciServer) Stop() {
if s.rsspChannel != nil {
s.rsspChannel.Stop()
s.rsspChannel = nil
}
if s.cancel != nil {
s.cancel()
}
}
func (s *ciServer) rcvUserData(data []byte) {
fmt.Println("==>>CI接收到区段状态数据", ",len=", len(data))
msg := &message.SectionStatusMsgPack{}
msg.Decode(data)
s.HandleSectionStatus(msg.Sms)
}
func NewRsspCiServer(cfg *config.RsspAxleConfig) CiServer {
ra := &ciServer{}
//
ra.city = cfg.City
ra.lineId = cfg.LineId
ra.centralizedStation = cfg.CentralizedStation
ra.sendingPeriod = cfg.RsspCfg.SendingPeriod
//
mrc := &axle_device.RsspChannel{}
ra.rsspChannel = mrc.Init(&cfg.RsspCfg)
//
return ra
}
func InitCiServerCodePoints() {
var ris []*rowId
for row, id := range codePointMap {
idRowMap[id] = row
ris = append(ris, &rowId{row: row, id: id})
}
sort.SliceStable(ris, func(i, j int) bool {
return ris[i].row < ris[j].row
})
for range ris {
sectionCmds = append(sectionCmds, &message.SectionCmdMsg{Drst: false, Pdrst: false})
}
}