Serial port communication read function cannot read full response - c++

I am having issues with reading complete return string after sending an "ATZ" command to my OBDII dongle device with an STN1100 chip in it. Here is the return response of sending "ATZ" command on putty:
Here is my COM setting code:
LPCWSTR port = L"COM6";
device = CreateFile(port,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
NULL,
0);
if (device == INVALID_HANDLE_VALUE) {
printf("Failed to open port\n");
printf("error code is %i\n", device);
return false;
}
else
printf("Port is open successfully!\n");
//Settings
/*Timeout*/
COMMTIMEOUTS timeout;
timeout.ReadIntervalTimeout = 1;
timeout.ReadTotalTimeoutConstant = 1;
timeout.ReadTotalTimeoutMultiplier = 1;
timeout.WriteTotalTimeoutConstant = 1;
timeout.WriteTotalTimeoutMultiplier = 1;
if (!SetCommTimeouts(serialHandle, &timeout)) {
printf("Error setting the timeout\n");
printf("Error code: %i\n", GetLastError());
}
/**/
DCB serialParams;
serialParams.DCBlength = sizeof(serialParams);
if (!GetCommState(device, &serialParams)) //need this getCommState before setCommState
printf("Error getting current DCB settings\n");
serialParams.BaudRate = CBR_9600;
serialParams.ByteSize = 8;
serialParams.StopBits = ONESTOPBIT;
serialParams.Parity = NOPARITY;
serialParams.fOutX = FALSE;
serialParams.fInX = FALSE;
serialParams.fBinary = TRUE;
serialParams.fNull = TRUE;
serialParams.fRtsControl = RTS_CONTROL_DISABLE;
if (!SetCommState(device, &serialParams)) {
printf("Error setting the DCB\n");
printf("Error code: %i\n", GetLastError());
}
Here is my Write and Read function:
bool Write(HANDLE device) {
bool bErrorFlag = FALSE;
char DataBuffer[] = "ATZ\n";
//char* cmd = DataBuffer;
DWORD dwBytesToWrite = (DWORD)strlen(DataBuffer);
DWORD dwBytesWritten = 0;
bErrorFlag = WriteFile(
device,
DataBuffer,
3,
&dwBytesWritten,
NULL);
if (!bErrorFlag) {
printf("Failed to write to device\n");
printf("Error code: %i\n", GetLastError());
return false;
}
return true;
}
bool Read(HANDLE device) {
char ReadBuffer[256] = { 0 };
int BUFFERSIZE = 256;
DWORD dwBytesRead = 0;
DWORD read;
OVERLAPPED ol = { 0 };
if (!ReadFile(device, ReadBuffer, BUFFERSIZE - 1, &read, 0))
{
printf("Terminal failure: Unable to read from device.\n GetLastError=%08x\n", GetLastError());
CloseHandle(device);
return false;
}
printf("Response is %s\n", ReadBuffer);
return true;
}
I can only receive returned echo command "ATZ" by running the code above, does anyone know what setting I did wrong? It looks like the read function stops reading from the buffer after receiving the first line.

Related

Some files send on a HLS Server using Http Put request are partially uploaded

I have to upload audio chunks continuously on a HLS Server as a part of my project. I am able to upload chunks sucessfully using HTTP Put method with wininet API in C++ using following code.
bool CHTTP::HttpPut(char *szFile,int fileType)
{
bool bErrorFlag = false;
if(m_hInternet == NULL)
{
int retStatus = OpenHTTPSession();
if(retStatus < 1)
{
return true;
}
}
char szPostURL[256];
INTERNET_BUFFERS BufferIn = {0};
DWORD dwBytesRead;
DWORD dwBytesWritten;
BYTE pBuffer[350000];
BOOL bRead, bRet;
static int flag = 1;
BufferIn.dwStructSize = sizeof( INTERNET_BUFFERS );
char szLocalFilePath[256];
if(fileType == AUDIO_CHUNK)
sprintf(szLocalFilePath,"%s/%s",m_strFilePath,szFile);
else
strcpy(szLocalFilePath,szFile);
int iFileSize = 0;
if(fileType == AUDIO_CHUNK)
{
strcpy(szPostURL,m_strPostPath);
strcat(szPostURL,"/");
strcat(szPostURL,szFile);
}
else if(fileType == M3U8)
strcpy(szPostURL,m_szM3U8FileToPost);
else if(fileType == AUTO_M3U8)
strcpy(szPostURL,m_szM3U8AutoPost);
DWORD dwFlags =
INTERNET_FLAG_KEEP_CONNECTION |
INTERNET_FLAG_NO_COOKIES |
INTERNET_FLAG_NO_CACHE_WRITE |
INTERNET_FLAG_NO_UI |
INTERNET_FLAG_RELOAD |INTERNET_FLAG_SECURE;
m_hRequest = HttpOpenRequest(m_hHttpSession, (const char*)"PUT",szPostURL, "HTTP/1.1",NULL , (const char**)"*/*\0",dwFlags, 1);
if(m_hRequest==NULL)
{
bErrorFlag = true;
CloseHTTPSession();
return bErrorFlag;
}
else
{
bErrorFlag = false;
}
int num_of_try = 0;
while(num_of_try < 3)
{
char logDump[1000];
num_of_try++;
HANDLE hFile = CreateFile (szLocalFilePath, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
bErrorFlag = true;
break;
}
else if(!m_bLogFlagCreateErr)
{
m_bLogFlagCreateErr = true;
sprintf(logDump,"CreateFile success %s",szFile);
WriteLog(mLogFile,logDump);
bErrorFlag = false;
}
BufferIn.dwBufferTotal = GetFileSize (hFile, NULL);
iFileSize = BufferIn.dwBufferTotal;
if(!HttpSendRequestEx( m_hRequest, &BufferIn, NULL, HSR_INITIATE, 0))
{
bErrorFlag = true;
m_bLogFlagSend = false;
sprintf(logDump,"Error on HttpSendRequestEx %lu %s",GetLastError(),szFile);
WriteLog(mLogFile,logDump);
break;
}
else
{
bErrorFlag = false;
sprintf(logDump,"HttpSendRequest success %s",szFile);
WriteLog(mLogFile,logDump);
}
DWORD sum = 0;
int size = 0;
do
{
bRead = ReadFile (hFile, pBuffer,iFileSize,
&dwBytesRead, NULL);
if(dwBytesRead != iFileSize)
{
sprintf(logDump,"dwBytesRead %d iFileSize %d %s",dwBytesRead,iFileSize,szFile);
WriteLog(mLogFile,logDump);
}
if(dwBytesRead > 0)
{
bRet=InternetWriteFile( m_hRequest, pBuffer, dwBytesRead,
&dwBytesWritten);
while(dwBytesRead < dwBytesWritten && bRet)
{
sprintf(logDump,"dwBytesRead %d dwBytesWritten %d %s",dwBytesRead,dwBytesWritten,szFile);
WriteLog(mLogFile,logDump);
bRet=InternetWriteFile( m_hRequest, pBuffer+dwBytesWritten, dwBytesRead - dwBytesWritten ,&dwBytesWritten);
}
if(!bRet)
{
int error = GetLastError();
sprintf(logDump,"InternetWriteFile %lu %s",error,szFile);
WriteLog(mLogFile,logDump);
bErrorFlag = true;
break;
}
else
{
sprintf(logDump,"InternetWriteFile buffer success %s",szFile);
WriteLog(mLogFile,logDump);
bErrorFlag = false;
}
}
}
while (dwBytesRead == iFileSize);
CloseHandle (hFile);
if(!HttpEndRequest(m_hRequest, NULL, 0, 0))
{
int error = GetLastError();
if(error != 12032)
{
sprintf(logDump,"HttpEndRequest %lu %s",error,szFile);
WriteLog(mLogFile,logDump)
bErrorFlag = true;
break;
}
else
{
bErrorFlag = true;
continue;
}
}
else
{
sprintf(logDump,"HttpEndRequest success %s",szFile);
WriteLog(mLogFile,logDump);
DWORD dwCode, dwCodeSize;
dwCodeSize = sizeof(DWORD);
if(!HttpQueryInfo(m_hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, &dwCode, &dwCodeSize, NULL))
{
int error = GetLastError();
char tmp[256];
sprintf(tmp,"HttpQueryfails %d %s",error, szFile);
WriteLog(mLogFile,tmp);
}
else
{
if(dwCode != 201 && dwCode != 204)
{
char tmp[256];
sprintf(tmp,"dwcode %d is not 201 or 204 %s",dwCode,szFile);
WriteLog(mLogFile,tmp);
bErrorFlag = true;
break;
}
}
bErrorFlag = false;
break;
}
}
CloseHTTPSession();
return bErrorFlag;
}
Most of the times chunks uploaded are of full size. Randomly chunks uploaded on server are not of full size as shown in following image.
sample image
In such case I am not getting any error messages, even dwBytesWritten returned by InternetWriteFile function is also correct. I am unable to understand what should I do to solve it. Any help in this regard is appreciated.

Error 5: Access is Denied when using WriteFile to interface Arduino and C++ program

I'm developing a C++ console program to connect with an Arduino Uno.
I need to send a key to the Arduino board so it can activate the RFID sensor and send back to the program the UID read.
The ReadFile function works ~almost~ perfectly, but when I try to send an "a" to Arduino so it can start running its ReadFromRFID function I get this message:
"Error 5: Access is Denied"
Does anyone know what am I doing wrong and how to do it right?
Here that is the code I have so far:
HANDLE hSerial;
void printErro() {
printf(":: ERRO ::\n");
wchar_t erro[1024];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), erro, 1024, NULL);
printf("Erro %ld: %ls", GetLastError(), erro);
}
HANDLE conectArduino() {
LPCWSTR porta = L"COM3";
hSerial = CreateFile(porta, GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (hSerial == INVALID_HANDLE_VALUE){
if (GetLastError() == ERROR_FILE_NOT_FOUND){
printErro();
}
//some other error occurred. Inform user.
printErro();
}
DCB parametros = { 0 };
parametros.DCBlength = sizeof(parametros);
parametros.BaudRate = CBR_9600;
parametros.ByteSize = 8;
parametros.StopBits = ONESTOPBIT;
parametros.Parity = NOPARITY;
if (!SetCommState(hSerial, &parametros)){
//error setting serial port state
printErro();
}
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 10000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.WriteTotalTimeoutConstant = 100;
timeouts.WriteTotalTimeoutMultiplier = 0;
if (!SetCommTimeouts(hSerial, &timeouts)) {
printErro();
}
return hSerial;
}
void readArduino(HANDLE hSerial) {
printf("RECEBENDO DADOS DO ARDUINO\n\n");
char buffer[12] = { 0 };
DWORD qtdBytesLida = 0;
if (!ReadFile(hSerial, buffer, 11, &qtdBytesLida, NULL)) {
printErro();
}
printf("%d: %*.*s", qtdBytesLida, qtdBytesLida, qtdBytesLida, buffer);
getchar();
printf("\n\n");
printf("----------------------------------------------------------------------");
printf("\n\n");
}
void sendArduino(const char* palavra) {
printf("ENVIANDO DADOS PARA O ARDUINO\n\n");
char buffer[2] = "a";
DWORD qtdBytesEscrita = 0;
HANDLE hSerial = conectArduino();
if (!WriteFile(hSerial, buffer, 1, &qtdBytesEscrita, NULL)) {
printErro();
}
else {
readArduino(hSerial);
}
CloseHandle(hSerial);
getchar();
printf("\n\n");
printf("----------------------------------------------------------------------");
printf("\n\n");
}
You're only opening the serial port with GENERIC_READ which means read-only access. You need to add GENERIC_WRITE as well if you want to be able to write to it.
hSerial = CreateFile(porta, GENERIC_READ | GENERIC_WRITE, 0, 0,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);

setting up serial port and writing to following online tutorials

i was reading some online tutorials on how to send a few bytes via the com port.
i solved some problems, but i get stuck on:
WriteFile(hSerial, bytes_to_send, 5, &bytes_written, NULL);
fprintf(stderr, "%d bytes written\n", bytes_written);
the code will output:
- Opening serial port...OK
- Sending bytes...0 bytes written
i would like to send some bytes via the com port to the uart on the micro controller.
this code looks very useful for what i need to do.
the code i'm using:
//
// serial.c / serial.cpp
// A simple serial port writing example
// Written by Ted Burke - last updated 13-2-2013
//
// To compile with MinGW:
//
// gcc -o serial.exe serial.c
//
// To compile with cl, the Microsoft compiler:
//
// cl serial.cpp
//
// To run:
//
// serial.exe
//
#include <windows.h>
#include <iostream>
#include <stdio.h>
using namespace std;
int main()
{
// Define the five bytes to send ("hello")
char bytes_to_send[5];
bytes_to_send[0] = 104;
bytes_to_send[1] = 101;
bytes_to_send[2] = 108;
bytes_to_send[3] = 108;
bytes_to_send[4] = 111;
// Declare variables and structures
HANDLE hSerial;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts = {0};
TCHAR *pcCommPort = TEXT("COM1");
// Open the highest available serial port number
fprintf(stderr, "Opening serial port...");
//hSerial = CreateFile( ComPortName,
// GENERIC_READ | GENERIC_WRITE,
// 0,
// NULL,
// OPEN_EXISTING,
// FILE_ATTRIBUTE_NORMAL,
// NULL);
hSerial = CreateFile(
pcCommPort, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hSerial == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Error\n");
return 1;
}
else fprintf(stderr, "OK\n");
// Set device parameters (38400 baud, 1 start bit,
// 1 stop bit, no parity)
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (GetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error getting device state\n");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_38400;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if(SetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error setting device parameters\n");
CloseHandle(hSerial);
return 1;
}
// Set COM port timeout settings
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if(SetCommTimeouts(hSerial, &timeouts) == 0)
{
fprintf(stderr, "Error setting timeouts\n");
CloseHandle(hSerial);
return 1;
}
// Send specified text (remaining command line arguments)
DWORD bytes_written, total_bytes_written = 0;
fprintf(stderr, "Sending bytes...");
if(!WriteFile(hSerial, bytes_to_send, 5, &bytes_written, NULL))
{
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
}
fprintf(stderr, "%d bytes written\n", bytes_written);
// Close serial port
fprintf(stderr, "Closing serial port...");
if (CloseHandle(hSerial) == 0)
{
fprintf(stderr, "Error\n");
return 1;
}
fprintf(stderr, "OK\n");
// exit normally
std::cin.get();
return 0;
}
further editing the code using GetLastError() results in:
OVERLAPPED o;
std::memset(&o, 0, sizeof(o));
o.Offset = FILE_WRITE_TO_END_OF_FILE;
o.OffsetHigh = -1;
if(!WriteFile(hSerial, bytes_to_send, 5, &bytes_written, &o))
{
//DWORD WINAPI GetLastError(void);
//wprintf(L"Format message failed with 0x%x\n", GetLastError()); // 0x3e3
printf("Error number: %ld\n", GetLastError()); 995 (0x3E3)
// The I/O operation has been aborted because of either a thread exit or an application request.
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
}
fprintf(stderr, "%d bytes written\n", bytes_written);
hyperterminal, can detect my app and want me to close it.
regards and thank you.

sending data through serial port in c++

I have copied this code to write through the serial port in c++. It works properly, but what I need now is to know how to convert a string into an array of bytes, because I want to write several strings to communicate with an arduino. I paste the code here:
#include <windows.h>
#include <stdio.h>
int main()
{
// Define the five bytes to send ("hello")
char bytes_to_send[5];
bytes_to_send[0] = 104;
bytes_to_send[1] = 101;
bytes_to_send[2] = 108;
bytes_to_send[3] = 108;
bytes_to_send[4] = 111;
// Declare variables and structures
HANDLE hSerial;
DCB dcbSerialParams = {0};
COMMTIMEOUTS timeouts = {0};
// Open the highest available serial port number
fprintf(stderr, "Opening serial port...");
hSerial = CreateFile(
"\\\\.\\COM1", GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
if (hSerial == INVALID_HANDLE_VALUE)
{
fprintf(stderr, "Error\n");
return 1;
}
else fprintf(stderr, "OK\n");
// Set device parameters (38400 baud, 1 start bit,
// 1 stop bit, no parity)
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if (GetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error getting device state\n");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_38400;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
if(SetCommState(hSerial, &dcbSerialParams) == 0)
{
fprintf(stderr, "Error setting device parameters\n");
CloseHandle(hSerial);
return 1;
}
// Set COM port timeout settings
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if(SetCommTimeouts(hSerial, &timeouts) == 0)
{
fprintf(stderr, "Error setting timeouts\n");
CloseHandle(hSerial);
return 1;
}
// Send specified text (remaining command line arguments)
DWORD bytes_written, total_bytes_written = 0;
fprintf(stderr, "Sending bytes...");
if(!WriteFile(hSerial, bytes_to_send, 5, &bytes_written, NULL))
{
fprintf(stderr, "Error\n");
CloseHandle(hSerial);
return 1;
}
fprintf(stderr, "%d bytes written\n", bytes_written);
// Close serial port
fprintf(stderr, "Closing serial port...");
if (CloseHandle(hSerial) == 0)
{
fprintf(stderr, "Error\n");
return 1;
}
fprintf(stderr, "OK\n");
// exit normally
return 0;
}
Here is the part I want to change:
// Define the five bytes to send ("hello")
char bytes_to_send[5];
bytes_to_send[0] = 104;
bytes_to_send[1] = 101;
bytes_to_send[2] = 108;
bytes_to_send[3] = 108;
bytes_to_send[4] = 111;
I want to use my own strings and a method to transform them into bytes, so that I can send them through the serial port.
A string already is an array of bytes.
char bytes_to_send[] = "hello";

Error while reading data from serial port

I am writing a program in Visual C++ to access serial port.Code is given below:-
#include "stdafx.h"
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <commdlg.h>
int nread,nwrite;
void main()
{
COMMTIMEOUTS timeouts;
COMMCONFIG dcbSerialParams;
char *words,*buffRead, *buffWrite;
DWORD dwBytesWritten,dwBytesRead;
HANDLE hSerial= CreateFile(L"COM1", GENERIC_READ | GENERIC_WRITE,
0,0,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,0);
if ( hSerial == INVALID_HANDLE_VALUE)
{
if (GetLastError() == ERROR_FILE_NOT_FOUND)
{
printf(" serial port does not exist \n");
}
printf(" some other error occured. Inform user.\n");
}
//DCB dcbSerialParams ;
//GetCommState( hSerial, &dcbSerialParams.dcb);
if (!GetCommState(hSerial, &dcbSerialParams.dcb))
{
printf("error getting state \n");
}
dcbSerialParams.dcb.DCBlength = sizeof(dcbSerialParams.dcb);
dcbSerialParams.dcb.BaudRate = CBR_1200;
dcbSerialParams.dcb.ByteSize = 8;
dcbSerialParams.dcb.StopBits = ONESTOPBIT;
dcbSerialParams.dcb.Parity = NOPARITY;
dcbSerialParams.dcb.fBinary = TRUE;
dcbSerialParams.dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.dcb.fOutxCtsFlow = FALSE;
dcbSerialParams.dcb.fOutxDsrFlow = FALSE;
dcbSerialParams.dcb.fDsrSensitivity= FALSE;
dcbSerialParams.dcb.fAbortOnError = TRUE;
if (!SetCommState(hSerial, &dcbSerialParams.dcb))
{
printf(" error setting serial port state \n");
}
GetCommTimeouts(hSerial,&timeouts);
timeouts.ReadIntervalTimeout = 1000;
timeouts.ReadTotalTimeoutConstant = 1000;
timeouts.ReadTotalTimeoutMultiplier = 1000;
timeouts.WriteTotalTimeoutConstant = 1000;
timeouts.WriteTotalTimeoutMultiplier= 1000;
if(!SetCommTimeouts(hSerial, &timeouts))
{
printf("error setting port state \n");
}
//****************Write Operation*********************//
words = "B";
nwrite = strlen(words);
buffWrite = words;
dwBytesWritten = 0;
if (!WriteFile(hSerial, buffWrite, nwrite, &dwBytesWritten, NULL))
{
printf("error writing to output buffer \n");
}
printf("Data written to write buffer is\n %s \n",buffWrite);
//***************Read Operation******************//
buffRead = 0;
dwBytesRead = 0;
nread = strlen(words);
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
printf("Data read from read buffer is \n %s \n",buffRead);
CloseHandle(hSerial);
}
Above program is working properly while write operation (i.e writing data on serial port) but while read operation its is not reading data from serial port.
I am getting output on console window is given below:-
Data written to write buffer is
B
error reading from input buffer
Data read from read buffer is
<null>
I want to know where I am getting wrong and how to resolve it.
The second ReadFile parameter cannot be NULL. It should be valid pointer to some buffer, for example:
dwBytesRead = 0;
nread = strlen(words);
buffRead = new char[nread + 1];
memset(buffRead, 0, nread+1]; // ensure that string will be null-terminated
if (!ReadFile(hSerial, buffRead, nread, &dwBytesRead, NULL))
{
printf("error reading from input buffer \n");
}
...
delete[] buffRead;