package broadcast import ( "bytes" "context" "fmt" "io" "net" "pbx-api-gin/internal/app/ami/action" "pbx-api-gin/internal/app/stc/active" msgdata "pbx-api-gin/internal/app/stc/data" "pbx-api-gin/internal/app/stc/priority" alstatus "pbx-api-gin/internal/app/stc/sendstatus" "pbx-api-gin/pkg/utils" "strconv" "time" ) var tagLog = 0 func HandleStcCmd(ctx context.Context, conn net.Conn) { for { select { case <-ctx.Done(): return default: var buf bytes.Buffer tmp := make([]byte, 1024) if conn != nil { n, err := conn.Read(tmp) if err != nil { if err != io.EOF { conn.Close() } return } buf.Write(tmp[:n]) } //lfshook.NewLogger().Logger.Infof("buf:%x==============================", buf.Bytes()) for { packet, err := msgdata.ExtractPacket(&buf) if err != nil { utils.LoggerDebug.Printf("Parse error: %v, resetting buffer", err) buf.Reset() // 解析失败,清空避免污染 break } if packet == nil { break // 当前无完整包,等待下次 ReadFrom } //处理 packet... go processPacket(packet) } } } } // 处理单个数据包(原 switch 逻辑迁移过来) func processPacket(packet []byte) { if len(packet) < 6 { utils.LoggerDebug.Printf("Get data wrong length from STC ! Data:%x", packet) return } //for recv data log debug if packet[5] != 0x0b && packet[5] != 0x09 { utils.LoggerDebug.Printf("Get data from STC:%x", packet) } //重联模式判断 if packet[5] == 0x0b { active.TrainUnionID = int(packet[8]) active.TrainUnionMaster = int(packet[9]) active.TrainUnionMode = int(packet[10]) if active.TrainUnionID != 0 { utils.LoggerDebug.Printf("active.TrainUnionID:%x active.TrainUnionMaster:%x active.TrainUnionMode:%x ", active.TrainUnionID, active.TrainUnionMaster, active.TrainUnionMode) } if active.TrainUnionMode == 1 && active.TrainUnionMaster == 1 { //尾--头,重联主车,6车服务器停用 if active.CabNum == "6" { return } } else if active.TrainUnionMode == 1 && active.TrainUnionMaster == 2 { //尾--头,重联从车,1车服务器停用 if active.CabNum == "1" { return } } else if active.TrainUnionMode == 2 && active.TrainUnionMaster == 1 { //尾--尾,重联主车,6车服务器停用 if active.CabNum == "6" { return } } else if active.TrainUnionMode == 2 && active.TrainUnionMaster == 2 { //尾--尾,重联从车,6车服务器停用 if active.CabNum == "6" { return } } else if active.TrainUnionMode == 3 && active.TrainUnionMaster == 1 { //头--头,重联主车,1车服务器停用 if active.CabNum == "1" { return } } else if active.TrainUnionMode == 3 && active.TrainUnionMaster == 2 { //头--头,重联从车,1车服务器停用 if active.CabNum == "1" { return } } else if active.TrainUnionMode == 4 && active.TrainUnionMaster == 1 { //头--尾,重联主车,1车服务器停用 if active.CabNum == "1" { return } } else if active.TrainUnionMode == 4 && active.TrainUnionMaster == 2 { //头--尾,重联从车,6车服务器停用 if active.CabNum == "6" { return } } } //check if Master role if !active.Master { if tagLog == 0 { utils.LoggerDebug.Printf("Not Master Role , Ignore all data from STC !") tagLog = 1 } return } tagLog = 0 switch packet[5] { case 0x01: //心跳 return case 0x02: // 自动报站 if priority.CheckPriority("STNA") { action.HangupTask() StationAnnAuto(packet[8:]) } else { alstatus.PaStatus("", "STNA", "refuse") } case 0x03: // 手动报站 if priority.CheckPriority("STNS") { action.HangupTask() StationAnnAuto(packet[8:]) } else { alstatus.PaStatus("", "STNS", "refuse") } case 0x04: // 手动服务消息、紧急广播 if priority.CheckPriority("SVM") { action.HangupTask() EmgMsg(packet[8:]) } else { alstatus.PaStatus("", "SVM", "refuse") } case 0x05: // STOP AnnStop([4]byte{packet[8], packet[9], packet[10], packet[11]}) //case 0x06: // 关门提示(预留) //DoorStatusNotice(packet[8:]) //case 0x07: // 司机室位置(预留) case 0x08: // EED报警 EEDAlarm(packet[8:]) //case 0x09: // 列车运行模式(预留) // RuningStatus(packet[8:]) //case 0x0a:(预留) //case 0x0b: // 重联方式 // active.TrainUnionMode = int(packet[9]) } } // EED报警,激活报警器到队列 func EEDAlarm(data []byte) { cab := data[0] pos := data[1] alarm := fmt.Sprintf("7%02d%d", cab, pos) //utils.LoggerDebug.Printf("Type:STN FileName:%x Count:%x SpecialVoice:%+v Interval:%+v", filename, cycleCount, specialVoice, delay) action.Dial(alarm, "0300", "queues", "", "") } // DSN ,开关门提示 func DoorStatusNotice(data []byte) (err error) { delay := data[0] cycleCount := data[1] FileLen := int(data[2]) filename := msgdata.SubstrByRune(string(data[3:]), 0, int(FileLen)-4) //utils.LoggerDebug.Printf("Type:STN FileName:%x Count:%x SpecialVoice:%+v Interval:%+v", filename, cycleCount, specialVoice, delay) action.PlaybackPacu(strconv.Quote(filename), int(cycleCount), int(delay), "DCS") return nil } // APA , 自动报站广播 func StationAnnAuto(data []byte) (err error) { //StationStatus := int(data[0]) filelen := data[1] filename := msgdata.SubstrByRune(string(data[2:]), 0, int(filelen)-4) //utils.LoggerDebug.Printf("Type:STN FileName:%x Count:%x SpecialVoice:%+v Interval:%+v", filename, cycleCount, specialVoice, delay) action.PlaybackPacu(strconv.Quote(filename), 1, 0, "STNA") return nil } // SPA , 手动报站广播 func StationAnnManu(data []byte) (err error) { //StationStatus := int(data[0]) filelen := data[1] filename := msgdata.SubstrByRune(string(data[2:]), 0, int(filelen)-4) //utils.LoggerDebug.Printf("Type:STN FileName:%x Count:%x SpecialVoice:%+v Interval:%+v", filename, cycleCount, specialVoice, delay) action.PlaybackPacu(strconv.Quote(filename), 1, 0, "STNS") return nil } // EMG ,紧急服务消息广播 func EmgMsg(data []byte) { delay := data[0] cycleCount := data[1] filelen := int(data[2]) filename := msgdata.SubstrByRune(string(data[3:]), 0, filelen-4) utils.LoggerDebug.Printf("Type:EMG FileName:%x Count:%x Interval:%+v", filename, cycleCount, delay) if int(cycleCount) == 255 { action.PlaybackPacu(strconv.Quote(filename), 9999999, int(delay), "SVM") } else { action.PlaybackPacu(strconv.Quote(filename), int(cycleCount), int(delay), "SVM") } } // 停止指定类型广播 func AnnStop(data [4]byte) { //lfshook.NewLogger().Logger.Infof("=========AnnStop Type %x", data[0]) utils.LoggerDebug.Printf("Stop PA Type:%x (自动报站=1,手动报站=2,服务信息=3)", data[0]) switch data[0] { case 0x01: //停止自动广播(自动报站) taskInfo, ok := priority.RegistryTask.Get("STNA") if ok { action.ConfbridgeKick(taskInfo.ConfbridgeID, "all") action.Hangup(taskInfo.RunChannel) } time.Sleep(time.Millisecond * 100) case 0x02: //停止半自动广播(手动报站) taskInfo, ok := priority.RegistryTask.Get("STNS") if ok { action.ConfbridgeKick(taskInfo.ConfbridgeID, "all") action.Hangup(taskInfo.RunChannel) } time.Sleep(time.Millisecond * 100) case 0x03: //停止服务信息广播(紧急广播) taskInfo, ok := priority.RegistryTask.Get("SVM") if ok { action.ConfbridgeKick(taskInfo.ConfbridgeID, "all") action.Hangup(taskInfo.RunChannel) } time.Sleep(time.Millisecond * 100) } }