SafeDispatch/LibrarySDR/Requests/SimpleTextSDSRequest.cs
2024-02-22 18:43:59 +02:00

289 lines
10 KiB
C#

using LibrarySDR.Enums;
using LibrarySDR.Flags;
using System;
using System.Globalization;
using System.Text;
using static LibrarySDR.Helpers.BinaryHexHelper;
namespace LibrarySDR.Requests
{
public class SimpleTextSDSRequest
{
private static PDUType PduType = PDUType.DATA_REQ_RESP;
private static ProtocolIdentifier protocolIdentifier = ProtocolIdentifier.SimpleTextWithoutSDSTL;
private Int64 sourceISSI;
public Int64 SourceISSI { get { return sourceISSI; } }
private Int64 destinationISSI;
public Int64 DestinationISSI { get { return destinationISSI; } }
private ProtocolIdentifier pi;
public ProtocolIdentifier ProtocolIdentifier { get { return pi; } }
private Int16 messageReference;
public Int16 MessageRefence { get { return messageReference; } }
private Int16 areaSelection;
public Int16 AreaSelection { get { return areaSelection; } }
private Int16 validityPeriod;
public Int16 ValidityPeriod { get { return validityPeriod; } }
private Int64 forwardAddress;
public Int64 ForwardAddress { get { return forwardAddress; } }
private Int16 flags;
public Int16 Flags { get { return flags; } }
private DataFlag dataFlag;
public DataFlag DataFlags { get { return dataFlag; } }
private Int16 lengthBits;
public Int16 LengthBits { get { return lengthBits; } }
private Int16 lengthBytes;
public Int16 LengthBytes { get { return lengthBytes; } }
private Int16 textEncoding;
public Int16 TextEncoding { get { return textEncoding; } }
private String message;
public String Message { get { return message; } }
private String hexMessage;
public String HexMessage { get { return hexMessage; } }
private static Int64 transactionId = 1;
public static Int64 TransactionId
{
get
{
return transactionId++;
}
}
public static Int32 EncodingType = 26;
public SimpleTextSDSRequest(string hexSimpleTextSDSReceived)
{
String resp = hexSimpleTextSDSReceived;
int i = 0;
int prevIdx = 0;
// get source SSI (32 bits = 4 byte = 8 hex characters)
String hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 4*2));
Int64.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out sourceISSI);
// get destination SSI (32 bits = 4 byte = 8 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 4*2));
Int64.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out destinationISSI);
// get protocol identifier (8 bits = 1 byte = 2 hex characters)
Int16 pi = 0;
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 2));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out pi);
this.pi = (ProtocolIdentifier)pi;
// get message reference (8 bits = 1 byte = 2 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 2));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out messageReference);
// return if no more data to parse
if (resp.Length < i + 1 * 2)
return;
// get area selection (8 bits = 1 byte = 2 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 2));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out areaSelection);
// return if no more data to parse
if (resp.Length < i + 1 * 2)
return;
// get validity period (8 bits = 1 byte = 2 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 2));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out validityPeriod);
// return if no more data to parse
if (resp.Length < i + 4 * 2)
return;
// get forward address (32 bits = 4 byte = 8 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 4 * 2));
Int64.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out forwardAddress);
// get flags (8 bits = 1 byte = 2 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 2));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out flags);
// parse the data flag
dataFlag = new DataFlag(flags);
// get length bits (16 bits = 2 byte = 4 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 4));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out lengthBits);
// get length bytes (16 bits = 2 byte = 4 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 4));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out lengthBytes);
if (ProtocolIdentifier != ProtocolIdentifier.GPS && ProtocolIdentifier != ProtocolIdentifier.GPSUsingSDSTL
&& ProtocolIdentifier != ProtocolIdentifier.SimpleGPSWithoutSDSTL)
{
// get encoding (8 bits = 1 byte = 2 hex characters)
hex = LittleToBigEndianHexString(resp.Substring(i = i + prevIdx, prevIdx = 2));
Int16.TryParse(hex, NumberStyles.HexNumber, CultureInfo.InvariantCulture, out textEncoding);
}
hexMessage = resp.Substring(i = i + prevIdx); // LittleToBigEndianHexString(resp.Substring(i = i + prevIdx));
// arrabic unicode
if (textEncoding == 26)
{
// convert the message to big endian
//hexMessage = LittleToBigEndianHexString(hexMessage);
// get the unicode for the hex message
String message2 = "";
int j = 0;
while(j < hexMessage.Length)
{
String hexChar = hexMessage.Substring(j, 4);
Int64 hexCharVal = Int64.Parse(hexChar, NumberStyles.HexNumber);
//Encoding.Unicode.GetString(hexCharVal);
message2 += HexToUnicode(hexChar);
j = j + 4;
}
message = Encoding.Unicode.GetString(StringToByteArray(hexMessage)); // For UTF-16
message = message2;
}
else
{
for (int w = 0; w < hexMessage.Length / 2; w++)
message += (char)Convert.ToInt16(hexMessage.Substring(w * 2, 2), 16);
}
}
public static char HexToUnicode(string hex)
{
byte[] bytes = HexToBytes(hex);
char c;
if (bytes.Length == 1)
{
c = (char)bytes[0];
}
else if (bytes.Length == 2)
{
c = (char)((bytes[0] << 8) + bytes[1]);
}
else
{
throw new Exception(hex);
}
return c;
}
public static byte[] HexToBytes(string hex)
{
hex = hex.Trim();
byte[] bytes = new byte[hex.Length / 2];
for (int index = 0; index < bytes.Length; index++)
{
bytes[index] = byte.Parse(hex.Substring(index * 2, 2), NumberStyles.HexNumber);
}
return bytes;
}
public static String GetInstance(Int64 sourceISSI, Int64 destinationISSI, String text)
{
StringBuilder sb = new StringBuilder("");
// PDU Type (8 bits)
sb.Append(GetBits((int)PduType, 8));
// Source ISSI (32 bits)
sb.Append(GetBits(sourceISSI, 32));
// Destination ISSI (32 bits)
sb.Append(GetBits(destinationISSI, 32));
// Protocol Identifier (8 bits)
sb.Append(GetBits((int)protocolIdentifier, 8));
// Message reference (8 bits) - ignored for Simple Text)
sb.Append(GetBits(0x00, 8));
// Area selection (8 bits) - unused
sb.Append(GetBits(0x00, 8));
// Validity period (8 bits) - unused
sb.Append(GetBits(0x00, 8));
// Forward Address (32 bits) - ignored for Simple Text
sb.Append(GetBits(0x00, 32));
// Flags (8 bits) - ignored for Simple Text
sb.Append(GetBits(0x00, 8));
// Length in bites (16 bits) + the encoding one
sb.Append(GetBits((text.Length + 1) * 8, 16));
// Length in bytes (16 bits) + the encoding one
sb.Append(GetBits(text.Length + 1, 16));
// Encoding (8 bits) - Latin-1
sb.Append(GetBits(EncodingType, 8));
// Text message
sb.Append(GetBits(text, Encoding.Unicode));
// Transaction Id
sb.Append(GetBits(TransactionId, 32));
// Gw Report
sb.Append(GetBits(0x01, 8));
// get the header with the length
String header = Header.GetHeaderBinary(sb.ToString().Length / 8);
// add header in front of the request
return BinaryStringToHexString($"{header}{sb.ToString()}", Padding.RIGHT);
}
public static byte[] GetBytes(Int64 sourceISSI, Int64 destinationISSI, String text)
{
String res = GetInstance(sourceISSI, destinationISSI, text);
byte[] response = new byte[res.Length / 2];
for (int i = 0; i < res.Length / 2; i++)
response[i] = (byte)Convert.ToInt16(res.Substring(i * 2, 2), 16);
return response;
}
}
}