Sei sulla pagina 1di 10

using System;

using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace TokenProtocolForArduinoSerial
{
public partial class SerialTest : Form
{
#region "member variables"
private Int64 nReceivedBytes = 0; //cati bytes s-au primit pe seriala
private Int64 nSentBytes = 0; //cati bytes s-au transmis pe seriala
private string strReceivedCharsBetweenTicks = ""; //ce s-a primit pe ser
iala intre 2 update-uri
//(ca sa nu fac update l
a fiecare caracter primit!!)
private string strSentCharsBetweenTicks = "";//ce s-a transmis intre 2 u
pdate-uri
int MAX_LINES = 1000; //numarul maxim de linii afisate (ultimele)
int MAX_CHARS_IN_UI_BUFFER = 5000; //numarul maxim de linii afisate (ult
imele)
string strLogFileName = ""; //calea catre fisierul de log
protected SerialPort serialPort = null; //portul serial
internal String m_szSerialCommBuffer = null; //folosit ca buffer de rece
ptie pentru comunicatia cu seriala
[DllImport("user32.dll")]
public static extern int SendMessage(IntPtr hWnd, Int32 wMsg, bool wPara
m, Int32 lParam);
private const int WM_SETREDRAW = 11;
TokenProtocol protocolT = null;
#endregion "member variables"
#region "ctor"
public SerialTest()
{
InitializeComponent();
setUIConnectionStatus(false);
this.FormBorderStyle = FormBorderStyle.FixedDialog;
this.comboCOMPort.Items.AddRange(SerialPort.GetPortNames());
protocolT = new TokenProtocol();
protocolT.sendData += WriteCommandToEquipment;
protocolT.onReceivedData += onCommandReceived;
protocolT.NodeAddress = 0x0A;

}
#endregion
#region "UI functions"
private void buttonConnect_Click(object sender, EventArgs e)
{
String szParity = this.comboParity.Text;
String szCOMPort = this.comboCOMPort.Text;
String szBaudRate = this.comboBaudRate.Text;
bool bPortOpened = OpenComPort(szParity, szCOMPort, szBaudRate);
if (bPortOpened)
{
setUIConnectionStatus(true);
serialPort.DataReceived += new System.IO.Ports.SerialDataReceive
dEventHandler(this.OnSerialPort_DataReceived);
}else
{
setUIConnectionStatus(false);
}
}
//linmiteaza numarul de linii scrise intr-un textBox la MAX_LINES
private void print(TextBox txtOut, string output)
{
if (!checkBoxFreezeUIReceive.Checked)
{
//stop redrawing
SendMessage(txtOut.Handle, WM_SETREDRAW, false, 0);
txtOut.Text += output;
if (txtOut.Lines.Length > MAX_LINES)
{
string[] newLines = new string[MAX_LINES];
Array.Copy(txtOut.Lines, 1, newLines, 0, MAX_LINES);
txtOut.Lines = newLines;
}
if (txtOut.Text.Length > MAX_CHARS_IN_UI_BUFFER)
{
//CUT IT down
txtOut.Text = txtOut.Text.Substring(txtOut.Text.Length - MAX
_CHARS_IN_UI_BUFFER, MAX_CHARS_IN_UI_BUFFER - 1);
}
//redraw again
SendMessage(txtOut.Handle, WM_SETREDRAW, true, 0);
txtOut.SelectionStart = txtOut.Text.Length;
txtOut.ScrollToCaret();
}
}
private void buttonDisconnect_Click(object sender, EventArgs e)
{
setUIConnectionStatus(false);

if(serialPort != null)
{
serialPort.DataReceived -= new System.IO.Ports.SerialDataReceive
dEventHandler(this.OnSerialPort_DataReceived);
//close the serial port. Must be done in another thread!!!
if (serialPort.IsOpen)
{
this.buttonConnect.Enabled = false;
Thread CloseDown = new Thread(new ThreadStart(CloseSerial));
CloseDown.Start();
CloseDown.Join(100);
}
}
}
private void buttonSend_Click(object sender, EventArgs e)
{
SendCommandToEquipment(textBoxDataToSend.Text);
textBoxDataToSend.Text = "";
}
void setUIConnectionStatus(bool bConnected)
{
comboParity.Enabled = !bConnected;
comboCOMPort.Enabled = !bConnected;
comboBaudRate.Enabled = !bConnected;
buttonConnect.Enabled = !bConnected;
buttonDisconnect.Enabled = bConnected;
buttonSend.Enabled = bConnected;
buttonSendCR.Enabled = bConnected;
buttonSendLF.Enabled = bConnected;
buttonSendAsHex.Enabled = bConnected;
buttonCRLF.Enabled = bConnected;
}
string toHex(string str)
{
string strNew = "";
foreach (char ch in str)
{
uint b = (byte)ch;
uint upper = (b & 0xf0) >> 4;
Debug.Assert(upper < 16, "Logic Hex error!");
uint lower = b & 0x0f;
Debug.Assert(lower < 16, "Logic Hex error!");
if (upper <= 9) strNew = strNew + (char)('0' + upper);
else strNew = strNew + (char)('A' + upper - 10);
if (lower <= 9) strNew = strNew + (char)('0' + lower);
else strNew = strNew + (char)('A' + lower - 10);
strNew += ' ';
}
return strNew;
}
string toHex(char c)

{
string str = "";
str = str + c;
return str;
}
string fromHex(string str)
{
string newStr = "";
//Debug.Assert(str.Length % 2 == 0, "Hex text should be multiple of
2!");
bool first = true;
int temp = 0;
foreach (char c1 in str)
{
char c = c1;
if (c == ' ') continue;
if (c >= 'a' && c <= 'f') c = (char)(c - 'a' + 'A');
if (!((c >= 'A' && c <= 'F') | (c >= '0' && c <= '9'))) throw ne
w Exception("The specified string is not in hex!");
if (first)
{
temp = (int)c;
temp = temp >= '0' && temp <= '9' ? temp - '0' : temp - 'A';
first = !first;
}
else
{
temp = temp << 4;
temp |= (int)c >= '0' && (int)c <= '9' ? (int)c - '0' : (int
)c - 'A' + 10;
first = !first;
newStr = newStr + Convert.ToChar(temp);
}
}
return newStr;
}
private void checkBoxHexView_CheckedChanged(object sender, EventArgs e)
{
if (checkBoxHexView.Checked)
{
textBoxReceivedData.Text = toHex(textBoxReceivedData.Text);
textBoxSentData.Text = toHex(textBoxSentData.Text);
}
else
{
textBoxReceivedData.Text = fromHex(textBoxReceivedData.Text);
textBoxSentData.Text = fromHex(textBoxSentData.Text);
}
checkBoxHexView.Update();
}
private void buttonSendCR_Click(object sender, EventArgs e)
{
SendCommandToEquipment("\r");
}

private void buttonSendLF_Click(object sender, EventArgs e)


{
SendCommandToEquipment("\n");
}
private void buttonClear_Click(object sender, EventArgs e)
{
textBoxReceivedData.Text = "";
textBoxSentData.Text = "";
}
private void buttonCRLF_Click(object sender, EventArgs e)
{
SendCommandToEquipment("\r\n");
}
private void checkBoxLogToFile_CheckedChanged(object sender, EventArgs e
)
{
//select a file to log to
DialogResult dr;
if (checkBoxLogToFile.Checked)
{
if (DialogResult.OK != openFileDialog.ShowDialog(this)) checkBox
LogToFile.Checked = false;
}
else
{
strLogFileName = "";
}
}
private void openFileDialog_FileOk(object sender, CancelEventArgs e)
{
strLogFileName = openFileDialog.FileName;
//check if file exists
try
{
if (!File.Exists(strLogFileName))
{
FileStream fs = File.Create(strLogFileName);
fs.Close();
}
}
catch (Exception ee)
{
MessageBox.Show("The specified file could not be created!", "Err
or", MessageBoxButtons.OK, MessageBoxIcon.Error);
strLogFileName = "";
checkBoxLogToFile.Checked = false;
}
}
private void timerUpdateUI_Tick(object sender, EventArgs e)
{
labelReceivedCounter.Text = Convert.ToString(nReceivedBytes);
labelSentBytesCounter.Text = Convert.ToString(nSentBytes);
if (!checkBoxFreezeUIReceive.Checked)

{
print(textBoxReceivedData, checkBoxHexView.Checked ? toHex(strRe
ceivedCharsBetweenTicks) : strReceivedCharsBetweenTicks);
strReceivedCharsBetweenTicks = "";
}
else strReceivedCharsBetweenTicks = "";
print(textBoxSentData, checkBoxHexView.Checked ? toHex(strSentCharsB
etweenTicks) : "" + strSentCharsBetweenTicks);
strSentCharsBetweenTicks = "";
}
private void buttonSendAsHex_Click(object sender, EventArgs e)
{
string str = "";
try
{
str = fromHex(textBoxDataToSend.Text);
}
catch (Exception ee)
{
MessageBox.Show("The data to send is not in HEX format!", "Error
!", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
SendCommandToEquipment(str);
textBoxDataToSend.Text = "";
}
//fereastra se va inchide in 3 pasi: 1)lanseaza un nou thread 2)noul thr
ead va inchide portul serial 3)din threadul nou se va apela NowClose() in thread
ul UI
private void SerialTest_FormClosing(object sender, FormClosingEventArgs
e)
{
if (serialPort == null)
{
return;
}
serialPort.DataReceived -= new System.IO.Ports.SerialDataReceivedEve
ntHandler(this.OnSerialPort_DataReceived);
if (serialPort.IsOpen)
{
e.Cancel = true;
Thread CloseDown = new Thread(new ThreadStart(CloseSerialOnExit)
);
CloseDown.Start();
}
else
{
serialPort = null;
}
}
//used to close the serial port (called from another thread)
void CloseSerialOnExit()
{
try
{
serialPort.Close();

serialPort = null;
this.Invoke(new EventHandler(NowClose));
}
catch (Exception)
{
serialPort = null;
}
}
//close this form in its own message processing queue
//closes this window
private void NowClose(object sender, EventArgs e)
{
this.Close();
}
#endregion
#region "serial port logic"
private void onCommandReceived(string sz)
{
//so smthng with the full received command (destined for my address)
//this command was destined for me and looks OK!!

}
private bool OpenComPort(String szParity, String szCOMPort, String szBau
dRate)
{
Parity parity = new Parity();
switch (szParity.ToUpper())
{
case "ODD":
parity = Parity.Odd;
break;
case "EVEN":
parity = Parity.Even;
break;
case "NONE":
parity = Parity.None;
break;
default:
MessageBox.Show(this, "Invalid parity!", "Error!", Messa
geBoxButtons.OK, MessageBoxIcon.Error);
return false;
}
int dataBits = parity == Parity.None ? 8 : 7;
StopBits stopBits = new StopBits();
stopBits = parity == Parity.None ? StopBits.One : StopBits.Two;
if (serialPort != null)
{
MessageBox.Show(this, "A COM port is already open in this wi
ndow!", "Ups!", MessageBoxButtons.OK, MessageBoxIcon.Asterisk);
return false;
}
try

{
serialPort = new SerialPort(szCOMPort, Int32.Parse(szBaudRat
e), parity, dataBits, stopBits);
System.Text.Encoding iso_8859_1 = System.Text.Encoding.GetEn
coding("iso-8859-1");
serialPort.Encoding = iso_8859_1;
serialPort.Open();
}
catch (Exception exc)
{
MessageBox.Show(this, "Could not open port!\n Exception was
thrown:\n" + exc.Message, "IO Error!", MessageBoxButtons.OK, MessageBoxIcon.Erro
r);
if(serialPort != null) if (serialPort.IsOpen) serialPort.Clos
e();
serialPort = null;
return false;
}
return true;
}
//apelata de SerialPort cand primeste date
//va invoca un alt eveniment deoarece SerialPort ruleazsa intr-un thread
propriu
private void OnSerialPort_DataReceived(object sender, SerialDataReceived
EventArgs e)
{
//apelata cand primesc date pe seriala - intr-un alt thread!!! - tre
buie invokata in threadul curent
//citesc datele
m_szSerialCommBuffer = serialPort.ReadExisting();
//apoi apelez un nou eveniment care sa trateze in threadul KST_Launc
her datele
this.Invoke(new EventHandler(OnDataReceived));
}
//invocata de OnSerialPort_DataReceived pentru a executa cod in threadul
propriu
private void OnDataReceived(object sender, EventArgs e)
{
char[] chArray = m_szSerialCommBuffer.ToCharArray();
//write to logfile
try
{
if (strLogFileName.Length > 0 && checkBoxLogToFile.Checked) File
.AppendAllText(strLogFileName, m_szSerialCommBuffer);
}
catch (Exception ee)
{
MessageBox.Show("Eroare la scriere logfile!", "Eroare!", Message
BoxButtons.OK, MessageBoxIcon.Error);
checkBoxLogToFile.Checked = false;
strLogFileName = "";
}
//do something with data
foreach (char ch in chArray) onSerialPortCharReceived(ch);
}

//apelata de OnDataReceived ca sa transmita ce a primit pe seriala char


cu char
private void onSerialPortCharReceived(char c)
{
if( !checkBoxFreezeUIReceive.Checked ) strReceivedCharsBetweenTicks
+= c;//update UI
//incrementez counterul de bytes receptionati
nReceivedBytes++;
//transmit datele mai departe in functie de protocol
if (checkBoxUseTokenProtocol.Enabled)
protocolT.onReceiveChar(c);
}
//used to close the serial port (called from another thread)
void CloseSerial()
{
try
{
serialPort.Close();
serialPort = null;
this.Invoke((MethodInvoker)delegate { this.buttonConnect.Enabled
= true; });
}
catch (Exception)
{
serialPort = null;
}
}
//pune o comanda in bufferul de transmisie, in functie de protocolul uti
lizat
public void SendCommandToEquipment(string cmd)
{
//UPDATE UI
//submit data to the protocol to handle it
if (checkBoxUseTokenProtocol.Enabled)
{
protocolT.writeCommand(cmd);
}
else
{
WriteCommandToEquipment(cmd);
}
}
//scrie efectiv pe portul serial
//returneaza true daca a trimis o comanda, false in caz contrar
//reprezinta punctul unic de iesire pe seriala
public bool WriteCommandToEquipment(string cmd)
{
strSentCharsBetweenTicks += cmd;
//adaug in bufferul de afisare tx doar daca nu folosesc un protocol
//daca folosesc un protocol adaug manual inainte de apelarea fun
ctiei acestea (pentru a nu afisa si caracterele suplimentare)
//write to logfile
try
{

if (strLogFileName.Length > 0 && checkBoxLogToFile.Checked) File


.AppendAllText(strLogFileName, cmd);
}
catch (Exception ee)
{
MessageBox.Show("Eroare la scriere logfile!", "Eroare!", Message
BoxButtons.OK, MessageBoxIcon.Error);
checkBoxLogToFile.Checked = false;
strLogFileName = "";
}
if (cmd != null)
{
//submit the command
try
{
//clear in/out buffers
serialPort.DiscardInBuffer();
serialPort.DiscardOutBuffer();
//write to the serial port
serialPort.Write(cmd);
//update sent bytes
nSentBytes += cmd.Length;
return true;
}
catch (Exception)
{
//daca au fost erori la transmis date schimb culoarea pe ros
u
MessageBox.Show(this, "Error while sending data!", "Error!",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
//nothing to submit!
}
return false;
}
#endregion
private void checkBoxUseTokenProtocol_CheckedChanged(object sender, Even
tArgs e)
{
if (checkBoxUseTokenProtocol.Checked) protocolT.clearRxBuffer();
}
}
}

Potrebbero piacerti anche