dujunchen 1 місяць тому
батько
коміт
89ca76678b

+ 1 - 0
cmd/main.go

@@ -72,6 +72,7 @@ func main() {
 func initVersion() {
 	if gitCommitCode != "" {
 		//构建信息
+		utils.Logger.Printf("software version: V10.01")
 		lfshook.NewLogger().Printf("git commit code: %s", gitCommitCode)
 		lfshook.NewLogger().Printf("build date: %s", buildDateTime)
 		lfshook.NewLogger().Printf("go version: %s", goVersion)

+ 2 - 0
internal/app/ami/action/call.go

@@ -38,6 +38,7 @@ func InActiveHangup() {
 		HangupTask("STN")
 		HangupTask("CHK")
 		HangupTask("VOL")
+		Hangup("2311") //hangup cabcab
 	}
 }
 
@@ -509,6 +510,7 @@ func SetPadTimer() {
 				lfshook.NewLogger().Logger.Infof("=========Release PAD timer false ! ============")
 			}
 		}
+		lfshook.NewLogger().Logger.Infof("=========Start PAD timer !======%d=======", active.PADTimeout)
 		//active.QueueTimer = time.AfterFunc(time.Duration(active.PADTimeout)*time.Second, func() { // check the PAD 30s timeout
 		active.QueueTimer = time.AfterFunc(30*time.Second, func() { // check the PAD 30s timeout
 			//if both not active , return

+ 29 - 15
internal/app/ami/action/index.go

@@ -3,6 +3,7 @@ package action
 import (
 	"fmt"
 	"os"
+	"path/filepath"
 	"pbx-api-gin/internal/app/stc/active"
 	"pbx-api-gin/internal/app/stc/priority"
 	alstatus "pbx-api-gin/internal/app/stc/sendstatus"
@@ -162,13 +163,13 @@ func HandleAMI(event map[string]string) {
 			//执行加密操作,并将录音信息写入日志文件
 			DstFile := ""
 			if len(FileNames) > 0 { // 文件切割之后进入循环处理
-				for _, filepath := range FileNames {
+				for _, filepathFull := range FileNames {
 
-					file := strings.Replace(filepath, ".wav", "", -1)
+					file := strings.Replace(filepathFull, ".wav", "", -1)
 					DstFile = fmt.Sprintf("%s-encrypted.wav", file)
 
 					//lfshook.NewLogger().Infof("Bin file====%s", DstFile)
-					err = utils.AudioFileEncode(DstFile, filepath)
+					err = utils.AudioFileEncode(DstFile, filepathFull)
 					if err != nil {
 						lfshook.NewLogger().Infof("Encode file: %s err: %+v", DstFile, err)
 						continue
@@ -176,34 +177,46 @@ func HandleAMI(event map[string]string) {
 					//切割&加密之后发送生成的文件名到STC;
 					alstatus.SendRecordFile(DstFile, event["RecordType"])
 
-					trainInfo = active.ActivedCab
+					trainInfo = fmt.Sprintf("Train Number %s     CabNumber %s", active.TrainNum, active.ActivedCab)
 
 					if strings.Contains(event["FILENAME"], "PAD") {
 						_, caller, callee := utils.GetPadInfo(event["FILENAME"])
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: PAD , CabNumber: %c , LocationCode: %c, Connected: %s, RecordFileName:%s", trainInfo, caller[2], caller[3], callee, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: PAD , CabNumber: %c , LocationCode: %c, Connected: %s, RecordFileName:%s", trainInfo, caller[2], caller[3], callee, DstFile)
 					} else if strings.Contains(event["FILENAME"], "PA") {
 						_, caller, _ := utils.GetPadInfo(event["FILENAME"])
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: PA, Caller: %s, RecordFileName: %s", trainInfo, caller, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: PA, Caller: %s, RecordFileName: %s", trainInfo, caller, DstFile)
 					} else if strings.Contains(event["FILENAME"], "C2C") {
 						_, caller, _ := utils.GetPadInfo(event["FILENAME"])
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: CabCab, Caller: %s, RecordFileName: %s", trainInfo, caller, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: CabCab, Caller: %s, RecordFileName: %s", trainInfo, caller, DstFile)
 					} else if strings.Contains(event["FILENAME"], "CPA") {
 						_, caller, _ := utils.GetPadInfo(event["FILENAME"])
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: CPA, Caller: %s, RecordFileName: %s", trainInfo, caller, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: CPA, Caller: %s, RecordFileName: %s", trainInfo, caller, DstFile)
 					} else if strings.Contains(event["FILENAME"], "EMG") {
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: EMG, RecordFileName: %s", trainInfo, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: EMG, RecordFileName: %s", trainInfo, DstFile)
 					} else if strings.Contains(event["FILENAME"], "STN") {
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: STN, RecordFileName: %s", trainInfo, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: STN, RecordFileName: %s", trainInfo, DstFile)
 					} else if strings.Contains(event["FILENAME"], "DCS") {
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: DCS, RecordFileName: %s", trainInfo, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: DCS, RecordFileName: %s", trainInfo, DstFile)
 					} else if strings.Contains(event["FILENAME"], "SPC") {
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: SPC, RecordFileName: %s", trainInfo, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: SPC, RecordFileName: %s", trainInfo, DstFile)
 					} else if strings.Contains(event["FILENAME"], "CHK") {
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: Self Check, RecordFileName: %s", trainInfo, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: Self Check, RecordFileName: %s", trainInfo, DstFile)
 					} else if strings.Contains(event["FILENAME"], "TONE") {
-						utils.Logger.Printf("Train Information: CabNumber %s, MessageType: TONE Test, RecordFileName: %s", trainInfo, DstFile)
+						utils.Logger.Printf("Train Information:%s , MessageType: TONE Test, RecordFileName: %s", trainInfo, DstFile)
 					}
 				}
+
+				//Get path & generate recording XML file
+				path := filepath.Dir(event["FILENAME"])
+				rcdFileName := filepath.Base(event["FILENAME"])
+				xmlFileName := strings.Replace(rcdFileName, "wav", "xml", 1)
+				xmlFilePath := path + xmlFileName
+
+				err := active.GenerateXML(xmlFilePath)
+				if err != nil {
+					lfshook.NewLogger().Infof("Generate recording XML err:%+v", err)
+				}
+
 			} else {
 				lfshook.NewLogger().Infof("No files to upload!!!")
 				break
@@ -312,7 +325,7 @@ func HandleAMI(event map[string]string) {
 					//SetPadTimer()
 					alstatus.PaStatus("", "PAD", "end")
 					priority.PADStart = 0
-					priority.PADTMSStart = 0
+					//priority.PADTMSStart = 0
 
 					//clean confbridge
 					//PAD-ICP
@@ -396,6 +409,7 @@ func HandleAMI(event map[string]string) {
 						lfshook.NewLogger().Logger.Infof("=========Release PAD timer false ! ============")
 					}
 				}
+				lfshook.NewLogger().Logger.Infof("=========Start PAD timer !======%d=======", active.PADTimeout)
 				//active.QueueTimer = time.AfterFunc(time.Duration(active.PADTimeout)*time.Second, func() { // check the PAD 30s timeout
 				active.QueueTimer = time.AfterFunc(30*time.Second, func() { // check the PAD 30s timeout
 					//if both not active , return

+ 89 - 0
internal/app/stc/active/index.go

@@ -1,8 +1,10 @@
 package active
 
 import (
+	"encoding/xml"
 	"fmt"
 	"net/http"
+	"os"
 	"pbx-api-gin/pkg/lfshook"
 	"time"
 )
@@ -13,6 +15,49 @@ var ActivedCab = "1"
 var PADTimeout = 30
 var Master = false
 
+trainMap := make(map[string]map[int]string)
+// 初始化所有列车号
+	trains := []string{"TS1", "TS2", "TS3", "TS4", "TS5", "TS6", "TS7", "TS8", "TS9", "TS10", "TS11", "TS12", "TS13"}
+
+	data := [][]string{
+		{"D433", "P433", "M433", "K433", "C434", "M434", "P434", "D434"},
+		{"D435", "P435", "M435", "K435", "C436", "M436", "P436", "D436"},
+		{"D437", "P437", "M437", "K437", "C438", "M438", "P438", "D438"},
+		{"D439", "P439", "M439", "K439", "C440", "M440", "P440", "D440"},
+		{"D441", "P441", "M441", "K441", "C442", "M442", "P442", "D442"},
+		{"D443", "P443", "M443", "K443", "C444", "M444", "P444", "D444"},
+		{"D445", "P445", "M445", "K445", "C446", "M446", "P446", "D446"},
+		{"D447", "P447", "M447", "K447", "C448", "M448", "P448", "D448"},
+		{"D449", "P449", "M449", "K449", "C450", "M450", "P450", "D450"},
+		{"D451", "P451", "M451", "K451", "C452", "M452", "P452", "D452"},
+		{"D453", "P653", "M453", "K453", "C454", "M454", "P454", "D454"},
+		{"D455", "P455", "M455", "K455", "C456", "M456", "P456", "D456"},
+		{"D457", "P457", "M457", "K457", "C458", "M458", "P458", "D458"},
+	}
+	
+var TrainNum = ""
+
+// Pacu 表示单个 pacu 节点
+type Pacu struct {
+	ID     string `xml:"id"`
+	Status string `xml:"status"`
+	Volume string `xml:"volume"`
+	Mute   bool   `xml:"mute"`
+}
+
+// Icp 表示单个 icp 节点
+type Icp struct {
+	ID     string `xml:"id"`
+	Volume string `xml:"volume"`
+}
+
+type Device struct {
+	PacuInfo [8]Pacu `xml:"-"` // 不自动序列化,由自定义方法处理
+	ICPInfo  [2]Icp  `xml:"-"`
+}
+
+var DeviceEndpoint Device
+
 // var SetTimer = false
 var QueueTimer *time.Timer = nil
 
@@ -48,3 +93,47 @@ func NotifyPaiu(Exten, Action string) {
 	   fmt.Printf("响应内容: %s\n", body)
 	*/
 }
+
+// MarshalXML 实现自定义 XML 输出:按顺序写入所有 pacu 和 icp 节点
+func (d Device) MarshalXML(e *xml.Encoder, start xml.StartElement) error {
+	// 写入根标签 <device>
+	if err := e.EncodeToken(xml.StartElement{Name: xml.Name{Local: "device"}}); err != nil {
+		return err
+	}
+
+	// 写入所有 <pacu> 节点
+	for _, p := range DeviceEndpoint.PacuInfo {
+		if err := e.Encode(p); err != nil {
+			return err
+		}
+	}
+
+	// 写入所有 <icp> 节点
+	for _, i := range DeviceEndpoint.ICPInfo {
+		if err := e.Encode(i); err != nil {
+			return err
+		}
+	}
+
+	// 写入根结束标签 </device>
+	return e.EncodeToken(xml.EndElement{Name: xml.Name{Local: "device"}})
+}
+
+func GenerateXML(pt string) error {
+	// 创建文件(会覆盖同名文件)
+	file, err := os.Create(pt)
+	if err != nil {
+		fmt.Printf("创建文件失败: %v\n", err)
+		return err
+	}
+	defer file.Close() // 确保关闭
+
+	// 使用 xml.Encoder 写入(更规范,支持缩进、处理特殊字符等)
+	encoder := xml.NewEncoder(file)
+	encoder.Indent("", "  ") // 启用缩进,等效于 MarshalIndent
+	if err := encoder.Encode(DeviceEndpoint); err != nil {
+		fmt.Printf("XML 编码写入失败: %v\n", err)
+		return err
+	}
+	return err
+}

+ 56 - 4
internal/app/stc/broadcast/stc-broadcast.go

@@ -3,6 +3,7 @@ package broadcast
 import (
 	"bytes"
 	"context"
+	"encoding/binary"
 	"fmt"
 	"io"
 	"net"
@@ -53,6 +54,56 @@ func HandleStcCmd(ctx context.Context, conn net.Conn) {
 	}
 }
 
+// get train info and pacu info from heartbeat
+func processHeartbeat(info []byte) {
+	//dataCount := info[0]
+	//Get train info
+	trainNumB1 := info[2]
+	trainNumB2 := info[3]
+	active.TrainNum = fmt.Sprintf("%s%s", string(trainNumB1), string(trainNumB2))
+	lfshook.NewLogger().Logger.Infof("TrainNum:%s===Byte1:%x=====Byte2:%x====str1:%s===str2:%s", active.TrainNum, trainNumB1, trainNumB2, string(trainNumB1), string(trainNumB2))
+
+	//Get ICP volume
+	active.DeviceEndpoint.ICPInfo[0].Volume = string((info[9] >> 4) & 0xF)
+	active.DeviceEndpoint.ICPInfo[0].ID = "1"
+	active.DeviceEndpoint.ICPInfo[1].Volume = string((info[9]) & 0xF)
+	active.DeviceEndpoint.ICPInfo[1].ID = "8"
+
+	//Get Pacu info
+	eidsStat := info[1]
+	pacuStat := info[4]
+	pacuVolume := binary.BigEndian.Uint32(info[4:8])
+
+	for i := 0; i < 8; i++ {
+		eidsBit := (eidsStat >> i) & 0x01       // 右移 i 位,再与 1 取最低位
+		fmt.Printf("bit %d = %d\n", i, eidsBit) // bit 0 是 LSB(最低位,最右)
+		//id = i
+		//mute = eidsBit
+
+		pacuStatBit := (pacuStat >> i) & 0x01
+		fmt.Printf("bit %d = %d\n", i, pacuStatBit)
+		//status = pacuStatBit
+
+		pacuVolBit := (pacuVolume >> i) & 0xF
+		fmt.Printf("bit %d = %d\n", i, pacuVolBit)
+		//volum = pacuVolBit
+
+		active.DeviceEndpoint.PacuInfo[i].ID = strconv.Itoa(i)
+		if eidsBit == 1 {
+			active.DeviceEndpoint.PacuInfo[i].Mute = true
+		} else {
+			active.DeviceEndpoint.PacuInfo[i].Mute = false
+		}
+		if pacuStatBit == 0 {
+			active.DeviceEndpoint.PacuInfo[i].Status = "normal"
+		} else {
+			active.DeviceEndpoint.PacuInfo[i].Status = "abnormal"
+		}
+		active.DeviceEndpoint.PacuInfo[i].Volume = strconv.Itoa(int(pacuVolBit))
+		lfshook.NewLogger().Logger.Infof("PACU INFO===ID:%s===Mute:%s===Stat:%s===Vol:%s", active.DeviceEndpoint.PacuInfo[i].ID, active.DeviceEndpoint.PacuInfo[i].Mute, active.DeviceEndpoint.PacuInfo[i].Status, active.DeviceEndpoint.PacuInfo[i].Volume)
+	}
+}
+
 // 处理单个数据包(原 switch 逻辑迁移过来)
 func processPacket(packet []byte) {
 
@@ -84,8 +135,8 @@ func processPacket(packet []byte) {
 
 	switch packet[5] {
 	case 0x01: //heartbeat
+		processHeartbeat(packet[8:])
 
-		break
 	case 0x02: // STN
 		if active.ActivedCab != "" {
 			if priority.CheckPriority("STN") {
@@ -212,6 +263,7 @@ func PadTimeOutSetting(data []byte) {
 	Seconds := data[7]
 	if Seconds != 0 {
 		active.PADTimeout = int(Seconds)
+		//lfshook.NewLogger().Logger.Infof("=========Set PAD Timeout seconds to %d ! ============", int(Seconds))
 	}
 
 }
@@ -244,21 +296,21 @@ func Active(data [2]byte) {
 		if !utils.CheckAsterisk() { //check asterisk not available and set master false
 			active.Master = false
 
-			utils.ExecCmd("/etc/init.d/asterisk", "stop")
+			utils.ExecCmd("/etc/init.d/asterisk", "stop", "PBX")
 		}
 	} else { // master false, check and start asterisk
 
 		//Master == false
 		if !utils.CheckAsterisk() {
 			if active.CabNum == "8" {
-				utils.ExecCmd("/etc/init.d/asterisk", "start")
+				utils.ExecCmd("/etc/init.d/asterisk", "start", "PBX")
 			}
 		}
 
 		//Master == false  cab == 1
 		if active.CabNum == "1" {
 			if utils.CheckAsterisk() {
-				utils.ExecCmd("/etc/init.d/asterisk", "stop")
+				utils.ExecCmd("/etc/init.d/asterisk", "stop", "PBX")
 			}
 		}
 	}

+ 3 - 2
internal/app/stc/index.go

@@ -33,9 +33,10 @@ func StartStcConnection(conn net.Conn, cab string) {
 			continue
 		}
 
+		trainInfo := fmt.Sprintf("Train Number %s     CabNumber %s", active.TrainNum, active.ActivedCab)
 		//set connection log
 		if logTag == 0 {
-			utils.Logger.Printf("Train Information: CabNumber %s, Message: Connection to Cab%s STC is up !", active.ActivedCab, cab)
+			utils.Logger.Printf("Train Information: %s, Message: Connection to Cab%s STC is up !", trainInfo, cab)
 			logTag = 1
 		}
 
@@ -82,7 +83,7 @@ func StartStcConnection(conn net.Conn, cab string) {
 
 		//set connection log
 		if logTag == 1 {
-			utils.Logger.Printf("Train Information: CabNumber %s, Message: Connection to Cab%s STC is down !", active.ActivedCab, cab)
+			utils.Logger.Printf("Train Information: %s, Message: Connection to Cab%s STC is down !", trainInfo, cab)
 			logTag = 0
 		}
 

+ 6 - 3
pkg/utils/file.go

@@ -9,6 +9,7 @@ import (
 	"os/exec"
 	"path/filepath"
 	"pbx-api-gin/internal/pkg/configs"
+	"pbx-api-gin/pkg/lfshook"
 	"strconv"
 	"strings"
 )
@@ -136,8 +137,8 @@ func WriteLogToFile(message string) {
 	defer file.Close()
 
 	// 创建一个写入到文件的日志器
-	logger := log.New(file, "", log.LstdFlags)
-
+	//logger := log.New(file, "", log.LstdFlags)
+	logger := log.New(file, "", log.LstdFlags|log.Lmicroseconds)
 	// 写入日志消息
 	logger.Println(message)
 }
@@ -146,7 +147,9 @@ var Logger *log.Logger
 
 func init() {
 	file, _ := os.OpenFile("/data/test/log/recordEvent.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
-	Logger = log.New(file, "", log.LstdFlags) // 自动带时间戳
+	//Logger = log.New(file, "", log.LstdFlags) // 自动带时间戳
+	Logger = log.New(file, "", log.LstdFlags|log.Lmicroseconds)
+	lfshook.NewLogger().Printf("software version: V10.01")
 }
 
 func GetPadInfo(base string) (padType, padNum, connectedCab string) {

+ 39 - 0
test.go

@@ -0,0 +1,39 @@
+package test
+
+import "fmt"
+
+func main1() {
+	// 构建映射表:map[列车号][位置] = 车厢号
+	trainMap := make(map[string]map[int]string)
+	// 初始化所有列车号
+	trains := []string{"TS1", "TS2", "TS3", "TS4", "TS5", "TS6", "TS7", "TS8", "TS9", "TS10", "TS11", "TS12", "TS13"}
+	//positions := []string{"1", "2", "3", "4", "5", "6", "7", "8"}
+	// 数据:从你的表格中提取
+	data := [][]string{
+		{"D433", "P433", "M433", "K433", "C434", "M434", "P434", "D434"},
+		{"D435", "P435", "M435", "K435", "C436", "M436", "P436", "D436"},
+		{"D437", "P437", "M437", "K437", "C438", "M438", "P438", "D438"},
+		{"D439", "P439", "M439", "K439", "C440", "M440", "P440", "D440"},
+		{"D441", "P441", "M441", "K441", "C442", "M442", "P442", "D442"},
+		{"D443", "P443", "M443", "K443", "C444", "M444", "P444", "D444"},
+		{"D445", "P445", "M445", "K445", "C446", "M446", "P446", "D446"},
+		{"D447", "P447", "M447", "K447", "C448", "M448", "P448", "D448"},
+		{"D449", "P449", "M449", "K449", "C450", "M450", "P450", "D450"},
+		{"D451", "P451", "M451", "K451", "C452", "M452", "P452", "D452"},
+		{"D453", "P653", "M453", "K453", "C454", "M454", "P454", "D454"},
+		{"D455", "P455", "M455", "K455", "C456", "M456", "P456", "D456"},
+		{"D457", "P457", "M457", "K457", "C458", "M458", "P458", "D458"},
+	}
+
+	// 填充 map
+	for i, train := range trains {
+		trainMap[train] = make(map[int]string)
+		for j, car := range data[i] {
+			trainMap[train][j+1] = car //位置从1开始
+		}
+	}
+	// 示例查询
+	fmt.Println(trainMap["TS1"][1])  // 输出: D433
+	fmt.Println(trainMap["TS5"][3])  // 输出: M441
+	fmt.Println(trainMap["TS13"][8]) // 输出: D458
+}