172 lines
9.5 KiB
C#
172 lines
9.5 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace SDRGatewayService
|
|
{
|
|
public enum TGctrl { TGControlNotUsed = 0x0, TGChangeOnAlert = 0x1, TGChangeUserInter = 0x2, Reserved = 0x3 };
|
|
public enum CallOutFunction { Alert = 0x1, Test = 0x2, Info = 0x3, Clear = 0x4, Availability = 0x5, AvailabilityRequest = 0x6 };
|
|
public enum TextEncoding { ISO8859Latin1 = 0x1, ISO10646UTF = 0x1A };
|
|
public enum UDH { Yes = 0x01, No = 0x00 };
|
|
|
|
public class CallOutClass
|
|
{
|
|
public UInt32 callOutNumber = 1;
|
|
public byte cm_msg_id = 1;
|
|
|
|
public static byte[] SendCallOut(bool recFlag, uint callOutFunction, uint callOutNumber, uint callOutSeverity, uint tgCtrl, uint tgNumber,
|
|
ref byte cm_msg_id, UInt32 sourceISSI, UInt32 destISSI, string data)
|
|
{
|
|
|
|
// Call Out Function [15-12] + CallOutNumber [11-4] + CallOutSeverity [3-0]
|
|
//uint bytes23 = (uint)CallOutFunction.Alert * 4096 + callOutNumber * 16 + callOutSeverity;
|
|
UInt16 callOut = (UInt16)(callOutFunction * 0x1000 + callOutNumber * 0x10 + callOutSeverity);
|
|
|
|
// TGctrl [31-30] + TGnumber [29-6] + Reserved [5-0]
|
|
UInt32 talkGroup = (uint)tgCtrl * 0x40000000 + tgNumber * 0x40 + 0x00;
|
|
|
|
|
|
//return SDR_CallOut(ref cm_msg_id, sourceISSI, destISSI, callOut, talkGroup, data);
|
|
return SDTS_CallOut(recFlag, ref cm_msg_id, sourceISSI, destISSI, callOut, talkGroup, data);
|
|
|
|
}
|
|
|
|
public static byte[] SDTS_CallOut(bool recFlag, ref byte cm_msg_id, UInt32 sourceISSI, UInt32 destISSI, UInt16 callOut, UInt32 talkGroup, string data)
|
|
{
|
|
int buflen = 0;
|
|
if (data != null) buflen = data.Length;
|
|
|
|
byte[] cmBytes = SDR_CM_COM_CallOut(ref cm_msg_id, sourceISSI, destISSI);
|
|
|
|
byte[] tlBytes = SDTS_TLX_CallOut(callOut, talkGroup);
|
|
|
|
CallOutFunction callOutFunction = (CallOutFunction)((callOut >> 12) & 0x0000f);
|
|
if (callOutFunction == CallOutFunction.Test ||
|
|
callOutFunction == CallOutFunction.Info ||
|
|
callOutFunction == CallOutFunction.Clear)
|
|
Array.Resize(ref tlBytes, tlBytes.Length - 7); // cut the buffer at the right length
|
|
else if (callOutFunction == CallOutFunction.Availability ||
|
|
callOutFunction == CallOutFunction.AvailabilityRequest)
|
|
Array.Resize(ref tlBytes, tlBytes.Length - 8);
|
|
|
|
|
|
// compute the TL length in bits
|
|
// the TL fields are taken into consideration (count starting with 'TL encoding scheme' and transform in bits (*8) ) ==> 9 fields
|
|
if (tlBytes != null)
|
|
{
|
|
int headerLength = tlBytes[0] * 256 + tlBytes[1];
|
|
int tlLength = tlBytes.Length - headerLength;
|
|
|
|
tlBytes[3] = (byte)((((buflen + tlLength) * 8) & 0xff00) >> 8);
|
|
tlBytes[4] = (byte)(((buflen + tlLength) * 8) & 0x00ff);
|
|
}
|
|
|
|
// compute the CM length in bytes
|
|
byte[] cmSize = new byte[2];
|
|
if (cmBytes != null)
|
|
{
|
|
int cmLength = cmBytes.Length + tlBytes.Length + buflen;
|
|
|
|
cmSize[0] = (byte)((cmLength & 0xff00) >> 8);
|
|
cmSize[1] = (byte)(cmLength & 0x00ff);
|
|
}
|
|
|
|
byte[] cmResult = Combine(cmSize, cmBytes);
|
|
|
|
if (recFlag)
|
|
tlBytes[6] = 0x80;
|
|
|
|
if (buflen > 0)
|
|
return Combine(cmResult, tlBytes, Encoding.UTF8.GetBytes(data));
|
|
|
|
return Combine(cmResult, tlBytes);
|
|
}
|
|
|
|
public static byte[] SDR_CM_COM_CallOut(ref byte cm_msg_id, UInt32 sourceISSI, UInt32 destISSI)
|
|
{
|
|
if (cm_msg_id > 0xfe) cm_msg_id = 0;
|
|
cm_msg_id += 1;
|
|
|
|
byte[] msg = { 0x17, //1 PDU Type
|
|
0x01, //2 Protocol version
|
|
0x00, //3 header length
|
|
0x34, //4 header length ( 52 bytes )
|
|
0x40, //5 Next PDU Type ( SDTS_CM_TLX)
|
|
0x00,0x00,0x00,0x00,0x00, //6-10 Reserved
|
|
0x01, //11 Calling party type identifier
|
|
(byte)(((UInt32)sourceISSI & 0xff0000)>>16), //12 source ISSI
|
|
(byte)(((UInt32)sourceISSI & 0x00ff00)>>8), //13 source ISSI
|
|
(byte)(((UInt32)sourceISSI & 0x0000ff)), //14 source ISSI
|
|
0x00,0x00,0x00, //15-17 Calling party extension
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //18-26 Reserved
|
|
0x01, //27 Calling party type identifier
|
|
(byte)(((UInt32)destISSI & 0x00ff0000)>>16), //28 destination ISSI
|
|
(byte)(((UInt32)destISSI & 0x0000ff00)>>8), //29 destination ISSI
|
|
(byte)(((UInt32)destISSI & 0x000000ff)), //30 destination ISSI
|
|
0x00,0x00,0x00, //31-33 Calling party extension
|
|
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, //34-42 Reserved
|
|
0xC3, //43 CM_PROTOCOL (CallOut),
|
|
0x60, //44 flags (SDS type=011 (7-5) | SS (4)| RV (3) | Reserved ( 2-1 )| CSV ( 0 )
|
|
cm_msg_id, //45 message reference
|
|
0x00, //46 Reserved
|
|
0x00, //47 Reserved (7-3)| GS (2)| PDCH (1) | MCCH (0)
|
|
0x00, //48 Reserved (7-1)| RR (0)
|
|
0x00,0x00, //49-50 Region selection
|
|
0x00,0x00 //51-52 Reserved
|
|
};
|
|
return msg;
|
|
}
|
|
|
|
public static byte[] SDTS_TLX_CallOut(UInt16 callOut, UInt32 talkGroup)
|
|
{
|
|
byte[] callOutBytes = BitConverter.GetBytes(callOut);
|
|
byte[] talkGroupBytes = BitConverter.GetBytes(talkGroup);
|
|
|
|
byte[] msg = { 0x00, //01 Header length
|
|
0x11, //02 Header length
|
|
0xFF, //03 Next extension PDU type
|
|
0x00, //04 TL user data length
|
|
0x00, //05 TL user data length
|
|
0x04, //06 PDU type
|
|
0x00, //07 REC | CON | STO | TL forward adress type
|
|
0x00, //08 Validity period
|
|
0x00,0x00,0x00, //09-11 Forward address
|
|
0x00,0x00,0x00,0x00,0x00,0x00, //12-17 Reserved
|
|
(byte)TextEncoding.ISO8859Latin1, //18 TL encoding scheme
|
|
callOutBytes[1], //19 TL call out number + call out severity
|
|
callOutBytes[0], //20 TL call out number + call out severity
|
|
talkGroupBytes[3], //21 TL TG ( ctrl + number )
|
|
talkGroupBytes[2], //22 TL TG ( ctrl + number )
|
|
talkGroupBytes[1], //23 TL TG ( ctrl + number )
|
|
talkGroupBytes[0], //24 TL TG ( ctrl + number )
|
|
0x00, //25 forward address
|
|
0x00, //26 forward address
|
|
0x00 //27 forward address
|
|
};
|
|
|
|
return msg;
|
|
|
|
}
|
|
|
|
private static byte[] Combine(byte[] a, byte[] b)
|
|
{
|
|
byte[] result = new byte[a.Length + b.Length];
|
|
Buffer.BlockCopy(a, 0, result, 0, a.Length);
|
|
Buffer.BlockCopy(b, 0, result, a.Length, b.Length);
|
|
return result;
|
|
}
|
|
|
|
|
|
private static byte[] Combine(byte[] a, byte[] b, byte[] c)
|
|
{
|
|
byte[] result = new byte[a.Length + b.Length + c.Length];
|
|
Buffer.BlockCopy(a, 0, result, 0, a.Length);
|
|
Buffer.BlockCopy(b, 0, result, a.Length, b.Length);
|
|
Buffer.BlockCopy(c, 0, result, a.Length + b.Length, c.Length);
|
|
return result;
|
|
}
|
|
}
|
|
}
|