I am working on this GUI for serial port application. I recently added stop and wait protocols to the application. Surprisingly my disconnect button stopped working. I have thought through the logic and I have not been able to find the problem.
namespace WindowsFormsApplication5
{
public partial class Form1 : Form
{
public bool packetreceived = false;
private SerialPort sp = null; //<---- serial port at form level
public delegate void AddDataDelegate(String myString);
public AddDataDelegate myDelegate;
//delegate variable to disconnect
public AddDataDelegate disconnectDelegate = null;
public void AddDataMethod(String myString)
{
richTextBox1.AppendText(myString);
}
/**
* Takes byte array and returns a string representation
*
*/
public String parseUARTData(byte[] data)
{
if (data.Length == 11)
{
String rv = "";
DataFields d = new DataFields();
if (!packetreceived)
{
d = mainLogic.parseData(data);
packetreceived = true;
}
//TODO
System.Threading.Thread.Sleep(5000);
if (d.sequence == 0)
{
sp.Write("1\r\n");
}
else
{
sp.Write("0\r\n");
}
packetreceived = false;
//now display it as a string
rv += STR_OPCODE + " = " + d.opcode + "\n";
rv += STR_CRC + " = " + d.crc + "\n";
rv += STR_SEQ + " = " + d.sequence + "\n";
rv += STR_FLAGS + " = " + d.flags + "\n";
rv += STR_TEMP + " = " + d.temperature + "\n";
rv += STR_HUMID + " = " + d.humidity + "\n";
rv += STR_PH + " = " + d.ph + "\n";
return rv + "\n\n";
}
else
{
return Encoding.ASCII.GetString(data);
}
}
private void sp_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
SerialPort sp = (SerialPort)sender;
string s = sp.ReadExisting();
if (disconnectDelegate != null)
{
disconnectDelegate.Invoke(s);
}
richTextBox1.Invoke(this.myDelegate, new Object[] { parseUARTData(Encoding.ASCII.GetBytes(s)) });
}
private void button1_Click(object sender, EventArgs e)
{
connect.Enabled = false;
try
{
// open port if not already open
// Note: exception occurs if Open when already open.
if (!sp.IsOpen)
{
//sp.PortName = this.comboBox1.SelectedItem.ToString();
sp.Open();
}
// send data to port
sp.Write("####,###########\r\n");
disconnect.Enabled = true;
}
catch (Exception)
{
// report exception to user
Console.WriteLine(e.ToString());
}
}
private void button2_Click(object sender, EventArgs e)
{
connect.Enabled = true;
try
{
// open port if not already open
// Note: exception occurs if Open when already open.
if (sp.IsOpen)
{
// send data to port
sp.Write("+++\r\n");
//add the delegate
disconnectDelegate = new AddDataDelegate(onDisconnect);
//sp.WriteTimeout = 500;
// sp.Write("####,0\r\n");
}
}
catch (Exception)
{
Console.WriteLine(e.ToString());
}
finally
{
disconnect.Enabled = false;
}
}
public void OnApplicationExit(object sender, EventArgs e)
{
sp.Close();
}
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
//foreach (string port in ports)
//{
// comboBoxSerialPorts.Items.Add(port);
//}
}
private void onDisconnect(string msg)
{
string trimmedMsg = msg.Trim();
if (trimmedMsg.Equals("OK"))
{
//send the second time
sp.Write("##,0\r\n");
//null the object
disconnectDelegate = null;
}
}
private void comPort_Click(object sender, EventArgs e)
{
try
{
if (sp.IsOpen)
{
//send data to port
sp.Write("1\r\n");
MessageBox.Show("bluetooth is transmitting data...");
//message box telling user that you are asking for data.
}
}
catch (Exception)
{
// report exception to user
Console.WriteLine(e.ToString());
}
}
Related
Using visual studios Windows forms on c#, I'm making a chatprogram with unlimited clients and one server. The server has to be activated before I connect any client. However, after connecting one or more clients and closing one of them, the server crashes. I can nor close it or send any data from my clients to it without getting an error. The CPU usage of my computer rises to 50% during the crash. After I manage to close the server through task manager, different code lines are highlighted, indicating the error.
Here's my server code:
namespace TCPa
{ // skapar en lista med tcp clients
// säg till så att send funktioner tar tcp clients som input i
metoderna och referera till metoderna
// och loopa genom listan, som kallar metoden i lista.
public partial class Server : Form
{
TcpClient klient = null;
List<TcpClient> klientLista = new List<TcpClient>();
TcpListener lyssnare;
int port = 0;
public Server()
{
InitializeComponent();
}
private void btnTaEmot_Click(object sender, EventArgs e)
{
try
{
port = int.Parse(tbxPort.Text);
if (port >= 1024 && port <= 65535)
{
les(port);
}
else
{
MessageBox.Show("Skriv in ett giltigt portnummer mellan 1024 och 65535");
}
}
catch (Exception)
{
MessageBox.Show("Skriv in ett giltigt portnummer mellan 1024 och 65535");
}
}
public void les(int portT)
{
btnTaEmot.Enabled = false;
tbxPort.Enabled = false;
try
{
lyssnare = new TcpListener(IPAddress.Any, portT);
lyssnare.Start();
}
catch (Exception error)
{
MessageBox.Show(error.Message, Text);
return;
}
StartAccepting();
}
public async void StartAccepting()
{
try
{
klient = await lyssnare.AcceptTcpClientAsync();
klientLista.Add(klient);
}
catch (Exception error)
{
MessageBox.Show(error.Message, Text);
return;
}
StartReading(klient);
StartAccepting();
}
public async void StartReading(TcpClient k)
{
byte[] buffer = new byte[1024];
int n = 0;
try
{
///NEW
n = await k.GetStream().ReadAsync(buffer, 0, 1024);
if (n <= 0)
{
klient.Close();
}
////NEW
}
catch (Exception error)
{
MessageBox.Show(error.Message, Text);
return;
}
StartSending(k, Encoding.Unicode.GetString(buffer, 0, n));
tbxLogg.AppendText(Encoding.Unicode.GetString(buffer, 0, n));
StartReading(k);
}
public async void StartSending(TcpClient klientSomSkickar, string message)
{
if (klientLista.Count > 0)
{
byte[] utData = Encoding.Unicode.GetBytes(message);
foreach (TcpClient klient in klientLista)
{
try
{
if (klient != klientSomSkickar)
{
await klient.GetStream().WriteAsync(utData, 0, utData.Length);
}
}
catch (Exception error)
{
MessageBox.Show(error.Message, Text); return;
}
}
}
}
private void Server_FormClosing(object sender, FormClosingEventArgs e)
{
lyssnare.Stop();
if (klient != null && klient.Connected)
{
klient.Close();
}
}
}
}
Here's my client code
namespace Klient
{
public partial class Klient : Form
{
TcpClient klient = new TcpClient();
public Klient()
{
InitializeComponent();
btnSend.Enabled = false;
}
private void btnAnslut_Click(object sender, EventArgs e)
{
Connect();
}
private async void Connect()
{
IPAddress adress = IPAddress.Parse(tbxIP.Text);
int port = int.Parse(tbxPort.Text);
try
{
await klient.ConnectAsync(adress, port);
}
catch (Exception error)
{
MessageBox.Show(error.Message, Text);
return;
}
if (klient.Connected)
{
btnAnslut.Enabled = false;
btnSend.Enabled = true;
tbxNmn.Enabled = false;
tbxMedd.Focus();
}
StartReading(klient);
}
private async void btnSend_Click(object sender, EventArgs e)
{
if (klient.Connected)
{
string namn = tbxNmn.Text;
string tid = DateTime.Now.ToString("HH:mm tt");
if (String.IsNullOrEmpty(tbxMedd.Text) || String.IsNullOrWhiteSpace(tbxMedd.Text))
{
MessageBox.Show("Skriv in ditt meddelande");
}
else
{
byte[] utData = Encoding.Unicode.GetBytes("<" + " " + namn + " " + ">" + " " + tid + ":" + "\t" + tbxMedd.Text + "\r\n");
try
{
tbxLogg.AppendText("<" + " " + namn + " " + ">" + " " + tid + ":" + "\t" + tbxMedd.Text + "\r\n");
await klient.GetStream().WriteAsync(utData, 0, utData.Length);
}
catch (Exception error)
{
MessageBox.Show(error.Message, Text);
return;
}
}
}
tbxMedd.Clear();
}
public async void StartReading(TcpClient k)
{
byte[] buffer = new byte[1024];
int n = 0;
try
{
n = await k.GetStream().ReadAsync(buffer, 0, 1024);
}
catch (Exception error)
{
MessageBox.Show(error.Message, Text);
return;
}
tbxLogg.AppendText(Encoding.Unicode.GetString(buffer, 0, n));
StartReading(k);
}
private void Klient_FormClosing(object sender, FormClosingEventArgs e)
{
if (klient != null)
klient.Close();
}
}
}
Any help is appreciated!!
I'm developing a sample program to connect multiple device using backgroundworker. Each device connected will be add to the list as new object. After finished connecting all the devices, i wanted to add an event handler for each connected devices. The problem that i'm facing now is the event handler doesn't firing at all. Below are the sample codes.
The Connect click button event :
private void btnConnect_Click(object sender, EventArgs e)
{
using (BackgroundWorker m_oWorker = new BackgroundWorker())
{
m_oWorker.DoWork += delegate (object s, DoWorkEventArgs args)
{
int iIpStart = 0;
int iIpEnd = 0;
string strIp1 = string.Empty;
string strIp2 = string.Empty;
list.Clear();
string[] sIP1 = txtIpStart.Text.Trim().ToString().Split('.');
string[] sIP2 = txtIpEnd.Text.Trim().ToString().Split('.');
iIpStart = Convert.ToInt32(sIP1[3]);
iIpEnd = Convert.ToInt32(sIP2[3]);
strIp1 = sIP1[0] + "." + sIP1[1] + "." + sIP1[2] + ".";
strIp2 = sIP2[0] + "." + sIP2[1] + "." + sIP2[2] + ".";
Ping ping = new Ping();
PingReply reply = null;
int iIncre = 0;
int iVal = (100 / (iIpEnd - iIpStart));
for (int i = iIpStart; i <= iIpEnd; i++)
{
Thread.Sleep(100);
string strIpconnect = strIp1 + i.ToString();
Console.Write("ip address : " + strIpconnect + ", status: ");
reply = ping.Send(strIpconnect);
if (reply.Status.ToString() == "Success")
{
if (ConnectDevice(strIpconnect))
{
strLastDevice = strIpconnect + " Connected";
isconnected = true;
}
else
{
isconnected = false;
}
}
else
{
isconnected = false;
}
m_oWorker.ReportProgress(iIncre);
iIncre = iIncre + iVal;
}
m_oWorker.ReportProgress(100);
};
m_oWorker.ProgressChanged += new ProgressChangedEventHandler(m_oWorker_ProgressChanged);
m_oWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(m_oWorker_RunWorkerCompleted);
m_oWorker.WorkerReportsProgress = true;
m_oWorker.WorkerSupportsCancellation = true;
m_oWorker.RunWorkerAsync();
}
}
ConnectDevice function method. Connected device will be added to the list :
protected bool ConnectDevice(string sIP)
{
try
{
NewSDK sdk = new NewSDK();
if (sdk.Connect() == true)
{
list.Add(new objSDK { sdk = sdk, ipaddress = sIP });
return true;
}
else
{
}
}
catch() {}
return false;
}
the Backgroundworker :
void m_oWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//If it was cancelled midway
if (e.Cancelled)
{
lblStatus.Text = "Task Cancelled.";
}
else if (e.Error != null)
{
lblStatus.Text = "Error while performing background operation.";
}
else
{
lblStatus.Text = "Task Completed...";
btnListen.Enabled = true;
}
}
void m_oWorker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
//Here you play with the main UI thread
progressBar1.Value = e.ProgressPercentage;
lblStatus.Text = "Processing......" + progressBar1.Value.ToString() + "%";
if (isconnected)
{
listBox2.Items.Add(strLastDevice);
string[] ssplit = sDeviceInfo.Split(';');
foreach (string sword in ssplit)
{
listBox1.Items.Add(sword);
}
}
}
The function to attached event :
private void RegisterEvent()
{
foreach (objSDK obj in list)
{
obj.sdk.OnTransaction += () =>
{
listBox1.Items.Add("ip : " + obj.IP + " transaction");
};
}
}
You have declared m_oWorker as a local variable. I'm guessing this was a mistake ( the m_ prefix should only be used for class member variables)?
Also, you declared it within a using statement, meaning that it that the framework will call Dispose() on it at the end of the using block. Even if you held on to a reference to it (and I don't think you do) it still means its resources will be deallocated, which is probably why it isn't handling any events.
I try another workaround by using thread and task and work perfectly. Thanks for all response
Halllo
I have made my first project and it works, well sort of, I can not get it to close serial port.
I am running 200hz in the Serialmonitor and the save funktion works perfect.
I suspect that it attempts to read data while I am trying to close the port.
It does not come up with an error but hanging in the debugger trying to close the port.
MY CODE IN VISUAL STUDIO 2015:
using System;
using System.Windows.Forms;
using System.IO.Ports;
namespace Arduino_Serial
{
public partial class Form1 : Form
{
private SerialPort myport;
private DateTime datetime;
private string in_data1;
private int runtime_sec = 0;
private float runtime_milis = 0;
public Form1()
{
InitializeComponent();
}
private void Start_Click_1(object sender, EventArgs e)
{
myport = new SerialPort();
myport.BaudRate = 115200;
myport.PortName = Port_name_tb.Text;
myport.Parity = Parity.None;
myport.DataBits = 8;
myport.StopBits = StopBits.One;
myport.DataReceived += Myport_DataReceived;
try
{
myport.Open();
timer2.Enabled = true;
timer1.Enabled = true;
Data_tb.Text = "\"Arduino\"" + "\n";
Data_tb.AppendText("Time" + "\t" + "Raw_data" + "\t" + "MAP" + "\n");
Data_tb.AppendText("Sec " + "\t" + "Raw_data" + "\t" + "KPA" + "\n");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error");
}
}
void Myport_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
in_data1 = myport.ReadLine();
Invoke(new EventHandler(displaydata_event));
}
private void displaydata_event(object sender, EventArgs e)
{
datetime = DateTime.Now;
string time = datetime.Hour + ":" + datetime.Minute + ":" + datetime.Second;
Data_tb.AppendText(("\n")+ (runtime_milis) + ("\t")+ in_data1 );
}
private void Stop_bt_Click(object sender, EventArgs e)
{
try
{
myport.ReadTimeout = 1000000000;
myport.Close();
timer2.Enabled = false;
timer1.Enabled = false;
runtime_milis = 0;
runtime_sec = 0;
}
catch (Exception ex2)
{
MessageBox.Show(ex2.Message, "Error");
}
}
private void Save_bt_Click(object sender, EventArgs e)
{
try
{
datetime = DateTime.Now;
String time = datetime.Year + "-"+ datetime.Month + "-"+ datetime.Day + "_" + datetime.Hour + "." + datetime.Minute + "." + datetime.Second;
string pathfile = #"C:\DATA\";
string filename = "Arduino_" + time + ".msl";
System.IO.File.WriteAllText(pathfile + filename, Data_tb.Text);
MessageBox.Show("Data has been saved");
Close();
}
catch (Exception ex3)
{
MessageBox.Show(ex3.Message, "Error");
}
}
private void timer1_Tick(object sender, EventArgs e)
{
runtime_sec++;
}
private void timer2_Tick(object sender, EventArgs e)
{
runtime_milis++;
}
}
}
Basically I need to communicate with a COM serial printer. There are 2 timers, one will print one ticket at time, and the others will hang up checking for errors and resuming the printing when the errors are gone.
For example: Printer is printing but if I press the pause button an error (read in the buffer) will get some booleans to 1 and after I read them I am able to tell what the error is and stop the printing.
My problem is in the method ErrorTimer_Elapsed() which is the timer elapsed event and probably is linked to the ErrorCheck and SendToCom (which is the printing method). The problem is that program detects errors well, but when in ErrorTimer_Elapsed() I try to repeatdly check for error status changes, I get IO errors like:
-Can't acces COM PORT
-The resource you required is in use
and so on.
Can you help me? Thanks, here's the code (about 180 lines), I'm bumping my head on this since 3 days :( :
using System;
using System.Collections;
using System.Configuration;
using System.IO;
using System.IO.Ports;
using System.Windows.Forms;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
#region Variabili di istanza
private ArrayList _filesToPrint = new ArrayList();
private static SerialPort _serialPort1 = new SerialPort();
private string _portName = ConfigurationSettings.AppSettings["COM"];
private string FilesPath = ConfigurationSettings.AppSettings["Path"];
private System.Timers.Timer PrintTimer = new System.Timers.Timer(2000);
private System.Timers.Timer ErrorTimer = new System.Timers.Timer(3500);
private bool PrintTimerIsActive = true;
private string HsCOMerrorStrings, PrintErrors;
#endregion
public Form1()
{
_serialPort1.PortName = _portName;
_serialPort1.ReadTimeout = 1000;
_IfFileExistsPrint();
}
private void _IfFileExistsPrint()
{
foreach (string file in Directory.GetFiles(FilesPath))
_filesToPrint.Add(file);
FileSystemWatcher SysWatch = new FileSystemWatcher(FilesPath, "*.*");
SysWatch.Created += new FileSystemEventHandler(SysWatch_Created);
SysWatch.EnableRaisingEvents = true;
PrintTimer.Elapsed += new System.Timers.ElapsedEventHandler(Timer_Elapsed);
PrintTimer.Start();
ErrorTimer.Elapsed += new System.Timers.ElapsedEventHandler(ErrorTimer_Elapsed);
}
private void SysWatch_Created(object Sender, FileSystemEventArgs w)
{
_filesToPrint.Add(w.FullPath);
}
private void Timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if (_filesToPrint.Count > 0 && PrintTimerIsActive)
{
PrintTimer.Stop();
SendFilesToCom(_filesToPrint[0].ToString());
MessageBox.Show("Printing file :" + _filesToPrint[0].ToString());
File.Delete(_filesToPrint[0].ToString());
_filesToPrint.RemoveAt(0);
_filesToPrint.TrimToSize();
Console.Write(HsCOMerrorStrings);
PrintTimer.Start();
PrintErrors = ErrorCheck(HsCOMerrorStrings);
}
}
private void ErrorTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs d)
{
if (!_serialPort1.IsOpen)
{
try
{
_serialPort1.Open();
}
catch (Exception ex)
{
Console.WriteLine(ex.Data);
}
}
try
{
HsCOMerrorStrings = _serialPort1.ReadExisting();
_serialPort1.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.Data);
}
Console.WriteLine(ErrorCheck(HsCOMerrorStrings));
}
private string ErrorCheck(string COMHostStatusReturn)
{
string ErrorsReturn = System.String.Empty;
string[] COMCode = COMHostStatusReturn.Split(',');
if (COMCode[1] == "1") { ErrorsReturn += "Carta Esaurita" + Environment.NewLine; }
if (COMCode[2] == "1") { ErrorsReturn += "Stampante in Pausa" + Environment.NewLine; }
if (COMCode[5] == "1") { ErrorsReturn += "Memoria Stampante Esaurita" + Environment.NewLine; }
if (COMCode[9] == "1") { ErrorsReturn += "Memoria RAM corrotta" + Environment.NewLine; }
if (COMCode[10] == "1") { ErrorsReturn += "Temperatura troppo bassa" + Environment.NewLine; }
if (COMCode[11] == "1") { ErrorsReturn += "Temperatura troppo alta" + Environment.NewLine; }
if (COMCode[7] == "1") { ErrorsReturn += "Partial Format Flag" + Environment.NewLine; }
if (ErrorsReturn != System.String.Empty)
{
if (PrintTimerIsActive == true)
{
PrintTimer.Stop();
if (!ErrorTimer.Enabled)
ErrorTimer.Start();
MessageBox.Show(ErrorsReturn);
}
PrintTimerIsActive = false;
}
else
{
if (PrintTimerIsActive == false)
{
ErrorTimer.Stop();
PrintTimer.Start();
PrintTimerIsActive = true;
}
}
return ErrorsReturn;
}
private void SendFilesToCom(string filePath)
{
if (!_serialPort1.IsOpen)
{
try
{
_serialPort1.Open();
}
catch (Exception ex)
{
}
}
try
{
using (System.IO.TextReader reader = File.OpenText(filePath))
{
string line;
while ((line = reader.ReadLine()) != null)
{
_serialPort1.WriteLine(line);
}
HsCOMerrorStrings = _serialPort1.ReadLine();
reader.Close();
_serialPort1.Close();
}
}
catch (Exception ex)
{
}
}
}
}
I am trying to build a simply app that returns the number calling via a modem, however I only seem to be getting the first line of the data received from the modem.
When I run HyperTerminal and pass through the AT#CID=1 command, ring the number, I get a full output of :
OK
DATE=0314
TIME=1111
NMBR=4936
NAME=Stuart E
RING
In my app i only seem to receive the first section containing the "OK" part. Any help on what i am doing wrong or am missing?
Code:
public partial class Form1 : Form
{
public SerialPort port = new SerialPort("COM3", 115200,Parity.None,8,StopBits.One);
public String sReadData = "";
public String sNumberRead = "";
public String sData = "AT#CID=1";
public Form1()
{
InitializeComponent();
}
private void btnRun_Click(object sender, EventArgs e)
{
SetModem();
ReadModem();
MessageBox.Show(sReadData);
}
public void SetModem()
{
if (port.IsOpen == false)
{
port.Open();
}
port.WriteLine(sData + System.Environment.NewLine);
port.BaudRate = iBaudRate;
port.DtrEnable = true;
port.RtsEnable = true;
}
public string ReadModem()
{
try
{
sReadData = port.ReadExisting().ToString();
return (sReadData);
}
catch (Exception ex)
{
String errorMessage;
errorMessage = "Error in Reading: ";
errorMessage = String.Concat(errorMessage, ex.Message);
errorMessage = String.Concat(errorMessage, " Line: ");
errorMessage = String.Concat(errorMessage, ex.Source);
MessageBox.Show(errorMessage, "Error");
return "";
}
}
private void btnExit_Click(object sender, EventArgs e)
{
port.Close();
Close();
}
}
}
In ReadModem() try to use port.ReadLine() in a loop instead and loop until you get a line saying RING (if that is the final line you are expecting).
You are just reading the Modem once after setting it. You need to subscribe the DataReceivedEvent on serialPort to continuously get data from the port.
public void SetModem()
{
if (port.IsOpen == false)
{
port.Open();
}
port.WriteLine(sData + System.Environment.NewLine);
port.BaudRate = iBaudRate;
port.DtrEnable = true;
port.RtsEnable = true;
port.DataReceived += port_DataReceived;
}
void port_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
//For e.g. display your incoming data in RichTextBox
richTextBox1.Text += this.serialPort1.ReadLine();
//OR
ReadModem();
}