Knowledge Base Nr: 00082 euromap.cpp - http://www.swe-kaiser.de
Downloads:
linux: euromap protokoll (beispiel: MIR - italienische spritzgussmaschinen)
implementiert für Win32 und Linux
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include "logger.h"
#include "SerialCom.h"
#include "mircom.h"
#include "mylib.h"
#ifdef WIN32
#define MIRPORT "COM1"
#define MYTRACE TRACE
#else //UNIX
#define MIRPORT "/dev/ttyS0"
#define MYTRACE printf
#endif
///////////////////////////////////////////////////////////
//c-interface (f.e. oracle)
CLog* g_pLog = 0;
CMIRCom* g_pMIR = 0;
int mir_open(const char* szDevice, const char* szLogfile, int nNoLogfiles)
{
if (g_pLog)
{
delete g_pLog;
g_pLog = 0;
}
if (strstr(szLogfile, "STDOUT"))
{
g_pLog = new CLog();
g_pLog->setLogFileFp(stdout);
}
else
g_pLog = new CLog("./", szLogfile, nNoLogfiles);
if (g_pMIR)
{
delete g_pMIR;
g_pMIR = 0;
}
g_pMIR = new CMIRCom(g_pLog);
return g_pMIR->SetParam(g_pLog, szDevice, 2400, 'e', 7, 1, 'n');
}
int mir_close()
{
if (!g_pMIR)
return -4711;
return g_pMIR->Free();
}
int mir_getParam(const char* szRequest, char* szAnswer, const int nMaxAnswer)
{
if (!g_pMIR)
return -4711;
return g_pMIR->getParam(szRequest, szAnswer, nMaxAnswer);
}
int mir_setParam(const char* szRequest)
{
if (!g_pMIR)
return -4711;
return g_pMIR->setParam(szRequest);
}
const char* mir_getParamStr(const char* szRequest)
{
if (!g_pMIR)
return "*** fehler: mir_open() not called!***";
static char s_szAnswer[4096] = {0};
int nErr = g_pMIR->getParam(szRequest, s_szAnswer, sizeof(s_szAnswer));
if (!nErr)
return s_szAnswer;
return "***fehler von g_pMIR->getParam() zurückgegeben!***";
}
const char* mir_strerror(int nErr)
{
if (!g_pMIR)
return "mir_open() nicht aufgerufen!";
return g_pMIR->GetErrorText(nErr);
}
////////////////////////////////////////////////////////////
///cpp - interface ////////////////////////////////
const int MAXLEN = 4096;
CMIRCom::CMIRCom(CLog* pLog, char* szPort, int nBaudRate, char cParity, int nByteSize, int nStopBits
, char cFlowControl, char cXON, char cXOFF)
: CSerialCom(pLog, szPort, nBaudRate, cParity, nByteSize, nStopBits
, cFlowControl, cXON, cXOFF)
{
}
CMIRCom::~CMIRCom()
{
}
const char* CMIRCom::GetErrorText(int nError)
{
if (nError < MIR_ERROR_OFFSET) //werte -9999999..-1100
return CSerialCom::GetErrorText(nError - MIR_ERROR_OFFSET);
switch (nError)
{
case MIR_OK : return "MIR_OK";
case MIR_NACK_ERROR : return "MIR_NACK_ERROR (NACK statt ACK von mir zurückgegeben)";
case MIR_PARAM_ERROR : return "MIR_PARAM_ERROR (getData: interner puffer zu klein)";
case MIR_WRONG_DATA : return "MIR_WRONG_DATA (getData: illegale daten)";
case MIR_DATA_TOO_LONG: return "MIR_DATA_TOO_LONG (maximale telegrammlänge überschritten)";
case MIR_WRONG_BCC: return "MIR_WRONG_BCC (berechneter bcc unterscheidet sich von mir bcc)";
case MIR_DIFF_TYPES: return "MIR_DIFF_TYPES (unterschiedliche variablenfamilien im selben telegramm)";
case MIR_DATA_NOSPACE: return "MIR_DATA_NOSPACE (abschliessendes space fehlt im telegramm";
}
return "unknown error";
}
char CMIRCom::calcBCC(const char* szData, int nLen)
{
char cBCC = 0;
for (int n=0; n<nLen; n++)
{
cBCC ^= szData[n];
}
return cBCC;
}
int CMIRCom::checkBCC(const char* szData, int nLen)
{
char cBCC = 0;
for (int n=0; n<nLen-1; n++)
{
cBCC ^= szData[n];
}
if (cBCC == szData[nLen])
{
WriteLog(LOGERR, "checkBCC: failed %c(0x%02X) != %c(0x%02X)", cBCC, cBCC, szData[nLen], szData[nLen]);
return -1;
}
return 0;
}
int CMIRCom::checkVariableTypes(const char* szData, int nLen)
{
char cFamily = 0;
for (int n=0; n<nLen; n++)
{
if (cFamily == 0)
{
if ((szData[n] >= 'A') && (szData[n] <= 'Z'))
{
cFamily = szData[n];
}
}
else
{
if ((szData[n] >= 'A') && (szData[n] <= 'Z'))
{
if (szData[n] != cFamily)
{
WriteLog(LOGERR, "checkVariableType: failed %c(0x%02X) != %c(0x%02X)"
, cFamily, cFamily, szData[n], szData[n]);
return -1;
}
}
}
}
return 0;
}
int CMIRCom::sendData(const char* szData, ...)
{
va_list args;
va_start(args, szData);
char szTele[MAXLEN] = {0};
vsprintf(szTele, szData, args);
int nLen = strlen(szTele);
if (nLen > MAXTELEGRAMLENGTH)
return MIR_DATA_TOO_LONG;
int nErr = Write(szTele, nLen);
if (nErr < 0)
{
WriteLog(LOGERR, "interface write <%s> failed: %d", szTele, nErr);
return MIR_ERROR_OFFSET + nErr;
}
return 0;
}
int CMIRCom::sendAck()
{
static int s_nAck = s_nAck ? 0 : 1; //toggle
int nErr = sendData("%c%d", ACK, s_nAck);
if (nErr < 0)
return nErr;
return 0;
}
int CMIRCom::getData(char* szResult, int nResultLenMax)
{
memset(szResult, 0, nResultLenMax);
char cReceive = 0;
int nErr = 0;
int nPos = 0;
int dwStart = CS_GetTickCount();
WriteLog(LOGDATA, "getData : ");
while (1)
{
nErr = ReadByte(&cReceive);
if ((nErr < 0) && (nErr != SC_NO_CHAR))
{
WriteLog(LOGERR, "getData: read failed %d %s(%d)", nErr, strerror(errno), errno);
return MIR_ERROR_OFFSET + nErr;
}
int dwNow = CS_GetTickCount();
if ((dwNow - dwStart) > TIMEOUTREAD)
{
WriteLog(LOGERR, "getData() Timeout (%dms)", TIMEOUTREAD);
return SC_READ_TIMEOUT;
}
if (nErr == SC_NO_CHAR)
continue;
szResult[nPos] = cReceive;
nPos++;
if ((nPos > nResultLenMax) || (nPos > MAXLEN))
{
WriteLog(LOGERR, "getData: buffer to small");
return MIR_PARAM_ERROR;
}
if (cReceive == ETX)
{
nErr = ReadByte(&cReceive, TIMEOUTACK); //bcc überlesen
if (nErr < 0)
{
WriteLog(LOGERR, "getData: read bcc failed %d %s(%d)", nErr, strerror(errno), errno);
return MIR_ERROR_OFFSET + nErr;
}
szResult[nPos] = cReceive;
nPos++;
if (checkBCC(szResult, nPos) < 0)
return MIR_WRONG_BCC;
return nPos;
}
}
return MIR_WRONG_DATA;
}
int CMIRCom::getAck()
{
char cReceive = 0;
int nErr = ReadByte(&cReceive, TIMEOUTACK);
if (nErr < 0)
{
WriteLog(LOGERR, "getAck: read failed %d %s(%d)", nErr, strerror(errno), errno);
return MIR_ERROR_OFFSET + nErr;
}
if (cReceive == ACK)
{
nErr = ReadByte(&cReceive, TIMEOUTACK);
if (nErr < 0)
{
WriteLog(LOGERR, "getAck: read failed %d %s(%d)", nErr, strerror(errno), errno);
return MIR_ERROR_OFFSET + nErr;
}
if ((cReceive == '1') || (cReceive == '0'))
{
return MIR_OK;
}
return MIR_NACK_ERROR;
}
MYTRACE("\n");
return MIR_NACK_ERROR; //never reached
}
int CMIRCom::setParam(const char* szRequest)
{
MYTRACE("*** setdata <%s>\n", szRequest);
int nErr = 0;
//prüfen ob telegramm mit space abgeschlossen ist
if (szRequest[strlen(szRequest)-1] != ' ')
return MIR_DATA_NOSPACE;
//prüfen ob nur variablen einer familie in telegramm
if (checkVariableTypes(szRequest, strlen(szRequest)) < 0)
return MIR_DIFF_TYPES;
//clear input buffer
Purge();
//send EOT
MYTRACE("* send EOT\n");
nErr = sendData("%c", EOT);
if (nErr < 0)
return nErr;
CS_Sleep(DELAYSENDEOT1);
//send 'A'ENQ
MYTRACE("* send 'A'ENQ\n");
nErr = sendData("A%c", ENQ);
if (nErr < 0)
return nErr;
//wait for ACK '1' or '0'
MYTRACE("* getAck()\n");
nErr = getAck();
if (nErr < 0)
return nErr;
//send data
MYTRACE("* send STX 01032 data| ETX\n");
char szData[200];
//sprintf(szData, "01032%s| %c", szRequest, ETX); //wird jetzt von forms gebildet!
sprintf(szData, "%s%c", szRequest, ETX);
char cBCC = calcBCC(szData, strlen(szData));
nErr = sendData("%c%s%c", STX, szData, cBCC);
if (nErr < 0)
return nErr;
CS_Sleep(DELAYSENDDATA);
//wait for ACK '1' or '0'
MYTRACE("* getAck()\n");
nErr = getAck();
return nErr;
}
int CMIRCom::getParam(const char* szRequest, char* szAnswer, int nMaxAnswer)
{
memset(szAnswer, 0, nMaxAnswer);
MYTRACE("*** request <%s>\n", szRequest);
int nErr = 0;
char szResult[MAXLEN] = {0};
//prüfen ob telegramm mit space abgeschlossen ist
if (szRequest[strlen(szRequest)-1] != ' ')
return MIR_DATA_NOSPACE;
//prüfen ob nur variablen einer familie in telegramm
if (checkVariableTypes(szRequest, strlen(szRequest)) < 0)
return MIR_DIFF_TYPES;
//clear input buffer
Purge();
//send EOT
MYTRACE("* send EOT\n");
nErr = sendData("%c", EOT);
if (nErr < 0)
return nErr;
CS_Sleep(DELAYSENDEOT1);
//send 'A'ENQ
MYTRACE("* send 'A'ENQ\n");
nErr = sendData("A%c", ENQ);
if (nErr < 0)
return nErr;
//wait for ACK '1' or '0'
MYTRACE("* getAck()\n");
nErr = getAck();
if (nErr < 0)
return nErr;
//send data
MYTRACE("* send STX 01031 data ETX\n");
char szData[200];
///sprintf(szData, "01031%s %c", szRequest, ETX); //wird jetzt von forms gebildet!
sprintf(szData, "%s%c", szRequest, ETX);
char cBCC = calcBCC(szData, strlen(szData));
nErr = sendData("%c%s%c", STX, szData, cBCC);
if (nErr < 0)
return nErr;
CS_Sleep(DELAYSENDDATA);
//wait for ACK '1' or '0'
MYTRACE("* getAck()\n");
nErr = getAck();
if (nErr < 0)
return nErr;
//send 'a'ENQ
MYTRACE("* send 'a' ENQ\n");
nErr = sendData("a%c", ENQ);
if (nErr < 0)
return nErr;
//wait for data
MYTRACE("* get data\n");
nErr = getData(szResult, sizeof(szResult));
if (nErr < 0)
return nErr;
//send ACK '1' or '0'
MYTRACE("\n");
MYTRACE("* sendAck()\n");
nErr = sendAck();
if (nErr < 0)
return nErr;
//data in szResult
int nLen = strlen(szResult);
if (nLen>8)
{
szResult[nLen - 2] = 0;
strcpy(szAnswer, szResult+6);
}
MYTRACE("*** mir answer <%s>\n", szAnswer);
return nErr;
}