m_nParity = NOPARITY;
m_nStopBits = ONESTOPBIT;
m_nFlowControl = FLOW_NONE;
+ m_writeBlockSize = -1;
+ m_writeDelay = 100;
#ifndef _WIN32
memset(&m_originalSettings, 0, sizeof(m_originalSettings));
#endif
Serial::~Serial()
{
close();
- safe_free(m_pszPort);
+ free(m_pszPort);
}
/**
return -1;
#ifdef _WIN32
+ // Read one byte
DWORD nDone;
-
- if (ReadFile(m_hPort, pBuff, nSize, &nDone, NULL) != 0)
+ if (ReadFile(m_hPort, pBuff, 1, &nDone, NULL))
{
nRet = (int)nDone;
+
+ COMSTAT stat;
+ if (ClearCommError(m_hPort, NULL, &stat))
+ {
+ if (stat.cbInQue > 0)
+ {
+ // Read rest of buffered data
+ if (ReadFile(m_hPort, &pBuff[1], min(stat.cbInQue, (DWORD)nSize - 1), &nDone, NULL))
+ {
+ nRet += (int)nDone;
+ }
+ }
+ }
}
else
{
offset = 0;
- while (offset < nSize)
+ while(offset < nSize)
{
FD_ZERO(&rdfs);
FD_SET(m_hPort, &rdfs);
/**
* Write character(s) to port
*/
-bool Serial::write(const char *pBuff, int nSize)
+bool Serial::writeBlock(const char *data, int length)
{
bool bRet = false;
if (m_hPort == INVALID_HANDLE_VALUE)
return false;
- ThreadSleepMs(100);
+ ThreadSleepMs(m_writeDelay);
#ifdef _WIN32
DWORD nDone;
- if (WriteFile(m_hPort, pBuff, nSize, &nDone, NULL) != 0)
+ if (WriteFile(m_hPort, data, length, &nDone, NULL) != 0)
{
- if (nDone == (DWORD)nSize)
+ if (nDone == (DWORD)length)
{
bRet = true;
}
#else // UNIX
- if (::write(m_hPort, (char *)pBuff, nSize) == nSize)
+ if (::write(m_hPort, (char *)data, length) == length)
{
bRet = true;
}
return bRet;
}
+/**
+ * Write character(s) to port
+ */
+bool Serial::write(const char *data, int length)
+{
+ if (m_writeBlockSize > 0)
+ {
+ int pos = 0;
+ while(pos < length)
+ {
+ int bs = min(m_writeBlockSize, length - pos);
+ if (!writeBlock(&data[pos], bs))
+ return false;
+ pos += bs;
+ }
+ return true;
+ }
+ else
+ {
+ return writeBlock(data, length);
+ }
+}
+
/**
* Flush buffer
*/
static enum { OM_TEXT, OM_PDU } s_operationMode = OM_TEXT;
static bool s_cmgsUseQuotes = true;
+/**
+ * Normalize text buffer (remove non-printable characters)
+ */
+static void NormalizeText(char *text)
+{
+ for(int i = 0; text[i] != 0; i++)
+ if (text[i] < ' ')
+ text[i] = ' ';
+}
+
/**
* Read input to OK
*/
nxlog_debug(5, _T("SMS: ReadToOK: readToMark returned %d"), rc);
return false;
}
+ NormalizeText(buffer);
+ nxlog_debug(5, _T("SMS: ReadToOK buffer content: '%hs'"), buffer);
if (mark != NULL)
{
if (data != NULL)
/**
* Initialize driver
*
- * pszInitArgs format: portname,speed,databits,parity,stopbits,mode
+ * pszInitArgs format: portname,speed,databits,parity,stopbits,mode,blocksize,writedelay
*/
extern "C" bool EXPORT SMSDriverInit(const TCHAR *pszInitArgs, Config *config)
{
int dataBits = 8;
int parity = NOPARITY;
int stopBits = ONESTOPBIT;
+ int blockSize = 8;
+ int writeDelay = 100;
if ((p = _tcschr(portName, _T(','))) != NULL)
{
if (*p == _T('T'))
{
s_operationMode = OM_TEXT;
- }
- else if (*p == _T('N'))
- {
- s_operationMode = OM_TEXT;
- s_cmgsUseQuotes = false;
}
else if (*p == _T('P'))
{
s_operationMode = OM_PDU;
}
+
+ // Use quotes
+ if ((p = _tcschr(p, _T(','))) != NULL)
+ {
+ *p = 0; p++;
+ if (*p == _T('N'))
+ {
+ s_cmgsUseQuotes = false;
+ }
+ else
+ {
+ s_cmgsUseQuotes = true;
+ }
+
+ // block size
+ if ((p = _tcschr(p, _T(','))) != NULL)
+ {
+ *p = 0; p++;
+ blockSize = _tcstol(p, NULL, 10);
+ if ((blockSize < 1) || (blockSize > 256))
+ blockSize = 8;
+
+ // write delay
+ if ((p = _tcschr(p, _T(','))) != NULL)
+ {
+ *p = 0; p++;
+ writeDelay = _tcstol(p, NULL, 10);
+ if ((writeDelay < 1) || (writeDelay > 10000))
+ writeDelay = 100;
+ }
+ }
+ }
}
}
}
parityAsText = _T("NONE");
break;
}
- nxlog_debug(2, _T("SMS init: port=\"%s\", speed=%d, data=%d, parity=%s, stop=%d, pduMode=%s, numberInQuotes=%s"),
+ nxlog_debug(2, _T("SMS init: port=\"%s\", speed=%d, data=%d, parity=%s, stop=%d, pduMode=%s, numberInQuotes=%s blockSize=%d writeDelay=%d"),
portName, portSpeed, dataBits, parityAsText, stopBits == TWOSTOPBITS ? 2 : 1,
(s_operationMode == OM_PDU) ? _T("true") : _T("false"),
- s_cmgsUseQuotes ? _T("true") : _T("false"));
+ s_cmgsUseQuotes ? _T("true") : _T("false"), blockSize, writeDelay);
+ s_serial.setWriteBlockSize(blockSize);
+ s_serial.setWriteDelay(writeDelay);
+
if (s_serial.open(portName))
{
nxlog_debug(5, _T("SMS: port opened"));
goto cleanup;
if ((mark == NULL) || (*mark != '>'))
{
+ NormalizeText(buffer);
nxlog_debug(5, _T("SMS: wrong response to AT+CMGS=%d (%hs)"), (int)strlen(pduBuffer) / 2 - 1, mark);
goto cleanup;
}
s_serial.write(pduBuffer, (int)strlen(pduBuffer)); // send PDU
- s_serial.write("\x1A\r\n", 3); // send ^Z
+ s_serial.write("\x1A", 1); // send ^Z
}
else
{
goto cleanup;
if ((mark == NULL) || (*mark != '>'))
{
+ NormalizeText(buffer);
nxlog_debug(5, _T("SMS: wrong response to AT+CMGS=\"%hs\" (%hs)"), pszPhoneNumber, mark);
goto cleanup;
}
char mbText[161];
WideCharToMultiByte(CP_ACP, WC_DEFAULTCHAR | WC_COMPOSITECHECK, pszText, -1, mbText, 161, NULL, NULL);
mbText[160] = 0;
- snprintf(buffer, sizeof(buffer), "%s\x1A\r\n", mbText);
+ snprintf(buffer, sizeof(buffer), "%s\x1A", mbText);
#else
if (strlen(pszText) <= 160)
{
- snprintf(buffer, sizeof(buffer), "%s\x1A\r\n", pszText);
+ snprintf(buffer, sizeof(buffer), "%s\x1A", pszText);
}
else
{
strncpy(buffer, pszText, 160);
- strcpy(&buffer[160], "\x1A\r\n");
+ strcpy(&buffer[160], "\x1A");
}
#endif
s_serial.write(buffer, (int)strlen(buffer)); // send text, end with ^Z
cleanup:
s_serial.setTimeout(2000);
s_serial.close();
+ nxlog_debug(5, _T("SMS: serial port closed"));
return success;
}