diff --git a/.gitignore b/.gitignore index 70ca3b2..333d004 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ __pycache__ *.pyc venv +/.idea/ +/py3_ecrterm.egg-info/ diff --git a/ecrterm/common.py b/ecrterm/common.py index 6a27554..2453e42 100644 --- a/ecrterm/common.py +++ b/ecrterm/common.py @@ -2,86 +2,173 @@ Common Base classes, Definitions and Ancestors. """ +TERMINAL_REQUIRED_STATUSES = [ + 0x01, 0x02, 0x03, 0x07, + 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x0E, 0x10, 0x12, 0x13, 0x14, 0x15, 0x17, 0x18, + 0x19, 0x1B, 0x1C, 0x1D, 0x43, 0x47, 0x48, 0x49, 0x4C, 0x4D, 0x4E, 0x50, 0x52, + 0x53, 0x55, 0x57, 0x58, 0x59, 0x5B, 0x5C, 0x5D +] + +INTERMEDIATE_STATUS_CODES_DE = { + 0x00: 'BZT wartet auf Betragbestätigung', + 0x01: 'Bitte Anzeigen auf dem PIN-Pad beachten', + 0x02: 'Bitte Anzeigen auf dem PIN-Pad beachten', + 0x03: 'Vorgang nicht möglich ', + 0x04: 'BZT wartet auf Antwort vom FEP ', + 0x05: 'BZT sendet Autostorno', + 0x06: 'BZT sendet Nachbuchungen', + 0x07: 'Karte nicht zugelassen ', + 0x08: 'Karte unbekannt / undefiniert ', + 0x09: 'Karte verfallen', + 0x0A: 'Karte einstecken', + 0x0B: 'Bitte Karte entnehmen!', + 0x0C: 'Karte nicht lesbar ', + 0x0D: 'Vorgang abgebrochen', + 0x0E: 'Vorgang wird bearbeitet bitte warten... ', + 0x0F: 'BZT leitet einen automatischen Kassenabschluss ein', + 0x10: 'Karte ungültig ', + 0x11: 'Guthabenanzeige', + 0x12: 'Systemfehler', + 0x13: 'Zahlung nicht möglich', + 0x14: 'Guthaben nicht ausreichend ', + 0x15: 'Geheimzahl falsch', + 0x16: 'Limit nicht ausreichend ', + 0x17: 'Bitte warten... ', + 0x18: 'Geheimzahl zu oft falsch ', + 0x19: 'Kartendaten falsch', + 0x1A: 'Servicemodus', + 0x1B: 'Autorisierung erfolgt. Bitte tanken ', + 0x1C: 'Zahlung erfolgt. Bitte Ware entnehmen ', + 0x1D: 'Autorisierung nicht möglich ', + 0x26: 'BZT wartet auf Eingabe der Mobilfunknummer', + 0x27: 'BZT wartet auf Wiederholung der Mobilfunknummer ', + 0x41: 'Bitte Anzeigen auf dem PIN-Pad beachten. Bitte Karte entnehmen! ', + 0x42: 'Bitte Anzeigen auf dem PIN-Pad beachten. Bitte Karte entnehmen! ', + 0x43: 'Vorgang nicht möglich. Bitte Karte entnehmen!', + 0x44: 'BZT wartet auf Antwort vom FEP. Bitte Karte entnehmen! ', + 0x45: 'BZT sendet Autostorno. Bitte Karte entnehmen! ', + 0x46: 'BZT sendet Nachbuchungen. Bitte Karte entnehmen! ', + 0x47: 'Karte nicht zugelassen. Bitte Karte entnehmen! ', + 0x48: 'Karte unbekannt / undefiniert. Bitte Karte entnehmen!', + 0x49: 'Karte verfallen. Bitte Karte entnehmen! ', + 0x4A: '', + 0x4B: 'Bitte Karte entnehmen!', + 0x4C: 'Karte nicht lesbar. Bitte Karte entnehmen! ', + 0x4D: 'Vorgang abgebrochen. Bitte Karte entnehmen! ', + 0x4E: 'Vorgang wird bearbeitet bitte warten... Bitte Karte entnehmen! ', + 0x4F: 'BZT leitet einen automatischen Kassenabschluss ein. Bitte Karte entnehmen!', + 0x50: 'Karte ungültig. Bitte Karte entnehmen!', + 0x51: 'Guthabenanzeige. Bitte Karte entnehmen! ', + 0x52: 'Systemfehler. Bitte Karte entnehmen! ', + 0x53: 'Zahlung nicht möglich. Bitte Karte entnehmen!', + 0x54: 'Guthaben nicht ausreichend. Bitte Karte entnehmen!', + 0x55: 'Geheimzahl falsch. Bitte Karte entnehmen! ', + 0x56: 'Limit nicht ausreichend. Bitte Karte entnehmen! ', + 0x57: 'Bitte warten... Bitte Karte entnehmen! ', + 0x58: 'Geheimzahl zu oft falsch. Bitte Karte entnehmen! ', + 0x59: 'Kartendaten falsch. Bitte Karte entnehmen!', + 0x5A: 'Servicemodus. Bitte Karte entnehmen! ', + 0x5B: 'Autorisierung erfolgt. Bitte tanken. Bitte Karte entnehmen! ', + 0x5C: 'Zahlung erfolgt. Bitte Ware entnehmen. Bitte Karte entnehmen!', + 0x5D: 'Autorisierung nicht möglich. Bitte Karte entnehmen! ', + 0x66: 'BZT wartet auf Eingabe der Mobilfunknummer. Bitte Karte entnehmen! ', + 0x67: 'BZT wartet auf Wiederholung der Mobilfunknummer. Bitte Karte entnehmen!', + 0xC7: 'BZT wartet auf Eingabe des Kilometerstands ', + 0xC8: 'BZT wartet auf Kassierer', + 0xC9: 'BZT leitet eine automatische Diagnose ein', + 0xCA: 'BZT leitet eine automatische Initialisierung ein', + 0xCB: 'Händlerjournal voll ', + 0xCC: 'Lastschrift nicht möglich, PIN notwendig ', + 0xD2: 'DFÜ-Verbindung wird hergestellt', + 0xD3: 'DFÜ-Verbindung besteht', + 0xE0: 'BZT wartet auf Anwendungsauswahl ', + 0xE1: 'BZT wartet auf Sprachauswahl ', + 0xF1: 'Offline ', + 0xF2: 'Online', + 0xF3: 'Offline-Transaktion', + 0xFF: 'custom or unknown status.', +} + INTERMEDIATE_STATUS_CODES = { 0x00: 'PT is waiting for amount - confirmation', - 0x01: 'please watch PIN - Pad', - 0x02: 'please watch PIN - Pads', - 0x03: 'not accepted', + 0x01: 'Please watch PIN - Pad', + 0x02: 'Please watch PIN - Pad', + 0x03: 'Not accepted', 0x04: 'PT is waiting for response from FEP', 0x05: 'PT is sending auto - reversal', 0x06: 'PT is sending post - bookings', - 0x07: 'card not admitted', - 0x08: 'card unknown / undefined', - 0x09: 'expired card', - 0x0A: 'insert card', - 0x0B: 'please remove card !', - 0x0C: 'card not readable', - 0x0D: 'processing error', - 0x0E: 'please wait...', + 0x07: 'Card not admitted', + 0x08: 'Card unknown / undefined', + 0x09: 'Expired card', + 0x0A: 'Insert card', + 0x0B: 'Please remove card !', + 0x0C: 'Card not readable', + 0x0D: 'Processing error', + 0x0E: 'Please wait...', 0x0F: 'PT is commencing an automatic end - of - day batch', - 0x10: 'invalid card', - 0x11: 'balance display', - 0x12: 'system malfunction', - 0x13: 'payment not possible', - 0x14: 'credit not sufficient', - 0x15: 'incorrect PIN', - 0x16: 'limit not sufficient', - 0x17: 'please wait...', + 0x10: 'Invalid card', + 0x11: 'Balance display', + 0x12: 'System malfunction', + 0x13: 'Payment not possible', + 0x14: 'Credit not sufficient', + 0x15: 'Incorrect PIN', + 0x16: 'Limit not sufficient', + 0x17: 'Please wait...', 0x18: 'PIN try limit exceeded', - 0x19: 'card - data incorrect', - 0x1A: 'service - mode', - 0x1B: 'approved. please fill - up', - 0x1C: 'approved. please take goods', - 0x1D: 'declined', + 0x19: 'Card - data incorrect', + 0x1A: 'Service - mode', + 0x1B: 'Approved. please fill - up', + 0x1C: 'Approved. please take goods', + 0x1D: 'Declined', 0x26: 'PT is waiting for input of the mobile - number', 0x27: 'PT is waiting for repeat of mobile number', - 0x41: 'please watch PIN - Pad please remove card !', - 0x42: 'please watch PIN - Pad please remove card !', - 0x43: 'not accepted, please remove card !', + 0x41: 'Please watch PIN - Pad please remove card !', + 0x42: 'Please watch PIN - Pad please remove card !', + 0x43: 'Not accepted, please remove card !', 0x44: 'PT is waiting for response from FEP please remove card !', 0x45: 'PT is sending auto - reversal please remove card !', 0x46: 'PT is sending post - booking please remove card !', - 0x47: 'card not admitted please remove card !', - 0x48: 'card unknown / undefined please remove card !', - 0x49: 'expired card please remove card !', + 0x47: 'Card not admitted please remove card !', + 0x48: 'Card unknown / undefined please remove card !', + 0x49: 'Expired card please remove card !', 0x4A: '', - 0x4B: 'please remove card !', - 0x4C: 'card not readable please remove card !', - 0x4D: 'processing error please remove card !', - 0x4E: 'please wait... please remove card !', + 0x4B: 'Please remove card !', + 0x4C: 'Card not readable please remove card !', + 0x4D: 'Processing error please remove card !', + 0x4E: 'Please wait... please remove card !', 0x4F: 'PT is commencing an automatic end - of - day batch please remove ' - 'card !', - 0x50: 'invalid card please remove card !', - 0x51: 'balance display please remove card !', - 0x52: 'system malfunction please remove card !', - 0x53: 'payment not possible please remove card !', - 0x54: 'credit not sufficient please remove card !', - 0x55: 'incorrect PIN please remove card !', - 0x56: 'limit not sufficient please remove card !', - 0x57: 'please wait... please remove card !', + 'card !', + 0x50: 'Invalid card please remove card !', + 0x51: 'Balance display please remove card !', + 0x52: 'System malfunction please remove card !', + 0x53: 'Payment not possible please remove card !', + 0x54: 'Credit not sufficient please remove card !', + 0x55: 'Incorrect PIN please remove card !', + 0x56: 'Limit not sufficient please remove card !', + 0x57: 'Please wait... please remove card !', 0x58: 'PIN try limit exceeded please remove card !', - 0x59: 'card - data incorrect please remove card !', - 0x5A: 'service - mode please remove card !', - 0x5B: 'approved. please fill - up please remove card !', - 0x5C: 'approved. please take goods please remove card !', - 0x5D: 'declined please remove card !', + 0x59: 'Card - data incorrect please remove card !', + 0x5A: 'Service - mode please remove card !', + 0x5B: 'Approved. please fill - up please remove card !', + 0x5C: 'Approved. please take goods please remove card !', + 0x5D: 'Declined please remove card !', 0x66: 'PT is waiting for input of the mobil - number please remove card !', 0x67: 'PT is waiting for repeat of the mobil - number please remove ' - 'card !', + 'card !', 0xC7: 'PT is waiting for input of the mileage', 0xC8: 'PT is waiting for cashier', 0xC9: 'PT is commencing an automatic diagnosis', 0xCA: 'PT is commencing an automatic initialisation', - 0xCB: 'merchant - journal full', - 0xCC: 'debit advice not possible, PIN required', - 0xD2: 'connecting dial - up', - 0xD3: 'dial - up connection made', + 0xCB: 'Merchant - journal full', + 0xCC: 'Debit advice not possible, PIN required', + 0xD2: 'Connecting dial - up', + 0xD3: 'Dial - up connection made', 0xE0: 'PT is waiting for application - selection', 0xE1: 'PT is waiting for language - selection', - 0xF1: 'offline', - 0xF2: 'online', - 0xF3: 'offline transaction', - 0xFF: 'custom or unknown status.', + 0xF1: 'Offline', + 0xF2: 'Online', + 0xF3: 'Offline transaction', + 0xFF: 'Custom or unknown status.', } ERRORCODES = { @@ -92,78 +179,78 @@ 0x00: '00 no error', # 01-63 01 – 99 errorcodes from network-operator # system/authorisation-system', - 0x64: 'card not readable (LRC-/parity-error)', - 0x65: 'card-data not present (neither track-data nor chip found)', - 0x66: 'processing-error (also for problems with card-reader mechanism)', - 0x67: 'function not permitted for ec- and Maestro-cards', - 0x68: 'function not permitted for credit- and tank-cards', - 0x6A: 'turnover-file full', - 0x6B: 'function deactivated (PT not registered)', - 0x6C: 'abort via time-out or abort-key ', - 0x6E: 'card in blocked-list (response to command 06 E4)', - 0x6F: 'wrong currency', - 0x71: 'credit not sufficient (chip-card)', - 0x72: 'chip error ', - 0x73: 'card-data incorrect (e.g. country-key check, checksum-error)', - 0x77: 'end-of-day batch not possible ', - 0x78: 'card expired', - 0x79: 'card not yet valid', - 0x7A: 'card unknown', - 0x7D: 'communication error (communication module does not answer or is ' - 'not present)', - 0x83: 'function not possible', - 0x85: 'key missing', + 0x64: 'Card not readable (LRC-/parity-error)', + 0x65: 'Card-data not present (neither track-data nor chip found)', + 0x66: 'Processing-error (also for problems with card-reader mechanism)', + 0x67: 'Function not permitted for ec- and Maestro-cards', + 0x68: 'Function not permitted for credit- and tank-cards', + 0x6A: 'Turnover-file full', + 0x6B: 'Function deactivated (PT not registered)', + 0x6C: 'Abort via time-out or abort-key ', + 0x6E: 'Card in blocked-list (response to command 06 E4)', + 0x6F: 'Wrong currency', + 0x71: 'Credit not sufficient (chip-card)', + 0x72: 'Chip error ', + 0x73: 'Card-data incorrect (e.g. country-key check, checksum-error)', + 0x77: 'End-of-day batch not possible ', + 0x78: 'Card expired', + 0x79: 'Card not yet valid', + 0x7A: 'Card unknown', + 0x7D: 'Communication error (communication module does not answer or is ' + 'not present)', + 0x83: 'Function not possible', + 0x85: 'Key missing', 0x89: 'PIN-pad defective', - 0x9A: 'trnasferprotocol- error', - 0x9B: 'error from dial-up/communication fault', - 0x9C: 'please wait', - 0xA0: 'receiver not ready', - 0xA1: 'remote station does not respond', - 0xA3: 'no connection', - 0xA4: 'submission of Geldkarte not possible', - 0xB1: 'memory full', - 0xB2: 'merchant-journal full', - 0xB4: 'already reversed', - 0xB5: 'reversal not possible', - 0xB7: 'pre-authorisation incorrect (amount too high) or amount wrong', - 0xB8: 'error pre-authorisation', - 0xBF: 'voltage supply to low (external power supply)', - 0xC0: 'card locking mechanism defective', - 0xC1: 'merchant-card locked ', - 0xC2: 'diagnosis required', - 0xC3: 'maximum amount exceeded', - 0xC4: 'card-profile invalid. New card-profiles must be loaded.', - 0xC5: 'payment method not supported', + 0x9A: 'Trnasferprotocol- error', + 0x9B: 'Error from dial-up/communication fault', + 0x9C: 'Please wait', + 0xA0: 'Receiver not ready', + 0xA1: 'Remote station does not respond', + 0xA3: 'No connection', + 0xA4: 'Submission of Geldkarte not possible', + 0xB1: 'Memory full', + 0xB2: 'Merchant-journal full', + 0xB4: 'Already reversed', + 0xB5: 'Reversal not possible', + 0xB7: 'Pre-authorisation incorrect (amount too high) or amount wrong', + 0xB8: 'Error pre-authorisation', + 0xBF: 'Voltage supply to low (external power supply)', + 0xC0: 'Card locking mechanism defective', + 0xC1: 'Merchant-card locked ', + 0xC2: 'Diagnosis required', + 0xC3: 'Maximum amount exceeded', + 0xC4: 'Card-profile invalid. New card-profiles must be loaded.', + 0xC5: 'Payment method not supported', # PAGE 166 - 0xC6: 'currency not applicable', - 0xC8: 'amount zu small', - 0xC9: 'max. transaction-amount zu small', - 0xCB: 'function only allowed in EURO', - 0xCC: 'printer not ready', - 0xD2: 'function not permitted for service-cards/bank-customer-cards', - 0xDC: 'card inserted', - 0xDD: 'error during card-eject (for motor-insertion reader)', - 0xDE: 'error during card-insertion (for motor-insertion reader)', - 0xE0: 'remote-maintenance activated', - 0xE2: 'card-reader does not answer / card-reader defective', - 0xE3: 'shutter closed', - 0xE7: 'min. one goods-group not found', - 0xE8: 'no goods-groups-table loaded', - 0xE9: 'restriction-code not permitted', - 0xEA: 'card-code not permitted (e.g. card not activated via Diagnosis)', - 0xEB: 'function not executable (PIN-algorithm unknown)', + 0xC6: 'Currency not applicable', + 0xC8: 'Amount zu small', + 0xC9: 'Max. transaction-amount zu small', + 0xCB: 'Function only allowed in EURO', + 0xCC: 'Printer not ready', + 0xD2: 'Function not permitted for service-cards/bank-customer-cards', + 0xDC: 'Card inserted', + 0xDD: 'Error during card-eject (for motor-insertion reader)', + 0xDE: 'Error during card-insertion (for motor-insertion reader)', + 0xE0: 'Remote-maintenance activated', + 0xE2: 'Card-reader does not answer / card-reader defective', + 0xE3: 'Shutter closed', + 0xE7: 'Min. one goods-group not found', + 0xE8: 'No goods-groups-table loaded', + 0xE9: 'Restriction-code not permitted', + 0xEA: 'Card-code not permitted (e.g. card not activated via Diagnosis)', + 0xEB: 'Function not executable (PIN-algorithm unknown)', 0xEC: 'PIN-processing not possible', 0xED: 'PIN-pad defective', - 0xF0: 'open end-of-day batch present', - 0xF1: 'ec-cash/Maestro offline error', + 0xF0: 'Open end-of-day batch present', + 0xF1: 'Ec-cash/Maestro offline error', 0xF5: 'OPT-error', 0xF6: 'OPT-data not available (= OPT personalisation required)', - 0xFA: 'error transmitting offline-transactions (clearing error)', - 0xFB: 'turnover data-set defective', - 0xFC: 'necessary device not present or defective', - 0xFD: 'baudrate not supported', - 0xFE: 'register unknown', - 0xFF: 'system error' # (= other/unknown error), See TLV tags 1F16 and 1F17 + 0xFA: 'Error transmitting offline-transactions (clearing error)', + 0xFB: 'Turnover data-set defective', + 0xFC: 'Necessary device not present or defective', + 0xFD: 'Baudrate not supported', + 0xFE: 'Register unknown', + 0xFF: 'System error' # (= other/unknown error), See TLV tags 1F16 and 1F17 } TERMINAL_STATUS_CODES = { @@ -187,10 +274,9 @@ 0xE3: 'shutter closed', 0xF6: 'OPT-data not availble (= OPT-Personalisation required)'} - DEBUG_PACKET_NAME = { (0x0F, None): 'RFU for proprietary applications, the utilisation for ' - 'particular cases should be clarified between manufacturers', + 'particular cases should be clarified between manufacturers', (0x01, 0x01): 'RFU', (0x04, 0x01): 'Set Date and Time in ECR', (0x04, 0x0E): 'Menu-Request', @@ -229,13 +315,13 @@ (0x06, 0x79): 'Selftest', (0x06, 0x82): 'RFU', (0x06, 0x85): 'Display Text (only included for downwards-compatibility, ' - 'for new implementations use 06 E0)', + 'for new implementations use 06 E0)', (0x06, 0x86): 'Display Text with Numerical Input (only included for ' - 'downwards-compatibility, for new implementations use 06 E2)', + 'downwards-compatibility, for new implementations use 06 E2)', (0x06, 0x87): 'PIN-Verification for Customer-Card (only included for ' - 'downwards-compatibility, for new implementations use 06 E3)', + 'downwards-compatibility, for new implementations use 06 E3)', (0x06, 0x88): 'Display Text with Function-Key Input (only included for ' - 'downwards-compatibility, for new implementations use 06 E1)', + 'downwards-compatibility, for new implementations use 06 E1)', (0x06, 0x90): 'RFU', (0x06, 0x91): 'Set Date and Time in PT', (0x06, 0x93): 'Initialisation', diff --git a/ecrterm/ecr.py b/ecrterm/ecr.py index 470fede..83c747e 100644 --- a/ecrterm/ecr.py +++ b/ecrterm/ecr.py @@ -16,7 +16,7 @@ from ecrterm.packets.apdu import Packets from ecrterm.packets.base_packets import ( Authorisation, Completion, DisplayText, EndOfDay, Packet, PrintLine, - Registration, ResetTerminal, StatusEnquiry, StatusInformation) + Registration, ResetTerminal, StatusEnquiry, StatusInformation, AbortCommand) from ecrterm.packets.bmp import BCD from ecrterm.transmission._transmission import Transmission from ecrterm.transmission.signals import ACK, DLE, ETX, NAK, STX, TRANSMIT_OK @@ -314,6 +314,16 @@ def reset(self): sleep(1) return ret + def cancel_transaction(self): + """ + Cancel transaction during the process + """ + if self.transport.insert_delays: + # we actually make a small sleep, allowing better flow. + sleep(0.2) + transmission = self.transmitter.abort(AbortCommand(), None) + return transmission + def show_text(self, lines=None, duration=5, beeps=0): """ displays a text on the PT screen for duration of seconds. @@ -373,6 +383,8 @@ def transmit(self, packet): transmission = self.transmitter.transmit(packet) return transmission + + # dev functions. ######################################################################### diff --git a/ecrterm/transmission/_transmission.py b/ecrterm/transmission/_transmission.py index dbc8d24..b1a9b43 100644 --- a/ecrterm/transmission/_transmission.py +++ b/ecrterm/transmission/_transmission.py @@ -47,6 +47,7 @@ def _transmit(self, packet, history): Transmit the packet, go into slave mode and wait until the whole sequence is finished. """ + if not self.is_master or self.is_waiting: raise TransmissionException( 'Can\'t send until transmisson is ready') @@ -95,3 +96,44 @@ def transmit(self, packet, history=None): except Exception: self.history += self.last_history raise + + def abort(self, packet, history): + """ + Transmit the packet, go into slave mode and wait until the whole + sequence is finished. + """ + self.is_master = False + self.last = packet + try: + history += [(False, packet)] + success, response = self.transport.send(packet) + history += [(True, response)] + # we sent the packet. + # now lets wait until we get master back. + while not self.is_master: + self.is_master = self.handle_packet_response( + self.last, response) + if self.is_master: + break + try: + success, response = self.transport.receive( + self.actual_timeout) + history += [(True, response)] + except TransportLayerException: + # some kind of timeout. + # if we are already master, we can bravely ignore this. + if self.is_master: + return TRANSMIT_OK + raise + if self.is_master and success: + # we actually have to handle a last packet + stay_master = self.handle_packet_response( + packet, response) + print('Is Master Read Ahead happened.') + self.is_master = stay_master + except Exception: + self.is_master = True + raise + self.is_master = True + return TRANSMIT_OK +