dujunchen 2 hafta önce
ebeveyn
işleme
ca1a119d15

+ 1 - 0
.gitignore

@@ -0,0 +1 @@
+./info.log

+ 0 - 39
api/panel/asterisk/channel.go

@@ -1,39 +0,0 @@
-package asterisk
-
-import (
-	"net/http"
-	"pbx-api-gin/api/model"
-	"pbx-api-gin/internal/app/ami"
-	"pbx-api-gin/internal/app/ami/action"
-
-	"github.com/gin-gonic/gin"
-)
-
-// @tags Asterisk-Channel
-// @Summary 当前通话通道
-// @Description 当前通话通道
-// @Security ApiKeyAuth
-// @Accept  json
-// @Produce  json
-// @Success 200 {object} model.APIOK "请求成功"
-// @Router /ginapi/plugin-asterisk/channel/show-channels [get]
-func showChannels(ctx *gin.Context) {
-	data, err := action.CoreShowChannels()
-	if err != nil {
-		ctx.JSON(http.StatusBadRequest, model.APIError{ErrorMessage: err.Error()})
-		return
-	}
-	ctx.JSON(http.StatusOK, model.APIOK{Message: "ok", Data: data})
-}
-
-// @tags Asterisk-Channel
-// @Summary 当前 Bridge 通道
-// @Description 当前 Bridge 通道
-// @Security ApiKeyAuth
-// @Accept  json
-// @Produce  json
-// @Success 200 {object} model.APIOK "请求成功"
-// @Router /ginapi/plugin-asterisk/channel/show-bridge-channels [get]
-func showBridgeChannels(ctx *gin.Context) {
-	ctx.JSON(http.StatusOK, model.APIOK{Message: "ok", Data: ami.GetBridgeMapValue()})
-}

BIN
deployments/pbx-panel


+ 0 - 99
internal/app/ami/bridge.go

@@ -1,99 +0,0 @@
-package ami
-
-import (
-	"fmt"
-
-	"pbx-api-gin/pkg/lfshook"
-	"sync"
-
-	"github.com/mitchellh/mapstructure"
-)
-
-var bridgeMap sync.Map
-
-const bridgeEventName = "CustomBridgeEvent"
-
-type BridgeEvent struct {
-	Event string `json:"event"`
-	// Timestamp         string `json:"timestamp"`
-	BridgeUniqueid          string `json:"-"`
-	Channel                 string `json:"channel"`
-	ChannelState            string `json:"channelState"`
-	ChannelStateDesc        string `json:"channelStateDesc"`
-	CallerIDNum             string `json:"callerIDNumber"`
-	CallerIDName            string `json:"callerIDName"`
-	CallerConnectedLineNum  string `json:"callerConnectedLineNumber"`
-	CallerConnectedLineName string `json:"callerConnectedLineName"`
-	BridgeType              string `json:"bridgeType"`
-	BridgeNumChannels       string `json:"bridgeNumberChannels"`
-	Uniqueid                string `json:"uniqueid"`
-}
-
-func (event BridgeEvent) String() string {
-	return fmt.Sprintf("channel: %s, uniqueid: %s\n", event.Channel, event.Uniqueid)
-}
-
-func handleAMIBridge(event map[string]string) {
-	if event["BridgeType"] != "basic" {
-		return
-	}
-
-	if event["CallerIDName"] == "conference" {
-		return
-	}
-
-	switch event["Event"] {
-	case "BridgeCreate":
-		bridgeMap.Store(event["BridgeUniqueid"], []*BridgeEvent{})
-	case "BridgeEnter":
-		status := &BridgeEvent{}
-		mapstructure.Decode(event, status)
-		if events, ok := bridgeMap.Load(status.BridgeUniqueid); ok {
-			bridgeMap.Store(status.BridgeUniqueid, append(events.([]*BridgeEvent), status))
-		} else {
-			lfshook.NewLogger().Warnf("BridgeEnter add failure id: %s on load", status.BridgeUniqueid)
-		}
-		//socketio.SocketIOServer.BroadcastToNamespace("", bridgeEventName, GetBridgeMapValue())
-	case "BridgeLeave":
-		status := &BridgeEvent{}
-		mapstructure.Decode(event, status)
-		if events, ok := bridgeMap.Load(status.BridgeUniqueid); ok {
-			events := events.([]*BridgeEvent)
-			for index, event := range events {
-				if event.Channel == status.Channel {
-					if index == len(events)-1 {
-						bridgeMap.Store(status.BridgeUniqueid, events[:index])
-					} else {
-						bridgeMap.Store(status.BridgeUniqueid, append(events[:index], events[index+1]))
-					}
-					break
-				}
-			}
-		} else {
-			lfshook.NewLogger().Warnf("BridgeLeave remove failure id: %s on load", status.BridgeUniqueid)
-		}
-		//socketio.SocketIOServer.BroadcastToNamespace("", bridgeEventName, GetBridgeMapValue())
-	case "BridgeDestroy":
-		bridgeMap.Delete(event["BridgeUniqueid"])
-		//socketio.SocketIOServer.BroadcastToNamespace("", bridgeEventName, GetBridgeMapValue())
-	}
-
-}
-
-func GetBridgeMapValue() (result map[string][]*BridgeEvent) {
-	result = make(map[string][]*BridgeEvent)
-	bridgeMap.Range(func(key, value interface{}) bool {
-		events := value.([]*BridgeEvent)
-		result[key.(string)] = events
-		return true
-	})
-	return
-}
-
-// ClearBridge Asterisk 重启,内部通话清空, AMI 重连成功也需求清空 Bridge
-func ClearBridge() {
-	bridgeMap.Range(func(key, value interface{}) bool {
-		bridgeMap.Delete(key)
-		return true
-	})
-}

+ 14 - 174
internal/app/ami/index.go

@@ -1,14 +1,14 @@
 package ami
 
 import (
+	"net"
 	"pbx-api-gin/internal/app/ami/model"
 	"pbx-api-gin/internal/app/mysql"
-	"pbx-api-gin/internal/pkg/configs"
+	status "pbx-api-gin/internal/app/stc/sendstatus"
 
+	"pbx-api-gin/internal/pkg/configs"
 	"pbx-api-gin/pkg/lfshook"
-	"strings"
 
-	"github.com/mitchellh/mapstructure"
 	"github.com/sirupsen/logrus"
 	"github.com/tqcenglish/amigo-go"
 	"github.com/tqcenglish/amigo-go/pkg"
@@ -16,7 +16,7 @@ import (
 
 var AminInstance *amigo.Amigo
 
-func StartAMI(connectOKCallBack func(), handleEvents []func(event map[string]string)) {
+func StartAMI(connectOKCallBack func(), handleEvents []func(event map[string]string), conn net.Conn) {
 	lfshook.NewLogger().Info("Start AMI")
 	settings := &amigo.Settings{
 		Host:     configs.ConfigGlobal.AsteriskAMIHost,
@@ -29,9 +29,7 @@ func StartAMI(connectOKCallBack func(), handleEvents []func(event map[string]str
 	AminInstance.EventOn(func(payload ...interface{}) {
 		// lfshook.NewLogger().Infof("ami event on %+v", payload[0])
 		event := payload[0].(map[string]string)
-		handleAMIBridge(event)
-		handleAMI(event)
-		//handleSocketIO(event)
+		handleAMI(event, conn)
 
 		for _, handle := range handleEvents {
 			go handle(event)
@@ -41,7 +39,7 @@ func StartAMI(connectOKCallBack func(), handleEvents []func(event map[string]str
 	AminInstance.ConnectOn(func(payload ...interface{}) {
 		lfshook.NewLogger().Infof("ami connect on %+v", payload[0])
 		if payload[0] == pkg.Connect_OK {
-			ClearBridge()
+
 			connectOKCallBack()
 		} else {
 			lfshook.NewLogger().Errorf("ami connect failure %+v", payload)
@@ -50,28 +48,12 @@ func StartAMI(connectOKCallBack func(), handleEvents []func(event map[string]str
 	AminInstance.Connect()
 }
 
-func handleAMI(event map[string]string) {
+func handleAMI(event map[string]string, conn net.Conn) {
 	switch event["Event"] {
-	case "ContactStatus": /*
-			endpointName := event["EndpointName"]
-			contactStatus := event["ContactStatus"]
-
-			// 中继变化也会触发此事件, 需要忽略
-			switch contactStatus {
-			case "Reachable":
-				//add contact
-				uri := event["URI"]
-				data := strings.Split(uri, "@")
-				if len(data) < 2 {
-					lfshook.NewLogger().Debugf("split URI by @ error URI: %s event:%+v", uri, event)
-					return
-				}
-				first := data[1]
-				redis.ExtensionSet(endpointName, event["URI"], strings.Split(first, ":")[0], event["RoundtripUsec"])*/
-	case "Removed":
-		//remove contact
-		//redis.ExtensionDel(endpointName)
-
+	case "DialBegin":
+		status.AlarmStatus(event["DestCallerIDNum"], event["StatusText"], conn)
+	case "DialEnd":
+		//stc.AlarmStatus(event["DestCallerIDNum"], event["StatusText"], conn) //stop dial ICP(Reset dial status)
 	case "ExtensionStatus":
 
 		status := &model.Extension{
@@ -82,152 +64,10 @@ func handleAMI(event map[string]string) {
 		if err != nil {
 			lfshook.NewLogger().Infof("update extension status err : %+v", err.Error())
 		}
+		//stc.AlarmStatus(event["Exten"], event["StatusText"], conn) // idle + unavailable
+	case "BridgeEnter":
 
-	}
-}
-
-func handleSocketIO(event map[string]string) {
-	var data interface{}
-	switch event["Event"] {
-	case "ExtensionStatus":
-		lfshook.NewLogger().Tracef("ExtensionStatus %+v", event)
-		status := &model.ExtensionStatus{}
-		mapstructure.Decode(event, status)
-		data = status
-	case "QueueMemberStatus":
-		lfshook.NewLogger().Tracef("QueueMemberStatus %+v", event)
-		status := &model.QueueMember{}
-		mapstructure.Decode(event, status)
-		data = status
-	case "QueueCallerJoin":
-		status := &model.QueueCallerJoin{}
-		lfshook.NewLogger().Infof("status %+v", event)
-		mapstructure.Decode(event, status)
-		data = status
-	case "QueueCallerLeave":
-		status := &model.QueueCallerLeave{}
-		mapstructure.Decode(event, status)
-		data = status
-	case "QueueCallerAbandon":
-		status := &model.QueueCallerAbandon{}
-		mapstructure.Decode(event, status)
-		data = status
-	case "ParkedCall":
-		status := &model.ParkedCall{}
-		mapstructure.Decode(event, status)
-		data = status
-	case "ParkedCallTimeOut":
-		status := &model.ParkedCallTimeOut{}
-		mapstructure.Decode(event, status)
-		data = status
-	case "ParkedCallGiveUp":
-		status := &model.ParkedCallGiveUp{}
-		mapstructure.Decode(event, status)
-		data = status
-	case "UnParkedCall":
-		status := &model.UnParkedCall{}
-		mapstructure.Decode(event, status)
-		data = status
-
-	case "MeetmeEnd":
-		status := &model.MeetmeEnd{}
-		mapstructure.Decode(event, status)
-		data = status
-
-	case "MeetmeJoin":
-		fallthrough
-	case "MeetmeLeave":
-		fallthrough
-	case "MeetmeMute":
-		fallthrough
-	case "MeetmeTalking":
-		fallthrough
-	case "MeetmeTalkRequest":
-		status := &model.Meetme{}
-		mapstructure.Decode(event, status)
-		data = status
-
-	case "PresenceStateChange":
-		status := &model.PresenceStateChange{}
-		mapstructure.Decode(event, status)
-		if status.Presentity != "" {
-			data := strings.Split(status.Presentity, ":")
-			if len(data) == 2 {
-				status.Extension = data[1]
-			}
-		}
-
-		if status.Status == "dnd" {
-			status.DndStatus = "yes"
-		} else {
-			status.DndStatus = ""
-		}
-		data = status
-
-	case "DialBegin":
-		fallthrough
-	case "DialEnd":
-		fallthrough
-	case "DialState":
-		status := &model.Dial{}
-		mapstructure.Decode(event, status)
-		data = status
-
-	case "Newstate":
-		status := &model.Newstate{}
-		mapstructure.Decode(event, status)
-		data = status
-
-	case "Hangup":
-		status := &model.Hangup{}
-		mapstructure.Decode(event, status)
-		data = status
-
-	case "UserEvent":
-		switch event["UserEvent"] {
-		case "SetDND":
-			status := &model.SetDND{}
-			mapstructure.Decode(event, status)
-			data = status
-			event["Event"] = event["UserEvent"]
-		case "WakeUpStatus":
-			status := &model.WakeUpStatus{}
-			mapstructure.Decode(event, status)
-			data = status
-			event["Event"] = event["UserEvent"]
-		default:
-			data = event
-		}
-	case "SuccessfulAuth":
-		// 获取上线 IP 地址
-		status := &model.SuccessfulAuth{}
-		mapstructure.Decode(event, status)
-		status.GetAddress()
-		data = status
-
-	case "MessageWaiting":
-		status := &model.MessageWaiting{}
-		mapstructure.Decode(event, status)
-		status.GetExtension()
-		data = status
-		if status.Extension == "" {
-			lfshook.NewLogger().Warnf("MessageWaiting error %+v", event)
-			return
-		}
-	default:
-		// if !strings.Contains(event["Event"], "RTP") &&
-		// 	!strings.Contains(event["Event"], "RTCP") &&
-		// 	!strings.Contains(event["Event"], "VarSet") &&
-		// 	!strings.Contains(event["Event"], "Bridge") &&
-		// 	!strings.Contains(event["Event"], "New") &&
-		// 	!strings.Contains(event["Event"], "SuccessfulAuth") &&
-		// 	!strings.Contains(event["Event"], "ChallengeSent") {
-		// 	lfshook.NewLogger().Info(event)
-		// }
-	}
-
-	if data != nil {
-		//socketio.SocketIOServer.BroadcastToNamespace("", event["Event"], data)
+		//stc.AlarmStatus(event["CallerIDNum"], event["StatusText"], conn) // alarm connected
 	}
 }
 

+ 1 - 1
internal/app/ami/model/sip.go

@@ -27,7 +27,7 @@ type Extension struct {
 	Extension string `xorm:"exten" json:"exten"`
 	Type      string `xorm:"type" json:"type"`
 	Priority  string `xorm:"priority" json:"priority"`
-	Special   string `xorm:"special" json:"special"`
+	Special   int    `xorm:"special" json:"special"`
 	Status    string `xorm:"status" json:"status"`
 	Remark    string `xorm:"remark" json:"remark"`
 }

+ 5 - 4
internal/app/index.go

@@ -10,13 +10,14 @@ import (
 
 func StartApp() {
 	mysql.CreateDBInstance()
+
+	conn := stc.CreateConnection("192.168.17.14", 6090)
+
 	go ami.StartAMI(func() {
 		lfshook.NewLogger().Info("ami callback")
 		// 首次连接才进行初始化
-	}, []func(event map[string]string){})
-	//go agi.StartAGI()
+	}, []func(event map[string]string){}, conn)
 
-	//go stc.ConnectStc("127.0.0.1", "10100") //connect mc1
-	go stc.ConnectStc("192.168.17.14", 6090) //connect mc2
+	go stc.StartStcConnection(conn) //connect
 
 }

+ 65 - 13
internal/app/stc/operation/broadcast.go

@@ -1,14 +1,65 @@
-package stc
+package broadcast
 
 import (
 	"bytes"
-	"pbx-api-gin/api/model"
-	"pbx-api-gin/api/panel/asterisk"
+	"fmt"
+	"net"
 	"pbx-api-gin/internal/app/ami/action"
+	"pbx-api-gin/internal/app/ami/model"
 	"pbx-api-gin/internal/app/mysql"
 	"pbx-api-gin/pkg/lfshook"
 )
 
+func HandleStcCmd(conn net.Conn) {
+
+	for {
+		buffer := make([]byte, 1024)
+		n, err := conn.Read(buffer)
+		if err != nil {
+			fmt.Println("Error reading from server:", err)
+			return
+		}
+		fmt.Println("Received from server:", string(buffer[:n]))
+
+		switch buffer[5] {
+		case 0x01: //heartbeat
+
+		case 0x02: //STN
+			StationAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+
+		case 0x03: //ACTIVE
+			Active([1]byte{buffer[8]})
+
+		case 0x05: //SPC
+			SpecialAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+
+		case 0x06: //EMG
+			EmgMsg([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+		case 0x07: //STOP
+			AnnStop([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+		case 0x08: //DCS
+			DcsAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+		case 0x09: //SELF CHECK
+			SelfCheck([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+		case 0x0a: //
+			AlarmHandle([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+		case 0x0b: //
+			AlarmResetAll([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+		case 0x0c: //
+			RecordStorageConf([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
+		}
+	}
+}
+
+/*
+	func SendToStc(conn net.Conn, buff []byte) {
+		_, err := conn.Write(buff)
+		if err != nil {
+			fmt.Println("send msg err:", err)
+		}
+	}
+*/
+
 func StationAnn(data [4]byte) (err error) {
 	specialVoice := int(data[0])
 	Exten := "2411"
@@ -20,7 +71,7 @@ func StationAnn(data [4]byte) (err error) {
 
 	//update special voice
 	_, er := mysql.DBOrmInstance.Where("exten = ?", Exten).Update(&model.Extension{Special: specialVoice})
-	if err != nil {
+	if er != nil {
 		lfshook.NewLogger().Logger.Infof("update special voice to exten err : %+v", er.Error())
 		return er
 	}
@@ -77,15 +128,15 @@ func EmgMsg(data [4]byte) {
 
 func AnnStop(data [4]byte) {
 	if data[0] == 0x03 {
-		asterisk.Hangup("2412")
+		//asterisk.Hangup("2412")
 	} else if data[0] == 0x04 {
-		asterisk.Hangup("2412")
+		//asterisk.Hangup("2412")
 	} else if data[0] == 0x07 {
-		asterisk.Hangup("2412")
+		//asterisk.Hangup("2412")
 	} else if data[0] == 0x08 {
-		asterisk.Hangup("2412")
+		//asterisk.Hangup("2412")
 	} else if data[0] == 0x09 {
-		asterisk.Hangup("2412")
+		//asterisk.Hangup("2412")
 	}
 }
 
@@ -115,7 +166,7 @@ func SelfCheck(data [4]byte) {
 	if check == 0x01 {
 		action.Playback(filename, int(cycleCount), Exten, int(timeLen), int(delay))
 	} else if check == 0x02 {
-		asterisk.Hangup(Exten)
+		//asterisk.Hangup(Exten)
 	}
 }
 
@@ -124,11 +175,12 @@ func AlarmHandle(data [4]byte) {
 	//len := data[1]
 	//src := data[2]
 
-	if handler == 0x01 { //answer
+	switch handler {
+	case 0x01: //answer
 
-	} else if handler == 0x02 { //hold
+	case 0x02: //hold
 
-	} else if handler == 0x03 { //hangup
+	case 0x03: //hangup
 
 	}
 }

+ 113 - 0
internal/app/stc/data/msgdata.go

@@ -0,0 +1,113 @@
+package data
+
+import (
+	"bytes"
+	"encoding/binary"
+	"fmt"
+)
+
+// Protocol 定义协议数据结构
+type Protocol struct {
+	StartBytes    [3]byte // 协议开始符
+	SourceID      uint8   // 源设备号
+	DestinationID uint8   // 目的设备号
+	MessageID     uint8   // 消息号
+	DataLength    uint16  // 数据长度
+	Data          []byte  // 数据
+	Checksum      uint8   // 异或校验码
+	EndByte       uint8   // 协议结束符
+}
+
+// NewProtocol 创建一个新的 Protocol 实例
+func NewProtocol() *Protocol {
+	return &Protocol{
+		StartBytes: [3]byte{0x7F, 0x8E, 0x9D},
+		EndByte:    0xFE,
+	}
+
+}
+
+// Encode 将 Protocol 结构体编码为字节切片
+func (p *Protocol) Encode() ([]byte, error) {
+	// 初始化字节缓冲区
+	var buf bytes.Buffer // 写入协议开始符
+	buf.Write(p.StartBytes[:])
+
+	// 写入源设备号、目的设备号和消息号
+	binary.Write(&buf, binary.BigEndian, p.SourceID)
+	binary.Write(&buf, binary.BigEndian, p.DestinationID)
+	binary.Write(&buf, binary.BigEndian, p.MessageID)
+
+	// 写入数据长度
+	binary.Write(&buf, binary.BigEndian, p.DataLength)
+
+	// 写入数据
+	buf.Write(p.Data[:])
+
+	// 计算校验码
+	checksum := p.CalculateChecksum()
+	p.Checksum = checksum // 写入校验码
+	binary.Write(&buf, binary.BigEndian, p.Checksum)
+
+	// 写入协议结束符
+	binary.Write(&buf, binary.BigEndian, p.EndByte)
+
+	return buf.Bytes(), nil
+}
+
+// CalculateChecksum 计算校验码
+func (p *Protocol) CalculateChecksum() uint8 {
+	// 初始化校验码
+	checksum := uint8(0)
+
+	// 跳过协议开始符
+	data := append([]byte{byte(p.SourceID), byte(p.DestinationID), byte(p.MessageID)},
+		append([]byte{byte(p.DataLength >> 8), byte(p.DataLength)}, p.Data...)...)
+
+	// 计算校验码
+	for _, b := range data {
+		checksum ^= b
+	}
+
+	return checksum
+}
+
+// Decode 解码字节切片为 Protocol 结构体
+func Decode(data []byte) (*Protocol, error) {
+	if len(data) < 10 { // 最小长度:3(StartBytes) +1(SourceID) +1(DestinationID) +1(MessageID) +2(DataLength) +1(Checksum) +1(EndByte)
+		return nil, fmt.Errorf("data too short")
+	}
+
+	p := NewProtocol()
+
+	// 读取协议开始符
+	copy(p.StartBytes[:], data[:3])
+
+	// 读取源设备号、目的设备号和消息号
+	p.SourceID = data[3]
+	p.DestinationID = data[4]
+	p.MessageID = data[5]
+
+	// 读取数据长度
+	p.DataLength = binary.BigEndian.Uint16(data[6:8])
+
+	// 读取数据
+	dataLength := int(p.DataLength)
+	if len(data) < 10+dataLength {
+		return nil, fmt.Errorf("data length mismatch")
+	}
+	p.Data = data[8 : 8+dataLength]
+
+	// 读取校验码
+	p.Checksum = data[8+dataLength]
+
+	// 读取协议结束符
+	p.EndByte = data[9+dataLength]
+
+	// 验证校验码
+	if p.Checksum != p.CalculateChecksum() {
+		return nil, fmt.Errorf("checksum mismatch")
+	}
+
+	return p, nil
+}

+ 12 - 180
internal/app/stc/index.go

@@ -1,56 +1,32 @@
 package stc
 
 import (
-	"bufio"
-	"bytes"
-	"encoding/binary"
 	"fmt"
 	"log"
 	"net"
-	"os"
-	stc "pbx-api-gin/internal/app/stc/operation"
+	"pbx-api-gin/internal/app/stc/broadcast"
+	"pbx-api-gin/internal/app/stc/data"
+
 	"syscall"
 	"time"
 )
 
-// Protocol 定义协议数据结构
-type Protocol struct {
-	StartBytes    [3]byte // 协议开始符
-	SourceID      uint8   // 源设备号
-	DestinationID uint8   // 目的设备号
-	MessageID     uint8   // 消息号
-	DataLength    uint16  // 数据长度
-	Data          []byte  // 数据
-	Checksum      uint8   // 异或校验码
-	EndByte       uint8   // 协议结束符
-}
+func StartStcConnection(conn net.Conn) {
 
-// NewProtocol 创建一个新的 Protocol 实例
-func NewProtocol() *Protocol {
-	return &Protocol{
-		StartBytes: [3]byte{0x7F, 0x8E, 0x9D},
-		EndByte:    0xFE,
-	}
-
-}
-
-func ConnectStc(ServerAddr string, Port int) {
+	//read msg
+	go func(conn net.Conn) {
+		broadcast.HandleStcCmd(conn)
 
-	//=================================================
-	// connect server
-	conn := connectServer(ServerAddr, Port)
-	defer conn.Close()
+	}(conn)
 
-	//read msg
+	//heartbeat
 	go func(conn net.Conn) {
-		readMsg(conn)
+		Sendheartbeat(conn)
 	}(conn)
 
-	// send msg
-	sendMsg(conn)
 }
 
-func connectServer(ServerAddr string, Port int) net.Conn {
+func CreateConnection(ServerAddr string, Port int) net.Conn {
 	// connect server
 	conn, err := net.DialTCP("tcp", &net.TCPAddr{
 		IP:   net.ParseIP("0.0.0.0"),
@@ -74,7 +50,7 @@ func connectServer(ServerAddr string, Port int) net.Conn {
 func Sendheartbeat(conn net.Conn) {
 	var count uint8
 	//init heartbeat data
-	protocol := NewProtocol()
+	protocol := data.NewProtocol()
 	protocol.SourceID = 0x02
 	protocol.DestinationID = 0x01
 	protocol.MessageID = 0x21
@@ -99,147 +75,3 @@ func Sendheartbeat(conn net.Conn) {
 		}
 	}
 }
-
-func readMsg(conn net.Conn) {
-
-	for {
-		buffer := make([]byte, 1024)
-		n, err := conn.Read(buffer)
-		if err != nil {
-			fmt.Println("Error reading from server:", err)
-			return
-		}
-		fmt.Println("Received from server:", string(buffer[:n]))
-
-		switch buffer[5] {
-		case 0x01: //heartbeat
-
-		case 0x02: //STN
-			stc.StationAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-
-		case 0x03: //ACTIVE
-			stc.Active([1]byte{buffer[8]})
-
-		case 0x05: //SPC
-			stc.SpecialAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-
-		case 0x06: //EMG
-			stc.EmgMsg([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-		case 0x07: //STOP
-			stc.AnnStop([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-		case 0x08: //DCS
-			stc.DcsAnn([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-		case 0x09: //SELF CHECK
-			stc.SelfCheck([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-		case 0x0a: //
-			stc.AlarmHandle([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-		case 0x0b: //
-			stc.AlarmResetAll([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-		case 0x0c: //
-			stc.RecordStorageConf([4]byte{buffer[8], buffer[9], buffer[10], buffer[11]})
-		}
-	}
-}
-
-func sendMsg(conn net.Conn) {
-
-	//heartbeat
-	go func(conn net.Conn) {
-		Sendheartbeat(conn)
-	}(conn)
-
-	scanner := bufio.NewScanner(os.Stdin)
-	for scanner.Scan() {
-		text := scanner.Text()
-		_, err := conn.Write([]byte(text + "\n"))
-		if err != nil {
-			fmt.Println("send msg err:", err)
-			return
-		}
-	}
-}
-
-// Encode 将 Protocol 结构体编码为字节切片
-func (p *Protocol) Encode() ([]byte, error) {
-	// 初始化字节缓冲区
-	var buf bytes.Buffer // 写入协议开始符
-	buf.Write(p.StartBytes[:])
-
-	// 写入源设备号、目的设备号和消息号
-	binary.Write(&buf, binary.BigEndian, p.SourceID)
-	binary.Write(&buf, binary.BigEndian, p.DestinationID)
-	binary.Write(&buf, binary.BigEndian, p.MessageID)
-
-	// 写入数据长度
-	binary.Write(&buf, binary.BigEndian, p.DataLength)
-
-	// 写入数据
-	buf.Write(p.Data[:])
-
-	// 计算校验码
-	checksum := p.CalculateChecksum()
-	p.Checksum = checksum // 写入校验码
-	binary.Write(&buf, binary.BigEndian, p.Checksum)
-
-	// 写入协议结束符
-	binary.Write(&buf, binary.BigEndian, p.EndByte)
-
-	return buf.Bytes(), nil
-}
-
-// CalculateChecksum 计算校验码
-func (p *Protocol) CalculateChecksum() uint8 {
-	// 初始化校验码
-	checksum := uint8(0)
-
-	// 跳过协议开始符
-	data := append([]byte{byte(p.SourceID), byte(p.DestinationID), byte(p.MessageID)},
-		append([]byte{byte(p.DataLength >> 8), byte(p.DataLength)}, p.Data...)...)
-
-	// 计算校验码
-	for _, b := range data {
-		checksum ^= b
-	}
-
-	return checksum
-}
-
-// Decode 解码字节切片为 Protocol 结构体
-func Decode(data []byte) (*Protocol, error) {
-	if len(data) < 10 { // 最小长度:3(StartBytes) +1(SourceID) +1(DestinationID) +1(MessageID) +2(DataLength) +1(Checksum) +1(EndByte)
-		return nil, fmt.Errorf("data too short")
-	}
-
-	p := NewProtocol()
-
-	// 读取协议开始符
-	copy(p.StartBytes[:], data[:3])
-
-	// 读取源设备号、目的设备号和消息号
-	p.SourceID = data[3]
-	p.DestinationID = data[4]
-	p.MessageID = data[5]
-
-	// 读取数据长度
-	p.DataLength = binary.BigEndian.Uint16(data[6:8])
-
-	// 读取数据
-	dataLength := int(p.DataLength)
-	if len(data) < 10+dataLength {
-		return nil, fmt.Errorf("data length mismatch")
-	}
-	p.Data = data[8 : 8+dataLength]
-
-	// 读取校验码
-	p.Checksum = data[8+dataLength]
-
-	// 读取协议结束符
-	p.EndByte = data[9+dataLength]
-
-	// 验证校验码
-	if p.Checksum != p.CalculateChecksum() {
-		return nil, fmt.Errorf("checksum mismatch")
-	}
-
-	return p, nil
-}

+ 34 - 0
internal/app/stc/sendstatus/status.go

@@ -0,0 +1,34 @@
+package status
+
+import (
+	"net"
+	"pbx-api-gin/internal/app/stc/data"
+)
+
+func AlarmStatus(exten string, status string, conn net.Conn) {
+
+	//ext, _ := strconv.Atoi(exten)
+	//if ext
+	//len := data[1]
+	//src := data[2]
+	protocol := data.NewProtocol()
+	protocol.MessageID = 0x26
+	protocol.DataLength = 0x04
+
+	protocol.Data[0] = byte(int(exten[3] - 0))
+	protocol.Data[1] = byte(int(exten[2] - 0))
+
+	switch status {
+	case "Unavailable": //offline
+		protocol.Data[2] = 0x01
+	case "idle": //idle
+		protocol.Data[2] = 0x00
+	case "dial": //dial
+		protocol.Data[2] = 0x01
+	case "Hold": //hold
+		protocol.Data[2] = 0x01
+	case "InUse", "Busy": //connect
+		protocol.Data[2] = 0x01
+	}
+
+}