visual studio c++ Serial Communication error - c++

I'm going to do serial communication using visual studio c++.
However, when I try to use 'serialport port open', I get an error with the phrase L"//./com3
The error code is c2665, e0289.
Also, there is a possibility that the open port may change from time to time, so please help me to read the port automatically.
serialport.h
#pragma once
#include <windows.h>
#include <iostream>
#include <stdlib.h>
using namespace std;
class SerialPort {
public:
HANDLE hComm;
LPCWSTR COMport;
DWORD dNoOFBytestoWrite;
DWORD dNoOfBytesWritten;
int BufSize;
int Status;
char* SerialBuffer;
char* commandBuffer;
DWORD NoBytesRead;
SerialPort(LPCWSTR COMport, int setBaudRate, int setByteSize, char* commandBuffer, int BufSize);
void Connect(LPCWSTR COMport, int setBaudRate, int setByteSize, char* commandBuffer);
void sendCommand(int setBaudRate, int setByteSize, char* commandBuffer);
void getData();
};
serial.cpp
#include "stdafx.h"
#include <string.h>
#include "SerialPort.h"
SerialPort::SerialPort(LPCWSTR COM, int setBaudRate, int setByteSize, char* commandBuffer, int BufSize) {
this->BufSize = BufSize;
this->SerialBuffer = new char[BufSize];
this->NoBytesRead = BufSize;
Connect(COM, setBaudRate, setByteSize, commandBuffer);
}
void SerialPort::Connect(LPCWSTR COM, int setBaudRate, int setByteSize, char* commandBuffer) {
this->COMport = COM;
this->hComm = CreateFile(COM, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); // (port name, read/write , no sharing , no security, open existing port only, non overlapped i/o , null for comm devices)
if (this->hComm == INVALID_HANDLE_VALUE)
cout << "Error in Opening serial port" << endl;
else {
cout << "Opening serial port successful" << endl;
sendCommand(setBaudRate, setByteSize, commandBuffer);
}
}
void SerialPort::sendCommand(int setBaudRate, int setByteSize, char* commandBuffer) {
this->commandBuffer = commandBuffer;
this->dNoOFBytestoWrite = sizeof(commandBuffer);
this->Status = WriteFile(hComm, commandBuffer, dNoOFBytestoWrite, &dNoOfBytesWritten, NULL);
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
dcbSerialParams.BaudRate = setBaudRate;
dcbSerialParams.ByteSize = setByteSize;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 10;
timeouts.ReadTotalTimeoutConstant = 10;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (this->Status)
cout << "Command Successful" << endl;
else
{
cout << "fail to Command" << endl;
}
}
void SerialPort::getData() {
ReadFile(this->hComm, &*this->SerialBuffer, this->BufSize, &this->NoBytesRead, NULL);
}
main.cpp
#include "stdafx.h"
#include "SerialPort.h"
int main()
{
SerialPort PortOpen( L"//./com3", CBR_115200, 8, "#or", 24);
PortOpen.getData();
PortOpen.getData();
cout << PortOpen.SerialBuffer << endl;
return 0;
}

Related

C++ Serial port with USB hub

I want to connect a seairl port with C++ using USB hub (USB splliter).
I have a code that works perfectly fine with my COM ports, but when I'm trying to use the USB hub, I get an error says the COM port not available (even though I see it in the device manager).
I there a way to connect a USB hub COM port in C++?
I attached my current code if necessary. Thank you!
SerialPort.hpp:
/*
* Author: Manash Kumar Mandal
* Modified Library introduced in Arduino Playground which does not work
* This works perfectly
* LICENSE: MIT
*/
#pragma once
#define ARDUINO_WAIT_TIME 2000
#define MAX_DATA_LENGTH 1024
#include <windows.h>
#include <iostream>
#include <string>
class SerialPort {
private:
std::string readBuffer;
HANDLE handler;
bool connected;
COMSTAT status;
DWORD errors;
public:
explicit SerialPort(const char* portName, DWORD baudRate = CBR_9600);
~SerialPort();
int readSerialPort(const char* buffer, unsigned int buf_size);
int readSerialPortUntil(std::string* payload, std::string until);
bool writeSerialPort(const char* buffer, unsigned int buf_size);
bool writeSerialPort(std::string payload);
bool isConnected();
void closeSerial();
};
SerialPort.cpp:
/*
* Author: Manash Kumar Mandal
* Modified Library introduced in Arduino Playground which does not work
* This works perfectly
* LICENSE: MIT
*/
#include <windows.h>
#include <iostream>
#include <string>
#include "SerialPort.hpp"
SerialPort::SerialPort(const char* portName, DWORD baudRate) {
this->connected = false;
this->handler = CreateFileA(static_cast<LPCSTR>(portName),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (this->handler == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
std::cerr << "ERROR: Handle was not attached.Reason : " << portName << " not available\n";
} else {
std::cerr << "ERROR!!!\n";
}
} else {
DCB dcbSerialParameters = { 0 };
if (!GetCommState(this->handler, &dcbSerialParameters)) {
std::cerr << "ERROR: Failed to get current serial parameters\n";
} else {
dcbSerialParameters.BaudRate = baudRate;
dcbSerialParameters.ByteSize = 8;
dcbSerialParameters.StopBits = ONESTOPBIT;
dcbSerialParameters.Parity = NOPARITY;
dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(handler, &dcbSerialParameters)) {
std::cout << "ALERT: could not set serial port parameters\n";
} else {
this->connected = true;
PurgeComm(this->handler, PURGE_RXCLEAR | PURGE_TXCLEAR);
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
SerialPort::~SerialPort() {
if (this->connected) {
this->connected = false;
CloseHandle(this->handler);
}
}
// Reading bytes from serial port to buffer;
// returns read bytes count, or if error occurs, returns 0
int SerialPort::readSerialPort(const char* buffer, unsigned int buf_size) {
DWORD bytesRead{};
unsigned int toRead = 0;
ClearCommError(this->handler, &this->errors, &this->status);
if (this->status.cbInQue > 0) {
if (this->status.cbInQue > buf_size) {
toRead = buf_size;
} else {
toRead = this->status.cbInQue;
}
}
memset((void*)buffer, 0, buf_size);
if (ReadFile(this->handler, (void*)buffer, toRead, &bytesRead, NULL)) {
return bytesRead;
}
return 0;
}
int SerialPort::readSerialPortUntil(std::string* payload, std::string until) {
int untilLen = until.length(), len;
do {
char buffer[MAX_DATA_LENGTH];
int bytesRead = this->readSerialPort(buffer, MAX_DATA_LENGTH);
if (bytesRead == 0) {
int endIndex = this->readBuffer.find(until);
if (endIndex != -1) {
int index = endIndex + untilLen;
*payload = this->readBuffer.substr(0, index);
this->readBuffer = this->readBuffer.substr(index);
}
return bytesRead;
}
this->readBuffer += std::string(buffer);
len = this->readBuffer.length();
} while (this->readBuffer.find(until) == std::string::npos);
int index = this->readBuffer.find(until) + untilLen;
*payload = this->readBuffer.substr(0, index);
this->readBuffer = this->readBuffer.substr(index);
return index;
}
// Sending provided buffer to serial port;
// returns true if succeed, false if not
bool SerialPort::writeSerialPort(const char* buffer, unsigned int buf_size) {
DWORD bytesSend;
if (!WriteFile(this->handler, (void*)buffer, buf_size, &bytesSend, 0)) {
ClearCommError(this->handler, &this->errors, &this->status);
return false;
}
return true;
}
bool SerialPort::writeSerialPort(std::string payload) {
return this->writeSerialPort(payload.c_str(), payload.length());
}
// Checking if serial port is connected
bool SerialPort::isConnected() {
if (!ClearCommError(this->handler, &this->errors, &this->status)) {
this->connected = false;
}
return this->connected;
}
void SerialPort::closeSerial() {
CloseHandle(this->handler);
}

Сommunicate server client C++

I am writing a network program in C ++. How it works:
The server streams video for the client in real time.
The client receives the video data.
I tried to set up sending and receiving messages (right during streaming). For this, I started the video in a separate thread.
Messages from the client to the server reach the server without any problems. But if you send messages from the server to the client, then firstly the video itself changes, and some kind of garbage is displayed.
How it works (no)
I understand that this is due to the fact that the client is constantly receiving messages (vide). But is it possible to somehow solve this problem?
Server code
#include "server.h"
int Server::open()
{
WORD DLLVersion = MAKEWORD(2, 1);
if (WSAStartup(DLLVersion, &wsaData) != 0)
{
std::cout << "Error" << std::endl;
exit(1);
}
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(addrss);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
server = socket(AF_INET, SOCK_STREAM, NULL);
bind(server, (SOCKADDR*)&addr, sizeof(addr));
listen(server, SOMAXCONN);
std::cout << "Listening..." << std::endl;
client = accept(server, (SOCKADDR*)&addr, &sizeofaddr);
if (client == 0) {
std::cout << "Error #2\n";
}
else {
std::cout << "Client Connected!\n";
}
}
int Server::sendData(const char *buffer, int len)
{
return send(client, buffer, len, NULL);
}
int Server::recvData(char *buffer, int len)
{
return recv(client, buffer, len, NULL);
}
int Server::close()
{
closesocket(server);
std::cout << "Server is closed" << std::endl;
return 0;
}
Server main
#include "server.h"
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2\video\background_segm.hpp"
#include <opencv2\video\tracking.hpp>
#include <Windows.h>
#include <thread>
#include <string>
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 480
#define CLIENT_CLOSE_CONNECTION_SYMBOl '#'
cv::Mat cameraFeed;
int height, width, IM_HEIGHT, IM_WIDTH, imgSize;
bool is_client_connection_close(const char *msg)
{
for (int i = 0; i < strlen(msg); ++i)
{
if (msg[i] == CLIENT_CLOSE_CONNECTION_SYMBOl)
{
return true;
}
}
return false;
}
void VideoSender(Server server)
{
cv::VideoCapture cap(0);
while (true)
{
cv::Mat frame, image;
if (!cap.read(cameraFeed))
{
std::cout << "Video dont work" << std::endl;
break;
}
height = cameraFeed.rows;
width = cameraFeed.cols;
IM_HEIGHT = FRAME_HEIGHT;
IM_WIDTH = FRAME_WIDTH;
resize(cameraFeed, cameraFeed, cv::Size(IM_WIDTH, IM_HEIGHT));
imgSize = cameraFeed.total()*cameraFeed.elemSize();
server.sendData(reinterpret_cast<char*>(cameraFeed.data), imgSize);
imshow("Video_sending", cameraFeed);
char button = cv::waitKey(10);
if (button == 'q')
{
std::cout << "Stop sending video data..." << std::endl;
cap.release();
cv::destroyWindow("Video_sending");
server.close();
break;
}
}
}
int main(int argc, char* argv[])
{
Server server;
server.open();
std::thread th_video(VideoSender, server);
while (true)
{
//sending message
std::string msg1;
std::getline(std::cin, msg1);
int msg_size1 = msg1.size();
server.sendData((char*)&msg_size1, sizeof(int));
server.sendData(msg1.c_str(), msg_size1);
//receive_message
int msg_size;
server.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
server.recvData(msg, msg_size);
std::cout << "Message from client: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
}
system("pause");
return 0;
}
Client code
#include "client.h"
int Client::open()
{
WORD DLLVersion = MAKEWORD(2, 1);
if (WSAStartup(DLLVersion, &wsaData) != 0) {
std::cout << "Error" << std::endl;
exit(1);
}
int sizeofaddr = sizeof(addr);
addr.sin_addr.s_addr = inet_addr(addrs);
addr.sin_port = htons(port);
addr.sin_family = AF_INET;
server = socket(AF_INET, SOCK_STREAM, NULL);
if (connect(server, (SOCKADDR*)&addr, sizeof(addr)) != 0) {
std::cout << "Error: failed connect to server.\n";
return 1;
}
std::cout << "Connected!\n";
}
int Client::sendData(const char * buffer, int len)
{
return send(server, buffer, len, NULL);
}
int Client::recvData(char *buffer, int len)
{
return recv(server, buffer, len, NULL);
}
int Client::close()
{
closesocket(server);
std::cout << "Server is closed" << std::endl;
return 0;
}
Client main
#include "client.h"
#include "opencv2/core/core.hpp"
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "opencv2\video\background_segm.hpp"
#include <opencv2\video\tracking.hpp>
#include <Windows.h>
#include <string>
#include <thread>
#pragma warning(disable: 4996)
#define FRAME_WIDTH 640
#define FRAME_HEIGHT 480
int imgSize;
int bytes = 0;
bool running = true;
int msg_size;
void VideoReceiver(Client client)
{
while (running)
{
int IM_HEIGHT = FRAME_HEIGHT;
int IM_WIDTH = FRAME_WIDTH;
cv::Mat img = cv::Mat::zeros(FRAME_HEIGHT, FRAME_WIDTH, CV_8UC3);
imgSize = img.total()*img.elemSize();
const int ah = 921600;
char sockData[ah];
for (int i = 0; i < imgSize; i += bytes)
if ((bytes = client.recvData(sockData + i, imgSize - i)) == 0)
std::cout << "WTF" << std::endl;
int ptr = 0;
for (int i = 0; i < img.rows; ++i)
for (int j = 0; j < img.cols; ++j)
{
img.at<cv::Vec3b>(i, j) = cv::Vec3b(sockData[ptr + 0], sockData[ptr + 1], sockData[ptr + 2]);
ptr = ptr + 3;
}
cv::namedWindow("Reveived_video", cv::WINDOW_AUTOSIZE);
imshow("Reveived_video", img);
char button = cv::waitKey(10);
if (button == 'q')
{
std::cout << "Stop reveiving video data..." << std::endl;
cv::destroyWindow("Reveived_video");
client.close();
break;
}
}
}
void message_sendind(Client client)
{
while (true)
{
//receiv message
int msg_size;
client.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
client.recvData(msg, msg_size);
std::cout << "Message from server: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
//sending message
//std::string msg1;
//std::getline(std::cin, msg1);
//int msg_size1 = msg1.size();
//client.sendData((char*)&msg_size1, sizeof(int));
//client.sendData(msg1.c_str(), msg_size1);
}
}
int main(int argc, char* argv[])
{
Client client;
client.open();
std::thread th_video(VideoReceiver, client);
while (true)
{
//receiv message
int msg_size;
client.recvData((char*)&msg_size, sizeof(int));
char *msg = new char[msg_size + 1];
msg[msg_size] = '\0';
client.recvData(msg, msg_size);
std::cout << "Message from server: " << msg
<< " (size: " << msg_size << ")"
<< std::endl;
delete[] msg;
//sending message
std::string msg1;
std::getline(std::cin, msg1);
int msg_size1 = msg1.size();
client.sendData((char*)&msg_size1, sizeof(int));
client.sendData(msg1.c_str(), msg_size1);
}
system("pause");
return 0;
}

How to get extended port information when enumerating ports using Windows API

I'm using some legacy code to enumerate ports on my machine:
#include <windows.h>
#include <devguid.h>
#include <setupapi.h>
#include <string>
#include <iostream>
#include <assert.h>
bool GetTextProperty( std::string& sProperty,
HDEVINFO dev,
_SP_DEVINFO_DATA* pDeviceInfoData,
DWORD prop )
{
char szBuf[MAX_PATH];
DWORD iPropertySize = 0;
if (SetupDiGetDeviceRegistryProperty(dev, pDeviceInfoData,
prop, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
{
sProperty = szBuf;
assert( iPropertySize >= sProperty.size() + 1 );
return true;
}
return false;
}
inline bool readRegistryKeyValue( HKEY hKey, const std::string& key, std::string& value )
{
bool res = false;
CHAR szBuffer[512];
DWORD dwBufferSize = sizeof(szBuffer);
ULONG nError = RegQueryValueEx(hKey, key.c_str(), 0, NULL, (LPBYTE)szBuffer, &dwBufferSize);
if (ERROR_SUCCESS == nError)
{
value = szBuffer;
res = true;
}
return res;
}
void ListPorts()
{
HDEVINFO hDevInfo;
SP_DEVINFO_DATA DeviceInfoData;
DWORD i;
hDevInfo = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, 0L, 0L, DIGCF_PRESENT);
if ( hDevInfo == INVALID_HANDLE_VALUE )
{
//Medoc_ReportError(MEDOC_ERROR_HARDWARE_DRIVER_API_FAILED,
// &hDevInfo, sizeof hDevInfo);
assert( false );
}
else
{
// Enumerate through all devices in Set.
DeviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
for (i = 0; SetupDiEnumDeviceInfo(hDevInfo, i, &DeviceInfoData) != 0; i++)
{
char szBuf[MAX_PATH];
short wImageIdx = 0;
short wItem = 0;
DWORD iPropertySize;
if (SetupDiGetDeviceRegistryProperty(hDevInfo, &DeviceInfoData,
SPDRP_FRIENDLYNAME, 0L, (PBYTE) szBuf, MAX_PATH, &iPropertySize))
{
std::cout << "Smart name: " << szBuf << std::endl;
HKEY hKey = SetupDiOpenDevRegKey(
hDevInfo,
&DeviceInfoData,
DICS_FLAG_GLOBAL,
0,
DIREG_DEV,
KEY_READ );
if ( hKey )
{
std::string portName;
readRegistryKeyValue( hKey, "PortName", portName );
std::cout << "Port name: " << szBuf << std::endl;
for ( DWORD prop = 0; prop != SPDRP_MAXIMUM_PROPERTY; ++prop )
{
std::string temp;
GetTextProperty( temp, hDevInfo, &DeviceInfoData, prop );
std::cout << prop << " : " << temp << std::endl;
}
RegCloseKey(hKey);
}
}
}
}
// Cleanup
SetupDiDestroyDeviceInfoList(hDevInfo);
}
int main( int argc, char* argv[] )
{
ListPorts();
return 0;
}
Among other information, this gives me access to port name (COM*), type (FTDI for instance), VID and PID...
However, when I have many different devices based on a FTDI chip plugged, they all have the same information (SPDRP_HARDWAREID prperty reports FTDIBUS\COMPORT&VID_0403&PID_6015 or FTDIBUS\COMPORT&VID_0403&PID_6010). So I cannot discriminate who is who.
When I use a USB sniffer ("Device Monitoring Studio"), this one is able to report more relevant information withoutestablishing any connection to the ports:
Can this kind of extended information be accessed through Windows API to discriminate by name many devices using the same FTDI chip? Or must I use FTDI driver API to achieve this?
With the help of Ben Voigt and Simon Mourier, I could achieve this, here is the piece of code:
// More includes:
#include <initguid.h>
#include <devpkey.h>
#include <cfgmgr32.h>
// A new dependency:
#pragma comment (lib, "Cfgmgr32.lib")
bool GetDeviceProperty( const std::string& what,
DEVINST dev,
DEVPROPKEY prop )
{
char szDeviceBuf[MAX_PATH];
DEVPROPTYPE type;
ULONG iDevicePropertySize = MAX_PATH;
if ( CM_Get_DevNode_PropertyW(dev,
&prop,
&type,
(PBYTE) szDeviceBuf,
&iDevicePropertySize,
0) == CR_SUCCESS )
{
wchar_t* txt = (wchar_t*) szDeviceBuf;
std::wstring ws(txt);
std::cout << what << " : " << std::string(ws.begin(), ws.end()) << std::endl;
return true;
}
else
{
return false;
}
}
void ListPorts()
{
...
DEVINST devInstParent;
auto status = CM_Get_Parent(&devInstParent, DeviceInfoData.DevInst, 0);
if (status == CR_SUCCESS)
{
ShowDeviceProperty( "Bus reported device description", devInstParent, DEVPKEY_Device_BusReportedDeviceDesc );
ShowDeviceProperty( "Device description", devInstParent, DEVPKEY_Device_DeviceDesc );
}
else
{
continue;
}
...

Arduino Serial printing stops at a certain value output from joystick module

I'm making an application that moves that mouse via the joystick module. I'm using C++ because my board doesn't support Mouse.move from the Arduino IDE.
I've run into an issue where if I push the joystick all the way back to where the X value is 1024 the command console that's printing the values out stops printing at all, no empty strings just paused. But if I look at the Serial monitor from the Arduino IDE I see it's continuously printing 1024, 513 printed as it should.
I find that when I do this with the Y value it prints 1024 to both Arduino IDE and C++ Serial Monitors just fine. e.g 513, 1024
I'm fairly new to using C++ with the Arduino, it might be something simple.
JoystickModule.ino (Arduino code)
#define BAUD 9600
const int SW_pin = 2;
const int X_pin = 0;
const int Y_pin = 1;
void setup(){
Serial.begin(BAUD);
pinMode(SW_pin, INPUT);
digitalWrite(SW_pin, HIGH);
}
void loop(){
Serial.println((String)analogRead(X_pin) + "," + (String)analogRead(Y_pin));
delay(100);
}
main.cpp
#include "stdafx.h"
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <sstream>
#include <string>
#include <Windows.h>
#include "SerialPort.h"
#include <vector>
using namespace std;
//portname must contain these backslashes, and remember to replace the following com port
char *port_name = "\\\\.\\COM4";
//String for incoming data
char incomingData[MAX_DATA_LENGTH];
int main() {
SerialPort arduino(port_name);
if (arduino.isConnected()) cout << "Connection Established" << endl;
else cout << "ERROR, check port name";
while (arduino.isConnected()) {
int read_result = arduino.readSerialPort(incomingData, MAX_DATA_LENGTH);
//store into array for later use by splitting by "," e.g. "513, 508"
//result[0] will store the X val and result[1] will store the Y val
string result[2];
int xVal = 0;
int yVal = 0;
string data = (string)incomingData;
size_t pos = data.find(",");
result[0] = data.substr(0, pos);
result[1] = data.substr(pos + 1, 4);
cout << data << endl;
Sleep(100);
}
return 0;
}
Header Files and other resources from this tutorial
SerialPort.h
#pragma once
#ifndef SERIALPORT_H
#define SERIALPORT_H
#define ARDUINO_WAIT_TIME 2000
#define MAX_DATA_LENGTH 255
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
class SerialPort
{
private:
HANDLE handler;
bool connected;
COMSTAT status;
DWORD errors;
public:
SerialPort(char *portName);
~SerialPort();
int readSerialPort(char *buffer, unsigned int buf_size);
bool writeSerialPort(char *buffer, unsigned int buf_size);
bool isConnected();
};
#endif // SERIALPORT_H
SerialPort.cpp
#include "stdafx.h"
#include "SerialPort.h"
SerialPort::SerialPort(char *portName)
{
this->connected = false;
this->handler = CreateFileA(static_cast<LPCSTR>(portName),
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (this->handler == INVALID_HANDLE_VALUE) {
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
printf("ERROR: Handle was not attached. Reason: %s not available\n", portName);
}
else
{
printf("ERROR!!!");
}
}
else {
DCB dcbSerialParameters = { 0 };
if (!GetCommState(this->handler, &dcbSerialParameters)) {
printf("failed to get current serial parameters");
}
else {
dcbSerialParameters.BaudRate = CBR_9600;
dcbSerialParameters.ByteSize = 8;
dcbSerialParameters.StopBits = ONESTOPBIT;
dcbSerialParameters.Parity = NOPARITY;
dcbSerialParameters.fDtrControl = DTR_CONTROL_ENABLE;
if (!SetCommState(handler, &dcbSerialParameters))
{
printf("ALERT: could not set Serial port parameters\n");
}
else {
this->connected = true;
PurgeComm(this->handler, PURGE_RXCLEAR | PURGE_TXCLEAR);
Sleep(ARDUINO_WAIT_TIME);
}
}
}
}
SerialPort::~SerialPort()
{
if (this->connected) {
this->connected = false;
CloseHandle(this->handler);
}
}
int SerialPort::readSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesRead;
unsigned int toRead;
ClearCommError(this->handler, &this->errors, &this->status);
if (this->status.cbInQue > 0) {
if (this->status.cbInQue > buf_size) {
toRead = buf_size;
}
else toRead = this->status.cbInQue;
}
if (ReadFile(this->handler, buffer, toRead, &bytesRead, NULL)) return bytesRead;
return 0;
}
bool SerialPort::writeSerialPort(char *buffer, unsigned int buf_size)
{
DWORD bytesSend;
if (!WriteFile(this->handler, (void*)buffer, buf_size, &bytesSend, 0)) {
ClearCommError(this->handler, &this->errors, &this->status);
return false;
}
else return true;
}
bool SerialPort::isConnected()
{
return this->connected;
}
Thank you in advance.

C++ get picture from HTTP response

I'm trying to download picture from website. The problem is that even tho I get all the content from HTTP response body, file won't open. I've been trying to solve this but I can't find the real problem. One thing I did notice is that picture downloaded using chromium displays different characters than picture downloaded from my code using command:
$ cat picture.png | less
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <fstream>
#include <iostream>
using std::cout;
using std::endl;
//with this function I remove HTTP header info, so I only get content.
char *removeHTTPHeader(char *buffer) {
char *t = strstr(buffer, "\r\n\r\n");
t = t + 4;
return t;
}
void getPicture(const int &socketfd, const int &bSize) {
std::ofstream file("picture.png",
std::ofstream::binary | std::ofstream::out);
char buffer[bSize];
ssize_t bReceived;
bReceived = recv(socketfd, buffer, bSize, 0);
char *t = removeHTTPHeader(buffer);
file.write(t, strlen(t));
memset(buffer, 0, bSize);
while ((bReceived = recv(socketfd, buffer, bSize, 0)) > 0) {
file.write(buffer, bReceived);
memset(buffer, 0, bSize);
}
file.close();
}
int main() {
int status;
addrinfo host_info;
addrinfo *host_info_list;
memset(&host_info, 0, sizeof(host_info));
host_info.ai_family = AF_UNSPEC;
host_info.ai_socktype = SOCK_STREAM;
host_info.ai_protocol = 0;
status = getaddrinfo("www.pngimg.com", "80", &host_info, &host_info_list);
if (status != 0) {
cout << "getaddrinfo error" << endl;
}
int socketfd;
socketfd = socket(host_info_list->ai_family, host_info_list->ai_socktype,
host_info_list->ai_protocol);
addrinfo *rp;
for (rp = host_info_list; rp != NULL; rp = rp->ai_next) {
socketfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
if (socketfd == -1) {
cout << "socket error" << endl;
}
if (connect(socketfd, rp->ai_addr, rp->ai_addrlen) != -1) {
break;
}
close(socketfd);
}
if (rp == NULL) {
cout << "Could not connect!" << endl;
exit(EXIT_FAILURE);
}
freeaddrinfo(host_info_list);
const char *msg =
"GET /upload/water_PNG3290.png HTTP/1.1\r\nhost: www.pngimg.com\r\nConnection: close\r\n\r\n";
status = send(socketfd, msg, strlen(msg), 0);
if (status == -1) {
cout << "error sending" << endl;
exit(EXIT_FAILURE);
}
getPicture(socketfd, 1024);
close(socketfd);
return 0;
}
Here is picture from using cat command:
terminal above is picture from my code, below is picture from chromium "save as"
Problem was that I didn't know that in C style string you can't do strlen on binary data. That's why I had to add counter in function removeHTTPHeader. Below are function getPicture and removeHTTPHeader that I've changed.
char *removeHTTPHeader(char *buffer, int &bodySize) {
char *t = strstr(buffer, "\r\n\r\n");
t = t + 4;
for (auto it = buffer; it != t; ++it) {
++bodySize;
}
return t;
}
void getPicture(const int &socketfd, const int &bSize) {
std::ofstream file("picture.png",
std::ofstream::binary | std::ofstream::out);
char buffer[bSize];
ssize_t bReceived;
bReceived = recv(socketfd, buffer, bSize, 0);
int bodySize = 0;
char *t = removeHTTPHeader(buffer, bodySize);
bodySize = bReceived - bodySize;
file.write(t, bodySize);
memset(buffer, 0, bSize);
while ((bReceived = recv(socketfd, buffer, bSize, 0)) > 0) {
file.write(buffer, bReceived);
memset(buffer, 0, bSize);
}
file.close();
}