DispatcherTimer timer;
DispatcherTimer fontTimer;
public int Port = 0;
TestItemsModel ConfigModel = new TestItemsModel();
bool isFirstLoad = true;
string IP = string.Empty;
SocketServer server = null;
// 每次发送的数据长度
const int SEND_DATA_LEN_ONE_TIME = 256;
//字库在SPI Flash中的起始地址
const int FONT_BASE_ADDR_IN_SPI_FLASH = 0X00;
//IC卡数据长度
const int IC_CARD_DATA_LEN = 128;
const int IC_CARD_DRIVER_NAME_LEN = 12;
const int IC_CARD_GENDER_LEN = 2;
const int IC_CARD_IDENTIYT_NUMBER_LEN = 18;
const int IC_CARD_DRIVER_LICENSE_LEN = 18;
const int IC_CARD_DRIVER_LICENSE_LMT_LEN = 3;
const int IC_CARD_DRIVER_LEGAL_CODE_LEN = 18;
const int IC_CARD_RESERVED_STD_EXTEND_LEN = 56;
const int IC_CARD_CHECKSUM_LEN = 4;
const int ACK_TIME_OUT = 10;
const int ERASE_FLASH_ACK_TIME_OUT = 60;
//IC卡数据的起始地址
const int IC_CARD_DATA_BASE_ADDR = 0X00;
const int COM_READ_BUF_LEN = 1024;
const string CMD_READ_24C01_CARD = "#RIC";
const string CMD_READ_SL4442_CARD = "#RSL";
const string CMD_WRITE_24C01_CARD = "#WIC";
const string CMD_WRITE_SL4442_CARD = "#WSL";
const string CMD_CLEAR_SPI_FLASH = "#CLR";
const string CMD_WRITE_SPI_FLASH = "#WW";
bool bIsFontLibInSending = false; //正在发送字库
bool bIsComPortOpen = false;//串口是否打开
bool bIsFlashErase = false; //正在擦除
bool bIsReadingICCard = false;
bool bIsWritingICCard = false;
private static FileStream fs = null;
private static long index = 0;
private static long blockCount;
private static DateTime dt;
int cardType = 0; //diskType" : int , 0--4 分别SD1 -- 镜像盘
int rsType = 0; //RS485 0 MCU 串口 1
DateTime startTime;
DateTime endTime;
byte[] m_pBuffer = null; /* 字库缓存地址程序中动态分配 */
uint m_CurSndPos = 0; /* 当前写的字库地址 */
uint m_CurSPI_Flash_Addr = 0; /* 当前写SPI_Flash的位置地址 */
uint m_LastSndLen = 0; /* 上一次发送的数据长度 */
uint m_FontLibFileLen = 0; /* 字库缓存的长度 */
bool isStopTest = false;
private void OpenPort(object model)
{
if (!bIsComPortOpen)
{
SerialHelper.OpenSerialPort(SelectSerialPort.Name, Convert.ToInt32(SelectBaudRate.Name), Convert.ToInt32(SelectDataBits.Name),
Convert.ToInt32(SelectStopBit.Name), Convert.ToInt32(SelectCheckBit.Value));
}
else
{
if (SerialHelper.serialP.IsOpen)
{
SerialHelper.serialP.Close();
OnOpen(false);
}
}
}
private void OnReceiveMsg(string msg)
{
}
private void OnOpen(bool result)
{
if (result)
{
IndicatorLightColor = Brushes.Green;
BtnDes = "关闭";
}
else
{
IndicatorLightColor = Brushes.Red;
BtnDes = "打开";
}
bIsComPortOpen = result;
}
long fileLen = 0;
int sendLen = 0;
Thread T;
private void UpgradeFont(object o)
{
if (CheckUpdate())
{
dt = DateTime.Now;
if (string.IsNullOrEmpty(FilePath) || !File.Exists(FilePath))
{
ShowTip("文件路径为空");
return;
}
fs = new FileStream(FilePath, FileMode.Open, FileAccess.Read);
long m_FontLibFileLen = fs.Length;
fileLen = m_FontLibFileLen;
if (m_FontLibFileLen == 0)
{
ShowTip("字库文件大小为:0");
return;
}
byte[] byteArray = new byte[m_FontLibFileLen];
fs.Read(byteArray, 0, (int)m_FontLibFileLen);
int m_CurSndPos = 0;
int m_CurSPI_Flash_Addr = 0;
int m_LastSndLen = 0;
if (m_FontLibFileLen < SEND_DATA_LEN_ONE_TIME)
{
m_CurSndPos = 0; // 发送的位置在m_pBuffer中的偏移
m_LastSndLen = (int)m_FontLibFileLen;
SendFontDataToCom((uint)m_CurSPI_Flash_Addr, byteArray, (uint)m_LastSndLen);
sendLen += m_LastSndLen;
bIsFontLibInSending = true;
}
else
{
m_CurSndPos = 0;
m_LastSndLen = SEND_DATA_LEN_ONE_TIME;
SendFontDataToCom((uint)m_CurSPI_Flash_Addr, byteArray, (uint)m_LastSndLen);
bIsFontLibInSending = true;
sendLen += m_LastSndLen;
}
int Range = (int)m_FontLibFileLen / (SEND_DATA_LEN_ONE_TIME); /* 文件长度 */
if (Range == 0) // 说明只需一步即可达到100%
{
Range = 1;
TxtMsg = "上传完成";
return;
}
else if (Range > 0 && (m_FontLibFileLen % (SEND_DATA_LEN_ONE_TIME)) != 0)
{
Range += 1;
}
TxtMsg = string.Empty;
startTime = DateTime.Now;
endTime = DateTime.Now;
byte[] AckCmdBuf = new byte[256];
T = new Thread(new ThreadStart(() =>
{
for (int i = 1; i < Range; i++)
{
if (i != (Range - 1))
{
sendLen += m_LastSndLen;
SendFontDataToCom((uint)i * 256, byteArray, (uint)m_LastSndLen);
Application.Current.Dispatcher.Invoke(() =>
{
TxtMsg = $"{sendLen}/{fileLen}";
ProMax = (int)fileLen;
ProVal = (int)sendLen;
ProVisual = Visibility.Visible;
});
}
else
{
int lastLen = (int)(m_FontLibFileLen % 256);
if (lastLen == 0)
lastLen = 256;
sendLen += lastLen;
SendFontDataToCom((uint)i * 256, byteArray, (uint)lastLen);
endTime = DateTime.Now;
TimeSpan timeSpan = endTime - startTime; // 两个CTime相减得到CTimeSpan
double nTSeconds = timeSpan.TotalSeconds;
Application.Current.Dispatcher.Invoke(() =>
{
TxtMsg = $"上传完成耗时:{ Math.Round(nTSeconds, 0)}秒 ({sendLen}/{fileLen})";
ProVal = Math.Min((int)sendLen, (int)fileLen);
ProVisual = Visibility.Hidden;
bIsFontLibInSending = false;
sendLen = 0;
});
}
}
}));
T.Start();
}
}
private void ParaseFontUpdateAck(byte[] PAckCmdBuf, int Len)
{
byte[] TmpStatues = new byte[128];
string str = GetStrByArray(PAckCmdBuf);
if (str.Contains(CMD_WRITE_SPI_FLASH))
{
uint AckComWriteSPI_Flash_Addr = 0;
uint AckComWriteSPI_Flash_Len = 0;
/* 写入SPI Flash的地址 */
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[3] << 24);
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[4] << 16);
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[5] << 8);
AckComWriteSPI_Flash_Addr |= (uint)(PAckCmdBuf[6] << 0);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[7] << 24);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[8] << 16);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[9] << 8);
AckComWriteSPI_Flash_Len |= (uint)(PAckCmdBuf[10] << 0);
if ((AckComWriteSPI_Flash_Len == m_LastSndLen) && (AckComWriteSPI_Flash_Addr == m_CurSPI_Flash_Addr))
{
m_CurSndPos += m_LastSndLen; /* 已经发送的长度累增 */
m_CurSPI_Flash_Addr += m_LastSndLen; /* 当前写文件地址累增 */
if (m_CurSndPos < m_FontLibFileLen)
{
/* 发送剩余的 */
if (m_FontLibFileLen - m_CurSndPos <= SEND_DATA_LEN_ONE_TIME)
{
m_LastSndLen = m_FontLibFileLen - m_CurSndPos;
SendFontDataToCom(m_CurSPI_Flash_Addr, PAckCmdBuf, m_LastSndLen);
bIsFontLibInSending = true;
}
else
{
m_LastSndLen = SEND_DATA_LEN_ONE_TIME;
SendFontDataToCom(m_CurSPI_Flash_Addr, m_pBuffer, m_LastSndLen);
bIsFontLibInSending = true;
}
TxtMsg = $"写入进度:{m_CurSndPos}/{m_FontLibFileLen}";
ProVisual = Visibility.Visible;
ProMax = (int)m_FontLibFileLen;
ProVal = (int)m_CurSndPos;
}
else if (m_CurSndPos == m_FontLibFileLen) /* 写完成 */
{
ProVal = (int)m_CurSndPos;
ProVisual = Visibility.Collapsed;
fontTimer.Stop();
bIsFontLibInSending = false;
m_CurSndPos = 0;
m_LastSndLen = 0;
m_CurSPI_Flash_Addr = 0;
endTime = System.DateTime.Now;
TimeSpan timeSpan = endTime - startTime; // 两个CTime相减得到CTimeSpan
double nTSeconds = timeSpan.TotalSeconds; // 得到总的秒数
TxtMsg = $"字库升级成功,共耗时:{nTSeconds}秒";
if (m_pBuffer != null)
{
m_pBuffer = null;
}
}
//CProgressCtrl *pProgressCtrl = (CProgressCtrl *)GetDlgItem(IDC_PROGRESS_UPDATE);
}
else /* 写Flash 出错 !*/
{
//sprintf(TmpStatues, "MCU写地址出错:AckAddr:%x, AckLen:%d, Addr:%x, Len:%d Pos:%d",\
// AckComWriteSPI_Flash_Addr, AckComWriteSPI_Flash_Len, \
// m_CurSPI_Flash_Addr, m_LastSndLen, m_CurSndPos);
//SetStauesText(TmpStatues);
//SendFontDataToCom(m_CurSPI_Flash_Addr, m_pBuffer + m_CurSndPos, m_LastSndLen);
//bIsFontLibInSending = true;
}
}
}
private void CleaningMemory(object o)
{
if (CheckPortOpen())
{
if (true == bIsFlashErase)
{
ShowTip("正在清除");
return;
}
SendEraseFlashToCom(FONT_BASE_ADDR_IN_SPI_FLASH, 0);
}
}
void SendFontDataToCom(uint WriteAddr, byte[] pSndBuf, uint SndBufLen)
{
/* 发送:#WW + 地址(4字节) + 长度(4字节) ... 数据(长度不超过256) ... 校验和(#W,参与校验,共1字节) + OO# */
byte[] pTmpBuf = null;
uint CalcBufLen = 0;
byte[] pCalcAddr = new byte[512];// [512] = { 0 };
pTmpBuf = pCalcAddr; /* 计算校验和的起始地址 */
/* 命令头 */
pTmpBuf[CalcBufLen++] = (byte)'#';
pTmpBuf[CalcBufLen++] = (byte)'W';
pTmpBuf[CalcBufLen++] = (byte)'W';
/* 写入SPI Flash的地址 */
pTmpBuf[CalcBufLen++] = (byte)((WriteAddr >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((WriteAddr >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((WriteAddr >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((WriteAddr >> 24) & 0xff);
/* 写入数据的长度 */
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((SndBufLen >> 24) & 0xff);
//真正发送的数据
Array.Copy(pSndBuf, 0, pTmpBuf, CalcBufLen, SndBufLen);
CalcBufLen += SndBufLen;
byte XorSum = XorCheckSum(pCalcAddr, CalcBufLen);
pTmpBuf[CalcBufLen++] = XorSum;
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'#';
try
{
SerialHelper.serialP.Write(pTmpBuf, 0, (int)CalcBufLen);
}
catch (Exception ex)
{
LogService.Instance.Debug("SendFontDataToCom:" + ex.Message);
TxtMsg = "写字库数据失败!";
}
}
void FontPath(object o)
{
Microsoft.Win32.OpenFileDialog ofd = new Microsoft.Win32.OpenFileDialog();
ofd.DefaultExt = ".*";
ofd.Filter = "字库文件|*.DZK";
if (ofd.ShowDialog() == true)
{
FilePath = ofd.FileName;
}
}
//清除
void SendEraseFlashToCom(UInt32 ClearAddr, UInt32 ClearLen)
{
string msg = "正在擦除Flash...";
if (bIsFlashErase)
{
ShowTip(msg);
return;
}
TxtMsg = msg;
bIsFlashErase = true;
/* 发送:#WW + 地址(4字节) + 长度(4字节) ... 数据(长度不超过256) ... 校验和(#W,参与校验,共1字节) + OO# */
byte[] pTmpBuf = null;
byte[] pCalcAddr = null;
uint CalcBufLen = 0;
pTmpBuf = new byte[512];
pCalcAddr = pTmpBuf; /* 计算校验和的起始地址 */
/* 命令头 */
pTmpBuf[CalcBufLen++] = (byte)'#';
pTmpBuf[CalcBufLen++] = (byte)'C';
pTmpBuf[CalcBufLen++] = (byte)'L';
pTmpBuf[CalcBufLen++] = (byte)'R';
/* 写入SPI Flash的地址 */
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearAddr >> 24) & 0xff);
/* 写入数据的长度 */
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 0) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 8) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 16) & 0xff);
pTmpBuf[CalcBufLen++] = (byte)((ClearLen >> 24) & 0xff);
byte XorSum = XorCheckSum(pCalcAddr, CalcBufLen);
pTmpBuf[CalcBufLen++] = XorSum;
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'O';
pTmpBuf[CalcBufLen++] = (byte)'#';
SerialHelper.serialP.Write(pTmpBuf, 0, (int)CalcBufLen);
Console.WriteLine("SerialHelper.serialP.Write:" + CalcBufLen);
startTime = DateTime.Now;
endTime = DateTime.Now;
SerialHelper.serialP.Write(pTmpBuf, 0, (int)CalcBufLen);
int AckCmdLen = 1;
byte[] AckCmdBuf = new byte[256];// [256] = { 0 };
Task.Factory.StartNew(() =>
{
while (bIsFlashErase) /* 擦除Flash */
{
Thread.Sleep(10);
AckCmdLen = GetAckCmdBuf(ref AckCmdBuf, 256);
if (AckCmdLen != 0)
{
ParaseEraseFlashAck(AckCmdBuf, AckCmdLen);
startTime = DateTime.Now;
}
else
{
endTime = DateTime.Now;
TimeSpan timeSpan = endTime - startTime; // 两个CTime相减得到CTimeSpan
double nTSeconds = timeSpan.TotalSeconds; // 得到总的秒数
if (nTSeconds > ERASE_FLASH_ACK_TIME_OUT)
{
bIsFlashErase = false;
Application.Current.Dispatcher.Invoke(() =>
{
TxtMsg = "擦除Flash超时失败!";
});
}
}
}
});
}
void ParaseEraseFlashAck(byte[] PAckCmdBuf, int Len)
{
string str = GetStrByArray(PAckCmdBuf);
if (str.Contains(CMD_CLEAR_SPI_FLASH))
{
Application.Current.Dispatcher.Invoke(() =>
{
bIsFlashErase = false;
TxtMsg = "擦除Flash成功";
});
}
}
byte XorCheckSum(byte[] pBuff, uint Len)
{
byte CheckSum = 0;
if (null == pBuff)
{
return CheckSum;
}
for (uint i = 0; i < Len; i++)
{
CheckSum ^= pBuff[i]; //*(pBuff + i);
}
return CheckSum;
}
int GetAckCmdBuf(ref byte[] PAckCmdBuf, int Len)
{
int len, Idx;
int AckCmdLen = 0; // 单片机返回的应答个数
byte[] RxDataBuf = new byte[COM_READ_BUF_LEN];// [COM_READ_BUF_LEN] = { 0 }; // 串口读取的缓存
int TotalRcvLen = 0;
System.Threading.Thread.Sleep(10);
byte[] ReDatas = new byte[SerialHelper.serialP.BytesToRead];
//从串口读取数据
len = SerialHelper.serialP.Read(ReDatas, 0, ReDatas.Length);
Array.Copy(ReDatas, 0, PAckCmdBuf, 0, Math.Min(ReDatas.Length, PAckCmdBuf.Length));
if (len > 0)
{
TotalRcvLen += len; // 长度累加
Console.WriteLine("TotalRcvLen:" + TotalRcvLen);
}
for (Idx = 0; Idx < TotalRcvLen; Idx++)
{
if (((byte)'O' == ReDatas[Idx]) && ((byte)'O' == ReDatas[Idx + 1]) && ((byte)'#' == ReDatas[Idx + 2]))
{
AckCmdLen = (int)Idx + 3;
TotalRcvLen -= (int)AckCmdLen; /* 数据向前移动 */
byte[] pTmpBuf = new byte[ReDatas.Length + AckCmdLen];
if (Len >= AckCmdLen)
{
Array.Copy(ReDatas, 0, PAckCmdBuf, 0, AckCmdLen);
}
else
{
Console.WriteLine("超出缓存限制");
AckCmdLen = 0;
}
for (int TmpIdx = 0; TmpIdx < TotalRcvLen; TmpIdx++)
{
RxDataBuf[TmpIdx] = pTmpBuf[TmpIdx];
}
break;
}
}
return AckCmdLen;
}