Files
UnmannedShip/depends/lpmsig1opensourcelib-v0.3.0-20210907-a15087c817ad/SerialPort.cpp
T
2026-07-27 14:50:01 +08:00

366 lines
9.5 KiB
C++

#include "SerialPort.h"
#include <algorithm>
using namespace std;
Serial::Serial():
portNo(0),
connected(false),
usbMode(MODE_USB_EXPRESS)
{
}
Serial::~Serial()
{
//Check if we are connected before trying to disconnect
close();
}
bool Serial::open(int portno, int baudrate)
{
if (isConnected())
CloseHandle(this->hSerial);
//if (usbMode == MODE_USB_EXPRESS)
// return open("0001");
portNo = portno;
stringstream ss;
ss << "\\\\.\\COM" << portNo;
string portName = ss.str();
//We're not yet connected
this->connected = false;
//Try to connect to the given port throuh CreateFile
this->hSerial = CreateFile(portName.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
0,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
//Check if the connection was successfull
if (this->hSerial == INVALID_HANDLE_VALUE)
{
printf("[Serial] ERROR: Invalid handle value\n");
CloseHandle(this->hSerial);
return false;
}
else
{
char mode_str[128];
switch (baudrate)
{
case BAUDRATE_4800:
strcpy(mode_str, "baud=4800");
break;
case BAUDRATE_9600:
strcpy(mode_str, "baud=9600");
break;
case BAUDRATE_19200:
strcpy(mode_str, "baud=19200");
break;
case BAUDRATE_38400:
strcpy(mode_str, "baud=38400");
break;
case BAUDRATE_57600:
strcpy(mode_str, "baud=57600");
break;
case BAUDRATE_115200:
strcpy(mode_str, "baud=115200");
break;
case BAUDRATE_230400:
strcpy(mode_str, "baud=230400");
break;
case BAUDRATE_256000:
strcpy(mode_str, "baud=256000");
break;
case BAUDRATE_460800:
strcpy(mode_str, "baud=460800");
break;
case BAUDRATE_921600:
strcpy(mode_str, "baud=921600");
break;
}
strcat(mode_str, " data=8");
strcat(mode_str, " parity=n");
strcat(mode_str, " stop=1");
strcat(mode_str, " dtr=on rts=on");
DCB port_settings;
memset(&port_settings, 0, sizeof(port_settings)); /* clear the new struct */
port_settings.DCBlength = sizeof(port_settings);
if (!BuildCommDCBA(mode_str, &port_settings))
{
printf("unable to set comport dcb settings\n");
CloseHandle(this->hSerial);
return false;
}
if (!BuildCommDCBA(mode_str, &port_settings))
{
printf("unable to set comport dcb settings\n");
CloseHandle(this->hSerial);
return false;
}
if (!SetCommState(this->hSerial, &port_settings))
{
printf("unable to set comport cfg settings\n");
CloseHandle(this->hSerial);
return false;
}
COMMTIMEOUTS Cptimeouts;
Cptimeouts.ReadIntervalTimeout = MAXDWORD;
Cptimeouts.ReadTotalTimeoutMultiplier = 0;
Cptimeouts.ReadTotalTimeoutConstant = 0;
Cptimeouts.WriteTotalTimeoutMultiplier = 100;
Cptimeouts.WriteTotalTimeoutConstant = 100;
if (!SetCommTimeouts(this->hSerial, &Cptimeouts))
{
printf("unable to set comport time-out settings\n");
CloseHandle(this->hSerial);
return false;
}
}
this->connected = true;
return true;
}
bool Serial::open(std::string deviceId, int baudrate)
{
bool f;
transform(deviceId.begin(), deviceId.end(), deviceId.begin(), ::toupper);
this->idNumber = deviceId;
std::cout << "[LpmsU] Lpms::connect deviceID is : " << deviceId << std::endl;
f = false;
SI_STATUS siStatus;
DWORD devercNum = 0;
SI_DEVICE_STRING DeviceString;
this->idNumber = deviceId;
DWORD numDevs;
if (SI_GetNumDevices(&numDevs) != SI_SUCCESS)
return false;
devercNum = numDevs;
for (DWORD d = 0; d < numDevs; d++)
{
siStatus = SI_GetProductString(d, DeviceString, SI_RETURN_SERIAL_NUMBER);
if (siStatus == SI_SUCCESS)
{
string deviceString = string(DeviceString);
transform(deviceString.begin(), deviceString.end(), deviceString.begin(), ::toupper);
if (deviceId == deviceString)
{
devercNum = d;
break;
}
}
}
siStatus = SI_Open(devercNum, &cyHandle);
siStatus = SI_SetBaudRate(cyHandle, baudrate);
siStatus = SI_SetFlowControl(cyHandle, SI_HANDSHAKE_LINE, SI_FIRMWARE_CONTROLLED, SI_HELD_INACTIVE, SI_STATUS_INPUT, SI_STATUS_INPUT, 0);
if (siStatus == SI_SUCCESS) {
std::cout << "[LpmsU] SI_Open device is successul : " << deviceId << std::endl;
this->connected = true;
SI_FlushBuffers(cyHandle, TRUE, TRUE);
}
else {
std::cout << "[LpmsU] SI_Open device is failed : " << deviceId << std::endl;
this->connected = false;
}
return this->connected ;
}
void Serial::setMode(int mode)
{
usbMode = mode;
}
int Serial::getMode(void)
{
return usbMode;
}
bool Serial::close()
{
if (this->connected)
{
//We're no longer connected
this->connected = false;
//Close the serial handler
if (usbMode == MODE_USB_EXPRESS)
{
SI_Close(cyHandle);
cout << "[LpmsU] Connection to " << idNumber << " closed." << endl;
}
else
{
return CloseHandle(this->hSerial);
}
}
return true;
}
int Serial::readData(unsigned char *buffer, unsigned int nbChar)
{
if (!isConnected())
return 0;
if (usbMode == MODE_USB_EXPRESS)
{
SI_STATUS siStatus;
PBYTE ModemStatus;
#ifdef _WIN32
unsigned long eventDWord;
unsigned long txBytes;
unsigned long rxBytes;
unsigned long qStatus;
#else
unsigned int eventDWord;
unsigned int txBytes;
unsigned int rxBytes;
#endif
bool f = true;
unsigned long bytesReceived = 0;
if (this->connected == false) return 0;
siStatus = SI_CheckRXQueue(cyHandle, &rxBytes, &qStatus);
if (siStatus != SI_SUCCESS)
{
std::cout << "USB read error\n";
return false;
}
#ifdef _WIN32
siStatus = SI_Read(cyHandle, buffer, rxBytes, &bytesReceived);
#else
siStatus = SI_Read(cyHandle, buffer, rxBytes, (unsigned int *)bytesReceived);
#endif
return bytesReceived;
}
else
{
//Number of bytes we'll have read
DWORD bytesRead;
//Number of bytes we'll really ask to read
unsigned int toRead;
//int n;
//ReadFile(this->hSerial, buffer, nbChar, (LPDWORD)((void *)&n), NULL);
//return n;
//Use the ClearCommError function to get status info on the Serial port
ClearCommError(this->hSerial, &this->errors, &this->status);
//Check if there is something to read
if (this->status.cbInQue>0)
{
//If there is we check if there is enough data to read the required number
//of characters, if not we'll read only the available characters to prevent
//locking of the application.
if (this->status.cbInQue>nbChar)
{
toRead = nbChar;
}
else
{
toRead = this->status.cbInQue;
}
//Try to read the require number of chars, and return the number of read bytes on success
if (ReadFile(this->hSerial, buffer, toRead, &bytesRead, NULL))
{
return bytesRead;
}
}
//If nothing has been read, or that an error was detected return -1
}
return 0;
}
bool Serial::writeData(const char *buffer, unsigned int nbChar)
{
if (!isConnected())
{
if (usbMode == MODE_USB_EXPRESS)
std::cout << "Sensor " << idNumber << " not connected\n";
else
std::cout << "COM "<< portNo << " not connected\n";
return false;
}
if (usbMode == MODE_USB_EXPRESS)
{
SI_STATUS siStatus;
#ifdef _WIN32
unsigned long bytesWritten;
#else
unsigned int bytesWritten;
#endif
bool f = false;
if (this->connected == false) return false;
siStatus = SI_Write(cyHandle, (unsigned char *)buffer, nbChar, &bytesWritten);
if (siStatus == SI_SUCCESS) {
f = true;
}else{
f = false;
std::cout << "Write error\n";
}
return f;
}
else
{
DWORD bytesSend;
//Try to write the buffer on the Serial port
if (!WriteFile(this->hSerial, (void *)buffer, nbChar, &bytesSend, 0))
{
std::cout << "Write error\n";
//In case it don't work get comm error and return false
ClearCommError(this->hSerial, &this->errors, &this->status);
return false;
}
else
{
return true;
}
}
}
bool Serial::isConnected()
{
//Simply return the connection status
return this->connected;
}