Reading COM port in c++, getting errors - c++

First time poster long time reader.
I've been playing round with reading in data from a bluetooth GPS unit.
I can connect to it using hyperterm and see the data
The following log is from the hyperterm
$GPRMC,195307.109,A,5208.2241,N,00027.7689,W,000.0,345.8,310712,,,A*7E
$GPVTG,345.8,T,,M,000.0,N,000.0,K,A*07
$GPGGA,195308.109,5208.2242,N,00027.7688,W,1,04,2.1,58.9,M,47.3,M,,0000*7E
$GPGSA,A,3,19,03,11,22,,,,,,,,,5.5,2.1,5.0*3F
$GPRMC,195308.109,A,5208.2242,N,00027.7688,W,000.0,345.8,310712,,,A*73
$GPVTG,345.8,T,,M,000.0,N,000.0,K,A*07
$GPGGA,195309.109,5208.2243,N,00027.7688,W,1,04,2.1,58.9,M,47.3,M,,0000*7E
END LOG
The following log is from my C++ program
$GPGSV,3,3,12,14,20,105,16,28,18,323,,08,07,288,,16,01,178,*7A
$GPRMC,195,3,2ÿþÿÿÿL.š945.109,A,5208.2386,N,00027.7592,W,000.0,169.5,8,323,,08,07,288,,16,01,178,*7A
$GPRMC,195,3,2ÿþÿÿÿL.š310712,,,A*70
$GPVTG,169.5,T,,M,000.0,N,000.0,K,A*06
8,07,288,,16,01,178,*7A
$GPRMC,195,3,2ÿþÿÿÿL.š310712,,,A*70
$GPVTG,169.5,T,,M,000.0,N,000.0,K,A*06
8,07,288,,16,01,178,*7A
$GPRMC,195,3,2ÿþÿÿÿL.š$GPGGA,195946.109,5208.2386,N,00027.7592,W,1.0,K,A*06
8,07,288,,16,01,178,*7A
END LOG
THE PROBLEM
I've left the line feeds as they come, the C++ output has extra line feeds, not sure why?
The C++ log also has some funky chars...?
The Code
for (int n=0;n<100;n++) {
char INBUFFER[100];
cv::waitKey(1000);
bStatus = ReadFile(comport, // Handle
&INBUFFER, // Incoming data
100, // Number of bytes to read
&bytes_read, // Number of bytes read
NULL);
cout << "bStatus " << bStatus << endl;
if (bStatus != 0)
{
// error processing code goes here
}
LogFile << INBUFFER;
}
I'm using settings...
comSettings.BaudRate = 2400;
comSettings.StopBits = ONESTOPBIT;
comSettings.ByteSize = 8;
comSettings.Parity = NOPARITY;
comSettings.fParity = FALSE;
...which as far as I can tell are the same as the settings used by hyperterm.
Any hints on what I'm doing wrong?
cheers!
UPDATE
So after updating to use bytes_read and account for the extra LF at the end of NMEA data I now have...
if (bytes_read!=0) {
for (int i=0; i < bytes_read; i++) {
LogFile << INBUFFER[i];
}
}
Which appears to have fixed things!
$GPGGA,215057.026,5208.2189,N,00027.7349,W,1,04,6.8,244.6,M,47.3,M,,0000*41
$GPGSA,A,3,32,11,01,19,,,,,,,,,9.7,6.8,7.0*3D
$GPRMC,215057.026,A,5208.2189,N,00027.7349,W,002.0,208.7,310712,,,A*74
$GPVTG,208.7,T,,M,002.0,N,003.8,K,A*09
$GPGGA,215058.026,5208.2166,N,00027.7333,W,1,04,6.8,243.1,M,47.3,M,,0000*42
Thanks folks, your help was much appreciated.

You have a bytes_read var, but you don't do anything with it? Seems to me that you're dumping the entire INBUFFER to the file, no matter how many/few bytes are actually loaded into it?

Related

Problem with esp8266 sending large JSON Document via MQTT

I developed a little application that read data from a sensor, store them in SPIFFS memory of my wemos D1 mini (esp8266) and then create a JSON Document and send it via MQTT to my topic. The problem is that as long as I send a JSON Doc with 10 object everything works great, but when I increase the size of the doc over 10 object nothing works. Eventually I need to send a JSON doc with 100 object inside.
What have I already done?
I'm using PubSubClient and I already set the MAX_PACKET_SIZE to the correct value
Using arduinojson assistant I found out the size of my JSON Document (8192 bytes)
I tried to use mqtt.fx to test if the problem was the esp8266 or the mqtt broker. Using mqtt.fx I'm able to send a JSON doc with 100 objects
As soon as I increase the size of the JSON doc I get a wdt error from the serial monitor of my arduino IDE.
I search the internet for wdt error but I don't get what they are and how to solve my problem
Last things I already tried to show on the serial monitor the file.txt in the SPIFFS where I store the data and I can store and then read the 100 object
So in the end I think it's an esp8266 problem and not PubSubClient or MQTT. Am I right?
Does anyone of you here ever encountered this problem before or have some other test I can run?
I search the internet for wdt error but I don't get what they are and how to solve my problem
WDT stands for a Watch Dog Timer. https://os.mbed.com/cookbook/WatchDog-Timer#:~:text=A%20watchdog%20timer%20(WDT)%20is,a%20software%20or%20hardware%20fault.
A watchdog timer (WDT) is a hardware timer that automatically generates a system reset if the main program neglects to periodically service it. It is often used to automatically reset an embedded device that hangs because of a software or hardware fault. Some systems may also refer to it as a computer operating properly (COP) timer. Many microcontrollers including the mbed processor have watchdog timer hardware.
Let's paint a better picture with an example. Let's say that you setup a WDT with a time of 10 seconds. Then the WDT starts counting down from 10 seconds. If it reaches 0 the processor will reset. "Feeding" the WDT will reset the countdown to the original value in this case 10 seconds. So if the WDT has counted down to 4 seconds remaining and you feed it, it resets the countdown back to 10 and starts counting down again.
Does anyone of you here ever encountered this problem before or have some other test I can run?
It looks to me like sending a larger JSON object takes a longer period of time than what the WDT is set for. One possibility would be to break up the JSON object into multiple pieces and send it in smaller chunks instead of one large one. This way the time between WDT "feedings" is reduced. I have no idea if this would be possible for you to change. But this should at least give you a better idea of what's happening.
OK in the end the problem was that sending a large JsonDocument triggered the WDT and the only way I found to overcome this problem was, as suggested by adamvz, to create a main file with all the 100 object, then call a function to split that file in 10 smaller one and send each of them over the internet through an HTTP request or Mosquitto.
Supposing you already created the main file in the spiffs memory, then:
This to split the main file:
void WritePacks() {
sourceFile = LittleFS.open("/file.txt", "r");
if (!sourceFile) {
Serial.println(F("Error: file.txt open failed"));
} else {
Serial.println("File open w/ success");
for (byte idx = 0; idx < outputCount; idx++) {
String aLine;
aLine.reserve(capacity);
if (sourceFile.available() == 0) break;
destinationFile = LittleFS.open(outputFileNames[idx], "w");
if (!destinationFile) {
Serial.print(F("can't open destination "));
Serial.println(outputFileNames[idx]);
break;
} else {
int lineCount = 0;
while (sourceFile.available() && (lineCount <= 10)) {
aLine = sourceFile.readStringUntil('\n');
destinationFile.println(aLine); // double check if the '\n' is in the String or not (--> print or println accordingly)
lineCount++;
}
outputIndex = idx;
Serial.println(outputIndex);
destinationFile.close();
}
} // end for
sourceFile.close();
}
}//end WritePacks
This to publish:
//------ HTTP Publish ------
void httpPublish(){
const char * outputFileNames[] = {"/out1.txt", "/out2.txt", "/out3.txt", "/out4.txt", "/out5.txt", "/out6.txt", "/out7.txt", "/out8.txt", "/out9.txt", "/out10.txt"};
const byte outputCount = sizeof outputFileNames / sizeof outputFileNames[0];
byte outputIndex = 0;
File sourceFile;
File destinationFile;
//Serial.println(capacity);
for (byte idx = 0; idx < outputCount; idx++) {
DynamicJsonDocument doc(capacity);
DynamicJsonDocument globalDoc(capacity);
StaticJsonDocument <1024> localDoc;
String aLine;
aLine.reserve(capacity);
destinationFile = LittleFS.open(outputFileNames[idx], "r");
if (!destinationFile) {
Serial.print(F("can't open destination "));
Serial.println(outputFileNames[idx]);
break;
} else {
Serial.print("Reading: ");
Serial.println(outputFileNames[idx]);
//int lineCount = 0;
while (destinationFile.available()) {
aLine = destinationFile.readStringUntil('\n');
DeserializationError error = deserializeJson(localDoc, aLine);
if (!error) globalDoc.add(localDoc);
else{ Serial.println("Error Writing All files");}
}//while
JsonObject Info = doc.createNestedObject("Info");
Info["Battery"] = battery;
Info["ID"] = id;
Info["Latitudine"] = latitudine;
Info["Longitudine"] = longitudine;
JsonArray Data = doc.createNestedArray("Data");
Data.add(globalDoc);
HTTPClient http;
//Send request
http.begin("yourURL");
char buffer[capacity];
size_t n = serializeJson(doc, buffer);
http.POST(buffer);
Serial.println(buffer);
http.end();
destinationFile.close();
}
}// end for
}//end httpPublish

libusb_get_string_descriptor_ascii() timeout error?

I'm trying to get the serial number of a USB device using libusb-1.0.
The problem I have is that sometimes the libusb_get_string_descriptor_ascii() function returns -7 (LIBUSB_ERROR_TIMEOUT) in my code, but other times the serial number is correctly written in my array and I can't figure out what is happening. Am I using libusb incorrectly? Thank you.
void EnumerateUsbDevices(uint16_t uVendorId, uint16_t uProductId) {
libusb_context *pContext;
libusb_device **ppDeviceList;
libusb_device_descriptor oDeviceDescriptor;
libusb_device_handle *hHandle;
int iReturnValue = libusb_init(&pContext);
if (iReturnValue != LIBUSB_SUCCESS) {
return;
}
libusb_set_debug(pContext, 3);
ssize_t nbUsbDevices = libusb_get_device_list(pContext, &ppDeviceList);
for (ssize_t i = 0; i < nbUsbDevices; ++i) {
libusb_device *pDevice = ppDeviceList[i];
iReturnValue = libusb_get_device_descriptor(pDevice, &oDeviceDescriptor);
if (iReturnValue != LIBUSB_SUCCESS) {
continue;
}
if (oDeviceDescriptor.idVendor == uVendorId && oDeviceDescriptor.idProduct == uProductId) {
iReturnValue = libusb_open(pDevice, &hHandle);
if (iReturnValue != LIBUSB_SUCCESS) {
continue;
}
unsigned char uSerialNumber[255] = {};
int iSerialNumberSize = libusb_get_string_descriptor_ascii(hHandle, oDeviceDescriptor.iSerialNumber, uSerialNumber, sizeof(uSerialNumber));
std::cout << iSerialNumberSize << std::endl; // Print size of serial number <--
libusb_close(hHandle);
}
}
libusb_free_device_list(ppDeviceList, 1);
libusb_exit(pContext);
}
I see nothing wrong with your code. I would not care to much about timeouts in the context of USB. It is a bus after all and can be occupied with different traffic.
As you may know there is depending on the version of USB a portion of the bandwidth reserved for control transfers. libusb_get_string_descriptor_ascii simply sends all the required control transfers to get the string. If any of those times out it will abort. You can try to send this control transfers yourself and use bigger timeout values but I guess the possibility of a timeout will always be there to wait for you (pun intended).
So it turns out my device was getting into weird states, possibly not being closed properly or the like. Anyway, calling libusb_reset_device(hHandle); just after the libusb_open() call seems to fix my sporadic timeout issue.
libusb_reset_device()

Windws C++ Intermittent Socket Disconnect

I've got a server that uses a two thread system to manage between 100 and 200 concurrent connections. It uses TCP sockets, as packet delivery guarantee is important (it's a communication system where missed remote API calls could FUBAR a client).
I've implemented a custom protocol layer to separate incoming bytes into packets and dispatch them properly (the library is included below). I realize the issues of using MSG_PEEK, but to my knowledge, it is the only system that will fulfill the needs of the library implementation. I am open to suggestions, especially if it could be part of the problem.
Basically, the problem is that, randomly, the server will drop the client's socket due to a lack of incoming packets for more than 20 seconds, despite the client successfully sending a keepalive packet every 4. I can verify that the server itself didn't go offline and that the connection of the users (including myself) experiencing the problem is stable.
The library for sending/receiving is here:
short ncsocket::send(wstring command, wstring data) {
wstringstream ss;
int datalen = ((int)command.length() * 2) + ((int)data.length() * 2) + 12;
ss << zero_pad_int(datalen) << L"|" << command << L"|" << data;
int tosend = datalen;
short __rc = 0;
do{
int res = ::send(this->sock, (const char*)ss.str().c_str(), datalen, NULL);
if (res != SOCKET_ERROR)
tosend -= res;
else
return FALSE;
__rc++;
Sleep(10);
} while (tosend != 0 && __rc < 10);
if (tosend == 0)
return TRUE;
return FALSE;
}
short ncsocket::recv(netcommand& nc) {
vector<wchar_t> buffer(BUFFER_SIZE);
int recvd = ::recv(this->sock, (char*)buffer.data(), BUFFER_SIZE, MSG_PEEK);
if (recvd > 0) {
if (recvd > 8) {
wchar_t* lenstr = new wchar_t[4];
memcpy(lenstr, buffer.data(), 8);
int fulllen = _wtoi(lenstr);
delete lenstr;
if (fulllen > 0) {
if (recvd >= fulllen) {
buffer.resize(fulllen / 2);
recvd = ::recv(this->sock, (char*)buffer.data(), fulllen, NULL);
if (recvd >= fulllen) {
buffer.resize(buffer.size() + 2);
buffer.push_back((char)L'\0');
vector<wstring> data = parsewstring(L"|", buffer.data(), 2);
if (data.size() == 3) {
nc.command = data[1];
nc.payload = data[2];
return TRUE;
}
else
return FALSE;
}
else
return FALSE;
}
else
return FALSE;
}
else {
::recv(this->sock, (char*)buffer.data(), BUFFER_SIZE, NULL);
return FALSE;
}
}
else
return FALSE;
}
else
return FALSE;
}
This is the code for determining if too much time has passed:
if ((int)difftime(time(0), regusrs[i].last_recvd) > SERVER_TIMEOUT) {
regusrs[i].sock.end();
regusrs[i].is_valid = FALSE;
send_to_all(L"removeuser", regusrs[i].server_user_id);
wstringstream log_entry;
log_entry << regusrs[i].firstname << L" " << regusrs[i].lastname << L" (suid:" << regusrs[i].server_user_id << L",p:" << regusrs[i].parent << L",pid:" << regusrs[i].parentid << L") was disconnected due to idle";
write_to_log_file(server_log, log_entry.str());
}
The "regusrs[i]" is using the currently iterated member of a vector I use to story socket descriptors and user information. The 'is_valid' check is there to tell if the associated user is an actual user - this is done to prevent the system from having to deallocate the member of the vector - it just returns it to the pool of available slots. No thread access/out-of-range issues that way.
Anyway, I started to wonder if it was the server itself was the problem. I'm testing on another server currently, but I wanted to see if another set of eyes could stop something out of place or cue me in on a concept with sockets and extended keepalives that I'm not aware of.
Thanks in advance!
I think I see what you're doing with MSG_PEEK, where you wait until it looks like you have enough data to read a full packet. However, I would be suspicious of this. (It's hard to determine the dynamic behaviour of your system just by looking at this small part of the source and not the whole thing.)
To avoid use of MSG_PEEK, follow these two principles:
When you get a notification that data is ready (I assume you're using select), then read all the waiting data from recv(). You may use more than one recv() call, so you can handle the incoming data in pieces.
If you read only a partial packet (length or payload), then save it somewhere for the next time you get a read notification. Put the packets and payloads back together yourself, don't leave them in the socket buffer.
As an aside, the use of new/memcpy/wtoi/delete is woefully inefficient. You don't need to allocate memory at all, you can use a local variable. And then you don't even need the memcpy at all, just a cast.
I presume you already assume that your packets can be no longer than 999 bytes in length.

Unable to receive data from serial port

Currently I try to write a serial port communication in VC++ to transfer data from PC and robot via XBee transmitter. But after I wrote some commands to poll data from robot, I didn't receive anything from the robot (the output of filesize is 0 in the code.). Because my MATLAB interface works, so the problem should happen in the code not the hardware or communication. Would you please give me help?
01/03/2014 Updated: I have updated my codes. It still can not receive any data from my robot (the output of read is 0). When I use "cout<<&read" in the while loop, I obtain "0041F01C1". I also don't know how to define the size of buffer, because I don't know the size of data I will receive. In the codes, I just give it a random size like 103. Please help me.
// This is the main DLL file.
#include "StdAfx.h"
#include <iostream>
#define WIN32_LEAN_AND_MEAN //for GetCommState command
#include "Windows.h"
#include <WinBase.h>
using namespace std;
int main(){
char init[]="";
HANDLE serialHandle;
// Open serial port
serialHandle = CreateFile("\\\\.\\COM8", GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
// Do some basic settings
DCB serialParams;
DWORD read, written;
serialParams.DCBlength = sizeof(serialParams);
if((GetCommState(serialHandle, &serialParams)==0))
{
printf("Get configuration port has a problem.");
return FALSE;
}
GetCommState(serialHandle, &serialParams);
serialParams.BaudRate = CBR_57600;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
//set flow control="hardware"
serialParams.fOutX=false;
serialParams.fInX=false;
serialParams.fOutxCtsFlow=true;
serialParams.fOutxDsrFlow=true;
serialParams.fDsrSensitivity=true;
serialParams.fRtsControl=RTS_CONTROL_HANDSHAKE;
serialParams.fDtrControl=DTR_CONTROL_HANDSHAKE;
if (!SetCommState(serialHandle, &serialParams))
{
printf("Set configuration port has a problem.");
return FALSE;
}
GetCommState(serialHandle, &serialParams);
// Set timeouts
COMMTIMEOUTS timeout = { 0 };
timeout.ReadIntervalTimeout = 30;
timeout.ReadTotalTimeoutConstant = 30;
timeout.ReadTotalTimeoutMultiplier = 30;
timeout.WriteTotalTimeoutConstant = 30;
timeout.WriteTotalTimeoutMultiplier = 30;
SetCommTimeouts(serialHandle, &timeout);
if (!SetCommTimeouts(serialHandle, &timeout))
{
printf("Set configuration port has a problem.");
return FALSE;
}
//write packet to poll data from robot
WriteFile(serialHandle,">*>p4",strlen(">*>p4"),&written,NULL);
//check whether the data can be received
char buffer[103];
do {
ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
cout << read;
} while (read!=0);
//buffer[read]="\0";
CloseHandle(serialHandle);
return 0;
}
GetFileSize is documented not to be valid when used with a serial port handle. Use the ReadFile function to receive serial port data.
You should use strlen instead of sizeof here:
WriteFile(serialHandle,init,strlen(init),&written,NULL)
You would be even better off creating a function like this:
function write_to_robot (const char * msg)
{
DWORD written;
BOOL ok = WriteFile(serialHandle, msg, strlen(msg), &written, NULL)
&& (written == strlen(msg));
if (!ok) printf ("Could not send message '%s' to robot\n", msg);
}
But that's only the appetizer. The main trouble is, as MDN says:
You cannot use the GetFileSize function with a handle of a nonseeking device such as a pipe or a communications device.
If you want to read from the port, you can simply use ReadFile until it returns zero bytes.
If you already know the max size of your robot's response, try reading that many characters.
Continue reading until the read reports an actual number of bytes read inferior to the size of the buffer. For instance:
#define MAX_ROBOT_ANSWER_LENGTH 1000 /* bytes */
const char * read_robot_response ()
{
static char buffer[MAX_ROBOT_ANSWER_LENGTH];
DWORD read;
if (!ReadFile (serialHandle, buffer, sizeof(buffer), &read, NULL))
{
printf ("something wrong with the com port handle");
exit (-1);
}
if (read == sizeof(buffer))
{
// the robot response is bigger than it should
printf ("this robot is overly talkative. Flushing input\n");
// read the rest of the input so that the next answer will not be
// polluted by leftovers of the previous one.
do {
ReadFile (serialHandle, buffer, sizeof(buffer), &read, NULL);
} while (read != 0);
// report error
return "error: robot response exceeds maximal length";
}
else
{
// add a terminator to string in case Mr Robot forgot to provide one
buffer[read] = '\0';
printf ("Mr Robot said '%s'\n", buffer);
return buffer;
}
}
This simplistic function returns a static variable, which will be overwritten each time you call read_robot_response.
Of course the proper way of doing things would be to use blocking I/Os instead of waiting one second and praying for the robot to answer in time, but that would require a lot more effort.
If you feel adventurous, you can use overlapped I/O, as this lenghty MDN article thoroughly explores.
EDIT: after looking at your code
// this reads at most 103 bytes of the answer, and does not display them
if (!ReadFile(serialHandle,buffer,sizeof(buffer),&read,NULL))
{
printf("Reading data to port has a problem.");
return FALSE;
}
// this could display the length of the remaining of the answer,
// provided it is more than 103 bytes long
do {
ReadFile (serialHandle,buffer,sizeof(buffer),&read,NULL);
cout << read;
}
while (read!=0);
You are displaying nothing but the length of the response beyond the first 103 characters received.
This should do the trick:
#define BUFFER_LEN 1000
DWORD read;
char buffer [BUFFER_LEN];
do {
if (!ReadFile(
serialHandle, // handle
buffer, // where to put your characters
sizeof(buffer) // max nr of chars to read
-1, // leave space for terminator character
&read, // get the number of bytes actually read
NULL)) // Yet another blody stupid Microsoft parameter
{
// die if something went wrong
printf("Reading data to port has a problem.");
return FALSE;
}
// add a terminator after last character read,
// so as to have a null terminated C string to display
buffer[read] = '\0';
// display what you actually read
cout << buffer;
}
while (read!=0);
I advised you to wrap the actual calls to serial port accesses inside simpler functions for a reason.
As I said before, Microsoft interfaces are a disaster. They are verbose, cumbersome and only moderately consistent. Using them directly leads to awkward and obfuscated code.
Here, for instance, you seem to have gotten confused between read and buffer
read holds the number of bytes actually read from the serial port
buffer holds the actual data.
buffer is what you will want to display to see what the robot answered you
Also, you should have a documentation for your robot stating which kind of answers you are supposed to expect. It would help to know how they are formatted, for instance whether they are null-terminated strings or not. That could dispense to add the string terminator.

Flush queued GPIB responses

Architecture ->GBIP from external interface is connected to target ( linux) system via gpib bus.
Inside Linux box , there is ethernet cable from GPIB to motherboard.
The PIC_GPIB card on external interface is IEEE 488.2
I am sending a query from external interface to linux box.
Few scenarios
1) If I send a query which does not expect a response back , then next query send will work.
2) If I send a query which expect response back , and when I have received the response and read it and then fire next query it works fine.
3) BUT if I send a query from external interface and got response back and I ignore to read the response , then Next query fails.
I am requesting help for scenario 3.
The coding is done on linux side and its a socket programming , which uses linux inbuilt function from unistd.h for read and write.
My investigation : I have found there is a internal memory on gbib card on external interface which stores the value of previous response until we have the read. Generally I use IEEE string utility software to write commands that goes to linux box and read reposne via read button .
Could someone please direct me how to clean input buffer or memory which stores value so that write from external command contiunues without bothering to read it.
My code on linux side has been developed in C++ and socket programming. I have used in bulit write and read function to write and read to the gpib and to json server.
Sample code is shown below
bool GpibClass::ReadWriteFromGPIB()
{
bool check = true;
int n = 0;
char buffer[BUFFER_SIZE];
fd_set read_set;
struct timeval lTimeOut;
// Reset the read mask for the select
FD_ZERO(&read_set);
FD_SET(mGpibFd, &read_set);
FD_SET(mdiffFd, &read_set);
// Set Timeout to check the status of the connection
// when no data is being received
lTimeOut.tv_sec = CONNECTION_STATUS_CHECK_TIMEOUT_SECONDS;
lTimeOut.tv_usec = 0;
cout << "Entered into this function" << endl;
// Look for sockets with available data
if (-1 == select(FD_SETSIZE, &read_set, NULL, NULL, &lTimeOut))
{
cout << "Select failed" << endl;
// We don't know the cause of select's failure.
// Close everything and start from scratch:
CloseConnection(mGpibFd);
CloseConnection(mdifferntServer); // this is different server
check = false;
}
// Check if data is available from GPIB server,
// and if any read and push it to gpib
if(true == check)
{
cout << "Check data from GPIB after select" << endl;
if (FD_ISSET(mGpibFd, &read_set))
{
n = read(mGpibFd, buffer, BUFFER_SIZE);
cout << "Read from GPIB" << n << " bytes" << endl;
if(0 < n)
{
// write it to different server and check if we get response from it
}
else
{
// Something failed on socket read - most likely
// connection dropped. Close socket and retry later
CloseConnection(mGpibFd);
check = false;
}
}
}
// Check if data is available from different server,
// and if any read and push it to gpib
if(true == check)
{
cout << "Check data from diff server after select" << endl;
if (FD_ISSET(mdiffFd, &read_set))
{
n = read(mdiffFd, buffer, BUFFER_SIZE);
cout << "Read from diff servewr " << n << " bytes" << endl;
if (0 < n)
{
// Append, just in case - makes sure data is sent.
// Extra cr/lf shouldn't cause any problem if the json
// server has already added them
strcpy(buffer + n, "\r\n");
write(mGpibFd, buffer, n + 2);
std::cout <<" the buffer sixze = " << buffer << std::endl;
}
else
{
// Something failed on socket read - most likely
// connection dropped. Close socket and retry later
CloseConnection(mdiffFd);
check = false;
}
}
}
return check;
}
You should ordinarily be reading responses after any operation which could generate them.
If you fail to do that, an easy solution would be to read responses in a loop until you have drained the queue to empty.
You can reset the instrument (probably *RST), but you would probably loose other state as well. You will have to check it's documentation to see if there is a command to reset only the response queue. Checking the documentation is always a good idea, because the number of instruments which precisely comply with the spec is dwarfed by the number which augment or omit parts in unique ways.