Handling COM serial port communication - serial-port

I was thinking about a best approach to properly handle the serial port communication in my program. I have some device that sends me data, im reciving it using DataRecieved event and ReadExisting method in it. Everything that it reads is being put inside a buffer, when last line equals some string then i start to parse it into some kind of packet.
Aside from that, when i send data to this device and wait for response, i mark flag
bool isReady = false;
while(!isReady)
Thread.Sleep(500);
And in data parsing method i set this flag to true so when I recieve packet data, code can jump out of this loop and continue to work as needed. But in my opinion this is not a clean/good way to do this. And there is a problem sometimes, if device will not send the packet I need, so program is being stuck in the loop forever.
I was wondering, how would you guys resolve this case in your code?
Thanks, and sorry for bad english.

Don't just wait for a response in an endless loop. Use the events like you previously mentioned to get the data. See this other SO question also. SerialPort class and DataReceived event... Getting bytes. Use ReadLine or ReadExisting? Any examples?

For now i've added a 5sec timeout using following code:
bool isReady = false;
DateTime timeout = DateTime.Now;
while(!isReady)
{
Thread.Sleep(500);
if((DateTime.Now-timeout).TotalMiliseconds >= 5000)
break;
}
So when no response is recieved then it just jumps out of this loop. This is solving one of my problems, but still I would like to know other ways to handle this. If you guys have any ideas, please share them.

Related

Establishing serial port communication between Arduino and Godot?

I’m wondering how do I go about establishing a serial port communication between Arduino Uno (as my input) and Godot game engine (as my output)? Context is, I'm trying to use sensors on Arduino to move/place objects on Godot, thus I need the serial port code or guidance on how to go about achieving that connection.
Any help is appreciated, thank you everyone!
You can try plugin GDSerCommPlugin. But it is work in progress and i didnt test it so i dont know if it is usable.
Since it's a long time this question was asked, I think that an update is welcome.
Since Godot 3.0, C# is fully supported, I'm using Godot 3.3.2 and my conclusion about dealing with serial communication in Godot is : use C#
You'll keep all the multi platform development advantage of Godot without writing a single (low level) line of code, here is a snipped:
using System.IO.Ports; // for .NET SerialPort
Then in your class if you want to open the port (assuming "SerialPort port" is defined):
port = new SerialPort(portName, (Int32)baudRate, Parity.None, 8, StopBits.One);
Then use the _Process to read the data:
public override void _Process(float delta)
{
if (port != null)
{
if (port.BytesToRead > 0)
{
string serData = port.ReadExisting();
string[] str = serData.Split('\n'); // Just an example
parseLines(str); // Your implementation
}
}
}
Note1: "DataReceived" event from SerialPort doesn't work (I don't know why but I think this is due to the different context) but with Godot this function is useless since you can check and parse directly the data in the _Process function.
Note2: For efficiency it's better to use the ReadExisting() function (and parse lines yourself) than the Readline() function in a loop in the _Process function.
Note3: Sending to serial port is immediate eg:
port.Write("Hello\r");

In Disassembler pipeline component - Send only last message out from GetNext() method

I have a requirement where I will be receiving a batch of records. I have to disassemble and insert the data into DB which I have completed. But I don't want any message to come out of the pipeline except the last custom made message.
I have extended FFDasm and called Disassembler(), then we have GetNext() which is returning every debatched message out and they are failing as there is subscribers. I want to send nothing out from GetNext() until Last message.
Please help if anyone have already implemented this requirement. Thanks!
If you want to send only one message on the GetNext, you have to call on Disassemble method to the base Disassemble and get all the messages (you can enqueue this messages to manage them on GetNext) as:
public new void Disassemble(IPipelineContext pContext, IBaseMessage pInMsg)
{
try
{
base.Disassemble(pContext, pInMsg);
IBaseMessage message = base.GetNext(pContext);
while (message != null)
{
// Only store one message
if (this.messagesCount == 0)
{
// _message is a Queue<IBaseMessage>
this._messages.Enqueue(message);
this.messagesCount++;
}
message = base.GetNext(pContext);
}
}
catch (Exception ex)
{
// Manage errors
}
Then on GetNext method, you have the queue and you can return whatever you want:
public new IBaseMessage GetNext(IPipelineContext pContext)
{
return _messages.Dequeue();
}
The recommended approach is to publish messages after disassemble stage to BizTalk message box db and use a db adapter to insert into database. Publishing messages to message box and using adapter will provide you more options on design/performance and will decouple your DB insert from receive logic. Also in future if you want to reuse the same message for something else, you would be able to do so.
Even then for any reason if you have to insert from pipeline component then do the following:
Please note, GetNext() method of IDisassembler interface is not invoked until Disassemble() method is complete. Based on this, you can use following approach assuming you have encapsulated FFDASM within your own custom component:
Insert all disassembled messages in disassemble method itself and enqueue only the last message to a Queue class variable. In GetNext() message then return the Dequeued message, when Queue is empty return null. You can optimize the DB insert by inserting multiple rows at a time and saving them in batches depending on volume. Please note this approach may encounter performance issues depending on the size of file and number of rows being inserted into db.
I am calling DBInsert SP from GetNext()
Oh...so...sorry to say, but you're doing it wrong and actually creating a bunch of problems doing this. :(
This is a very basic scenario to cover with BizTalk Server. All you need is:
A Pipeline Component to Promote BTS.InterchageID
A Sequential Convoy Orchestration Correlating on BTS.InterchangeID and using Ordered Delivery.
In the Orchestration, call the SP, transform to SOAP, call the SOAP endpoint, whatever you need.
As you process the Messages, check for BTS.LastInterchagneMessage, then perform your close out logic.
To be 100% clear, there are no practical 'performance' issues here. By guessing about 'performance' you've actually created the problem you were thinking to solve, and created a bunch of support issues for later on, sorry again. :( There is no reason to not use an Orchestration.
As noted, 25K records isn't a lot. Be sure to have the Receive Location and Orchestration in different Hosts.

Can a thread in ASP.NET work keep continue after Response.End?

I want to make a tcp connection to a device and keep continously retrieve data from device. I want to start this with a simple request and keep it working background even Page response completed. Is this possible in asp.net?
Can a thread in ASP.NET work keep continue after Response.End?
Yes, you can if you do not care or do not need the result.
For example, in the following code, you call AddLogAsync and insert a log, but you not care whether insert successful or not.
public Task AddLogAsync(Log log)
{
return Task.Run(() => AddLog(log));
}
private void AddLog(TraceLog traceLog)
{
// Do something here.
}
I want to make a tcp connection to a device and keep continously
retrieve data from device. I want to start this with a simple request
and keep it working. Is this possible in asp.net?
I'm not really understanding above question. After Response.End, you cannot return anything, although you can continue work on something in different thread.

Qt5 QSerialPort write data

How I can write data in serial port, with delay between send's messages?
This is my code:
void MainWindow::on_pushButton_Done_clicked()
{
if(sport->isOpen()){
sport->clear();
QString cmd = Phase+Mode;
//Write Stop
sport->write("stop!", 5);
//Write Mode
sport->write(cmd.toStdString().c_str(), cmd.toStdString().length());
//Write Speed
sport->write(Speed.toStdString().c_str(), Speed.toStdString().length());
//Write Direction
sport->write(Direction.toStdString().c_str(), Direction.toStdString().length());
//Run
sport->write("start!", 6);
}
}
My device receives an error message when I call this function.
Thank you.
2 options:
use waitForBytesWritten to ensure the bytes are written and then a short sleep
however this will block the thread and will block the gui
the other is using a QTimer to trigger another slot a few times and a field that will indicate what needs to be sent
Looks like you are trying to program some step motor controller or something similar.
Usually in such controllers you should wait for controller response to verify that command was processed properly.
It looks like that your design of code is very bad. Move everything related with this controller to separate class, which has set of slots, something like: starRotateLeftWithSpeed(double). Code will be cleaner and it will be easy to use thread if you decide to use methods like waitForBytesWritten proposed in another answer.
Definitely you should read controller manual more carefully.

Broadcast TCP-Server with libevent

I am looking for some sample code of a dead simple libevent-based TCP-Server which broadcasts incoming Messages to all connected clients. On the Web I only found TCP-Servers which echoes back messages.
One echo example if found is on the bottom of this page http://www.wangafu.net/~nickm/libevent-book/Ref8_listener.html
I am sure that its not so difficult to change the code provided on this Site, so that messages are brodcast to all connected clients, but I don't know how.
Could someone advise me?
EDIT: Yes, some kind of a chat server. It seams i need to do sth like this:
void server_read_cb(struct bufferevent *bev, void *data)
{
struct evbuffer *input = bufferevent_get_input(bev);
struct evbuffer *output = bufferevent_get_output(bev);
char *mem = malloc(len); /* XXX: check for malloc failure */
evbuffer_remove(input, mem, len);
"for every connection conn" {
/* XXX you'll need to implement a real connection list;
the above isn't real C. */
evbuffer_add(bufferevent_get_output(conn), mem, len);
}
free(mem);
}
But i can't put this to work.
Seems you want something similar to a chat server. One example is here. Basically, when you receive data from one connection, you just go through the list of connections and send that same data to each one (including/excluding the original).

Resources