Innovenergy_trunk/csharp/Lib/Devices/BatteryDeligreen/TelecommandFrameParser.cs

146 lines
5.0 KiB
C#

using System.Globalization;
namespace InnovEnergy.Lib.Devices.BatteryDeligreen;
using System;
using System.Collections.Generic;
public class TelecommandFrameParser
{
private static Int32 _currentIndex;
private const Int32 FrameLength = 232;
public Boolean ParsingTelecommandFrame(String response)
{
_currentIndex = 0; // Reset currentIndex to the start
if (string.IsNullOrEmpty(response) || response.Length < FrameLength)
{
Console.WriteLine("Response is too short to contain valid data.");
Console.WriteLine(" Fixed Length" + FrameLength);
Console.WriteLine(" response Length" + response.Length);
return false;
}
// Check starting byte
string startingByte = response.Substring(_currentIndex, 2).ToUpper();
if (startingByte == "7E")
{
// Console.WriteLine($"Starting byte: {startingByte} (Hex)");
}
else
{
Console.WriteLine($"Incorrect starting byte: {startingByte}");
return false;
}
_currentIndex += 2;
// Extract firmware version
var versionBytes = response.Substring(_currentIndex, 4);
try
{
var versionAscii = HexToAscii(versionBytes);
// Console.WriteLine($"Firmware version: {versionBytes} (Hex), ASCII: {versionAscii}");
}
catch (Exception)
{
Console.WriteLine($"Failed to decode firmware version from bytes: {versionBytes}");
return false;
}
_currentIndex += 4;
// Extract and parse other fields
ParseAndPrintHexField(response, "Device Address", 4);
ParseAndPrintHexField(response, "Device Code (CID1)", 4);
ParseAndPrintHexField(response, "Function Code", 4);
ParseAndPrintHexField(response, "Length Code", 8);
ParseAndPrintHexField(response, "Data Flag", 4);
ParseAndPrintHexField(response, "Command Group", 4);
ParseAndPrintHexField(response, "Number of Cells", 4);
ExtractCellAlarm(response);
return true;
}
private static void ExtractCellAlarm(String response)
{
Dictionary<string, string> byteAlarmCodes = new Dictionary<string, string>
{
{ "00", "Normal, no alarm" },
{ "01", "Alarm that analog quantity reaches the lower limit" },
{ "02", "Alarm that analog quantity reaches the upper limit" },
{ "F0", "Other alarms" }
};
// Process Alarms for all 16 cells
for (var i = 0; i < 16; i++)
{
var cellAlarm = response.Substring(_currentIndex, 4);
try
{
var alarmAscii = HexToAscii(cellAlarm);
var cellVoltageDecimal = HexToDecimal(alarmAscii);
string alarmMessage = byteAlarmCodes.ContainsKey(alarmAscii) ? byteAlarmCodes[alarmAscii] : "Unknown alarm code";
// Console.WriteLine($"Cell {i + 1}: Alarm Code {cellAlarm}, Status: {alarmMessage}");
}
catch (Exception)
{
Console.WriteLine($"Failed to decode Voltage of Cell {i + 1} from bytes: {cellAlarm}");
}
_currentIndex += 4;
}
}
private static void ParseAndPrintHexField(String response, String fieldName, int length)
{
var hexBytes = response.Substring(_currentIndex, length);
try
{
var asciiValue = HexToAscii(hexBytes);
var decimalValue = int.Parse(asciiValue, NumberStyles.HexNumber);
// Console.WriteLine($"{fieldName}: {hexBytes} (Hex), ASCII: {asciiValue}, Decimal: {decimalValue}");
}
catch (Exception)
{
Console.WriteLine($"Failed to decode {fieldName} from bytes: {hexBytes}");
}
_currentIndex += length;
}
private static void ParseAndPrintField(String response, String fieldName, Int32 length, Func<Double, Double> conversion, String unit)
{
var fieldBytes = response.Substring(_currentIndex, length);
try
{
var fieldAscii = HexToAscii(fieldBytes);
var fieldDecimal = conversion(HexToDecimal(fieldAscii));
Console.WriteLine($"{fieldName}: {fieldBytes} (Hex), ASCII: {fieldAscii}, {fieldName}: {fieldDecimal:F3} {unit}");
}
catch (Exception)
{
Console.WriteLine($"Failed to decode {fieldName} from bytes: {fieldBytes}");
}
_currentIndex += length;
}
private static String HexToAscii(String hex)
{
var bytes = new Byte[hex.Length / 2];
for (var i = 0; i < hex.Length; i += 2)
{
bytes[i / 2] = byte.Parse(hex.Substring(i, 2), NumberStyles.HexNumber);
}
return System.Text.Encoding.ASCII.GetString(bytes);
}
private static double HexToDecimal(String hex)
{
return int.Parse(hex, NumberStyles.HexNumber);
}
}