fixed RTP/CMoIP streaming
This commit is contained in:
parent
b42323d518
commit
a1a6c6d7ef
7 changed files with 180 additions and 45 deletions
|
@ -10,5 +10,6 @@ type RegistrationInfo struct {
|
|||
CallCount byte
|
||||
StreamCount byte
|
||||
RoamingRef uint32
|
||||
Description string
|
||||
RTPPorts []uint16
|
||||
}
|
||||
|
|
21
common/rtpenums.go
Normal file
21
common/rtpenums.go
Normal file
|
@ -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"
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"git.cheetah.cat/cheetah/opentetraflex-go/common/tmkind"
|
||||
)
|
||||
|
@ -24,6 +25,8 @@ type TerminalClient struct {
|
|||
|
||||
GroupConfig []GroupConfig
|
||||
RegistrationInfo RegistrationInfo
|
||||
|
||||
udpRTP_TX *net.UDPConn
|
||||
}
|
||||
|
||||
func NewTerminalClient(address string) (tc *TerminalClient) {
|
||||
|
@ -184,6 +187,26 @@ func (tc *TerminalClient) CallConnect(callRef byte) (err error) {
|
|||
|
||||
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) {
|
||||
// IpApiCallPttRequest
|
||||
tfPTTRequest, err := NewTMIpApiCallPTTRequest(callRef, identityInfo, octaStateByte)
|
||||
|
@ -226,6 +249,32 @@ func (tc *TerminalClient) PTTRelease(callRef byte) (err error) {
|
|||
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)
|
||||
identityNum := common.NewAddressFromSSINumber(1007)
|
||||
|
|
|
@ -37,11 +37,11 @@ func NewTerminalMessage(length uint16, kind tmkind.TetraFlexTerminalMessageKinds
|
|||
return tm, nil
|
||||
}
|
||||
|
||||
// Write<Type> Functions
|
||||
func (tm *TerminalMessage) WriteShort(data uint16) (err error) {
|
||||
_, err = tm.data.Write(uint16ToBytes(data))
|
||||
return err
|
||||
}
|
||||
|
||||
func (tm *TerminalMessage) WriteUInt(data uint32) (err error) {
|
||||
_, err = tm.data.Write(uint32ToBytes(data))
|
||||
return err
|
||||
|
@ -150,11 +150,9 @@ func (tm *TerminalMessage) WriteTFAddress(addr TetraFlexAddress) (err error) {
|
|||
//return tm.data.WriteByte(data)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (tm *TerminalMessage) WriteIdentityInfoAddress(identityInfo TetraFlexIdentityInfo) (err error) {
|
||||
return tm.WriteTFAddress(identityInfo.Address)
|
||||
}
|
||||
|
||||
func (tm *TerminalMessage) WriteIdentityInfoKind(identityInfo TetraFlexIdentityInfo) (err error) {
|
||||
/*
|
||||
case TetraFlexIdentityKind.Mobile:
|
||||
|
@ -175,16 +173,15 @@ func (tm *TerminalMessage) WriteIdentityInfoUnfied(identityInfo TetraFlexIdentit
|
|||
}
|
||||
return tm.data.WriteByte(byteVal)
|
||||
}
|
||||
|
||||
func (tm *TerminalMessage) FillZero(zeroCount uint32) (err error) {
|
||||
_, err = tm.data.Write(make([]byte, zeroCount))
|
||||
return err
|
||||
}
|
||||
|
||||
func (tm *TerminalMessage) Encode() []byte {
|
||||
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) {
|
||||
tfAuthReq, err := NewTerminalMessage(256, tmkind.IpApiRegistrationRequest, NextHandlerID())
|
||||
if err != nil {
|
||||
|
|
|
@ -121,6 +121,13 @@ func (tmr *TerminalMessageResponse) readAddress() (result TetraFlexAddress, err
|
|||
|
||||
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) {
|
||||
authChallenge.RandomSeed = make([]byte, 10)
|
||||
|
@ -181,6 +188,14 @@ func (tmr *TerminalMessageResponse) AsRegistrationInfo() (regInfo RegistrationIn
|
|||
if regInfo.RoamingRef, err = tmr.readUInt32(); err != nil {
|
||||
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 {
|
||||
port1, err := tmr.readUInt16()
|
||||
if err != nil {
|
||||
|
|
|
@ -20,6 +20,7 @@ const (
|
|||
IpApiSubscriberInfoConfirm TetraFlexTerminalMessageKinds = 1810
|
||||
IpApiSoftwareInfoRequest TetraFlexTerminalMessageKinds = 2065
|
||||
IpApiSoftwareInfoConfirm TetraFlexTerminalMessageKinds = 2066
|
||||
|
||||
IpApiCallSetupRequest TetraFlexTerminalMessageKinds = 4369
|
||||
IpApiCallSetupConfirm TetraFlexTerminalMessageKinds = 4370
|
||||
IpApiCallConnectRequest TetraFlexTerminalMessageKinds = 4625
|
||||
|
@ -28,6 +29,7 @@ const (
|
|||
IpApiCallStreamRequest TetraFlexTerminalMessageKinds = 5393
|
||||
IpApiCallUpdateNotification TetraFlexTerminalMessageKinds = 5649
|
||||
IpApiCallRoamingFinishedNotification TetraFlexTerminalMessageKinds = 5905
|
||||
|
||||
IpApiSdsDataType4Request TetraFlexTerminalMessageKinds = 9233
|
||||
IpApiSdsStatusRequest TetraFlexTerminalMessageKinds = 9489
|
||||
IpApiSdsTlTransferRequest TetraFlexTerminalMessageKinds = 9745
|
||||
|
|
60
main.go
60
main.go
|
@ -1,10 +1,13 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.cheetah.cat/cheetah/opentetraflex-go/common"
|
||||
|
@ -26,7 +29,7 @@ func main() {
|
|||
//
|
||||
myAddr := common.TetraFlexAddress{
|
||||
Kind: common.UserNo,
|
||||
UserNo: "1005",
|
||||
UserNo: "9400001",
|
||||
}
|
||||
err = terminalClient.Authenticate(myAddr)
|
||||
if err != nil {
|
||||
|
@ -69,19 +72,17 @@ func main() {
|
|||
}
|
||||
fmt.Println("Groups attached")
|
||||
go func() {
|
||||
fmt.Println("Test started, waiting 3s")
|
||||
time.Sleep(3 * time.Second)
|
||||
groupAddr := common.NewAddressFromSSINumber(101)
|
||||
fmt.Println("Test callSetup")
|
||||
callRef, err := terminalClient.CallSetup(*groupAddr, common.CallTypeGroup, common.CallPriorityDefault, false, common.TetraFlexIdentityInfo{
|
||||
Description: "Blaa",
|
||||
Description: "2m/FM Gateway SWM",
|
||||
|
||||
/* Kind: common.IdentityKindApplication,
|
||||
Address: *common.NewAddressFromSSINumber(1002),
|
||||
UnifiedSSIKinds: common.UnifiedKindExternalNumber,
|
||||
*/
|
||||
Kind: common.IdentityKindTerminal,
|
||||
Address: *common.NewAddressFromSSINumber(1002),
|
||||
Address: *common.NewAddressFromSSINumber(9400001),
|
||||
UnifiedSSIKinds: common.UnifiedKindPersonalNumber,
|
||||
})
|
||||
if err != nil {
|
||||
|
@ -89,6 +90,11 @@ func main() {
|
|||
}
|
||||
fmt.Printf("callRef=%d\n", callRef)
|
||||
|
||||
err = terminalClient.CallStreamRequest(0, callRef, 0, common.AudioChannel_CMoIP_Tetra) // CMoIP_aLaw
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// IpApiCallStreamRequest
|
||||
err = terminalClient.PTTRequest(callRef, common.TetraFlexIdentityInfo{
|
||||
Description: "Blaa",
|
||||
|
@ -104,6 +110,48 @@ func main() {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
// Connect RTP
|
||||
err = terminalClient.RTPConnect()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
file, err := os.Open("./test.tetra.txt")
|
||||
if err != nil {
|
||||
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)
|
||||
|
@ -116,6 +164,8 @@ func main() {
|
|||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
*/
|
||||
// IpApiCallPttRequest
|
||||
}()
|
||||
// idk send help xD
|
||||
|
|
Loading…
Add table
Reference in a new issue