* Added RS232/RS485 Packet Analyzer (Tools -> Packet Analyzer)
* Updated BMS History register request/response length by model
* Fixed decimal truncation issue in Brazil locale for DB/CSV Log and Excel Export
This commit is contained in:
2026-11-06 15:35:44 +09:00
parent 56e341a48a
commit e041527b56
42 changed files with 5888 additions and 160 deletions

View File

@@ -1,8 +1,9 @@
using LFP_Manager.DataStructure;
using LFP_Manager.DataStructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
@@ -619,11 +620,11 @@ namespace LFP_Manager.Utils
new SQLiteParameter("alarm_status", systemData.StatusData.batteryStatus),
new SQLiteParameter("warning", systemData.StatusData.warning),
new SQLiteParameter("fault", systemData.StatusData.protection),
new SQLiteParameter("module_voltage", (systemData.ValueData.voltageOfPack / 10.0).ToString()),
new SQLiteParameter("module_current", (systemData.ValueData.current / 10.0).ToString()),
new SQLiteParameter("module_soc", (systemData.ValueData.rSOC / 10.0).ToString()),
new SQLiteParameter("module_soh", (systemData.ValueData.stateOfHealth / 10.0).ToString()),
new SQLiteParameter("module_cyclecount", systemData.ValueData.cycleCount.ToString())
new SQLiteParameter("module_voltage", (systemData.ValueData.voltageOfPack / 10.0).ToString(CultureInfo.InvariantCulture)),
new SQLiteParameter("module_current", (systemData.ValueData.current / 10.0).ToString(CultureInfo.InvariantCulture)),
new SQLiteParameter("module_soc", (systemData.ValueData.rSOC / 10.0).ToString(CultureInfo.InvariantCulture)),
new SQLiteParameter("module_soh", (systemData.ValueData.stateOfHealth / 10.0).ToString(CultureInfo.InvariantCulture)),
new SQLiteParameter("module_cyclecount", systemData.ValueData.cycleCount.ToString(CultureInfo.InvariantCulture))
};
// Add cell voltage parameters
@@ -631,7 +632,7 @@ namespace LFP_Manager.Utils
{
parameters.Add(new SQLiteParameter(
string.Format("cell_voltage_{0:00}", i + 1),
(systemData.ValueData.CellVoltage[i] / (float)cvUnit).ToString()));
(systemData.ValueData.CellVoltage[i] / (float)cvUnit).ToString(CultureInfo.InvariantCulture)));
}
// Add temperature parameters
@@ -639,12 +640,12 @@ namespace LFP_Manager.Utils
{
parameters.Add(new SQLiteParameter(
string.Format("temperature_{0:00}", i + 1),
(systemData.ValueData.CellTemperature[i] / 10.0).ToString()));
(systemData.ValueData.CellTemperature[i] / 10.0).ToString(CultureInfo.InvariantCulture)));
}
parameters.Add(new SQLiteParameter("ext1_temp", (systemData.ValueData.Ext1Temperature / 10.0).ToString()));
parameters.Add(new SQLiteParameter("ext2_temp", (systemData.ValueData.Ext2Temperature / 10.0).ToString()));
parameters.Add(new SQLiteParameter("chg_option", systemData.CalibrationData.ChaMode.Mode.ToString()));
parameters.Add(new SQLiteParameter("ext1_temp", (systemData.ValueData.Ext1Temperature / 10.0).ToString(CultureInfo.InvariantCulture)));
parameters.Add(new SQLiteParameter("ext2_temp", (systemData.ValueData.Ext2Temperature / 10.0).ToString(CultureInfo.InvariantCulture)));
parameters.Add(new SQLiteParameter("chg_option", systemData.CalibrationData.ChaMode.Mode.ToString(CultureInfo.InvariantCulture)));
return parameters.ToArray();
}
@@ -1071,6 +1072,7 @@ namespace LFP_Manager.Utils
{
connection.Open();
BeginTran(connection);
csDbUtils.RepairCommaDecimalsIfNeeded(connection);
// Insert data
using (SQLiteCommand command = connection.CreateCommand())
@@ -1303,6 +1305,7 @@ namespace LFP_Manager.Utils
{
connection.Open();
BeginTran(connection);
csDbUtils.RepairCommaDecimalsIfNeeded(connection);
// Insert data
using (SQLiteCommand command = connection.CreateCommand())

View File

@@ -1,7 +1,9 @@
using LFP_Manager.DataStructure;
using LFP_Manager.DataStructure;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SQLite;
using System.Globalization;
using System.IO;
using System.Text;
using System.Windows.Forms;
@@ -564,24 +566,24 @@ namespace LFP_Manager.Utils
p[j++].Value = aSystemData.StatusData.batteryStatus; // 7 alarm_status
p[j++].Value = aSystemData.StatusData.warning; // 8 warning
p[j++].Value = aSystemData.StatusData.protection; // 9 fault
p[j++].Value = ((float)aSystemData.ValueData.voltageOfPack / 10).ToString(); // 10 module_voltage
p[j++].Value = ((float)aSystemData.ValueData.current / 10).ToString(); // 11 module_current
p[j++].Value = ((float)aSystemData.ValueData.rSOC / 10).ToString(); // 12 module_soc
p[j++].Value = ((float)aSystemData.ValueData.stateOfHealth / 10).ToString(); // 13 module_soh
p[j++].Value = ((float)aSystemData.ValueData.cycleCount / 1).ToString(); // 14 module_soh
p[j++].Value = ((float)aSystemData.ValueData.voltageOfPack / 10).ToString(CultureInfo.InvariantCulture); // 10 module_voltage
p[j++].Value = ((float)aSystemData.ValueData.current / 10).ToString(CultureInfo.InvariantCulture); // 11 module_current
p[j++].Value = ((float)aSystemData.ValueData.rSOC / 10).ToString(CultureInfo.InvariantCulture); // 12 module_soc
p[j++].Value = ((float)aSystemData.ValueData.stateOfHealth / 10).ToString(CultureInfo.InvariantCulture); // 13 module_soh
p[j++].Value = ((float)aSystemData.ValueData.cycleCount / 1).ToString(CultureInfo.InvariantCulture); // 14 module_soh
for (int i = 0; i < aSystemData.cellQty; i++)
{
p[j++].Value = ((float)aSystemData.ValueData.CellVoltage[i] / cvUnit).ToString(); // 15 cell_voltage_01
p[j++].Value = ((float)aSystemData.ValueData.CellVoltage[i] / cvUnit).ToString(CultureInfo.InvariantCulture); // 15 cell_voltage_01
}
for (int i = 0; i < aSystemData.tempQty; i++)
{
p[j++].Value = ((float)aSystemData.ValueData.CellTemperature[i] / 10).ToString(); // 30 temperature_01
p[j++].Value = ((float)aSystemData.ValueData.CellTemperature[i] / 10).ToString(CultureInfo.InvariantCulture); // 30 temperature_01
}
p[j++].Value = ((float)aSystemData.ValueData.Ext1Temperature / 10).ToString(); // 34 temperature_ext1 - FET Temp
p[j++].Value = ((float)aSystemData.ValueData.Ext2Temperature / 10).ToString(); // 35 temperature_ext2 - Lmt Temp
p[j++].Value = ((float)aSystemData.ValueData.Ext1Temperature / 10).ToString(CultureInfo.InvariantCulture); // 34 temperature_ext1 - FET Temp
p[j++].Value = ((float)aSystemData.ValueData.Ext2Temperature / 10).ToString(CultureInfo.InvariantCulture); // 35 temperature_ext2 - Lmt Temp
p[j++].Value = aSystemData.CalibrationData.ChaMode.Mode.ToString(); // 36 chg_option
p[j++].Value = aSystemData.CalibrationData.ChaMode.Mode.ToString(CultureInfo.InvariantCulture); // 36 chg_option
command.ExecuteNonQuery();
@@ -1011,6 +1013,57 @@ namespace LFP_Manager.Utils
#region SELECT QUARY
public static void RepairCommaDecimalsIfNeeded(SQLiteConnection connection)
{
try
{
bool hasCommaText = false;
using (SQLiteCommand checkCmd = connection.CreateCommand())
{
checkCmd.CommandText = "SELECT 1 FROM TModuleValue WHERE typeof(module_voltage) = 'text' OR typeof(cell_voltage_01) = 'text' LIMIT 1";
object res = checkCmd.ExecuteScalar();
hasCommaText = (res != null && res != DBNull.Value);
}
if (!hasCommaText) return;
List<string> numCols = new List<string>();
using (SQLiteCommand pragmaCmd = connection.CreateCommand())
{
pragmaCmd.CommandText = "PRAGMA table_info(TModuleValue);";
using (SQLiteDataReader reader = pragmaCmd.ExecuteReader())
{
while (reader.Read())
{
string colName = Convert.ToString(reader["name"]);
string colType = Convert.ToString(reader["type"]).ToUpperInvariant();
if (colType.Contains("NUMERIC") || colType.Contains("REAL") || colType.Contains("DOUBLE") || colType.Contains("FLOAT") || colType.Contains("DECIMAL"))
{
numCols.Add(colName);
}
}
}
}
if (numCols.Count == 0) return;
List<string> setClauses = new List<string>(numCols.Count);
foreach (string col in numCols)
{
setClauses.Add(string.Format("{0} = CASE WHEN typeof({0}) = 'text' THEN CAST(REPLACE({0}, ',', '.') AS NUMERIC) ELSE {0} END", col));
}
using (SQLiteCommand updateCmd = connection.CreateCommand())
{
updateCmd.CommandText = "UPDATE TModuleValue SET " + string.Join(", ", setClauses.ToArray());
updateCmd.ExecuteNonQuery();
}
}
catch
{
}
}
public static int DbQuaryExcuteToDataTable(string dbFileName, string Quary, ref DataTable rDT)
{
int result = 0;
@@ -1023,6 +1076,7 @@ namespace LFP_Manager.Utils
{
connection.Open();
BeginTran(connection);
RepairCommaDecimalsIfNeeded(connection);
// Insert data
using (SQLiteCommand command = connection.CreateCommand())
@@ -1255,6 +1309,7 @@ namespace LFP_Manager.Utils
{
connection.Open();
BeginTran(connection);
RepairCommaDecimalsIfNeeded(connection);
// Insert data
using (SQLiteCommand command = connection.CreateCommand())

View File

@@ -1,5 +1,6 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
using System.IO;
@@ -399,10 +400,10 @@ namespace LFP_Manager.Utils
, GetCommStatus(tData) // 3 COMM STATUS
, GetStatusString(tData.StatusData.status) // 4 STATUS
, GetAlarmString(tData.StatusData.batteryStatus) // 5 ALARM
, String.Format("{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalVoltage) / 10) // 6 voltageOfPack
, String.Format("{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalCurrent) / 10) // 7 current
, String.Format("{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalSOC) / 10) // 8 SOC
, String.Format("{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalTemp) / 10) // 9 Max Temperature
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalVoltage) / 10) // 6 voltageOfPack
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalCurrent) / 10) // 7 current
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalSOC) / 10) // 8 SOC
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(tData.ValueData.TotalTemp) / 10) // 9 Max Temperature
);
sdata += "\r\n";
@@ -428,27 +429,27 @@ namespace LFP_Manager.Utils
, GetCommStatus(sConfig, sData) // 5 COMM STATUS
, GetStatusString(sData.StatusData.status) // 6 STATUS
, GetAlarmString(sData.StatusData.batteryStatus) // 7 ALARM
, String.Format("{0:#0.0}", Convert.ToDouble(sData.ValueData.voltageOfPack) / 10) // 8 voltageOfPack
, String.Format("{0:#0.0}", Convert.ToDouble(sData.ValueData.current) / 10) // 9 current
, String.Format("{0:#0.0}", Convert.ToDouble(sData.ValueData.rSOC) / 10) // 10 SOC
, String.Format("{0:#0.0}", Convert.ToDouble(sData.ValueData.stateOfHealth) / 10) // 11 SOH
, String.Format("{0}", Convert.ToDouble(sData.ValueData.cycleCount) / 1) // 12 Cycle Count
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(sData.ValueData.voltageOfPack) / 10) // 8 voltageOfPack
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(sData.ValueData.current) / 10) // 9 current
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(sData.ValueData.rSOC) / 10) // 10 SOC
, String.Format(CultureInfo.InvariantCulture, "{0:#0.0}", Convert.ToDouble(sData.ValueData.stateOfHealth) / 10) // 11 SOH
, String.Format(CultureInfo.InvariantCulture, "{0}", Convert.ToDouble(sData.ValueData.cycleCount) / 1) // 12 Cycle Count
);
sdata += String.Format("{0:#0.000},", Convert.ToDouble(sData.AvgData.diffCellVoltage) / 1000); // 13 Cell Voltage Diff
sdata += String.Format(CultureInfo.InvariantCulture, "{0:#0.000},", Convert.ToDouble(sData.AvgData.diffCellVoltage) / 1000); // 13 Cell Voltage Diff
for (int i = 0; i < sData.cellQty; i++)
{
sdata += String.Format("{0:#0.000},", Convert.ToDouble(sData.ValueData.CellVoltage[i]) / 1000); // 14 - 28 Cell Voltage n
sdata += String.Format(CultureInfo.InvariantCulture, "{0:#0.000},", Convert.ToDouble(sData.ValueData.CellVoltage[i]) / 1000); // 14 - 28 Cell Voltage n
}
sdata += String.Format("{0:#0.0},", Convert.ToDouble(sData.AvgData.diffTemp) / 10); // 29 Temperature Diff
sdata += String.Format(CultureInfo.InvariantCulture, "{0:#0.0},", Convert.ToDouble(sData.AvgData.diffTemp) / 10); // 29 Temperature Diff
for (int i = 0; i < sData.tempQty; i++)
{
sdata += String.Format("{0:#0.0},", Convert.ToDouble(sData.ValueData.CellTemperature[i]) / 10); // 30 - 33 Cell Temperature n
sdata += String.Format(CultureInfo.InvariantCulture, "{0:#0.0},", Convert.ToDouble(sData.ValueData.CellTemperature[i]) / 10); // 30 - 33 Cell Temperature n
}
sdata += String.Format("{0:#0.0},", Convert.ToDouble(sData.ValueData.Ext1Temperature) / 10); // 34 Ext1 Temperature n
sdata += String.Format("{0:#0.0},", Convert.ToDouble(sData.ValueData.Ext2Temperature) / 10); // 35 Ext2 Temperature n
sdata += String.Format(CultureInfo.InvariantCulture, "{0:#0.0},", Convert.ToDouble(sData.ValueData.Ext1Temperature) / 10); // 34 Ext1 Temperature n
sdata += String.Format(CultureInfo.InvariantCulture, "{0:#0.0},", Convert.ToDouble(sData.ValueData.Ext2Temperature) / 10); // 35 Ext2 Temperature n
sdata += String.Format(
"{0},{1},{2},"

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
@@ -392,30 +392,46 @@ namespace LFP_Manager.Utils
{
int Max, Avg, Min, Sum;
int MaxNo, MinNo;
int validCount = 0;
Max = Avg = Min = Sum = 0;
Max = Min = Sum = 0;
MaxNo = MinNo = 0;
for (int i = 0; i < tempQty; i++)
{
if (i == 0)
{
Max = Min = rSystemData.ValueData.CellTemperature[i];
}
Sum += rSystemData.ValueData.CellTemperature[i];
short tempVal = rSystemData.ValueData.CellTemperature[i];
if (tempVal == 0) continue; // 미연결 및 초기 0도 제외
if (Max < rSystemData.ValueData.CellTemperature[i])
if (validCount == 0)
{
Max = rSystemData.ValueData.CellTemperature[i];
Max = Min = tempVal;
MaxNo = MinNo = i;
}
Sum += tempVal;
validCount++;
if (Max < tempVal)
{
Max = tempVal;
MaxNo = i;
}
if (Min > rSystemData.ValueData.CellTemperature[i])
if (Min > tempVal)
{
Min = rSystemData.ValueData.CellTemperature[i];
Min = tempVal;
MinNo = i;
}
}
Avg = Sum / tempQty;
if (validCount == 0)
{
Avg = 0;
Min = 0;
Max = 0;
}
else
{
Avg = Sum / validCount;
}
rSystemData.AvgData.avgTemp = (short)Avg;
rSystemData.AvgData.maxTemp = (short)Max;