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