Receiving continuous data using 32feet in .Net (BLUETOOTH) - c#

I am creating a Windows Form application, where it is connecting to a device through bluetooth. I am able to send commands to the device and I am receiving the data continuously. The problem I am facing is that I am not able to show the continuous data in the text box. The text box only shows the first line of characters the application is receiving. Here is my code:
CONNECT BUTTON ACTION:
private void btnConnect_Click(object sender, EventArgs e)
{
if (listBox.SelectedItem != null)
{
lblProgress.Text = "";
btnStart.Enabled = true;
cBoxAvailablePorts.Enabled = cBoxAvailableBaudRates.Enabled = true;
try
{
int pos = listBox.SelectedIndex;
deviceInfo = array.ElementAt(pos);
if (pairDevice())
{
Thread thread = new Thread(() => connectThread());
thread.Start();
}
else
{
MessageBox.Show("Pair failed!");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
else
{
MessageBox.Show("Please connect to a device!");
}
}
THREAD ACTION
private void connectThread()
{
//BluetoothClient client = new BluetoothClient();
bc.BeginConnect(deviceInfo.DeviceAddress, serviceClass, this.connectCallBack, bc);
}
CALLBACK ACTION:
private void connectCallBack(IAsyncResult result)
{
//BluetoothClient client = (BluetoothClient)result.AsyncState;
try
{
if (bc.Connected)
{
MessageBox.Show("Connected!");
}
else
{
MessageBox.Show("Connection Failed!");
}
}
catch (Exception)
{
MessageBox.Show("Not able to identify Bluetooth devices! Please try again.!");
}
}
START BUTTON ACTION:
Here I send a command "S".
In button action I call sendMessage("S").
The function that is called is shown below:
public void sendMessage(string msg)
{
try
{
if (bc.Connected)
{
Stream stream = bc.GetStream();
stream.ReadTimeout = 1000;
StreamWriter streamWriter = new StreamWriter(stream);
streamWriter.WriteLine(msg);
streamWriter.Flush();
// Read operation
StreamReader streamReader = new StreamReader(stream);
string result = streamReader.ReadLine();
txtResult.Text = result;
}
else
{
MessageBox.Show("Sending failed!");
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
I wrote the StreamReader part in a loop, and it gave me Socket Exception.
I also tried to get the data from Serial Port and used DataReceived event just in case, but still it didn't help.
Any help would be appreciated.
Thank you!

OKAY! I solved the problem. Without getting in trouble with 32feet library (though it is fun to code with 32feet), I thought to make communication through serial port. I connected the device with my laptop and got to know the outgoing COMPORT in bluetooth setting of my laptop. The two-way communication can only be done through outgoing COMPORT, not the incoming COMPORT.
Suppose the outgoing COMPORT is COM12 and the baud rate that I have set is 9600.
So here is my code:
public delegate void updateDelegate(string text);
private updateDelegate objDelegate;
private SerialPort serialPort;
public View() // constructor
{
InitializeComponent();
this.WindowState = FormWindowState.Normal;
this.StartPosition = FormStartPosition.CenterScreen;
this.objDelegate = new updateDelegate(getText);
serialPort = new SerialPort("COM12", 9600);
serialPort.Handshake = Handshake.None;
serialPort.Parity = Parity.None;
serialPort.StopBits = StopBits.One;
serialPort.DtrEnable = true;
serialPort.RtsEnable = true;
}
START BUTTON ACTION
private void btnStart_Click(object sender, EventArgs e)
{
sendData("S");
}
// SEND COMMAND
public void sendData(string msg)
{
try
{
if (!serialPort.IsOpen)
{
serialPort.Open();
//serialPort.Close();
}
if (serialPort.IsOpen)
{
serialPort.Write(msg);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
// READ DATA
public void readData()
{
try
{
serialPort.DataReceived += SerialPort_DataReceived;
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
string res = serialPort.ReadExisting();
Thread.Sleep(500);
txtResult.Invoke(this.objDelegate, new object[] {res});
}
public void getText(string text)
{
txtResult.Text = text;
}
I hope this will help someone! Thank you!!!

Related

Reading Serial Data from Arduino in Windows Forms Application

I am currently trying to build a windows forms app that gets sensor data from an arduino via the serial com.
when checking in the arduino IDE the data gets writen into the serial port correctly.
But i can't figure out how to read the data via c#.
class Program
{
static SerialPort SP;
static void Main(string[] args)
{
SP = new SerialPort();
SP.PortName = "COM7";
SP.BaudRate = 9600;
SP.Handshake = System.IO.Ports.Handshake.RequestToSend;
SP.Open();
while (true)
{
Console.WriteLine(DateTime.Now.ToString() + " : " + SP.ReadLine());
}
}
}
My guess is that the Port is not properly set up, but i have no idea what i am missing.
The Goal is just to receive strings from the arduino, i do not necessarily need to send any data to the arduino.
edit: i am working with an arduino micro
Did you close Arduino IDE?
You need to add a wait code before reading from the port
Below is a working example:
private SerialPort _currentPort = new SerialPort("COM7", 9600);
private readonly object _sync = new object();
public bool Open()
{
_currentPort.Encoding = Encoding.UTF8;
_currentPort.DtrEnable = true;
_currentPort.ReadTimeout = 2000;
try
{
if (!_currentPort.IsOpen)
lock (_sync)
{
if (_currentPort.IsOpen)
return true;
_currentPort.Open();
System.Threading.Thread.Sleep(1500);
}
}
catch (Exception e)
{
//_localLogger?.Error($"{_currentPort.PortName}, {e.Message}", e);
return false;
}
return _currentPort.IsOpen;
}
public bool Subscribe()
{
try
{
if (Open())
{
_currentPort.DataReceived += CurrentPortOnDataReceived;
return true;
}
return false;
}
catch (Exception e)
{
//_localLogger?.Error($"{_currentPort.PortName}, {e.Message}", e);
return false;
}
}
private void CurrentPortOnDataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (!_currentPort.IsOpen)
{
//_localLogger.Info($"{_currentPort} is closed");
Open();
}
Console.WriteLine(_currentPort.ReadExisting());
}

TcpListener does not receive data

So my homework is to write a POP3 messaging software using tcp packets and im not allowed to use external libraries. I start the tcp connection when i press the Connect button and i also have a Disconnect button which stops it. I tested my server program with PuTTY and it works fine after the first connection but when i press Disconnect and Connect again it doesnt print the received data to the monitor. This problem is bothering me for ages please help. Here is my code:
Edit:
The problem was that i dont quite understand how threads work and i didnt create a new thread for each connection so i instantiated a new thread every time i created a new listener.
namespace POP3Server
{
public partial class MainWindow : Window
{
private TcpListener server;
private Int32 port;
private IPAddress ipAddress;
private TcpClient client;
private Logger log;
private Thread tcpAcceptThread;
private bool serverStarted;
public MainWindow()
{
InitializeComponent();
log = new Logger(txtConsole);
serverStarted = false;
tcpAcceptThread = new Thread(GetData);
}
private void btnConnect_Click(object sender, RoutedEventArgs e)
{
try
{
port = Convert.ToInt32(txtPort.Text);
ipAddress = IPAddress.Parse(txtIP.Text);
server = new TcpListener(ipAddress, port);
server.Start();
if (tcpAcceptThread.ThreadState != ThreadState.Unstarted)
tcpAcceptThread.Start();
serverStarted = true;
log.WriteLine("Server started!");
btnConnect.IsEnabled = false;
btnDisconnect.IsEnabled = true;
}
catch (Exception ex)
{
log.WriteLine(ex.ToString());
}
}
private void btnDisconnect_Click(object sender, RoutedEventArgs e)
{
try
{
if (client != null)
client.Close();
server.Stop();
log.WriteLine("Server stopped!");
serverStarted = false;
btnConnect.IsEnabled = true;
btnDisconnect.IsEnabled = false;
}
catch (Exception ex)
{
log.WriteLine(ex.ToString());
}
}
private void GetData()
{
try
{
while (serverStarted)
{
client = server.AcceptTcpClient();
this.Dispatcher.Invoke(() => log.WriteLine("Connected!"));
Byte[] bytes = new Byte[256];
String data = null;
NetworkStream stream = client.GetStream();
int i;
// Loop to receive all the data sent by the client.
while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
{
// Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
this.Dispatcher.Invoke(() => log.WriteLine("Received: " + data));
}
}
}
catch (Exception ex)
{
this.Dispatcher.Invoke(() => log.WriteLine(ex.ToString()));
}
}
private void btnClear_Click(object sender, RoutedEventArgs e)
{
log.Clear();
}
}
}
Could you change following code
private bool serverStarted;
to:
private object _someLockObject = new object();
private bool _serverStarted = false;
private bool serverStarted {
get {
lock (_someLockObject)
{
return _serverStarted;
}
}
set {
lock (_someLockObject)
{
_serverStarted = value;
}
}
};
My first hunch is boolean property is not updated.

A very simple TCP server/client in C# occasionally drops packets. What can I do to prevent this?

I've got an intra-PC communication server / client set up to send and receive data from one program to another - in this case, a custom server that is listening to text commands and Unity3D.
For the most part, it works, however every once in awhile, it will drop packets, and Unity will not get them without multiple attempts. The packets seem to be sent but lost, as I do see the "Sent message" console log. The following is the code for the server and client:
SERVER:
class TCPGameServer
{
public event EventHandler Error;
public Action<Data> ADelegate;
TcpListener TCPListener;
TcpClient TCPClient;
Client ActiveClient;
NetworkStream networkStream;
StreamWriter returnWriter;
StreamReader streamReader;
Timer SystemTimer = new Timer();
Timer PingTimer = new Timer();
int Port = 8637;
public TCPGameServer()
{
TCPListener = new TcpListener(IPAddress.Loopback, Port);
SystemTimer.Elapsed += StreamTimer_Tick;
SystemTimer.AutoReset = true;
SystemTimer.Interval = 2000;
PingTimer.Elapsed += PingTimer_Tick;
PingTimer.AutoReset = true;
PingTimer.Interval = 30000;
}
public void OpenListener()
{
TCPListener.Start();
TCPListener.BeginAcceptTcpClient(AcceptTCPCallBack, null);
Console.WriteLine("Network Open.");
}
public void GameLogout()
{
SystemTimer.AutoReset = false;
SystemTimer.Stop();
PingTimer.AutoReset = false;
PingTimer.Stop();
ActiveClient = null;
returnWriter.Dispose();
streamReader.Dispose();
Console.WriteLine("The client has logged out successfully.");
}
private void AcceptTCPCallBack(IAsyncResult asyncResult)
{
TCPClient = null;
ActiveClient = null;
returnWriter = null;
streamReader = null;
try
{
TCPClient = TCPListener.EndAcceptTcpClient(asyncResult);
TCPListener.BeginAcceptTcpClient(AcceptTCPCallBack, null);
ActiveClient = new Client(TCPClient);
networkStream = ActiveClient.NetworkStream;
returnWriter = new StreamWriter(TCPClient.GetStream());
streamReader = new StreamReader(TCPClient.GetStream());
Console.WriteLine("Client Connected Successfully.");
Data Packet = new Data();
Packet.cmdCommand = Command.Login;
Packet.strName = "Server";
Packet.strMessage = "LOGGEDIN";
SendMessage(Packet);
SystemTimer.AutoReset = true;
SystemTimer.Enabled = true;
SystemTimer.Start();
Ping();
PingTimer.AutoReset = true;
PingTimer.Enabled = true;
PingTimer.Start();
} catch (Exception ex)
{
OnError(TCPListener, ex);
return;
}
}
private void StreamTimer_Tick(object source, System.Timers.ElapsedEventArgs e)
{
CheckStream();
}
private void PingTimer_Tick(object source, System.Timers.ElapsedEventArgs e)
{
Ping();
}
private void Ping()
{
if (TCPClient.Connected)
{
Data Packet = new Data();
Packet.cmdCommand = Command.Ping;
Packet.strName = "Server";
Packet.strMessage = "PING";
SendMessage(Packet);
}
}
public void CheckStream()
{
try
{
if (TCPClient.Available > 0 || streamReader.Peek() >= 0)
{
string PacketString = streamReader.ReadLine();
Data packet = JsonConvert.DeserializeObject<Data>(PacketString);
switch (packet.cmdCommand)
{
case Command.Logout:
GameLogout();
break;
case Command.Message:
if (ADelegate != null)
{
ADelegate(packet);
}
break;
case Command.Ping:
Console.WriteLine("PONG!");
break;
}
}
} catch (IOException e)
{
Console.WriteLine(e.Message);
} catch (NullReferenceException e)
{
Console.WriteLine(e.Message);
}
}
public void SendMessage(Data packet)
{
if (ActiveClient != null)
{
string packetMessage = JsonConvert.SerializeObject(packet);
returnWriter.WriteLine(packetMessage);
returnWriter.Flush();
}
}
public void OnError(object sender, Exception ex)
{
EventHandler handler = Error;
if (handler != null)
{
ErrorEventArgs e = new ErrorEventArgs(ex);
handler(sender, e);
}
}
public void RegisterActionDelegate(Action<Data> RegisterDelegate)
{
ADelegate += RegisterDelegate;
}
public void UnRegisterActionDelegate(Action<Data> UnregisterDelegate)
{
ADelegate -= UnregisterDelegate;
}
}
CLIENT:
public class TCPNetworkClient
{
public Action<Data> PacketDelegate;
public TcpClient TCPClient;
int Port = 8637;
StreamReader streamReader;
StreamWriter streamWriter;
Timer StreamTimer = new Timer();
public bool LoggedIn = false;
public void Start()
{
if (LoggedIn == false)
{
TCPClient = null;
StreamTimer.AutoReset = true;
StreamTimer.Interval = 2000;
StreamTimer.Elapsed += StreamTimer_Tick;
try
{
TCPClient = new TcpClient("127.0.0.1", Port);
streamReader = new StreamReader(TCPClient.GetStream());
streamWriter = new StreamWriter(TCPClient.GetStream());
StreamTimer.Enabled = true;
StreamTimer.Start();
}
catch (Exception ex)
{
Debug.Log(ex.Message);
}
}
}
private void StreamTimer_Tick(System.Object source, System.Timers.ElapsedEventArgs e)
{
if (TCPClient.Available > 0 || streamReader.Peek() >= 0)
{
string PacketString = streamReader.ReadLine();
Data packet = JsonConvert.DeserializeObject<Data>(PacketString);
PacketDelegate(packet);
}
}
public void Logout()
{
Data Packet = new Data();
Packet.cmdCommand = Command.Logout;
Packet.strMessage = "LOGOUT";
Packet.strName = "Game";
SendMessage(Packet);
if (streamReader != null && streamWriter != null)
{
streamReader.Dispose();
streamWriter.Dispose();
TCPClient.Close();
TCPClient = null;
streamReader = null;
streamWriter = null;
}
StreamTimer.Stop();
}
public void SendMessage(Data packet)
{
string packetMessage = JsonConvert.SerializeObject(packet);
try
{
streamWriter.WriteLine(packetMessage);
streamWriter.Flush();
} catch (Exception e)
{
}
}
public void RegisterActionDelegate(Action<Data> RegisterDelegate)
{
PacketDelegate += RegisterDelegate;
}
public void UnRegisterActionDelegate(Action<Data> UnregisterDelegate)
{
PacketDelegate -= UnregisterDelegate;
}
}
I'm not really sure what's going on, or if there are any more additional checks that I need to add into the system. Note: It's TCP so that "when" this fully works, I can drop the client into other programs that I might write that may not fully rely or use Unity.
new TcpClient("127.0.0.1", Port) is not appropriate for the client. Just use TcpClient(). There is no need to specify IP and port, both of which will end up being wrong.
TCPClient.Available is almost always a bug. You seem to assume that TCP is packet based. You can't test whether a full message is incoming or not. TCP only offers a boundaryless stream of bytes. Therefore, this Available check does not tell you if a whole line is available. Also, there could be multiple lines. The correct way to read is to have a reading loop always running and simply reading lines without checking. Any line that arrives will be processed that way. No need for timers etc.
The server has the same problems.
Issue (2) might have caused the appearance of lost packets somehow. You need to fix this in any case.

C# COM port not disposed

this is my first interaction here! I'm learning C# by myself, there will be a lot of errors beside to the bug i'm trying to get rid of, please be patient :)
I'm developing a very basic app that let you interact with serial ports, something like the tool integrated in Arduino.
There is a button that is meant to Connect/Disconnect, it lanches/stops a Backgroundworker that keeps the form updated with new data. I've tryed to move .close(); every where in the code, but nothing changed, when I try to open it again it catches the Exception. And other apps con't access too. I think that I simply don't know what I'm doing :)
Can you help me releasing the resource?
The code involved in this operation:
private void ConnectB_Click(object sender, EventArgs e)
{
if (!connected)
{
int baud = Convert.ToInt32(baudRate.SelectedItem.ToString());
COMport = new SerialPort(COMpick.SelectedItem.ToString(), baud, Parity.None, 8, StopBits.One);
try
{
COMport.Open();
connected = true;
ConnectB.Text = "Disconnect";
}
catch (ArgumentOutOfRangeException)
{
MessageBox.Show("Baud rate not valid.");
connected = false;
}
catch (ArgumentException)
{
MessageBox.Show("Port name not valid.");
connected = false;
}
catch (UnauthorizedAccessException)
{
MessageBox.Show("Access denied, try close applications that may using the port.");
connected = false;
}
if (backWorker.IsBusy != true)
{
backWorker.RunWorkerAsync();
}
}
else
{
connected = false;
backWorker.CancelAsync();
ConnectB.Text = "Connect";
}
}
private void backWorker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
while (true)
{
if (worker.CancellationPending == true)
{
e.Cancel = true;
break;
}
else if(COMport.IsOpen)
{
// Get data and print it in the form
try
{
inbox = COMport.ReadLine() + '\n';
}
catch (InvalidOperationException) { }
//Scroll down the form, passing something useless to make it work
worker.ReportProgress(inbox.Length);
}
}
}
private void backWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
this.COMport.Close();
this.COMport.Dispose();
}
Thank you!

.Net- Action<T> Delegate error?

i am using Action<T> Delegate to make a link between class and Form. the class connects to serial port and data received is displayed in the form. the Action<T> Delegate encapsulates a method in the Form that displays the data received. but the delegate is always showing null, does not encapsulate the method.
the class code is :
public SerialPort mySerialPort;
public Action<byte[]> DataReceived_Del; //delegate for data recieved
public string connect()
{
try
{
mySerialPort = new SerialPort("COM14");
mySerialPort.BaudRate = 115200;
mySerialPort.DataBits = 8;
mySerialPort.Parity = System.IO.Ports.Parity.None;
mySerialPort.StopBits = System.IO.Ports.StopBits.One;
mySerialPort.RtsEnable = false;
mySerialPort.DataReceived += mySerialPort_DataReceived;
mySerialPort.Open();
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message);
}
if (mySerialPort.IsOpen)
{
return "Connected";
}
else
{
return "Disconnected";
}
}
//serial port data recieved handler
public void mySerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
try
{
//no. of data at the port
int ByteToRead = mySerialPort.BytesToRead;
//create array to store buffer data
byte[] inputData = new byte[ByteToRead];
//read the data and store
mySerialPort.Read(inputData, 0, ByteToRead);
var copy = DataReceived_Del;
if (copy != null) copy(inputData);
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message, "Data Received Event");
}
}
in the form we display the data:
public Form1()
{
InitializeComponent();
Processes newprocess = new Processes();
newprocess.DataReceived_Del += Display;
}
//Display
public void Display(byte[] inputData)
{
try
{
Invoke(new Action(() => TboxDisp.AppendText((BitConverter.ToString(inputData)))));
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message, "Display section");
}
}
the DataReceived_Del supposed to encapsulate the method Display, but it is NULL.
I can't see what is happening..
Any help is appreciated..
you should define newprocess outside the constructor , may this will resolve the
Processes newprocess;
public Form1()
{
InitializeComponent();
newprocess = new Processes();
newprocess.DataReceived_Del += Display;
}
You are using += to add to the delegate, but the delegate is NULL to begin with. I'm not sure that will work. I would try = instead of +=.
public Form1() {
InitializeComponent();
Processes newprocess = new Processes();
newprocess.DataReceived_Del = Display;
}

Categories

Resources