This commit is contained in:
ChiKyun Kim
2025-12-04 17:10:42 +09:00
parent 34ad1db0e3
commit 8459230053
13 changed files with 540 additions and 1121 deletions

View File

@@ -1,12 +0,0 @@
*.suo
*.user
*.pdb
bin
obj
desktop.ini
.vs
.git
packages
*.patch
/Project/SourceSetup.exe
*.zip

View File

@@ -1,424 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.CodeDom;
namespace arDev
{
public class BMS : arRS232
{
public BMS()
{
MinRecvLength = 34;
}
/// <summary>
/// 시리얼포트의 핀 상태값이 변경될 때 발생합니다.
/// </summary>
public event EventHandler<BMSInformationEventArgs> BMSDataReceive;
public event EventHandler<BMSCelvoltageEventArgs> BMSCellDataReceive;
protected override bool CustomParser(byte[] buf, out byte[] remainBuffer)
{
List<byte> remain = new List<byte>();
//데이터는 총 34byt 이며 , DD~77로 구성됨
Boolean bComplete = false;
for (int i = 0; i < buf.Length; i++)
{
var incomByte = buf[i];
if (bComplete == true)
{
remain.Add(incomByte);
}
else
{
if (findSTX == false)
{
if (incomByte != 0xDD)
{
//버리는데이터
}
else
{
findSTX = true;
tempBuffer.Clear();
tempBuffer.Add(incomByte);
}
}
else
{
tempBuffer.Add(incomByte);
var queylen = QueryIndex == 0 ? 34 : 23;
if (tempBuffer.Count == queylen)
{
if (incomByte != 0x77)
{
//종단기호가 맞지 않다. 이자료는 폐기한다.
tempBuffer.Clear();
}
else
{
//데이터가 맞게 수신됨
LastReceiveBuffer = tempBuffer.ToArray();
bComplete = true;
}
findSTX = false;
}
else
{
//아직 모자르므로 대기한다
}
}
}
}
remainBuffer = remain.ToArray();
return bComplete;
}
bool Recv0 = false;
bool Recv1 = false;
public event EventHandler<ChargetDetectArgs> ChargeDetect;
public override bool ProcessRecvData(byte[] data)
{
//LastReceiveBuffer
if (data == null)
{
RaiseMessage(MessageType.Error, "수신 데이터가 없습니다");
return false;
}
var datalne = QueryIndex == 0 ? 34 : 23;
if (data.Length != datalne)
{
RaiseMessage(MessageType.Error, $"데이터의 길이가 {MinRecvLength}가 아닙니다 길이={data.Length}");
return false;
}
if (QueryIndex == 0)
{
return ParseBMSInfo();
}
else
{
return ParseBMSCellVoltage();
}
}
bool ParseBMSCellVoltage()
{
//var i = 0;
var BatteryCell_Checksum = 0xffff;// - (LastReceiveBuffer[i + 3] + LastReceiveBuffer[i + 4] + LastReceiveBuffer[i + 5] + LastReceiveBuffer[i + 6] + LastReceiveBuffer[i + 7] + LastReceiveBuffer[i + 8] + LastReceiveBuffer[i + 9] + LastReceiveBuffer[i + 10] + LastReceiveBuffer[i + 11] + LastReceiveBuffer[i + 12] + LastReceiveBuffer[i + 13] + LastReceiveBuffer[i + 14] + LastReceiveBuffer[i + 15] + LastReceiveBuffer[i + 16] + LastReceiveBuffer[i + 17] + LastReceiveBuffer[i + 18] + LastReceiveBuffer[i + 19])) + 1;
for (int i = 3; i < 20; i++)
{
BatteryCell_Checksum -= LastReceiveBuffer[i];// + LastReceiveBuffer[i + 4] + LastReceiveBuffer[i + 5] + LastReceiveBuffer[i + 6] + LastReceiveBuffer[i + 7] + LastReceiveBuffer[i + 8] + LastReceiveBuffer[i + 9] + LastReceiveBuffer[i + 10] + LastReceiveBuffer[i + 11] + LastReceiveBuffer[i + 12] + LastReceiveBuffer[i + 13] + LastReceiveBuffer[i + 14] + LastReceiveBuffer[i + 15] + LastReceiveBuffer[i + 16] + LastReceiveBuffer[i + 17] + LastReceiveBuffer[i + 18] + LastReceiveBuffer[i + 19])) + 1;
}
BatteryCell_Checksum += 1;
var recvchecksum = BitConverter.ToUInt16(LastReceiveBuffer.Skip(20).Take(2).Reverse().ToArray(), 0);
if (recvchecksum == BatteryCell_Checksum)
{
var v1 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(4).Take(2).Reverse().ToArray(), 0) / 1000.0;
var v2 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(6).Take(2).Reverse().ToArray(), 0) / 1000.0;
var v3 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(8).Take(2).Reverse().ToArray(), 0) / 1000.0;
var v4 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(10).Take(2).Reverse().ToArray(), 0) / 1000.0;
var v5 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(12).Take(2).Reverse().ToArray(), 0) / 1000.0;
var v6 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(14).Take(2).Reverse().ToArray(), 0) / 1000.0;
var v7 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(16).Take(2).Reverse().ToArray(), 0) / 1000.0;
var v8 = BitConverter.ToUInt16(LastReceiveBuffer.Skip(18).Take(2).Reverse().ToArray(), 0) / 1000.0;
var idx = 0;
CellVoltage[idx++] = v1;
CellVoltage[idx++] = v2;
CellVoltage[idx++] = v3;
CellVoltage[idx++] = v4;
CellVoltage[idx++] = v5;
CellVoltage[idx++] = v6;
CellVoltage[idx++] = v7;
CellVoltage[idx++] = v8;
Recv1 = true;
try
{
BMSCellDataReceive?.Invoke(this, new BMSCelvoltageEventArgs(v1, v2, v3, v4, v5, v6, v7, v8));
Current_CellTime = DateTime.Now;
return true;
}
catch (Exception ex)
{
RaiseMessage(MessageType.Error, ex.Message);
return false;
}
}
else return false;
}
bool ParseBMSInfo()
{
//전압확인
UInt16 batH = (UInt16)LastReceiveBuffer[4];
UInt16 batL = (UInt16)LastReceiveBuffer[5];
batH = (UInt16)(batH << 8);
batH = (UInt16)(batH | batL);
Current_Volt = (float)(batH / 100.0);
//잔량확인
batH = (UInt16)LastReceiveBuffer[8];
batL = (UInt16)LastReceiveBuffer[9];
batH = (UInt16)(batH << 8);
batH = (UInt16)(batH | batL);
var newamp = (int)batH;
var Changed = newamp != Current_Amp;
Current_Amp = newamp;
//총량확인
batH = (UInt16)LastReceiveBuffer[10];
batL = (UInt16)LastReceiveBuffer[11];
batH = (UInt16)(batH << 8);
batH = (UInt16)(batH | batL);
Current_MaxAmp = (int)batH;
//남은 % 계산
float levraw = (float)(Current_Amp / (Current_MaxAmp * 1.0));
Current_Level = (float)(levraw * 100.0);// (float)(map(remain, 0, total, 0, 100));
Current_LevelA = LastReceiveBuffer[23]; //<- 23번자료는 byte이므로 소수점이잇는 데이터로 직접 계산한다
//250620 jwlee 추가
int temp1 = (LastReceiveBuffer[27] << 8) | LastReceiveBuffer[28];
int temp2 = (LastReceiveBuffer[29] << 8) | LastReceiveBuffer[30];
Current_temp1 = (temp1 - 2731) / 10f;
Current_temp2 = (temp2 - 2731) / 10f;
CheckManualCharge();
Recv0 = true;
try
{
BMSDataReceive?.Invoke(this, new BMSInformationEventArgs(Current_Volt, Current_Amp, Current_MaxAmp, Current_Level, Changed));
Current_DataTime = DateTime.Now;
return true;
}
catch (Exception ex)
{
RaiseMessage(MessageType.Error, ex.Message);
return false;
}
}
private bool _autocharge = false;
public Boolean AutoCharge
{
get { return _autocharge; }
set { _autocharge = false; }
}
//public void ClearManualChargeCheckValue()
//{
// chk_timee = new DateTime(1982, 11, 23);
// chk_times = new DateTime(1982, 11, 23);
// chk_valuee = 0f;
// chk_values = 0f;
//}
void CheckManualCharge()
{
if (AutoCharge)
{
if (chk_timee.Year != 1982)
{
chk_timee = new DateTime(1982, 11, 23);
chk_valuee = 999f;
}
if (chk_times.Year != 1982)
{
chk_times = new DateTime(1982, 11, 23);
chk_values = 999f;
}
}
if (chk_times.Year == 1982)
{
chk_times = DateTime.Now;
chk_values = Current_Level;
}
else
{
if (chk_timee.Year == 1982)
{
if ((Current_Level - chk_values) >= 0.1)
{
//충전중이다
chk_timee = DateTime.Now;
chk_valuee = Current_Level;
try
{
ChargeDetect?.Invoke(this, new ChargetDetectArgs(chk_times, chk_values, chk_timee, chk_valuee));
}
catch (Exception ex) { RaiseMessage(MessageType.Error, ex.Message); }
}
else if ((Current_Level - chk_values) <= -0.1)
{
//방전중이다
if (chk_times.Year != 1982) chk_times = new DateTime(1982, 11, 23);
if (chk_timee.Year != 1982) chk_timee = new DateTime(1982, 11, 23);
}
else
{
//아직 변화가 없으니 종료일을 기록하지 않는다
}
}
else
{
//이미 종료일이 셋팅된 상태이다
if ((Current_Level - chk_valuee) >= 0.1)
{
//종료시간을 시작값에 넣는다
chk_times = chk_timee;
chk_values = chk_valuee;
chk_timee = DateTime.Now;
chk_valuee = Current_Level;
try
{
ChargeDetect?.Invoke(this, new ChargetDetectArgs(chk_times, chk_values, chk_timee, chk_valuee));
}
catch (Exception ex) { RaiseMessage(MessageType.Error, ex.Message); }
}
else if ((Current_Level - chk_valuee) <= -0.1)
{
//방전중이다
if (chk_times.Year != 1982) chk_times = new DateTime(1982, 11, 23);
if (chk_timee.Year != 1982) chk_timee = new DateTime(1982, 11, 23);
}
else
{
//아직 변화가 없으니 종료일을 기록하지 않는다
}
}
}
}
public DateTime chk_times { get; set; } = new DateTime(1982, 11, 23);
public DateTime chk_timee { get; set; } = new DateTime(1982, 11, 23);
public float chk_values { get; set; } = 0f;
public float chk_valuee { get; set; } = 0f;
/// <summary>
/// 전압
/// </summary>
public float Current_Volt { get; set; }
/// <summary>
/// 남은 잔량(%)
/// </summary>
public float Current_Level { get; set; }
public double[] CellVoltage = new double[] { 0, 0, 0, 0, 0, 0, 0, 0 };
public float Current_LevelA { get; set; }
/// <summary>
/// 남은 전류량
/// </summary>
public int Current_Amp { get; set; }
/// <summary>
/// BMS 온도값1
/// </summary>
public double Current_temp1 { get; set; }
/// <summary>
/// BMS 온도값2
/// </summary>
public double Current_temp2 { get; set; }
/// <summary>
/// 총 전류량
/// </summary>
public int Current_MaxAmp { get; set; }
public DateTime Current_DataTime = DateTime.Parse("1982-11-23");
public DateTime Current_CellTime = DateTime.Parse("1982-11-23");
public int QueryIndex { get; set; } = 0;
/// <summary>
/// 상태읽기와 전압읽기명령을 반복합니다
/// </summary>
/// <returns></returns>
public Boolean SendQuery()
{
if (QueryIndex == 0)
{
if (Recv0 == true)
{
QueryIndex = 1;
Recv1 = false;
return true;
}
else
{
return SendQuery_ReadStatue();
}
}
else
{
if (Recv1 == true)
{
QueryIndex = 0;
Recv0 = false;
return true;
}
else
{
return SendQuery_ReadCellvoltage();
}
}
}
public Boolean SendQuery_ReadStatue()
{
Recv0 = false;
var cmd = new List<byte>();
cmd.Add(0xDD);
cmd.Add(0xA5);
cmd.Add(0x03);
cmd.Add(0x00);
cmd.Add(0xFF);
cmd.Add(0xFD);
cmd.Add(0x77);
cmd.Add(0x0D);
return WriteData(cmd.ToArray());
}
public Boolean SendQuery_ReadCellvoltage()
{
Recv1 = false;
var cmd = new List<byte>();
cmd.Add(0xDD);
cmd.Add(0xA5);
cmd.Add(0x04);
cmd.Add(0x00);
cmd.Add(0xFF);
cmd.Add(0xFC);
cmd.Add(0x77);
cmd.Add(0x0D);
return WriteData(cmd.ToArray());
}
}
}

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{7A94C30C-6772-4F71-BF9C-0DF071A1BC70}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>arDevice</RootNamespace>
<AssemblyName>BMS</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<Deterministic>true</Deterministic>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="BMSInformationEventArgs.cs" />
<Compile Include="BMS.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CommData\CommData.csproj">
<Project>{14e8c9a5-013e-49ba-b435-efefc77dd623}</Project>
<Name>CommData</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -1,44 +0,0 @@
using System;
namespace arDev
{
public class ChargetDetectArgs : EventArgs
{
public DateTime times { get; set; }
public DateTime timee { get; set; }
public float values { get; set; }
public float valuee { get; set; }
public ChargetDetectArgs(DateTime times, float values, DateTime timee, float valuee)
{
this.times = times;
this.times = timee;
this.values = values;
this.valuee = valuee;
}
}
public class BMSInformationEventArgs : EventArgs
{
public float Volt { get; set; }
public int CurAmp { get; set; }
public int MaxAmp { get; set; }
public float Level { get; set; }
public bool Changed { get; set; }
public BMSInformationEventArgs(float _volt, int _curamp, int _maxamp, float _level, bool _changed)
{
this.Volt = _volt;
this.CurAmp = _curamp;
this.MaxAmp = _maxamp;
this.Level = _level;
this.Changed = _changed;
}
}
public class BMSCelvoltageEventArgs : EventArgs
{
public double[] voltage;
public BMSCelvoltageEventArgs(double v1, double v2, double v3, double v4, double v5, double v6, double v7, double v8)
{
voltage = new double[] { v1, v2, v3, v4, v5, v6, v7, v8 };
}
}
}

View File

@@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// 어셈블리에 대한 일반 정보는 다음 특성 집합을 통해
// 제어됩니다. 어셈블리와 관련된 정보를 수정하려면
// 이러한 특성 값을 변경하세요.
[assembly: AssemblyTitle("BMS Commnunication Module")]
[assembly: AssemblyDescription("BMS Commnunication Module")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("ATK4")]
[assembly: AssemblyProduct("BMS Commnunication Module")]
[assembly: AssemblyCopyright("Copyright ©ATK4 2020")]
[assembly: AssemblyTrademark("ATK4")]
[assembly: AssemblyCulture("")]
// ComVisible을 false로 설정하면 이 어셈블리의 형식이 COM 구성 요소에
// 표시되지 않습니다. COM에서 이 어셈블리의 형식에 액세스하려면
// 해당 형식에 대해 ComVisible 특성을 true로 설정하세요.
[assembly: ComVisible(false)]
// 이 프로젝트가 COM에 노출되는 경우 다음 GUID는 typelib의 ID를 나타냅니다.
[assembly: Guid("7a94c30c-6772-4f71-bf9c-0df071a1bc70")]
// 어셈블리의 버전 정보는 다음 네 가지 값으로 구성됩니다.
//
// 주 버전
// 부 버전
// 빌드 번호
// 수정 버전
//
// 모든 값을 지정하거나 아래와 같이 '*'를 사용하여 빌드 번호 및 수정 번호를
// 기본값으로 할 수 있습니다.
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("20.03.09.0000")]
[assembly: AssemblyFileVersion("20.03.09.0000")]

View File

@@ -1,495 +0,0 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading;
public abstract partial class arRS232 : IDisposable
{
protected System.IO.Ports.SerialPort _device;
protected ManualResetEvent _mre;
protected byte[] LastReceiveBuffer = new byte[] { };
/// <summary>
/// 최종 전송 메세지
/// </summary>
public byte[] lastSendBuffer = new byte[] { };
//public int ValidCheckTimeMSec { get; set; } = 5000;
protected List<byte> tempBuffer = new List<byte>();
protected Boolean findSTX = false;
public string errorMessage { get; set; }
public DateTime LastConnTime { get; set; }
public DateTime LastConnTryTime { get; set; }
public DateTime lastSendTime;
/// <summary>
/// 메세지 수신시 사용하는 내부버퍼
/// </summary>
protected List<byte> _buffer = new List<byte>();
/// <summary>
/// 데이터조회간격(초)
/// </summary>
public float ScanInterval { get; set; }
// public byte[] LastRecvData;
public string LastRecvString
{
get
{
if (LastReceiveBuffer == null) return String.Empty;
else return System.Text.Encoding.Default.GetString(LastReceiveBuffer);
}
}
/// <summary>
/// 마지막으로 데이터를 받은 시간
/// </summary>
public DateTime lastRecvTime;
public int WriteError = 0;
public string WriteErrorMessage = string.Empty;
public int WaitTimeout { get; set; } = 1000;
public int MinRecvLength { get; set; } = 1;
/// <summary>
/// 포트이름
/// </summary>
[Description("시리얼 포트 이름")]
[Category("설정"), DisplayName("Port Name")]
public string PortName
{
get
{
if (_device == null) return string.Empty;
else return _device.PortName;
}
set
{
if (this.IsOpen)
{
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 포트이름을 변경할 수 없습니다", true));
}
else if (String.IsNullOrEmpty(value) == false)
_device.PortName = value;
else
{
Message?.Invoke(this, new MessageEventArgs("No PortName", true));
}
}
}
public int BaudRate
{
get
{
if (_device == null) return 0;
else return _device.BaudRate;
}
set
{
if (this.IsOpen)
{
Message?.Invoke(this, new MessageEventArgs("포트가 열려있어 BaudRate(를) 변경할 수 없습니다", true));
}
else if (value != 0)
_device.BaudRate = value;
else Message?.Invoke(this, new MessageEventArgs("No baud rate", true));
}
}
public arRS232()
{
_device = new System.IO.Ports.SerialPort();
this.BaudRate = 9600;
ScanInterval = 10;
_device.DataReceived += barcode_DataReceived;
_device.ErrorReceived += this.barcode_ErrorReceived;
_device.WriteTimeout = 5000;
_device.ReadTimeout = 5000;
// _device.DtrEnable = false;
_device.ReadBufferSize = 8192;
_device.WriteBufferSize = 8192;
errorMessage = string.Empty;
lastRecvTime = DateTime.Parse("1982-11-23");
LastConnTime = DateTime.Parse("1982-11-23");
LastConnTryTime = DateTime.Parse("1982-11-23");
lastRecvTime = DateTime.Parse("1982-11-23");
this._mre = new ManualResetEvent(true);
}
~arRS232()
{
Dispose(false);
}
// Flag: Has Dispose already been called?
bool disposed = false;
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
// Free any other managed objects here.
//
}
_device.DataReceived -= barcode_DataReceived;
_device.ErrorReceived -= this.barcode_ErrorReceived;
// Free any unmanaged objects here.
//
disposed = true;
}
public Boolean Open()
{
try
{
_device.Open();
return IsOpen;
}
catch (Exception ex)
{
errorMessage = ex.Message;
Message.Invoke(this, new MessageEventArgs(ex.Message, true));
return false;
}
}
public string GetHexString(Byte[] input)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
foreach (byte b in input)
sb.Append(" " + b.ToString("X2"));
return sb.ToString();
}
/// <summary>
/// 포트가 열려있는지 확인
/// </summary>
[Description("현재 시리얼포트가 열려있는지 확인합니다")]
[Category("정보"), DisplayName("Port Open")]
public Boolean IsOpen
{
get
{
if (_device == null) return false;
return _device.IsOpen;
}
}
public virtual void Close(Boolean PortClose = true)
{
if (_device != null && _device.IsOpen)
{
_device.DiscardInBuffer();
_device.DiscardOutBuffer();
if (PortClose) _device.Close(); //dispose에서는 포트를 직접 클리어하지 않게 해뒀다.
}
}
protected Boolean RaiseRecvData()
{
return RaiseRecvData(LastReceiveBuffer.ToArray(), false);
}
/// <summary>
/// 수신받은 메세지를 발생 시킵니다
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public virtual Boolean RaiseRecvData(byte[] Data, bool udpatelastbuffer)
{
//181206 - 최종수신 메세지 기록
lastRecvTime = DateTime.Now;
if (udpatelastbuffer && Data != null)
{
if (LastReceiveBuffer == null || LastReceiveBuffer.Length != Data.Length)
{
LastReceiveBuffer = new byte[Data.Length];
Array.Copy(Data, LastReceiveBuffer, Data.Length);
}
}
try
{
Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
if (ProcessRecvData(Data) == false)
{
//Message?.Invoke(this, new MessageEventArgs(Data, true)); //recvmessage
Message?.Invoke(this, new MessageEventArgs(this.errorMessage, true)); //errormessage
return false;
}
else
{
return true;
}
}
catch (Exception ex)
{
this.errorMessage = ex.Message;
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
return false;
}
}
/// <summary>
/// 수신받은 자료를 처리한다
/// </summary>
/// <param name="data"></param>
/// <returns></returns>
public abstract bool ProcessRecvData(byte[] data);
#region "Internal Events"
void barcode_ErrorReceived(object sender, System.IO.Ports.SerialErrorReceivedEventArgs e)
{
Message?.Invoke(this, new MessageEventArgs(e.ToString(), true));
}
byte[] buffer = new byte[] { };
void barcode_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
int ReadCount = _device.BytesToRead;
buffer = new byte[ReadCount];
_device.Read(buffer, 0, buffer.Length);
System.Text.StringBuilder LogMsg = new StringBuilder();
byte[] remainBuffer;
Repeat:
if (CustomParser(buffer, out remainBuffer))
{
//분석완료이므로 받은 데이터를 버퍼에 기록한다
if (LastReceiveBuffer == null || (LastReceiveBuffer.Length != tempBuffer.Count))
Array.Resize(ref LastReceiveBuffer, tempBuffer.Count);
Array.Copy(tempBuffer.ToArray(), LastReceiveBuffer, tempBuffer.Count);
tempBuffer.Clear();
//수신메세지발생
RaiseRecvData();
if (remainBuffer != null && remainBuffer.Length > 0)
{
//버퍼를 변경해서 다시 전송을 해준다.
Array.Resize(ref buffer, remainBuffer.Length);
Array.Copy(remainBuffer, buffer, remainBuffer.Length);
goto Repeat; //남은 버퍼가 있다면 진행을 해준다.
}
}
}
catch (Exception ex)
{
//if (IsOpen)
//{
// //_device.DiscardInBuffer();
// //_device.DiscardOutBuffer();
//}
errorMessage = ex.Message;
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
}
}
#endregion
#region "External Events"
/// <summary>
/// 오류 및 기타 일반 메세지
/// </summary>
public event EventHandler<MessageEventArgs> Message;
#endregion
#region "Event Args"
/// <summary>
/// 데이터를 수신할떄 사용함(RAW 포함)
/// </summary>
public class ReceiveDataEventArgs : EventArgs
{
private byte[] _buffer = null;
/// <summary>
/// 바이트배열의 버퍼값
/// </summary>
public byte[] Value { get { return _buffer; } }
/// <summary>
/// 버퍼(바이트배열)의 데이터를 문자로 반환합니다.
/// </summary>
public string StrValue
{
get
{
//return string.Empty;
if (_buffer == null || _buffer.Length < 1) return string.Empty;
else return System.Text.Encoding.Default.GetString(_buffer);
}
}
public ReceiveDataEventArgs(byte[] buffer)
{
_buffer = buffer;
}
}
/// <summary>
/// 메세지를 강제 발생
/// </summary>
/// <param name="mt"></param>
/// <param name="message"></param>
protected virtual void RaiseMessage(MessageType mt, string message)
{
this.Message?.Invoke(this, new MessageEventArgs(mt, message));
}
public enum MessageType
{
Normal,
Error,
Send,
Recv,
}
public class MessageEventArgs : EventArgs
{
public MessageType MsgType { get; set; }
private string _message = string.Empty;
/// <summary>
/// Recv,Send,Normal,Error 모두 지원
/// </summary>
public string Message { get { return _message; } }
private byte[] _data = null;
/// <summary>
/// Recv,Send에서만 값이 존재 합니다
/// </summary>
public byte[] Data { get { return _data; } }
public MessageEventArgs(string Message, bool isError = false)
{
if (isError) MsgType = MessageType.Error;
else MsgType = MessageType.Normal;
_message = Message;
}
public MessageEventArgs(MessageType msgtype, string Message)
{
MsgType = msgtype;
_message = Message;
_data = System.Text.Encoding.Default.GetBytes(Message);
}
public MessageEventArgs(byte[] buffer, bool isRecv = true)
{
if (isRecv) MsgType = MessageType.Recv;
else MsgType = MessageType.Send;
_data = new byte[buffer.Length];
Array.Copy(buffer, _data, Data.Length);
_message = System.Text.Encoding.Default.GetString(_data);
}
}
#endregion
protected abstract bool CustomParser(byte[] buf, out byte[] remainBuffer);
/// <summary>
/// 포트가 열려있거나 데이터 수신시간이 없는경우 false를 반환합니다
/// </summary>
public Boolean IsValid
{
get
{
if (IsOpen == false) return false;
if (lastRecvTime.Year == 1982) return false;
var ts = DateTime.Now - lastRecvTime;
if (ts.TotalSeconds > (this.ScanInterval * 2.5)) return false;
return true;
}
}
protected string ByteListToHexString(List<byte> src)
{
return string.Join(" ", src.Select(t => t.ToString("X2")));
}
protected bool WriteData(string cmd)
{
return WriteData(System.Text.Encoding.Default.GetBytes(cmd));
}
/// <summary>
/// 포트에 쓰기(barcode_DataReceived 이벤트로 메세지수신)
/// </summary>
protected Boolean WriteData(byte[] data)
{
Boolean bRet = false;
//171205 : 타임아웃시간추가
if (!_mre.WaitOne(WaitTimeout))
{
errorMessage = $"WriteData:MRE:WaitOne:TimeOut {WaitTimeout}ms";
this.Message?.Invoke(this, new MessageEventArgs(errorMessage, true));
return false;
}
_mre.Reset();
//Array.Resize(ref data, data.Length + 2);
try
{
lastSendTime = DateTime.Now;
if (lastSendBuffer == null) lastSendBuffer = new byte[data.Length]; //171113
else Array.Resize(ref lastSendBuffer, data.Length);
Array.Copy(data, lastSendBuffer, data.Length);
for (int i = 0; i < data.Length; i++)
_device.Write(data, i, 1);
//_device.Write(data, 0, data.Length);
//171113
this.Message?.Invoke(this, new MessageEventArgs(data, false));
bRet = true;
WriteError = 0;
WriteErrorMessage = string.Empty;
}
catch (Exception ex)
{
// this.isinit = false;
this.Message?.Invoke(this, new MessageEventArgs(ex.Message, true));
bRet = false;
WriteError += 1; //연속쓰기오류횟수
WriteErrorMessage = ex.Message;
}
finally
{
_mre.Set();
}
return bRet;
}
}

Submodule Cs_HMI/SubProject/EnigProtocol updated: 4f360f33a7...8877cb1a9d