//---------------------------------------------------------------------------
//#pragma hdrstop
//#include "stdafx.h"
//---------------------------------------------------------------------------
#include "ComPort.h"
#include <sstream>
#include <iostream>
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	//#define WIN32_LEAN_AND_MEAN //По моему это для выбора функции поиска файлов по умолчанию
	//#define NOMINMAX
	#include <windows.h>
	//#include <minwinbase.h>
	#include <winnt.h>
	//#include <fileapi.h>
#else
	#include <stdio.h> // standard input / output functions
	#include <string.h> // string function definitions
	#include <unistd.h> // UNIX standard function definitions
	#include <fcntl.h> // File control definitions
	#include <errno.h> // Error number definitions
	#include <termios.h> // POSIX terminal control definitionss
	#include <time.h>   // time calls
#endif

//#include <stdTools.h>

#include <sstream>
//---------------------------------------------------------------------------
#if defined( _BORLAND )
	#pragma package(smart_init)
#endif
//---------------------------------------------------------------------------
/*template <typename T>
std::string toString2(T val)
{
	std::ostringstream oss;
	oss << val;
	return oss.str();

}*/
//---------------------------------------------------------------------------
/*std::string getComName(int num)
{
//	if(num<10) return "COM"+IntToStr(num);
//	else
		return "\\\\.\\COM"+toString2(num);
}*/
//------------------------------------------------------------------------------
ComPort::ComPort()
{
	//m_time=0;
	hCom=0;
	ComNumber=1;
	BaudRate=115200;
	bOpen=false;
}
//------------------------------------------------------------------------------
ComPort::~ComPort()
{
	Close();
}
//------------------------------------------------------------------------------
void ComPort::CheckBaudRate()
{
	if(BaudRate==0) BaudRate=1200;
	if(BaudRate==1) BaudRate=2400;
	if(BaudRate==2) BaudRate=4800;
	if(BaudRate==3) BaudRate=9600;
	if(BaudRate==4) BaudRate=19200;
	if(BaudRate==5) BaudRate=38400;
	if(BaudRate==6) BaudRate=57600;
	if(BaudRate==7) BaudRate=115200;
}
//------------------------------------------------------------------------------
bool ComPort::Open(std::string ComNumber)
{
	if(hCom!=0) Close(); //Если открыт ком порт закроем
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	this->ComNumber=ComNumber;
	std::string port="\\\\.\\COM";
	port+=ComNumber;
	hCom = CreateFileA(
			port.c_str(),
			GENERIC_READ | GENERIC_WRITE,	// Доступ для чтения и записи
			0,								// Без совместного использования
			NULL,							// Без защиты
			OPEN_EXISTING,					// Только если существует
			FILE_ATTRIBUTE_NORMAL,			// Без дополнительных атрибутов
			NULL							// Без шаблона файла
			);
	if(hCom == INVALID_HANDLE_VALUE) bOpen=false; else bOpen=true;

#else
	hCom = open(ComNumber.c_str(), O_RDWR | O_NOCTTY | O_NDELAY);
	if(hCom== -1)
	{
		//printf("Unable to open /dev/ttyS0. \n");
		std::cout << "Unable to open " << ComNumber << std::endl;
		bOpen=false;
	}else
	{
		fcntl(hCom, F_SETFL, 0);
		//printf("port is open.\n");
		bOpen=true;
	}
#endif
	return bOpen;
}
//------------------------------------------------------------------------------
bool ComPort::Open(std::wstring ComNumber)
{
	std::string str( ComNumber.begin(), ComNumber.end() );
	return Open(str);
}
//------------------------------------------------------------------------------
bool ComPort::Close()
{
	bool result=true;
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	if(bOpen){
		if(CloseHandle(hCom))
		{
			hCom=0;
			bOpen=false;
		}
	}
#else
	if(close(hCom) == -1)
	{
		hCom=0;
		result=false;
	}else
	{
		hCom=0;
		bOpen=false;
		result=true;
	}
#endif
	return result;
}
//------------------------------------------------------------------------------
bool ComPort::SetupDCB(int BaudRate,int ByteSize)
{
	this->BaudRate = BaudRate;
	CheckBaudRate(); //из 1,2,3... в 1200,2400,4800...

#if defined(WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)

	int RxBufferSize = 2048;
	int TxBufferSize = 2048;
	if (!SetupComm(hCom, RxBufferSize, TxBufferSize)) return false;

	DCB dcb; //Описание в https://ru.wikibooks.org/wiki/COM-порт_в_Windows_(программирование)
	memset((void *)&dcb, (int)0, (size_t)sizeof(dcb));
	dcb.DCBlength = sizeof(DCB);

	if(!GetCommState(hCom, &dcb)){ //Берём текущие настройки из винды
		return false;
	}
	dcb.BaudRate = BaudRate;

	dcb.ByteSize = ByteSize;
	dcb.Parity = NOPARITY;
	dcb.StopBits = ONESTOPBIT;
	dcb.fAbortOnError = FALSE;				// Задает игнорирование всех операций чтения/записи при возникновении ошибки. Если это поле равно TRUE, драйвер прекращает все операции чтения/записи для порта при возникновении ошибки. Продолжать работать с портом можно будет только после устранения причины ошибки и вызова функции ClearCommError.
	dcb.fDtrControl = DTR_CONTROL_ENABLE;	// Задает режим управления обменом для сигнала DTR.
	dcb.fRtsControl = RTS_CONTROL_ENABLE;	// Задает режим управления потоком для сигнала RTS
	dcb.fBinary = TRUE;						// Win32 не поддерживает недвоичный режим, поэтому данное поле всегда должно быть равно 1
	dcb.fParity = FALSE;					// Включает режим контроля четности. Если это поле равно TRUE, то выполняется проверка четности, при ошибке, в вызывающую программу, выдается соответствующий код завершения.
	dcb.fInX = FALSE;						// Задает использование XON/XOFF управления потоком при приеме. Если это поле равно TRUE, то драйвер передает символ XoffChar, когда в приемном буфере находится более XoffLim, и XonChar, когда в приемном буфере остается менее XonLim символов.
	dcb.fOutX = FALSE;						// Задает использование XON/XOFF управления потоком при передаче. Если это поле равно TRUE, то передача останавливается при приеме символа XoffChar, и возобновляется при приеме символа XonChar
	dcb.XonChar = 0;						// Tx and Rx XON character
	dcb.XoffChar = (unsigned char)0xFF;		// Tx and Rx XOFF character
	dcb.fErrorChar = FALSE;					// error replacement character
	dcb.fNull = FALSE;						//Определяет действие выполняемое при приеме нулевого байта. Если это поле TRUE, то нулевые байты отбрасываются при передаче.
	dcb.fOutxCtsFlow = FALSE;				//Включает режим слежения за сигналом [[|CTS]]. Если это поле равно [[|TRUE]] и сигнал [[|CTS]] сброшен, передача данных приостанавливается до установки сигнала CTS. Это позволяет подключеному к компьютеру прибору приостановить поток передаваемой в него информации, если он не успевает ее обрабатывать.
	dcb.fOutxDsrFlow = FALSE;				//Включает режим слежения за сигналом [[|DSR]]. Если это поле равно TRUE и сигнал DSR сброшен, передача данных прекращается до установки сигнала DSR.
	dcb.XonLim = 128;						//Задает минимальное число символов в приемном буфере перед посылкой символа XON.
	dcb.XoffLim = 128;						//Определяет максимальное количество байт в приемном буфере перед посылкой символа XOFF. Максимально допустимое количество байт в буфере вычисляется вычитанием данного значения из размера приемного буфера в байтах.

	if(!SetCommState(hCom, &dcb)) return false;
#else

#endif
	return true;
}
//------------------------------------------------------------------------------
//num - номер настроек под разное оборудование (num=1 то атоловские настройки для ком порта)
bool ComPort::Setup(int num)
{
	CheckBaudRate(); //из 1,2,3... в 1200,2400,4800...

#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	int RxBufferSize = 2048;
	int TxBufferSize = 2048;
	if(!SetupComm(hCom, RxBufferSize, TxBufferSize)) return false;

	DCB dcb;
	memset(&dcb,0,sizeof(dcb));
	dcb.DCBlength = sizeof (DCB);
	GetCommState(hCom,&dcb); //Берём текущие настройки из винды
	dcb.BaudRate=BaudRate;

	if(num==-1) //Настройки для Фрезерного станка с ЧПУ
	{
 		dcb.ByteSize = 8;
 		dcb.Parity = NOPARITY;
 		dcb.StopBits = ONESTOPBIT;
 		dcb.fAbortOnError = TRUE;
		dcb.fDtrControl = DTR_CONTROL_DISABLE;
 		dcb.fRtsControl = RTS_CONTROL_DISABLE;
 		dcb.fBinary = TRUE;
 		dcb.fParity = FALSE;
 		dcb.fInX = FALSE;
		dcb.fOutX = FALSE;
 		dcb.XonChar = 0;
 		dcb.XoffChar = (unsigned char)0xFF;
 		dcb.fErrorChar = FALSE;
 		dcb.fNull = FALSE; //Определяет действие выполняемое при приеме нулевого байта. Если это поле TRUE, то нулевые байты отбрасываются при передаче.
 		dcb.fOutxCtsFlow = FALSE; //Включает режим слежения за сигналом [[|CTS]]. Если это поле равно [[|TRUE]] и сигнал [[|CTS]] сброшен, передача данных приостанавливается до установки сигнала CTS. Это позволяет подключеному к компьютеру прибору приостановить поток передаваемой в него информации, если он не успевает ее обрабатывать.
 		dcb.fOutxDsrFlow = FALSE; //Включает режим слежения за сигналом [[|DSR]]. Если это поле равно TRUE и сигнал DSR сброшен, передача данных прекращается до установки сигнала DSR.
		dcb.XonLim = 128; //Задает минимальное число символов в приемном буфере перед посылкой символа XON.
		dcb.XoffLim = 128; //Определяет максимальное количество байт в приемном буфере перед посылкой символа XOFF. Максимально допустимое количество байт в буфере вычисляется вычитанием данного значения из размера приемного буфера в байтах.
	}
	else if(num==0) //Настройки для ПОРТ 300 100
	{
		//if(!GetCommState(hCom, &dcb)) return false;
		dcb.fBinary=1;
		//dcb.fDtrControl=DTR_CONTROL_ENABLE; //Без этого 0x03 не принималось с принтера а потом начала принимать и без...
		dcb.fRtsControl=RTS_CONTROL_ENABLE;
		dcb.XonLim=2048;
		dcb.XoffLim=512;
		dcb.ByteSize=8;
		dcb.XonChar=17;
		dcb.XoffChar=19;
	}else
	if(num==1) //Настройки для Аура-01ФР-KZ
	{
		dcb.DCBlength = sizeof (DCB);
		dcb.fBinary=1;
		dcb.XonLim=2048;
		dcb.XoffLim=512;
		dcb.ByteSize=8;
		dcb.XonChar=17;
		dcb.XoffChar=19;
		}else
	if(num==2) //Настройки для CashCode
	{
		//if(!GetCommState(hCom, &dcb)) return false;
		dcb.ByteSize=8;
		dcb.Parity=NOPARITY;
		dcb.StopBits=ONESTOPBIT;
		dcb.fDtrControl=DTR_CONTROL_ENABLE;
	}else
	if(num==3) //Настройки для дисплея покупателя WINCOR NIXDORF
	{
		dcb.ByteSize=8;
		dcb.fBinary=1;

		//Проверка чётности
		dcb.fParity=TRUE;
		dcb.Parity=ODDPARITY;

		dcb.StopBits=ONESTOPBIT;
		dcb.fRtsControl = RTS_CONTROL_DISABLE;
		dcb.fDtrControl = DTR_CONTROL_DISABLE;
		//dcb.fDtrControl=DTR_CONTROL_ENABLE;

	}else //Свои настройки
	{
		if(!GetCommState(hCom, &dcb)) return false; //Берём текущие настройки

		dcb.fBinary = TRUE;				// В винде только двоичный режим всегда 1
		dcb.fParity = TRUE;				// Если этот член структуры - ИСТИНА (TRUE), выполняется проверка четности и сообщается об ошибках...
		dcb.ByteSize = 8;				// Number of bits/byte, 4-8

		dcb.Parity = NOPARITY;			// Используемая схема четности. (EVENPARITY Проверка по четности MARKPARITY Проверка четности по метке NOPARITY Без проверки четности ODDPARITY Проверка по нечетности SPACEPARITY Проверка четности по паузе)
		dcb.fTXContinueOnXoff = FALSE;	// Если FALSE то будет следить за переполнением принимающего буфера.
		dcb.fNull = TRUE;
		dcb.StopBits = ONESTOPBIT;

		/*EFlowControl fc;
		switch (fc)
		{
			case ENoFlowControl: // No HandShaking
			{
				dcb.fOutxCtsFlow = FALSE; // Disable CTS(Clear To Send) monitoring
				dcb.fOutxDsrFlow = FALSE; // Disable DSR(Data Set Ready) monitoring
				dcb.fDtrControl = DTR_CONTROL_DISABLE; //Сигнал  DTR (готовности терминала к передаче данных)  управления потоком данных. Этот член структуры может быть одним из следующих значений.
				//DTR_CONTROL_ENABLE	Включает линию DTR, когда устройство открывается и оставляет ее включенной.
				//DTR_CONTROL_HANDSHAKE	Отключает линию DTR, когда устройство открывается и оставляет ее заблокированной.
				//DTR_CONTROL_DISABLE	Включает  процедуру установления связи DTR. Если процедура установления связи включена, она является ошибкой для приложения, которое корректировать линию, используя функцию EscapeCommFunction.

				dcb.fRtsControl = RTS_CONTROL_DISABLE; // Disable RTS (Ready To Send) monitoring
				dcb.fOutX = FALSE; // Disable XON/XOFF for transmission (Управление потоком (это своойство есть в гипертерминале))
				dcb.fInX = FALSE; // Disable XON/XOFF for receiving
				break;
			}
			case EXonXoffFlowControl: // Software Handshaking
			{
				dcb.fOutxCtsFlow = FALSE;
				dcb.fOutxDsrFlow = FALSE;
				dcb.fDtrControl = DTR_CONTROL_DISABLE;
				dcb.fRtsControl = RTS_CONTROL_DISABLE;
				dcb.fOutX = TRUE;
				dcb.fInX = TRUE;
				dcb.XonChar = 0x11;
				dcb.XoffChar = 0x13;
				dcb.XoffLim = 100;
				dcb.XonLim = 100;
				break;
			}
			case EFullHardwareFlowControl: // Hardware Handshaking
			{*/
				dcb.fOutxCtsFlow = TRUE;
				dcb.fOutxDsrFlow = TRUE;
				dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
				dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
				dcb.fOutX = FALSE;
				dcb.fInX = FALSE;
			/*}
			case ECtsRtsFlowControl:
			{
				dcb.fOutxCtsFlow = TRUE;
				dcb.fOutxDsrFlow = FALSE;
				dcb.fDtrControl = DTR_CONTROL_DISABLE;
				dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
				dcb.fOutX = FALSE;
				dcb.fInX = FALSE;
				break;
			}
			case ECtsDtrFlowControl:
			{
				dcb.fOutxCtsFlow = TRUE;
				dcb.fOutxDsrFlow = FALSE;
				dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
				dcb.fRtsControl = RTS_CONTROL_DISABLE;
				dcb.fOutX = FALSE;
				dcb.fInX = FALSE;
				break;
			}
			case EDsrRtsFlowControl:
			{
				dcb.fOutxCtsFlow = FALSE;
				dcb.fOutxDsrFlow = TRUE;
				dcb.fDtrControl = DTR_CONTROL_DISABLE;
				dcb.fRtsControl = RTS_CONTROL_HANDSHAKE;
				dcb.fOutX = FALSE;
				dcb.fInX = FALSE;
				break;
			}
			case EDsrDtrFlowControl:
			{
				dcb.fOutxCtsFlow = FALSE;
				dcb.fOutxDsrFlow = TRUE;
				dcb.fDtrControl = DTR_CONTROL_HANDSHAKE;
				dcb.fRtsControl = RTS_CONTROL_DISABLE;
				dcb.fOutX = FALSE;
				dcb.fInX = FALSE;
				break;
			}
			default:
			{
				RETAILMSG(1,(_T("CSerial::Setup - %s flow control assigned
				Failed!!"), sPort));
				return;
			}
		}*/
	}
	if(!SetCommState(hCom, &dcb)) return false;
#else
	int result=-1;
	struct termios tty;      // structure to store the port settings in
	memset (&tty, 0, sizeof tty);
    if (tcgetattr (hCom, &tty) != 0)
    {
    	std::cout << "Error read serial port config." << std::endl;
    	return false;
    }

	switch(BaudRate)
	{
	case 1200:
		result = cfsetospeed(&tty, B1200);
		break;
	case 1800:
		result = cfsetospeed(&tty, B1800);
		break;
	case 2400:
		result = cfsetospeed(&tty, B2400);
		break;
	case 4800:
		result = cfsetospeed(&tty, B4800);
		break;
	case 9600:
		result = cfsetospeed(&tty, B9600);
		break;
	case 19200:
		result = cfsetospeed(&tty, B19200);
		break;
	case 38400:
		result = cfsetospeed(&tty, B38400);
		break;
	case 57600:
		result = cfsetospeed(&tty, B57600);
		break;
	case 115200:
		result = cfsetospeed(&tty, B115200);
		break;
	default:
		cfsetospeed(&tty, BaudRate);
	}
	if(result == -1)
	{
		std::cout << "Error set baud rate \"" << BaudRate << "\"." << std::endl;
	}

	if(num==0) //Настройки для ПОРТ 300 100
	{
		//Отключаю "канонический" режим те. возможность редактирования в буфере до получения символа /r или /n
		tty.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
		/*tty.c_lflag &= ~ICANON; // Don't canonicalise
		tty.c_lflag &= ~ECHO; // Don't echo
		tty.c_lflag &= ~ECHOK; // Don't echo
		tty.c_lflag &= ~ECHOE;*/

		//Similarly, to disable hardware flow control:
		//tty.c_cflag &= ~CNEW_RTSCTS;

        // set no parity, stop bits, data bits
        tty.c_cflag &= ~PARENB;
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CSIZE;
        tty.c_cflag |= CS8; //Размер байта


/*
        tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8;     // 8-bit chars
        // disable IGNBRK for mismatched speed tests; otherwise receive break
        // as \000 chars
        tty.c_iflag &= ~IGNBRK;         // disable break processing
        tty.c_lflag = 0;                // no signaling chars, no echo,
                                        // no canonical processing
        tty.c_oflag = 0;                // no remapping, no delays
        tty.c_cc[VMIN]  = 0;            // read doesn't block
        tty.c_cc[VTIME] = 5;            // 0.5 seconds read timeout

        tty.c_iflag &= ~(IXON | IXOFF | IXANY); // shut off xon/xoff ctrl

        tty.c_cflag |= (CLOCAL | CREAD);// ignore modem controls,
                                        // enable reading
        tty.c_cflag &= ~(PARENB | PARODD);      // shut off parity
        tty.c_cflag |= 0; //parity; no parity
        tty.c_cflag &= ~CSTOPB;
        tty.c_cflag &= ~CRTSCTS;
*/

	}

    if(tcsetattr(hCom, TCSANOW, &tty) != 0)
    {
    	std::cout << "Error set attributes." << std::endl;
    	return -1;
    }

#endif

	return true;
}
//------------------------------------------------------------------------------
//Если time=0 то не ждет данные и с разу выдает все что в буфере
//Если задать миллисекунды то это время доожидания следующего байта (не ставить меньше 10 миллисекунд)

//Операция чтения работает асинхронно те. не ждёт данные за временем нужно следить самому ! (читать байты в цикле с задержкой)
//Подробное оисание: http://www.vsokovikov.narod.ru/New_MSDN_API/Comm_res/str_commtimeouts.htm
//time - время в миллисекундах (не ставить меньше 10 миллисекунд)
bool ComPort::SetTimeout(unsigned long time)
{
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	COMMTIMEOUTS CommTimeouts;

	CommTimeouts.ReadIntervalTimeout = time; //Максимальное время, которое допускается для интервала между поступлением двух символов в миллисекундах (отсчёт после первого символа)
	CommTimeouts.ReadTotalTimeoutMultiplier  = 0; //Множитель умножается на число проч. байтов получаются милисекунды которые прибовляются к нижнему
	CommTimeouts.ReadTotalTimeoutConstant    = time; //Это время простоя прибавляется к (ReadTotalTimeoutMultiplier * кол-во прочитанных байт)
	CommTimeouts.WriteTotalTimeoutMultiplier = 0; //Множитель умножается на число зап. байтов получаются милисекунды которые прибовляются к нижнему
	CommTimeouts.WriteTotalTimeoutConstant   = 0; //Это время простоя для записи прибавляется к (WriteTotalTimeoutMultiplier * кол-во записанных байт)
/*
	CommTimeouts.ReadIntervalTimeout = MAXDWORD; //Максимальное время, которое допускается для интервала между поступлением двух символов
	CommTimeouts.ReadTotalTimeoutMultiplier  = 0; //Множитель умножается на число проч. байтов получаются милисекунды которые прибовляются к нижнему
	CommTimeouts.ReadTotalTimeoutConstant    = time; //Это время простоя прибавляется к (ReadTotalTimeoutMultiplier * кол-во прочитанных байт)
	CommTimeouts.WriteTotalTimeoutMultiplier = 0; //Множитель умножается на число зап. байтов получаются милисекунды которые прибовляются к нижнему
	CommTimeouts.WriteTotalTimeoutConstant   = time; //Это время простоя для записи прибавляется к (WriteTotalTimeoutMultiplier * кол-во записанных байт)
*/
	return SetCommTimeouts(hCom, &CommTimeouts)!=0; //В MSDN так написанно
#else
	struct termios termios;
	tcgetattr(hCom, &termios);

	termios.c_cc[VMIN] = 0; //Не учитываем кол-во байт а только время
	termios.c_cc[VTIME] = time/10.0f; //Время в 0.1 секунду поэтому разделил на 10

	tcsetattr(hCom, TCSANOW, &termios);
#endif
	return true;
}
//------------------------------------------------------------------------------
//Записать буфер в COM порт
unsigned long ComPort::Write(const void* lpBuffer,unsigned long nNumberOfBytesToWrite)
{
	if (nNumberOfBytesToWrite == 0) return 0; //А то через блютуз подвисало
	unsigned long lpNumberOfBytesWritten=0;
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	WriteFile(hCom, lpBuffer, nNumberOfBytesToWrite, &lpNumberOfBytesWritten, NULL);
#else
	lpNumberOfBytesWritten = write(hCom,lpBuffer,nNumberOfBytesToWrite);
#endif
	return lpNumberOfBytesWritten;
}
//------------------------------------------------------------------------------
//Записать строку в COM порт
unsigned long ComPort::WriteString(std::string str)
{
	return Write(str.c_str(),str.length());
}
//------------------------------------------------------------------------------
//Записать 1 байт в COM порт
unsigned char ComPort::WriteChar(signed char ch)
{
	return (unsigned char)Write(&ch,1);
}
//------------------------------------------------------------------------------
unsigned char ComPort::WriteUChar(unsigned char ch)
{
	return (unsigned char)Write(&ch,1);
}
//------------------------------------------------------------------------------
unsigned char ComPort::WriteUInt(unsigned int val)
{
	return (unsigned char)Write(&val,4);
}
//------------------------------------------------------------------------------
//Прочитать байты из COM порта в буфер
int ComPort::Read(void* lpBuffer,unsigned long nNumberOfBytesToRead)
{
	int result=0;
	if (nNumberOfBytesToRead == 0) return 0;
#if defined(_WIN32) || defined(_WINDOWS) || defined(_BORLAND) || defined(__BORLANDC__)
	unsigned long lpNumberOfBytesRead;
	BOOL error = ReadFile(hCom, lpBuffer, nNumberOfBytesToRead, &lpNumberOfBytesRead, NULL);
	if (!error) {
		result=-1; // Указание на ошибку
	}else{
		result = lpNumberOfBytesRead;
	}
#else
	result = read(hCom, lpBuffer, nNumberOfBytesToRead);
#endif
	return result;
}
//------------------------------------------------------------------------------
//Так как может выдавать данные порциями
int ComPort::ReadAll(void* lpBuffer, unsigned long nNumberOfBytesToRead) {
	if (nNumberOfBytesToRead == 0) return 0;
	DWORD len=0;
	int pos = 0;
	while (true) {
		ReadFile(hCom, lpBuffer, nNumberOfBytesToRead, &len, NULL);
		if (len <= 0) break;
		pos += len;
		nNumberOfBytesToRead -= len;
		if (nNumberOfBytesToRead == 0)
			break;
	}
	return pos;
}
//------------------------------------------------------------------------------
//Читать до символа и этот символ в результат не входит
int ComPort::ReadUntilChar(void* lpBuffer, unsigned long maxLen, char suffix,bool* error){
	*error=true;
	if(maxLen == 0) return 0;
	unsigned long pos=0;
	char ch;
	while (true) {
		if(Read(&ch, 1)!=1){
			break;
		}else{
			if(ch==suffix){
				*error=false;
				break;
			}
			((char*)lpBuffer)[pos]=ch;
			pos++;
			if(maxLen==pos){
				break;
			}
		}
	}
	return pos;
}
//------------------------------------------------------------------------------
//Прочитать байт из ком порта
unsigned char ComPort::ReadUInt1(bool* b)
{
	unsigned char result=0;
	if(Read(&result, 1)!=1)
		*b=false;
	else
		*b=true;
	return result;
}
//------------------------------------------------------------------------------
