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

160 lines
6.1 KiB
C#

using System.Globalization;
namespace InnovEnergy.Lib.Devices.BatteryDeligreen;
public class TelemetryFrameParser
{
private static Int32 _currentIndex;
private const Int32 FrameLenght = 286;
public void ParsingTelemetryFrame(String response)
{
_currentIndex = 0; // Reset currentIndex to the start
if (string.IsNullOrEmpty(response) || response.Length < FrameLenght)
{
Console.WriteLine("Response is too short to contain valid data.");
return;
}
// 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;
}
_currentIndex += 2;
// Extract firmware version
var versionBytes = response.Substring(_currentIndex, 4);
try
{
String versionAscii = HexToAscii(versionBytes);
Console.WriteLine($"Firmware version: {versionBytes} (Hex), ASCII: {versionAscii}");
}
catch (Exception)
{
Console.WriteLine($"Failed to decode firmware version from bytes: {versionBytes}");
return;
}
_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);
// Process voltages for all 16 cells
for (var i = 0; i < 16; i++)
{
String cellVoltageBytes = response.Substring(_currentIndex, 8);
try
{
var cellVoltageAscii = HexToAscii(cellVoltageBytes);
var cellVoltageDecimal = HexToDecimal(cellVoltageAscii) / 1000.0; // cell voltage are divided 1000
Console.WriteLine($"Voltage of Cell {i + 1}: {cellVoltageBytes} (Hex), ASCII: {cellVoltageAscii}, Voltage: {cellVoltageDecimal:F3} V");
}
catch (Exception)
{
Console.WriteLine($"Failed to decode Voltage of Cell {i + 1} from bytes: {cellVoltageBytes}");
}
_currentIndex += 8;
}
// Parse other fields
ParseAndPrintHexField(response, "Number of Temperature Sensors", 4);
// Parse cell temperatures
for (var i = 1; i <= 4; i++)
{
ParseAndPrintTemperatureField(response, $"Cell Temperature {i}");
}
// Parse other temperature and battery information
ParseAndPrintTemperatureField(response, "Environment Temperature");
ParseAndPrintTemperatureField(response, "Power Temperature");
ParseAndPrintField(response, "Charge/Discharge Current", 8, value => value / 100.0, "A");
ParseAndPrintField(response, "Total Battery Voltage", 8, value => value / 100.0, "V");
ParseAndPrintField(response, "Residual Capacity", 8, value => value / 100.0, "Ah");
ParseAndPrintHexField(response, "Custom Number", 4);
ParseAndPrintField(response, "Battery Capacity", 8, value => value / 100.0, "Ah");
ParseAndPrintField(response, "SOC", 8, value => value / 10.0, "%");
ParseAndPrintField(response, "Rated Capacity", 8, value => value / 100.0, "Ah");
ParseAndPrintHexField(response, "Number of Cycles", 8);
ParseAndPrintField(response, "SOH", 8, value => value / 10.0, "%");
ParseAndPrintField(response, "Bus Voltage", 8, value => value / 100.0, "V");
}
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 ParseAndPrintTemperatureField(String response, String fieldName)
{
var tempBytes = response.Substring(_currentIndex, 8);
try
{
var tempAscii = HexToAscii(tempBytes);
var tempDecimal = (HexToDecimal(tempAscii) - 2731) / 10.0;
Console.WriteLine($"{fieldName}: {tempBytes} (Hex), ASCII: {tempAscii}, Temperature: {tempDecimal:F2} °C");
}
catch (Exception)
{
Console.WriteLine($"Failed to decode {fieldName} from bytes: {tempBytes}");
}
_currentIndex += 8;
}
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);
}
}