fixed RTP/CMoIP streaming

master
cheetah 1 year ago
parent b42323d518
commit a1a6c6d7ef

@ -10,5 +10,6 @@ type RegistrationInfo struct {
CallCount byte CallCount byte
StreamCount byte StreamCount byte
RoamingRef uint32 RoamingRef uint32
Description string
RTPPorts []uint16 RTPPorts []uint16
} }

@ -0,0 +1,21 @@
package common
type TetraFlexCMoIPPayload byte
const (
TetraFlexCMoIPPayload_None TetraFlexCMoIPPayload = 0
TetraFlexCMoIPPayload_Tetra_STCH_U TetraFlexCMoIPPayload = 1
TetraFlexCMoIPPayload_Tetra_TCH_S TetraFlexCMoIPPayload = 2
TetraFlexCMoIPPayload_Tetra_TCH_7_2 TetraFlexCMoIPPayload = 3
TetraFlexCMoIPPayload_Tetra_TCH_4_8 TetraFlexCMoIPPayload = 4
TetraFlexCMoIPPayload_Tetra_TCH_2_4 TetraFlexCMoIPPayload = 5
TetraFlexCMoIPPayload_aLaw TetraFlexCMoIPPayload = 7
TetraFlexCMoIPPayload_uLaw TetraFlexCMoIPPayload = 8
)
type TetraFlexRTPPayload byte
const (
TetraFlexRTPPayload_uLaw TetraFlexRTPPayload = 0
TetraFlexRTPPayload_aLaw TetraFlexRTPPayload = 8
)

@ -8,6 +8,7 @@ import (
"fmt" "fmt"
"io" "io"
"net" "net"
"strings"
"git.cheetah.cat/cheetah/opentetraflex-go/common/tmkind" "git.cheetah.cat/cheetah/opentetraflex-go/common/tmkind"
) )
@ -24,6 +25,8 @@ type TerminalClient struct {
GroupConfig []GroupConfig GroupConfig []GroupConfig
RegistrationInfo RegistrationInfo RegistrationInfo RegistrationInfo
udpRTP_TX *net.UDPConn
} }
func NewTerminalClient(address string) (tc *TerminalClient) { func NewTerminalClient(address string) (tc *TerminalClient) {
@ -184,6 +187,26 @@ func (tc *TerminalClient) CallConnect(callRef byte) (err error) {
return nil return nil
} }
func (tc *TerminalClient) CallStreamRequest(uint1 uint, callRef byte, streamRef byte, audioChannelType TetraFlexAudioChannelTypes) (err error) {
tfStreamReq, err := NewTMIpApiCallStreamRequest(uint1, callRef, streamRef, audioChannelType)
if err != nil {
return nil
}
fmt.Println(hex.EncodeToString(tfStreamReq.Encode()))
tc.HandlerMap[tfStreamReq.handler] = make(chan HandlerResponse)
//fmt.Println(hex.EncodeToString(tfAuthReq.Encode()))
err = tc.Send(tfStreamReq)
if err != nil {
return err
}
response := <-tc.HandlerMap[tfStreamReq.handler]
if !response.Success {
return response.Error
}
return nil
}
func (tc *TerminalClient) PTTRequest(callRef byte, identityInfo TetraFlexIdentityInfo, octaStateByte byte) (err error) { func (tc *TerminalClient) PTTRequest(callRef byte, identityInfo TetraFlexIdentityInfo, octaStateByte byte) (err error) {
// IpApiCallPttRequest // IpApiCallPttRequest
tfPTTRequest, err := NewTMIpApiCallPTTRequest(callRef, identityInfo, octaStateByte) tfPTTRequest, err := NewTMIpApiCallPTTRequest(callRef, identityInfo, octaStateByte)
@ -226,6 +249,32 @@ func (tc *TerminalClient) PTTRelease(callRef byte) (err error) {
return nil return nil
} }
func (tc *TerminalClient) RTPConnect() (err error) {
portNum := tc.RegistrationInfo.RTPPorts[0]
localAddress, _ := net.ResolveUDPAddr("udp", fmt.Sprintf("0.0.0.0:%d", portNum))
parts := strings.Split(tc.address, ":")
remoteTXAddr := fmt.Sprintf("%s:%d", parts[0], portNum)
remoteAddress, _ := net.ResolveUDPAddr("udp", remoteTXAddr)
tc.udpRTP_TX, err = net.DialUDP("udp", localAddress, remoteAddress)
if err != nil {
return err
}
return nil
}
func (tc *TerminalClient) RTPSend(data []byte) (err error) {
//parts := strings.Split(tc.address, ":")
//remoteTXAddr := fmt.Sprintf("%s:%d", parts[0], tc.RegistrationInfo.RTPPorts[0])
//remoteAddress, _ := net.ResolveUDPAddr("udp", remoteTXAddr)
_, err = tc.udpRTP_TX.Write(data) //WriteToUDP(data, remoteAddress)
if err != nil {
return err
}
return nil
}
/* /*
groupAddr := common.NewAddressFromSSINumber(103) groupAddr := common.NewAddressFromSSINumber(103)
identityNum := common.NewAddressFromSSINumber(1007) identityNum := common.NewAddressFromSSINumber(1007)

@ -37,11 +37,11 @@ func NewTerminalMessage(length uint16, kind tmkind.TetraFlexTerminalMessageKinds
return tm, nil return tm, nil
} }
// Write<Type> Functions
func (tm *TerminalMessage) WriteShort(data uint16) (err error) { func (tm *TerminalMessage) WriteShort(data uint16) (err error) {
_, err = tm.data.Write(uint16ToBytes(data)) _, err = tm.data.Write(uint16ToBytes(data))
return err return err
} }
func (tm *TerminalMessage) WriteUInt(data uint32) (err error) { func (tm *TerminalMessage) WriteUInt(data uint32) (err error) {
_, err = tm.data.Write(uint32ToBytes(data)) _, err = tm.data.Write(uint32ToBytes(data))
return err return err
@ -150,11 +150,9 @@ func (tm *TerminalMessage) WriteTFAddress(addr TetraFlexAddress) (err error) {
//return tm.data.WriteByte(data) //return tm.data.WriteByte(data)
return nil return nil
} }
func (tm *TerminalMessage) WriteIdentityInfoAddress(identityInfo TetraFlexIdentityInfo) (err error) { func (tm *TerminalMessage) WriteIdentityInfoAddress(identityInfo TetraFlexIdentityInfo) (err error) {
return tm.WriteTFAddress(identityInfo.Address) return tm.WriteTFAddress(identityInfo.Address)
} }
func (tm *TerminalMessage) WriteIdentityInfoKind(identityInfo TetraFlexIdentityInfo) (err error) { func (tm *TerminalMessage) WriteIdentityInfoKind(identityInfo TetraFlexIdentityInfo) (err error) {
/* /*
case TetraFlexIdentityKind.Mobile: case TetraFlexIdentityKind.Mobile:
@ -175,16 +173,15 @@ func (tm *TerminalMessage) WriteIdentityInfoUnfied(identityInfo TetraFlexIdentit
} }
return tm.data.WriteByte(byteVal) return tm.data.WriteByte(byteVal)
} }
func (tm *TerminalMessage) FillZero(zeroCount uint32) (err error) { func (tm *TerminalMessage) FillZero(zeroCount uint32) (err error) {
_, err = tm.data.Write(make([]byte, zeroCount)) _, err = tm.data.Write(make([]byte, zeroCount))
return err return err
} }
func (tm *TerminalMessage) Encode() []byte { func (tm *TerminalMessage) Encode() []byte {
return tm.data.Bytes() return tm.data.Bytes()
} }
// TerminalMessage Builder for PDUs
func NewTMAuthReq(addr TetraFlexAddress, num uint32, randomBytes []byte, terminalTypeID byte, terminalTypeStr string, terminalVersionDate uint32, terminalVersionStr string) (tm *TerminalMessage, err error) { func NewTMAuthReq(addr TetraFlexAddress, num uint32, randomBytes []byte, terminalTypeID byte, terminalTypeStr string, terminalVersionDate uint32, terminalVersionStr string) (tm *TerminalMessage, err error) {
tfAuthReq, err := NewTerminalMessage(256, tmkind.IpApiRegistrationRequest, NextHandlerID()) tfAuthReq, err := NewTerminalMessage(256, tmkind.IpApiRegistrationRequest, NextHandlerID())
if err != nil { if err != nil {

@ -121,6 +121,13 @@ func (tmr *TerminalMessageResponse) readAddress() (result TetraFlexAddress, err
return result, nil return result, nil
} }
func (tmr *TerminalMessageResponse) readString(count int) (result string, err error) {
textBytes := make([]byte, count)
if _, err = tmr.data.Read(textBytes); err != nil {
return result, err
}
return string(textBytes), nil
}
func (tmr *TerminalMessageResponse) AsAuthenticationChallenge() (authChallenge AuthenticationChallenge, err error) { func (tmr *TerminalMessageResponse) AsAuthenticationChallenge() (authChallenge AuthenticationChallenge, err error) {
authChallenge.RandomSeed = make([]byte, 10) authChallenge.RandomSeed = make([]byte, 10)
@ -181,6 +188,14 @@ func (tmr *TerminalMessageResponse) AsRegistrationInfo() (regInfo RegistrationIn
if regInfo.RoamingRef, err = tmr.readUInt32(); err != nil { if regInfo.RoamingRef, err = tmr.readUInt32(); err != nil {
return regInfo, err return regInfo, err
} }
if regInfo.Description, err = tmr.readString(64); err != nil {
return regInfo, err
}
if err != nil {
return regInfo, err
}
if regInfo.RemoteVersion > 20120702 { if regInfo.RemoteVersion > 20120702 {
port1, err := tmr.readUInt16() port1, err := tmr.readUInt16()
if err != nil { if err != nil {

@ -3,23 +3,24 @@ package tmkind
type TetraFlexTerminalMessageKinds uint16 type TetraFlexTerminalMessageKinds uint16
const ( const (
NONE TetraFlexTerminalMessageKinds = 0 NONE TetraFlexTerminalMessageKinds = 0
IpApiGeneralConfirm TetraFlexTerminalMessageKinds = 1 IpApiGeneralConfirm TetraFlexTerminalMessageKinds = 1
IpApiRegistrationRequest TetraFlexTerminalMessageKinds = 273 IpApiRegistrationRequest TetraFlexTerminalMessageKinds = 273
IpApiRegistrationConfirm TetraFlexTerminalMessageKinds = 274 IpApiRegistrationConfirm TetraFlexTerminalMessageKinds = 274
IpApiAuthenticationChallenge TetraFlexTerminalMessageKinds = 529 IpApiAuthenticationChallenge TetraFlexTerminalMessageKinds = 529
IpApiAuthenticationResponse TetraFlexTerminalMessageKinds = 530 IpApiAuthenticationResponse TetraFlexTerminalMessageKinds = 530
IpApiNotificationRequest TetraFlexTerminalMessageKinds = 785 IpApiNotificationRequest TetraFlexTerminalMessageKinds = 785
IpApiNotificationConfirm TetraFlexTerminalMessageKinds = 786 IpApiNotificationConfirm TetraFlexTerminalMessageKinds = 786
IpApiGroupAttachRequest TetraFlexTerminalMessageKinds = 1041 IpApiGroupAttachRequest TetraFlexTerminalMessageKinds = 1041
IpApiGroupAttachConfirm TetraFlexTerminalMessageKinds = 1042 IpApiGroupAttachConfirm TetraFlexTerminalMessageKinds = 1042
IpApiDeregistrationRequest TetraFlexTerminalMessageKinds = 1297 IpApiDeregistrationRequest TetraFlexTerminalMessageKinds = 1297
IpApiKeepAliveChallenge TetraFlexTerminalMessageKinds = 1553 IpApiKeepAliveChallenge TetraFlexTerminalMessageKinds = 1553
IpApiKeepAliveResponse TetraFlexTerminalMessageKinds = 1554 IpApiKeepAliveResponse TetraFlexTerminalMessageKinds = 1554
IpApiSubscriberInfoRequest TetraFlexTerminalMessageKinds = 1809 IpApiSubscriberInfoRequest TetraFlexTerminalMessageKinds = 1809
IpApiSubscriberInfoConfirm TetraFlexTerminalMessageKinds = 1810 IpApiSubscriberInfoConfirm TetraFlexTerminalMessageKinds = 1810
IpApiSoftwareInfoRequest TetraFlexTerminalMessageKinds = 2065 IpApiSoftwareInfoRequest TetraFlexTerminalMessageKinds = 2065
IpApiSoftwareInfoConfirm TetraFlexTerminalMessageKinds = 2066 IpApiSoftwareInfoConfirm TetraFlexTerminalMessageKinds = 2066
IpApiCallSetupRequest TetraFlexTerminalMessageKinds = 4369 IpApiCallSetupRequest TetraFlexTerminalMessageKinds = 4369
IpApiCallSetupConfirm TetraFlexTerminalMessageKinds = 4370 IpApiCallSetupConfirm TetraFlexTerminalMessageKinds = 4370
IpApiCallConnectRequest TetraFlexTerminalMessageKinds = 4625 IpApiCallConnectRequest TetraFlexTerminalMessageKinds = 4625
@ -28,14 +29,15 @@ const (
IpApiCallStreamRequest TetraFlexTerminalMessageKinds = 5393 IpApiCallStreamRequest TetraFlexTerminalMessageKinds = 5393
IpApiCallUpdateNotification TetraFlexTerminalMessageKinds = 5649 IpApiCallUpdateNotification TetraFlexTerminalMessageKinds = 5649
IpApiCallRoamingFinishedNotification TetraFlexTerminalMessageKinds = 5905 IpApiCallRoamingFinishedNotification TetraFlexTerminalMessageKinds = 5905
IpApiSdsDataType4Request TetraFlexTerminalMessageKinds = 9233
IpApiSdsStatusRequest TetraFlexTerminalMessageKinds = 9489 IpApiSdsDataType4Request TetraFlexTerminalMessageKinds = 9233
IpApiSdsTlTransferRequest TetraFlexTerminalMessageKinds = 9745 IpApiSdsStatusRequest TetraFlexTerminalMessageKinds = 9489
IpApiSdsTlReportRequest TetraFlexTerminalMessageKinds = 10001 IpApiSdsTlTransferRequest TetraFlexTerminalMessageKinds = 9745
IpApiSdsTlShortReportRequest TetraFlexTerminalMessageKinds = 10257 IpApiSdsTlReportRequest TetraFlexTerminalMessageKinds = 10001
IpApiSdsDataType4Notification TetraFlexTerminalMessageKinds = 13329 IpApiSdsTlShortReportRequest TetraFlexTerminalMessageKinds = 10257
IpApiSdsStatusNotification TetraFlexTerminalMessageKinds = 13585 IpApiSdsDataType4Notification TetraFlexTerminalMessageKinds = 13329
IpApiSdsTlTransferNotification TetraFlexTerminalMessageKinds = 13841 IpApiSdsStatusNotification TetraFlexTerminalMessageKinds = 13585
IpApiSdsTlReportNotification TetraFlexTerminalMessageKinds = 14097 IpApiSdsTlTransferNotification TetraFlexTerminalMessageKinds = 13841
IpApiSdsTlShortReportNotification TetraFlexTerminalMessageKinds = 14353 IpApiSdsTlReportNotification TetraFlexTerminalMessageKinds = 14097
IpApiSdsTlShortReportNotification TetraFlexTerminalMessageKinds = 14353
) )

@ -1,10 +1,13 @@
package main package main
import ( import (
"bufio"
"encoding/hex" "encoding/hex"
"encoding/json" "encoding/json"
"fmt" "fmt"
"math/rand" "math/rand"
"os"
"strings"
"time" "time"
"git.cheetah.cat/cheetah/opentetraflex-go/common" "git.cheetah.cat/cheetah/opentetraflex-go/common"
@ -26,7 +29,7 @@ func main() {
// //
myAddr := common.TetraFlexAddress{ myAddr := common.TetraFlexAddress{
Kind: common.UserNo, Kind: common.UserNo,
UserNo: "1005", UserNo: "9400001",
} }
err = terminalClient.Authenticate(myAddr) err = terminalClient.Authenticate(myAddr)
if err != nil { if err != nil {
@ -69,19 +72,17 @@ func main() {
} }
fmt.Println("Groups attached") fmt.Println("Groups attached")
go func() { go func() {
fmt.Println("Test started, waiting 3s")
time.Sleep(3 * time.Second)
groupAddr := common.NewAddressFromSSINumber(101) groupAddr := common.NewAddressFromSSINumber(101)
fmt.Println("Test callSetup") fmt.Println("Test callSetup")
callRef, err := terminalClient.CallSetup(*groupAddr, common.CallTypeGroup, common.CallPriorityDefault, false, common.TetraFlexIdentityInfo{ callRef, err := terminalClient.CallSetup(*groupAddr, common.CallTypeGroup, common.CallPriorityDefault, false, common.TetraFlexIdentityInfo{
Description: "Blaa", Description: "2m/FM Gateway SWM",
/* Kind: common.IdentityKindApplication, /* Kind: common.IdentityKindApplication,
Address: *common.NewAddressFromSSINumber(1002), Address: *common.NewAddressFromSSINumber(1002),
UnifiedSSIKinds: common.UnifiedKindExternalNumber, UnifiedSSIKinds: common.UnifiedKindExternalNumber,
*/ */
Kind: common.IdentityKindTerminal, Kind: common.IdentityKindTerminal,
Address: *common.NewAddressFromSSINumber(1002), Address: *common.NewAddressFromSSINumber(9400001),
UnifiedSSIKinds: common.UnifiedKindPersonalNumber, UnifiedSSIKinds: common.UnifiedKindPersonalNumber,
}) })
if err != nil { if err != nil {
@ -89,6 +90,11 @@ func main() {
} }
fmt.Printf("callRef=%d\n", callRef) fmt.Printf("callRef=%d\n", callRef)
err = terminalClient.CallStreamRequest(0, callRef, 0, common.AudioChannel_CMoIP_Tetra) // CMoIP_aLaw
if err != nil {
panic(err)
}
// IpApiCallStreamRequest // IpApiCallStreamRequest
err = terminalClient.PTTRequest(callRef, common.TetraFlexIdentityInfo{ err = terminalClient.PTTRequest(callRef, common.TetraFlexIdentityInfo{
Description: "Blaa", Description: "Blaa",
@ -104,18 +110,62 @@ func main() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
time.Sleep(3 * time.Second) time.Sleep(1 * time.Second)
// PTT Release
err = terminalClient.PTTRelease(callRef) // Connect RTP
err = terminalClient.RTPConnect()
if err != nil { if err != nil {
panic(err) panic(err)
} }
time.Sleep(3 * time.Second)
err = terminalClient.CallDisconnect(callRef, common.DisconnectReason_CallRejectedByCalled) file, err := os.Open("./test.tetra.txt")
if err != nil { if err != nil {
panic(err) panic(err)
} }
defer file.Close()
scanner := bufio.NewScanner(file)
var counter byte = 0
var voiceArray [][]byte
for scanner.Scan() {
hexData := scanner.Text()
hexData = strings.Trim(hexData, " ")
byteData, _ := hex.DecodeString(hexData)
fmt.Println(hexData)
voiceArray = append(voiceArray, byteData)
}
for {
for _, byteData := range voiceArray {
fmt.Println(byteData)
byteData[8] = counter
err = terminalClient.RTPSend(byteData)
if err != nil {
panic(err)
}
if counter == 255 {
counter = 128
} else {
counter++
}
time.Sleep(20 * time.Millisecond)
}
}
/*
time.Sleep(3 * time.Second)
// PTT Release
err = terminalClient.PTTRelease(callRef)
if err != nil {
panic(err)
}
time.Sleep(3 * time.Second)
err = terminalClient.CallDisconnect(callRef, common.DisconnectReason_CallRejectedByCalled)
if err != nil {
panic(err)
}
*/
// IpApiCallPttRequest // IpApiCallPttRequest
}() }()
// idk send help xD // idk send help xD

Loading…
Cancel
Save