Cannot read data from Arduino bluetooth serial data in WinRT - c#

I am using Arduino UNO connected with bluetooth module. I have this below code in Arduino, which listen to specific input and glow the LED.
int LED= 13;
char input;
void setup()
{
Serial.begin(9600);
pinMode(LED, OUTPUT);
Serial.println(">> START<<");
Serial.flush();
}
void loop()
{
Serial.flush();
if(Serial.available()>0)
{
input= Serial.read();
if(input=='1')
{
Serial.write(1);
Serial.println('a');
digitalWrite(LED, HIGH);
}
else if(input=='0')
{
Serial.println("OFF");
digitalWrite(LED, LOW);
}
else
{
Serial.println("NO INPUT");
Serial.println(input);
}
}
}
From Windows 8.1 (XAML/C#) application I am sending data through bluetooth. And it works perfectly as expected. But I am also trying to read data from Arduino. For that I have below code in C#.
socket = new StreamSocket();
connectAction = socket.ConnectAsync(rfcommService.ConnectionHostName, rfcommService.ConnectionServiceName, SocketProtectionLevel.BluetoothEncryptionAllowNullAuthentication);
await connectAction;//to make it cancellable
writer = new DataWriter(socket.OutputStream);
reader = new DataReader(socket.InputStream);
Task.Run(() =>
{
ListenForMessagesAsync();
});
The ListenForMessagesAsync method supposed to keep listening the dataReader. But it just waiting for infinite time and never returns.
private async Task ListenForMessagesAsync()
{
while (reader != null)
{
try
{
uint sizeFieldCount = await reader.LoadAsync(1);// taskLoadLength.GetResults();
if (sizeFieldCount != 1)
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Read the message.
uint messageLength = reader.ReadByte();
uint actualMessageLength = await reader.LoadAsync(messageLength);
if (messageLength != actualMessageLength)
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Read the message and process it.
string message = reader.ReadString(actualMessageLength);
}
catch (Exception ex)
{
}
}
}
What am I doing wrong here?

You need a return after a successful ReadString and of course you need to do something with the message.

Related

UWP TCP receive data continuously

I've programmed a TCP server application where I can listen to incoming connections on a dedicated port. With this I'm able to get an "connected" event and then receive data (only once).
How can I receive data continuously from the port (and maybe also detect if the client is still connected)?
I've connected a NodeMCU (Arduino based) system which sends some temperature data every second using the TCP connection.
Starting and stopping the server through a toggle switch in the UI:
public async Task<bool> StartListeningAsync()
{
if (TCPSocket == null)
{
TCPSocket = new StreamSocketListener();
TCPSocket.ConnectionReceived += LocalSocketConnectionReceived;
await TCPSocket.BindServiceNameAsync(CommunicationPort);
return true;
}
return false;
}
public async Task<bool> StopListening()
{
if (connectedSocket != null)
{
connectedSocket.Dispose();
connectedSocket = null;
}
if (TCPSocket != null)
{
await TCPSocket.CancelIOAsync();
TCPSocket.ConnectionReceived -= LocalSocketConnectionReceived;
TCPSocket.Dispose();
TCPSocket = null;
return true;
}
return false;
}
Event that handles a new connection and receive data:
private async void LocalSocketConnectionReceived(StreamSocketListener sender, StreamSocketListenerConnectionReceivedEventArgs args)
{
if (connectedSocket != null)
{
connectedSocket.Dispose();
connectedSocket = null;
}
connectedSocket = args.Socket;
await textBox_send.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, () =>
{
textBox_send.IsEnabled = true;
txtConnected.Text = "Client Connected";
});
using (var reader = new DataReader(args.Socket.InputStream))
{
await readTCPDataAsync(reader);
}
}
private async Task readTCPDataAsync(DataReader reader)
{
reader.InputStreamOptions = InputStreamOptions.None;
// Read the length of the payload that will be received.
byte[] payloadSize = new byte[(uint)BitConverter.GetBytes(0).Length];
await reader.LoadAsync((uint)payloadSize.Length);
reader.ReadBytes(payloadSize);
// Read the payload.
int size = BitConverter.ToInt32(payloadSize, 0);
//size = 2;
byte[] payload = new byte[size];
await reader.LoadAsync((uint)size);
reader.ReadBytes(payload);
string data = Encoding.ASCII.GetString(payload);
}
This code works perfectly to receive the data once the connection is established.
I'm thinking of a solution to get an event once new data is on the input buffer and then process the data.
I'm thinking of a solution to get an event once new data is on the input buffer and then process the data.
There is no such event in UWP API that can be triggered at each time a new date is received. What we usually do here is using a while loop to receive data continuously. For example, you can add a while loop in your LocalSocketConnectionReceived method like the following:
using (var reader = new DataReader(args.Socket.InputStream))
{
while (true)
{
await readTCPDataAsync(reader);
}
}
The while loop works here because Data​Reader.LoadAsync(UInt32) is a asynchronous method. It will wait there if there is no date received.
For more info, please refer to the StreamSocket sample on GitHub, especially the OnConnection method in Scenario 1.
/// <summary>
/// Invoked once a connection is accepted by StreamSocketListener.
/// </summary>
/// <param name="sender">The listener that accepted the connection.</param>
/// <param name="args">Parameters associated with the accepted connection.</param>
private async void OnConnection(
StreamSocketListener sender,
StreamSocketListenerConnectionReceivedEventArgs args)
{
DataReader reader = new DataReader(args.Socket.InputStream);
try
{
while (true)
{
// Read first 4 bytes (length of the subsequent string).
uint sizeFieldCount = await reader.LoadAsync(sizeof(uint));
if (sizeFieldCount != sizeof(uint))
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Read the string.
uint stringLength = reader.ReadUInt32();
uint actualStringLength = await reader.LoadAsync(stringLength);
if (stringLength != actualStringLength)
{
// The underlying socket was closed before we were able to read the whole data.
return;
}
// Display the string on the screen. The event is invoked on a non-UI thread, so we need to marshal
// the text back to the UI thread.
NotifyUserFromAsyncThread(
String.Format("Received data: \"{0}\"", reader.ReadString(actualStringLength)),
NotifyType.StatusMessage);
}
}
catch (Exception exception)
{
// If this is an unknown status it means that the error is fatal and retry will likely fail.
if (SocketError.GetStatus(exception.HResult) == SocketErrorStatus.Unknown)
{
throw;
}
NotifyUserFromAsyncThread(
"Read stream failed with error: " + exception.Message,
NotifyType.ErrorMessage);
}
}

Getting a speed-bottleneck in data-communication when using anonymous pipes

I have a program setup where a MCU sends me sensor data via USART to a C# windows forms application. That application upon receiving the data via the serialdatareceived event sends it to a managed c++ application using anonymous pipes. As soon as the data is received it is plotted in an OpenGL 3d enviroment.
My problem is that the 3D application only refreshes a few times per second and the animation is quite slow and not smooth enough. I did my best to improve the USART speed but the result is the same. I believe the animations speed is bottlenecked by the anonymous pipes speed. I was wondering if anyone else encountered this problem before and possibly found ways to speed upthe anonymous pipes data transfer.
So my problem is the low data transfer speed between the two applications. Ideally I would want 20+ messages a second but at the very least the bottleneck of the data transfer should be the USART interface and not the anonymous pipes. I am running a BAUD-rate of 19200 and am transferring the command "get_angle" and receiving data back fairly fast (~20 ms for calculation of data on the MCU), the data received is ~12 chars.
My anonymous pipe client in managed c++ (in WinMain):
try
{
String^ args = gcnew String(lpCmdLine);
PipeStream^ pipeClient = gcnew AnonymousPipeClientStream(PipeDirection::In, args);
StreamReader^ sr = gcnew StreamReader(pipeClient);
String^ temp;
fullscreen = FALSE;
if (!CreateGLWindow("OpenGL Test", 640, 480, 16, fullscreen))
{
return 0; // Quit If Window Was Not Created
}
while (!done) // Loop That Runs While done=FALSE
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) // Is There A Message Waiting?
{
if (msg.message == WM_QUIT) // Was the message a quit message?
{
done = TRUE; // Set Flag to execute program
}
else // If Not, Deal With Window Messages
{
TranslateMessage(&msg); // Translate The Message
DispatchMessage(&msg); // Dispatch The Message
}
}
temp = sr->ReadLine(); // Read text from pipeline
if (temp != "") // Make sure message is not empty/New message has been received
{
try
{
x_an = FLOAT::Parse(temp->Substring(0, 5)); // Parse X value from string to float
y_an = FLOAT::Parse(temp->Substring(7, 12)); // Parse Y value from string to float
}
catch (Exception^)
{
MessageBox(NULL, "Error parsing string to float", "Fatal error", MB_OK);
}
}
if ((!done)&& (1))
{
// Draw The Scene. Watch For ESC Key And Quit Messages From DrawGLScene()
if ((active && !DrawGLScene()) || keys[VK_ESCAPE]) // Active? Was There A Quit Received?
{
done = TRUE; // ESC or DrawGLScene Signalled A Quit
}
else // Not Time To Quit, Update Screen
{
SwapBuffers(hDC); // Swap Buffers (Double Buffering)
}
}
}
// Shutdown
sr->Close();
pipeClient->Close();
KillGLWindow(); // Kill The Window
return (msg.wParam); // Exit The Program
}
catch (Exception^)
{
MessageBox(NULL, "Pipe connection error", "Fatal error", MB_OK);
return 0x01;
}
My code for the C# anonymous pipes server part:
private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
if (Ready_To_Receive)
{
if (Setup_Pipe)
{
try
{
pipeClient.StartInfo.FileName = "client.exe";
pipeClient.StartInfo.Arguments =
pipeServer.GetClientHandleAsString();
pipeClient.StartInfo.UseShellExecute = false;
pipeClient.Start();
pipeServer.DisposeLocalCopyOfClientHandle();
sw = new System.IO.StreamWriter(pipeServer);
sw.AutoFlush = true;
Setup_Pipe = false;
}
catch
{
MessageBox.Show("Error setting up pipeserver.");
button2_Click(this, null); // Resets application
}
}
Debug_String = serialPort1.ReadExisting();
Debug_String = Debug_String.Replace(serialPort1.NewLine, ""); // Delete newline character so all that remains are numbers
if (!(Debug_String == "")) // String is not empty
{
DataReceived = true;
try
{
sw.WriteLine(Debug_String);
}
catch (Exception)
{
MessageBox.Show("Connection to Pipe Client lost.");
button2_Click(this, null);
}
}
}
else if (Shutting_Down)
{
pipeClient.Close();
}
else
{
serialPort1.ReadExisting(); // Flush the data buffer
DataReceived = true;
}
}

How to handle serial port incomplete received data?

I am working on a project where i send a command through serial port and wait for the response to process. it follows some kind of protocol.
the problem i am facing is the response i am receiving is incomplete, so i am unable to process it. Some the response comes early at one event and some others will follow afterwards.
the response i am expecting looks like this:
05-00-0F-01-02-00-08-E2-00-60-03-11-73-D2-C1-86-5C
but i will receive only 05-00 and the rest comes after and it changes from time to time, so i can't predict.
i need to store the response to a buffer until it is complete then process it. how can i do that?
the way i am receiving from serial port is like this:
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
try
{
int ByteToRead = serialPort1.BytesToRead;
//create array to store buffer data
byte[] inputData = new byte[ByteToRead];
//read the data and store
serialPort1.Read(inputData, 0, ByteToRead);
//invoke the display in another thread
this.BeginInvoke(new DelegateDisplay(Display), new object[] { inputData });
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message, "Serial Port Error ");
}
}
then process and display at here:
public void Display(byte[] inputData)
{
try
{
TboxOutput.AppendText(BitConverter.ToString(inputData, 0) + "\n");
//Add recieved data to List
List<byte> Data = new List<byte>();
try
{
for (int i = 0; i < inputData.Length; i++)
{
Data.Add(inputData[i]);
}
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message + "Data Process");
}
}
catch (SystemException ex)
{
MessageBox.Show(ex.Message, "Display Error");
}
}
This should do:
const int timeout = 1000;
const int step = 100;
for (int t = 0; t < timeout; t += step)
{
Thread.Sleep(step);
if (serialPort1.BytesToRead >= ResponseSize)
break;
}
if (serialPort1.BytesToRead < ResponseSize)
{
serialPort1.DiscardInBuffer();
throw new Exception("Incorrect buffer size!");
}
serialPort1.Read(inputData, 0, ResponseSize);
Where ResponseSize is the length of message you expect to recieve.
Keep reading until you have the complete response. The protocol specification should specify how you tell if the response is complete.
you could use lists, or queues. but as #David Schwartz mentioned, you have to figure the right patron, maybe the size of the chain you're trying to read, or maybe the protocol being used for the sender.
here an example I use to read, 7bit asccii. the chains usin format {STX}{CHAIN}{ETX}{CRC}. But it have a particular case, with an one byte answer {ACK}
this reads from serial port, till get a complete chain, and returns that chain as a byte array:
public Byte[] RECIBE()
{
int count = serialPort1.BytesToRead;
if (count > 0)
{
List<Byte> bytes = new List<Byte>();
bool ETX = false;
while (ETX == false)
{
Byte b = Convert.ToByte(serialPort1.ReadByte());
if (b == 0x06)
{
bytes.Add(b);
return bytes.ToArray();
}
if (b != 0x03)
{
bytes.Add(b);
}
else
{
bytes.Add(b);
ETX = true;
}
}
Byte b2 = Convert.ToByte(serialPort1.ReadByte());
bytes.Add(b2);
return bytes.ToArray();
}
else
{
return null;
}
}

Constantly running server

When a client disconnects, the server closes. Tell me how to leave the ability to connect new customers after the close of the first session .Thanks in advance.
namespace tcpserver
{
class Program
{
static void Main(string[] args)
{
string cmd;
int port = 56568;
Server Serv = new Server(); // Создаем новый экземпляр класса
// сервера
Serv.Create(port);
while (true)
{
cmd = Console.ReadLine(); // Ждем фразы EXIT когда
// понадобится выйти из приложения.
// типа интерактивность.
if (cmd == "EXIT")
{
Serv.Close(); // раз выход – значит выход. Серв-нах.
return;
}
}
//while (Serv.Close() == true) { Serv.Create(port); }
}
public class Server // класс сервера.
{
private int LocalPort;
private Thread ServThread; // экземпляр потока
TcpListener Listener; // листенер))))
public void Create(int port)
{
LocalPort = port;
ServThread = new Thread(new ThreadStart(ServStart));
ServThread.Start(); // запустили поток. Стартовая функция –
// ServStart, как видно выше
}
public void Close() // Закрыть серв?
{
Listener.Stop();
ServThread.Abort();
return;
}
private void ServStart()
{
Socket ClientSock; // сокет для обмена данными.
string data;
byte[] cldata = new byte[1024]; // буфер данных
Listener = new TcpListener(LocalPort);
Listener.Start(); // начали слушать
Console.WriteLine("Waiting connections on " + Convert.ToString(LocalPort) + " port");
try
{
ClientSock = Listener.AcceptSocket(); // пробуем принять клиента
}
catch
{
ServThread.Abort(); // нет – жаль(
return;
}
int i = 0;
if (ClientSock.Connected)
{
while (true)
{
try
{
i = ClientSock.Receive(cldata); // попытка чтения
// данных
}
catch
{
}
try
{
if (i > 0)
{
data = Encoding.ASCII.GetString(cldata).Trim();
Console.WriteLine("<" + data);
if (data == "CLOSE") // если CLOSE –
// вырубимся
{
ClientSock.Send(Encoding.ASCII.GetBytes("Closing the server..."));
ClientSock.Close();
Listener.Stop();
Console.WriteLine("Server closed. Reason: client wish! Type EXIT to quit the application.");
ServThread.Abort();
return;
}
else
{ // нет – шлем данные взад.
ClientSock.Send(Encoding.ASCII.GetBytes("Your data: " + data));
}
}
}
catch
{
ClientSock.Close(); //
Listener.Stop();
Console.WriteLine("Client disconnected. Server closed.");
ServThread.Abort();
}
}
}
}
}
}
}
Typical threaded server code will read more like this (in a pseudo code, because I don't know enough Java details to write it exactly, and because C is a bit stifling):
socket s = new socket
bind s to an optional IP, port
listen s
while true
cli = accept s
t = new thread(handle_client, cli)
maybe disown thread, so no need to join it later
t.start
The important point is that creating the socket, binding it to an address, and listen are all handled outside the loop, and accept() and starting threads are inside the loop.
You may want to wrap this entire block inside another thread; that is acceptable. The important part is separating the listen from the accept and per-client thread. This allows your code to stop accepting new connections but handle existing clients until they disconnect, or disconnect existing connections when they use their allotment of resources but continue accepting connections, etc. (Note how your last catch block will terminate the server if any single client socket throws an exception; that kind of code is easy to avoid with the usual server layout.)
replace
ServThread.Abort();
return;
with a continue instead, this will not break the while loop and yet stop the current "round". Please consider reading this: http://www.codeproject.com/KB/IP/serversocket.aspx nice project to build from

question about port

i have a problem
i am writing a code in C#
i wanna receive a byte from serial port
but when i wanna receive data from port that sounds my program is hang
and doesnt work any more
SerialPort port = new SerialPort("COM3");
port.Open();
byte[] b = new byte[10];
port.Read(b, 0, 1);
port.Close();
please help me
This is because SerialPort reads data synchronously and blocks current thread until the data would be available.
You can use separate thread for this:
public class SerialPort : IDisposable
{
public SerialPort(byte comNum, int baudRate)
{
this.comNum = comNum;
serialPort = new System.IO.Ports.SerialPort("COM" + comNum.ToString(), baudRate);
serialPort.Open();
thread = new System.Threading.Thread(ThreadFn);
thread.Start();
}
public void Dispose()
{
if (thread != null)
thread.Abort();
if (serialPort != null)
serialPort.Dispose();
}
private void OnReceiveByte(byte b)
{
//handle received byte
}
private void ThreadFn(object obj)
{
Byte[] inputBuffer = new Byte[inputBufferSize];
while (true)
{
try
{
int availibleBytes = serialPort.BytesToRead;
if (availibleBytes > 0)
{
int bytesToRead = availibleBytes < inputBufferSize ? availibleBytes : inputBufferSize;
int readedBytes = serialPort.Read(inputBuffer, 0, bytesToRead);
for (int i = 0; i < readedBytes; i++)
OnReceiveByte(inputBuffer[i]);
}
System.Threading.Thread.Sleep(1);
}
catch (System.Threading.ThreadAbortException)
{
break;
}
catch (Exception e)
{
System.Diagnostics.Debug.Assert(false, e.Message);
}
}
}
private Byte comNum;
private System.IO.Ports.SerialPort serialPort;
private System.Threading.Thread thread;
private const int inputBufferSize = 1024;
}
Is there actually any data being sent over the serial port? The call to Read might just be waiting to receive some data before returning. Make sure that you have set a value for the ReadTimeout property. This will make the call to Read throw a TimeoutException if no data was read from the port.
Reference:
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.readtimeout.aspx
Also make sure you set the serial speed right (if you're reading too fast you'll miss some data, etc)

Categories

Resources