SafeDispatch/ServiceGatewaySDR/CallOutClass.cs
2024-02-22 18:43:59 +02:00

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;
}
}
}