/* * cc_iuc_asynchpos.c * * Created: 21.11.2017 16:36:28 * Author: Matthias */ #include "cc_iuc_asynchpos.h" #include "aes128.h" #include <QByteArray> #include <QDebug> //#include <log.h> uint32_t iuc_asynchpos_sub_updateCRC(uint32_t crc, char* pData, size_t len) { // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 QByteArray a(pData, len); qCritical() << "updateCRC" << a.toHex(' '); qCritical() << "updateCRC" << len; int i = 0; int j = 0; // unsigned long rem; // unsigned char octet; // UCHAR *p, *q; unsigned char ucCarry = 0x00; crc = ~crc; while (len > 0) { crc ^= (uint32_t) pData[i]; ++i; for (j = 0; j < 8; ++j) { ucCarry = crc & 1; crc >>= 1; if (ucCarry) { crc ^= IUC_ASYNCHPOS_POLYNOME; } } --len; } return ~crc; } #if 0 #include <buf.h> extern struct T_CONF eeprom Conf; extern struct T_dynamicData GWglobTime; extern struct T_vend Vend; static struct billAsynchData asynchBill; extern struct T_GWstate GWstate; //extern UCHAR GWstate.VendRequest; unsigned static char messageData[IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE]; ULONG com_totalSecSince1jan2017(void) { // eine Zahl erzeugen die sich jede sec ändert und nicht 2x vorkommen darf // Zeit und Datum in Sekunden umrechnen. Beginne bei 1.1.2017 um 0:00Uhr // die nächsten Schaltjahre: 2020, 2024, 2028... // Der Wert wird sich in den nächsten 130 Jahren nicht gleichen/wiederholen UINT uitmp; ULONG ultmp; //uitmp=com_totalDaysSince1Jan2017(GlobTime.Year, GlobTime.Month, GlobTime.Day); uitmp= ((UINT)GWglobTime.dayOfMon) + ((UINT)GWglobTime.month) * 30; ultmp=(ULONG)uitmp; ultmp*=1440L; // Tage--->min ultmp+=(ULONG) (GWglobTime.MinOfDay);//GlobTime.MinOfDay; // min von heute drauf ultmp*=60L; return ultmp; } void generate_UniqueTransNr(UCHAR *buf) { // buf>=20 bytes! UCHAR tmp12[12]; ULONG ultmp = 0; ULONG transID = com_totalSecSince1jan2017(); // a) Transaction ID, max 19 chars // ab April 2017: TID muss über alle Automaten und über alle Zeiten eindeutig sein, // sonst gibt SessionBase keine Antwort. //uitmp=VKdata.TransID; sub_BufferNummEntry(ultmp); // einfache Version bis März 2017 biox_ClearMem(buf, '0', 19); biox_ClearMem(tmp12, 0, 12); //VdKdata.TransID = com_totalSecSince1jan2017(); //biox_ultoa(VKdata.TransID, tmp12); biox_ultoa(transID, tmp12); biox_MemCpPos(tmp12, buf, 1); // Automaten-nr auch rein, sonst können versch. Automaten die gleiche Nummer haben! biox_ClearMem(tmp12, 0, 12); ultmp=(ULONG) Conf.MachNr; //.MachineID; biox_ultoa(ultmp, tmp12); biox_MemCpPos(tmp12, buf, 11); biox_ClearMem(tmp12, 0, 12); ultmp=(ULONG)Conf.CustomNr; //.CustID; biox_ultoa(ultmp, tmp12); biox_MemCpPos(tmp12, buf, 16); buf[19]=0; } void iuc_asynchpos_sub_initArray(unsigned char* pArray, int length) { unsigned int uitemp = 0; for (uitemp = 0; uitemp < length; ++uitemp) pArray[uitemp] = 0x00; } void iuc_asynchpos_setTerminalID(unsigned char *pID, unsigned int length) { unsigned int uctemp = 0; if (!biox_StrComp(pID,terminalID,length)) { for (uctemp = 0; uctemp < length; ++uctemp) { terminalID[uctemp] = pID[uctemp]; } } } void iuc_asynchpos_setTerminalAPAK(unsigned char *pAPAK, unsigned int length) { unsigned char uctemp = 0; if (!biox_StrComp(pAPAK,terminalAPAK,length)) { for (uctemp = 0; uctemp < length; ++uctemp) { terminalAPAK[uctemp] = pAPAK[uctemp]; Conf.APAK_backup[uctemp] = pAPAK[uctemp]; } } } ULONG iuc_asynchpos_sub_updateCRC(ULONG crc, UCHAR* pData, UINT len) //TODO { // berechne CRC32 nach Polynom x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x + 1 int i = 0; int j = 0; // unsigned long rem; // unsigned char octet; // UCHAR *p, *q; unsigned char ucCarry = 0x00; crc = ~crc; while (len > 0) { crc ^= (ULONG) pData[i]; ++i; for (j = 0; j < 8; ++j) { ucCarry = crc & 1; crc >>= 1; if (ucCarry) { crc ^= IUC_ASYNCHPOS_POLYNOME; } } --len; } return ~crc; } unsigned char iuc_asynchpos_rts() { unsigned char timeOut = 0x00; unsigned char uctmp = 0x00; brd_switch_RS3(RS3SW2IUC); biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none); uctmp = EOT; biox_Usart3_ClearRecBuffer(); biox_Usart3_SendBlock(&uctmp,1); while (timeOut < 0x06 && uctmp != ENQ) { biox_delay_ms(400); if (biox_Usart3_NewTelegram()) { brd_SendDiagStr("->IUC ASYNCHPOS 0x05 (ENQ) received. RTS.",1); biox_Usart3_GetRecBuffer(&uctmp,1); biox_Usart3_ClearRecBuffer(); iucAsynchpoxDataContext = 0x00; } else { brd_SendDiagStr("->IUC ASYNCHPOS waiting for 0x05 (ENQ).",1); biox_Usart3_ClearRecBuffer(); biox_Usart3_SendBlock(&uctmp,1); } ++timeOut; } if (uctmp == ENQ) return 0; return 1; } unsigned char iuc_asynchpos_cts() { unsigned int recLength; unsigned char uctmp = ENQ; recLength = biox_Usart3BuffSize(); if (recLength > 0) { biox_Usart3_GetRecBuffer(&uctmp,1); if (uctmp == EOT) { //The terminal is trying to send us data uctmp = ENQ; biox_Usart3_ClearRecBuffer(); biox_Usart3_SendBlock(&uctmp,1); biox_delay_ms(10); return 1; } } return 0; } unsigned char iuc_asynchpos_waitforACK() { //unsigned char timeOut = 0x00; unsigned char retVal = 0x00; unsigned char rxData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; unsigned int uitmp = 0; uitmp = biox_Usart3BuffSize(); if (uitmp > 1) { //iuc_asynchpos_sub_initArray(rxData_,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); biox_Usart3_GetRecBuffer(rxData_,uitmp); if (GWstate.DebugLevel & 0x10) { brd_SendDiagStr("->IUC ASYNCHPOS (ACK/NACK) rx data: ",0); brd_SendDiagBlock(rxData_,1,uitmp); } retVal = rxData_[0]; for (;uitmp > 0;--uitmp) { if (rxData_[uitmp] == 0x0A) { retVal |= 0xA0; } if (rxData_[uitmp] == 0x0F) { retVal |= 0xF0; } } } else { //if (uitmp == 1) biox_Usart3_GetRecBuffer(&retVal,1); } biox_Usart3_ClearRecBuffer(); return retVal; } unsigned char iuc_asynchpos_send_serial(unsigned char* pData, unsigned int length, unsigned char needRTS, unsigned char overrideACK) { unsigned int uitmp = 0; unsigned int uitmp2 = 0; unsigned int uitmp3 = 0; unsigned int txCounter = 0; unsigned int dxCounter = 0; unsigned char uctmp = 0x00; // unsigned char uctmp2 =0x00; unsigned char chksum = 0x00; //unsigned char dataContext = 0x00; unsigned int retryCount = 0; unsigned long lastRetry = 0; unsigned int dxLength; // unsigned int dx = biox_StrLen(pData) + 1; unsigned char rxBuf[8]; //unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; // unsigned int loopCount = 1000; // unsigned char retVal = 0x01; //preparing to send if (needRTS) { brd_SendDiagStr("->IUC ASYNCHPOS sending 0x04 (EOT).",1); uctmp = iuc_asynchpos_rts(); } //sending data if (!uctmp) { brd_SendDiagStr("----->IUC ASYNCHPOS",1); iuc_asynchpos_sub_initArray(txAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); //iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); //biox_CopyBlock(pData,0,pData_,0,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); /*dxCounter = 0; for (uitmp = 0; uitmp < dx + dxCounter; ++uitmp) { if ((pData[uitmp] >= STX && pData[uitmp] <= ACK2) || (pData[uitmp] == DLE) || (pData[uitmp] == NAK)) { pData[uitmp] = (pData[uitmp] + 0x30); for (uitmp2 = uitmp; uitmp2 < dx + dxCounter; ++uitmp2) { pData[uitmp2 + 1] = pData[uitmp2]; } pData[uitmp] = DLE; ++dxCounter; } } dxCounter = 0;*/ for (uitmp = 0; uitmp < length; uitmp += IUC_ASYNCHPOS_MIN_PACKET_SIZE) { //if (dxCounter > 0) //uitmp -= dxCounter; uctmp = 0x00; dxCounter = 0; chksum = 0x00; dxLength = IUC_ASYNCHPOS_MIN_PACKET_SIZE; if (length - uitmp <= IUC_ASYNCHPOS_MIN_PACKET_SIZE) dxLength = 2 + length - uitmp; iuc_asynchpos_sub_initArray(txAsynchData, 3 + IUC_ASYNCHPOS_MIN_PACKET_SIZE); //Packet structure is STX <packet_data> ETX1|ETX2 {LRC} txAsynchData[0] = STX; for (txCounter = 0; (txCounter/* + dxCounter*/) < dxLength; ++txCounter) { //for (txCounter = 0; txCounter < dxLength; ++txCounter) { /*if ((pData[uitmp + txCounter] >= STX && pData[uitmp + txCounter] <= ACK2) || (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) { txAsynchData[1 + txCounter + dxCounter] = DLE; uctmp = (pData[uitmp + txCounter] + 0x30); ++dxCounter; txAsynchData[1 + txCounter + dxCounter] = uctmp; //(pData[uitmp + txCounter] + 0x30); } else {*/ txAsynchData[1 + txCounter/* + dxCounter*/] = pData[uitmp + txCounter]; if ((pData[uitmp + txCounter] >= STX && pData[uitmp + txCounter] <= ACK2) || (pData[uitmp + txCounter] == DLE) || (pData[uitmp + txCounter] == NAK)) { ++dxCounter; } } for (uitmp2 = 1; uitmp2 < dxLength + dxCounter; ++uitmp2) { if ((txAsynchData[uitmp2] >= STX && txAsynchData[uitmp2] <= ACK2) || (txAsynchData[uitmp2] == DLE) || (txAsynchData[uitmp2] == NAK)) { for (uitmp3 = dxLength + dxCounter; uitmp3 > uitmp2; --uitmp3) { txAsynchData[uitmp3] = txAsynchData[uitmp3 - 1]; } txAsynchData[uitmp2 + 1] = (txAsynchData[uitmp2 + 1] + 0x30); txAsynchData[uitmp2] = DLE; } } /*if (dxLength < IUC_ASYNCHPOS_MIN_PACKET_SIZE && txAsynchData[txCounter + dxCounter] != 0x00) { ++dxCounter; }*/ for (uitmp2 = 1; uitmp2 <= (txCounter + dxCounter); ++uitmp2) { chksum ^= txAsynchData[uitmp2]; } if (!iucAsynchpoxDataContext) { txAsynchData[1 + txCounter + dxCounter] = ETX1; chksum ^= ETX1; } else { txAsynchData[1 + txCounter + dxCounter] = ETX2; chksum ^= ETX2; } txAsynchData[2 + txCounter + dxCounter] = chksum; //Check if the terminal has decided, that our gateway is gone and is frantically sending us EOTs all the time //iuc_asynchpos_cts(); //send packet biox_Usart3_ClearRecBuffer(); biox_Usart3_SendBlock(txAsynchData,3 + txCounter + dxCounter); biox_delay_ms(1); iuc_asynchpos_sub_initArray(rxBuf,8); biox_itoa(3 + txCounter + dxCounter,rxBuf); if (GWstate.DebugLevel & 0x10) { brd_SendDiagStr("->IUC ASYNCHPOS Packetlength: ",0); brd_SendDiagBlock(rxBuf,1,8); brd_SendDiagStr("->IUC ASYNCHPOS send package: ",0); brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter); } //brd_SendDiagStr("->IUC ASYNCHPOS Send: ",0); //brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter); //wait for ACK uctmp = 0x00; lastRetry = 0; retryCount = 0; brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); do { uctmp = iuc_asynchpos_waitforACK(); //uctmp2 = uctmp; uctmp &= 0x0F; //if (!(lastRetry % 10)) { //} if ((uctmp == NAK) || ((lastRetry >= 100) && (uctmp == 0x00))) { brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); if (uctmp == NAK) brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1); biox_Usart3_SendBlock(txAsynchData,3 + txCounter + dxCounter); biox_delay_ms(1); ++retryCount; uctmp = 0x00; lastRetry = 0; } else { ++lastRetry; biox_delay_ms(1); } } while (retryCount < 25 && uctmp == 0x00); //Entweder Timeout, keine neuen Versuche oder ein ACK1/ACK2 holen uns hier raus /*while (retryCount < 5 && (uctmp == 0x00 || uctmp == NAK)) { uctmp = iuc_asynchpos_waitforACK(); ++lastRetry; // if (uitmp == 0) // biox_delay_ms(100); if ((uctmp == NAK) || (uctmp == 0x00 && (lastRetry % 10 == 0x00))) { biox_Usart2_ClearRecBuffer(); brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1); biox_Usart2_SendBlock(txAsynchData,3 + txCounter + dxCounter); biox_delay_ms(10); brd_SendDiagStr("->IUC ASYNCHPOS resend: ",0); brd_SendDiagBlock(txAsynchData,1,3 + txCounter + dxCounter); ++retryCount; } else if (uctmp == ETX1 || uctmp == ETX2) { biox_Usart2_ClearRecBuffer(); uctmp = NAK; biox_Usart2_SendBlock(&uctmp,1); } }*/ if (!uctmp) { brd_SendDiagStr("->IUC ASYNCHPOS Terminal did not reply.",1); return 1; //sending failed } //iuc_asynchpos_sub_initArray(txAsynchData, 3 + txCounter + dxCounter); if (uctmp == ACK1) { brd_SendDiagStr("->IUC ASYNCHPOS ACK 1 (serial)",1); //dataContext = 0x01; iucAsynchpoxDataContext = 0x01; } if (uctmp == ACK2) { brd_SendDiagStr("->IUC ASYNCHPOS ACK 2 (serial)",1); //dataContext = 0x00; iucAsynchpoxDataContext = 0x00; } if (retryCount >= 5) { brd_SendDiagStr("->IUC ASYNCHPOS Too much NACKs, giving up.",1); return 2; //too much NACKs, giving up } } /*uctmp2 &= 0xF0; if (uctmp2 == 0xA0) { retVal = 1; } if (uctmp2 == 0xF0) { retVal = 0; }*/ /*if (!overrideACK) { brd_SendDiagStr("->IUC ASYNCHPOS Retrieving.",1); retVal = 0x01; uitmp = 0x01; while(uitmp > 0 && loopCount > 0) { uitmp = iuc_asynchpos_recieve_serial(0x01); biox_delay_ms(1); --loopCount; biox_Usart2_ClearRecBuffer(); } if (loopCount == 0) { brd_SendDiagStr("->IUC ASYNCHPOS Retrieving timeout!",1); retVal = 0x00; } brd_SendDiagStr("->IUC ASYNCHPOS Retrieving ended.",1); }*/ return 1;//retVal;//(UCHAR) uitmp; } else { brd_SendDiagStr("->IUC ASYNCHPOS Not ready to send to POS, giving up.",1); } return 2; } unsigned int iuc_asynchpos_send(unsigned char packetType, unsigned char* pData, unsigned int length, unsigned char needRTS) { unsigned char txData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; unsigned char tempID [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; unsigned char tempID_ [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; unsigned char tempAPAK [IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE]; unsigned long uitmp = 0; unsigned int posID = 0; unsigned long chksum = 0; unsigned int messageLength = length + 1; unsigned int length_ = length + 1; unsigned char pData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; unsigned char uctemp = 0; // unsigned char retries = 4; unsigned char rxBuf[8]; iuc_asynchpos_crc_old = 0; iuc_asynchpos_sub_initArray(rxBuf, 8); iuc_asynchpos_sub_initArray(pData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); biox_CopyBlock(pData,0,pData_,0,length_); iuc_asynchpos_sub_initArray(txData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); iuc_asynchpos_sub_initArray(tempID, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); iuc_asynchpos_sub_initArray(tempID_, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); iuc_asynchpos_sub_initArray(tempAPAK, IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE); //header /* The header of the message is composed of: ? 1 byte packet Type, which indicates the type of the packet; ? 8 bytes Packet ID, a unique ID to achieve maximum security (for information on forming Packet ID see chapter 3.4 Communication security); ? 1 byte P.O.S. ID length; ? ASCII encoded P.O.S. ID (up to 255 bytes); ((gemeint ist Terminal ID) */ txData_[2] = packetType; //1 byte P.O.S. ID length /*for (uitmp = 0; uitmp < 32 && terminalID[uitmp] != 0x00; ++uitmp) { ++posID; // -= uitmp; }*/ posID = biox_StrLen(terminalID)/* + 1*/; //++posID; txData_[11] = (UCHAR) posID; messageLength += (10 + posID); //Added header txData_[0] = (messageLength) & 0xFF00; //high byte txData_[1] = (messageLength) & 0x00FF; //low byte //8 byte Packet ID /* Apak: 9D547268976ADE1BBB39DE90F3A449E5 Terminal id: T-LT-OPT-01 */ //calculate CRC32 uctemp = (UCHAR) posID; chksum = IUC_ASYNCHPOS_POLYNOME_INITIAL; chksum = iuc_asynchpos_sub_updateCRC(chksum,&uctemp,1); chksum = iuc_asynchpos_sub_updateCRC(chksum,terminalID,posID); //for (uitmp = 0; uitmp < length_; ++uitmp) { chksum = iuc_asynchpos_sub_updateCRC(chksum,pData_/*[uitmp]*/,length_); //} //XOR crc value with APAK //chksum = 2502456899; //HACK FOR TESTING, REMOVE LATER! for(uitmp = 0; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) { tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[uitmp * 2]) << 4; tempAPAK[uitmp] |= biox_ah2ui_char(terminalAPAK[(uitmp * 2) + 1]); //tempAPAK[uitmp] = (terminalAPAK[uitmp * 2] << 8) | (terminalAPAK[(uitmp * 2) + 1]); } tempID[0] = (chksum >> 24) & 0xFF; tempID[1] = (chksum >> 16) & 0xFF; tempID[2] = (chksum >> 8) & 0xFF; tempID[3] = chksum & 0xFF; for (uitmp = 0; uitmp < 4; ++uitmp) { tempID[uitmp] ^= tempAPAK[uitmp]; //terminalAPAK[uitmp]; } for (uitmp = 4; uitmp < IUC_ASYNCHPOS_MIN_BASE_BYTE_DATA_SIZE; ++uitmp) { tempID[uitmp] = tempAPAK[uitmp]; //terminalAPAK[uitmp]; } //Eyncrypt result with APAK, according to AES128 aes_encrypt(tempID,tempID_,tempAPAK); //get the leftmost 8 byte of that value and set then as Packet ID for (uitmp = 0; uitmp < 8; ++uitmp) txData_[3 + uitmp] = tempID_[uitmp]; //P.O.S.ID for (uitmp = 0; uitmp < posID; ++uitmp) { txData_[12 + uitmp] = terminalID[uitmp]; } //Message //1 byte - marker //0 . 7F bytes - tag name //2 + N bytes - data for (uitmp = 0; uitmp < length_; ++uitmp) { txData_[12 + posID + uitmp] = pData_[uitmp]; } brd_SendDiagStr("->IUC ASYNCHPOS send message: ",0); brd_SendDiagBlock(txData_,1,messageLength); //Message compiled, now send it via serial uitmp = 1; //while (retries > 0 && uitmp > 0) { //uitmp = iuc_asynchpos_send_serial(txData_, (messageLength + 1)); //--retries; if (iuc_asynchpos_send_serial(txData_, (messageLength/* + 1*/),needRTS,0x00)) { //brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1); //TODO Message sending failed -> Error handling here //return 1; uitmp = 0x00; brd_SendDiagStr("->IUC ASYNCHPOS Message NOT send",1); } else { brd_SendDiagStr("->IUC ASYNCHPOS Message send",1); } /*else { --retries; } }*/ //if (!uitmp) //return 1; /*if (retries == 0) { brd_SendDiagStr("->IUC ASYNCHPOS Message failed!",1); rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0xFF; vmc_SendWithBuffer(rxBuf,20,0x69,0); return 1; } rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0x00; vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ //brd_SendDiagStr("->IUC ASYNCHPOS Message send",1); //while(iuc_asynchpos_recieve_serial()); return 0; } /* Let us assume that a client wants to purchase items and he wants to pay for these items with his bank card. When the client is ready to authorize the transaction, the ECR needs to send [Authorize] request for the operations to start. Within the request, the ECR must include: ? An [Amount] sub tag with the tender amount in minor currency; ? A [Currency] sub tag with a three digit currency code; ? A [DocNr] sub tag with the number referencing the current receipt; ? [Time] the time of the transaction; ? A [Lang] sub tag specifying a language code; As a result, the P.O.S. will reply by an [AuthorizationResult] device event with an [ID], [DocNr], [Result] sub tags. When ECR closes/finalizes its receipt, ECR must send [DocClosed] event to finalize bank operation of in this receipt. A successful authorization Id from [AuthorizationResult] must be included in [DocClosed] message. Only Id of successful authorization has to be included, other Ids has to be omitted from message. Depending on the configuration, and requirements, the ECR may receive a [PrintReceipt] event (though some models of P.O.S. could as well print the receipt itself), with an [ID], [DocNr], and the [ReceiptText], to be printed out. The [PrintReceipt] event may occur at any time of the operation, whenever the P.O.S. needs to print something, and it should be printed as soon as possible. ECR may be occupied during the event, so it may start printing when no more operations are waiting to be processed. After the receipt has been printed, the ECR has to send a [PrintResult] to P.O.S. to confirm the successful action. P.O.S. may send [GetMessageBoxInput] message to ECR if signature of Client needed. ECR must send [InputResult] message to POS. This message informs about sign status. During bank card authorization [PrintReceipt] messages usually are sent before [AuthorizationResult] event. POS could send additional [DisplayText] message(s) to ECR to inform about process steps. */ void iuc_asynchpos_sub_initZero(unsigned char* pArray, int length) { unsigned int uitemp = 0; for (uitemp = 0; uitemp < (length - 1); ++uitemp) pArray[uitemp] = 0x30; pArray[length - 1] = 0x00; } void iuc_asynchpos_sub_clear_message(unsigned char fillwithZero) { if (fillwithZero) { iuc_asynchpos_sub_initZero(asynchBill.id,37); iuc_asynchpos_sub_initZero(asynchBill.docNr,33); /*iuc_asynchpos_sub_initZero(asynchBill.token,25); iuc_asynchpos_sub_initZero(asynchBill.result,8); iuc_asynchpos_sub_initZero(asynchBill.amount,10); iuc_asynchpos_sub_initZero(asynchBill.authCode,7); iuc_asynchpos_sub_initZero(asynchBill.rrn,13); iuc_asynchpos_sub_initZero(asynchBill.stan,7); iuc_asynchpos_sub_initZero(asynchBill.cardtype,33);*/ //iuc_asynchpos_sub_initZero(asynchBill.errCode,17); } else { iuc_asynchpos_sub_initArray(asynchBill.id,37); iuc_asynchpos_sub_initArray(asynchBill.docNr,33); /*iuc_asynchpos_sub_initArray(asynchBill.token,25); iuc_asynchpos_sub_initArray(asynchBill.result,8); iuc_asynchpos_sub_initArray(asynchBill.amount,10); iuc_asynchpos_sub_initArray(asynchBill.authCode,7); iuc_asynchpos_sub_initArray(asynchBill.rrn,13); iuc_asynchpos_sub_initArray(asynchBill.stan,7); iuc_asynchpos_sub_initArray(asynchBill.cardtype,33);*/ //iuc_asynchpos_sub_initArray(asynchBill.errCode,17); } } void iuc_asynchpos_sub_sendACK(unsigned char switchPrint) { unsigned char messageReturnData[100]; unsigned int uitemp = 0; unsigned int uitemp2 = 0; unsigned int uitemp3 = 0; unsigned char uctmp = 0; unsigned int lastRetry = 0; unsigned int retryCount = 0; iuc_asynchpos_sub_initArray(messageReturnData, 100); //iuc_asynchpos_sub_initArray(messageData, messageLength + 1);//iuc_asynchpos_sub_initArray(messageReturnData, IUC_ASYNCHPOS_MAX_MESSAGE_SIZE); switch (switchPrint) { case 1: for (uitemp = 0; uitemp < 8; ++uitemp) { messageReturnData[uitemp + 3] = terminalSignature[uitemp]; } messageReturnData[uitemp + 3] = (UCHAR) biox_StrLen(terminalID); for (uitemp = 0; uitemp < biox_StrLen(terminalID); ++uitemp) { messageReturnData[uitemp + 12] = terminalID[uitemp]; } uitemp += 10; break; case 2: for (uitemp = 0; uitemp < 8; ++uitemp) { messageReturnData[uitemp + 3] = terminalSignature[uitemp + 8]; } messageReturnData[uitemp + 3] = biox_StrLen(terminalID); for (uitemp = 0; uitemp < biox_StrLen(terminalID); ++uitemp) { messageReturnData[uitemp + 12] = terminalID[uitemp]; } uitemp += 10; break; case 0: default: for (uitemp = 0; uitemp < rxAsynchData[11] + 9; ++uitemp) { messageReturnData[uitemp + 3] = rxAsynchData[uitemp + 3]; } ++uitemp; break; } messageReturnData[0] = uitemp & (0xFF00); messageReturnData[1] = uitemp & (0x00FF); messageReturnData[2] = 0x0A; //iuc_asynchpos_send_serial(messageReturnData,uitemp/* + 1*/,0x00,0x01); for (uitemp2 = uitemp + 2; uitemp2 > 0; --uitemp2) { messageReturnData[uitemp2] = messageReturnData[uitemp2 - 1]; } uitemp += 2; messageReturnData[0] = 0x01; //convert characters for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) { if ((messageReturnData[uitemp2] >= STX && messageReturnData[uitemp2] <= ACK2) || (messageReturnData[uitemp2] == DLE) || (messageReturnData[uitemp2] == NAK)) { ++uitemp; for (uitemp3 = uitemp + 1; uitemp3 > uitemp2; --uitemp3) { messageReturnData[uitemp3] = messageReturnData[uitemp3 - 1]; } messageReturnData[uitemp2 + 1] = messageReturnData[uitemp2 + 1] + 0x30; messageReturnData[uitemp2] = DLE; } } messageReturnData[uitemp + 1] = ETX1; //calculate chksum for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) { messageReturnData[uitemp + 2] ^= messageReturnData[uitemp2]; } biox_Usart3_SendBlock(messageReturnData,uitemp2+1); //wait for ACK uctmp = 0x00; lastRetry = 1; retryCount = 0; brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); do { uctmp = iuc_asynchpos_waitforACK(); //if (!(lastRetry % 10)) { //} if (uctmp == NAK || ((lastRetry % 500 == 0) && (uctmp == 0x00))) { brd_SendDiagStr("->IUC ASYNCHPOS waiting for answer (serial)",1); if (uctmp == NAK) brd_SendDiagStr("->IUC ASYNCHPOS NACK (serial)",1); biox_Usart3_SendBlock(messageReturnData,uitemp2+1); biox_delay_ms(1); ++retryCount; uctmp = 0x00; lastRetry = 1; } else { ++lastRetry; biox_delay_ms(1); } } while (retryCount < 5 && uctmp == 0x00); //Entweder Timeout, keine neuen Versuche oder ein ACK1/ACK2 holen uns hier raus if (!uctmp) { brd_SendDiagStr("->IUC ASYNCHPOS Terminal did not reply.",1); //return 1; //sending failed } if (uctmp == ACK1) { brd_SendDiagStr("->IUC ASYNCHPOS ACK 1 (ACK serial)",1); //dataContext = 0x01; iucAsynchpoxDataContext = 0x01; } if (uctmp == ACK2) { brd_SendDiagStr("->IUC ASYNCHPOS ACK 2 (ACK serial)",1); //dataContext = 0x00; iucAsynchpoxDataContext = 0x00; } if (retryCount >= 5) { brd_SendDiagStr("->IUC ASYNCHPOS (ACK serial) Too much NACKs, giving up.",1); //return 2; //too much NACKs, giving up } } void iuc_asynchpos_resetBuffers(unsigned char sendENQ) { unsigned char uctmp = ENQ; unsigned char rxBuf[8]; if (sendENQ != 0x02) { rxCounter = 0; messageLength = 0; iuc_asynchpos_sub_initArray(rxAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); iuc_asynchpos_sub_initArray(txAsynchData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); } if (sendENQ) { iucAsynchpoxDataContext = 0x00; ENQrecieved = 1; brd_SendDiagStr("->IUC ASYNCHPOS 0x04 (EOT) received.",1); brd_switch_RS3(RS3SW2IUC); biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none); biox_delay_ms(1); biox_Usart3_ClearRecBuffer(); brd_SendDiagStr("->IUC ASYNCHPOS send 0x05 (ENQ). CTS",1); biox_Usart3_SendBlock(&uctmp,1); if (asynchState <= 0x03) { brd_SendDiagStr("->IUC ASYNCHPOS sending an error to the VMC",1); iuc_asynchpos_sub_initArray(rxBuf,8); rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0xFF; vmc_SendWithBuffer(rxBuf,8,0x69,0); } } } //46 void iuc_asynchpos_command_print_Result(unsigned char status) { //Finalize sale UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; UCHAR packetType = 0x00; UINT uitemp = 0; UCHAR command[] = "PrintResult"; UCHAR tagName[] = "DocNr"; UCHAR tag2Name[] = "Result"; UCHAR tag3Name[] = "ID"; UCHAR tag2ValueO[] = "OK"; UCHAR tag2ValueE[] = "ERROR"; unsigned char uctmp = status; //Constructing the message iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); uitemp = biox_StrLen(command); message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length biox_CopyBlock(command,0,message,1,uitemp); //tag name ++uitemp; //ID message[uitemp] = (UCHAR) biox_StrLen(tag3Name); ++uitemp; biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name)); uitemp += (1 + biox_StrLen(tag3Name)); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.printId);//value length ++uitemp; biox_CopyBlock(asynchBill.printId,0,message,uitemp, biox_StrLen(asynchBill.printId));//value uitemp += biox_StrLen(asynchBill.printId); //DocNr message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length ++uitemp; biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name uitemp += (1 + biox_StrLen(tagName)); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length ++uitemp; biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value uitemp += biox_StrLen(asynchBill.docNr); //Result message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name uitemp += (1 + biox_StrLen(tag2Name)); if (!uctmp) { message[uitemp] = (UCHAR) biox_StrLen(tag2ValueE);//value length ++uitemp; biox_CopyBlock(tag2ValueE,0,message,uitemp, biox_StrLen(tag2ValueE));//value uitemp += biox_StrLen(tag2ValueE)/* + 1*/; } else { message[uitemp] = (UCHAR) biox_StrLen(tag2ValueO);//value length ++uitemp; biox_CopyBlock(tag2ValueO,0,message,uitemp, biox_StrLen(tag2ValueO));//value uitemp += biox_StrLen(tag2ValueO)/* + 1*/; } iuc_asynchpos_send(packetType,message,uitemp,0x00); } void iuc_asynchpos_handleMessage(unsigned char* pData) { //unsigned char marker = pData[0]; // unsigned int tagNameLength = pData[1]; unsigned char tagName[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; // unsigned int curElementLength = 0; //unsigned char curElement[IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE]; //unsigned char receiptData[IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1]; unsigned char rxBuf[20]; // unsigned char flags[129]; // unsigned char docNr[32]; //unsigned char messageType = pData[1]; unsigned int uitmp = 0; unsigned int uitmp2 = 0; iuc_asynchpos_sub_initArray(tagName, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); //iuc_asynchpos_sub_initArray(curElement, IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); uitmp = biox_FindStrInBufferInt("LoginResult",pData) | biox_FindStrInBuffer("LOGINRESULT",pData); if (uitmp) { asynchState = 0x02; //eingeloggt /*rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0x00; vmc_SendWithBuffer(rxBuf,40,0x69,0);*/ } uitmp = biox_FindStrInBufferInt("AuthorizationStarted",pData) | biox_FindStrInBuffer("AUTHORIZATIONSTARTED",pData); if (uitmp) { iuc_asynchpos_sub_initArray(rxBuf,5); rxBuf[0] = 0x53; rxBuf[1] = 0x00; rxBuf[2] = 0x00; vmc_SendWithBuffer(rxBuf,5,0x69,0); } uitmp = biox_FindStrInBufferInt("AuthorizationResult",pData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",pData); if (uitmp) { asynchState = 0x03; //successfully authorized iuc_asynchpos_sub_clear_message(0x00); uitmp = biox_FindStrInBufferInt("ID",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]); uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]); //uitmp = biox_FindStrInBuffer("Result",pData) | biox_FindStrInBuffer("RESULT",pData); //biox_CopyBlock(pData, uitmp + 2, asynchBill.result, 0, pData[uitmp + 1]); brd_SendDiagStr("->IUC ASYNCHPOS message ID: ",0); brd_SendDiagBlock(asynchBill.id,1,36); /*if (iuc_asynch_PrintControl) { brd_SendDiagStr("->IUC ASYNCHPOS print data send AUTH: ",1); vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); iuc_asynch_PrintControl = 0x00; //biox_delay_ms(750); } else { brd_SendDiagStr("->IUC ASYNCHPOS sending authorization: ",1); iuc_asynch_PrintControl = 0x01; }*/ uitmp = biox_FindStrInBufferInt("ERROR",pData); if (!uitmp/*biox_FindStrInBuffer("OK",pData) | biox_FindStrInBuffer("Approved",pData) | biox_FindStrInBuffer("APPROVED",asynchBill.result)*/) { iuc_asynch_PrintControl |= 0xF0; /*uitmp = biox_FindStrInBufferInt("Amount",pData) | biox_FindStrInBufferInt("AMOUNT",pData); //if (pData[uitmp + 1] <= 10) { biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, pData[uitmp + 1]); //} else { //biox_CopyBlock(pData, uitmp + 2, asynchBill.amount, 0, 10); //}*/ //uitmp = biox_FindStrInBuffer("Token",pData); //biox_CopyBlock(pData, uitmp + 2, asynchBill.token, 0, pData[uitmp + 1]); /*uitmp = biox_FindStrInBufferInt("Authcode",pData) | biox_FindStrInBufferInt("AUTHCODE",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.authCode, 0, pData[uitmp + 1]); uitmp = biox_FindStrInBufferInt("RRN",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.rrn, 0, pData[uitmp + 1]); uitmp = biox_FindStrInBufferInt("STAN",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.stan, 0, pData[uitmp + 1]); uitmp = biox_FindStrInBufferInt("CardType",pData) | biox_FindStrInBufferInt("CARDTYPE",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.cardtype, 0, pData[uitmp + 1]);*/ asynchState = 0x04; brd_SendDiagStr("->IUC ASYNCHPOS authorization confirmed.",1); /*iuc_asynchpos_sub_initArray(rxBuf,20); rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0x00; vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ //iuc_asynchpos_resetBuffers(0x01); //iuc_asynchpos_command_close_Document(); } else { iuc_asynch_PrintControl |= 0xF0; //uitmp = biox_FindStrInBufferInt("ErrCode",pData) | biox_FindStrInBufferInt("ERRCODE",pData); //biox_CopyBlock(pData, uitmp + 2, asynchBill.errCode, 0, pData[uitmp + 1]); brd_SendDiagStr("->IUC ASYNCHPOS authorization failed.",1); /*iuc_asynchpos_sub_initArray(rxBuf,20); rxBuf[0] = 0x45; rxBuf[1] = 0xFF; biox_CopyBlock(pData, uitmp + 2, rxBuf, 2, pData[uitmp + 1]); vmc_SendWithBuffer(rxBuf,20,0x69,0);*/ iuc_asynch_keepAlive = 0x00; //VendRequest=0; } } uitmp = biox_FindStrInBufferInt("PrintReceipt",pData) | biox_FindStrInBufferInt("PRINTRECEIPT",pData); if (uitmp) { asynchState = 0x03; //Customer receipt recieved //iuc_asynchpos_sub_initArray(flags,129); //uitmp = biox_FindStrInBufferInt("Flag",pData) | biox_FindStrInBufferInt("FLAG",pData) | biox_FindStrInBufferInt("Flags",pData) | biox_FindStrInBufferInt("FLAGS",pData); /*if (uitmp) { biox_CopyBlock(pData, uitmp + 2, flags, 0, pData[uitmp + 1]); uitmp = biox_FindStrInBufferInt("CD",flags) | biox_FindStrInBufferInt("LR",flags); }*/ /*iuc_asynchpos_sub_clear_message(0x00); uitmp = biox_FindStrInBufferInt("ID",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.id, 0, pData[uitmp + 1]); uitmp = biox_FindStrInBufferInt("DocNr",pData) | biox_FindStrInBuffer("DOCNR",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.docNr, 0, pData[uitmp + 1]);*/ iuc_asynchpos_sub_initArray(asynchBill.printId,129); uitmp = biox_FindStrInBufferInt("ID",pData); biox_CopyBlock(pData, uitmp + 2, asynchBill.printId, 0, pData[uitmp + 1]); //if(asynchState == 0x02/* && uitmp biox_FindStrInBufferInt("CD",flags) || biox_FindStrInBufferInt("LR",flags)*/) { if((!iuc_asynch_PRNrecieved) && (biox_FindStrInBufferInt("CD",pData) || biox_FindStrInBufferInt("LR",pData)) ) { iuc_asynch_PRNrecieved = 0x01; iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE + 1); uitmp = /*biox_FindStrInBuffer("ReceiptText",pData) | */biox_FindStrInBufferInt("RECEIPTTEXT",pData); uitmp2 = (pData[uitmp] * 256) + pData[uitmp + 1]; //if (uitmp2 <= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { if (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { uitmp2 = IUC_ASYNCHPOS_MAX_ARRAY_SIZE; brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large! Cutting off.",1); /*receiptData[0] = 0x50; biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*); //uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE; //uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE; brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0); brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); iuc_asynch_PrintControl |= 0x0F;*/ /*if (iuc_asynch_PrintControl) { brd_SendDiagStr("->IUC ASYNCHPOS print data send: ",1); vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); iuc_asynch_PrintControl = 0x00; } else { brd_SendDiagStr("->IUC ASYNCHPOS print data stored: ",1); iuc_asynch_PrintControl = 0x01; }*/ //biox_delay_ms(750); //iuc_asynchpos_resetBuffers(0x01); //iuc_asynchpos_command_close_Document(); //iuc_asynchpos_resetBuffers(0x02); //iuc_asynchpos_command_print_Result(0x01); } receiptData[0] = 0x50; biox_CopyBlock(pData, uitmp + 2, receiptData, 1, uitmp2/*IUC_ASYNCHPOS_MAX_ARRAY_SIZE*/); brd_SendDiagStr("->IUC ASYNCHPOS receipt: ",0); brd_SendDiagBlock(receiptData,1,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); iuc_asynch_PrintControl |= 0x0F; /* else { //receiptData[0] = 0x50; //iuc_asynchpos_sub_initZero(receiptData,1); brd_SendDiagStr("->IUC ASYNCHPOS receipt: ERROR. Receipt too large!",1); iuc_asynch_PrintControl |= 0x0E; } */ /* else { //iuc_asynchpos_resetBuffers(0x02); iuc_asynchpos_command_print_Result(0x00); }*/ } //++iuc_print_counter; //if(asynchState == 0x04 && iuc_asynch_PrintControl == 0) { //iuc_asynchpos_resetBuffers(0x01); //iuc_asynchpos_resetBuffers(0x00); //iuc_asynchpos_command_print_Result(0x01); /*} /else { //iuc_asynchpos_resetBuffers(0x02); iuc_asynchpos_command_print_Result(0x01); }*/ //iuc_asynchpos_command_print_Result(0x01); /*while (uitmp2 > IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { biox_CopyBlock(pData, uitmp + 2, receiptData, 0, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); uitmp += IUC_ASYNCHPOS_MAX_ARRAY_SIZE; uitmp2 -= IUC_ASYNCHPOS_MAX_ARRAY_SIZE; vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0); } //Rest des Packets biox_CopyBlock(pData, uitmp + 2, receiptData, 0, uitmp2); vmc_SendWithBuffer(receiptData,uitmp2,0x69,0); //iuc_asynchpos_resetBuffers(0x02); iuc_asynchpos_command_print_Result(0x01);*/ } uitmp = biox_FindStrInBufferInt("VoidResult",pData) | biox_FindStrInBufferInt("VOIDRESULT",pData); if (uitmp) { asynchState = 0x01; //There was a cancel. Relogin and try again. uitmp = biox_FindStrInBufferInt("ERROR",pData); if (uitmp) { rxBuf[0] = 0x45; rxBuf[1] = 0x56; rxBuf[2] = 0x45; vmc_SendWithBuffer(rxBuf,3,0x69,0); } uitmp = biox_FindStrInBufferInt("REFUND",pData); if (uitmp) { rxBuf[0] = 0x45; rxBuf[1] = 0x56; rxBuf[2] = 0x52; vmc_SendWithBuffer(rxBuf,3,0x69,0); //TODO refund bill here. Should not trigger, but it might. } } uitmp = biox_FindStrInBufferInt("DocClosed",pData); if (uitmp) { asynchState = 0x01; //Transaction successful //if (VendRequest) GWstate.VendRequest=0; } /*while (pData[uitmp] != 0x00) { //0x00 is the end marker if (tagNameLength > 0x7F) { //tagNameLength -= 0x80; for (uitmp2 = 0; uitmp2 < (tagNameLength - 0x80); ++uitmp2) { tagName[uitmp2] = pData[uitmp + 1 + uitmp2]; } //TODO Do something with the name here uitmp = uitmp2 + 1; tagNameLength = pData[uitmp]; } else { for (uitmp2 = 0; uitmp2 < tagNameLength; ++uitmp2) { tagName[uitmp2] = pData[uitmp + 1 + uitmp2]; } //TODO Do something with the name here uitmp = uitmp2 + 1; curElementLength = ((UINT) pData[uitmp] << 8) | pData[uitmp]; for (uitmp2 = 0; uitmp2 < curElementLength; ++uitmp2) { curElement[uitmp2] = pData[uitmp + 1 + uitmp2]; } //TODO Do something with the data here uitmp = uitmp2 + 1; tagNameLength = pData[uitmp]; } }*/ } void iuc_asynchpos_startCommunication() { unsigned char uctmp = EOT; biox_Usart3_ClearRecBuffer(); biox_Usart3_SendBlock(&uctmp,1); } void iuc_asynchpos_init() { //TODO: CHANGE THIS LATER ON! TEST ONLY! #ifdef IUC_ASYCHNPOS_TESTMODE unsigned char APAK[] = "9D547268976ADE1BBB39DE90F3A449E5"; //9D547268976ADE1BBB39DE90F3A449E5 unsigned char TID[] = "T-LT-OPT-01"; #endif unsigned char timeStart[] = "2018-01-01 00:00:00"; unsigned int uitmp = 0; iuc_asynchpos_sub_initArray(asynchBill.time,20); biox_CopyBlock(timeStart,0,asynchBill.time,0,biox_StrLen(timeStart)); //iuc_asynchpos_sub_initArray(asynchBill.id,20); //iuc_asynchpos_sub_initArray(asynchBill.docNr,32); iuc_asynchpos_sub_clear_message(0x01); asynchState = 0; iuc_asynch_keepAlive = 0x00; iuc_asynch_PrintControl = 0x00; tableCreated = 0x00; #ifdef IUC_ASYCHNPOS_TESTMODE iuc_asynchpos_setTerminalAPAK(APAK, biox_StrLen(APAK)); iuc_asynchpos_setTerminalID(TID, biox_StrLen(TID)); #endif ENQrecieved = 0x00; timeInitalized = GWglobTime.SecOfDay; asynchSessionClosed = 0x00; iuc_asynch_PRNrecieved = 0x00; iuc_asynchpos_crc_old = 0; iucAsynchpoxDataContext = 0x00; iuc_asynch_printTimeout = IUC_ASYNCHPOS_PRINTTIMOUT; brd_switch_RS3(RS3SW2IUC); biox_Usart3_ClearRecBuffer(); biox_Usart3Ini(USART_Mode_Int, USART_Baud19200, USART_data8, USART_stop1, USART_parity_none); biox_delay_ms(1); /* Apak: 9D547268976ADE1BBB39DE90F3A449E5 Terminal id: T-LT-OPT-01 */ for (uitmp = 0; uitmp < IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE; ++uitmp) terminalAPAK[uitmp] = Conf.APAK_backup[uitmp]; //biox_CopyBlock(Conf.APAK_backup,0,terminalAPAK,0,IUC_ASYNCHPOS_MIN_BASE_DATA_SIZE); iuc_asynchpos_resetBuffers(0x00); iuc_asynchpos_startCommunication(); } unsigned char iuc_asynchpos_recieve_serial(unsigned char waitforACK) { unsigned int rxLength = 0; unsigned int uitemp = 0; unsigned int uitemp2 = 0; unsigned char rxData_[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; // unsigned char messageReturnData[100]; unsigned char messageLength_[8]; unsigned char messageCounter_[8]; unsigned char chksum = 0x00; unsigned char uctmp = 0x00; unsigned char resetBuffers = 0x00; //unsigned int rxCounter = messageLength; unsigned char fullPackage = 0x00; unsigned char rxBuf[8]; //if (biox_Usart2_NewTelegram()) { //brd_SendDiagStr("<----- IUC ASYNCHPOS",1); //get datastream from buffer //iuc_asynchpos_sub_initArray(rxData_, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); rxLength = biox_Usart3BuffSize(); rxData_[0] = 0xFF; if (rxLength > 0) { brd_SendDiagStr("<----- IUC ASYNCHPOS",1); if (rxLength >= IUC_ASYNCHPOS_MAX_ARRAY_SIZE) { brd_SendDiagStr("->IUC ASYNCHPOS rx buffer overflow!",1); biox_Usart3_ClearRecBuffer(); return 8; } brd_SendDiagStr("->IUC ASYNCHPOS Data recieved, ISMAS locked!",1); ism_lock(); timeHoldISMAS = GWglobTime.SecOfDay; //iuc_asynchpos_sub_initArray(rxData_, rxLength); biox_Usart3_GetRecBuffer(rxData_,rxLength); if (GWstate.DebugLevel & 0x10) { biox_itoa(rxLength,messageLength_); brd_SendDiagStr("->IUC ASYNCHPOS recieved: ",0); brd_SendDiagBlock(messageLength_,1,8); brd_SendDiagStr("->IUC ASYNCHPOS rx data: ",0); brd_SendDiagBlock(rxData_,1,rxLength); if (rxLength <= 1) brd_SendDiagStr("->IUC ASYNCHPOS Single Byte recieved.",1); } for (uitemp = 0; uitemp < rxLength/* && resetBuffers == 0x00*/; ++uitemp) { if (rxData_[uitemp] == EOT || (!ENQrecieved && rxData_[uitemp] == ENQ)) {//Either we did not initialize everysthing yet OR the PT wants to send something. if (uitemp == 0 || (uitemp > 0 && (rxData_[uitemp-1] != ETX1 || rxData_[uitemp-1] != ETX2))) { if (rxData_[uitemp] != ENQ) { resetBuffers = 0x01; } else { resetBuffers = 0x02; brd_SendDiagStr("->IUC ASYNCHPOS ENQ recieved, ISMAS unlocked!",1); ism_unlock(); } } } if (rxData_[uitemp] == ETX1 || (rxData_[uitemp] == ETX2)) fullPackage = 0x01; } if (resetBuffers) { //Does the terminal want to send? / Did we receive an EOT? /*ENQrecieved = 0x01; rxCounter = 0; messageLength = 0; iuc_asynchpos_sub_initArray(rxData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE);*/ /*if (ENQrecieved == 0) { brd_SendDiagStr("-> IUC ANSNYCHPOS initialized",1); } else { brd_SendDiagStr("->IUC ASYNCHPOS listening to terminal",1); }*/ if (resetBuffers >= 0x01) { iuc_asynchpos_resetBuffers(0x01); } else { iuc_asynchpos_resetBuffers(0x00); } if (rxLength > 1) { //biox_Usart2_ClearRecBuffer(); uctmp = NAK; biox_Usart3_SendBlock(&uctmp,1); } //iuc_asynchpos_sub_initArray(messageData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE); return 2; //Yes, it does. / Yes, we did. } else if (ENQrecieved && fullPackage/* && biox_Usart2_NewTelegram()*/) { brd_SendDiagStr("->IUC ASYNCHPOS Full packet recieved, ISMAS unlocked!",1); ism_unlock(); //brd_SendDiagStr("->IUC ASYNCHPOS Data recieved.",1); //calculate chksum for (uitemp = 1; uitemp < (rxLength - 1) && (rxData_[uitemp - 1] != ACK1 || rxData_[uitemp - 1] != ACK2); ++uitemp) { chksum ^= rxData_[uitemp]; } if (chksum != rxData_[uitemp]) { biox_Usart3_ClearRecBuffer(); uctmp = NAK; biox_Usart3_SendBlock(&uctmp,1); brd_SendDiagStr("->IUC ASYNCHPOS Sending NACK (Checksum mismatch).",1); return 3; //checksum mismatch } else { biox_Usart3_ClearRecBuffer(); if (rxData_[rxLength - 2] == ETX1) { uctmp = ACK1; biox_Usart3_SendBlock(&uctmp,1); brd_SendDiagStr("->IUC ASYNCHPOS Sending ACK1.",1); //iucAsynchpoxDataContext = 0x01; } else if (rxData_[rxLength - 2] == ETX2) { uctmp = ACK2; biox_Usart3_SendBlock(&uctmp,1); brd_SendDiagStr("->IUC ASYNCHPOS Sending ACK2.",1); //iucAsynchpoxDataContext = 0x00; } else { uctmp = NAK; biox_Usart3_SendBlock(&uctmp,1); brd_SendDiagStr("->IUC ASYNCHPOS Sending NACK (Wrong Byte).",1); return 4; //We got something wrong and it's causing an error } } /*if (iuc_asynchpos_crc_old == rxData_[rxLength - 2]) { //We recieved that package already iuc_asynchpos_crc_old = 0; brd_SendDiagStr("->IUC ASYNCHPOS EXCEPTION: double package!",1); brd_SendDiagStr("->IUC ASYNCHPOS rx data: ",0); brd_SendDiagBlock(rxData_,1,rxLength); return 5; } iuc_asynchpos_crc_old = rxData_[rxLength - 2];*/ //reformatting according to specs for (uitemp = 0; uitemp < rxLength; ++uitemp) { if (rxData_[uitemp] == DLE) { rxData_[uitemp] = rxData_[uitemp + 1] - 0x30; for (uitemp2 = uitemp + 2; uitemp2 < rxLength; ++uitemp2) { rxData_[uitemp2 - 1] = rxData_[uitemp2]; } --rxLength; } } //Check if we received a logical ACK or NACK if (rxCounter == 0) { if (rxData_[3] == 0x0F) { //NACK recieved, resend message brd_SendDiagStr("-> IUC ANSNYCHPOS Message NOT ackknowledged",1); if (asynchState < 0x02) { iuc_asynchpos_sub_initArray(rxBuf,8); rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0xFF; vmc_SendWithBuffer(rxBuf,3,0x69,0); } return 0; } if (rxData_[3] == 0x0A) { //ACK recieved, do nothing brd_SendDiagStr("-> IUC ANSNYCHPOS Message acknowledged",1); if (asynchState < 0x02) { asynchState = 0x02; iuc_asynchpos_sub_initArray(rxBuf,8); rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0x00; vmc_SendWithBuffer(rxBuf,3,0x69,0); } return 0; } } if (rxCounter == 0) { messageLength = ((UINT) rxData_[1] << 8) | rxData_[2]; if (GWstate.DebugLevel & 0x10) { biox_itoa(messageLength,messageLength_); brd_SendDiagStr("->IUC ASYNCHPOS message length: ",0); brd_SendDiagBlock(messageLength_,1,8); } if (messageLength + 1 < IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE) { iuc_asynchpos_sub_initArray(messageData, /*messageLength + 1*/ IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE); } else { messageLength = 0; brd_SendDiagStr("->IUC ASYNCHPOS message too long!",0); //iuc_asynchpos_sub_initArray(messageData, IUC_ASYNCHPOS_MAX_RX_MESSAGE_SIZE); iuc_asynchpos_sub_initArray(rxBuf,8); rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0xFF; vmc_SendWithBuffer(rxBuf,3,0x69,0); iuc_asynchpos_resetBuffers(0x00); return 6; } } if (messageLength > 0) { //add to rxData uitemp = 1; //while (rxData_[uitemp] != ETX1 && rxData_[uitemp] != ETX2 && rxData_[uitemp] != STX) { while (/*rxData_[uitemp] != 0x02 && rxData_[uitemp] != 0x03*/uitemp < (rxLength - 2)) { //removing the STX, ETX, the checksum and additional zero at the end rxAsynchData[(uitemp - 1) + rxCounter] = rxData_[uitemp]; ++uitemp; } rxCounter += uitemp - 1; if (GWstate.DebugLevel & 0x10) { biox_itoa(rxCounter,messageCounter_); brd_SendDiagStr("->IUC ASYNCHPOS message counter: ",0); brd_SendDiagBlock(messageCounter_,1,8); brd_SendDiagStr("->IUC ASYNCHPOS recieve buffer: ",0); brd_SendDiagBlock(rxAsynchData,1,rxCounter); } //NEXT Telegram if (/*messageLength != 0 && messageLength <= (rxCounter + 5)*/ rxCounter >= (messageLength - 1)) { if (GWstate.DebugLevel & 0x10) { biox_itoa(messageLength,messageLength_); brd_SendDiagStr("->IUC ASYNCHPOS message length FINAL: ",0); brd_SendDiagBlock(messageLength_,1,8); biox_itoa(rxCounter,messageCounter_); brd_SendDiagStr("->IUC ASYNCHPOS message counter FINAL: ",0); brd_SendDiagBlock(messageCounter_,1,8); } if (rxAsynchData[2] != 0x0A) { //iuc_asynchpos_sub_initArray(messageReturnData, 100);; //iuc_asynchpos_sub_initArray(messageData, messageLength + 1);//iuc_asynchpos_sub_initArray(messageReturnData, IUC_ASYNCHPOS_MAX_MESSAGE_SIZE); //if (!iuc_asynchpos_sub_confirm_message(messageData, IUC_ASYNCHPOS_MAX_ARRAY_SIZE))) { //Send ACK to terminal //iuc_asynchpos_resetBuffers(0x02); /*for (uitemp = 0; uitemp < rxAsynchData[11] + 9; ++uitemp) { messageReturnData[uitemp + 3] = rxAsynchData[uitemp + 3]; } ++uitemp; //messageReturnData[0] = 0x02; messageReturnData[0] = uitemp & (0xFF00); messageReturnData[1] = uitemp & (0x00FF); messageReturnData[2] = 0x0A;*/ //messageReturnData[uitemp + 2] = ETX1; //calculate chksum /*for (uitemp2 = 1; uitemp2 < uitemp + 2; ++uitemp2) { messageReturnData[uitemp + 3] ^= messageReturnData[uitemp]; }*/ //biox_Usart2_SendBlock(messageReturnData,uitemp + 4); //brd_SendDiagStr("->IUC ASYNCHPOS message ACKNOWLEDGE: ",0); //brd_SendDiagBlock(messageReturnData,1,uitemp + 1); //iuc_asynchpos_send_serial(messageReturnData,uitemp + 1,0x01,0x01); for (uitemp = 0; uitemp < rxCounter - (12 + rxAsynchData[11]); ++uitemp) { messageData[uitemp] = rxAsynchData[uitemp + (12 + (UINT) rxAsynchData[11])]; if (messageData[uitemp] == 0x00) messageData[uitemp] = 0x30; } uitemp = biox_FindStrInBufferInt("PrintReceipt",messageData) | biox_FindStrInBufferInt("PRINTRECEIPT",messageData) | biox_FindStrInBufferInt("AuthorizationResult",messageData) | biox_FindStrInBuffer("AUTHORIZATIONRESULT",messageData); if (uitemp) { if (biox_FindStrInBufferInt("PrintReceipt",messageData) | biox_FindStrInBufferInt("PRINTRECEIPT",messageData)) { biox_CopyBlock(rxAsynchData,3,terminalSignature,0,8); } else { biox_CopyBlock(rxAsynchData,3,terminalSignature,8,8); } } else { iuc_asynchpos_sub_sendACK(0); } if (GWstate.DebugLevel & 0x10) { brd_SendDiagStr("->IUC ASYNCHPOS full message: ",0); brd_SendDiagBlock(messageData,1,rxCounter - (12 + ((UINT) rxAsynchData[11]))); } iuc_asynchpos_handleMessage(messageData); brd_SendDiagStr("-> IUC ANSNYCHPOS Data handled",1); } /*brd_SendDiagStr("->IUC ASYNCHPOS full message: ",0); brd_SendDiagBlock(messageData,1,rxCounter - (12 + rxAsynchData[11])); iuc_asynchpos_handleMessage(messageData); brd_SendDiagStr("-> IUC ANSNYCHPOS Data handled",1);*/ iuc_asynchpos_resetBuffers(0x00); } } return 1; //Still busy } } //else { if (ENQrecieved == 0 && (timeInitalized + 10) < GWglobTime.SecOfDay) { brd_SendDiagStr("->IUC ASYNCHPOS waiting for initialization",1); biox_Usart3_ClearRecBuffer(); iuc_asynchpos_init(); return 1; } if (ism_islocked() && (timeHoldISMAS - GWglobTime.SecOfDay >= 1800)) { brd_SendDiagStr("->IUC ASYNCHPOS ISMAS holding timeout, ISMAS unlocked!",1); ism_unlock(); } if (iuc_asynch_PrintControl == 0xFF) { iuc_asynch_keepAlive = 0x00; iuc_asynchpos_sub_sendACK(1); biox_delay_ms(2); iuc_asynchpos_sub_sendACK(2); biox_delay_ms(2); iuc_asynchpos_command_print_Result(0x01); biox_delay_ms(2); if (0x04 == asynchState) { //Was the authorization successful? brd_SendDiagStr("->IUC ASYNCHPOS Sending YES receipt to VMC.",1); vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x10); //Yes } else { brd_SendDiagStr("->IUC ASYNCHPOS Sending NO receipt to VMC.",1); vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x20); //No } iuc_asynch_PrintControl = 0; //VendRequest=0; return 1; } /*if (iuc_asynch_PrintControl == 0xFE) { iuc_asynch_keepAlive = 0x00; iuc_asynchpos_sub_initArray(rxBuf,8); rxBuf[0] = 0x45; rxBuf[1] = 0x00; rxBuf[2] = 0x00; vmc_SendWithBuffer(rxBuf,8,0x69,0); iuc_asynch_PrintControl = 0; return 1; }*/ if (rxData_[0] != STX/* && rxLength > 0 && rxData_[0] != 0xFF*/) { //brd_SendDiagStr("->IUC ASYNCHPOS No STX recieved, ISMAS unlocked, sending NACK!",1); if (rxData_[0] != 0xFF) { brd_SendDiagStr("->IUC ASYNCHPOS No STX recieved, ISMAS unlocked!",1); ism_unlock(); } biox_Usart3_ClearRecBuffer(); //uctmp = NAK; //biox_Usart3_SendBlock(&uctmp,1); } //Workaround for our terminal problem, which, sometimes, fails to send a Print Result /*if (0xF0 == iuc_asynch_PrintControl) { if (0x00 == iuc_asynch_printTimeout) { iuc_asynchpos_sub_initArray(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); receiptData[0] = 0x50; if (0x04 == asynchState) { //Was the authorization successful? vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x10); //Yes } else { vmc_SendWithBuffer(receiptData,IUC_ASYNCHPOS_MAX_ARRAY_SIZE,0x69,0x20); //No } iuc_asynch_printTimeout = IUC_ASYNCHPOS_PRINTTIMOUT; iuc_asynch_PrintControl = 0; } else { --iuc_asynch_printTimeout; biox_delay_ms(1); } }*/ //} if (waitforACK) return 8; return 0; } //messagees void iuc_asynchpos_sub_synchTime() { UINT uitemp = 0; //unsigned char timeStart[] = "2017-12-19 13:40:00"; //biox_CopyBlock(timeStart,0,asynchBill.time,0,biox_StrLen(timeStart)); for (uitemp = 0; uitemp < 6; ++uitemp) { switch (uitemp) { case 0: //year asynchBill.time[2] = (GWglobTime.year / 10) + 0x30;; asynchBill.time[3] = (GWglobTime.year % 10) + 0x30; /*#ifdef IUC_ASYCHNPOS_TESTMODE asynchBill.time[2] = 0x31; asynchBill.time[3] = 0x39; #endif*/ break; case 1: //month asynchBill.time[5] = (GWglobTime.month / 10) + 0x30;; asynchBill.time[6] = (GWglobTime.month % 10) + 0x30; /*#ifdef IUC_ASYCHNPOS_TESTMODE asynchBill.time[5] = 0x31; asynchBill.time[6] = 0x32; #endif*/ break; case 2: //day asynchBill.time[8] = (GWglobTime.dayOfMon / 10) + 0x30;; asynchBill.time[9] = (GWglobTime.dayOfMon % 10) + 0x30; /*#ifdef IUC_ASYCHNPOS_TESTMODE asynchBill.time[8] = 0x30; asynchBill.time[9] = 0x32; #endif*/ break; case 3: //hours asynchBill.time[11] = (GWglobTime.hour / 10) + 0x30;; asynchBill.time[12] = (GWglobTime.hour % 10) + 0x30; /*#ifdef IUC_ASYCHNPOS_TESTMODE asynchBill.time[11] = 0x31; asynchBill.time[12] = 0x32; #endif*/ break; case 4: //minutes asynchBill.time[14] = (GWglobTime.min / 10) + 0x30;; asynchBill.time[15] = (GWglobTime.min % 10) + 0x30; /*#ifdef IUC_ASYCHNPOS_TESTMODE asynchBill.time[14] = 0x30; asynchBill.time[15] = 0x30; #endif*/ break; case 5: //seconds asynchBill.time[17] = (GWglobTime.sec / 10) + 0x30;; asynchBill.time[18] = (GWglobTime.sec % 10) + 0x30; break; } } } void iuc_asynchpos_command_ping_terminal() { UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; UCHAR packetType = 0x00; UINT uitemp = 0; UCHAR command[] = "Ping"; UCHAR tagName[] = "Time"; // UCHAR tagValue[] = "2017-12-19 13:40:00"; //Constructing the message iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); //biox_CopyBlock(UCHAR *src, UINT srcPos, UCHAR *dest, UINT destPos, UINT len); uitemp = (UCHAR) biox_StrLen(command); message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length biox_CopyBlock(command,0,message,1,uitemp); //tag name ++uitemp; message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length ++uitemp; biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name uitemp += (1 + biox_StrLen(tagName)); iuc_asynchpos_sub_synchTime(); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length ++uitemp; biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value uitemp += biox_StrLen(asynchBill.time)/* + 1*/; iuc_asynchpos_send(packetType,message,uitemp,0x00); } //80 - d void iuc_asynchpos_command_Login() { //Kasse registrieren UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; UCHAR packetType = 0x00; UINT uitemp = 0; UCHAR command[] = "Login"; UCHAR tagName[] = "Time"; //UCHAR tag2Name[] = "IdleText"; UCHAR tag3Name[] = "Flags"; UCHAR tag3Value[] = "AP3"; //Constructing the message iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); uitemp = (UCHAR) biox_StrLen(command); message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length biox_CopyBlock(command,0,message,1,uitemp); //tag name ++uitemp; message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length ++uitemp; biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name uitemp += (1 + biox_StrLen(tagName)); //Time iuc_asynchpos_sub_synchTime(); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length ++uitemp; biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value uitemp += biox_StrLen(asynchBill.time); //Flags message[uitemp] = (UCHAR) biox_StrLen(tag3Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name uitemp += (1 + biox_StrLen(tag3Name)); message[uitemp] = (UCHAR) biox_StrLen(tag3Value);//value length ++uitemp; biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value uitemp += biox_StrLen(tag3Value)/* + 1*/; iuc_asynchpos_send(packetType,message,uitemp,0x01); } //81 - d void iuc_asynchpos_command_Logout () { //Kassenschluss UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; UCHAR packetType = 0x00; UINT uitemp = 0; UCHAR command[] = "Logout"; UCHAR tagName[] = "Time"; //Constructing the message iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); uitemp = (UCHAR) biox_StrLen(command); message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length biox_CopyBlock(command,0,message,1,uitemp); //tag name ++uitemp; message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length ++uitemp; biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name uitemp += (1 + biox_StrLen(tagName)); iuc_asynchpos_sub_synchTime(); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length ++uitemp; biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value uitemp += biox_StrLen(asynchBill.time)/* + 1*/; iuc_asynchpos_send(packetType,message,uitemp,0x01); asynchState = 0x00; } //54 - d void iuc_asynchpos_command_authorize(unsigned int vkPreis) { UCHAR message[IUC_ASYNCHPOS_MAX_ARRAY_SIZE]; UCHAR packetType = 0x00; UINT uitemp = 0; UCHAR command[] = "Authorize"; UCHAR tag1Name[] = "Amount"; UCHAR tag2Name[] = "Cash"; UCHAR tag3Name[] = "Currency"; UCHAR tag4Name[] = "DocNr"; UCHAR tag5Name[] = "Time"; UCHAR tag6Name[] = "Lang"; UCHAR tag1Value[10]; UCHAR tag2Value[] = "0"; UCHAR tag3Value[] = "978"; UCHAR tag6Value[] = "lt"; UINT vkPreis_ = vkPreis; iuc_asynch_PRNrecieved = 0; //Constructing the message iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_ARRAY_SIZE); iuc_asynchpos_sub_initArray(tag1Value,10); uitemp = (UCHAR) biox_StrLen(command); message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length biox_CopyBlock(command,0,message,1,uitemp); //tag name ++uitemp; //Amount message[uitemp] = (UCHAR) biox_StrLen(tag1Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag1Name,0,message,uitemp, biox_StrLen(tag1Name));// tag name uitemp += (1 + biox_StrLen(tag1Name)); biox_itoa(vkPreis_,tag1Value); message[uitemp] = (UCHAR) biox_StrLen(tag1Value);//value length ++uitemp; biox_CopyBlock(tag1Value,0,message,uitemp, biox_StrLen(tag1Value));//value uitemp += (/*1 + */biox_StrLen(tag1Value)); //Cash message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name uitemp += (1 + biox_StrLen(tag2Name)); message[uitemp] = (UCHAR) biox_StrLen(tag2Value);//value length ++uitemp; biox_CopyBlock(tag2Value,0,message,uitemp, biox_StrLen(tag2Value));//value uitemp += (/*1 + */biox_StrLen(tag2Value)); //Currency message[uitemp] = (UCHAR) biox_StrLen(tag3Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag3Name,0,message,uitemp, biox_StrLen(tag3Name));// tag name uitemp += (1 + biox_StrLen(tag3Name)); message[uitemp] = (UCHAR) biox_StrLen(tag3Value);//value length ++uitemp; biox_CopyBlock(tag3Value,0,message,uitemp, biox_StrLen(tag3Value));//value uitemp += (/*1 + */biox_StrLen(tag3Value)); //DocNr message[uitemp] = (UCHAR) biox_StrLen(tag4Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag4Name,0,message,uitemp, biox_StrLen(tag4Name));// tag name uitemp += (1 + biox_StrLen(tag4Name)); //biox_ltoa(asynchBill.docuNr,asynchBill.docNr); //++asynchBill.docuNr; generate_UniqueTransNr(asynchBill.docNr); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length ++uitemp; biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value uitemp += biox_StrLen(asynchBill.docNr)/* + 1*/; //Time message[uitemp] = (UCHAR) biox_StrLen(tag5Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag5Name,0,message,uitemp, biox_StrLen(tag5Name));// tag name uitemp += (1 + biox_StrLen(tag5Name)); iuc_asynchpos_sub_synchTime(); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.time);//value length ++uitemp; biox_CopyBlock(asynchBill.time,0,message,uitemp, biox_StrLen(asynchBill.time));//value uitemp += biox_StrLen(asynchBill.time)/* + 1*/; //Language message[uitemp] = (UCHAR) biox_StrLen(tag6Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag6Name,0,message,uitemp, biox_StrLen(tag6Name));// tag name uitemp += (1 + biox_StrLen(tag6Name)); message[uitemp] = (UCHAR) biox_StrLen(tag6Value);//value length ++uitemp; biox_CopyBlock(tag6Value,0,message,uitemp, biox_StrLen(tag6Value));//value uitemp += biox_StrLen(tag6Value)/* + 1*/; iuc_asynchpos_send(packetType,message,uitemp,0x00); } //73 - d void iuc_asynchpos_command_cancel_authorize() { UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; UCHAR packetType = 0x00; UINT uitemp = 0; UCHAR command[] = "AuthorizationCancelled"; UCHAR tagName[] = "ID"; //Constructing the message iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); uitemp = biox_StrLen(command); message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length biox_CopyBlock(command,0,message,1,uitemp); //tag name if (asynchBill.id[0] != 0x00) { ++uitemp; message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length ++uitemp; biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name uitemp += (1 + biox_StrLen(tagName)); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.id);//value length ++uitemp; biox_CopyBlock(asynchBill.id,0,message,uitemp, biox_StrLen(asynchBill.id));//value uitemp += biox_StrLen(asynchBill.id)/* + 1*/; } iuc_asynchpos_send(packetType,message,uitemp,0x00); } //77 - d void iuc_asynchpos_command_close_Document(unsigned char isStorno) { //Finalize sale UCHAR message[IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE]; UCHAR packetType = 0x00; UINT uitemp = 0; UCHAR command[] = "DocClosed"; UCHAR tagName[] = "DocNr"; UCHAR tag2Name[] = "AuthID"; //Constructing the message iuc_asynchpos_sub_initArray(message,IUC_ASYNCHPOS_MAX_TX_MESSAGE_SIZE); uitemp = biox_StrLen(command); message[0] = (UCHAR) uitemp + 0x80; //constructed element, tag name length biox_CopyBlock(command,0,message,1,uitemp); //tag name ++uitemp; //DocNr message[uitemp] = (UCHAR) biox_StrLen(tagName);//data element, tag name length ++uitemp; biox_CopyBlock(tagName,0,message,uitemp, biox_StrLen(tagName));// tag name uitemp += (1 + biox_StrLen(tagName)); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.docNr);//value length ++uitemp; biox_CopyBlock(asynchBill.docNr,0,message,uitemp, biox_StrLen(asynchBill.docNr));//value uitemp += biox_StrLen(asynchBill.docNr); //AuthID if (!isStorno) { message[uitemp] = (UCHAR) biox_StrLen(tag2Name);//data element, tag name length ++uitemp; biox_CopyBlock(tag2Name,0,message,uitemp, biox_StrLen(tag2Name));// tag name uitemp += (1 + biox_StrLen(tag2Name)); message[uitemp] = (UCHAR) biox_StrLen(asynchBill.id);//value length ++uitemp; biox_CopyBlock(asynchBill.id,0,message,uitemp, biox_StrLen(asynchBill.id));//value uitemp += biox_StrLen(asynchBill.id)/* + 1*/; } iuc_asynchpos_send(packetType,message,uitemp,0x00); } void iuc_asynchpos_handleCommand(unsigned char command, unsigned char status) { //r - registration, a - authorization, c - cancel, s - storno, k - kassenschnitt UCHAR tempBuf[3]; UCHAR rxBuf[8]; // UINT uitemp = 0; UINT uitmp= 700; tempBuf[0] = 0x00; tempBuf[1] = 0x00; tempBuf[2] = 0x00; timeHoldISMAS = GWglobTime.SecOfDay; iuc_asynchpos_sub_initArray(rxBuf,8); //iuc_asynchpos_resetBuffers(0x00); switch (command) { case 0x72: //registration //iuc_asynchpos_init(); asynchState = 0x01; iuc_asynchpos_command_Login(); GWstate.VendRequest=1; break; case 0x61: //authorisation iuc_asynch_keepAlive = 0x01; iuc_asynch_PrintControl = 0; iuc_asynchpos_sub_clear_message(0x01); //VendRequest=1; iuc_asynchpos_resetBuffers(0x00); ///#ifdef IUC_ASYCHNPOS_TESTMODE //iuc_asynchpos_command_authorize(uitmp); //#else iuc_asynchpos_command_authorize(Vend.Amount); //#endif break; case 0x63: //cancel case 0x73: //storno /*if (asynchState <= 0x02 != 0) { //Authorization result recieved? iuc_asynchpos_command_cancel_authorize(); } else {*/ iuc_asynchpos_command_close_Document(0x01); //} iuc_asynch_keepAlive = 0x00; //VendRequest=0; break; case 0x6B: //kassenschnitt iuc_asynchpos_command_Logout(); break; case 0x62: //get last bill //iuc_zvt_getLastBill(tempBuf); break; case 0x01: iuc_asynchpos_command_close_Document(0x00); iuc_asynch_keepAlive = 0x00; //VendRequest=0; break; case 0x70: iuc_asynchpos_command_ping_terminal(); break; default: break; } } int iuc_asynchpos_checkTime() { int retVal = 0; if ((GWglobTime.hour == 0) && asynchSessionClosed != 0x00) { asynchSessionClosed = 0x00; retVal = 1; } else if ((GWglobTime.hour == 1) && asynchSessionClosed == 0x00) { iuc_asynchpos_command_Logout(); retVal = 1; asynchSessionClosed = 0x01; } else if ((GWglobTime.hour == 2) && asynchSessionClosed == 0x01) { iuc_asynchpos_command_Login(); retVal = 1; asynchSessionClosed = 0x02; } return retVal; } unsigned char iuc_asynchpos_getIsSaleRunning() { //Print, when idle /*if (iuc_print_counter && asynchState == 0x01) { iuc_asynchpos_command_print_Result(0x01); --iuc_print_counter; return 1; }*/ return iuc_asynch_keepAlive; } #endif