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;
}