From 89065e3b7343f2940ce2b1e3a81d140b78accf06 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Thu, 20 May 2021 17:07:40 +0300 Subject: [PATCH 01/11] Update sas.py Its working on IGT, EGT, Amatic, Novomatic, Casino Technology (Tested on all) Don't return False. At RAM CLEAR 0 is False and code is broken. Do not cache. If you lose SAS it will return the cache. Check crc method --- sas.py | 4474 ++++++++++++++++++++++++++++++++------------------------ 1 file changed, 2535 insertions(+), 1939 deletions(-) diff --git a/sas.py b/sas.py index f82db52..7b150c9 100644 --- a/sas.py +++ b/sas.py @@ -1,1953 +1,2549 @@ #!/usr/bin/python # -*- coding: utf8 -*- -import bcd +# import bcd import serial import time import binascii -#import string +# import string from PyCRC.CRC16Kermit import CRC16Kermit from array import array -#ser = serial.Serial('/dev/ttyS3','19200', timeout=1) # open first serial port -data_to_sent=[0x01, 0x21, 0x00, 0x00] -#adress=1 -#print "OK" -meters = dict.fromkeys(('total_cancelled_credits_meter', - 'total_in_meter', - 'total_out_meter', - 'total_in_meter', - 'total_jackpot_meter', - 'games_played_meter', - 'games_won_meter', - 'games_lost_meter', - 'games_last_power_up', - 'games_last_slot_door_close', - 'slot_door_opened_meter', - 'power_reset_meter', - 's1_bills_accepted_meter', - 's5_bills_accepted_meter', - 's10_bills_accepted_meter', - 's20_bills_accepted_meter', - 's50_bills_accepted_meter', - 's100_bills_accepted_meter', - 's500_bills_accepted_meter', - 's1000_bills_accepted_meter', - 's200_bills_accepted_meter', - 's25_bills_accepted_meter', - 's2000_bills_accepted_meter', - 's2500_bills_accepted_meter', - 's5000_bills_accepted_meter', - 's10000_bills_accepted_meter', - 's20000_bills_accepted_meter', - 's25000_bills_accepted_meter', - 's50000_bills_accepted_meter', - 's100000_bills_accepted_meter', - 's250_bills_accepted_meter', - 'cashout_ticket_number', - 'cashout_amount_in_cents', - 'ASCII_game_ID', - 'ASCII_additional_ID', - 'bin_denomination', - 'bin_max_bet', - 'bin_progressive_mode', - 'bin_game_options', - 'ASCII_paytable_ID', - 'ASCII_base_percentage', - 'bill_meter_in_dollars', - 'ROM_signature', - 'current_credits', - 'bin_level', - 'amount', - 'partial_pay_amount', - 'bin_reset_ID', - 'bill_meter_in_dollars', - 'true_coin_in', - 'true_coin_out', - 'current_hopper_level', - 'credit_amount_of_all_bills_accepted', - 'coin_amount_accepted_from_external_coin_acceptor', - 'country_code', - 'bill_denomination', - 'meter_for_accepted_bills', - 'number_bills_in_stacker', - 'credits_SAS_in_stacker', - 'machine_ID', - 'sequence_number', - 'validation_type', - 'index_number', - 'date_validation_operation', - 'time_validation_operation', - 'validation_number', - 'ticket_amount', - 'ticket_number', - 'validation_system_ID', - 'expiration_date_printed_on_ticket', - 'pool_id', - 'current_hopper_lenght', - 'current_hopper_ststus', - 'current_hopper_percent_full', - 'current_hopper_level', - 'bin_validation_type', - 'total_validations', - 'cumulative_amount', - 'total_number_of_games_impemented', - 'game_n_number', - 'game_n_coin_in_meter', - 'game_n_coin_out_meter', - 'game_n_jackpot_meter', - 'geme_n_games_played_meter', - 'game_n_number_config', - 'game_n_ASCII_game_ID', - 'game_n_ASCII_additional_id', - 'game_n_bin_denomination', - 'game_n_bin_max_bet', - 'game_n_bin_progressive_group', - 'game_n_bin_game_options', - 'game_n_ASCII_paytable_ID', - 'game_n_ASCII_base_percentage', - 'ASCII_SAS_version', - 'ASCII_serial_number', - 'selected_game_number', - 'number_of_enabled_games', - 'enabled_games_numbers', - 'cashout_type', - 'cashout_amount', - 'ticket_status', - 'ticket_amount', - 'parsing_code', - 'validation_data', - 'registration_status', - 'asset_number', - 'registration_key', - 'POS_ID', - 'game_lock_status', - 'avilable_transfers', - 'host_cashout_status', - 'AFT_ststus', - 'max_buffer_index', - 'current_cashable_amount', - 'current_restricted_amount', - 'current_non_restricted_amount', - 'restricted_expiration', - 'restricted_pool_ID', - 'game_number', - 'features_1', - 'features_2', - 'features_3' - - - ),[]) -aft_statement=dict.fromkeys(( - 'registration_status', - 'asset_number', - 'registration_key', - 'POS_ID', - 'transaction_buffer_position', - 'transfer_status', - 'receipt_status', - 'transfer_type', - 'cashable_amount', - 'restricted_amount', - 'nonrestricted_amount', - 'transfer_flags', - 'asset_number', - 'transaction_ID_lenght', - 'transaction_ID', - 'transaction_date', - 'transaction_time', - 'expiration', - 'pool_ID', - 'cumulative_casable_amount_meter_size', - 'cumulative_casable_amount_meter', - 'cumulative_restricted_amount_meter_size', - 'cumulative_restricted_amount_meter', - 'cumulative_nonrestricted_amount_meter_size', - 'cumulative_nonrestricted_amount_meter', - 'asset_number', - 'game_lock_status', - 'avilable_transfers', - 'host_cashout_status', - 'AFT_status', - 'max_buffer_index', - 'current_cashable_amount', - 'current_restricted_amount', - 'current_non_restricted_amount', - 'restricted_expiration', - 'restricted_pool_ID', - - - - - ),[]) -tito_statement=dict.fromkeys(( - 'asset_number', - 'status_bits', - 'cashable_ticket_reciept_exp', - 'restricted_ticket_exp', - 'cashout_ticket_number', - 'cashout_amount_in_cents', - 'machine_ID', - 'sequence_number' - 'cashout_type', - 'cashout_amount', - 'validation_type', - 'index_number', - 'date_validation_operation', - 'time_validation_operation', - 'validation_number', - 'ticket_amount', - 'ticket_number', - 'validation_system_ID', - 'expiration_date_printed_on_ticket' - 'pool_id' - ),[]) - - -eft_statement=dict.fromkeys(( - 'eft_status', - 'promo_amount', - 'cashable_amount', - 'eft_transfer_counter' - - ),[]) -game_features=dict.fromkeys(( - 'game_number', - 'jackpot_multiplier', - 'AFT_bonus_avards', - 'legacy_bonus_awards', - 'tournament', - 'validation_extensions', - 'validation_style', - 'ticket_redemption' - ),[]) -class sas(object): - adress=1 - - def __init__(self, port): - try: - #print 1 - self.connection=serial.Serial(port=port,baudrate=19200, timeout=2) - except: - print "port error" - return - def start(self): - print 'Connecting SAS...' - while True: - response =self.connection.read(1) - if (response<>''): - self.adress=int(binascii.hexlify(response)) - if self.adress>=1: - print 'adress recognised '+str(self.adress) - break - - #print str(binascii.hexlifyself.adress)) - time.sleep(.5) - - self.gaming_machine_ID() - print meters.get('ASCII_game_ID') - print meters.get('ASCII_additional_ID') - print meters.get('bin_denomination') - print meters.get('bin_max_bet') - print meters.get('bin_progressive_mode') - print meters.get('bin_game_options') - print meters.get('ASCII_paytable_ID') - print meters.get('ASCII_base_percentage') - self.SAS_version_gaming_machine_serial_ID() - print meters.get('ASCII_SAS_version') - print meters.get('ASCII_serial_number') - self.enabled_features() #todo - - # 7e date_time_add - self.AFT_register_gaming_machine(reg_code=0xff) - print aft_statement.get('registration_status') - print aft_statement.get('asset_number') - print aft_statement.get('registration_key') - print aft_statement.get('POS_ID') - - - - - return True - - def __send_command( self, command, no_response=False, timeout=3, crc_need=True): - busy = True - response=b'' - try: - buf_header=[self.adress] - buf_header.extend(command) - buf_count=len(command) - #buf_header[2]=buf_count+2 - if (crc_need==True): - crc=CRC16Kermit().calculate(str(bytearray(buf_header))) - buf_header.extend([((crc>>8)&0xFF),(crc&0xFF)]) - #print buf_header - print buf_header - #print self.connection.portstr - #self.connection.write([0x31, 0x32,0x33,0x34,0x35]) - self.connection.write((buf_header)) - - except Exception as e: - print e - - try: - buffer = [] - self.connection.flushInput() - t=time.time() - while time.time()-tFalse): - break - - if time.time()-t>=timeout: - print "timeout waiting response" - #buffer.append(response) - #print binascii.hexlify(bytearray(response)) - return None - - busy = False - return self.checkResponse(response) - #return None - except Exception as e: - print e - busy = False - return None - - def checkResponse(self, rsp): - if (rsp==''): - print 'not response' - return False - - resp = bytearray(rsp) - #print resp - if (resp[0]<>self.adress): - print "wrong ardess or NACK" - return False - - CRC = binascii.hexlify(resp[-2:]) - - - command = resp[0:-2] - - crc1=crc=CRC16Kermit().calculate(str(bytearray(command))) - - data = resp[1:-2] - - crc1 = hex(crc1).split('x')[-1] - - while len(crc1)<4: - crc1 = "0"+crc1 - - #print crc1 - #print CRC - if(CRC != crc1): - - #print "Wrong response command hash " + str(CRC) - #print "////" + str(hex(crc1).split('x')[-1]) - #print "////" + str(binascii.hexlify(command)) - return False - print binascii.hexlify(data) - return data -## def check_crc(self): -## cmd=[0x01, 0x50, 0x81] -## cmd=bytearray(cmd) -## #print self.sas_CRC([0x01, 0x50, 0x81]) -## #print ('\\'+'\\'.join(hex(e)[1:] for e in cmd)) -## -## print (CRC16Kermit().calculate(str(cmd))) -## return - - def events_poll(self, timeout=1): - event='' - cmd=[0x80+self.adress] +# ser = serial.Serial('/dev/ttyS3','19200', timeout=1) # open first serial port +data_to_sent = [0x01, 0x21, 0x00, 0x00] +# adress=1 +# print "OK" +from multiprocessing import log_to_stderr +import logging +import datetime + +AFT_LOCK_STATUS = {'00': 'Game locked', '40': 'Game lock pending', 'ff': 'Game not locked'} +AFT_REGISTRACION_STATUS = {'00': 'Gaming machine registration ready', '01': 'Gaming machine registered', + '40': 'Gaming machine registration pending', '80': 'Gaming machine not registered'} +AFT_TRANSFER_STATUS = { + '00': 'Full transfer successful', + '01': 'Partial transfer successful Binary codes 010xxxxx indicate transfer pending', + '40': 'Transfer pending (not complete)', + '80': 'Transfer cancelled by host', + '81': 'Transaction ID not unique (same as last successful transfer logged in history)', + '82': 'Not a valid transfer function (unsupported type, amount, index, etc.)', + '83': 'Not a valid transfer amount or expiration (non-BCD, etc.)', + '84': 'Transfer amount exceeds the gaming machine transfer limit', + '85': 'Transfer amount not an even multiple of gaming machine denomination', + '86': 'Gaming machine unable to perform partial transfers to the host', + '87': 'Gaming machine unable to perform transfers at this time (door open, tilt, disabled, cashout in progress, etc.)', + '88': 'Gaming machine not registered (required for debit transfers)', + '89': 'Registration key does not match', + '8A': 'No POS ID (required for debit transfers)', + '8B': 'No won credits available for cashout', + '8C': 'No gaming machine denomination set (unable to perform cents to credits conversion)', + '8D': 'Expiration not valid for transfer to ticket (already expired)', + '8E': 'Transfer to ticket device not available', + '8F': 'Unable to accept transfer due to existing restricted amounts from different pool', + '90': 'Unable to print transaction receipt (receipt device not currently available)', + '91': 'Insufficient data to print transaction receipt (required fields missing)', + '92': 'Transaction receipt not allowed for specified transfer type', + '93': 'Asset number zero or does not match', + '94': 'Gaming machine not locked (transfer specified lock required)', + '95': 'Transaction ID not valid', + '9F': 'Unexpected error Binary codes 110xxxxx indicate incompatible or unsupported poll', + 'c0': 'Not compatible with current transfer in progress', + 'c1': 'Unsupported transfer code Binary codes 111xxxxx indicate no transfer information available', + 'ff': 'No transfer information available', + # ' ': 'No response', +} + +AFT_RECEIPT_STATUS = { + '00': 'Receipt printed', + '20': 'Receipt printing in progress (not complete)', + '40': 'Receipt pending (not complete)', + 'ff': 'No receipt requested or receipt not printed', +} + +AFT_TRANSFER_TYPE = { + '00': 'Transfer in-house amount from host to gaming machine', + '10': 'Transfer bonus coin out win amount from host to gaming machine', + '11': 'Transfer bonus jackpot win amount from host to gaming machine (force attendant pay lockup)', + '20': 'Transfer in-house amount from host to ticket (only one amount type allowed per transfer)', + '40': 'Transfer debit amount from host to gaming machine', + '60': 'Transfer debit amount from host to ticket', + '80': 'Transfer in-house amount from gaming machine to host', + '90': 'Transfer win amount (in-house) from gaming machine to host', + +} +DENOMINATION = { + '00': None, + '01': 0.01, + '17': 0.02, + '02': 0.05, + '03': 0.10, + '04': 0.25, + '05': 0.50, + '06': 1.00, + '07': 5.00, + '08': 10.00, + '09': 20.00, +} + +GPOLL = { + '00': 'No activity', + '01': 'No Response', + '11': 'Slot door was opened', + '12': 'Slot door was closed', + '13': 'Drop door was opened', + '14': 'Drop door was closed', + '15': 'Card cage was opened', + '16': 'Card cage was closed', + '17': 'AC power was applied to gaming machine', + '18': 'AC power was lost from gaming machine', + '19': 'Cashbox door was opened', + '1a': 'Cashbox door was closed', + '1b': 'Cashbox was removed', + '1c': 'Cashbox was installed', + '1d': 'Belly door was opened', + '1e': 'Belly door was closed', + '1f': 'No activity and waiting for player input (obsolete)', + '20': '''General tilt (Use this tilt when other exception tilt codes do not apply or + when the tilt condition cannot be determined.)''', + '21': 'Coin in tilt', + '22': 'Coin out tilt', + '23': 'Hopper empty detected', + '24': 'Extra coin paid', + '25': 'Diverter malfunction (controls coins to drop or hopper)', + '27': 'Cashbox full detected', + '28': 'Bill jam', + '29': 'Bill acceptor hardware failure', + '2a': 'Reverse bill detected', + '2b': 'Bill rejected', + '2c': 'Counterfeit bill detected', + '2d': 'Reverse coin in detected', + '2e': 'Cashbox near full detected', + '31': 'CMOS RAM error (data recovered from EEPROM)', + '32': 'CMOS RAM error (no data recovered from EEPROM)', + '33': 'CMOS RAM error (bad device)', + '34': 'EEPROM error (data error)', + '35': 'EEPROM error (bad device)', + '36': 'EPROM error (different checksum – version changed)', + '37': 'EPROM error (bad checksum compare)', + '38': 'Partitioned EPROM error (checksum – version changed)', + '39': 'Partitioned EPROM error (bad checksum compare)', + '3a': 'Memory error reset (operator used self test switch)', + '3b': 'Low backup battery detected', + '3c': '''Operator changed options (This is sent whenever the operator changes + configuration options. This includes, but is not limited to, denomination, + gaming machine address, or any option that affects the response to long polls + 1F, 53, 54, 56, A0, B2, B3, B4, or B5.)''', + '3d': 'A cash out ticket has been printed', + '3e': 'A handpay has been validated', + '3f': 'Validation ID not configured', + '40': 'Reel Tilt (Which reel is not specified.)', + '41': 'Reel 1 tilt', + '42': 'Reel 2 tilt', + '43': 'Reel 3 tilt', + '44': 'Reel 4 tilt', + '45': 'Reel 5 tilt', + '46': 'Reel mechanism disconnected', + '47': '$1.00 bill accepted (non-RTE only)', + '48': '$5.00 bill accepted (non-RTE only)', + '49': '$10.00 bill accepted (non-RTE only)', + '4a': '$20.00 bill accepted (non-RTE only)', + '4b': '$50.00 bill accepted (non-RTE only)', + '4c': '$100.00 bill accepted (non-RTE only)', + '4d': '$2.00 bill accepted (non-RTE only)', + '4e': '$500.00 bill accepted (non-RTE only)', + '4f': 'Bill accepted (In non-RTE mode, use this exception for all bills without a specific exception. In RTE mode, use for all bill denominations.)', + '50': '$200.00 bill accepted (non-RTE only)', + '51': 'Handpay is pending (Progressive, non-progressive or cancelled credits)', + '52': 'Handpay was reset (Jackpot reset switch activated)', + '53': 'No progressive information has been received for 5 seconds', + '54': 'Progressive win (cashout device/credit paid)', + '55': 'Player has cancelled the handpay request', + '56': 'SAS progressive level hit', + '57': 'System validation request', + '60': 'Printer communication error', + '61': 'Printer paper out error', + '66': 'Cash out button pressed', + '67': 'Ticket has been inserted', + '68': 'Ticket transfer complete', + '69': 'AFT transfer complete', + '6a': 'AFT request for host cashout', + '6b': 'AFT request for host to cash out win', + '6c': 'AFT request to register', + '6d': 'AFT registration acknowledged', + '6e': 'AFT registration cancelled', + '6f': 'Game locked', + '70': 'Exception buffer overflow', + '71': 'Change lamp on', + '72': 'Change lamp off', + '74': 'Printer paper low', + '75': 'Printer power off', + '76': 'Printer power on', + '77': 'Replace printer ribbon', + '78': 'Printer carriage jammed', + '79': 'Coin in lockout malfunction (coin accepted while coin mech disabled)', + '7a': 'Gaming machine soft (lifetime-to-date) meters reset to zero', + '7b': 'Bill validator (period) totals have been reset by an attendant/operator', + '7c': 'A legacy bonus pay awarded and/or a multiplied jackpot occurred', + '7e': 'Game has started', + '7f': 'Game has ended', + '80': 'Hopper full detected', + '81': 'Hopper level low detected', + '82': 'Display meters or attendant menu has been entered', + '83': 'Display meters or attendant menu has been exited', + '84': 'Self test or operator menu has been entered', + '85': 'Self test or operator menu has been exited', + '86': 'Gaming machine is out of service (by attendant)', + '87': 'Player has requested draw cards (only send when in RTE mode)', + '88': 'Reel N has stopped (only send when in RTE mode)', + '89': '''Coin/credit wagered (only send when in RTE mode, and only send if the + configured max bet is 10 or less)''', + '8a': 'Game recall entry has been displayed', + '8b': 'Card held/not held (only send when in RTE mode)', + '8c': 'Game selected', + '8e': 'Component list changed', + '8f': 'Authentication complete', + '98': 'Power off card cage access', + '99': 'Power off slot door access', + '9a': 'Power off cashbox door access', + '9b': 'Power off drop door access' +} +meters = dict.fromkeys(('total_cancelled_credits_meter', + 'total_in_meter', + 'total_out_meter', + 'total_in_meter', + 'total_jackpot_meter', + 'games_played_meter', + 'games_won_meter', + 'games_lost_meter', + 'games_last_power_up', + 'games_last_slot_door_close', + 'slot_door_opened_meter', + 'power_reset_meter', + 's1_bills_accepted_meter', + 's5_bills_accepted_meter', + 's10_bills_accepted_meter', + 's20_bills_accepted_meter', + 's50_bills_accepted_meter', + 's100_bills_accepted_meter', + 's500_bills_accepted_meter', + 's1000_bills_accepted_meter', + 's200_bills_accepted_meter', + 's25_bills_accepted_meter', + 's2000_bills_accepted_meter', + 's2500_bills_accepted_meter', + 's5000_bills_accepted_meter', + 's10000_bills_accepted_meter', + 's20000_bills_accepted_meter', + 's25000_bills_accepted_meter', + 's50000_bills_accepted_meter', + 's100000_bills_accepted_meter', + 's250_bills_accepted_meter', + 'cashout_ticket_number', + 'cashout_amount_in_cents', + 'ASCII_game_ID', + 'ASCII_additional_ID', + 'bin_denomination', + 'bin_max_bet', + 'bin_progressive_mode', + 'bin_game_options', + 'ASCII_paytable_ID', + 'ASCII_base_percentage', + 'bill_meter_in_dollars', + 'ROM_signature', + 'current_credits', + 'bin_level', + 'amount', + 'partial_pay_amount', + 'bin_reset_ID', + 'bill_meter_in_dollars', + 'true_coin_in', + 'true_coin_out', + 'current_hopper_level', + 'credit_amount_of_all_bills_accepted', + 'coin_amount_accepted_from_external_coin_acceptor', + 'country_code', + 'bill_denomination', + 'meter_for_accepted_bills', + 'number_bills_in_stacker', + 'credits_SAS_in_stacker', + 'machine_ID', + 'sequence_number', + 'validation_type', + 'index_number', + 'date_validation_operation', + 'time_validation_operation', + 'validation_number', + 'ticket_amount', + 'ticket_number', + 'validation_system_ID', + 'expiration_date_printed_on_ticket', + 'pool_id', + 'current_hopper_lenght', + 'current_hopper_ststus', + 'current_hopper_percent_full', + 'current_hopper_level', + 'bin_validation_type', + 'total_validations', + 'cumulative_amount', + 'total_number_of_games_impemented', + 'game_n_number', + 'game_n_coin_in_meter', + 'game_n_coin_out_meter', + 'game_n_jackpot_meter', + 'geme_n_games_played_meter', + 'game_n_number_config', + 'game_n_ASCII_game_ID', + 'game_n_ASCII_additional_id', + 'game_n_bin_denomination', + 'game_n_bin_max_bet', + 'game_n_bin_progressive_group', + 'game_n_bin_game_options', + 'game_n_ASCII_paytable_ID', + 'game_n_ASCII_base_percentage', + 'ASCII_SAS_version', + 'ASCII_serial_number', + 'selected_game_number', + 'number_of_enabled_games', + 'enabled_games_numbers', + 'cashout_type', + 'cashout_amount', + 'ticket_status', + 'ticket_amount', + 'parsing_code', + 'validation_data', + 'registration_status', + 'asset_number', + 'registration_key', + 'POS_ID', + 'game_lock_status', + 'avilable_transfers', + 'host_cashout_status', + 'AFT_ststus', + 'max_buffer_index', + 'current_cashable_amount', + 'current_restricted_amount', + 'current_non_restricted_amount', + 'restricted_expiration', + 'restricted_pool_ID', + 'game_number', + 'features_1', + 'features_2', + 'features_3' + + ), []) +aft_statement = dict.fromkeys(( + 'registration_status', + 'asset_number', + 'registration_key', + 'POS_ID', + 'transaction_buffer_position', + 'transfer_status', + 'receipt_status', + 'transfer_type', + 'cashable_amount', + 'restricted_amount', + 'nonrestricted_amount', + 'transfer_flags', + 'asset_number', + 'transaction_ID_lenght', + 'transaction_ID', + 'transaction_date', + 'transaction_time', + 'expiration', + 'pool_ID', + 'cumulative_casable_amount_meter_size', + 'cumulative_casable_amount_meter', + 'cumulative_restricted_amount_meter_size', + 'cumulative_restricted_amount_meter', + 'cumulative_nonrestricted_amount_meter_size', + 'cumulative_nonrestricted_amount_meter', + 'asset_number', + 'game_lock_status', + 'avilable_transfers', + 'host_cashout_status', + 'AFT_status', + 'max_buffer_index', + 'current_cashable_amount', + 'current_restricted_amount', + 'current_non_restricted_amount', + 'restricted_expiration', + 'restricted_pool_ID', + +), []) +tito_statement = dict.fromkeys(( + 'asset_number', + 'status_bits', + 'cashable_ticket_reciept_exp', + 'restricted_ticket_exp', + 'cashout_ticket_number', + 'cashout_amount_in_cents', + 'machine_ID', + 'sequence_number' + 'cashout_type', + 'cashout_amount', + 'validation_type', + 'index_number', + 'date_validation_operation', + 'time_validation_operation', + 'validation_number', + 'ticket_amount', + 'ticket_number', + 'validation_system_ID', + 'expiration_date_printed_on_ticket' + 'pool_id' +), []) + +eft_statement = dict.fromkeys(( + 'eft_status', + 'promo_amount', + 'cashable_amount', + 'eft_transfer_counter' + +), []) +game_features = dict.fromkeys(( + 'game_number', + 'jackpot_multiplier', + 'AFT_bonus_avards', + 'legacy_bonus_awards', + 'tournament', + 'validation_extensions', + 'validation_style', + 'ticket_redemption' +), []) + + +class BadCRC(Exception): + pass + + +class AFTBadAmount(Exception): + pass + + +class BadTransactionID(Exception): + pass + + +class NoSasConnection(Exception): + pass + + +class SASOpenError(Exception): + pass + + +class EMGGpollBadResponse(Exception): + pass + + +class Sas(object): + adress = 1 + mashin_n = '01' + denom = 0.01 + asset_number = '01000000' + reg_key = '0000000000000000000000000000000000000000' + POS_ID = 'B374A402' + transaction = None + my_key = '44' + + def __init__(self, port, timeout=2, log=None): + if log == None: + self.log = log_to_stderr() + self.log.setLevel(logging.INFO) + else: + self.log = log + while 1: + try: + # print 1 + self.connection = serial.Serial(port=port, baudrate=19200, timeout=timeout) + self.close() + self.timeout = timeout + self.log.info('SAS Port OK!') + break + except: + self.log.critical("SAS Port error") + time.sleep(10) + return + + def is_open(self): + return self.connection.isOpen() + + def start(self): + self.log.info('Connecting SAS...') + while True: + if self.is_open() == False: + # self.log.error('Port not open') try: - self.connection.write(cmd) - t=time.time() - while time.time()-t ''): + self.adress = int(binascii.hexlify(response)) + if self.adress >= 1: + self.mashin_n = response.encode('HEX') + self.log.info('adress recognised ' + str(self.adress)) + break else: - return "False" - return - def startup(self, timeout=0.2): - #02 - cmd=[self.adress, 0x02] - try: - self.connection.write(cmd) - t=time.time() - while time.time()-t> 4) ^ (q * 0o010201) + q = (seed ^ (int(c, 16) >> 4)) & 0o17 + seed = (seed >> 4) ^ (q * 0o010201) + c = '' + data = hex(seed) + tmp = [] + if len(data) == 5: + data = data[0:2] + '0' + data[2:] + elif len(data) == 4: + data = data[0:2] + '00' + data[2:] + elif len(data) == 3: + data = data[0:2] + '000' + data[2:] + elif len(data) == 2: + data = data[0:2] + '0000' + if chk == False: + data = data[4:] + data[2:-2] + # pass + else: + data = data[4:] + data[2:-2] + if data == crc: + return True + else: + raise BadCRC, response + return data + + def __send_command(self, command, no_response=False, timeout=None, crc_need=True): + if timeout == None: + timeout = self.timeout + 1 + busy = True + response = b'' + try: + buf_header = [self.adress] + self._conf_port() + self.connection.write(("82" + self.mashin_n).decode("hex")) + self.close() + self.connection.parity = serial.PARITY_SPACE + self.open() + + buf_header.extend(command) + buf_count = len(command) + # buf_header[2]=buf_count+2 + if (crc_need == True): + crc = CRC16Kermit().calculate(str(bytearray(buf_header))) + buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) + self.log.debug(buf_header) + # cmd =self.change_cmd(buf_header[1:]) + # cmd = cmd.encode('hex'), 'my command' + # print self.connection.portstr + # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) + self.connection.write((buf_header[1:])) + + except Exception as e: + self.log.error(e, exc_info=True) + + try: + buffer = [] + # self.connection.flushInput() + + t = time.time() + while time.time() - t < timeout: + response += self.connection.read() + if no_response == True: + return int(binascii.hexlify(response)) + elif (self.checkResponse(response) <> False): + break + + if time.time() - t >= timeout: + self.log.warning("sas timeout waiting response") + # buffer.append(response) + # print binascii.hexlify(bytearray(response)) + return None - except Exception as e: - print e - return None - return event - - def sound_off(self): - #03 - if (self.__send_command([0x03],True, crc_need=True)[0]==0x80+self.adress): - return "True" - else: - return "False" - return - def sound_on(self): - #04 - if (self.__send_command([0x04],True, crc_need=True)[0]==0x80+self.adress): - return "True" - else: - return "False" - return - def reel_spin_game_sounds_disabled(self): - #05 - if (self.__send_command([0x05],True, crc_need=True)[0]==0x80+self.adress): - return "True" - else: - return "False" - return - def enable_bill_acceptor(self): - #06 - if (self.__send_command([0x06],True, crc_need=True)[0]==0x80+self.adress): - return "True" - else: - return "False" - return - def disable_bill_acceptor(self): - #07 - if (self.__send_command([0x07],True, crc_need=True)[0]==0x80+self.adress): - return "True" - else: - return "False" - return - def configure_bill_denom(self, bill_denom=[0xFF,0xFF,0xFF], action_flag=[0xff]): - #08 - cmd=[0x08,0x00] - ##print str(hex(bill_denom)) - s='00ffffff' - #print bytes.fromhex(((s))) - cmd.extend(bill_denom) - cmd.extend(action_flag) - print cmd - if (self.__send_command(cmd,True, crc_need=True)[0]==0x80+self.adress): - return "True" - else: - return "False" - return - def en_dis_game(self, game_number=[1], en_dis=[1]): - #09 - cmd=[0x09] - cmd.extend(bytearray(game_number)) - cmd.extend(bytearray(en_dis)) - print cmd - if (self.__send_command(cmd,True, crc_need=True)[0]==0x80+self.adress): - return "True" - else: - return "False" - - return - def enter_maintenance_mode(self): - #0A - return - def exit_maintanance_mode(self): - #0B - return - def en_dis_rt_event_reporting(self): - #0E - return - def send_meters_10_15(self): - #0F - cmd=[0x0f] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - meters['total_cancelled_credits_meter']=int((binascii.hexlify(bytearray(data[1:5])))) - meters['total_in_meter']=int(binascii.hexlify(bytearray(data[5:9]))) - meters['total_out_meter']=int(binascii.hexlify(bytearray(data[9:13]))) - meters['total_droup_meter']=int(binascii.hexlify(bytearray(data[13:17]))) - meters['total_jackpot_meter']=int(binascii.hexlify(bytearray(data[17:21]))) - meters['games_played_meter']=int(binascii.hexlify(bytearray(data[21:25]))) - return data - return '' - def total_cancelled_credits(self): - #10 - cmd=[0x10] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - meters['total_cancelled_credits_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - return data - return '' - def total_bet_meter(self): - #11 - cmd=[0x11] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['total_bet_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def total_win_meter(self): - #12 - cmd=[0x12] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['total_win_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def total_in_meter(self): - #13 - cmd=[0x13] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['total_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def total_jackpot_meter(self): - #14 - cmd=[0x14] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['total_jackpot_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def games_played_meter(self): - #15 - cmd=[0x15] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['games_played_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def games_won_meter(self): - #16 - cmd=[0x16] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['games_won_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def games_lost_meter(self): - #17 - cmd=[0x17] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['games_lost_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def games_powerup_door_opened(self): - #18 - cmd=[0x18] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['games_last_power_up']=int(binascii.hexlify(bytearray(data[1:3]))) - meters['games_last_slot_door_close']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def meters_11_15(self): - #19 - cmd=[0x19] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - meters['total_bet_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - meters['total_win_meter']=int(binascii.hexlify(bytearray(data[5:9]))) - meters['total_in_meter']=int(binascii.hexlify(bytearray(data[9:13]))) - meters['total_jackpot_meter']=int(binascii.hexlify(bytearray(data[13:17]))) - meters['games_played_meter']=int(binascii.hexlify(bytearray(data[17:21]))) - return data - return '' - def current_credits(self): - #1A - cmd=[0x1A] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - meters['current_credits']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def handpay_info(self): - #1B - cmd=[0x1B] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['bin_progressive_group']=int(binascii.hexlify(bytearray(data[1:2]))) - meters['bin_level']=int(binascii.hexlify(bytearray(data[2:3]))) - meters['amount']=int(binascii.hexlify(bytearray(data[3:8]))) - meters['bin_reset_ID']=int(binascii.hexlify(bytearray(data[8:]))) - return data - return '' - def meters(self): - #1C - cmd=[0x1C] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - meters['total_bet_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - meters['total_win_meter']=int(binascii.hexlify(bytearray(data[5:9]))) - meters['total_in_meter']=int(binascii.hexlify(bytearray(data[9:13]))) - meters['total_jackpot_meter']=int(binascii.hexlify(bytearray(data[13:17]))) - meters['games_played_meter']=int(binascii.hexlify(bytearray(data[17:21]))) - meters['games_won_meter']=int(binascii.hexlify(bytearray(data[21:25]))) - meters['slot_door_opened_meter']=int(binascii.hexlify(bytearray(data[25:29]))) - meters['power_reset_meter']=int(binascii.hexlify(bytearray(data[29:33]))) - - return data - return '' - def total_bill_meters(self): - #1E - cmd=[0x1E] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - meters['s1_bills_accepted_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - meters['s5_bills_accepted_meter']=int(binascii.hexlify(bytearray(data[5:9]))) - meters['s10_bills_accepted_meter']=int(binascii.hexlify(bytearray(data[9:13]))) - meters['s20_bills_accepted_meter']=int(binascii.hexlify(bytearray(data[13:17]))) - meters['s50_bills_accepted_meter']=int(binascii.hexlify(bytearray(data[17:21]))) - meters['s100_bills_accepted_meter']=int(binascii.hexlify(bytearray(data[21:25]))) - - return data - return '' - def gaming_machine_ID(self): - #1F - cmd=[0x1F] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['ASCII_game_ID']=(((data[1:3]))) - meters['ASCII_additional_ID']=(((data[3:6]))) - meters['bin_denomination']=int(binascii.hexlify(bytearray(data[6]))) - meters['bin_max_bet']=(binascii.hexlify(bytearray(data[7:8]))) - meters['bin_progressive_mode']=int(binascii.hexlify(bytearray(data[8:9]))) - meters['bin_game_options']=(binascii.hexlify(bytearray(data[9:11]))) - meters['ASCII_paytable_ID']=(((data[11:17]))) - meters['ASCII_base_percentage']=(((data[17:21]))) - - return data - return '' - def total_dollar_value_of_bills_meter(self): - #20 - - cmd=[0x20] - data=self.__send_command(cmd,True, crc_need=False) - - if(data<>''): - - meters['bill_meter_in_dollars']=int(binascii.hexlify(bytearray(data[1:]))) - - return data - return '' - def ROM_signature_verification(self): - #21 - - cmd=[0x21, 0x00, 0x00] - data=self.__send_command(cmd,True, crc_need=True) - print data - if(data<>None): - - meters['ROM_signature']= int(binascii.hexlify(bytearray(data[1:3]))) - print (str(meters.get('ROM_signature'))) - return data - return False - - def eft_button_pressed(self, state=0): - #24 - - cmd=[0x24, 0x03] - cmd.append(state) - - data=self.__send_command(cmd,True, crc_need=True) - print data - if(data<>None): - - return data - return '' - - def true_coin_in(self): - #2A - cmd=[0x2A] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['true_coin_in']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def true_coin_out(self): - #2B - cmd=[0x2B] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['true_coin_out']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def curr_hopper_level(self): - #2C - cmd=[0x2C] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['current_hopper_level']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def total_hand_paid_cancelled_credit(self): - #2D - return - def delay_game(self, delay=0x01): - #2E - cmd=[0x2E] -## if (delay[0]<=0xff): -## cmd.extend([0x00]) - cmd.append(delay) - - - #print cmd - if (self.__send_command(cmd,True, crc_need=True)[0]==self.adress): - return "True" - else: - return "False" - - return - def selected_meters_for_game(self): - #2F - return - def send_1_bills_in_meters(self): - #31 - cmd=[0x31] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s1_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_2_bills_in_meters(self): - #32 - cmd=[0x32] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s2_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_5_bills_in_meters(self): - #33 - cmd=[0x33] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s5_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_10_bills_in_meters(self): - #34 - cmd=[0x34] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s10_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_20_bills_in_meters(self): - #35 - cmd=[0x35] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s20_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_50_bills_in_meters(self): - #36 - cmd=[0x36] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s50_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_100_bills_in_meters(self): - #37 - cmd=[0x37] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s100_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_500_bills_in_meters(self): - #38 - cmd=[0x38] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s500_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_1000_bills_in_meters(self): - #39 - cmd=[0x39] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s1000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_200_bills_in_meters(self): - #3A - cmd=[0x3a] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s200_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_25_bills_in_meters(self): - #3B - cmd=[0x3B] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s25_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_2000_bills_in_meters(self): - #3C - cmd=[0x3C] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s2000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def cash_out_ticket_info(self): - #3D - cmd=[0x3D] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - tito_statement['cashout_ticket_number']=int(binascii.hexlify(bytearray(data[1:3]))) - tito_statement['cashout_amount_in_cents']=int(binascii.hexlify(bytearray(data[3:]))) - - return data - return '' - def send_2500_bills_in_meters(self): - #3E - cmd=[0x3E] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s2500_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_5000_bills_in_meters(self): - #3F - cmd=[0x3F] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s5000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_10000_bills_in_meters(self): - #40 - cmd=[0x40] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s10000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_20000_bills_in_meters(self): - #41 - cmd=[0x41] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s20000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_25000_bills_in_meters(self): - #42 - cmd=[0x42] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s25000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_50000_bills_in_meters(self): - #43 - cmd=[0x43] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s50000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_100000_bills_in_meters(self): - #44 - cmd=[0x44] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s100000_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def send_250_bills_in_meters(self): - #45 - cmd=[0x45] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['s250_bills_in_meter']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def credit_amount_of_all_bills_accepted(self): - #46 - - cmd=[0x46] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>''): - - meters['credit_amount_of_all_bills_accepted']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def coin_amount_accepted_from_external_coin_acceptor(self): - #47 - cmd=[0x47] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - - meters['coin_amount_accepted_from_external_coin_acceptor']=int(binascii.hexlify(bytearray(data[1:5]))) - - return data - return '' - def last_accepted_bill_info(self): - #48 - cmd=[0x48] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['country_code']=int(binascii.hexlify(bytearray(data[1:2]))) - meters['bill_denomination']=int(binascii.hexlify(bytearray(data[2:3]))) - meters['meter_for_accepted_bills']=int(binascii.hexlify(bytearray(data[3:6]))) - return data - return '' - def number_of_bills_currently_in_stacker(self): - #49 - cmd=[0x49] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['number_bills_in_stacker']=int(binascii.hexlify(bytearray(data[1:5]))) - return data - return '' - def total_credit_amount_of_all_bills_in_stacker(self): - #4A - cmd=[0x49] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['credits_SAS_in_stacker']=int(binascii.hexlify(bytearray(data[1:5]))) - return data - return '' - def set_secure_enhanced_validation_ID(self, MachineID=[0x01,0x01,0x01], seq_num=[0x00,0x00,0x01]): - #4C - cmd=[0x4C] - - cmd.extend(MachineID) - cmd.extend(seq_num) - cmd=bytearray(cmd) - #print str(binascii.hexlify((cmd))) - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - tito_statement['machine_ID']=int(binascii.hexlify(bytearray(data[1:4]))) - tito_statement['sequence_number']=int(binascii.hexlify(bytearray(data[4:8]))) - - return data - return '' - def enhanced_validation_information(self, curr_validation_info=0): - #4D - - cmd=[0x4D] - - #cmd.append(transfer_code) - #cmd=cmd.extend(0) - #rint str(binascii.hexlify(bytearray(cmd))) - cmd.append((curr_validation_info)) - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - tito_statement['validation_type']=int(binascii.hexlify(bytearray(data[1:2]))) - tito_statement['index_number']=int(binascii.hexlify(bytearray(data[2:3]))) - tito_statement['date_validation_operation']=str(binascii.hexlify(bytearray(data[3:7]))) - tito_statement['time_validation_operation']=str(binascii.hexlify(bytearray(data[7:10]))) - tito_statement['validation_number']=str(binascii.hexlify(bytearray(data[10:18]))) - tito_statement['ticket_amount']=int(binascii.hexlify(bytearray(data[18:23]))) - tito_statement['ticket_number']=int(binascii.hexlify(bytearray(data[23:25]))) - tito_statement['validation_system_ID']=int(binascii.hexlify(bytearray(data[25:26]))) - tito_statement['expiration_date_printed_on_ticket']=str(binascii.hexlify(bytearray(data[26:30]))) - tito_statement['pool_id']=int(binascii.hexlify(bytearray(data[30:32]))) - - - return data - return '' - def current_hopper_status(self): - #4F - - cmd=[0x4F] - - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['current_hopper_lenght']=int(binascii.hexlify(bytearray(data[1:2]))) - meters['current_hopper_ststus']=int(binascii.hexlify(bytearray(data[2:3]))) - meters['current_hopper_percent_full']=int(binascii.hexlify(bytearray(data[3:4]))) - meters['current_hopper_level']=int(binascii.hexlify(bytearray(data[4:]))) - return data - return '' - def validation_meters(self, type_of_validation=0x00): - #50 - - cmd=[0x50] - cmd.append(type_of_validation) - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - meters['bin_validation_type']=int(binascii.hexlify(bytearray(data[1]))) - meters['total_validations']=int(binascii.hexlify(bytearray(data[2:6]))) - meters['cumulative_amount']=str(binascii.hexlify(bytearray(data[6:]))) - - return data - return '' - def total_number_of_games_impimented(self): - #51 - cmd=[0x51] - cmd.extend(type_of_validation) - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['total_number_of_games_impemented']=str(binascii.hexlify(bytearray(data[1:]))) - - - return data - return '' - def game_meters(self, n=1): - #52 - - cmd=[0x52] - cmd.extend([(n&0xFF), ((n>>8)&0xFF)]) - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - meters['game_n_number']=str(binascii.hexlify(bytearray(data[1:3]))) - meters['game_n_coin_in_meter']=str(binascii.hexlify(bytearray(data[3:7]))) - meters['game_n_coin_out_meter']=str(binascii.hexlify(bytearray(data[7:11]))) - meters['game_n_jackpot_meter']=str(binascii.hexlify(bytearray(data[11:15]))) - meters['geme_n_games_played_meter']=str(binascii.hexlify(bytearray(data[15:]))) - - - return data - return '' - def game_configuration(self, n=1): - #53 - - cmd=[0x53] - cmd.extend([(n&0xFF), ((n>>8)&0xFF)]) - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - meters['game_n_number_config']=int(binascii.hexlify(bytearray(data[1:3]))) - meters['game_n_ASCII_game_ID']=str(binascii.hexlify(bytearray(data[3:5]))) - meters['game_n_ASCII_additional_id']=str(binascii.hexlify(bytearray(data[5:7]))) - meters['game_n_bin_denomination']=str(binascii.hexlify(bytearray(data[7]))) - meters['game_n_bin_progressive_group']=str(binascii.hexlify(bytearray(data[8]))) - meters['game_n_bin_game_options']=str(binascii.hexlify(bytearray(data[9:11]))) - meters['game_n_ASCII_paytable_ID']=str(binascii.hexlify(bytearray(data[11:17]))) - meters['game_n_ASCII_base_percentage']=str(binascii.hexlify(bytearray(data[17:]))) - - - return data - return '' - def SAS_version_gaming_machine_serial_ID(self): - #54 - cmd=[0x54] - - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['ASCII_SAS_version']=data[2:5] - meters['ASCII_serial_number']=data[5:] - return data - return '' - def selected_game_number(self): - #55 - cmd=[0x55] - - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['selected_game_number']=int(binascii.hexlify(bytearray(data[1:]))) - return data - return '' - def enabled_game_numbers(self): - #56 - - cmd=[0x56] - - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['number_of_enabled_games']=int(binascii.hexlify(bytearray(data[2]))) - meters['enabled_games_numbers']=int(binascii.hexlify(bytearray(data[3:]))) - - return data - return '' - def pending_cashout_info(self): - #57 - - cmd=[0x57] - - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - tito_statement['cashout_type']=int(binascii.hexlify(bytearray(data[1:2]))) - tito_statement['cashout_amount']=str(binascii.hexlify(bytearray(data[2:]))) - - return data - return '' - def validation_number(self, validationID=1, valid_number=0): - #58 - - cmd=[0x58] - cmd.append(validationID) - cmd.extend(self.bcd_coder_array( valid_number,8)) - print cmd - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - - return data[1] - return '' - def eft_send_promo_to_machine(self, amount=0, count=1, status=0): - #63 - cmd=[0x63, count, ] - #status 0-init 1-end - cmd.append(status) - cmd.extend(self.bcd_coder_array(amount, 4)) - data=self.__send_command(cmd,True, crc_need=True) - - if(data<>None): - eft_statement['eft_status']=str(binascii.hexlify(bytearray(data[1:]))) - eft_statement['promo_amount']=str(binascii.hexlify(bytearray(data[4:]))) - # eft_statement['eft_transfer_counter']=int(binascii.hexlify(bytearray(data[3:4]))) - - - return data[3] - return '' - def eft_load_cashable_credits(self, amount=0, count=1, status=0): - #69 - cmd=[0x69, count, ] - cmd.append(status) - cmd.extend(self.bcd_coder_array(amount, 4)) - data=self.__send_command(cmd,True, crc_need=True) - - if(data<>None): - meters['eft_status']=str(binascii.hexlify(bytearray(data[1:2]))) - meters['cashable_amount']=str(binascii.hexlify(bytearray(data[2:5]))) - - - return data[3] - return '' - - def eft_avilable_transfers(self): - #6A - cmd=[0x6A] - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - #meters['number_bills_in_stacker']=int(binascii.hexlify(bytearray(data[1:5]))) - return data - return '' - - - def autentification_info(self, action=0, adressing_mode=0, component_name='', auth_method=b'\x00\x00\x00\x00', seed_lenght=0, seed='', offset_lenght=0, offset=''): - #6E - cmd=[0x6E, 0x00] - cmd.append(action) - if action==0: - #cmd.append(action) - cmd[1]=1 - else: - if (action==1 or action==3): - cmd.append(adressing_mode) - cmd.append(len(bytearray(component_name))) - cmd.append (bytearray(component_name)) - cmd[1]=len(bytearray(component_name))+3 - else: - if action==2: - cmd.append(adressing_mode) - cmd.append(len(bytearray(component_name))) - cmd.append (bytearray(component_name)) - cmd.append(auth_metod) - cmd.append(seed_lenght) - cmd.append(bytearray(seed)) - cmd.append(offset_lenght) - cmd.append(bytearray(offset)) - - cmd[1]=len(bytearray(offset))+len(bytearray(seed))+len(bytearray(component_name))+6 - - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - - return data[1] - return '' - def extended_meters_for_game(self, n=1): - #6F - return - def ticket_validation_data(self): - #70 - - cmd=[0x70] - - data=self.__send_command(cmd,True, crc_need=False) - if(data<>None): - meters['ticket_status']=int(binascii.hexlify(bytearray(data[2:3]))) - meters['ticket_amount']=str(binascii.hexlify(bytearray(data[3:8]))) - meters['parsing_code']=int(binascii.hexlify(bytearray(data[8:9]))) - meters['validation_data']=str(binascii.hexlify(bytearray(data[9:]))) - - - return data[1] - return '' - def redeem_ticket(self, transfer_code=0, transfer_amount=0, parsing_code=0, validation_data=0, rescticted_expiration=0, pool_ID=0): - #71 - - cmd=[0x71, 0x00] - cmd.append(transfer_code) - cmd.extend(self.bcd_coder_array(transfer_amount, 5)) - cmd.append(parsing_code) - - cmd.extend(self.bcd_coder_array(validation_data, 8)) - cmd.extend(self.bcd_coder_array(rescticted_expiration, 4)) - cmd.extend(self.bcd_coder_array(pool_ID,2)) - cmd[1]=8+13 - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - meters['ticket_status']=int(binascii.hexlify(bytearray(data[2:3]))) - meters['ticket_amount']=int(binascii.hexlify(bytearray(data[3:8]))) - meters['parsing_code']=int(binascii.hexlify(bytearray(data[8:9]))) - meters['validation_data']=str(binascii.hexlify(bytearray(data[9:]))) - - - return data[1] - return '' - def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfer_type=0x00, cashable_amount=0, restricted_amount=0, non_restricted_amount=0, transfer_flags=0x00, asset_number=b'\x00\x00\x00\x00\x00', registration_key=0, transaction_ID_lenght=0x00, transaction_ID='', expiration=0, pool_ID=0, reciept_data='', lock_timeout=0): - #72 -#sas.AFT_transfer_funds(0, 1, 0x60, 10000, 0, 0, 0b00000000,) - cmd=[0x72, 0x00] - cmd.append(transfer_code) - cmd.append(transaction_index) - cmd.append(transfer_type) - cmd.extend(self.bcd_coder_array(cashable_amount, 5)) - cmd.extend(self.bcd_coder_array(restricted_amount, 5)) - cmd.extend(self.bcd_coder_array(non_restricted_amount, 5)) - cmd.append(transfer_flags) - cmd.extend((asset_number)) - cmd.extend(self.bcd_coder_array(registration_key, 20)) - cmd.append(len(transaction_ID)) - cmd.extend(transaction_ID) - cmd.extend(self.bcd_coder_array(expiration, 4)) - cmd.extend(self.bcd_coder_array(pool_ID, 2)) - - cmd.append(len(reciept_data)) - cmd.extend(reciept_data) - cmd.extend(self.bcd_coder_array(lock_timeout,2)) - - cmd[1]=len(transaction_ID)+len(transaction_ID)+53 - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - aft_statement['transaction_buffer_position']=int(binascii.hexlify(bytearray(data[2:3]))) - aft_statement['transfer_status']=int(binascii.hexlify(bytearray(data[3:4]))) - aft_statement['receipt_status']=int(binascii.hexlify(bytearray(data[4:5]))) - aft_statement['transfer_type']=int(binascii.hexlify(bytearray(data[5:6]))) - aft_statement['cashable_amount']=int(binascii.hexlify(bytearray(data[6:11]))) - aft_statement['restricted_amount']=int(binascii.hexlify(bytearray(data[11:16]))) - aft_statement['nonrestricted_amount']=int(binascii.hexlify(bytearray(data[16:21]))) - aft_statement['transfer_flags']=int(binascii.hexlify(bytearray(data[21:22]))) - aft_statement['asset_number']=(binascii.hexlify(bytearray(data[22:26]))) - aft_statement['transaction_ID_lenght']=int(binascii.hexlify(bytearray(data[26:27]))) - a=int(binascii.hexlify(bytearray(data[26:27]))) - aft_statement['transaction_ID']=str(binascii.hexlify(bytearray(data[27:(27+a+1)]))) - a=27+a+1 - aft_statement['transaction_date']=str(binascii.hexlify(bytearray(data[a:a+5]))) - a=a+5 - aft_statement['transaction_time']=str(binascii.hexlify(bytearray(data[a:a+4]))) - aft_statement['expiration']=str(binascii.hexlify(bytearray(data[a+4:a+9]))) - aft_statement['pool_ID']=str(binascii.hexlify(bytearray(data[a+9:a+11]))) - aft_statement['cumulative_casable_amount_meter_size']=(binascii.hexlify(bytearray(data[a+11:a+12]))) - b=a+int(binascii.hexlify(bytearray(data[a+11:a+12]))) - aft_statement['cumulative_casable_amount_meter']=(binascii.hexlify(bytearray(data[a+12:b+1]))) - aft_statement['cumulative_restricted_amount_meter_size']=(binascii.hexlify(bytearray(data[b+1:b+2]))) - c=b+2+int(binascii.hexlify(bytearray(data[b+1:b+2]))) - aft_statement['cumulative_restricted_amount_meter']=(binascii.hexlify(bytearray(data[b+2:c]))) - aft_statement['cumulative_nonrestricted_amount_meter_size']=(binascii.hexlify(bytearray(data[c:c+1]))) - b=int(binascii.hexlify(bytearray(data[c:c+1])))+c - aft_statement['cumulative_nonrestricted_amount_meter']=(binascii.hexlify(bytearray(data[c+1:]))) - - - return data[1] - return '' - def AFT_register_gaming_machine(self, reg_code=0xff, asset_number=0, reg_key=0, POS_ID=b'\x00\x00\x00\x00'): - #73 - cmd=[0x73, 0x00] - if reg_code==0xFF: - cmd.append(reg_code) - cmd[1]=1 - - else: - cmd.append(reg_code) - cmd.extend(self.bcd_coder_array(asset_number, 4)) - cmd.extend(self.bcd_coder_array(reg_key, 20)) - cmd.extend(self.bcd_coder_array(POS_ID, 4)) - cmd[1]=0x1D - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - print len(data) - aft_statement['registration_status']=(binascii.hexlify((data[2:3]))) - aft_statement['asset_number']=bytearray(data[3:7]) - aft_statement['registration_key']=bytearray(data[7:27]) - aft_statement['POS_ID']=str(binascii.hexlify((data[27:]))) - return data[1] - return '' - def AFT_game_lock_and_status_request(self, lock_code=0x00, transfer_condition=0b00000000, lock_timeout=0): - #74 - cmd=[0x74] - - cmd.append(lock_code) - cmd.append(transfer_condition) - cmd.extend(self.bcd_coder_array(lock_timeout, 2)) - #cmd.addend(0x23) - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - aft_statement['asset_number']=str(binascii.hexlify(bytearray(data[2:6]))) - aft_statement['game_lock_status']=str(binascii.hexlify(bytearray(data[6:7]))) - aft_statement['avilable_transfers']=str(binascii.hexlify(bytearray(data[7:8]))) - aft_statement['host_cashout_status']=str(binascii.hexlify(bytearray(data[8:9]))) - aft_statement['AFT_status']=str(binascii.hexlify(bytearray(data[9:10]))) - aft_statement['max_buffer_index']=str(binascii.hexlify(bytearray(data[10:11]))) - aft_statement['current_cashable_amount']=str(binascii.hexlify(bytearray(data[11:16]))) - aft_statement['current_restricted_amount']=str(binascii.hexlify(bytearray(data[16:21]))) - aft_statement['current_non_restricted_amount']=str(binascii.hexlify(bytearray(data[21:26]))) - aft_statement['restricted_expiration']=str(binascii.hexlify(bytearray(data[26:29]))) - aft_statement['restricted_pool_ID']=str(binascii.hexlify(bytearray(data[29:31]))) - - return data[1] - return '' - def set_AFT_reciept_data(self): - #75 - return - def set_custom_AFT_ticket_data(self): - #76 - return - def exnended_validation_status(self, control_mask=[0,0], status_bits=[0,0], cashable_ticket_reciept_exp=0, restricted_ticket_exp=0): - #7B - cmd=[0x7B, 0x08] - - cmd.extend(control_mask) - cmd.extend(status_bits) - cmd.extend(self.bcd_coder_array(cashable_ticket_reciept_exp, 2)) - cmd.extend(self.bcd_coder_array(restricted_ticket_exp, 2)) - - #cmd.addend(0x23) - - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - aft_statement['asset_number']=str(binascii.hexlify(bytearray(data[2:6]))) - aft_statement['status_bits']=str(binascii.hexlify(bytearray(data[6:8]))) - aft_statement['cashable_ticket_reciept_exp']=str(binascii.hexlify(bytearray(data[8:10]))) - aft_statement['restricted_ticket_exp']=str(binascii.hexlify(bytearray(data[10:]))) - - return data[1] - return '' - def set_extended_ticket_data(self): - #7C - return - def set_ticket_data(self): - #7D - return - def current_date_time(self): - #7E - return - def recieve_date_time(self): - #7F - return - def recieve_progressive_amount(self): - #80 - return - def cumulative_progressive_wins(self): - #83 - return - def progressive_win_amount(self): - #84 - return - def SAS_progressive_win_amount(self): - #85 - return - def recieve_multiple_progressive_levels(self): - #86 - return - def multiple_SAS_progresive_win_amounts(self): - #87 - return - def initiate_legacy_bonus_pay(self): - #8A - return - def initiate_multiplied_jackpot_mode(self): - #8B - return - def enter_exit_tournament_mode(self): - #8C - return - def card_info(self): - #8E - return - def physical_reel_stop_info(self): - #8F - return - def legacy_bonus_win_info(self): - #90 - return - def remote_handpay_reset(self): - #94 - return - def tournament_games_played(self): - #95 - return - def tournament_games_won(self): - #96 - return - def tournament_credits_wagered(self): - #97 - return - def tournament_credits_won(self): - #98 - return - def meters_95_98(self): - #99 - return - def legacy_bonus_meters(self): - #9A - return - def enabled_features(self, game_nimber=0): - #A0 - cmd=[0xA0] - - cmd.extend(self.bcd_coder_array(game_nimber, 2)) - - data=self.__send_command(cmd,True, crc_need=True) - if(data<>None): - aft_statement['game_number']=str(binascii.hexlify(bytearray(data[1:3]))) - aft_statement['features_1']=data[3] - aft_statement['features_2']=data[4] - aft_statement['features_3']=data[5] - - game_features['game_number']=aft_statement.get('game_number') - if (data[3]&0b00000001): - game_features['jackpot_multiplier']=1 - else: - game_features['jackpot_multiplier']=0 - - if (data[3]&0b00000010): - game_features['AFT_bonus_avards']=1 - else: - game_features['AFT_bonus_avards']=0 - if (data[3]&0b00000100): - game_features['legacy_bonus_awards']=1 - else: - game_features['legacy_bonus_awards']=0 - if (data[3]&0b00001000): - game_features['tournament']=1 - else: - game_features['tournament']=0 - if (data[3]&0b00010000): - game_features['validation_extensions']=1 - else: - game_features['validation_extensions']=0 - - game_features['validation_style']=data[3]&0b01100000>>5 - - if (data[3]&0b10000000): - game_features['ticket_redemption']=1 - else: - game_features['ticket_redemption']=0 - - - - - return data[1] - return '' - def cashout_limit(self): - #A4 - return - def enable_jackpot_handpay_reset_method(self): - #A8 - return - def en_dis_game_auto_rebet(self): - #AA - return - def extended_meters_game_alt(self,n=1): - #AF - return - def multi_denom_preamble(self): - #B0 - return - def current_player_denomination(self): - #B1 - return - def enabled_player_denominations(self): - #B2 - return - def token_denomination(self): - #B3 - return - def wager_category_info(self): - #B4 - return - def extended_game_info(self,n=1): - #B5 - return - def event_response_to_long_poll(self): - #FF - return - def bcd_coder_array(self, value=0, lenght=4): - return self.int_to_bcd(value, lenght) - - - def int_to_bcd(self, number=0, lenght=5): - n=0 - m=0 - bval=0 - p=lenght-1 - result=[] - for i in range(0, lenght): - result.extend([0x00]) - while (p>=0): - if (number!=0): - digit=number%10 - number=number/10 - m=m+1 - else: - digit=0 - if (n&1): - bval |= digit<<4 - result[p]=bval - p=p-1 - bval=0 - else: - bval=digit - n=n+1 - return result - - -if __name__ =="__main__": - print "OK" - sas=sas('/dev/ttyS3') - #print ( bcd.bcd_to_int(100)) - #print int(bcd.int_to_bcd(0x1467)) - #a=sas.bcd_coder_array(value=100, lenght=10) - #print ((a)) - print sas.int_to_bcd(1234567890365421,8) - #sas.start() - #sas.ROM_signature_verification() - #sas.total_cancelled_credits() - #sas.send_meters_10_15() - #sas.total_bet_meter() - #sas.total_win_meter() - #sas.total_in_meter() - #sas.total_jackpot_meter() - - - - #sas.SAS_version_gaming_machine_serial_ID() - -## sas.start( ) -## -## -## -## - # print sas.events_poll( timeout=1) -## -## -## -## sas.shutdown( ) -## -## sas.startup( ) -## -## sas.sound_off( ) -## -## sas.sound_on( ) -## -## sas.reel_spin_game_sounds_disabled( ) -## -## sas.enable_bill_acceptor( ) -## -## sas.disable_bill_acceptor( ) -## -## sas.configure_bill_denom( , bill_denom=[0xFF,0xFF,0xFF], action_flag=[0xff]) -## -## sas.en_dis_game( , game_number=[1], en_dis=[1]) -## -## sas.enter_maintenance_mode( ) -## -## sas.exit_maintanance_mode( ) -## -## sas.en_dis_rt_event_reporting( ) -## -## sas.send_meters_10_15( ) -## -## sas.total_cancelled_credits( ) -## -## sas.total_bet_meter( ) -## -## sas.total_win_meter( ) -## -## sas.total_in_meter( ) -## -## sas.total_jackpot_meter( ) -## - - - -# sas.games_played_meter( ) -## - # sas.games_won_meter( ) -## -# sas.games_lost_meter( ) -## - # sas.games_powerup_door_opened( ) -## - # sas.meters_11_15( ) -## - # sas.current_credits( ) -## - # sas.handpay_info( ) -## - # sas.meters( ) -## - # sas.total_bill_meters( ) -## -# sas.gaming_machine_ID( ) -## -# sas.total_dollar_value_of_bills_meter( ) -## - # sas.ROM_signature_verification( ) # test usage? -## - # sas.true_coin_in( ) -## -# sas.true_coin_out( ) -## -# sas.curr_hopper_level( ) -## - # sas.total_hand_paid_cancelled_credit( ) #need for maid -## -# sas.delay_game( delay=1) # need to test -## - # sas.selected_meters_for_game( ) #need to maid -## -# sas.send_1_bills_in_meters( ) -## - # sas.send_2_bills_in_meters( ) -## - # sas.send_5_bills_in_meters( ) -## -# sas.send_10_bills_in_meters( ) -## - # sas.send_20_bills_in_meters( ) -## -# sas.send_50_bills_in_meters( ) -## - # sas.send_100_bills_in_meters( ) -## - # sas.send_500_bills_in_meters( ) -## - # sas.send_1000_bills_in_meters( ) -## - # sas.send_200_bills_in_meters( ) -## -# sas.send_25_bills_in_meters( ) -## - # sas.send_2000_bills_in_meters( ) -## - # sas.cash_out_ticket_info( ) -## -# sas.send_2500_bills_in_meters( ) -## -# sas.send_5000_bills_in_meters( ) -## -# sas.send_10000_bills_in_meters( ) -## -# sas.send_20000_bills_in_meters( ) -## - # sas.send_25000_bills_in_meters( ) -## -# sas.send_50000_bills_in_meters( ) -## -# sas.send_100000_bills_in_meters( ) -## -# sas.send_250_bills_in_meters( ) -## -# sas.credit_amount_of_all_bills_accepted( ) -## - # sas.coin_amount_accepted_from_external_coin_acceptor( ) -## - # sas.last_accepted_bill_info( ) -## -# sas.number_of_bills_currently_in_stacker( ) -## - # sas.total_credit_amount_of_all_bills_in_stacker( ) -## - # sas.set_secure_enhanced_validation_ID( MachineID=b'\x01\x00\x01', seq_num=b'\x00\x01\x00') # read manual -## - # sas.enhanced_validation_information( curr_validation_info=0x00) # asc Lena (append) -## -# sas.current_hopper_status( ) -## - # sas.validation_meters( type_of_validation=0x01) -## -## sas.total_number_of_games_impimented( ) -## -## sas.game_meters( , n=1) -## -## sas.game_configuration( , n=1) -## -## sas.SAS_version_gaming_machine_serial_ID( ) -## -## sas.selected_game_number( ) -## -## sas.enabled_game_numbers( ) -## -## sas.pending_cashout_info( ) -## - # sas.validation_number( 11, 123456) -## -## sas.autentification_info( ) -## -## sas.extended_meters_for_game( , n=1) -## #6F -## -## sas.ticket_validation_data( ) -## #70 -## - # sas.redeem_ticket( ) -## #71 -## - # sas.AFT_transfer_funds(0x00, 0,0x00, 10000, 0, 0, 0, b'\xea\x03\x00\x00', b'\x67\x68\x6a\x68\x62\x76\x79\x64\x6a\x6c\x66\x79\x76\x6d\x6b\x64\x79\x79\x64\x72', transaction_ID_lenght=0x01, transaction_ID='1', expiration=b'\x03\x25\x20\x18', pool_ID=0x1010, reciept_data='fgh', lock_timeout=1) -#transfer_code=0x00, transaction_index=0x00, transfer_type=0x00, cashable_amount=0, restricted_amount=0, non_restricted_amount=0, transfer_flags=0x00, asset_number=b'\x00\x00\x00\x00\x00', registration_key=b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00', transaction_ID_lenght=0x00, transaction_ID='', expiration=b'\x00\x00\x00\x00', pool_ID=0, reciept_data='', lock_timeout=0): - -## #72 -## -## sas.AFT_register_gaming_machine( ) -## #73 -## -## sas.AFT_game_lock_and_status_request( ) -## #74 - # sas.AFT_register_gaming_machine(reg_code=0x01, asset_number=b'\xea\x03\x00\x00', reg_key='ghjhbvydjlfyvmkdyydr', POS_ID=b'\x03\x04\x05\x06') -## -## sas.set_AFT_reciept_data( ) -## #75 -## -## sas.set_custom_AFT_ticket_data( ) -## #76 -## - # sas.exnended_validation_status(control_mask=[0b00000011,0b00000000], status_bits=[0b00000011,0b00000000], cashable_ticket_reciept_exp=0, restricted_ticket_exp=0) - -## #7B -## -## sas.set_extended_ticket_data( ) -## #7C -## -## sas.set_ticket_data( ) -## #7D -## -## sas.current_date_time( ) -## #7E -## -## sas.recieve_date_time( ) -## #7F -## -## sas.recieve_progressive_amount( ) -## #80 -## -## sas.cumulative_progressive_wins( ) -## #83 -## -## sas.progressive_win_amount( ) -## #84 -## -## sas.SAS_progressive_win_amount( ) -## #85 -## -## sas.recieve_multiple_progressive_levels( ) -## #86 -## -## sas.multiple_SAS_progresive_win_amounts( ) -## #87 -## -## sas.initiate_legacy_bonus_pay( ) -## #8A -## -## sas.initiate_multiplied_jackpot_mode( ) -## #8B -## -## sas.enter_exit_tournament_mode( ) -## #8C -## -## sas.card_info( ) -## #8E -## -## sas.physical_reel_stop_info( ) -## #8F -## -## sas.legacy_bonus_win_info( ) -## #90 -## -## sas.remote_handpay_reset( ) -## #94 -## -## sas.tournament_games_played( ) -## #95 -## -## sas.tournament_games_won( ) -## #96 -## -## sas.tournament_credits_wagered( ) -## #97 -## -## sas.tournament_credits_won( ) -## #98 -## -## sas.meters_95_98( ) -## #99 -## -## sas.legacy_bonus_meters( ) -## #9A -## -## sas.enabled_features( ) -## #A0 -## -## sas.cashout_limit( ) -## #A4 -## -## sas.enable_jackpot_handpay_reset_method( ) -## #A8 -## -## sas.en_dis_game_auto_rebet( ) -## #AA -## -## sas.extended_meters_game_alt( ,n=1) -## #AF -## -## sas.multi_denom_preamble( ) -## #B0 -## -## sas.current_player_denomination( ) -## #B1 -## -## sas.enabled_player_denominations( ) -## #B2 -## -## sas.token_denomination( ) -## #B3 -## -## sas.wager_category_info( ) -## #B4 -## -## sas.extended_game_info( ,n=1) -## #B5 -## -## sas.event_response_to_long_poll( ) -## #FF - - - - -## -## for keys, values in aft_statement.items(): -## print(keys) -## print(values) - - #sas.enhanced_validation_information(0) - - #sas.set_secure_enhanced_validation_ID( MachineID=[0x01,0x01,0x01], seq_num=[0x00,0x00,0x01]) -## - while True: - state= binascii.hexlify(bytearray(sas.events_poll())) - print state - if (state=='57'): - sas.pending_cashout_info() - sas.validation_number( validationID=1, valid_number=1234567890365421) - - #sas.cash_out_ticket_info() - - if (state=='67'): #cashin - sas.ticket_validation_data() - sas.redeem_ticket( transfer_code=0, transfer_amount=10000, parsing_code=0, validation_data=1234567891234567, rescticted_expiration=3, pool_ID=0) - time.sleep(.3) - sas.redeem_ticket( transfer_code=0xff, transfer_amount=10000, parsing_code=0, validation_data=1234567891234567, rescticted_expiration=3, pool_ID=0) - - #71 - - time.sleep(1) - - for keys, values in tito_statement.items(): - print(keys) - print(values) - + busy = False + response = self.checkResponse(response) + self.log.debug('sas response %s', binascii.hexlify(response)) + if response == '': + response = None + self.log.error('no sas response') + return response + # return None + except Exception as e: + self.log.error(e, exc_info=True) + + busy = False + return None + + def checkResponse(self, rsp): + if (rsp == ''): + self.log.warning('sas not response') + return False + + resp = bytearray(rsp) + # print resp + if (resp[0] <> self.adress): + self.log.error("wrong ardess or NACK") + return False + + CRC = binascii.hexlify(resp[-2:]) + + command = resp[0:-2] + + crc1 = crc = CRC16Kermit().calculate(str(bytearray(command))) + + data = resp[1:-2] + + crc1 = hex(crc1).split('x')[-1] + + while len(crc1) < 4: + crc1 = "0" + crc1 + + # print crc1 + # print CRC + if (CRC != crc1): + # print "Wrong response command hash " + str(CRC) + # print "////" + str(hex(crc1).split('x')[-1]) + # print "////" + str(binascii.hexlify(command)) + return False + + return data + + ## def check_crc(self): + ## cmd=[0x01, 0x50, 0x81] + ## cmd=bytearray(cmd) + ## #print self.sas_CRC([0x01, 0x50, 0x81]) + ## #print ('\\'+'\\'.join(hex(e)[1:] for e in cmd)) + ## + ## print (CRC16Kermit().calculate(str(cmd))) + ## return + + def events_poll(self, timeout=1, **kwargs): + self._conf_event_port() + event = '' + cmd = [0x82, 0x80 + self.adress] + try: + self.connection.write(cmd) + t = time.time() + while time.time() - t < timeout: + # print "time"+ str(time.time()-t) + event = self.connection.read() + if event != '': + break + if event == '': + self.log.error('events poll no response') + event = None + event = GPOLL[event.encode('hex')] + except KeyError as e: + self.log.error('events poll unknown response') + event = None + except Exception as e: + self.log.critical(e, exc_info=True) + event = None + self._conf_port() + return event + + def shutdown(self, **kwargs): + # 01 + # print "1" + + if (self.__send_command([0x01], True, crc_need=True) == self.adress): + return True + else: + return False + return None + + def startup(self, **kwargs): + # 02 + # cmd=[0x02] + if (self.__send_command([0x02], True, crc_need=True) == self.adress): + return True + else: + return False + return None + + def sound_off(self, **kwargs): + # 03 + if (self.__send_command([0x03], True, crc_need=True) == self.adress): + return True + else: + return False + return None + + def sound_on(self, **kwargs): + # 04 + if (self.__send_command([0x04], True, crc_need=True) == self.adress): + return True + else: + return False + return None + + def reel_spin_game_sounds_disabled(self, **kwargs): + # 05 + if (self.__send_command([0x05], True, crc_need=True) == self.adress): + return True + else: + return None + return None + + def enable_bill_acceptor(self, **kwargs): + # 06 + if (self.__send_command([0x06], True, crc_need=True) == self.adress): + return True + else: + return False + return None + + def disable_bill_acceptor(self, **kwargs): + # 07 + if (self.__send_command([0x07], True, crc_need=True) == self.adress): + return True + else: + return False + return None + + def configure_bill_denom(self, bill_denom=[0xFF, 0xFF, 0xFF], action_flag=[0xff], **kwargs): + # 08 + cmd = [0x08, 0x00] + ##print str(hex(bill_denom)) + s = '00ffffff' + # print bytes.fromhex(((s))) + cmd.extend(bill_denom) + cmd.extend(action_flag) + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return None + + def en_dis_game(self, game_number=None, en_dis=True, **kwargs): + if game_number == None: + game_number = self.selected_game_number() + if en_dis == True: + en_dis = [0] + else: + en_dis = [1] + cmd = [0x09] + cmd.extend(bytearray(game_number)) + cmd.extend(bytearray(en_dis)) + + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return None + + def enter_maintenance_mode(self, **kwargs): + # 0A + if (self.__send_command([0x0A], True, crc_need=True) == self.adress): + return True + else: + return None + # return None + + def exit_maintanance_mode(self, **kwargs): + # 0B + if (self.__send_command([0x0B], True, crc_need=True) == self.adress): + return True + else: + return False + return None + + def en_dis_rt_event_reporting(self, enable=False, **kwargs): + # 0E + if enable == False: + enable = [0] + else: + enable = [1] + cmd = [0x0E] + cmd.extend(bytearray(enable)) + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return None + + def send_meters_10_15(self, denom=True, **kwargs): + cmd = [0x0f] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + if denom == True: + meters['total_cancelled_credits_meter'] = round( + int((binascii.hexlify(bytearray(data[1:5])))) * self.denom, 2) + meters['total_in_meter'] = round(int(binascii.hexlify(bytearray(data[5:9]))) * self.denom, 2) + meters['total_out_meter'] = round(int(binascii.hexlify(bytearray(data[9:13]))) * self.denom, 2) + meters['total_droup_meter'] = round(int(binascii.hexlify(bytearray(data[13:17]))) * self.denom, 2) + meters['total_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[17:21]))) * self.denom, 2) + meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) + else: + meters['total_cancelled_credits_meter'] = int((binascii.hexlify(bytearray(data[1:5])))) + meters['total_in_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) + meters['total_out_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) + meters['total_droup_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) + meters['total_jackpot_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) + return meters + return None + + def total_cancelled_credits(self, denom=True, **kwargs): + # 10 + cmd = [0x10] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == True: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + else: + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def total_bet_meter(self, denom=True, **kwargs): + # 11 + cmd = [0x11] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == True: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + else: + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def total_win_meter(self, denom=True, **kwargs): + # 12 + cmd = [0x12] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == True: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + else: + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def total_in_meter(self, denom=True, **kwargs): + # 13 + cmd = [0x13] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == True: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + else: + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def total_jackpot_meter(self, denom=True, **kwargs): + # 14 + cmd = [0x14] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == True: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + else: + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def games_played_meter(self, **kwargs): + # 15 + cmd = [0x15] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def games_won_meter(self, denom=True, **kwargs): + # 16 + cmd = [0x16] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == True: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + else: + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def games_lost_meter(self, **kwargs): + # 17 + cmd = [0x17] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def games_powerup_door_opened(self, **kwargs): + # 18 + cmd = [0x18] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + meters['games_last_power_up'] = int(binascii.hexlify(bytearray(data[1:3]))) + meters['games_last_slot_door_close'] = int(binascii.hexlify(bytearray(data[1:5]))) + + return data + return None + + def meters_11_15(self, denom=True, **kwargs): + # 19 + cmd = [0x19] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + if denom == False: + meters['total_bet_meter'] = int(binascii.hexlify(bytearray(data[1:5]))) + meters['total_win_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) + meters['total_in_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) + meters['total_jackpot_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) + meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + else: + meters['total_bet_meter'] = round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + meters['total_win_meter'] = round(int(binascii.hexlify(bytearray(data[5:9]))) * self.denom, 2) + meters['total_in_meter'] = round(int(binascii.hexlify(bytearray(data[9:13]))) * self.denom, 2) + meters['total_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[13:17]))) * self.denom, 2) + meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + return meters + return None + + def current_credits(self, denom=True, **kwargs): + # 1A + cmd = [0x1A] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == True: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + else: + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def handpay_info(self, **kwargs): + # 1B + cmd = [0x1B] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + meters['bin_progressive_group'] = int(binascii.hexlify(bytearray(data[1:2]))) + meters['bin_level'] = int(binascii.hexlify(bytearray(data[2:3]))) + meters['amount'] = int(binascii.hexlify(bytearray(data[3:8]))) + meters['bin_reset_ID'] = int(binascii.hexlify(bytearray(data[8:]))) + return meters + return None + + def meters(self, denom=True, **kwargs): + # 1C + cmd = [0x1C] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + if denom == False: + meters['total_bet_meter'] = int(binascii.hexlify(bytearray(data[1:5]))) + meters['total_win_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) + meters['total_in_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) + meters['total_jackpot_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) + meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + meters['games_won_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) + meters['slot_door_opened_meter'] = int(binascii.hexlify(bytearray(data[25:29]))) + meters['power_reset_meter'] = int(binascii.hexlify(bytearray(data[29:33]))) + else: + meters['total_bet_meter'] = round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + meters['total_win_meter'] = round(int(binascii.hexlify(bytearray(data[5:9]))) * self.denom, 2) + meters['total_in_meter'] = round(int(binascii.hexlify(bytearray(data[9:13]))) * self.denom, 2) + meters['total_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[13:17]))) * self.denom, 2) + meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + meters['games_won_meter'] = round(int(binascii.hexlify(bytearray(data[21:25]))) * self.denom, 2) + meters['slot_door_opened_meter'] = int(binascii.hexlify(bytearray(data[25:29]))) + meters['power_reset_meter'] = int(binascii.hexlify(bytearray(data[29:33]))) + + return meters + return None + + def total_bill_meters(self, **kwargs): + # 1E + cmd = [0x1E] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + meters['s1_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[1:5]))) + meters['s5_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) + meters['s10_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) + meters['s20_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) + meters['s50_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + meters['s100_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) + + return meters + return None + + def gaming_machine_ID(self, **kwargs): + # 1F + cmd = [0x1F] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + denom = DENOMINATION[binascii.hexlify(bytearray(data[6:7]))] + self.log.info('addenomination recognised ' + str(denom)) + return denom + # meters['ASCII_game_ID']=(((data[1:3]))) + # meters['ASCII_additional_ID']=(((data[3:6]))) + # meters['bin_denomination']=int(binascii.hexlify(bytearray(data[4:5]))) + # meters['bin_max_bet']=(binascii.hexlify(bytearray(data[7:8]))) + # meters['bin_progressive_mode']=int(binascii.hexlify(bytearray(data[8:9]))) + # meters['bin_game_options']=(binascii.hexlify(bytearray(data[9:11]))) + # meters['ASCII_paytable_ID']=(((data[11:17]))) + # meters['ASCII_base_percentage']=(((data[17:21]))) + + # return data + return None + + def total_dollar_value_of_bills_meter(self, **kwargs): + # 20 + + cmd = [0x20] + data = self.__send_command(cmd, crc_need=False) + + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:]))) + + return None + + def ROM_signature_verification(self, **kwargs): + # 21 + + cmd = [0x21, 0x00, 0x00] + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:3]))) + return None + + def eft_button_pressed(self, state=0, **kwargs): + # 24 + cmd = [0x24, 0x03] + cmd.append(state) + + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + return data + return None + + def true_coin_in(self, denom=True, **kwargs): + # 2A + cmd = [0x2A] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == False: + return int(binascii.hexlify(bytearray(data[1:5]))) + else: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return None + + def true_coin_out(self, denom=True, **kwargs): + # 2B + cmd = [0x2B] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + if denom == False: + return int(binascii.hexlify(bytearray(data[1:5]))) + else: + return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return None + + def curr_hopper_level(self, **kwargs): + # 2C + cmd = [0x2C] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def total_hand_paid_cancelled_credit(self, **kwargs): + # 2D + cmd = [0x2D] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def delay_game(self, delay_time=100, **kwargs): + # 2E + tmp = [] + delay_time = str(delay_time) + delay = '' + ('0' * (4 - len(delay_time)) + delay_time) + cmd = [0x2E] + count = 0 + for i in range(len(delay) / 2): + cmd.append(int(delay[count:count + 2], 16)) + count += 2 + if self.__send_command(cmd, True, crc_need=True) == self.adress: + return True + else: + return False + + return None + + def selected_meters_for_game(self, **kwargs): + # 2F + # FIXME: selected_meters_for_game + return None + + def send_1_bills_in_meters(self, **kwargs): + # 31 + cmd = [0x31] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_2_bills_in_meters(self, **kwargs): + # 32 + cmd = [0x32] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_5_bills_in_meters(self, **kwargs): + # 33 + cmd = [0x33] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_10_bills_in_meters(self, **kwargs): + # 34 + cmd = [0x34] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_20_bills_in_meters(self, **kwargs): + # 35 + cmd = [0x35] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_50_bills_in_meters(self, **kwargs): + # 36 + cmd = [0x36] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_100_bills_in_meters(self, **kwargs): + # 37 + cmd = [0x37] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_500_bills_in_meters(self, **kwargs): + # 38 + cmd = [0x38] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_1000_bills_in_meters(self, **kwargs): + # 39 + cmd = [0x39] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_200_bills_in_meters(self, **kwargs): + # 3A + cmd = [0x3a] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_25_bills_in_meters(self, **kwargs): + # 3B + cmd = [0x3B] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_2000_bills_in_meters(self, **kwargs): + # 3C + cmd = [0x3C] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def cash_out_ticket_info(self, **kwargs): + # 3D + cmd = [0x3D] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + tito_statement = {} + tito_statement['cashout_ticket_number'] = int(binascii.hexlify(bytearray(data[1:3]))) + tito_statement['cashout_amount_in_cents'] = int(binascii.hexlify(bytearray(data[3:]))) + return tito_statement + return None + + def send_2500_bills_in_meters(self, **kwargs): + # 3E + cmd = [0x3E] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_5000_bills_in_meters(self, **kwargs): + # 3F + cmd = [0x3F] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_10000_bills_in_meters(self, **kwargs): + # 40 + cmd = [0x40] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_20000_bills_in_meters(self, **kwargs): + # 41 + cmd = [0x41] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_25000_bills_in_meters(self, **kwargs): + # 42 + cmd = [0x42] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_50000_bills_in_meters(self, **kwargs): + # 43 + cmd = [0x43] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_100000_bills_in_meters(self, **kwargs): + # 44 + cmd = [0x44] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def send_250_bills_in_meters(self, **kwargs): + # 45 + cmd = [0x45] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def credit_amount_of_all_bills_accepted(self, **kwargs): + # 46 + cmd = [0x46] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def coin_amount_accepted_from_external_coin_acceptor(self, **kwargs): + # 47 + cmd = [0x47] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def last_accepted_bill_info(self, **kwargs): + # 48 + cmd = [0x48] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + meters['country_code'] = int(binascii.hexlify(bytearray(data[1:2]))) + meters['bill_denomination'] = int(binascii.hexlify(bytearray(data[2:3]))) + meters['meter_for_accepted_bills'] = int(binascii.hexlify(bytearray(data[3:6]))) + return meters + return None + + def number_of_bills_currently_in_stacker(self, **kwargs): + # 49 + cmd = [0x49] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def total_credit_amount_of_all_bills_in_stacker(self, **kwargs): + # 4A + cmd = [0x49] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return int(binascii.hexlify(bytearray(data[1:5]))) + return None + + def set_secure_enhanced_validation_ID(self, MachineID=[0x01, 0x01, 0x01], seq_num=[0x00, 0x00, 0x01], **kwargs): + # 4C + # FIXME: set_secure_enhanced_validation_ID + cmd = [0x4C] + + cmd.extend(MachineID) + cmd.extend(seq_num) + cmd = bytearray(cmd) + # print str(binascii.hexlify((cmd))) + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + tito_statement['machine_ID'] = int(binascii.hexlify(bytearray(data[1:4]))) + tito_statement['sequence_number'] = int(binascii.hexlify(bytearray(data[4:8]))) + + return data + return None + + def enhanced_validation_information(self, curr_validation_info=0, **kwargs): + # 4D + # FIXME: enhanced_validation_information + cmd = [0x4D] + + # cmd.append(transfer_code) + # cmd=cmd.extend(0) + # rint str(binascii.hexlify(bytearray(cmd))) + cmd.append((curr_validation_info)) + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + tito_statement['validation_type'] = int(binascii.hexlify(bytearray(data[1:2]))) + tito_statement['index_number'] = int(binascii.hexlify(bytearray(data[2:3]))) + tito_statement['date_validation_operation'] = str(binascii.hexlify(bytearray(data[3:7]))) + tito_statement['time_validation_operation'] = str(binascii.hexlify(bytearray(data[7:10]))) + tito_statement['validation_number'] = str(binascii.hexlify(bytearray(data[10:18]))) + tito_statement['ticket_amount'] = int(binascii.hexlify(bytearray(data[18:23]))) + tito_statement['ticket_number'] = int(binascii.hexlify(bytearray(data[23:25]))) + tito_statement['validation_system_ID'] = int(binascii.hexlify(bytearray(data[25:26]))) + tito_statement['expiration_date_printed_on_ticket'] = str(binascii.hexlify(bytearray(data[26:30]))) + tito_statement['pool_id'] = int(binascii.hexlify(bytearray(data[30:32]))) + + return data + return None + + def current_hopper_status(self, **kwargs): + # 4F + # FIXME: current_hopper_status + + cmd = [0x4F] + + data = self.__send_command(cmd, True, crc_need=False) + if (data <> None): + meters['current_hopper_lenght'] = int(binascii.hexlify(bytearray(data[1:2]))) + meters['current_hopper_ststus'] = int(binascii.hexlify(bytearray(data[2:3]))) + meters['current_hopper_percent_full'] = int(binascii.hexlify(bytearray(data[3:4]))) + meters['current_hopper_level'] = int(binascii.hexlify(bytearray(data[4:]))) + return data + return None + + def validation_meters(self, type_of_validation=0x00, **kwargs): + # 50 + # FIXME: validation_meters + cmd = [0x50] + cmd.append(type_of_validation) + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + meters['bin_validation_type'] = int(binascii.hexlify(bytearray(data[1]))) + meters['total_validations'] = int(binascii.hexlify(bytearray(data[2:6]))) + meters['cumulative_amount'] = str(binascii.hexlify(bytearray(data[6:]))) + + return data + return None + + def total_number_of_games_impimented(self, **kwargs): + # 51 + cmd = [0x51] + # cmd.extend(type_of_validation) + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + return str(binascii.hexlify(bytearray(data[1:]))) + return None + + def game_meters(self, n=None, denom=True, **kwargs): + # 52 + cmd = [0x52] + if n == None: + n == self.selected_game_number() + cmd.extend([((n >> 8) & 0xFF), (n & 0xFF)]) + + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + meters = {} + if denom == False: + meters['game_n_number'] = str(binascii.hexlify(bytearray(data[1:3]))) + meters['game_n_coin_in_meter'] = int(binascii.hexlify(bytearray(data[3:7]))) + meters['game_n_coin_out_meter'] = int(binascii.hexlify(bytearray(data[7:11]))) + meters['game_n_jackpot_meter'] = int(binascii.hexlify(bytearray(data[11:15]))) + meters['geme_n_games_played_meter'] = int(binascii.hexlify(bytearray(data[15:]))) + else: + meters['game_n_number'] = str(binascii.hexlify(bytearray(data[1:3]))) + meters['game_n_coin_in_meter'] = round(int(binascii.hexlify(bytearray(data[3:7]))) * self.denom, 2) + meters['game_n_coin_out_meter'] = round(int(binascii.hexlify(bytearray(data[7:11]))) * self.denom, 2) + meters['game_n_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[11:15]))) * self.denom, 2) + meters['geme_n_games_played_meter'] = int(binascii.hexlify(bytearray(data[15:]))) + return meters + return None + + def game_configuration(self, n=None, **kwargs): + # 53 + # FIXME: game_configuration + if n == None: + n = self.selected_game_number() + cmd = [0x53] + cmd.extend([(n & 0xFF), ((n >> 8) & 0xFF)]) + + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + meters['game_n_number_config'] = int(binascii.hexlify(bytearray(data[1:3]))) + meters['game_n_ASCII_game_ID'] = str(binascii.hexlify(bytearray(data[3:5]))) + meters['game_n_ASCII_additional_id'] = str(binascii.hexlify(bytearray(data[5:7]))) + meters['game_n_bin_denomination'] = str(binascii.hexlify(bytearray(data[7]))) + meters['game_n_bin_progressive_group'] = str(binascii.hexlify(bytearray(data[8]))) + meters['game_n_bin_game_options'] = str(binascii.hexlify(bytearray(data[9:11]))) + meters['game_n_ASCII_paytable_ID'] = str(binascii.hexlify(bytearray(data[11:17]))) + meters['game_n_ASCII_base_percentage'] = str(binascii.hexlify(bytearray(data[17:]))) + + return data + return None + + def SAS_version_gaming_machine_serial_ID(self, **kwargs): + # 54 + cmd = [0x54, 0x00] + + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + meters['ASCII_SAS_version'] = int(binascii.hexlify(bytearray(data[2:5]))) * 0.01 + meters['ASCII_serial_number'] = str(bytearray(data[5:])) + return meters + return None + + def selected_game_number(self, **kwargs): + # 55 + cmd = [0x55] + + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + # meters['selected_game_number']=int(binascii.hexlify(bytearray(data[1:]))) + return int(binascii.hexlify(bytearray(data[1:]))) + return None + + def enabled_game_numbers(self, **kwargs): + # 56 + + cmd = [0x56] + + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + meters = {} + meters['number_of_enabled_games'] = int(binascii.hexlify(bytearray(data[2]))) + meters['enabled_games_numbers'] = int(binascii.hexlify(bytearray(data[3:]))) + + return meters + return None + + def pending_cashout_info(self, **kwargs): + # 57 + + cmd = [0x57] + + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + tito_statement = {} + tito_statement['cashout_type'] = int(binascii.hexlify(bytearray(data[1:2]))) + tito_statement['cashout_amount'] = str(binascii.hexlify(bytearray(data[2:]))) + + return tito_statement + return None + + def validation_number(self, validationID=1, valid_number=0, **kwargs): + # 58 + + cmd = [0x58] + cmd.append(validationID) + cmd.extend(self.bcd_coder_array(valid_number, 8)) + print cmd + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + return str(binascii.hexlify(bytearray(data[1]))) + return None + + def eft_send_promo_to_machine(self, amount=0, count=1, status=0, **kwargs): + # 63 + # FIXME: eft_send_promo_to_machine + cmd = [0x63, count, ] + # status 0-init 1-end + cmd.append(status) + cmd.extend(self.bcd_coder_array(amount, 4)) + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + eft_statement = {} + eft_statement['eft_status'] = str(binascii.hexlify(bytearray(data[1:]))) + eft_statement['promo_amount'] = str(binascii.hexlify(bytearray(data[4:]))) + # eft_statement['eft_transfer_counter']=int(binascii.hexlify(bytearray(data[3:4]))) + + return eft_statement + return None + + def eft_load_cashable_credits(self, amount=0, count=1, status=0, **kwargs): + # 69 + # FIXME: eft_load_cashable_credits + cmd = [0x69, count, ] + cmd.append(status) + cmd.extend(self.bcd_coder_array(amount, 4)) + data = self.__send_command(cmd, True, crc_need=True) + + if (data <> None): + meters['eft_status'] = str(binascii.hexlify(bytearray(data[1:2]))) + meters['cashable_amount'] = str(binascii.hexlify(bytearray(data[2:5]))) + + return data[3] + return None + + def eft_avilable_transfers(self, **kwargs): + # 6A + # FIXME: eft_load_cashable_credits + cmd = [0x6A] + data = self.__send_command(cmd, True, crc_need=False) + if (data <> None): + # meters['number_bills_in_stacker']=int(binascii.hexlify(bytearray(data[1:5]))) + return data + return None + + def autentification_info(self, action=0, adressing_mode=0, component_name='', auth_method=b'\x00\x00\x00\x00', + seed_lenght=0, seed='', offset_lenght=0, offset='', **kwargs): + # 6E + # FIXME: autentification_info + cmd = [0x6E, 0x00] + cmd.append(action) + if action == 0: + # cmd.append(action) + cmd[1] = 1 + else: + if (action == 1 or action == 3): + cmd.append(adressing_mode) + cmd.append(len(bytearray(component_name))) + cmd.append(bytearray(component_name)) + cmd[1] = len(bytearray(component_name)) + 3 + else: + if action == 2: + cmd.append(adressing_mode) + cmd.append(len(bytearray(component_name))) + cmd.append(bytearray(component_name)) + cmd.append(auth_method) + cmd.append(seed_lenght) + cmd.append(bytearray(seed)) + cmd.append(offset_lenght) + cmd.append(bytearray(offset)) + + cmd[1] = len(bytearray(offset)) + len(bytearray(seed)) + len(bytearray(component_name)) + 6 + + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + return data[1] + return None + + def extended_meters_for_game(self, n=1, **kwargs): + # TODO: extended_meters_for_game + # 6F + return None + + def ticket_validation_data(self, **kwargs): + # 70 + # FIXME: ticket_validation_data + cmd = [0x70] + + data = self.__send_command(cmd, True, crc_need=False) + if (data <> None): + meters['ticket_status'] = int(binascii.hexlify(bytearray(data[2:3]))) + meters['ticket_amount'] = str(binascii.hexlify(bytearray(data[3:8]))) + meters['parsing_code'] = int(binascii.hexlify(bytearray(data[8:9]))) + meters['validation_data'] = str(binascii.hexlify(bytearray(data[9:]))) + + return data[1] + return None + + def redeem_ticket(self, transfer_code=0, transfer_amount=0, parsing_code=0, validation_data=0, + rescticted_expiration=0, pool_ID=0, **kwargs): + # 71 + # FIXME: redeem_ticket + cmd = [0x71, 0x00] + cmd.append(transfer_code) + cmd.extend(self.bcd_coder_array(transfer_amount, 5)) + cmd.append(parsing_code) + + cmd.extend(self.bcd_coder_array(validation_data, 8)) + cmd.extend(self.bcd_coder_array(rescticted_expiration, 4)) + cmd.extend(self.bcd_coder_array(pool_ID, 2)) + cmd[1] = 8 + 13 + + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + meters['ticket_status'] = int(binascii.hexlify(bytearray(data[2:3]))) + meters['ticket_amount'] = int(binascii.hexlify(bytearray(data[3:8]))) + meters['parsing_code'] = int(binascii.hexlify(bytearray(data[8:9]))) + meters['validation_data'] = str(binascii.hexlify(bytearray(data[9:]))) + + return data[1] + return None + + def AFT_out(self, amount=1, mony=None, lock_timeout=0, **kwargs): + # self.lock_emg(lock_time=500, condition=1) + my_time = datetime.datetime.now() + my_time = datetime.datetime.strftime(my_time, '%m%d%Y') + if mony == None: + mony = str(self.current_credits(denom=False)) + else: + mony = str(int((mony / self.denom))) + mony = mony.replace('.', '') + mony = '0' * (10 - len(mony)) + mony + if amount == 1: + mony_1 = mony + mony_2 = '0000000000' + mony_3 = '0000000000' + elif amount == 2: + mony_1 = '0000000000' + mony_2 = mony + mony_3 = '0000000000' + elif amount == 3: + mony_1 = '0000000000' + mony_2 = '0000000000' + mony_3 = mony + else: + raise AFTBadAmount + + last_transaction = self.AFT_format_transaction() + len_transaction_id = hex(len(last_transaction) / 2)[2:] + if len(len_transaction_id) < 2: + len_transaction_id = '0' + len_transaction_id + elif len(len_transaction_id) % 2 == 1: + len_transaction_id = '0' + len_transaction_id + cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, + asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, + times=my_time, my_key=self.my_key) + new_cmd = [] + count = 0 + for i in range(len(cmd) / 2): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + self.AFT_register() + if lock_timeout > 0: + self.AFT_game_lock(lock_timeout) + response = None + data = self.__send_command(new_cmd, crc_need=True) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + self.AFT_unregister() + return response + + def AFT_cashout_enable(self, amount=1, **kwargs): + + my_time = datetime.datetime.now() + my_time = datetime.datetime.strftime(my_time, '%m%d%Y') + mony = '0000000000' + + if amount == 1: + mony_1 = mony + mony_2 = '0000000000' + mony_3 = '0000000000' + elif amount == 2: + mony_1 = '0000000000' + mony_2 = mony + mony_3 = '0000000000' + elif amount == 3: + mony_1 = '0000000000' + mony_2 = '0000000000' + mony_3 = mony + else: + raise AFTBadAmount + + last_transaction = self.AFT_format_transaction() + len_transaction_id = hex(len(last_transaction) / 2)[2:] + if len(len_transaction_id) < 2: + len_transaction_id = '0' + len_transaction_id + elif len(len_transaction_id) % 2 == 1: + len_transaction_id = '0' + len_transaction_id + + cmd = '72{my_key}00{index}{transfer_code}{mony_1}{mony_2}{mony_3}02{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, + asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, + times=my_time, my_key=self.my_key) + new_cmd = [] + count = 0 + for i in range(len(cmd) / 2): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + self.AFT_register() + + response = None + data = self.__send_command(new_cmd, crc_need=True) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + self.AFT_unregister() + return self.AFT_clean_transaction_poll() + + def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): + + if self.denom > 0.01: + return None + if games == None: + game_selected = self.selected_game_number() + else: + game_selected = games + + if game_selected == 0: + return 'NoGame' + elif game_selected == None: + return 'NoGame' + elif game_selected < 1: + return 'NoGame' + + my_time = datetime.datetime.now() + my_time = datetime.datetime.strftime(my_time, '%m%d%Y') + mony = str(int((mony / self.denom))) + mony = mony.replace('.', '') + mony = '0' * (10 - len(mony)) + mony + if amount == 1: + mony_1 = mony + mony_2 = '0000000000' + mony_3 = '0000000000' + elif amount == 2: + mony_1 = '0000000000' + mony_2 = mony + mony_3 = '0000000000' + elif amount == 3: + mony_1 = '0000000000' + mony_2 = '0000000000' + mony_3 = mony + else: + raise AFTBadAmount + # if lock == True: + # self.lock_emg(lock_time=500, condition=0) + # self.lock_emg() + last_transaction = self.AFT_format_transaction() + len_transaction_id = hex(len(last_transaction) / 2)[2:] + if len(len_transaction_id) < 2: + len_transaction_id = '0' + len_transaction_id + elif len(len_transaction_id) % 2 == 1: + len_transaction_id = '0' + len_transaction_id + cmd = '72{my_key}{transfer_code}{index}{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + transfer_code='0000', index='10', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, + asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, + times=my_time, my_key=self.my_key) + + new_cmd = [] + count = 0 + for i in range(len(cmd) / 2): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + self.AFT_register() + if lock_timeout > 0: + self.AFT_game_lock(lock_timeout) + response = None + data = self.__send_command(new_cmd, crc_need=True) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + self.AFT_unregister() + return response + + def AFT_in(self, mony, amount=1, lock_timeout=0, **kwargs): + if self.denom > 0.01: + return None + my_time = datetime.datetime.now() + my_time = datetime.datetime.strftime(my_time, '%m%d%Y') + mony = str(int((mony / self.denom))) + mony = mony.replace('.', '') + mony = '0' * (10 - len(mony)) + mony + if amount == 1: + mony_1 = mony + mony_2 = '0000000000' + mony_3 = '0000000000' + elif amount == 2: + mony_1 = '0000000000' + mony_2 = mony + mony_3 = '0000000000' + elif amount == 3: + mony_1 = '0000000000' + mony_2 = '0000000000' + mony_3 = mony + else: + raise AFTBadAmount + + last_transaction = self.AFT_format_transaction() + len_transaction_id = hex(len(last_transaction) / 2)[2:] + if len(len_transaction_id) < 2: + len_transaction_id = '0' + len_transaction_id + elif len(len_transaction_id) % 2 == 1: + len_transaction_id = '0' + len_transaction_id + cmd = '72{my_key}{transfer_code}{index}00{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + transfer_code='00', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, + asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, + times=my_time, my_key=self.my_key) + new_cmd = [] + count = 0 + for i in range(len(cmd) / 2): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + self.AFT_register() + if lock_timeout > 0: + self.AFT_game_lock(lock_timeout) + response = None + data = self.__send_command(new_cmd, crc_need=True) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + self.AFT_unregister() + return response + + def AFT_clean_transaction_poll(self, register=False, **kwargs): + try: + if register == True: + self.AFT_register() + if self.transaction == None: + self.AFT_get_last_transaction() + + cmd = '7202FF00' + count = 0 + new_cmd = [] + for i in range(len(cmd) / 2): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + response = None + data = self.__send_command(new_cmd, crc_need=True) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + except BadCRC: + pass + if register == True: + self.AFT_unregister() + if hex(self.transaction)[2:-1] >= response['Transaction ID']: + return response + else: + raise BadTransactionID, 'last: %s, new:%s ' % ( + hex(self.last_transaction)[2:-1], response['Transaction ID']) + return response + + def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfer_type=0x00, cashable_amount=0, + restricted_amount=0, non_restricted_amount=0, transfer_flags=0x00, + asset_number=b'\x00\x00\x00\x00\x00', registration_key=0, transaction_ID_lenght=0x00, + transaction_ID='', expiration=0, pool_ID=0, reciept_data='', lock_timeout=0, **kwargs): + # 72 + cmd = [0x72, 0x00] + cmd.append(transfer_code) + cmd.append(transaction_index) + cmd.append(transfer_type) + cmd.extend(self.bcd_coder_array(cashable_amount, 5)) + cmd.extend(self.bcd_coder_array(restricted_amount, 5)) + cmd.extend(self.bcd_coder_array(non_restricted_amount, 5)) + cmd.append(transfer_flags) + cmd.extend((asset_number)) + cmd.extend(self.bcd_coder_array(registration_key, 20)) + cmd.append(len(transaction_ID)) + cmd.extend(transaction_ID) + cmd.extend(self.bcd_coder_array(expiration, 4)) + cmd.extend(self.bcd_coder_array(pool_ID, 2)) + + cmd.append(len(reciept_data)) + cmd.extend(reciept_data) + cmd.extend(self.bcd_coder_array(lock_timeout, 2)) + + cmd[1] = len(transaction_ID) + len(transaction_ID) + 53 + + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + aft_statement['transaction_buffer_position'] = int(binascii.hexlify(bytearray(data[2:3]))) + aft_statement['transfer_status'] = int(binascii.hexlify(bytearray(data[3:4]))) + aft_statement['receipt_status'] = int(binascii.hexlify(bytearray(data[4:5]))) + aft_statement['transfer_type'] = int(binascii.hexlify(bytearray(data[5:6]))) + aft_statement['cashable_amount'] = int(binascii.hexlify(bytearray(data[6:11]))) + aft_statement['restricted_amount'] = int(binascii.hexlify(bytearray(data[11:16]))) + aft_statement['nonrestricted_amount'] = int(binascii.hexlify(bytearray(data[16:21]))) + aft_statement['transfer_flags'] = int(binascii.hexlify(bytearray(data[21:22]))) + aft_statement['asset_number'] = (binascii.hexlify(bytearray(data[22:26]))) + aft_statement['transaction_ID_lenght'] = int(binascii.hexlify(bytearray(data[26:27]))) + a = int(binascii.hexlify(bytearray(data[26:27]))) + aft_statement['transaction_ID'] = str(binascii.hexlify(bytearray(data[27:(27 + a + 1)]))) + a = 27 + a + 1 + aft_statement['transaction_date'] = str(binascii.hexlify(bytearray(data[a:a + 5]))) + a = a + 5 + aft_statement['transaction_time'] = str(binascii.hexlify(bytearray(data[a:a + 4]))) + aft_statement['expiration'] = str(binascii.hexlify(bytearray(data[a + 4:a + 9]))) + aft_statement['pool_ID'] = str(binascii.hexlify(bytearray(data[a + 9:a + 11]))) + aft_statement['cumulative_casable_amount_meter_size'] = (binascii.hexlify(bytearray(data[a + 11:a + 12]))) + b = a + int(binascii.hexlify(bytearray(data[a + 11:a + 12]))) + aft_statement['cumulative_casable_amount_meter'] = (binascii.hexlify(bytearray(data[a + 12:b + 1]))) + aft_statement['cumulative_restricted_amount_meter_size'] = (binascii.hexlify(bytearray(data[b + 1:b + 2]))) + c = b + 2 + int(binascii.hexlify(bytearray(data[b + 1:b + 2]))) + aft_statement['cumulative_restricted_amount_meter'] = (binascii.hexlify(bytearray(data[b + 2:c]))) + aft_statement['cumulative_nonrestricted_amount_meter_size'] = (binascii.hexlify(bytearray(data[c:c + 1]))) + b = int(binascii.hexlify(bytearray(data[c:c + 1]))) + c + aft_statement['cumulative_nonrestricted_amount_meter'] = (binascii.hexlify(bytearray(data[c + 1:]))) + + return data[1] + return None + + def AFT_get_last_transaction(self, **kwargs): + cmd = [0x72, 0x02, 0xFF, 0x00] + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + count = int(binascii.hexlify(data[26:27]), 16) + # print count + try: + transaction = binascii.hexlify(data[27:27 + count]) + count = 0 + tmp = [] + for i in range(len(transaction) / 2): + tmp.append(transaction[count:count + 2]) + count += 2 + tmp.reverse() + for i in range(len(tmp)): + if int(tmp[i], 16) >= 124: + tmp[i] = '20' + tmp[i + 1] = hex(int(tmp[i + 1], 16) + 1)[2:] + tmp.reverse() + response = '' + for i in tmp: + response += i + if response == '2121212121212121212121212121212121': + response = '2020202020202020202020202020202021' + self.transaction = int(response, 16) + return self.transaction + except: + self.transaction = int('2020202020202020202020202020202021', 16) + self.log.warning('AFT no transaction') + else: + self.transaction = int('2020202020202020202020202020202021', 16) + self.log.warning('AFT no transaction') + + return self.transaction + + def AFT_format_transaction(self, **kwargs): + self.AFT_get_last_transaction() + self.transaction += 1 + return hex(self.transaction)[2:-1] + + def AFT_register_initial(self, **kwargs): + return self.AFT_register_gaming_machine(reg_code=0x01) + + def AFT_register(self, **kwargs): + return self.AFT_register_gaming_machine(reg_code=0x00) + + def AFT_unregister(self, **kwargs): + return self.AFT_register_gaming_machine(reg_code=0x80) + + def AFT_register_gaming_machine(self, reg_code=0xff, **kwargs): + # 73 + cmd = [0x73, 0x00] + if reg_code == 0xFF: + cmd.append(reg_code) + cmd[1] = 0x01 + else: + cmd.append(reg_code) + tmp = self.asset_number + self.reg_key + self.POS_ID + cmd[1] = 0x1D + count = 0 + for i in range(len(tmp) / 2): + cmd.append(int(tmp[count:count + 2], 16)) + count += 2 + data = self.__send_command(cmd, crc_need=True) + # data = None + if (data <> None): + aft_statement = {} + aft_statement['registration_status'] = AFT_REGISTRACION_STATUS[str(binascii.hexlify((data[2:3])))] + aft_statement['asset_number'] = str(binascii.hexlify(data[3:7])) + aft_statement['registration_key'] = str(binascii.hexlify(data[7:27])) + aft_statement['POS_ID'] = str(binascii.hexlify((data[27:]))) + return aft_statement + return None + + def AFT_game_lock(self, lock_timeout=100, **kwargs): + return self.AFT_game_lock_and_status_request(lock_code=0x00, lock_timeout=lock_timeout) + + def AFT_game_unlock(self, **kwargs): + return self.AFT_game_lock_and_status_request(lock_code=0x80) + + def AFT_game_lock_and_status_request(self, lock_code=0x00, transfer_condition=0b00000000, lock_timeout=0, **kwargs): + # 74 + cmd = [0x74] + + cmd.append(lock_code) + cmd.append(transfer_condition) + cmd.extend(self.bcd_coder_array(lock_timeout, 2)) + # cmd.addend(0x23) + + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + aft_statement = {} + aft_statement['asset_number'] = str(binascii.hexlify(bytearray(data[2:6]))) + aft_statement['game_lock_status'] = str(binascii.hexlify(bytearray(data[6:7]))) + aft_statement['avilable_transfers'] = str(binascii.hexlify(bytearray(data[7:8]))) + aft_statement['host_cashout_status'] = str(binascii.hexlify(bytearray(data[8:9]))) + aft_statement['AFT_status'] = str(binascii.hexlify(bytearray(data[9:10]))) + aft_statement['max_buffer_index'] = str(binascii.hexlify(bytearray(data[10:11]))) + aft_statement['current_cashable_amount'] = str(binascii.hexlify(bytearray(data[11:16]))) + aft_statement['current_restricted_amount'] = str(binascii.hexlify(bytearray(data[16:21]))) + aft_statement['current_non_restricted_amount'] = str(binascii.hexlify(bytearray(data[21:26]))) + aft_statement['restricted_expiration'] = str(binascii.hexlify(bytearray(data[26:29]))) + aft_statement['restricted_pool_ID'] = str(binascii.hexlify(bytearray(data[29:31]))) + + return aft_statement + return None + + def AFT_cansel_request(self, **kwargs): + cmd = [0x72, 0x01, 0x80] + self.AFT_register() + response = None + data = self.__send_command(cmd, crc_need=True) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + self.AFT_unregister() + return response + + def AFT_reciept_data(self, **kwargs): + # 75 + return + + def AFT_set_custom_ticket_data(self, **kwargs): + # 76 + return + + def exnended_validation_status(self, control_mask=[0, 0], status_bits=[0, 0], cashable_ticket_reciept_exp=0, + restricted_ticket_exp=0, **kwargs): + # 7B + cmd = [0x7B, 0x08] + + cmd.extend(control_mask) + cmd.extend(status_bits) + cmd.extend(self.bcd_coder_array(cashable_ticket_reciept_exp, 2)) + cmd.extend(self.bcd_coder_array(restricted_ticket_exp, 2)) + + # cmd.addend(0x23) + + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + aft_statement['asset_number'] = str(binascii.hexlify(bytearray(data[2:6]))) + aft_statement['status_bits'] = str(binascii.hexlify(bytearray(data[6:8]))) + aft_statement['cashable_ticket_reciept_exp'] = str(binascii.hexlify(bytearray(data[8:10]))) + aft_statement['restricted_ticket_exp'] = str(binascii.hexlify(bytearray(data[10:]))) + + return data[1] + return None + + def set_extended_ticket_data(self, **kwargs): + # 7C + return None + + def set_ticket_data(self, **kwargs): + # 7D + return None + + def current_date_time(self, **kwargs): + # 7E + cmd = [0x7E] + data = self.__send_command(cmd, crc_need=False) + if (data <> None): + data = str(binascii.hexlify(bytearray(data[1:8]))) + return datetime.datetime.strptime(data, '%m%d%Y%H%M%S') + return None + + def recieve_date_time(self, dates, times, **kwargs): + # 7F + cmd = [0x7F] + my_cmd = '' + dates.replace('.', '') + times.replace(':', '') + '00' + count = 0 + for i in range(len(my_cmd) / 2): + cmd.append(int(my_cmd[count:count + 2], 16)) + count += 2 + + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return None + + def recieve_progressive_amount(self, **kwargs): + # 80 + return None + + def cumulative_progressive_wins(self, **kwargs): + # 83 + return None + + def progressive_win_amount(self, **kwargs): + # 84 + return None + + def SAS_progressive_win_amount(self, **kwargs): + # 85 + return None + + def recieve_multiple_progressive_levels(self, **kwargs): + # 86 + return None + + def multiple_SAS_progresive_win_amounts(self, **kwargs): + # 87 + return None + + def initiate_legacy_bonus_pay(self, mony, tax='00', games=None, **kwargs): + # 8A + if games == None: + game_selected = self.selected_game_number() + else: + game_selected = games + if game_selected == 0: + return None + elif game_selected == None: + return None + cmd = str(int(round(mony / self.denom, 2))) + # cmd = cmd.replace('.', '') + cmd = '0' * (8 - len(cmd)) + cmd + my_cmd = cmd + tax + cmd = [0x8A] + count = 0 + for i in range(len(my_cmd) / 2): + cmd.append(int(my_cmd[count:count + 2], 16)) + count += 2 + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return None + + def initiate_multiplied_jackpot_mode(self, **kwargs): + # 8B + return None + + def enter_exit_tournament_mode(self, **kwargs): + # 8C + return None + + def card_info(self, **kwargs): + # 8E + return None + + def physical_reel_stop_info(self, **kwargs): + # 8F + return None + + def legacy_bonus_win_info(self, **kwargs): + # 90 + return None + + def remote_handpay_reset(self, **kwargs): + # 94 + cmd = [0x94] + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return + + def tournament_games_played(self, **kwargs): + # 95 + return + + def tournament_games_won(self, **kwargs): + # 96 + return + + def tournament_credits_wagered(self, **kwargs): + # 97 + return + + def tournament_credits_won(self, **kwargs): + # 98 + return + + def meters_95_98(self, **kwargs): + # 99 + return + + def legacy_bonus_meters(self, denom=True, n=0, **kwargs): + # 9A + cmd = [0x9A, ((n >> 8) & 0xFF), (n & 0xFF)] + # cmd.extend([(n&0xFF), ((n>>8)&0xFF)]) + # cmd=[0x19] + data = self.__send_command(cmd, crc_need=True) + + if (data <> None): + meters = {} + if denom == False: + meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:4]))) + meters['deductible'] = int(binascii.hexlify(bytearray(data[4:7]))) + meters['non-deductible'] = int(binascii.hexlify(bytearray(data[7:11]))) + meters['wager match'] = int(binascii.hexlify(bytearray(data[11:15]))) + + else: + meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:4]))) + meters['deductible'] = round(int(binascii.hexlify(bytearray(data[4:7]))) * self.denom, 2) + meters['non-deductible'] = round(int(binascii.hexlify(bytearray(data[7:11]))) * self.denom, 2) + meters['wager match'] = round(int(binascii.hexlify(bytearray(data[11:15]))) * self.denom, 2) + return meters + return None + + def stop_autorebet(self, **kwargs): + # AA00 + cmd = [0xAA, 0x00] + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return + + def start_autorebet(self, **kwargs): + # AA01 + cmd = [0xAA, 0x01] + if (self.__send_command(cmd, True, crc_need=True) == self.adress): + return True + else: + return None + # return + + def enabled_features(self, game_nimber=0, **kwargs): + # A0 + cmd = [0xA0] + + cmd.extend(self.bcd_coder_array(game_nimber, 2)) + + data = self.__send_command(cmd, True, crc_need=True) + if (data <> None): + aft_statement['game_number'] = str(binascii.hexlify(bytearray(data[1:3]))) + aft_statement['features_1'] = data[3] + aft_statement['features_2'] = data[4] + aft_statement['features_3'] = data[5] + + game_features['game_number'] = aft_statement.get('game_number') + if (data[3] & 0b00000001): + game_features['jackpot_multiplier'] = 1 + else: + game_features['jackpot_multiplier'] = 0 + + if (data[3] & 0b00000010): + game_features['AFT_bonus_avards'] = 1 + else: + game_features['AFT_bonus_avards'] = 0 + if (data[3] & 0b00000100): + game_features['legacy_bonus_awards'] = 1 + else: + game_features['legacy_bonus_awards'] = 0 + if (data[3] & 0b00001000): + game_features['tournament'] = 1 + else: + game_features['tournament'] = 0 + if (data[3] & 0b00010000): + game_features['validation_extensions'] = 1 + else: + game_features['validation_extensions'] = 0 + + game_features['validation_style'] = data[3] & 0b01100000 >> 5 + + if (data[3] & 0b10000000): + game_features['ticket_redemption'] = 1 + else: + game_features['ticket_redemption'] = 0 + + return data[1] + return None + + def cashout_limit(self, **kwargs): + # A4 + return + + def enable_jackpot_handpay_reset_method(self, **kwargs): + # A8 + return + + def extended_meters_game_alt(self, n=1, **kwargs): + # AF + return + + def multi_denom_preamble(self, **kwargs): + # B0 + return + + def current_player_denomination(self, **kwargs): + # B1 + return + + def enabled_player_denominations(self, **kwargs): + # B2 + return + + def token_denomination(self, **kwargs): + # B3 + return + + def wager_category_info(self, **kwargs): + # B4 + return + + def extended_game_info(self, n=1, **kwargs): + # B5 + return + + def event_response_to_long_poll(self, **kwargs): + # FF + return + + def bcd_coder_array(self, value=0, lenght=4, **kwargs): + return self.int_to_bcd(value, lenght) + + def int_to_bcd(self, number=0, lenght=5, **kwargs): + n = 0 + m = 0 + bval = 0 + p = lenght - 1 + result = [] + for i in range(0, lenght): + result.extend([0x00]) + while (p >= 0): + if (number != 0): + digit = number % 10 + number = number / 10 + m = m + 1 + else: + digit = 0 + if (n & 1): + bval |= digit << 4 + result[p] = bval + p = p - 1 + bval = 0 + else: + bval = digit + n = n + 1 + return result + + +class Sas_USB(Sas): + + def _conf_event_port(self): + # self.close() + self.connection.parity = serial.PARITY_NONE + self.connection.stopbits = serial.STOPBITS_TWO + # self.open() + + def _conf_port(self): + # self.close() + self.connection.parity = serial.PARITY_MARK + self.connection.stopbits = serial.STOPBITS_ONE + # self.open() + + def __send_command(self, command, no_response=False, timeout=None, crc_need=True): + if timeout == None: + timeout = self.timeout + 1 + busy = True + response = b'' + try: + if self.is_open() == False: + self.open() + buf_header = [self.adress] + self._conf_port() + self.connection.write(("82" + self.mashin_n).decode("hex")) + # self.close() + self.connection.parity = serial.PARITY_SPACE + # self.open() + + buf_header.extend(command) + buf_count = len(command) + # buf_header[2]=buf_count+2 + if (crc_need == True): + crc = CRC16Kermit().calculate(str(bytearray(buf_header))) + buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) + self.log.debug(buf_header) + # cmd =self.change_cmd(buf_header[1:]) + # cmd = cmd.encode('hex'), 'my command' + # print self.connection.portstr + # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) + self.connection.write((buf_header[1:])) + + except Exception as e: + self.log.error(e, exc_info=True) + + try: + buffer = [] + # self.connection.flushInput() + + t = time.time() + while time.time() - t < timeout: + response += self.connection.read() + if no_response == True: + return int(binascii.hexlify(response)) + if (self.checkResponse(response) <> False): + break + + if time.time() - t >= timeout: + self.log.warning("sas timeout waiting response") + # buffer.append(response) + # print binascii.hexlify(bytearray(response)) + return None + busy = False + response = self.checkResponse(response) + self.log.debug('sas response %s', binascii.hexlify(response)) + if response == '': + response = None + self.log.error('no sas response') + return response + # return None + except Exception as e: + self.log.error(e, exc_info=True) + + busy = False + return None + + +if __name__ == "__main__": + sas = Sas('/dev/ttyUSB0') + print sas.start() + print 'denom %s' % (sas.gaming_machine_ID()) + # sas.AFT_get_last_transaction() + sas.AFT_register_initial() + + # print sas.AFT_in(mony=1, lock_timeout=0) + # print sas.AFT_out() + # print sas.AFT_clean_transaction_poll() + print sas.current_credits() + # print sas.AFT_cashout_enable() + # sas.AFT_get_last_transaction() + + # print sas.shutdown() + # print sas.startup() From 6f03c4f77312f74cd6569239b349d77358a7fe28 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Mon, 6 Jun 2022 13:14:09 +0300 Subject: [PATCH 02/11] Update sas.py --- sas.py | 972 +++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 599 insertions(+), 373 deletions(-) diff --git a/sas.py b/sas.py index 7b150c9..e770707 100644 --- a/sas.py +++ b/sas.py @@ -16,6 +16,8 @@ import logging import datetime +EVENTS_POLL_TIMEOUT = 0.2 +# SLEEP_IF_FORMAT_TRANSACTION = 0 AFT_LOCK_STATUS = {'00': 'Game locked', '40': 'Game lock pending', 'ff': 'Game not locked'} AFT_REGISTRACION_STATUS = {'00': 'Gaming machine registration ready', '01': 'Gaming machine registered', '40': 'Gaming machine registration pending', '80': 'Gaming machine not registered'} @@ -33,19 +35,19 @@ '87': 'Gaming machine unable to perform transfers at this time (door open, tilt, disabled, cashout in progress, etc.)', '88': 'Gaming machine not registered (required for debit transfers)', '89': 'Registration key does not match', - '8A': 'No POS ID (required for debit transfers)', - '8B': 'No won credits available for cashout', - '8C': 'No gaming machine denomination set (unable to perform cents to credits conversion)', - '8D': 'Expiration not valid for transfer to ticket (already expired)', - '8E': 'Transfer to ticket device not available', - '8F': 'Unable to accept transfer due to existing restricted amounts from different pool', + '8a': 'No POS ID (required for debit transfers)', + '8b': 'No won credits available for cashout', + '8c': 'No gaming machine denomination set (unable to perform cents to credits conversion)', + '8d': 'Expiration not valid for transfer to ticket (already expired)', + '8e': 'Transfer to ticket device not available', + '8f': 'Unable to accept transfer due to existing restricted amounts from different pool', '90': 'Unable to print transaction receipt (receipt device not currently available)', '91': 'Insufficient data to print transaction receipt (required fields missing)', '92': 'Transaction receipt not allowed for specified transfer type', '93': 'Asset number zero or does not match', '94': 'Gaming machine not locked (transfer specified lock required)', '95': 'Transaction ID not valid', - '9F': 'Unexpected error Binary codes 110xxxxx indicate incompatible or unsupported poll', + '9f': 'Unexpected error Binary codes 110xxxxx indicate incompatible or unsupported poll', 'c0': 'Not compatible with current transfer in progress', 'c1': 'Unsupported transfer code Binary codes 111xxxxx indicate no transfer information available', 'ff': 'No transfer information available', @@ -435,17 +437,22 @@ class EMGGpollBadResponse(Exception): pass -class Sas(object): - adress = 1 - mashin_n = '01' - denom = 0.01 - asset_number = '01000000' - reg_key = '0000000000000000000000000000000000000000' - POS_ID = 'B374A402' - transaction = None - my_key = '44' - - def __init__(self, port, timeout=2, log=None): +class Sas(): + + def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_transaction=True): + # self.poll_adres = '82' + self.adress = None + self.mashin_n = None + self.aft_get_last_transaction = aft_get_last_transaction + # self.last_transaction_n = None + self.denom = 0.01 + self.asset_number = '01000000' + self.reg_key = '0000000000000000000000000000000000000000' + self.POS_ID = 'B374A402' + self.transaction = None + self.my_key = '44' + self.poll_adress = poll_adress + #self.my_log = file('/home/colibri/dump.log', 'a') if log == None: self.log = log_to_stderr() self.log.setLevel(logging.INFO) @@ -461,12 +468,22 @@ def __init__(self, port, timeout=2, log=None): break except: self.log.critical("SAS Port error") - time.sleep(10) + time.sleep(1) return def is_open(self): return self.connection.isOpen() + def flush(self): + try: + if self.is_open() == False: + self.open() + self.connection.flushOutput() + self.connection.flushInput() + except Exception as e: + self.log.error(e, exc_info=True) + self.close() + def start(self): self.log.info('Connecting SAS...') while True: @@ -481,19 +498,22 @@ def start(self): except Exception as e: self.log.critical(e, exc_info=True) else: + self.connection.flushOutput() + self.connection.flushInput() response = self.connection.read(1) if response == None: self.log.error('No SAS Connection') time.sleep(1) - if (response <> ''): + if response != '': self.adress = int(binascii.hexlify(response)) - if self.adress >= 1: - self.mashin_n = response.encode('HEX') - self.log.info('adress recognised ' + str(self.adress)) - break + # if self.adress >= 1: + self.mashin_n = response.encode('HEX') + self.log.info('adress recognised ' + str(self.adress)) + break else: self.log.error('No SAS Connection') time.sleep(1) + self.close() return self.mashin_n @@ -508,12 +528,14 @@ def open(self): def _conf_event_port(self): self.close() + self.connection.timeout = EVENTS_POLL_TIMEOUT self.connection.parity = serial.PARITY_NONE self.connection.stopbits = serial.STOPBITS_TWO self.open() def _conf_port(self): self.close() + self.connection.timeout = self.timeout self.connection.parity = serial.PARITY_MARK self.connection.stopbits = serial.STOPBITS_ONE self.open() @@ -553,18 +575,27 @@ def crc(self, response, chk=False, seed=0): raise BadCRC, response return data - def __send_command(self, command, no_response=False, timeout=None, crc_need=True): - if timeout == None: - timeout = self.timeout + 1 + def _send_command(self, command, no_response=False, timeout=None, crc_need=True, size=1): + + # if timeout == None: + # timeout = self.timeout + 1 + # time.sleep(0.04) busy = True response = b'' + #self.my_log.flush() try: + # if self.poll_adres == '82': + # self.poll_adres = '80' + # else: + # self.poll_adres = '82' + buf_header = [self.adress] self._conf_port() - self.connection.write(("82" + self.mashin_n).decode("hex")) - self.close() - self.connection.parity = serial.PARITY_SPACE - self.open() + # self.connection.flushInput() + # self.connection.write(('80' + self.mashin_n).decode("hex")) + # self.close() + # self.connection.parity = serial.PARITY_SPACE + # self.open() buf_header.extend(command) buf_count = len(command) @@ -573,8 +604,14 @@ def __send_command(self, command, no_response=False, timeout=None, crc_need=True crc = CRC16Kermit().calculate(str(bytearray(buf_header))) buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) self.log.debug(buf_header) - # cmd =self.change_cmd(buf_header[1:]) - # cmd = cmd.encode('hex'), 'my command' + #time.sleep(0.04) + self.connection.write([self.poll_adress, self.adress]) + self.close() + self.connection.parity = serial.PARITY_SPACE + self.open() + # self.connection.flushInput() + #my_log = open('/home/colibri/dump.log', 'w') + #self.my_log.write('TX %s: %s\n' % (time.time(), '82'+ binascii.hexlify(bytearray(buf_header)))) # print self.connection.portstr # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) self.connection.write((buf_header[1:])) @@ -585,51 +622,47 @@ def __send_command(self, command, no_response=False, timeout=None, crc_need=True try: buffer = [] # self.connection.flushInput() - - t = time.time() - while time.time() - t < timeout: - response += self.connection.read() - if no_response == True: + # time.sleep(0.04) + # t = time.time() + # while time.time() - t < timeout: + response = self.connection.read(size) + if no_response == True: + try: return int(binascii.hexlify(response)) - elif (self.checkResponse(response) <> False): - break - - if time.time() - t >= timeout: - self.log.warning("sas timeout waiting response") - # buffer.append(response) - # print binascii.hexlify(bytearray(response)) - return None + except ValueError as e: + self.log.warning('no sas response %s' % (str(buf_header[1:]))) + return None busy = False response = self.checkResponse(response) self.log.debug('sas response %s', binascii.hexlify(response)) - if response == '': - response = None - self.log.error('no sas response') return response - # return None + except BadCRC as e: + raise e except Exception as e: - self.log.error(e, exc_info=True) + self.log.info(e, exc_info=True) busy = False return None def checkResponse(self, rsp): if (rsp == ''): - self.log.warning('sas not response') - return False + # self.flush() + # self.close() + raise NoSasConnection + # return False resp = bytearray(rsp) # print resp - if (resp[0] <> self.adress): - self.log.error("wrong ardess or NACK") - return False + # if (resp[0] <> self.adress): + # self.log.error("wrong ardess or NACK") + # raise BadCRC CRC = binascii.hexlify(resp[-2:]) command = resp[0:-2] - crc1 = crc = CRC16Kermit().calculate(str(bytearray(command))) + crc1 = CRC16Kermit().calculate(str(bytearray(command))) data = resp[1:-2] @@ -644,9 +677,12 @@ def checkResponse(self, rsp): # print "Wrong response command hash " + str(CRC) # print "////" + str(hex(crc1).split('x')[-1]) # print "////" + str(binascii.hexlify(command)) - return False - - return data + raise BadCRC, binascii.hexlify(resp) + # return False + elif CRC == crc1: + #self.my_log.write('RX %s: %s\n' % (time.time(), binascii.hexlify(resp))) + return data + raise BadCRC, binascii.hexlify(resp) ## def check_crc(self): ## cmd=[0x01, 0x50, 0x81] @@ -657,36 +693,40 @@ def checkResponse(self, rsp): ## print (CRC16Kermit().calculate(str(cmd))) ## return - def events_poll(self, timeout=1, **kwargs): + def events_poll(self, timeout=EVENTS_POLL_TIMEOUT, **kwargs): self._conf_event_port() event = '' - cmd = [0x82, 0x80 + self.adress] + #self.my_log.write('TX %s: %s\n' % (time.time(), '8281')) + # time.sleep(0.04) + cmd = [0x80 + self.adress] + self.connection.write([self.poll_adress]) try: self.connection.write(cmd) - t = time.time() - while time.time() - t < timeout: - # print "time"+ str(time.time()-t) - event = self.connection.read() - if event != '': - break + # t = time.time() + # while time.time() - t < timeout: + # print "time"+ str(time.time()-t) + event = self.connection.read(1) + # if event != '': + # break if event == '': - self.log.error('events poll no response') - event = None + raise NoSasConnection + # event = None + # return None + #self.my_log.write('RX %s: %s\n' % (time.time(), event.encode('hex'))) + #self.my_log.flush() event = GPOLL[event.encode('hex')] except KeyError as e: - self.log.error('events poll unknown response') - event = None + raise EMGGpollBadResponse except Exception as e: - self.log.critical(e, exc_info=True) - event = None - self._conf_port() + raise e + # self._conf_port() return event def shutdown(self, **kwargs): # 01 # print "1" - if (self.__send_command([0x01], True, crc_need=True) == self.adress): + if (self._send_command([0x01], True, crc_need=True) == self.adress): return True else: return False @@ -695,7 +735,7 @@ def shutdown(self, **kwargs): def startup(self, **kwargs): # 02 # cmd=[0x02] - if (self.__send_command([0x02], True, crc_need=True) == self.adress): + if (self._send_command([0x02], True, crc_need=True) == self.adress): return True else: return False @@ -703,7 +743,7 @@ def startup(self, **kwargs): def sound_off(self, **kwargs): # 03 - if (self.__send_command([0x03], True, crc_need=True) == self.adress): + if (self._send_command([0x03], True, crc_need=True) == self.adress): return True else: return False @@ -711,7 +751,7 @@ def sound_off(self, **kwargs): def sound_on(self, **kwargs): # 04 - if (self.__send_command([0x04], True, crc_need=True) == self.adress): + if (self._send_command([0x04], True, crc_need=True) == self.adress): return True else: return False @@ -719,7 +759,7 @@ def sound_on(self, **kwargs): def reel_spin_game_sounds_disabled(self, **kwargs): # 05 - if (self.__send_command([0x05], True, crc_need=True) == self.adress): + if (self._send_command([0x05], True, crc_need=True) == self.adress): return True else: return None @@ -727,7 +767,7 @@ def reel_spin_game_sounds_disabled(self, **kwargs): def enable_bill_acceptor(self, **kwargs): # 06 - if (self.__send_command([0x06], True, crc_need=True) == self.adress): + if (self._send_command([0x06], True, crc_need=True) == self.adress): return True else: return False @@ -735,7 +775,7 @@ def enable_bill_acceptor(self, **kwargs): def disable_bill_acceptor(self, **kwargs): # 07 - if (self.__send_command([0x07], True, crc_need=True) == self.adress): + if (self._send_command([0x07], True, crc_need=True) == self.adress): return True else: return False @@ -749,32 +789,34 @@ def configure_bill_denom(self, bill_denom=[0xFF, 0xFF, 0xFF], action_flag=[0xff] # print bytes.fromhex(((s))) cmd.extend(bill_denom) cmd.extend(action_flag) - if (self.__send_command(cmd, True, crc_need=True) == self.adress): + if (self._send_command(cmd, True, crc_need=True) == self.adress): return True - else: - return None + # else: + return None # return None - def en_dis_game(self, game_number=None, en_dis=True, **kwargs): + def en_dis_game(self, game_number=None, en_dis=False, **kwargs): if game_number == None: game_number = self.selected_game_number() + game = int(game_number, 16) if en_dis == True: en_dis = [0] else: en_dis = [1] cmd = [0x09] - cmd.extend(bytearray(game_number)) - cmd.extend(bytearray(en_dis)) - if (self.__send_command(cmd, True, crc_need=True) == self.adress): - return True - else: - return None + cmd.extend([((game >> 8) & 0xFF), (game & 0xFF)]) + cmd.extend(bytearray(en_dis)) + # print cmd + if (self._send_command(cmd, True, crc_need=True) == self.adress): + return game_number + # else: + return None # return None def enter_maintenance_mode(self, **kwargs): # 0A - if (self.__send_command([0x0A], True, crc_need=True) == self.adress): + if (self._send_command([0x0A], True, crc_need=True) == self.adress): return True else: return None @@ -782,7 +824,7 @@ def enter_maintenance_mode(self, **kwargs): def exit_maintanance_mode(self, **kwargs): # 0B - if (self.__send_command([0x0B], True, crc_need=True) == self.adress): + if (self._send_command([0x0B], True, crc_need=True) == self.adress): return True else: return False @@ -796,20 +838,19 @@ def en_dis_rt_event_reporting(self, enable=False, **kwargs): enable = [1] cmd = [0x0E] cmd.extend(bytearray(enable)) - if (self.__send_command(cmd, True, crc_need=True) == self.adress): + if (self._send_command(cmd, True, crc_need=True) == self.adress): return True - else: - return None + # else: + return None # return None def send_meters_10_15(self, denom=True, **kwargs): cmd = [0x0f] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=28) if (data <> None): meters = {} if denom == True: - meters['total_cancelled_credits_meter'] = round( - int((binascii.hexlify(bytearray(data[1:5])))) * self.denom, 2) + meters['total_cancelled_credits_meter'] = round(int((binascii.hexlify(bytearray(data[1:5])))) * self.denom, 2) meters['total_in_meter'] = round(int(binascii.hexlify(bytearray(data[5:9]))) * self.denom, 2) meters['total_out_meter'] = round(int(binascii.hexlify(bytearray(data[9:13]))) * self.denom, 2) meters['total_droup_meter'] = round(int(binascii.hexlify(bytearray(data[13:17]))) * self.denom, 2) @@ -828,7 +869,7 @@ def send_meters_10_15(self, denom=True, **kwargs): def total_cancelled_credits(self, denom=True, **kwargs): # 10 cmd = [0x10] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): if denom == True: return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) @@ -839,7 +880,7 @@ def total_cancelled_credits(self, denom=True, **kwargs): def total_bet_meter(self, denom=True, **kwargs): # 11 cmd = [0x11] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): if denom == True: return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) @@ -850,7 +891,7 @@ def total_bet_meter(self, denom=True, **kwargs): def total_win_meter(self, denom=True, **kwargs): # 12 cmd = [0x12] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): if denom == True: return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) @@ -861,7 +902,7 @@ def total_win_meter(self, denom=True, **kwargs): def total_in_meter(self, denom=True, **kwargs): # 13 cmd = [0x13] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): if denom == True: return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) @@ -872,7 +913,7 @@ def total_in_meter(self, denom=True, **kwargs): def total_jackpot_meter(self, denom=True, **kwargs): # 14 cmd = [0x14] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): if denom == True: return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) @@ -883,7 +924,7 @@ def total_jackpot_meter(self, denom=True, **kwargs): def games_played_meter(self, **kwargs): # 15 cmd = [0x15] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -891,7 +932,7 @@ def games_played_meter(self, **kwargs): def games_won_meter(self, denom=True, **kwargs): # 16 cmd = [0x16] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): if denom == True: return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) @@ -902,7 +943,7 @@ def games_won_meter(self, denom=True, **kwargs): def games_lost_meter(self, **kwargs): # 17 cmd = [0x17] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -910,7 +951,7 @@ def games_lost_meter(self, **kwargs): def games_powerup_door_opened(self, **kwargs): # 18 cmd = [0x18] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): meters = {} meters['games_last_power_up'] = int(binascii.hexlify(bytearray(data[1:3]))) @@ -922,7 +963,7 @@ def games_powerup_door_opened(self, **kwargs): def meters_11_15(self, denom=True, **kwargs): # 19 cmd = [0x19] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=24) if (data <> None): meters = {} if denom == False: @@ -943,7 +984,7 @@ def meters_11_15(self, denom=True, **kwargs): def current_credits(self, denom=True, **kwargs): # 1A cmd = [0x1A] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): if denom == True: return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) @@ -954,7 +995,7 @@ def current_credits(self, denom=True, **kwargs): def handpay_info(self, **kwargs): # 1B cmd = [0x1B] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): meters = {} meters['bin_progressive_group'] = int(binascii.hexlify(bytearray(data[1:2]))) @@ -967,7 +1008,7 @@ def handpay_info(self, **kwargs): def meters(self, denom=True, **kwargs): # 1C cmd = [0x1C] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=36) if (data <> None): meters = {} if denom == False: @@ -995,7 +1036,7 @@ def meters(self, denom=True, **kwargs): def total_bill_meters(self, **kwargs): # 1E cmd = [0x1E] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=28) if (data <> None): meters = {} meters['s1_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[1:5]))) @@ -1011,10 +1052,11 @@ def total_bill_meters(self, **kwargs): def gaming_machine_ID(self, **kwargs): # 1F cmd = [0x1F] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=24) if (data <> None): denom = DENOMINATION[binascii.hexlify(bytearray(data[6:7]))] self.log.info('addenomination recognised ' + str(denom)) + self.denom = denom return denom # meters['ASCII_game_ID']=(((data[1:3]))) # meters['ASCII_additional_ID']=(((data[3:6]))) @@ -1032,7 +1074,7 @@ def total_dollar_value_of_bills_meter(self, **kwargs): # 20 cmd = [0x20] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:]))) @@ -1043,7 +1085,7 @@ def ROM_signature_verification(self, **kwargs): # 21 cmd = [0x21, 0x00, 0x00] - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True) if (data <> None): return int(binascii.hexlify(bytearray(data[1:3]))) return None @@ -1053,7 +1095,7 @@ def eft_button_pressed(self, state=0, **kwargs): cmd = [0x24, 0x03] cmd.append(state) - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True) if (data <> None): return data return None @@ -1061,7 +1103,7 @@ def eft_button_pressed(self, state=0, **kwargs): def true_coin_in(self, denom=True, **kwargs): # 2A cmd = [0x2A] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): if denom == False: return int(binascii.hexlify(bytearray(data[1:5]))) @@ -1072,7 +1114,7 @@ def true_coin_in(self, denom=True, **kwargs): def true_coin_out(self, denom=True, **kwargs): # 2B cmd = [0x2B] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): if denom == False: return int(binascii.hexlify(bytearray(data[1:5]))) @@ -1083,7 +1125,7 @@ def true_coin_out(self, denom=True, **kwargs): def curr_hopper_level(self, **kwargs): # 2C cmd = [0x2C] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1091,7 +1133,7 @@ def curr_hopper_level(self, **kwargs): def total_hand_paid_cancelled_credit(self, **kwargs): # 2D cmd = [0x2D] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1106,7 +1148,7 @@ def delay_game(self, delay_time=100, **kwargs): for i in range(len(delay) / 2): cmd.append(int(delay[count:count + 2], 16)) count += 2 - if self.__send_command(cmd, True, crc_need=True) == self.adress: + if self._send_command(cmd, True, crc_need=True) == self.adress: return True else: return False @@ -1121,7 +1163,7 @@ def selected_meters_for_game(self, **kwargs): def send_1_bills_in_meters(self, **kwargs): # 31 cmd = [0x31] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1129,7 +1171,7 @@ def send_1_bills_in_meters(self, **kwargs): def send_2_bills_in_meters(self, **kwargs): # 32 cmd = [0x32] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1137,7 +1179,7 @@ def send_2_bills_in_meters(self, **kwargs): def send_5_bills_in_meters(self, **kwargs): # 33 cmd = [0x33] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1145,7 +1187,7 @@ def send_5_bills_in_meters(self, **kwargs): def send_10_bills_in_meters(self, **kwargs): # 34 cmd = [0x34] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1153,7 +1195,7 @@ def send_10_bills_in_meters(self, **kwargs): def send_20_bills_in_meters(self, **kwargs): # 35 cmd = [0x35] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1161,7 +1203,7 @@ def send_20_bills_in_meters(self, **kwargs): def send_50_bills_in_meters(self, **kwargs): # 36 cmd = [0x36] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1169,7 +1211,7 @@ def send_50_bills_in_meters(self, **kwargs): def send_100_bills_in_meters(self, **kwargs): # 37 cmd = [0x37] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1177,7 +1219,7 @@ def send_100_bills_in_meters(self, **kwargs): def send_500_bills_in_meters(self, **kwargs): # 38 cmd = [0x38] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1185,7 +1227,7 @@ def send_500_bills_in_meters(self, **kwargs): def send_1000_bills_in_meters(self, **kwargs): # 39 cmd = [0x39] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1193,7 +1235,7 @@ def send_1000_bills_in_meters(self, **kwargs): def send_200_bills_in_meters(self, **kwargs): # 3A cmd = [0x3a] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1201,7 +1243,7 @@ def send_200_bills_in_meters(self, **kwargs): def send_25_bills_in_meters(self, **kwargs): # 3B cmd = [0x3B] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1209,7 +1251,7 @@ def send_25_bills_in_meters(self, **kwargs): def send_2000_bills_in_meters(self, **kwargs): # 3C cmd = [0x3C] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1217,7 +1259,7 @@ def send_2000_bills_in_meters(self, **kwargs): def cash_out_ticket_info(self, **kwargs): # 3D cmd = [0x3D] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): tito_statement = {} tito_statement['cashout_ticket_number'] = int(binascii.hexlify(bytearray(data[1:3]))) @@ -1228,7 +1270,7 @@ def cash_out_ticket_info(self, **kwargs): def send_2500_bills_in_meters(self, **kwargs): # 3E cmd = [0x3E] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1236,7 +1278,7 @@ def send_2500_bills_in_meters(self, **kwargs): def send_5000_bills_in_meters(self, **kwargs): # 3F cmd = [0x3F] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1244,7 +1286,7 @@ def send_5000_bills_in_meters(self, **kwargs): def send_10000_bills_in_meters(self, **kwargs): # 40 cmd = [0x40] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1252,7 +1294,7 @@ def send_10000_bills_in_meters(self, **kwargs): def send_20000_bills_in_meters(self, **kwargs): # 41 cmd = [0x41] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1260,7 +1302,7 @@ def send_20000_bills_in_meters(self, **kwargs): def send_25000_bills_in_meters(self, **kwargs): # 42 cmd = [0x42] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1268,7 +1310,7 @@ def send_25000_bills_in_meters(self, **kwargs): def send_50000_bills_in_meters(self, **kwargs): # 43 cmd = [0x43] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1276,7 +1318,7 @@ def send_50000_bills_in_meters(self, **kwargs): def send_100000_bills_in_meters(self, **kwargs): # 44 cmd = [0x44] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1284,7 +1326,7 @@ def send_100000_bills_in_meters(self, **kwargs): def send_250_bills_in_meters(self, **kwargs): # 45 cmd = [0x45] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1292,7 +1334,7 @@ def send_250_bills_in_meters(self, **kwargs): def credit_amount_of_all_bills_accepted(self, **kwargs): # 46 cmd = [0x46] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1300,7 +1342,7 @@ def credit_amount_of_all_bills_accepted(self, **kwargs): def coin_amount_accepted_from_external_coin_acceptor(self, **kwargs): # 47 cmd = [0x47] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1308,7 +1350,7 @@ def coin_amount_accepted_from_external_coin_acceptor(self, **kwargs): def last_accepted_bill_info(self, **kwargs): # 48 cmd = [0x48] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): meters = {} meters['country_code'] = int(binascii.hexlify(bytearray(data[1:2]))) @@ -1320,7 +1362,7 @@ def last_accepted_bill_info(self, **kwargs): def number_of_bills_currently_in_stacker(self, **kwargs): # 49 cmd = [0x49] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1328,7 +1370,7 @@ def number_of_bills_currently_in_stacker(self, **kwargs): def total_credit_amount_of_all_bills_in_stacker(self, **kwargs): # 4A cmd = [0x49] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=8) if (data <> None): return int(binascii.hexlify(bytearray(data[1:5]))) return None @@ -1342,7 +1384,7 @@ def set_secure_enhanced_validation_ID(self, MachineID=[0x01, 0x01, 0x01], seq_nu cmd.extend(seq_num) cmd = bytearray(cmd) # print str(binascii.hexlify((cmd))) - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): tito_statement['machine_ID'] = int(binascii.hexlify(bytearray(data[1:4]))) tito_statement['sequence_number'] = int(binascii.hexlify(bytearray(data[4:8]))) @@ -1359,7 +1401,7 @@ def enhanced_validation_information(self, curr_validation_info=0, **kwargs): # cmd=cmd.extend(0) # rint str(binascii.hexlify(bytearray(cmd))) cmd.append((curr_validation_info)) - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): tito_statement['validation_type'] = int(binascii.hexlify(bytearray(data[1:2]))) tito_statement['index_number'] = int(binascii.hexlify(bytearray(data[2:3]))) @@ -1381,7 +1423,7 @@ def current_hopper_status(self, **kwargs): cmd = [0x4F] - data = self.__send_command(cmd, True, crc_need=False) + data = self._send_command(cmd, True, crc_need=False) if (data <> None): meters['current_hopper_lenght'] = int(binascii.hexlify(bytearray(data[1:2]))) meters['current_hopper_ststus'] = int(binascii.hexlify(bytearray(data[2:3]))) @@ -1395,7 +1437,7 @@ def validation_meters(self, type_of_validation=0x00, **kwargs): # FIXME: validation_meters cmd = [0x50] cmd.append(type_of_validation) - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): meters['bin_validation_type'] = int(binascii.hexlify(bytearray(data[1]))) meters['total_validations'] = int(binascii.hexlify(bytearray(data[2:6]))) @@ -1408,7 +1450,7 @@ def total_number_of_games_impimented(self, **kwargs): # 51 cmd = [0x51] # cmd.extend(type_of_validation) - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=6) if (data <> None): return str(binascii.hexlify(bytearray(data[1:]))) return None @@ -1417,10 +1459,10 @@ def game_meters(self, n=None, denom=True, **kwargs): # 52 cmd = [0x52] if n == None: - n == self.selected_game_number() + n == self.selected_game_number(in_hex=False) cmd.extend([((n >> 8) & 0xFF), (n & 0xFF)]) - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True, size=22) if (data <> None): meters = {} if denom == False: @@ -1442,11 +1484,11 @@ def game_configuration(self, n=None, **kwargs): # 53 # FIXME: game_configuration if n == None: - n = self.selected_game_number() + n = self.selected_game_number(in_hex=False) cmd = [0x53] cmd.extend([(n & 0xFF), ((n >> 8) & 0xFF)]) - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): meters['game_n_number_config'] = int(binascii.hexlify(bytearray(data[1:3]))) meters['game_n_ASCII_game_ID'] = str(binascii.hexlify(bytearray(data[3:5]))) @@ -1464,7 +1506,7 @@ def SAS_version_gaming_machine_serial_ID(self, **kwargs): # 54 cmd = [0x54, 0x00] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=20) if (data <> None): meters = {} meters['ASCII_SAS_version'] = int(binascii.hexlify(bytearray(data[2:5]))) * 0.01 @@ -1472,14 +1514,17 @@ def SAS_version_gaming_machine_serial_ID(self, **kwargs): return meters return None - def selected_game_number(self, **kwargs): + def selected_game_number(self, in_hex=True, **kwargs): # 55 cmd = [0x55] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=6) if (data <> None): # meters['selected_game_number']=int(binascii.hexlify(bytearray(data[1:]))) - return int(binascii.hexlify(bytearray(data[1:]))) + if in_hex == False: + return int(binascii.hexlify(bytearray(data[1:]))) + else: + return binascii.hexlify(bytearray(data[1:])) return None def enabled_game_numbers(self, **kwargs): @@ -1487,7 +1532,7 @@ def enabled_game_numbers(self, **kwargs): cmd = [0x56] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): meters = {} meters['number_of_enabled_games'] = int(binascii.hexlify(bytearray(data[2]))) @@ -1501,7 +1546,7 @@ def pending_cashout_info(self, **kwargs): cmd = [0x57] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False) if (data <> None): tito_statement = {} tito_statement['cashout_type'] = int(binascii.hexlify(bytearray(data[1:2]))) @@ -1516,8 +1561,8 @@ def validation_number(self, validationID=1, valid_number=0, **kwargs): cmd = [0x58] cmd.append(validationID) cmd.extend(self.bcd_coder_array(valid_number, 8)) - print cmd - data = self.__send_command(cmd, crc_need=True) + # print cmd + data = self._send_command(cmd, crc_need=True) if (data <> None): return str(binascii.hexlify(bytearray(data[1]))) return None @@ -1529,7 +1574,7 @@ def eft_send_promo_to_machine(self, amount=0, count=1, status=0, **kwargs): # status 0-init 1-end cmd.append(status) cmd.extend(self.bcd_coder_array(amount, 4)) - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True) if (data <> None): eft_statement = {} eft_statement['eft_status'] = str(binascii.hexlify(bytearray(data[1:]))) @@ -1545,7 +1590,7 @@ def eft_load_cashable_credits(self, amount=0, count=1, status=0, **kwargs): cmd = [0x69, count, ] cmd.append(status) cmd.extend(self.bcd_coder_array(amount, 4)) - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): meters['eft_status'] = str(binascii.hexlify(bytearray(data[1:2]))) @@ -1558,7 +1603,7 @@ def eft_avilable_transfers(self, **kwargs): # 6A # FIXME: eft_load_cashable_credits cmd = [0x6A] - data = self.__send_command(cmd, True, crc_need=False) + data = self._send_command(cmd, True, crc_need=False) if (data <> None): # meters['number_bills_in_stacker']=int(binascii.hexlify(bytearray(data[1:5]))) return data @@ -1592,7 +1637,7 @@ def autentification_info(self, action=0, adressing_mode=0, component_name='', au cmd[1] = len(bytearray(offset)) + len(bytearray(seed)) + len(bytearray(component_name)) + 6 - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): return data[1] return None @@ -1607,7 +1652,7 @@ def ticket_validation_data(self, **kwargs): # FIXME: ticket_validation_data cmd = [0x70] - data = self.__send_command(cmd, True, crc_need=False) + data = self._send_command(cmd, True, crc_need=False) if (data <> None): meters['ticket_status'] = int(binascii.hexlify(bytearray(data[2:3]))) meters['ticket_amount'] = str(binascii.hexlify(bytearray(data[3:8]))) @@ -1631,7 +1676,7 @@ def redeem_ticket(self, transfer_code=0, transfer_amount=0, parsing_code=0, vali cmd.extend(self.bcd_coder_array(pool_ID, 2)) cmd[1] = 8 + 13 - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): meters['ticket_status'] = int(binascii.hexlify(bytearray(data[2:3]))) meters['ticket_amount'] = int(binascii.hexlify(bytearray(data[3:8]))) @@ -1641,8 +1686,28 @@ def redeem_ticket(self, transfer_code=0, transfer_amount=0, parsing_code=0, vali return data[1] return None - def AFT_out(self, amount=1, mony=None, lock_timeout=0, **kwargs): + def AFT_jp(self, mony, amount=1, lock_timeout=0, games=None, **kwargs): # self.lock_emg(lock_time=500, condition=1) + if self.denom > 0.01: + return None + if games == None: + for i in range(3): + try: + game_selected = self.selected_game_number(in_hex=False) + except: + game_selected = None + if game_selected == None: + time.sleep(0.04) + else: + break + else: + game_selected = games + if game_selected == 0: + return 'NoGame' + elif game_selected == None: + return 'NoGame' + elif game_selected < 1: + return 'NoGame' my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') if mony == None: @@ -1673,7 +1738,7 @@ def AFT_out(self, amount=1, mony=None, lock_timeout=0, **kwargs): elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( - transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, + transfer_code='11', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, times=my_time, my_key=self.my_key) new_cmd = [] @@ -1681,11 +1746,12 @@ def AFT_out(self, amount=1, mony=None, lock_timeout=0, **kwargs): for i in range(len(cmd) / 2): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 + + response = None self.AFT_register() if lock_timeout > 0: - self.AFT_game_lock(lock_timeout) - response = None - data = self.__send_command(new_cmd, crc_need=True) + self.AFT_game_lock(lock_timeout, condition=1) + data = self._send_command(new_cmd, crc_need=True, size=82) if (data <> None): a = int(binascii.hexlify(bytearray(data[26:27])), 16) response = { @@ -1702,7 +1768,83 @@ def AFT_out(self, amount=1, mony=None, lock_timeout=0, **kwargs): 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) } + try: + self.AFT_unregister() + except: + self.log.warning('AFT UNREGISTER ERROR: won to host') + return response + + def AFT_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): + # self.lock_emg(lock_time=500, condition=1) + if self.denom > 0.01: + return None + my_time = datetime.datetime.now() + my_time = datetime.datetime.strftime(my_time, '%m%d%Y') + if mony == None: + mony = str(self.current_credits(denom=False)) + else: + mony = str(int((mony / self.denom))) + mony = mony.replace('.', '') + mony = '0' * (10 - len(mony)) + mony + if amount == 1: + mony_1 = mony + mony_2 = '0000000000' + mony_3 = '0000000000' + elif amount == 2: + mony_1 = '0000000000' + mony_2 = mony + mony_3 = '0000000000' + elif amount == 3: + mony_1 = '0000000000' + mony_2 = '0000000000' + mony_3 = mony + else: + raise AFTBadAmount + + last_transaction = self.AFT_format_transaction() + len_transaction_id = hex(len(last_transaction) / 2)[2:] + if len(len_transaction_id) < 2: + len_transaction_id = '0' + len_transaction_id + elif len(len_transaction_id) % 2 == 1: + len_transaction_id = '0' + len_transaction_id + cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, + asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, + times=my_time, my_key=self.my_key) + new_cmd = [] + count = 0 + for i in range(len(cmd) / 2): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + + response = None + self.AFT_register() + if lock_timeout > 0: + self.AFT_game_lock(lock_timeout, condition=1) + try: + data = self._send_command(new_cmd, crc_need=True, size=82) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + except Exception as e: + self.log.error(e, exc_info=True) + # try: self.AFT_unregister() + # except: + # self.log.warning('AFT UNREGISTER ERROR: out') return response def AFT_cashout_enable(self, amount=1, **kwargs): @@ -1745,41 +1887,64 @@ def AFT_cashout_enable(self, amount=1, **kwargs): self.AFT_register() response = None - data = self.__send_command(new_cmd, crc_need=True) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) - response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) - } + try: + data = self._send_command(new_cmd, crc_need=True, size=82) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + except Exception as e: + self.log.info(e, exc_info=True) + # try: self.AFT_unregister() - return self.AFT_clean_transaction_poll() + # except: + # try: + # time.sleep(0.04) + # self.AFT_clean_transaction_poll() + # except Exception as e: + # pass + try: + self.AFT_clean_transaction_poll() + except: + pass + return True def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): if self.denom > 0.01: return None if games == None: - game_selected = self.selected_game_number() + for i in range(3): + try: + game_selected = self.selected_game_number(in_hex=False) + except: + game_selected = None + if game_selected == None: + time.sleep(0.04) + else: + break else: game_selected = games - if game_selected == 0: return 'NoGame' elif game_selected == None: return 'NoGame' elif game_selected < 1: return 'NoGame' + elif game_selected < None: + return 'NoGame' my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') @@ -1819,28 +1984,34 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): for i in range(len(cmd) / 2): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 + + response = None self.AFT_register() if lock_timeout > 0: - self.AFT_game_lock(lock_timeout) - response = None - data = self.__send_command(new_cmd, crc_need=True) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) - response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) - } + self.AFT_game_lock(lock_timeout, condition=3) + try: + data = self._send_command(new_cmd, crc_need=True, size=82) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + except Exception as e: + self.log.error(e, exc_info=True) self.AFT_unregister() + # except: + # self.log.warning('AFT UNREGISTER ERROR: won') return response def AFT_in(self, mony, amount=1, lock_timeout=0, **kwargs): @@ -1881,50 +2052,62 @@ def AFT_in(self, mony, amount=1, lock_timeout=0, **kwargs): for i in range(len(cmd) / 2): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 + # self.AFT_register() + # if lock_timeout > 0: + # self.AFT_game_lock(lock_timeout, condition=0) + response = None self.AFT_register() if lock_timeout > 0: - self.AFT_game_lock(lock_timeout) - response = None - data = self.__send_command(new_cmd, crc_need=True) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) - response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) - } + self.AFT_game_lock(lock_timeout, condition=0) + try: + data = self._send_command(new_cmd, crc_need=True, size=82) + if (data <> None): + a = int(binascii.hexlify(bytearray(data[26:27])), 16) + response = { + 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), + 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), + 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], + 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, + 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), + 'Asset number': binascii.hexlify(bytearray(data[22:26])), + 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), + 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + } + except Exception as e: + self.log.error(e, exc_info=True) + # try: self.AFT_unregister() + # except: + # self.log.warning('AFT UNREGISTER ERROR: in') return response def AFT_clean_transaction_poll(self, register=False, **kwargs): + # try: + if register == True: + self.AFT_register() + # except Exception as e: + # self.log.error(e, exc_info = True) + if self.transaction == None: + self.AFT_get_last_transaction() + # time.sleep(0.7) + cmd = '7202FF00' + count = 0 + new_cmd = [] + for i in range(len(cmd) / 2): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + response = None try: - if register == True: - self.AFT_register() - if self.transaction == None: - self.AFT_get_last_transaction() - - cmd = '7202FF00' - count = 0 - new_cmd = [] - for i in range(len(cmd) / 2): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 - response = None - data = self.__send_command(new_cmd, crc_need=True) + data = self._send_command(new_cmd, crc_need=True, size=90) if (data <> None): + # print binascii.hexlify(data) a = int(binascii.hexlify(bytearray(data[26:27])), 16) response = { 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], @@ -1936,16 +2119,23 @@ def AFT_clean_transaction_poll(self, register=False, **kwargs): 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) } + if register == True: + try: + self.AFT_unregister() + except: + self.log.warning('AFT UNREGISTER ERROR: cleean poll') + if hex(self.transaction)[2:-1] == response['Transaction ID']: + return response + else: + if self.aft_get_last_transaction == True: + raise BadTransactionID, 'last: %s, new:%s ' % ( + hex(self.transaction)[2:-1], response['Transaction ID']) + else: + self.log.info('last: %s, new:%s ' % ( + hex(self.transaction)[2:-1], response['Transaction ID'])) except BadCRC: pass - if register == True: - self.AFT_unregister() - if hex(self.transaction)[2:-1] >= response['Transaction ID']: - return response - else: - raise BadTransactionID, 'last: %s, new:%s ' % ( - hex(self.last_transaction)[2:-1], response['Transaction ID']) - return response + return False def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfer_type=0x00, cashable_amount=0, restricted_amount=0, non_restricted_amount=0, transfer_flags=0x00, @@ -1973,7 +2163,7 @@ def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfe cmd[1] = len(transaction_ID) + len(transaction_ID) + 53 - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True) if (data <> None): aft_statement['transaction_buffer_position'] = int(binascii.hexlify(bytearray(data[2:3]))) aft_statement['transfer_status'] = int(binascii.hexlify(bytearray(data[3:4]))) @@ -2008,52 +2198,77 @@ def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfe def AFT_get_last_transaction(self, **kwargs): cmd = [0x72, 0x02, 0xFF, 0x00] - data = self.__send_command(cmd, crc_need=True) + # time.sleep(SLEEP_IF_FORMAT_TRANSACTION) + data = self._send_command(cmd, crc_need=True, size=90) if (data <> None): - count = int(binascii.hexlify(data[26:27]), 16) - # print count try: + if self.aft_get_last_transaction == False: + raise ValueError + count = int(binascii.hexlify(data[26:27]), 16) transaction = binascii.hexlify(data[27:27 + count]) - count = 0 - tmp = [] - for i in range(len(transaction) / 2): - tmp.append(transaction[count:count + 2]) - count += 2 - tmp.reverse() - for i in range(len(tmp)): - if int(tmp[i], 16) >= 124: - tmp[i] = '20' - tmp[i + 1] = hex(int(tmp[i + 1], 16) + 1)[2:] - tmp.reverse() - response = '' - for i in tmp: - response += i - if response == '2121212121212121212121212121212121': - response = '2020202020202020202020202020202021' - self.transaction = int(response, 16) + if transaction == '2121212121212121212121212121212121': + transaction = '2020202020202020202020202020202021' + self.transaction = int(transaction, 16) return self.transaction - except: + except ValueError as e: + self.log.warning(e, exc_info=True) + self.transaction = int('2020202020202020202020202020202021', 16) + self.log.warning('AFT no transaction') + except Exception as e: + self.log.error(e, exc_info=True) self.transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') else: self.transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') - return self.transaction - def AFT_format_transaction(self, **kwargs): - self.AFT_get_last_transaction() + def AFT_format_transaction(self, get_from_emg=False, **kwargs): + if get_from_emg == True: + self.AFT_get_last_transaction() self.transaction += 1 - return hex(self.transaction)[2:-1] + transaction = hex(self.transaction)[2:-1] + count = 0 + tmp = [] + for i in range(len(transaction) / 2): + tmp.append(transaction[count:count + 2]) + count += 2 + tmp.reverse() + for i in range(len(tmp)): + if int(tmp[i], 16) >= 124: + tmp[i] = '20' + tmp[i + 1] = hex(int(tmp[i + 1], 16) + 1)[2:] + tmp.reverse() + response = '' + for i in tmp: + response += i + if response == '2121212121212121212121212121212121': + response = '2020202020202020202020202020202021' + self.transaction = int(response, 16) + return response def AFT_register_initial(self, **kwargs): - return self.AFT_register_gaming_machine(reg_code=0x01) + try: + return self.AFT_register_gaming_machine(reg_code=0x01) + except Exception as e: + self.log.error(e, exc_info=True) + return None def AFT_register(self, **kwargs): - return self.AFT_register_gaming_machine(reg_code=0x00) + return True + try: + return self.AFT_register_gaming_machine(reg_code=0x00) + except Exception as e: + self.log.error(e, exc_info=True) + return None def AFT_unregister(self, **kwargs): - return self.AFT_register_gaming_machine(reg_code=0x80) + return True + try: + return self.AFT_register_gaming_machine(reg_code=0x80) + except Exception as e: + self.log.error(e, exc_info=True) + return None def AFT_register_gaming_machine(self, reg_code=0xff, **kwargs): # 73 @@ -2069,7 +2284,7 @@ def AFT_register_gaming_machine(self, reg_code=0xff, **kwargs): for i in range(len(tmp) / 2): cmd.append(int(tmp[count:count + 2], 16)) count += 2 - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True, size=34) # data = None if (data <> None): aft_statement = {} @@ -2080,13 +2295,13 @@ def AFT_register_gaming_machine(self, reg_code=0xff, **kwargs): return aft_statement return None - def AFT_game_lock(self, lock_timeout=100, **kwargs): - return self.AFT_game_lock_and_status_request(lock_code=0x00, lock_timeout=lock_timeout) + def AFT_game_lock(self, lock_timeout=100, condition=00, **kwargs): + return self.AFT_game_lock_and_status_request(lock_code=0x00, lock_timeout=lock_timeout, transfer_condition=condition) def AFT_game_unlock(self, **kwargs): return self.AFT_game_lock_and_status_request(lock_code=0x80) - def AFT_game_lock_and_status_request(self, lock_code=0x00, transfer_condition=0b00000000, lock_timeout=0, **kwargs): + def AFT_game_lock_and_status_request(self, lock_code=0x00, transfer_condition=00, lock_timeout=0, **kwargs): # 74 cmd = [0x74] @@ -2095,7 +2310,7 @@ def AFT_game_lock_and_status_request(self, lock_code=0x00, transfer_condition=0b cmd.extend(self.bcd_coder_array(lock_timeout, 2)) # cmd.addend(0x23) - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True, size=40) if (data <> None): aft_statement = {} aft_statement['asset_number'] = str(binascii.hexlify(bytearray(data[2:6]))) @@ -2117,7 +2332,7 @@ def AFT_cansel_request(self, **kwargs): cmd = [0x72, 0x01, 0x80] self.AFT_register() response = None - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True, size=90) if (data <> None): a = int(binascii.hexlify(bytearray(data[26:27])), 16) response = { @@ -2133,8 +2348,15 @@ def AFT_cansel_request(self, **kwargs): 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) } - self.AFT_unregister() - return response + try: + self.AFT_unregister() + except: + self.log.warning('AFT UNREGISTER ERROR') + + if response['Transaction ID'] == hex(self.transaction)[2:-1]: + return response + # self.log.warning('NO CLEAN POLL: %s', response) + return False def AFT_reciept_data(self, **kwargs): # 75 @@ -2156,7 +2378,7 @@ def exnended_validation_status(self, control_mask=[0, 0], status_bits=[0, 0], ca # cmd.addend(0x23) - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): aft_statement['asset_number'] = str(binascii.hexlify(bytearray(data[2:6]))) aft_statement['status_bits'] = str(binascii.hexlify(bytearray(data[6:8]))) @@ -2177,7 +2399,7 @@ def set_ticket_data(self, **kwargs): def current_date_time(self, **kwargs): # 7E cmd = [0x7E] - data = self.__send_command(cmd, crc_need=False) + data = self._send_command(cmd, crc_need=False, size=11) if (data <> None): data = str(binascii.hexlify(bytearray(data[1:8]))) return datetime.datetime.strptime(data, '%m%d%Y%H%M%S') @@ -2192,10 +2414,10 @@ def recieve_date_time(self, dates, times, **kwargs): cmd.append(int(my_cmd[count:count + 2], 16)) count += 2 - if (self.__send_command(cmd, True, crc_need=True) == self.adress): + if (self._send_command(cmd, True, crc_need=True) == self.adress): return True - else: - return None + # else: + return None # return None def recieve_progressive_amount(self, **kwargs): @@ -2225,13 +2447,24 @@ def multiple_SAS_progresive_win_amounts(self, **kwargs): def initiate_legacy_bonus_pay(self, mony, tax='00', games=None, **kwargs): # 8A if games == None: - game_selected = self.selected_game_number() + for i in range(3): + try: + game_selected = self.selected_game_number(in_hex=False) + except: + game_selected = None + if game_selected == None: + time.sleep(0.04) + else: + break else: game_selected = games - if game_selected == 0: + if game_selected == None: return None - elif game_selected == None: + elif game_selected == 0: + return None + elif game_selected < 0: return None + cmd = str(int(round(mony / self.denom, 2))) # cmd = cmd.replace('.', '') cmd = '0' * (8 - len(cmd)) + cmd @@ -2241,10 +2474,10 @@ def initiate_legacy_bonus_pay(self, mony, tax='00', games=None, **kwargs): for i in range(len(my_cmd) / 2): cmd.append(int(my_cmd[count:count + 2], 16)) count += 2 - if (self.__send_command(cmd, True, crc_need=True) == self.adress): + if (self._send_command(cmd, True, crc_need=True) == self.adress): return True - else: - return None + # else: + return None # return None def initiate_multiplied_jackpot_mode(self, **kwargs): @@ -2270,10 +2503,10 @@ def legacy_bonus_win_info(self, **kwargs): def remote_handpay_reset(self, **kwargs): # 94 cmd = [0x94] - if (self.__send_command(cmd, True, crc_need=True) == self.adress): + if (self._send_command(cmd, True, crc_need=True) == self.adress): return True - else: - return None + # else: + return None # return def tournament_games_played(self, **kwargs): @@ -2301,19 +2534,19 @@ def legacy_bonus_meters(self, denom=True, n=0, **kwargs): cmd = [0x9A, ((n >> 8) & 0xFF), (n & 0xFF)] # cmd.extend([(n&0xFF), ((n>>8)&0xFF)]) # cmd=[0x19] - data = self.__send_command(cmd, crc_need=True) + data = self._send_command(cmd, crc_need=True, size=18) if (data <> None): meters = {} if denom == False: - meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:4]))) - meters['deductible'] = int(binascii.hexlify(bytearray(data[4:7]))) + meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:3]))) + meters['deductible'] = int(binascii.hexlify(bytearray(data[3:7]))) meters['non-deductible'] = int(binascii.hexlify(bytearray(data[7:11]))) meters['wager match'] = int(binascii.hexlify(bytearray(data[11:15]))) else: - meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:4]))) - meters['deductible'] = round(int(binascii.hexlify(bytearray(data[4:7]))) * self.denom, 2) + meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:3]))) + meters['deductible'] = round(int(binascii.hexlify(bytearray(data[3:7]))) * self.denom, 2) meters['non-deductible'] = round(int(binascii.hexlify(bytearray(data[7:11]))) * self.denom, 2) meters['wager match'] = round(int(binascii.hexlify(bytearray(data[11:15]))) * self.denom, 2) return meters @@ -2322,19 +2555,19 @@ def legacy_bonus_meters(self, denom=True, n=0, **kwargs): def stop_autorebet(self, **kwargs): # AA00 cmd = [0xAA, 0x00] - if (self.__send_command(cmd, True, crc_need=True) == self.adress): + if (self._send_command(cmd, True, crc_need=True) == self.adress): return True - else: - return None + # else: + return None # return def start_autorebet(self, **kwargs): # AA01 cmd = [0xAA, 0x01] - if (self.__send_command(cmd, True, crc_need=True) == self.adress): + if (self._send_command(cmd, True, crc_need=True) == self.adress): return True - else: - return None + # else: + return None # return def enabled_features(self, game_nimber=0, **kwargs): @@ -2343,7 +2576,7 @@ def enabled_features(self, game_nimber=0, **kwargs): cmd.extend(self.bcd_coder_array(game_nimber, 2)) - data = self.__send_command(cmd, True, crc_need=True) + data = self._send_command(cmd, True, crc_need=True) if (data <> None): aft_statement['game_number'] = str(binascii.hexlify(bytearray(data[1:3]))) aft_statement['features_1'] = data[3] @@ -2452,33 +2685,26 @@ def int_to_bcd(self, number=0, lenght=5, **kwargs): return result -class Sas_USB(Sas): - - def _conf_event_port(self): - # self.close() - self.connection.parity = serial.PARITY_NONE - self.connection.stopbits = serial.STOPBITS_TWO - # self.open() - - def _conf_port(self): - # self.close() - self.connection.parity = serial.PARITY_MARK - self.connection.stopbits = serial.STOPBITS_ONE - # self.open() +class SAS_USB(Sas): - def __send_command(self, command, no_response=False, timeout=None, crc_need=True): - if timeout == None: - timeout = self.timeout + 1 + def _send_command(self, command, no_response=False, timeout=None, crc_need=True, size=1): + # if timeout == None: + # timeout = self.timeout + 1 + # time.sleep(0.04) busy = True response = b'' + # self.my_log.flush() try: - if self.is_open() == False: - self.open() + # if self.poll_adres == '82': + # self.poll_adres = '80' + # else: + # self.poll_adres = '82' + buf_header = [self.adress] self._conf_port() - self.connection.write(("82" + self.mashin_n).decode("hex")) + # self.connection.write(('80' + self.mashin_n).decode("hex")) # self.close() - self.connection.parity = serial.PARITY_SPACE + # self.connection.parity = serial.PARITY_SPACE # self.open() buf_header.extend(command) @@ -2488,8 +2714,13 @@ def __send_command(self, command, no_response=False, timeout=None, crc_need=True crc = CRC16Kermit().calculate(str(bytearray(buf_header))) buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) self.log.debug(buf_header) - # cmd =self.change_cmd(buf_header[1:]) - # cmd = cmd.encode('hex'), 'my command' + # time.sleep(0.04) + self.connection.write([self.poll_adress, self.adress]) + # self.close() + self.connection.parity = serial.PARITY_SPACE + # self.open() + # my_log = open('/home/colibri/dump.log', 'w') + # self.my_log.write('TX %s: %s\n' % (time.time(), '82'+ binascii.hexlify(bytearray(buf_header)))) # print self.connection.portstr # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) self.connection.write((buf_header[1:])) @@ -2500,27 +2731,33 @@ def __send_command(self, command, no_response=False, timeout=None, crc_need=True try: buffer = [] # self.connection.flushInput() - - t = time.time() - while time.time() - t < timeout: - response += self.connection.read() - if no_response == True: + # time.sleep(0.04) + # t = time.time() + # while time.time() - t < timeout: + response = self.connection.read(size) + if no_response == True: + try: return int(binascii.hexlify(response)) - if (self.checkResponse(response) <> False): - break - - if time.time() - t >= timeout: - self.log.warning("sas timeout waiting response") - # buffer.append(response) - # print binascii.hexlify(bytearray(response)) - return None + except ValueError as e: + self.log.warning('no sas response %s' % (str(buf_header[1:]))) + return None + # else: + # # response += self.connection.read(size) + # if (self.checkResponse(response, size) <> False): + # break + # + # if time.time() - t >= timeout: + # self.log.warning("sas timeout") + # # buffer.append(response) + # # print binascii.hexlify(bytearray(response)) + # return None busy = False response = self.checkResponse(response) self.log.debug('sas response %s', binascii.hexlify(response)) if response == '': response = None - self.log.error('no sas response') + # self.log.info('no sas response') return response # return None except Exception as e: @@ -2529,21 +2766,10 @@ def __send_command(self, command, no_response=False, timeout=None, crc_need=True busy = False return None - -if __name__ == "__main__": - sas = Sas('/dev/ttyUSB0') +if __name__ == '__main__': + sas = Sas('/dev/ttyS1') print sas.start() - print 'denom %s' % (sas.gaming_machine_ID()) - # sas.AFT_get_last_transaction() - sas.AFT_register_initial() - - # print sas.AFT_in(mony=1, lock_timeout=0) - # print sas.AFT_out() - # print sas.AFT_clean_transaction_poll() - print sas.current_credits() - # print sas.AFT_cashout_enable() - # sas.AFT_get_last_transaction() - - # print sas.shutdown() - # print sas.startup() - + print sas.gaming_machine_ID() + print sas.AFT_get_last_transaction() + print sas.AFT_in(0.05) + print sas.AFT_clean_transaction_poll() From d2161a67085191f003e7a29ffd93f323871bf480 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Thu, 22 Feb 2024 18:16:45 +0200 Subject: [PATCH 03/11] Update sas.py python 3 --- sas.py | 1349 ++++++++++++++++++++++++++++++-------------------------- 1 file changed, 726 insertions(+), 623 deletions(-) diff --git a/sas.py b/sas.py index e770707..3686b16 100644 --- a/sas.py +++ b/sas.py @@ -1,9 +1,10 @@ -#!/usr/bin/python +#!/usr/bin/env python3 # -*- coding: utf8 -*- # import bcd import serial import time import binascii +import os # import string from PyCRC.CRC16Kermit import CRC16Kermit from array import array @@ -417,6 +418,10 @@ class BadCRC(Exception): pass +class BadCommand(Exception): + pass + + class AFTBadAmount(Exception): pass @@ -439,7 +444,7 @@ class EMGGpollBadResponse(Exception): class Sas(): - def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_transaction=True): + def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_transaction=True, sas_dump=False): # self.poll_adres = '82' self.adress = None self.mashin_n = None @@ -452,7 +457,13 @@ def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_tra self.transaction = None self.my_key = '44' self.poll_adress = poll_adress - #self.my_log = file('/home/colibri/dump.log', 'a') + self.sas_dump = sas_dump + self.timeout = timeout + if self.sas_dump: + os.system('sudo touch /var/log/sas_dump.log') + os.system('sudo chown colibri:colibri /var/log/sas_dump.log') + self.my_log = open('/var/log/sas_dump.log', 'w') + self.my_log.close() if log == None: self.log = log_to_stderr() self.log.setLevel(logging.INFO) @@ -460,10 +471,8 @@ def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_tra self.log = log while 1: try: - # print 1 self.connection = serial.Serial(port=port, baudrate=19200, timeout=timeout) self.close() - self.timeout = timeout self.log.info('SAS Port OK!') break except: @@ -474,15 +483,41 @@ def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_tra def is_open(self): return self.connection.isOpen() + def clean_buffer(self): + try: + if self.is_open() == False: + self.open() + self.connection.reset_output_buffer() + self.connection.reset_output_buffer() + except Exception as e: + self.log.error(e, exc_info=True) + self.close() + def flush(self): try: if self.is_open() == False: self.open() - self.connection.flushOutput() + self.connection.flush() + except Exception as e: + self.log.error(e, exc_info=True) + + def flushInput(self): + try: + if self.is_open() == False: + self.open() self.connection.flushInput() except Exception as e: self.log.error(e, exc_info=True) - self.close() + # self.close() + + def flushOutput(self): + try: + if self.is_open() == False: + self.open() + self.connection.flushOutput() + except Exception as e: + self.log.error(e, exc_info=True) + # self.close() def start(self): self.log.info('Connecting SAS...') @@ -498,16 +533,16 @@ def start(self): except Exception as e: self.log.critical(e, exc_info=True) else: - self.connection.flushOutput() - self.connection.flushInput() + self.flush() + # self.flushInput() response = self.connection.read(1) if response == None: self.log.error('No SAS Connection') time.sleep(1) - if response != '': + if response: self.adress = int(binascii.hexlify(response)) # if self.adress >= 1: - self.mashin_n = response.encode('HEX') + self.mashin_n = response.hex() self.log.info('adress recognised ' + str(self.adress)) break else: @@ -522,7 +557,8 @@ def close(self): def open(self): try: - self.connection.open() + if self.connection.isOpen() is not True: + self.connection.open() except: raise SASOpenError @@ -532,6 +568,7 @@ def _conf_event_port(self): self.connection.parity = serial.PARITY_NONE self.connection.stopbits = serial.STOPBITS_TWO self.open() + # self.clean_buffer() def _conf_port(self): self.close() @@ -572,7 +609,7 @@ def crc(self, response, chk=False, seed=0): if data == crc: return True else: - raise BadCRC, response + raise BadCRC(response) return data def _send_command(self, command, no_response=False, timeout=None, crc_need=True, size=1): @@ -582,7 +619,7 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # time.sleep(0.04) busy = True response = b'' - #self.my_log.flush() + # self.my_log.flush() try: # if self.poll_adres == '82': # self.poll_adres = '80' @@ -590,6 +627,11 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # self.poll_adres = '82' buf_header = [self.adress] + if self.sas_dump: + self.my_log = open('/var/log/sas_dump.log', 'a') + self.my_log.write('TX %s: %s\n' % (time.time(), '82'+ binascii.hexlify(bytearray(buf_header)))) + self.my_log.close() + # self.flush() self._conf_port() # self.connection.flushInput() # self.connection.write(('80' + self.mashin_n).decode("hex")) @@ -599,94 +641,114 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, buf_header.extend(command) buf_count = len(command) - # buf_header[2]=buf_count+2 if (crc_need == True): - crc = CRC16Kermit().calculate(str(bytearray(buf_header))) + crc = CRC16Kermit().calculate(bytes(buf_header)) buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) self.log.debug(buf_header) - #time.sleep(0.04) + + # buf_header[2]=buf_count+2 + self.connection.write([self.poll_adress, self.adress]) - self.close() + self.flush() self.connection.parity = serial.PARITY_SPACE - self.open() + # self.open() # self.connection.flushInput() - #my_log = open('/home/colibri/dump.log', 'w') - #self.my_log.write('TX %s: %s\n' % (time.time(), '82'+ binascii.hexlify(bytearray(buf_header)))) + # my_log = open('/home/colibri/dump.log', 'w') + + # self.my_log = open('/var/log/sas_dump.log', 'w') # print self.connection.portstr # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) - self.connection.write((buf_header[1:])) + self.connection.write(buf_header[1:]) except Exception as e: self.log.error(e, exc_info=True) try: buffer = [] - # self.connection.flushInput() - # time.sleep(0.04) # t = time.time() - # while time.time() - t < timeout: + # while time.time() - t < self.timeout: + # response += self.connection.read() + # if len(response) == size: + # break + self.flushInput() response = self.connection.read(size) if no_response == True: try: + # raise KeyError(response) return int(binascii.hexlify(response)) except ValueError as e: self.log.warning('no sas response %s' % (str(buf_header[1:]))) return None + # else: + # # response += self.connection.read(size) + # if (self.checkResponse(response, size) is False): + # break + # + # if time.time() - t >= timeout: + # self.log.warning("sas timeout") + # # buffer.append(response) + # # print response)) + # return None busy = False - response = self.checkResponse(response) + self.flushInput() + response = self.checkResponse(response, binascii.hexlify(bytearray(buf_header))) self.log.debug('sas response %s', binascii.hexlify(response)) + if not response: + response = None + # self.log.info('no sas response') return response - except BadCRC as e: - raise e + # return None except Exception as e: - self.log.info(e, exc_info=True) + self.log.error(e, exc_info=True) busy = False return None - def checkResponse(self, rsp): - if (rsp == ''): + def checkResponse(self, rsp, cmd): + if not rsp: # self.flush() # self.close() - raise NoSasConnection - # return False - - resp = bytearray(rsp) + raise NoSasConnection(cmd) + # if self.crc(rsp.hex(), True): + # return rsp[1:-2] + # raise BadCRC(rsp) + resp = rsp # print resp - # if (resp[0] <> self.adress): + # if (resp[0] is self.adress): # self.log.error("wrong ardess or NACK") # raise BadCRC - CRC = binascii.hexlify(resp[-2:]) + CRC = resp.hex()[-4:] command = resp[0:-2] - crc1 = CRC16Kermit().calculate(str(bytearray(command))) + crc1 = CRC16Kermit().calculate(bytes(command)) data = resp[1:-2] crc1 = hex(crc1).split('x')[-1] - - while len(crc1) < 4: - crc1 = "0" + crc1 - - # print crc1 - # print CRC + crc1 = crc1.zfill(4) + # while len(crc1) < 4: + # crc1 = "0" + crc1 + + if self.sas_dump: + self.my_log = open('/var/log/sas_dump.log', 'a') + self.my_log.write('RX %s: %s\n' % (time.time(), binascii.hexlify(resp))) + self.my_log.close() if (CRC != crc1): # print "Wrong response command hash " + str(CRC) # print "////" + str(hex(crc1).split('x')[-1]) - # print "////" + str(binascii.hexlify(command)) - raise BadCRC, binascii.hexlify(resp) - # return False + # print "////" + str(self.hexlify(command)) + raise BadCRC(self.hexlify(self.bytearray(resp))) + # return False elif CRC == crc1: - #self.my_log.write('RX %s: %s\n' % (time.time(), binascii.hexlify(resp))) return data - raise BadCRC, binascii.hexlify(resp) + # raise BadCRC(self.hexlify(resp)) ## def check_crc(self): ## cmd=[0x01, 0x50, 0x81] - ## cmd=bytearray(cmd) + ## cmd=self.bytearray(cmd) ## #print self.sas_CRC([0x01, 0x50, 0x81]) ## #print ('\\'+'\\'.join(hex(e)[1:] for e in cmd)) ## @@ -696,7 +758,7 @@ def checkResponse(self, rsp): def events_poll(self, timeout=EVENTS_POLL_TIMEOUT, **kwargs): self._conf_event_port() event = '' - #self.my_log.write('TX %s: %s\n' % (time.time(), '8281')) + # self.my_log.write('TX %s: %s\n' % (time.time(), '8281')) # time.sleep(0.04) cmd = [0x80 + self.adress] self.connection.write([self.poll_adress]) @@ -712,9 +774,9 @@ def events_poll(self, timeout=EVENTS_POLL_TIMEOUT, **kwargs): raise NoSasConnection # event = None # return None - #self.my_log.write('RX %s: %s\n' % (time.time(), event.encode('hex'))) - #self.my_log.flush() - event = GPOLL[event.encode('hex')] + # self.my_log.write('RX %s: %s\n' % (time.time(), event.encode('hex'))) + # self.my_log.flush() + event = GPOLL[event.hex()] except KeyError as e: raise EMGGpollBadResponse except Exception as e: @@ -806,7 +868,7 @@ def en_dis_game(self, game_number=None, en_dis=False, **kwargs): cmd = [0x09] cmd.extend([((game >> 8) & 0xFF), (game & 0xFF)]) - cmd.extend(bytearray(en_dis)) + cmd.extend(self.bytearray(en_dis)) # print cmd if (self._send_command(cmd, True, crc_need=True) == self.adress): return game_number @@ -837,7 +899,7 @@ def en_dis_rt_event_reporting(self, enable=False, **kwargs): else: enable = [1] cmd = [0x0E] - cmd.extend(bytearray(enable)) + cmd.extend(self.bytearray(enable)) if (self._send_command(cmd, True, crc_need=True) == self.adress): return True # else: @@ -847,22 +909,23 @@ def en_dis_rt_event_reporting(self, enable=False, **kwargs): def send_meters_10_15(self, denom=True, **kwargs): cmd = [0x0f] data = self._send_command(cmd, crc_need=False, size=28) - if (data <> None): + if (data is not None): meters = {} if denom == True: - meters['total_cancelled_credits_meter'] = round(int((binascii.hexlify(bytearray(data[1:5])))) * self.denom, 2) - meters['total_in_meter'] = round(int(binascii.hexlify(bytearray(data[5:9]))) * self.denom, 2) - meters['total_out_meter'] = round(int(binascii.hexlify(bytearray(data[9:13]))) * self.denom, 2) - meters['total_droup_meter'] = round(int(binascii.hexlify(bytearray(data[13:17]))) * self.denom, 2) - meters['total_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[17:21]))) * self.denom, 2) - meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) + meters['total_cancelled_credits_meter'] = round( + int((self.hexlify(self.bytearray(data[1:5])))) * self.denom, 2) + meters['total_in_meter'] = round(int(self.hexlify(self.bytearray(data[5:9]))) * self.denom, 2) + meters['total_out_meter'] = round(int(self.hexlify(self.bytearray(data[9:13]))) * self.denom, 2) + meters['total_droup_meter'] = round(int(self.hexlify(self.bytearray(data[13:17]))) * self.denom, 2) + meters['total_jackpot_meter'] = round(int(self.hexlify(self.bytearray(data[17:21]))) * self.denom, 2) + meters['games_played_meter'] = int(self.hexlify(self.bytearray(data[21:25]))) else: - meters['total_cancelled_credits_meter'] = int((binascii.hexlify(bytearray(data[1:5])))) - meters['total_in_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) - meters['total_out_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) - meters['total_droup_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) - meters['total_jackpot_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) - meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) + meters['total_cancelled_credits_meter'] = int((self.hexlify(self.bytearray(data[1:5])))) + meters['total_in_meter'] = int(self.hexlify(self.bytearray(data[5:9]))) + meters['total_out_meter'] = int(self.hexlify(self.bytearray(data[9:13]))) + meters['total_droup_meter'] = int(self.hexlify(self.bytearray(data[13:17]))) + meters['total_jackpot_meter'] = int(self.hexlify(self.bytearray(data[17:21]))) + meters['games_played_meter'] = int(self.hexlify(self.bytearray(data[21:25]))) return meters return None @@ -870,92 +933,92 @@ def total_cancelled_credits(self, denom=True, **kwargs): # 10 cmd = [0x10] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): if denom == True: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) else: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) return None def total_bet_meter(self, denom=True, **kwargs): # 11 cmd = [0x11] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): if denom == True: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) else: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) return None def total_win_meter(self, denom=True, **kwargs): # 12 cmd = [0x12] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): if denom == True: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) else: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) return None def total_in_meter(self, denom=True, **kwargs): # 13 cmd = [0x13] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): if denom == True: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) else: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) return None def total_jackpot_meter(self, denom=True, **kwargs): # 14 cmd = [0x14] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): if denom == True: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) else: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) return None def games_played_meter(self, **kwargs): # 15 cmd = [0x15] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def games_won_meter(self, denom=True, **kwargs): # 16 cmd = [0x16] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): if denom == True: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) else: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) return None def games_lost_meter(self, **kwargs): # 17 cmd = [0x17] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def games_powerup_door_opened(self, **kwargs): # 18 cmd = [0x18] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): meters = {} - meters['games_last_power_up'] = int(binascii.hexlify(bytearray(data[1:3]))) - meters['games_last_slot_door_close'] = int(binascii.hexlify(bytearray(data[1:5]))) + meters['games_last_power_up'] = int(self.hexlify(self.bytearray(data[1:3]))) + meters['games_last_slot_door_close'] = int(self.hexlify(self.bytearray(data[1:5]))) return data return None @@ -964,20 +1027,20 @@ def meters_11_15(self, denom=True, **kwargs): # 19 cmd = [0x19] data = self._send_command(cmd, crc_need=False, size=24) - if (data <> None): + if (data is not None): meters = {} if denom == False: - meters['total_bet_meter'] = int(binascii.hexlify(bytearray(data[1:5]))) - meters['total_win_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) - meters['total_in_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) - meters['total_jackpot_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) - meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + meters['total_bet_meter'] = int(self.hexlify(self.bytearray(data[1:5]))) + meters['total_win_meter'] = int(self.hexlify(self.bytearray(data[5:9]))) + meters['total_in_meter'] = int(self.hexlify(self.bytearray(data[9:13]))) + meters['total_jackpot_meter'] = int(self.hexlify(self.bytearray(data[13:17]))) + meters['games_played_meter'] = int(self.hexlify(self.bytearray(data[17:21]))) else: - meters['total_bet_meter'] = round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) - meters['total_win_meter'] = round(int(binascii.hexlify(bytearray(data[5:9]))) * self.denom, 2) - meters['total_in_meter'] = round(int(binascii.hexlify(bytearray(data[9:13]))) * self.denom, 2) - meters['total_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[13:17]))) * self.denom, 2) - meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) + meters['total_bet_meter'] = round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) + meters['total_win_meter'] = round(int(self.hexlify(self.bytearray(data[5:9]))) * self.denom, 2) + meters['total_in_meter'] = round(int(self.hexlify(self.bytearray(data[9:13]))) * self.denom, 2) + meters['total_jackpot_meter'] = round(int(self.hexlify(self.bytearray(data[13:17]))) * self.denom, 2) + meters['games_played_meter'] = int(self.hexlify(self.bytearray(data[17:21]))) return meters return None @@ -985,23 +1048,23 @@ def current_credits(self, denom=True, **kwargs): # 1A cmd = [0x1A] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): + if (data is not None): if denom == True: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) else: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) return None def handpay_info(self, **kwargs): # 1B cmd = [0x1B] data = self._send_command(cmd, crc_need=False) - if (data <> None): + if (data is not None): meters = {} - meters['bin_progressive_group'] = int(binascii.hexlify(bytearray(data[1:2]))) - meters['bin_level'] = int(binascii.hexlify(bytearray(data[2:3]))) - meters['amount'] = int(binascii.hexlify(bytearray(data[3:8]))) - meters['bin_reset_ID'] = int(binascii.hexlify(bytearray(data[8:]))) + meters['bin_progressive_group'] = int(self.hexlify(self.bytearray(data[1:2]))) + meters['bin_level'] = int(self.hexlify(self.bytearray(data[2:3]))) + meters['amount'] = int(self.hexlify(self.bytearray(data[3:8]))) + meters['bin_reset_ID'] = int(self.hexlify(self.bytearray(data[8:]))) return meters return None @@ -1009,26 +1072,26 @@ def meters(self, denom=True, **kwargs): # 1C cmd = [0x1C] data = self._send_command(cmd, crc_need=False, size=36) - if (data <> None): + if (data is not None): meters = {} if denom == False: - meters['total_bet_meter'] = int(binascii.hexlify(bytearray(data[1:5]))) - meters['total_win_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) - meters['total_in_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) - meters['total_jackpot_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) - meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) - meters['games_won_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) - meters['slot_door_opened_meter'] = int(binascii.hexlify(bytearray(data[25:29]))) - meters['power_reset_meter'] = int(binascii.hexlify(bytearray(data[29:33]))) + meters['total_bet_meter'] = int(self.hexlify(self.bytearray(data[1:5]))) + meters['total_win_meter'] = int(self.hexlify(self.bytearray(data[5:9]))) + meters['total_in_meter'] = int(self.hexlify(self.bytearray(data[9:13]))) + meters['total_jackpot_meter'] = int(self.hexlify(self.bytearray(data[13:17]))) + meters['games_played_meter'] = int(self.hexlify(self.bytearray(data[17:21]))) + meters['games_won_meter'] = int(self.hexlify(self.bytearray(data[21:25]))) + meters['slot_door_opened_meter'] = int(self.hexlify(self.bytearray(data[25:29]))) + meters['power_reset_meter'] = int(self.hexlify(self.bytearray(data[29:33]))) else: - meters['total_bet_meter'] = round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) - meters['total_win_meter'] = round(int(binascii.hexlify(bytearray(data[5:9]))) * self.denom, 2) - meters['total_in_meter'] = round(int(binascii.hexlify(bytearray(data[9:13]))) * self.denom, 2) - meters['total_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[13:17]))) * self.denom, 2) - meters['games_played_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) - meters['games_won_meter'] = round(int(binascii.hexlify(bytearray(data[21:25]))) * self.denom, 2) - meters['slot_door_opened_meter'] = int(binascii.hexlify(bytearray(data[25:29]))) - meters['power_reset_meter'] = int(binascii.hexlify(bytearray(data[29:33]))) + meters['total_bet_meter'] = round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) + meters['total_win_meter'] = round(int(self.hexlify(self.bytearray(data[5:9]))) * self.denom, 2) + meters['total_in_meter'] = round(int(self.hexlify(self.bytearray(data[9:13]))) * self.denom, 2) + meters['total_jackpot_meter'] = round(int(self.hexlify(self.bytearray(data[13:17]))) * self.denom, 2) + meters['games_played_meter'] = int(self.hexlify(self.bytearray(data[17:21]))) + meters['games_won_meter'] = round(int(self.hexlify(self.bytearray(data[21:25]))) * self.denom, 2) + meters['slot_door_opened_meter'] = int(self.hexlify(self.bytearray(data[25:29]))) + meters['power_reset_meter'] = int(self.hexlify(self.bytearray(data[29:33]))) return meters return None @@ -1037,14 +1100,14 @@ def total_bill_meters(self, **kwargs): # 1E cmd = [0x1E] data = self._send_command(cmd, crc_need=False, size=28) - if (data <> None): + if (data is not None): meters = {} - meters['s1_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[1:5]))) - meters['s5_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[5:9]))) - meters['s10_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[9:13]))) - meters['s20_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[13:17]))) - meters['s50_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[17:21]))) - meters['s100_bills_accepted_meter'] = int(binascii.hexlify(bytearray(data[21:25]))) + meters['s1_bills_accepted_meter'] = int(self.hexlify(self.bytearray(data[1:5]))) + meters['s5_bills_accepted_meter'] = int(self.hexlify(self.bytearray(data[5:9]))) + meters['s10_bills_accepted_meter'] = int(self.hexlify(self.bytearray(data[9:13]))) + meters['s20_bills_accepted_meter'] = int(self.hexlify(self.bytearray(data[13:17]))) + meters['s50_bills_accepted_meter'] = int(self.hexlify(self.bytearray(data[17:21]))) + meters['s100_bills_accepted_meter'] = int(self.hexlify(self.bytearray(data[21:25]))) return meters return None @@ -1053,17 +1116,17 @@ def gaming_machine_ID(self, **kwargs): # 1F cmd = [0x1F] data = self._send_command(cmd, crc_need=False, size=24) - if (data <> None): - denom = DENOMINATION[binascii.hexlify(bytearray(data[6:7]))] + if (data is not None): + denom = DENOMINATION[self.hexlify(self.bytearray(data[6:7]))] self.log.info('addenomination recognised ' + str(denom)) self.denom = denom return denom # meters['ASCII_game_ID']=(((data[1:3]))) # meters['ASCII_additional_ID']=(((data[3:6]))) - # meters['bin_denomination']=int(binascii.hexlify(bytearray(data[4:5]))) - # meters['bin_max_bet']=(binascii.hexlify(bytearray(data[7:8]))) - # meters['bin_progressive_mode']=int(binascii.hexlify(bytearray(data[8:9]))) - # meters['bin_game_options']=(binascii.hexlify(bytearray(data[9:11]))) + # meters['bin_denomination']=int(self.hexlify(self.bytearray(data[4:5]))) + # meters['bin_max_bet']=(self.hexlify(self.bytearray(data[7:8]))) + # meters['bin_progressive_mode']=int(self.hexlify(self.bytearray(data[8:9]))) + # meters['bin_game_options']=(self.hexlify(self.bytearray(data[9:11]))) # meters['ASCII_paytable_ID']=(((data[11:17]))) # meters['ASCII_base_percentage']=(((data[17:21]))) @@ -1076,8 +1139,8 @@ def total_dollar_value_of_bills_meter(self, **kwargs): cmd = [0x20] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:]))) return None @@ -1086,8 +1149,8 @@ def ROM_signature_verification(self, **kwargs): cmd = [0x21, 0x00, 0x00] data = self._send_command(cmd, crc_need=True) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:3]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:3]))) return None def eft_button_pressed(self, state=0, **kwargs): @@ -1096,7 +1159,7 @@ def eft_button_pressed(self, state=0, **kwargs): cmd.append(state) data = self._send_command(cmd, crc_need=True) - if (data <> None): + if (data is not None): return data return None @@ -1104,38 +1167,38 @@ def true_coin_in(self, denom=True, **kwargs): # 2A cmd = [0x2A] data = self._send_command(cmd, crc_need=False) - if (data <> None): + if (data is not None): if denom == False: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) else: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) return None def true_coin_out(self, denom=True, **kwargs): # 2B cmd = [0x2B] data = self._send_command(cmd, crc_need=False) - if (data <> None): + if (data is not None): if denom == False: - return int(binascii.hexlify(bytearray(data[1:5]))) + return int(self.hexlify(self.bytearray(data[1:5]))) else: - return round(int(binascii.hexlify(bytearray(data[1:5]))) * self.denom, 2) + return round(int(self.hexlify(self.bytearray(data[1:5]))) * self.denom, 2) return None def curr_hopper_level(self, **kwargs): # 2C cmd = [0x2C] data = self._send_command(cmd, crc_need=False) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def total_hand_paid_cancelled_credit(self, **kwargs): # 2D cmd = [0x2D] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def delay_game(self, delay_time=100, **kwargs): @@ -1145,7 +1208,7 @@ def delay_game(self, delay_time=100, **kwargs): delay = '' + ('0' * (4 - len(delay_time)) + delay_time) cmd = [0x2E] count = 0 - for i in range(len(delay) / 2): + for i in range(int(len(delay) / 2)): cmd.append(int(delay[count:count + 2], 16)) count += 2 if self._send_command(cmd, True, crc_need=True) == self.adress: @@ -1164,106 +1227,106 @@ def send_1_bills_in_meters(self, **kwargs): # 31 cmd = [0x31] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_2_bills_in_meters(self, **kwargs): # 32 cmd = [0x32] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_5_bills_in_meters(self, **kwargs): # 33 cmd = [0x33] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_10_bills_in_meters(self, **kwargs): # 34 cmd = [0x34] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_20_bills_in_meters(self, **kwargs): # 35 cmd = [0x35] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_50_bills_in_meters(self, **kwargs): # 36 cmd = [0x36] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_100_bills_in_meters(self, **kwargs): # 37 cmd = [0x37] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_500_bills_in_meters(self, **kwargs): # 38 cmd = [0x38] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_1000_bills_in_meters(self, **kwargs): # 39 cmd = [0x39] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_200_bills_in_meters(self, **kwargs): # 3A cmd = [0x3a] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_25_bills_in_meters(self, **kwargs): # 3B cmd = [0x3B] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_2000_bills_in_meters(self, **kwargs): # 3C cmd = [0x3C] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def cash_out_ticket_info(self, **kwargs): # 3D cmd = [0x3D] data = self._send_command(cmd, crc_need=False) - if (data <> None): + if (data is not None): tito_statement = {} - tito_statement['cashout_ticket_number'] = int(binascii.hexlify(bytearray(data[1:3]))) - tito_statement['cashout_amount_in_cents'] = int(binascii.hexlify(bytearray(data[3:]))) + tito_statement['cashout_ticket_number'] = int(self.hexlify(self.bytearray(data[1:3]))) + tito_statement['cashout_amount_in_cents'] = int(self.hexlify(self.bytearray(data[3:]))) return tito_statement return None @@ -1271,91 +1334,91 @@ def send_2500_bills_in_meters(self, **kwargs): # 3E cmd = [0x3E] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_5000_bills_in_meters(self, **kwargs): # 3F cmd = [0x3F] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_10000_bills_in_meters(self, **kwargs): # 40 cmd = [0x40] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_20000_bills_in_meters(self, **kwargs): # 41 cmd = [0x41] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_25000_bills_in_meters(self, **kwargs): # 42 cmd = [0x42] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_50000_bills_in_meters(self, **kwargs): # 43 cmd = [0x43] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_100000_bills_in_meters(self, **kwargs): # 44 cmd = [0x44] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def send_250_bills_in_meters(self, **kwargs): # 45 cmd = [0x45] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def credit_amount_of_all_bills_accepted(self, **kwargs): # 46 cmd = [0x46] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def coin_amount_accepted_from_external_coin_acceptor(self, **kwargs): # 47 cmd = [0x47] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def last_accepted_bill_info(self, **kwargs): # 48 cmd = [0x48] data = self._send_command(cmd, crc_need=False) - if (data <> None): + if (data is not None): meters = {} - meters['country_code'] = int(binascii.hexlify(bytearray(data[1:2]))) - meters['bill_denomination'] = int(binascii.hexlify(bytearray(data[2:3]))) - meters['meter_for_accepted_bills'] = int(binascii.hexlify(bytearray(data[3:6]))) + meters['country_code'] = int(self.hexlify(self.bytearray(data[1:2]))) + meters['bill_denomination'] = int(self.hexlify(self.bytearray(data[2:3]))) + meters['meter_for_accepted_bills'] = int(self.hexlify(self.bytearray(data[3:6]))) return meters return None @@ -1363,16 +1426,16 @@ def number_of_bills_currently_in_stacker(self, **kwargs): # 49 cmd = [0x49] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def total_credit_amount_of_all_bills_in_stacker(self, **kwargs): # 4A cmd = [0x49] data = self._send_command(cmd, crc_need=False, size=8) - if (data <> None): - return int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + return int(self.hexlify(self.bytearray(data[1:5]))) return None def set_secure_enhanced_validation_ID(self, MachineID=[0x01, 0x01, 0x01], seq_num=[0x00, 0x00, 0x01], **kwargs): @@ -1382,12 +1445,12 @@ def set_secure_enhanced_validation_ID(self, MachineID=[0x01, 0x01, 0x01], seq_nu cmd.extend(MachineID) cmd.extend(seq_num) - cmd = bytearray(cmd) - # print str(binascii.hexlify((cmd))) + cmd = self.bytearray(cmd) + # print str(self.hexlify((cmd))) data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - tito_statement['machine_ID'] = int(binascii.hexlify(bytearray(data[1:4]))) - tito_statement['sequence_number'] = int(binascii.hexlify(bytearray(data[4:8]))) + if (data is not None): + tito_statement['machine_ID'] = int(self.hexlify(self.bytearray(data[1:4]))) + tito_statement['sequence_number'] = int(self.hexlify(self.bytearray(data[4:8]))) return data return None @@ -1399,20 +1462,20 @@ def enhanced_validation_information(self, curr_validation_info=0, **kwargs): # cmd.append(transfer_code) # cmd=cmd.extend(0) - # rint str(binascii.hexlify(bytearray(cmd))) + # rint str(self.hexlify(self.bytearray(cmd))) cmd.append((curr_validation_info)) data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - tito_statement['validation_type'] = int(binascii.hexlify(bytearray(data[1:2]))) - tito_statement['index_number'] = int(binascii.hexlify(bytearray(data[2:3]))) - tito_statement['date_validation_operation'] = str(binascii.hexlify(bytearray(data[3:7]))) - tito_statement['time_validation_operation'] = str(binascii.hexlify(bytearray(data[7:10]))) - tito_statement['validation_number'] = str(binascii.hexlify(bytearray(data[10:18]))) - tito_statement['ticket_amount'] = int(binascii.hexlify(bytearray(data[18:23]))) - tito_statement['ticket_number'] = int(binascii.hexlify(bytearray(data[23:25]))) - tito_statement['validation_system_ID'] = int(binascii.hexlify(bytearray(data[25:26]))) - tito_statement['expiration_date_printed_on_ticket'] = str(binascii.hexlify(bytearray(data[26:30]))) - tito_statement['pool_id'] = int(binascii.hexlify(bytearray(data[30:32]))) + if (data is not None): + tito_statement['validation_type'] = int(self.hexlify(self.bytearray(data[1:2]))) + tito_statement['index_number'] = int(self.hexlify(self.bytearray(data[2:3]))) + tito_statement['date_validation_operation'] = str(self.hexlify(self.bytearray(data[3:7]))) + tito_statement['time_validation_operation'] = str(self.hexlify(self.bytearray(data[7:10]))) + tito_statement['validation_number'] = str(self.hexlify(self.bytearray(data[10:18]))) + tito_statement['ticket_amount'] = int(self.hexlify(self.bytearray(data[18:23]))) + tito_statement['ticket_number'] = int(self.hexlify(self.bytearray(data[23:25]))) + tito_statement['validation_system_ID'] = int(self.hexlify(self.bytearray(data[25:26]))) + tito_statement['expiration_date_printed_on_ticket'] = str(self.hexlify(self.bytearray(data[26:30]))) + tito_statement['pool_id'] = int(self.hexlify(self.bytearray(data[30:32]))) return data return None @@ -1424,11 +1487,11 @@ def current_hopper_status(self, **kwargs): cmd = [0x4F] data = self._send_command(cmd, True, crc_need=False) - if (data <> None): - meters['current_hopper_lenght'] = int(binascii.hexlify(bytearray(data[1:2]))) - meters['current_hopper_ststus'] = int(binascii.hexlify(bytearray(data[2:3]))) - meters['current_hopper_percent_full'] = int(binascii.hexlify(bytearray(data[3:4]))) - meters['current_hopper_level'] = int(binascii.hexlify(bytearray(data[4:]))) + if (data is not None): + meters['current_hopper_lenght'] = int(self.hexlify(self.bytearray(data[1:2]))) + meters['current_hopper_ststus'] = int(self.hexlify(self.bytearray(data[2:3]))) + meters['current_hopper_percent_full'] = int(self.hexlify(self.bytearray(data[3:4]))) + meters['current_hopper_level'] = int(self.hexlify(self.bytearray(data[4:]))) return data return None @@ -1438,10 +1501,10 @@ def validation_meters(self, type_of_validation=0x00, **kwargs): cmd = [0x50] cmd.append(type_of_validation) data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - meters['bin_validation_type'] = int(binascii.hexlify(bytearray(data[1]))) - meters['total_validations'] = int(binascii.hexlify(bytearray(data[2:6]))) - meters['cumulative_amount'] = str(binascii.hexlify(bytearray(data[6:]))) + if (data is not None): + meters['bin_validation_type'] = int(self.hexlify(self.bytearray(data[1]))) + meters['total_validations'] = int(self.hexlify(self.bytearray(data[2:6]))) + meters['cumulative_amount'] = str(self.hexlify(self.bytearray(data[6:]))) return data return None @@ -1451,8 +1514,8 @@ def total_number_of_games_impimented(self, **kwargs): cmd = [0x51] # cmd.extend(type_of_validation) data = self._send_command(cmd, crc_need=False, size=6) - if (data <> None): - return str(binascii.hexlify(bytearray(data[1:]))) + if (data is not None): + return str(self.hexlify(self.bytearray(data[1:]))) return None def game_meters(self, n=None, denom=True, **kwargs): @@ -1463,20 +1526,20 @@ def game_meters(self, n=None, denom=True, **kwargs): cmd.extend([((n >> 8) & 0xFF), (n & 0xFF)]) data = self._send_command(cmd, crc_need=True, size=22) - if (data <> None): + if (data is not None): meters = {} if denom == False: - meters['game_n_number'] = str(binascii.hexlify(bytearray(data[1:3]))) - meters['game_n_coin_in_meter'] = int(binascii.hexlify(bytearray(data[3:7]))) - meters['game_n_coin_out_meter'] = int(binascii.hexlify(bytearray(data[7:11]))) - meters['game_n_jackpot_meter'] = int(binascii.hexlify(bytearray(data[11:15]))) - meters['geme_n_games_played_meter'] = int(binascii.hexlify(bytearray(data[15:]))) + meters['game_n_number'] = str(self.hexlify(self.bytearray(data[1:3]))) + meters['game_n_coin_in_meter'] = int(self.hexlify(self.bytearray(data[3:7]))) + meters['game_n_coin_out_meter'] = int(self.hexlify(self.bytearray(data[7:11]))) + meters['game_n_jackpot_meter'] = int(self.hexlify(self.bytearray(data[11:15]))) + meters['geme_n_games_played_meter'] = int(self.hexlify(self.bytearray(data[15:]))) else: - meters['game_n_number'] = str(binascii.hexlify(bytearray(data[1:3]))) - meters['game_n_coin_in_meter'] = round(int(binascii.hexlify(bytearray(data[3:7]))) * self.denom, 2) - meters['game_n_coin_out_meter'] = round(int(binascii.hexlify(bytearray(data[7:11]))) * self.denom, 2) - meters['game_n_jackpot_meter'] = round(int(binascii.hexlify(bytearray(data[11:15]))) * self.denom, 2) - meters['geme_n_games_played_meter'] = int(binascii.hexlify(bytearray(data[15:]))) + meters['game_n_number'] = str(self.hexlify(self.bytearray(data[1:3]))) + meters['game_n_coin_in_meter'] = round(int(self.hexlify(self.bytearray(data[3:7]))) * self.denom, 2) + meters['game_n_coin_out_meter'] = round(int(self.hexlify(self.bytearray(data[7:11]))) * self.denom, 2) + meters['game_n_jackpot_meter'] = round(int(self.hexlify(self.bytearray(data[11:15]))) * self.denom, 2) + meters['geme_n_games_played_meter'] = int(self.hexlify(self.bytearray(data[15:]))) return meters return None @@ -1489,15 +1552,15 @@ def game_configuration(self, n=None, **kwargs): cmd.extend([(n & 0xFF), ((n >> 8) & 0xFF)]) data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - meters['game_n_number_config'] = int(binascii.hexlify(bytearray(data[1:3]))) - meters['game_n_ASCII_game_ID'] = str(binascii.hexlify(bytearray(data[3:5]))) - meters['game_n_ASCII_additional_id'] = str(binascii.hexlify(bytearray(data[5:7]))) - meters['game_n_bin_denomination'] = str(binascii.hexlify(bytearray(data[7]))) - meters['game_n_bin_progressive_group'] = str(binascii.hexlify(bytearray(data[8]))) - meters['game_n_bin_game_options'] = str(binascii.hexlify(bytearray(data[9:11]))) - meters['game_n_ASCII_paytable_ID'] = str(binascii.hexlify(bytearray(data[11:17]))) - meters['game_n_ASCII_base_percentage'] = str(binascii.hexlify(bytearray(data[17:]))) + if (data is not None): + meters['game_n_number_config'] = int(self.hexlify(self.bytearray(data[1:3]))) + meters['game_n_ASCII_game_ID'] = str(self.hexlify(self.bytearray(data[3:5]))) + meters['game_n_ASCII_additional_id'] = str(self.hexlify(self.bytearray(data[5:7]))) + meters['game_n_bin_denomination'] = str(self.hexlify(self.bytearray(data[7]))) + meters['game_n_bin_progressive_group'] = str(self.hexlify(self.bytearray(data[8]))) + meters['game_n_bin_game_options'] = str(self.hexlify(self.bytearray(data[9:11]))) + meters['game_n_ASCII_paytable_ID'] = str(self.hexlify(self.bytearray(data[11:17]))) + meters['game_n_ASCII_base_percentage'] = str(self.hexlify(self.bytearray(data[17:]))) return data return None @@ -1507,10 +1570,10 @@ def SAS_version_gaming_machine_serial_ID(self, **kwargs): cmd = [0x54, 0x00] data = self._send_command(cmd, crc_need=False, size=20) - if (data <> None): + if (data is not None): meters = {} - meters['ASCII_SAS_version'] = int(binascii.hexlify(bytearray(data[2:5]))) * 0.01 - meters['ASCII_serial_number'] = str(bytearray(data[5:])) + meters['ASCII_SAS_version'] = int(self.hexlify(self.bytearray(data[2:5]))) * 0.01 + meters['ASCII_serial_number'] = str(self.bytearray(data[5:])) return meters return None @@ -1519,12 +1582,12 @@ def selected_game_number(self, in_hex=True, **kwargs): cmd = [0x55] data = self._send_command(cmd, crc_need=False, size=6) - if (data <> None): - # meters['selected_game_number']=int(binascii.hexlify(bytearray(data[1:]))) + if (data is not None): + # meters['selected_game_number']=int(self.hexlify(self.bytearray(data[1:]))) if in_hex == False: - return int(binascii.hexlify(bytearray(data[1:]))) + return int(self.hexlify(self.bytearray(data[1:]))) else: - return binascii.hexlify(bytearray(data[1:])) + return self.hexlify(self.bytearray(data[1:])) return None def enabled_game_numbers(self, **kwargs): @@ -1533,10 +1596,10 @@ def enabled_game_numbers(self, **kwargs): cmd = [0x56] data = self._send_command(cmd, crc_need=False) - if (data <> None): + if (data is not None): meters = {} - meters['number_of_enabled_games'] = int(binascii.hexlify(bytearray(data[2]))) - meters['enabled_games_numbers'] = int(binascii.hexlify(bytearray(data[3:]))) + meters['number_of_enabled_games'] = int(self.hexlify(self.bytearray(data[2]))) + meters['enabled_games_numbers'] = int(self.hexlify(self.bytearray(data[3:]))) return meters return None @@ -1547,10 +1610,10 @@ def pending_cashout_info(self, **kwargs): cmd = [0x57] data = self._send_command(cmd, crc_need=False) - if (data <> None): + if (data is not None): tito_statement = {} - tito_statement['cashout_type'] = int(binascii.hexlify(bytearray(data[1:2]))) - tito_statement['cashout_amount'] = str(binascii.hexlify(bytearray(data[2:]))) + tito_statement['cashout_type'] = int(self.hexlify(self.bytearray(data[1:2]))) + tito_statement['cashout_amount'] = str(self.hexlify(self.bytearray(data[2:]))) return tito_statement return None @@ -1563,8 +1626,8 @@ def validation_number(self, validationID=1, valid_number=0, **kwargs): cmd.extend(self.bcd_coder_array(valid_number, 8)) # print cmd data = self._send_command(cmd, crc_need=True) - if (data <> None): - return str(binascii.hexlify(bytearray(data[1]))) + if (data is not None): + return str(self.hexlify(self.bytearray(data[1]))) return None def eft_send_promo_to_machine(self, amount=0, count=1, status=0, **kwargs): @@ -1575,11 +1638,11 @@ def eft_send_promo_to_machine(self, amount=0, count=1, status=0, **kwargs): cmd.append(status) cmd.extend(self.bcd_coder_array(amount, 4)) data = self._send_command(cmd, crc_need=True) - if (data <> None): + if (data is not None): eft_statement = {} - eft_statement['eft_status'] = str(binascii.hexlify(bytearray(data[1:]))) - eft_statement['promo_amount'] = str(binascii.hexlify(bytearray(data[4:]))) - # eft_statement['eft_transfer_counter']=int(binascii.hexlify(bytearray(data[3:4]))) + eft_statement['eft_status'] = str(self.hexlify(self.bytearray(data[1:]))) + eft_statement['promo_amount'] = str(self.hexlify(self.bytearray(data[4:]))) + # eft_statement['eft_transfer_counter']=int(self.hexlify(self.bytearray(data[3:4]))) return eft_statement return None @@ -1592,9 +1655,9 @@ def eft_load_cashable_credits(self, amount=0, count=1, status=0, **kwargs): cmd.extend(self.bcd_coder_array(amount, 4)) data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - meters['eft_status'] = str(binascii.hexlify(bytearray(data[1:2]))) - meters['cashable_amount'] = str(binascii.hexlify(bytearray(data[2:5]))) + if (data is not None): + meters['eft_status'] = str(self.hexlify(self.bytearray(data[1:2]))) + meters['cashable_amount'] = str(self.hexlify(self.bytearray(data[2:5]))) return data[3] return None @@ -1604,8 +1667,8 @@ def eft_avilable_transfers(self, **kwargs): # FIXME: eft_load_cashable_credits cmd = [0x6A] data = self._send_command(cmd, True, crc_need=False) - if (data <> None): - # meters['number_bills_in_stacker']=int(binascii.hexlify(bytearray(data[1:5]))) + if (data is not None): + # meters['number_bills_in_stacker']=int(self.hexlify(self.bytearray(data[1:5]))) return data return None @@ -1621,24 +1684,25 @@ def autentification_info(self, action=0, adressing_mode=0, component_name='', au else: if (action == 1 or action == 3): cmd.append(adressing_mode) - cmd.append(len(bytearray(component_name))) - cmd.append(bytearray(component_name)) - cmd[1] = len(bytearray(component_name)) + 3 + cmd.append(len(self.bytearray(component_name))) + cmd.append(self.bytearray(component_name)) + cmd[1] = len(self.bytearray(component_name)) + 3 else: if action == 2: cmd.append(adressing_mode) - cmd.append(len(bytearray(component_name))) - cmd.append(bytearray(component_name)) + cmd.append(len(self.bytearray(component_name))) + cmd.append(self.bytearray(component_name)) cmd.append(auth_method) cmd.append(seed_lenght) - cmd.append(bytearray(seed)) + cmd.append(self.bytearray(seed)) cmd.append(offset_lenght) - cmd.append(bytearray(offset)) + cmd.append(self.bytearray(offset)) - cmd[1] = len(bytearray(offset)) + len(bytearray(seed)) + len(bytearray(component_name)) + 6 + cmd[1] = len(self.bytearray(offset)) + len(self.bytearray(seed)) + len( + self.bytearray(component_name)) + 6 data = self._send_command(cmd, True, crc_need=True) - if (data <> None): + if (data is not None): return data[1] return None @@ -1653,11 +1717,11 @@ def ticket_validation_data(self, **kwargs): cmd = [0x70] data = self._send_command(cmd, True, crc_need=False) - if (data <> None): - meters['ticket_status'] = int(binascii.hexlify(bytearray(data[2:3]))) - meters['ticket_amount'] = str(binascii.hexlify(bytearray(data[3:8]))) - meters['parsing_code'] = int(binascii.hexlify(bytearray(data[8:9]))) - meters['validation_data'] = str(binascii.hexlify(bytearray(data[9:]))) + if (data is not None): + meters['ticket_status'] = int(self.hexlify(self.bytearray(data[2:3]))) + meters['ticket_amount'] = str(self.hexlify(self.bytearray(data[3:8]))) + meters['parsing_code'] = int(self.hexlify(self.bytearray(data[8:9]))) + meters['validation_data'] = str(self.hexlify(self.bytearray(data[9:]))) return data[1] return None @@ -1677,11 +1741,11 @@ def redeem_ticket(self, transfer_code=0, transfer_amount=0, parsing_code=0, vali cmd[1] = 8 + 13 data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - meters['ticket_status'] = int(binascii.hexlify(bytearray(data[2:3]))) - meters['ticket_amount'] = int(binascii.hexlify(bytearray(data[3:8]))) - meters['parsing_code'] = int(binascii.hexlify(bytearray(data[8:9]))) - meters['validation_data'] = str(binascii.hexlify(bytearray(data[9:]))) + if (data is not None): + meters['ticket_status'] = int(self.hexlify(self.bytearray(data[2:3]))) + meters['ticket_amount'] = int(self.hexlify(self.bytearray(data[3:8]))) + meters['parsing_code'] = int(self.hexlify(self.bytearray(data[8:9]))) + meters['validation_data'] = str(self.hexlify(self.bytearray(data[9:]))) return data[1] return None @@ -1732,18 +1796,18 @@ def AFT_jp(self, mony, amount=1, lock_timeout=0, games=None, **kwargs): raise AFTBadAmount last_transaction = self.AFT_format_transaction() - len_transaction_id = hex(len(last_transaction) / 2)[2:] + len_transaction_id = hex(len(last_transaction) // 2)[2:] if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='11', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key) + times=my_time, my_key=self.my_key, transfer_flag='00') new_cmd = [] count = 0 - for i in range(len(cmd) / 2): + for i in range(int(len(cmd) / 2)): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 @@ -1752,29 +1816,102 @@ def AFT_jp(self, mony, amount=1, lock_timeout=0, games=None, **kwargs): if lock_timeout > 0: self.AFT_game_lock(lock_timeout, condition=1) data = self._send_command(new_cmd, crc_need=True, size=82) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) + if (data is not None): + a = int(self.hexlify(self.bytearray(data[26:27])), 16) response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transaction buffer position': int(self.hexlify(self.bytearray(data[2:3])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } + # try: + self.AFT_unregister() + # except: + # self.log.warning('AFT UNREGISTER ERROR: won to host') + return response + + def AFT_initial_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): + # self.lock_emg(lock_time=500, condition=1) + if self.denom > 0.01: + return None + my_time = datetime.datetime.now() + my_time = datetime.datetime.strftime(my_time, '%m%d%Y') + if mony == None: + mony = str(self.current_credits(denom=False)) + else: + mony = str(int((mony / self.denom))) + mony = mony.replace('.', '') + mony = '0' * (10 - len(mony)) + mony + if amount == 1: + mony_1 = mony + mony_2 = '0000000000' + mony_3 = '0000000000' + elif amount == 2: + mony_1 = '0000000000' + mony_2 = mony + mony_3 = '0000000000' + elif amount == 3: + mony_1 = '0000000000' + mony_2 = '0000000000' + mony_3 = mony + else: + raise AFTBadAmount + + last_transaction = self.AFT_format_transaction() + len_transaction_id = hex(len(last_transaction) // 2)[2:] + if len(len_transaction_id) < 2: + len_transaction_id = '0' + len_transaction_id + elif len(len_transaction_id) % 2 == 1: + len_transaction_id = '0' + len_transaction_id + cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + transfer_code='00', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, + asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, + times=my_time, my_key=self.my_key, transfer_flag='0a') + new_cmd = [] + count = 0 + for i in range(int(len(cmd) / 2)): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + + response = None + self.AFT_register() + if lock_timeout > 0: + self.AFT_game_lock(lock_timeout, condition=1) try: - self.AFT_unregister() - except: - self.log.warning('AFT UNREGISTER ERROR: won to host') + data = self._send_command(new_cmd, crc_need=True, size=82) + if (data is not None): + a = int(self.hexlify(self.bytearray(data[26:27])), 16) + response = { + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transaction buffer position': int(self.hexlify(self.bytearray(data[2:3])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) + } + except Exception as e: + self.log.error(e, exc_info=True) + # try: + self.AFT_unregister() + # except: + # self.log.warning('AFT UNREGISTER ERROR: out') return response - def AFT_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): + def AFT_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): # self.lock_emg(lock_time=500, condition=1) if self.denom > 0.01: return None @@ -1802,18 +1939,18 @@ def AFT_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): raise AFTBadAmount last_transaction = self.AFT_format_transaction() - len_transaction_id = hex(len(last_transaction) / 2)[2:] + len_transaction_id = hex(len(last_transaction) // 2)[2:] if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key) + times=my_time, my_key=self.my_key, transfer_flag='00') new_cmd = [] count = 0 - for i in range(len(cmd) / 2): + for i in range(int(len(cmd) / 2)): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 @@ -1823,21 +1960,21 @@ def AFT_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): self.AFT_game_lock(lock_timeout, condition=1) try: data = self._send_command(new_cmd, crc_need=True, size=82) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) + if (data is not None): + a = int(self.hexlify(self.bytearray(data[26:27])), 16) response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transaction buffer position': int(self.hexlify(self.bytearray(data[2:3])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } except Exception as e: self.log.error(e, exc_info=True) @@ -1869,19 +2006,19 @@ def AFT_cashout_enable(self, amount=1, **kwargs): raise AFTBadAmount last_transaction = self.AFT_format_transaction() - len_transaction_id = hex(len(last_transaction) / 2)[2:] + len_transaction_id = hex(len(last_transaction) // 2)[2:] if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}00{index}{transfer_code}{mony_1}{mony_2}{mony_3}02{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '72{my_key}00{index}{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key) + times=my_time, my_key=self.my_key, transfer_flag='02') new_cmd = [] count = 0 - for i in range(len(cmd) / 2): + for i in range(int(len(cmd) / 2)): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 self.AFT_register() @@ -1889,21 +2026,21 @@ def AFT_cashout_enable(self, amount=1, **kwargs): response = None try: data = self._send_command(new_cmd, crc_need=True, size=82) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) + if (data is not None): + a = int(self.hexlify(self.bytearray(data[26:27])), 16) response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transaction buffer position': int(self.hexlify(self.bytearray(data[2:3])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } except Exception as e: self.log.info(e, exc_info=True) @@ -1943,7 +2080,7 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): return 'NoGame' elif game_selected < 1: return 'NoGame' - elif game_selected < None: + elif not game_selected: return 'NoGame' my_time = datetime.datetime.now() @@ -1969,19 +2106,21 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): # self.lock_emg(lock_time=500, condition=0) # self.lock_emg() last_transaction = self.AFT_format_transaction() - len_transaction_id = hex(len(last_transaction) / 2)[2:] + len_transaction_id = hex(int(len(last_transaction) // 2))[2:] + if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{transfer_code}{index}{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + + cmd = '72{my_key}{transfer_code}{index}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='0000', index='10', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key) + times=my_time, my_key=self.my_key, transfer_flag='00') new_cmd = [] count = 0 - for i in range(len(cmd) / 2): + for i in range(int(len(cmd) / 2)): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 @@ -1991,21 +2130,21 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): self.AFT_game_lock(lock_timeout, condition=3) try: data = self._send_command(new_cmd, crc_need=True, size=82) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) + if (data is not None): + a = int(self.hexlify(self.bytearray(data[26:27])), 16) response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transaction buffer position': int(self.hexlify(self.bytearray(data[2:3])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } except Exception as e: self.log.error(e, exc_info=True) @@ -2038,51 +2177,54 @@ def AFT_in(self, mony, amount=1, lock_timeout=0, **kwargs): raise AFTBadAmount last_transaction = self.AFT_format_transaction() - len_transaction_id = hex(len(last_transaction) / 2)[2:] + len_transaction_id = hex(int(len(last_transaction) // 2))[2:] + # raise KeyError(last_transaction, len_transaction_id) if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{transfer_code}{index}00{mony_1}{mony_2}{mony_3}00{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '72{my_key}{transfer_code}{index}00{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='00', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key) + times=my_time, my_key=self.my_key, transfer_flag='00') new_cmd = [] count = 0 - for i in range(len(cmd) / 2): + for i in range(int(len(cmd) / 2)): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 + # self.AFT_register() # if lock_timeout > 0: # self.AFT_game_lock(lock_timeout, condition=0) response = None self.AFT_register() + if lock_timeout > 0: self.AFT_game_lock(lock_timeout, condition=0) try: data = self._send_command(new_cmd, crc_need=True, size=82) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) + if (data is not None): + a = int(self.hexlify(self.bytearray(data[26:27])), 16) response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transaction buffer position': int(binascii.hexlify(bytearray(data[2:3]))), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transaction buffer position': int(self.hexlify(self.bytearray(data[2:3])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } except Exception as e: self.log.error(e, exc_info=True) # try: self.AFT_unregister() # except: - # self.log.warning('AFT UNREGISTER ERROR: in') + # self.log.warning('AFT UNREGISTER ERROR: in') return response def AFT_clean_transaction_poll(self, register=False, **kwargs): @@ -2097,42 +2239,42 @@ def AFT_clean_transaction_poll(self, register=False, **kwargs): cmd = '7202FF00' count = 0 new_cmd = [] - for i in range(len(cmd) / 2): + for i in range(int(len(cmd) / 2)): new_cmd.append(int(cmd[count:count + 2], 16)) count += 2 response = None try: data = self._send_command(new_cmd, crc_need=True, size=90) - if (data <> None): - # print binascii.hexlify(data) - a = int(binascii.hexlify(bytearray(data[26:27])), 16) + if (data is not None): + # print self.hexlify(self.bytearray(data)) + a = int(self.hexlify(self.bytearray(data[26:27])), 16) response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } if register == True: - try: - self.AFT_unregister() - except: - self.log.warning('AFT UNREGISTER ERROR: cleean poll') - if hex(self.transaction)[2:-1] == response['Transaction ID']: + # try: + self.AFT_unregister() + if response == None: + pass + elif hex(self.transaction)[2:] == response['Transaction ID']: return response else: if self.aft_get_last_transaction == True: - raise BadTransactionID, 'last: %s, new:%s ' % ( - hex(self.transaction)[2:-1], response['Transaction ID']) + raise BadTransactionID('last: %s, new:%s ' % ( + hex(self.transaction)[2:], response['Transaction ID'])) else: self.log.info('last: %s, new:%s ' % ( - hex(self.transaction)[2:-1], response['Transaction ID'])) + hex(self.transaction)[2:], response['Transaction ID'])) except BadCRC: pass return False @@ -2164,73 +2306,88 @@ def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfe cmd[1] = len(transaction_ID) + len(transaction_ID) + 53 data = self._send_command(cmd, crc_need=True) - if (data <> None): - aft_statement['transaction_buffer_position'] = int(binascii.hexlify(bytearray(data[2:3]))) - aft_statement['transfer_status'] = int(binascii.hexlify(bytearray(data[3:4]))) - aft_statement['receipt_status'] = int(binascii.hexlify(bytearray(data[4:5]))) - aft_statement['transfer_type'] = int(binascii.hexlify(bytearray(data[5:6]))) - aft_statement['cashable_amount'] = int(binascii.hexlify(bytearray(data[6:11]))) - aft_statement['restricted_amount'] = int(binascii.hexlify(bytearray(data[11:16]))) - aft_statement['nonrestricted_amount'] = int(binascii.hexlify(bytearray(data[16:21]))) - aft_statement['transfer_flags'] = int(binascii.hexlify(bytearray(data[21:22]))) - aft_statement['asset_number'] = (binascii.hexlify(bytearray(data[22:26]))) - aft_statement['transaction_ID_lenght'] = int(binascii.hexlify(bytearray(data[26:27]))) - a = int(binascii.hexlify(bytearray(data[26:27]))) - aft_statement['transaction_ID'] = str(binascii.hexlify(bytearray(data[27:(27 + a + 1)]))) + if (data is not None): + aft_statement['transaction_buffer_position'] = int(self.hexlify(self.bytearray(data[2:3])), 16) + aft_statement['transfer_status'] = int(self.hexlify(self.bytearray(data[3:4]))) + aft_statement['receipt_status'] = int(self.hexlify(self.bytearray(data[4:5]))) + aft_statement['transfer_type'] = int(self.hexlify(self.bytearray(data[5:6]))) + aft_statement['cashable_amount'] = int(self.hexlify(self.bytearray(data[6:11]))) + aft_statement['restricted_amount'] = int(self.hexlify(self.bytearray(data[11:16]))) + aft_statement['nonrestricted_amount'] = int(self.hexlify(self.bytearray(data[16:21]))) + aft_statement['transfer_flags'] = int(self.hexlify(self.bytearray(data[21:22]))) + aft_statement['asset_number'] = (self.hexlify(self.bytearray(data[22:26]))) + aft_statement['transaction_ID_lenght'] = int(self.hexlify(self.bytearray(data[26:27]))) + a = int(self.hexlify(self.bytearray(data[26:27]))) + aft_statement['transaction_ID'] = str(self.hexlify(self.bytearray(data[27:(27 + a + 1)]))) a = 27 + a + 1 - aft_statement['transaction_date'] = str(binascii.hexlify(bytearray(data[a:a + 5]))) + aft_statement['transaction_date'] = str(self.hexlify(self.bytearray(data[a:a + 5]))) a = a + 5 - aft_statement['transaction_time'] = str(binascii.hexlify(bytearray(data[a:a + 4]))) - aft_statement['expiration'] = str(binascii.hexlify(bytearray(data[a + 4:a + 9]))) - aft_statement['pool_ID'] = str(binascii.hexlify(bytearray(data[a + 9:a + 11]))) - aft_statement['cumulative_casable_amount_meter_size'] = (binascii.hexlify(bytearray(data[a + 11:a + 12]))) - b = a + int(binascii.hexlify(bytearray(data[a + 11:a + 12]))) - aft_statement['cumulative_casable_amount_meter'] = (binascii.hexlify(bytearray(data[a + 12:b + 1]))) - aft_statement['cumulative_restricted_amount_meter_size'] = (binascii.hexlify(bytearray(data[b + 1:b + 2]))) - c = b + 2 + int(binascii.hexlify(bytearray(data[b + 1:b + 2]))) - aft_statement['cumulative_restricted_amount_meter'] = (binascii.hexlify(bytearray(data[b + 2:c]))) - aft_statement['cumulative_nonrestricted_amount_meter_size'] = (binascii.hexlify(bytearray(data[c:c + 1]))) - b = int(binascii.hexlify(bytearray(data[c:c + 1]))) + c - aft_statement['cumulative_nonrestricted_amount_meter'] = (binascii.hexlify(bytearray(data[c + 1:]))) + aft_statement['transaction_time'] = str(self.hexlify(self.bytearray(data[a:a + 4]))) + aft_statement['expiration'] = str(self.hexlify(self.bytearray(data[a + 4:a + 9]))) + aft_statement['pool_ID'] = str(self.hexlify(self.bytearray(data[a + 9:a + 11]))) + aft_statement['cumulative_casable_amount_meter_size'] = (self.hexlify(self.bytearray(data[a + 11:a + 12]))) + b = a + int(self.hexlify(self.bytearray(data[a + 11:a + 12]))) + aft_statement['cumulative_casable_amount_meter'] = (self.hexlify(self.bytearray(data[a + 12:b + 1]))) + aft_statement['cumulative_restricted_amount_meter_size'] = (self.hexlify(self.bytearray(data[b + 1:b + 2]))) + c = b + 2 + int(self.hexlify(self.bytearray(data[b + 1:b + 2]))) + aft_statement['cumulative_restricted_amount_meter'] = (self.hexlify(self.bytearray(data[b + 2:c]))) + aft_statement['cumulative_nonrestricted_amount_meter_size'] = (self.hexlify(self.bytearray(data[c:c + 1]))) + b = int(self.hexlify(self.bytearray(data[c:c + 1]))) + c + aft_statement['cumulative_nonrestricted_amount_meter'] = (self.hexlify(self.bytearray(data[c + 1:]))) return data[1] return None def AFT_get_last_transaction(self, **kwargs): cmd = [0x72, 0x02, 0xFF, 0x00] - # time.sleep(SLEEP_IF_FORMAT_TRANSACTION) - data = self._send_command(cmd, crc_need=True, size=90) - if (data <> None): + transaction = None + try: + data = self._send_command(cmd, crc_need=True, size=90) + except Exception as e: + self.log.error(e, exc_info=True) + transaction = int('2020202020202020202020202020202021', 16) + self.log.warning('AFT no transaction') + if (data is not None): try: - if self.aft_get_last_transaction == False: + # if self.aft_get_last_transaction == False: + # raise ValueError + + count = int(self.hexlify(self.bytearray(data[26:27])), 16) + if count > 1: + pass + else: + raise ValueError + # raise KeyError(self.hexlify(self.bytearray(data[27:27 + count]))) + transaction = self.hexlify(self.bytearray(data[27:27 + count])) + if int(transaction, 16) < 10931737842416972128203783466984490934305: raise ValueError - count = int(binascii.hexlify(data[26:27]), 16) - transaction = binascii.hexlify(data[27:27 + count]) + # raise KeyError(self.hexlify(self.bytearray(data[26:]))) if transaction == '2121212121212121212121212121212121': transaction = '2020202020202020202020202020202021' - self.transaction = int(transaction, 16) - return self.transaction + # self.transaction = int(transaction, 16) + return int(transaction, 16) except ValueError as e: self.log.warning(e, exc_info=True) - self.transaction = int('2020202020202020202020202020202021', 16) + transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') except Exception as e: self.log.error(e, exc_info=True) - self.transaction = int('2020202020202020202020202020202021', 16) + transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') else: - self.transaction = int('2020202020202020202020202020202021', 16) + # if not self.transaction: + transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') - return self.transaction + return transaction def AFT_format_transaction(self, get_from_emg=False, **kwargs): if get_from_emg == True: - self.AFT_get_last_transaction() + self.transaction = self.AFT_get_last_transaction() self.transaction += 1 - transaction = hex(self.transaction)[2:-1] + transaction = hex(self.transaction)[2:] count = 0 tmp = [] - for i in range(len(transaction) / 2): + for i in range(int(len(transaction) / 2)): tmp.append(transaction[count:count + 2]) count += 2 tmp.reverse() @@ -2254,16 +2411,18 @@ def AFT_register_initial(self, **kwargs): self.log.error(e, exc_info=True) return None - def AFT_register(self, **kwargs): - return True + def AFT_register(self, mk_reg=False, **kwargs): + if mk_reg is False: + return True try: return self.AFT_register_gaming_machine(reg_code=0x00) except Exception as e: self.log.error(e, exc_info=True) return None - def AFT_unregister(self, **kwargs): - return True + def AFT_unregister(self, mk_reg=False, **kwargs): + if mk_reg is False: + return True try: return self.AFT_register_gaming_machine(reg_code=0x80) except Exception as e: @@ -2281,50 +2440,60 @@ def AFT_register_gaming_machine(self, reg_code=0xff, **kwargs): tmp = self.asset_number + self.reg_key + self.POS_ID cmd[1] = 0x1D count = 0 - for i in range(len(tmp) / 2): + for i in range(int(len(tmp) / 2)): cmd.append(int(tmp[count:count + 2], 16)) count += 2 data = self._send_command(cmd, crc_need=True, size=34) # data = None - if (data <> None): + if (data is not None): aft_statement = {} - aft_statement['registration_status'] = AFT_REGISTRACION_STATUS[str(binascii.hexlify((data[2:3])))] - aft_statement['asset_number'] = str(binascii.hexlify(data[3:7])) - aft_statement['registration_key'] = str(binascii.hexlify(data[7:27])) - aft_statement['POS_ID'] = str(binascii.hexlify((data[27:]))) + aft_statement['registration_status'] = AFT_REGISTRACION_STATUS[self.hexlify(self.bytearray(data[2:3]))] + aft_statement['asset_number'] = self.hexlify(self.bytearray(data[3:7])) + aft_statement['registration_key'] = self.hexlify(self.bytearray(data[7:27])) + aft_statement['POS_ID'] = self.hexlify(self.bytearray(data[27:])) return aft_statement return None - def AFT_game_lock(self, lock_timeout=100, condition=00, **kwargs): - return self.AFT_game_lock_and_status_request(lock_code=0x00, lock_timeout=lock_timeout, transfer_condition=condition) + def AFT_game_lock(self, lock_timeout=100, condition='01', **kwargs): + return self.AFT_game_lock_and_status_request(lock_code='00', lock_timeout=lock_timeout, + condition=condition) def AFT_game_unlock(self, **kwargs): - return self.AFT_game_lock_and_status_request(lock_code=0x80) + return self.AFT_game_lock_and_status_request(lock_code='80') - def AFT_game_lock_and_status_request(self, lock_code=0x00, transfer_condition=00, lock_timeout=0, **kwargs): + def AFT_game_lock_and_status_request(self, lock_code='00', lock_time=0, condition='01', **kwargs): # 74 - cmd = [0x74] - - cmd.append(lock_code) - cmd.append(transfer_condition) - cmd.extend(self.bcd_coder_array(lock_timeout, 2)) - # cmd.addend(0x23) - - data = self._send_command(cmd, crc_need=True, size=40) - if (data <> None): + lock_time = str(lock_time) + if len(lock_time) == 1: + lock_time = '000%s' % (lock_time) + elif len(lock_time) == 2: + lock_time = '00%s' % (lock_time) + elif len(lock_time) == 3: + lock_time = '0%s' % (lock_time) + elif len(lock_time) == 4: + lock_time = '%s' % (lock_time) + else: + raise ValueError('Invalid time') + cmd = '74%s%s%s' % (lock_code, condition, lock_time) + new_cmd = [] + count = 0 + for i in range(int(len(cmd) / 2)): + new_cmd.append(int(cmd[count:count + 2], 16)) + count += 2 + response = self._send_command(new_cmd, crc_need=True, size=40) + if (response): aft_statement = {} - aft_statement['asset_number'] = str(binascii.hexlify(bytearray(data[2:6]))) - aft_statement['game_lock_status'] = str(binascii.hexlify(bytearray(data[6:7]))) - aft_statement['avilable_transfers'] = str(binascii.hexlify(bytearray(data[7:8]))) - aft_statement['host_cashout_status'] = str(binascii.hexlify(bytearray(data[8:9]))) - aft_statement['AFT_status'] = str(binascii.hexlify(bytearray(data[9:10]))) - aft_statement['max_buffer_index'] = str(binascii.hexlify(bytearray(data[10:11]))) - aft_statement['current_cashable_amount'] = str(binascii.hexlify(bytearray(data[11:16]))) - aft_statement['current_restricted_amount'] = str(binascii.hexlify(bytearray(data[16:21]))) - aft_statement['current_non_restricted_amount'] = str(binascii.hexlify(bytearray(data[21:26]))) - aft_statement['restricted_expiration'] = str(binascii.hexlify(bytearray(data[26:29]))) - aft_statement['restricted_pool_ID'] = str(binascii.hexlify(bytearray(data[29:31]))) - + aft_statement['asset_number'] = str(self.hexlify(self.bytearray(response[2:6]))) + aft_statement['game_lock_status'] = str(self.hexlify(self.bytearray(response[6:7]))) + aft_statement['avilable_transfers'] = str(self.hexlify(self.bytearray(response[7:8]))) + aft_statement['host_cashout_status'] = str(self.hexlify(self.bytearray(response[8:9]))) + aft_statement['AFT_status'] = str(self.hexlify(self.bytearray(response[9:10]))) + aft_statement['max_buffer_index'] = str(self.hexlify(self.bytearray(response[10:11]))) + aft_statement['current_cashable_amount'] = str(self.hexlify(self.bytearray(response[11:16]))) + aft_statement['current_restricted_amount'] = str(self.hexlify(self.bytearray(response[16:21]))) + aft_statement['current_non_restricted_amount'] = str(self.hexlify(self.bytearray(response[21:26]))) + aft_statement['restricted_expiration'] = str(self.hexlify(self.bytearray(response[26:29]))) + aft_statement['restricted_pool_ID'] = str(self.hexlify(self.bytearray(response[29:31]))) return aft_statement return None @@ -2333,28 +2502,28 @@ def AFT_cansel_request(self, **kwargs): self.AFT_register() response = None data = self._send_command(cmd, crc_need=True, size=90) - if (data <> None): - a = int(binascii.hexlify(bytearray(data[26:27])), 16) + if (data is not None): + a = int(self.hexlify(self.bytearray(data[26:27])), 16) response = { - 'Length': int(binascii.hexlify(bytearray(data[26:27])), 16), - 'Transfer status': AFT_TRANSFER_STATUS[binascii.hexlify(bytearray(data[3:4]))], - 'Receipt status': AFT_RECEIPT_STATUS[binascii.hexlify(bytearray(data[4:5]))], - 'Transfer type': AFT_TRANSFER_TYPE[binascii.hexlify(bytearray(data[5:6]))], - 'Cashable amount': int(binascii.hexlify(bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(binascii.hexlify(bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(binascii.hexlify(bytearray(data[16:21]))) * self.denom, - 'Transfer flags': binascii.hexlify(bytearray(data[21:22])), - 'Asset number': binascii.hexlify(bytearray(data[22:26])), - 'Transaction ID length': binascii.hexlify(bytearray(data[26:27])), - 'Transaction ID': binascii.hexlify(bytearray(data[27:(27 + a)])) + 'Length': int(self.hexlify(self.bytearray(data[26:27])), 16), + 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], + 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], + 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], + 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, + 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, + 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), + 'Asset number': self.hexlify(self.bytearray(data[22:26])), + 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), + 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } - try: - self.AFT_unregister() - except: - self.log.warning('AFT UNREGISTER ERROR') - - if response['Transaction ID'] == hex(self.transaction)[2:-1]: - return response + # try: + self.AFT_unregister() + # except: + # self.log.warning('AFT UNREGISTER ERROR') + if response: + if response['Transaction ID'] == hex(self.transaction)[2:]: + return response # self.log.warning('NO CLEAN POLL: %s', response) return False @@ -2379,11 +2548,11 @@ def exnended_validation_status(self, control_mask=[0, 0], status_bits=[0, 0], ca # cmd.addend(0x23) data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - aft_statement['asset_number'] = str(binascii.hexlify(bytearray(data[2:6]))) - aft_statement['status_bits'] = str(binascii.hexlify(bytearray(data[6:8]))) - aft_statement['cashable_ticket_reciept_exp'] = str(binascii.hexlify(bytearray(data[8:10]))) - aft_statement['restricted_ticket_exp'] = str(binascii.hexlify(bytearray(data[10:]))) + if (data is not None): + aft_statement['asset_number'] = str(self.hexlify(self.bytearray(data[2:6]))) + aft_statement['status_bits'] = str(self.hexlify(self.bytearray(data[6:8]))) + aft_statement['cashable_ticket_reciept_exp'] = str(self.hexlify(self.bytearray(data[8:10]))) + aft_statement['restricted_ticket_exp'] = str(self.hexlify(self.bytearray(data[10:]))) return data[1] return None @@ -2400,8 +2569,8 @@ def current_date_time(self, **kwargs): # 7E cmd = [0x7E] data = self._send_command(cmd, crc_need=False, size=11) - if (data <> None): - data = str(binascii.hexlify(bytearray(data[1:8]))) + if (data is not None): + data = str(self.hexlify(self.bytearray(data[1:8]))) return datetime.datetime.strptime(data, '%m%d%Y%H%M%S') return None @@ -2410,7 +2579,7 @@ def recieve_date_time(self, dates, times, **kwargs): cmd = [0x7F] my_cmd = '' + dates.replace('.', '') + times.replace(':', '') + '00' count = 0 - for i in range(len(my_cmd) / 2): + for i in range(int(len(my_cmd) / 2)): cmd.append(int(my_cmd[count:count + 2], 16)) count += 2 @@ -2471,7 +2640,7 @@ def initiate_legacy_bonus_pay(self, mony, tax='00', games=None, **kwargs): my_cmd = cmd + tax cmd = [0x8A] count = 0 - for i in range(len(my_cmd) / 2): + for i in range(int(len(my_cmd) / 2)): cmd.append(int(my_cmd[count:count + 2], 16)) count += 2 if (self._send_command(cmd, True, crc_need=True) == self.adress): @@ -2536,19 +2705,19 @@ def legacy_bonus_meters(self, denom=True, n=0, **kwargs): # cmd=[0x19] data = self._send_command(cmd, crc_need=True, size=18) - if (data <> None): + if (data is not None): meters = {} if denom == False: - meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:3]))) - meters['deductible'] = int(binascii.hexlify(bytearray(data[3:7]))) - meters['non-deductible'] = int(binascii.hexlify(bytearray(data[7:11]))) - meters['wager match'] = int(binascii.hexlify(bytearray(data[11:15]))) + meters['game bumber'] = int(self.hexlify(self.bytearray(data[2:3]))) + meters['deductible'] = int(self.hexlify(self.bytearray(data[3:7]))) + meters['non-deductible'] = int(self.hexlify(self.bytearray(data[7:11]))) + meters['wager match'] = int(self.hexlify(self.bytearray(data[11:15]))) else: - meters['game bumber'] = int(binascii.hexlify(bytearray(data[2:3]))) - meters['deductible'] = round(int(binascii.hexlify(bytearray(data[3:7]))) * self.denom, 2) - meters['non-deductible'] = round(int(binascii.hexlify(bytearray(data[7:11]))) * self.denom, 2) - meters['wager match'] = round(int(binascii.hexlify(bytearray(data[11:15]))) * self.denom, 2) + meters['game bumber'] = int(self.hexlify(self.bytearray(data[2:3]))) + meters['deductible'] = round(int(self.hexlify(self.bytearray(data[3:7]))) * self.denom, 2) + meters['non-deductible'] = round(int(self.hexlify(self.bytearray(data[7:11]))) * self.denom, 2) + meters['wager match'] = round(int(self.hexlify(self.bytearray(data[11:15]))) * self.denom, 2) return meters return None @@ -2577,8 +2746,8 @@ def enabled_features(self, game_nimber=0, **kwargs): cmd.extend(self.bcd_coder_array(game_nimber, 2)) data = self._send_command(cmd, True, crc_need=True) - if (data <> None): - aft_statement['game_number'] = str(binascii.hexlify(bytearray(data[1:3]))) + if (data is not None): + aft_statement['game_number'] = str(self.hexlify(self.bytearray(data[1:3]))) aft_statement['features_1'] = data[3] aft_statement['features_2'] = data[4] aft_statement['features_3'] = data[5] @@ -2659,6 +2828,13 @@ def event_response_to_long_poll(self, **kwargs): def bcd_coder_array(self, value=0, lenght=4, **kwargs): return self.int_to_bcd(value, lenght) + def bytearray(self, data): + return data.hex() + + def hexlify(self, data): + data = data.replace('-', '') + return data + def int_to_bcd(self, number=0, lenght=5, **kwargs): n = 0 m = 0 @@ -2686,90 +2862,17 @@ def int_to_bcd(self, number=0, lenght=5, **kwargs): class SAS_USB(Sas): + pass - def _send_command(self, command, no_response=False, timeout=None, crc_need=True, size=1): - # if timeout == None: - # timeout = self.timeout + 1 - # time.sleep(0.04) - busy = True - response = b'' - # self.my_log.flush() - try: - # if self.poll_adres == '82': - # self.poll_adres = '80' - # else: - # self.poll_adres = '82' - - buf_header = [self.adress] - self._conf_port() - # self.connection.write(('80' + self.mashin_n).decode("hex")) - # self.close() - # self.connection.parity = serial.PARITY_SPACE - # self.open() - - buf_header.extend(command) - buf_count = len(command) - # buf_header[2]=buf_count+2 - if (crc_need == True): - crc = CRC16Kermit().calculate(str(bytearray(buf_header))) - buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) - self.log.debug(buf_header) - # time.sleep(0.04) - self.connection.write([self.poll_adress, self.adress]) - # self.close() - self.connection.parity = serial.PARITY_SPACE - # self.open() - # my_log = open('/home/colibri/dump.log', 'w') - # self.my_log.write('TX %s: %s\n' % (time.time(), '82'+ binascii.hexlify(bytearray(buf_header)))) - # print self.connection.portstr - # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) - self.connection.write((buf_header[1:])) - - except Exception as e: - self.log.error(e, exc_info=True) - - try: - buffer = [] - # self.connection.flushInput() - # time.sleep(0.04) - # t = time.time() - # while time.time() - t < timeout: - response = self.connection.read(size) - if no_response == True: - try: - return int(binascii.hexlify(response)) - except ValueError as e: - self.log.warning('no sas response %s' % (str(buf_header[1:]))) - return None - # else: - # # response += self.connection.read(size) - # if (self.checkResponse(response, size) <> False): - # break - # - # if time.time() - t >= timeout: - # self.log.warning("sas timeout") - # # buffer.append(response) - # # print binascii.hexlify(bytearray(response)) - # return None - - busy = False - response = self.checkResponse(response) - self.log.debug('sas response %s', binascii.hexlify(response)) - if response == '': - response = None - # self.log.info('no sas response') - return response - # return None - except Exception as e: - self.log.error(e, exc_info=True) - busy = False - return None if __name__ == '__main__': - sas = Sas('/dev/ttyS1') - print sas.start() - print sas.gaming_machine_ID() - print sas.AFT_get_last_transaction() - print sas.AFT_in(0.05) - print sas.AFT_clean_transaction_poll() + sas = Sas('/dev/ttyS4') + print(sas.start()) + print(sas.gaming_machine_ID()) + sas.transaction = sas.AFT_get_last_transaction() + print(sas.transaction) + print(sas.send_meters_10_15()) + print(sas.events_poll()) + print(sas.AFT_clean_transaction_poll()) + print(sas.total_dollar_value_of_bills_meter()) From afb2629395c0cdc1a51b19fccabc10918a07e621 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Thu, 22 Feb 2024 18:20:49 +0200 Subject: [PATCH 04/11] Update sas.py --- sas.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sas.py b/sas.py index 3686b16..631df69 100644 --- a/sas.py +++ b/sas.py @@ -2867,12 +2867,9 @@ class SAS_USB(Sas): if __name__ == '__main__': - sas = Sas('/dev/ttyS4') + sas = Sas('/dev/ttyS1') print(sas.start()) - print(sas.gaming_machine_ID()) sas.transaction = sas.AFT_get_last_transaction() print(sas.transaction) - print(sas.send_meters_10_15()) - print(sas.events_poll()) + print(sas.AFT_in(15)) print(sas.AFT_clean_transaction_poll()) - print(sas.total_dollar_value_of_bills_meter()) From 5d740aa0db81a603db9b46a993e92be422fa5262 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Mon, 26 Feb 2024 11:11:56 +0200 Subject: [PATCH 05/11] Update sas.py python 3.9 --- sas.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/sas.py b/sas.py index 631df69..3686b16 100644 --- a/sas.py +++ b/sas.py @@ -2867,9 +2867,12 @@ class SAS_USB(Sas): if __name__ == '__main__': - sas = Sas('/dev/ttyS1') + sas = Sas('/dev/ttyS4') print(sas.start()) + print(sas.gaming_machine_ID()) sas.transaction = sas.AFT_get_last_transaction() print(sas.transaction) - print(sas.AFT_in(15)) + print(sas.send_meters_10_15()) + print(sas.events_poll()) print(sas.AFT_clean_transaction_poll()) + print(sas.total_dollar_value_of_bills_meter()) From bd3736f0d05e1dc6ee5c1255582a563340eb0850 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Mon, 26 Feb 2024 13:57:10 +0200 Subject: [PATCH 06/11] Update sas.py --- sas.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sas.py b/sas.py index 3686b16..134ece6 100644 --- a/sas.py +++ b/sas.py @@ -2867,12 +2867,14 @@ class SAS_USB(Sas): if __name__ == '__main__': - sas = Sas('/dev/ttyS4') + sas = Sas('/dev/ttyUSB0') print(sas.start()) print(sas.gaming_machine_ID()) sas.transaction = sas.AFT_get_last_transaction() print(sas.transaction) print(sas.send_meters_10_15()) print(sas.events_poll()) + print(sas.AFT_in(15)) print(sas.AFT_clean_transaction_poll()) - print(sas.total_dollar_value_of_bills_meter()) + print(sas.send_meters_10_15()) + From f3bb5502309431575dea56c7b6bac58ea5619283 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Mon, 4 Mar 2024 15:45:48 +0200 Subject: [PATCH 07/11] Update sas.py --- sas.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/sas.py b/sas.py index 134ece6..3c63116 100644 --- a/sas.py +++ b/sas.py @@ -418,7 +418,7 @@ class BadCRC(Exception): pass -class BadCommand(Exception): +class BadCommandIsRunning(Exception): pass @@ -444,13 +444,13 @@ class EMGGpollBadResponse(Exception): class Sas(): - def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_transaction=True, sas_dump=False): + def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_transaction=True, sas_dump=False, denom=0.01): # self.poll_adres = '82' self.adress = None self.mashin_n = None self.aft_get_last_transaction = aft_get_last_transaction # self.last_transaction_n = None - self.denom = 0.01 + self.denom = denom self.asset_number = '01000000' self.reg_key = '0000000000000000000000000000000000000000' self.POS_ID = 'B374A402' @@ -459,6 +459,7 @@ def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_tra self.poll_adress = poll_adress self.sas_dump = sas_dump self.timeout = timeout + self.last_gpoll_event = None if self.sas_dump: os.system('sudo touch /var/log/sas_dump.log') os.system('sudo chown colibri:colibri /var/log/sas_dump.log') @@ -491,7 +492,7 @@ def clean_buffer(self): self.connection.reset_output_buffer() except Exception as e: self.log.error(e, exc_info=True) - self.close() + # self.close() def flush(self): try: @@ -658,6 +659,7 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # self.my_log = open('/var/log/sas_dump.log', 'w') # print self.connection.portstr # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) + time.sleep(0.01) self.connection.write(buf_header[1:]) except Exception as e: @@ -670,7 +672,6 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # response += self.connection.read() # if len(response) == size: # break - self.flushInput() response = self.connection.read(size) if no_response == True: try: @@ -679,6 +680,10 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, except ValueError as e: self.log.warning('no sas response %s' % (str(buf_header[1:]))) return None + else: + if int(binascii.hexlify(response)[2:4], 16) != buf_header[1]: + raise BadCommandIsRunning('response %s run %s' % (binascii.hexlify(response), binascii.hexlify(bytearray(buf_header)))) + # else: # # response += self.connection.read(size) # if (self.checkResponse(response, size) is False): @@ -691,9 +696,8 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # return None busy = False - self.flushInput() - response = self.checkResponse(response, binascii.hexlify(bytearray(buf_header))) self.log.debug('sas response %s', binascii.hexlify(response)) + response = self.checkResponse(response, binascii.hexlify(bytearray(buf_header))) if not response: response = None # self.log.info('no sas response') @@ -777,6 +781,10 @@ def events_poll(self, timeout=EVENTS_POLL_TIMEOUT, **kwargs): # self.my_log.write('RX %s: %s\n' % (time.time(), event.encode('hex'))) # self.my_log.flush() event = GPOLL[event.hex()] + if self.last_gpoll_event != event: + self.last_gpoll_event = event + else: + event = 'No activity' except KeyError as e: raise EMGGpollBadResponse except Exception as e: @@ -2867,14 +2875,14 @@ class SAS_USB(Sas): if __name__ == '__main__': - sas = Sas('/dev/ttyUSB0') + sas = Sas('/dev/ttyS4') print(sas.start()) print(sas.gaming_machine_ID()) sas.transaction = sas.AFT_get_last_transaction() print(sas.transaction) print(sas.send_meters_10_15()) print(sas.events_poll()) - print(sas.AFT_in(15)) + print(sas.AFT_in(1)) print(sas.AFT_clean_transaction_poll()) print(sas.send_meters_10_15()) From 37dbbbf22ba3765161ee621ab4802f06b0300a73 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Wed, 10 Jul 2024 16:45:09 +0300 Subject: [PATCH 08/11] Update sas.py --- sas.py | 217 +++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 141 insertions(+), 76 deletions(-) diff --git a/sas.py b/sas.py index 3c63116..82dcb88 100644 --- a/sas.py +++ b/sas.py @@ -418,7 +418,7 @@ class BadCRC(Exception): pass -class BadCommandIsRunning(Exception): +class BadCommand(Exception): pass @@ -450,20 +450,19 @@ def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_tra self.mashin_n = None self.aft_get_last_transaction = aft_get_last_transaction # self.last_transaction_n = None - self.denom = denom self.asset_number = '01000000' self.reg_key = '0000000000000000000000000000000000000000' self.POS_ID = 'B374A402' self.transaction = None self.my_key = '44' self.poll_adress = poll_adress + self.denom = denom self.sas_dump = sas_dump - self.timeout = timeout - self.last_gpoll_event = None + self.event = None if self.sas_dump: os.system('sudo touch /var/log/sas_dump.log') os.system('sudo chown colibri:colibri /var/log/sas_dump.log') - self.my_log = open('/var/log/sas_dump.log', 'w') + self.my_log = open('/var/log/sas_dump.log', 'a') self.my_log.close() if log == None: self.log = log_to_stderr() @@ -472,8 +471,10 @@ def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_tra self.log = log while 1: try: + # print 1 self.connection = serial.Serial(port=port, baudrate=19200, timeout=timeout) self.close() + self.timeout = timeout self.log.info('SAS Port OK!') break except: @@ -492,7 +493,7 @@ def clean_buffer(self): self.connection.reset_output_buffer() except Exception as e: self.log.error(e, exc_info=True) - # self.close() + self.close() def flush(self): try: @@ -501,24 +502,7 @@ def flush(self): self.connection.flush() except Exception as e: self.log.error(e, exc_info=True) - - def flushInput(self): - try: - if self.is_open() == False: - self.open() - self.connection.flushInput() - except Exception as e: - self.log.error(e, exc_info=True) - # self.close() - - def flushOutput(self): - try: - if self.is_open() == False: - self.open() - self.connection.flushOutput() - except Exception as e: - self.log.error(e, exc_info=True) - # self.close() + self.close() def start(self): self.log.info('Connecting SAS...') @@ -534,8 +518,7 @@ def start(self): except Exception as e: self.log.critical(e, exc_info=True) else: - self.flush() - # self.flushInput() + self.connection.flush() response = self.connection.read(1) if response == None: self.log.error('No SAS Connection') @@ -558,8 +541,7 @@ def close(self): def open(self): try: - if self.connection.isOpen() is not True: - self.connection.open() + self.connection.open() except: raise SASOpenError @@ -569,7 +551,7 @@ def _conf_event_port(self): self.connection.parity = serial.PARITY_NONE self.connection.stopbits = serial.STOPBITS_TWO self.open() - # self.clean_buffer() + def _conf_port(self): self.close() @@ -577,6 +559,7 @@ def _conf_port(self): self.connection.parity = serial.PARITY_MARK self.connection.stopbits = serial.STOPBITS_ONE self.open() + # self.clean_buffer() def crc(self, response, chk=False, seed=0): c = '' @@ -628,11 +611,6 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # self.poll_adres = '82' buf_header = [self.adress] - if self.sas_dump: - self.my_log = open('/var/log/sas_dump.log', 'a') - self.my_log.write('TX %s: %s\n' % (time.time(), '82'+ binascii.hexlify(bytearray(buf_header)))) - self.my_log.close() - # self.flush() self._conf_port() # self.connection.flushInput() # self.connection.write(('80' + self.mashin_n).decode("hex")) @@ -642,24 +620,25 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, buf_header.extend(command) buf_count = len(command) + # buf_header[2]=buf_count+2 if (crc_need == True): crc = CRC16Kermit().calculate(bytes(buf_header)) buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) self.log.debug(buf_header) - - # buf_header[2]=buf_count+2 - + # time.sleep(0.04) self.connection.write([self.poll_adress, self.adress]) - self.flush() + time.sleep(0.02) + self.close() self.connection.parity = serial.PARITY_SPACE - # self.open() + self.open() # self.connection.flushInput() # my_log = open('/home/colibri/dump.log', 'w') - - # self.my_log = open('/var/log/sas_dump.log', 'w') + if self.sas_dump: + self.my_log = open('/var/log/sas_dump.log', 'a') + self.my_log.write('TX %s: %s\n' % (time.time(), binascii.hexlify(bytearray(buf_header)))) + self.my_log.close() # print self.connection.portstr # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) - time.sleep(0.01) self.connection.write(buf_header[1:]) except Exception as e: @@ -669,7 +648,19 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, buffer = [] # t = time.time() # while time.time() - t < self.timeout: - # response += self.connection.read() + # tmp = self.connection.read(1) + # if not tmp: + # pass + # elif binascii.hexlify(tmp) == bytes(self.mashin_n.encode('utf-8')) and not response: + # response += tmp + # elif len(response) == 1 and no_response is False and binascii.hexlify(tmp) == binascii.hexlify( + # bytearray([buf_header[1]])): + # response += tmp + # elif len(response) == 1 and no_response is False and binascii.hexlify(tmp) != binascii.hexlify( + # bytearray([buf_header[1]])): + # response = b'' + # elif response: + # response += tmp # if len(response) == size: # break response = self.connection.read(size) @@ -678,12 +669,8 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # raise KeyError(response) return int(binascii.hexlify(response)) except ValueError as e: - self.log.warning('no sas response %s' % (str(buf_header[1:]))) + self.log.warning("wrong ardess or NACK") return None - else: - if int(binascii.hexlify(response)[2:4], 16) != buf_header[1]: - raise BadCommandIsRunning('response %s run %s' % (binascii.hexlify(response), binascii.hexlify(bytearray(buf_header)))) - # else: # # response += self.connection.read(size) # if (self.checkResponse(response, size) is False): @@ -696,10 +683,8 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, # return None busy = False + response = self.checkResponse(response) self.log.debug('sas response %s', binascii.hexlify(response)) - response = self.checkResponse(response, binascii.hexlify(bytearray(buf_header))) - if not response: - response = None # self.log.info('no sas response') return response # return None @@ -709,11 +694,11 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, busy = False return None - def checkResponse(self, rsp, cmd): + def checkResponse(self, rsp): if not rsp: # self.flush() # self.close() - raise NoSasConnection(cmd) + raise NoSasConnection('NoSasConnection') # if self.crc(rsp.hex(), True): # return rsp[1:-2] # raise BadCRC(rsp) @@ -732,14 +717,13 @@ def checkResponse(self, rsp, cmd): data = resp[1:-2] crc1 = hex(crc1).split('x')[-1] - crc1 = crc1.zfill(4) - # while len(crc1) < 4: - # crc1 = "0" + crc1 - if self.sas_dump: - self.my_log = open('/var/log/sas_dump.log', 'a') - self.my_log.write('RX %s: %s\n' % (time.time(), binascii.hexlify(resp))) - self.my_log.close() + while len(crc1) < 4: + crc1 = "0" + crc1 + + # print crc1 + # print CRC + # raise KeyError(crc1, CRC) if (CRC != crc1): # print "Wrong response command hash " + str(CRC) # print "////" + str(hex(crc1).split('x')[-1]) @@ -747,6 +731,10 @@ def checkResponse(self, rsp, cmd): raise BadCRC(self.hexlify(self.bytearray(resp))) # return False elif CRC == crc1: + if self.sas_dump: + self.my_log = open('/var/log/sas_dump.log', 'a') + self.my_log.write('RX %s: %s\n' % (time.time(), binascii.hexlify(resp))) + self.my_log.close() return data # raise BadCRC(self.hexlify(resp)) @@ -775,14 +763,14 @@ def events_poll(self, timeout=EVENTS_POLL_TIMEOUT, **kwargs): # if event != '': # break if event == '': - raise NoSasConnection + raise NoSasConnection('NoSasConnection') # event = None # return None # self.my_log.write('RX %s: %s\n' % (time.time(), event.encode('hex'))) # self.my_log.flush() event = GPOLL[event.hex()] - if self.last_gpoll_event != event: - self.last_gpoll_event = event + if event != self.event: + self.event = event else: event = 'No activity' except KeyError as e: @@ -876,8 +864,7 @@ def en_dis_game(self, game_number=None, en_dis=False, **kwargs): cmd = [0x09] cmd.extend([((game >> 8) & 0xFF), (game & 0xFF)]) - cmd.extend(self.bytearray(en_dis)) - # print cmd + cmd.extend(en_dis) if (self._send_command(cmd, True, crc_need=True) == self.adress): return game_number # else: @@ -920,8 +907,7 @@ def send_meters_10_15(self, denom=True, **kwargs): if (data is not None): meters = {} if denom == True: - meters['total_cancelled_credits_meter'] = round( - int((self.hexlify(self.bytearray(data[1:5])))) * self.denom, 2) + meters['total_cancelled_credits_meter'] = round(int((self.hexlify(self.bytearray(data[1:5])))) * self.denom, 2) meters['total_in_meter'] = round(int(self.hexlify(self.bytearray(data[5:9]))) * self.denom, 2) meters['total_out_meter'] = round(int(self.hexlify(self.bytearray(data[9:13]))) * self.denom, 2) meters['total_droup_meter'] = round(int(self.hexlify(self.bytearray(data[13:17]))) * self.denom, 2) @@ -2383,7 +2369,7 @@ def AFT_get_last_transaction(self, **kwargs): transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') else: - # if not self.transaction: + #if not self.transaction: transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') return transaction @@ -2870,8 +2856,91 @@ def int_to_bcd(self, number=0, lenght=5, **kwargs): class SAS_USB(Sas): - pass + def _send_command(self, command, no_response=False, timeout=None, crc_need=True, size=1): + # if timeout == None: + # timeout = self.timeout + 1 + # time.sleep(0.04) + busy = True + response = b'' + # self.my_log.flush() + try: + # if self.poll_adres == '82': + # self.poll_adres = '80' + # else: + # self.poll_adres = '82' + + buf_header = [self.adress] + self._conf_port() + # self.connection.write(('80' + self.mashin_n).decode("hex")) + # self.close() + # self.connection.parity = serial.PARITY_SPACE + # self.open() + + buf_header.extend(command) + buf_count = len(command) + # self.log.debug('%s', buf_header) + if (crc_need == True): + crc = CRC16Kermit().calculate(bytes(buf_header)) + buf_header.extend([((crc >> 8) & 0xFF), (crc & 0xFF)]) + self.log.debug(buf_header) + # time.sleep(0.04) + self.connection.write([self.poll_adress, self.adress]) + time.sleep(0.02) + # self.close() + self.connection.parity = serial.PARITY_SPACE + # self.open() + # my_log = open('/home/colibri/dump.log', 'w') + if self.sas_dump: + self.my_log = open('/var/log/sas_dump.log', 'a') + self.my_log.write('TX %s: %s\n' % (time.time(), binascii.hexlify(bytearray(buf_header)))) + self.my_log.close() + + # print self.connection.portstr + # self.connection.write([0x31, 0x32,0x33,0x34,0x35]) + self.connection.write(buf_header[1:]) + + + except Exception as e: + self.log.error(e, exc_info=True) + + try: + buffer = [] + # self.connection.flushInput() + # time.sleep(0.04) + # t = time.time() + # while time.time() - t < timeout: + response = self.connection.read(size) + # self.log.error('%s', response) + if no_response == True: + try: + # raise KeyError(response) + return int(binascii.hexlify(response)) + except ValueError as e: + self.log.warning("wrong ardess or NACK") + return None + # else: + # # response += self.connection.read(size) + # if (self.checkResponse(response, size) is False): + # break + # + # if time.time() - t >= timeout: + # self.log.warning("sas timeout") + # # buffer.append(response) + # # print response)) + # return None + + busy = False + response = self.checkResponse(response) + self.log.debug('sas response %s', response) + # self.log.info('no sas response') + return response + # return None + except Exception as e: + self.log.error(e, exc_info=True) + + busy = False + return None if __name__ == '__main__': @@ -2879,10 +2948,6 @@ class SAS_USB(Sas): print(sas.start()) print(sas.gaming_machine_ID()) sas.transaction = sas.AFT_get_last_transaction() - print(sas.transaction) - print(sas.send_meters_10_15()) - print(sas.events_poll()) - print(sas.AFT_in(1)) - print(sas.AFT_clean_transaction_poll()) - print(sas.send_meters_10_15()) - + while True: + print(sas.send_meters_10_15()) + print(sas.total_dollar_value_of_bills_meter()) From 13b96195e8124e04c7fc9e562452233104b1a847 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Tue, 30 Sep 2025 19:45:55 +0300 Subject: [PATCH 09/11] Update sas.py Fix --- sas.py | 585 ++++++++++++++++++++++++++++++++------------------------- 1 file changed, 326 insertions(+), 259 deletions(-) diff --git a/sas.py b/sas.py index 82dcb88..61e4eb6 100644 --- a/sas.py +++ b/sas.py @@ -444,21 +444,25 @@ class EMGGpollBadResponse(Exception): class Sas(): - def __init__(self, port, timeout=2, log=None, poll_adress=0x82, aft_get_last_transaction=True, sas_dump=False, denom=0.01): + def __init__(self, port, timeout=2, log=None, sleep_time=0.02, poll_adress=0x82, aft_check_last_transaction=True, sas_dump=False, denom=0.01, lock_time=0, get_aft_transaction_from_EMG=False,): # self.poll_adres = '82' self.adress = None self.mashin_n = None - self.aft_get_last_transaction = aft_get_last_transaction + self.sleep_time = sleep_time + self.lock_time = lock_time + self.aft_check_last_transaction = aft_check_last_transaction # self.last_transaction_n = None self.asset_number = '01000000' self.reg_key = '0000000000000000000000000000000000000000' self.POS_ID = 'B374A402' self.transaction = None - self.my_key = '44' + # self.my_key = '44' self.poll_adress = poll_adress self.denom = denom self.sas_dump = sas_dump self.event = None + self.last_AFT_lock_status = False + self.get_aft_transaction_from_EMG = get_aft_transaction_from_EMG if self.sas_dump: os.system('sudo touch /var/log/sas_dump.log') os.system('sudo chown colibri:colibri /var/log/sas_dump.log') @@ -627,7 +631,7 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, self.log.debug(buf_header) # time.sleep(0.04) self.connection.write([self.poll_adress, self.adress]) - time.sleep(0.02) + time.sleep(self.sleep_time) self.close() self.connection.parity = serial.PARITY_SPACE self.open() @@ -1198,13 +1202,15 @@ def total_hand_paid_cancelled_credit(self, **kwargs): def delay_game(self, delay_time=100, **kwargs): # 2E tmp = [] - delay_time = str(delay_time) - delay = '' + ('0' * (4 - len(delay_time)) + delay_time) - cmd = [0x2E] - count = 0 - for i in range(int(len(delay) / 2)): - cmd.append(int(delay[count:count + 2], 16)) - count += 2 + delay_time = self.mony_to_hex(delay_time, 2, False) + # delay_time = str(delay_time) + # delay = '' + ('0' * (4 - len(delay_time)) + delay_time) + cmd = '2E' + delay_time + cmd = self.cmd_to_list(cmd) + # count = 0 + # for i in range(int(len(delay) / 2)): + # cmd.append(int(delay[count:count + 2], 16)) + # count += 2 if self._send_command(cmd, True, crc_need=True) == self.adress: return True else: @@ -1512,12 +1518,14 @@ def total_number_of_games_impimented(self, **kwargs): return str(self.hexlify(self.bytearray(data[1:]))) return None - def game_meters(self, n=None, denom=True, **kwargs): + def game_meters(self, game_number=None, denom=True, **kwargs): # 52 cmd = [0x52] - if n == None: - n == self.selected_game_number(in_hex=False) - cmd.extend([((n >> 8) & 0xFF), (n & 0xFF)]) + if game_number == None: + game_number == self.selected_game_number(in_hex=False) + else: + game_number = int(game_number, 16) + cmd.extend([((game_number >> 8) & 0xFF), (game_number & 0xFF)]) data = self._send_command(cmd, crc_need=True, size=22) if (data is not None): @@ -1537,13 +1545,15 @@ def game_meters(self, n=None, denom=True, **kwargs): return meters return None - def game_configuration(self, n=None, **kwargs): + def game_configuration(self, game_number=None, **kwargs): # 53 # FIXME: game_configuration - if n == None: - n = self.selected_game_number(in_hex=False) + if game_number == None: + game_number = self.selected_game_number(in_hex=False) + else: + game_number = int(game_number, 16) cmd = [0x53] - cmd.extend([(n & 0xFF), ((n >> 8) & 0xFF)]) + cmd.extend([(game_number & 0xFF), ((game_number >> 8) & 0xFF)]) data = self._send_command(cmd, True, crc_need=True) if (data is not None): @@ -1744,7 +1754,11 @@ def redeem_ticket(self, transfer_code=0, transfer_amount=0, parsing_code=0, vali return data[1] return None - def AFT_jp(self, mony, amount=1, lock_timeout=0, games=None, **kwargs): + def AFT_change_transaction(self, transaction='2020202020202020202020202020202021'): + self.transaction = int(transaction, 16) + return True + + def AFT_jp(self, mony, amount=1, lock_timeout=None, games=None, **kwargs): # self.lock_emg(lock_time=500, condition=1) if self.denom > 0.01: return None @@ -1769,46 +1783,58 @@ def AFT_jp(self, mony, amount=1, lock_timeout=0, games=None, **kwargs): my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') if mony == None: - mony = str(self.current_credits(denom=False)) - else: - mony = str(int((mony / self.denom))) - mony = mony.replace('.', '') - mony = '0' * (10 - len(mony)) + mony + mony = self.current_credits(denom=True) + mony_1 = mony_2 = mony_3 = self.mony_to_hex(0, 5) if amount == 1: - mony_1 = mony - mony_2 = '0000000000' - mony_3 = '0000000000' + mony_1 = self.mony_to_hex(mony, 5) elif amount == 2: - mony_1 = '0000000000' - mony_2 = mony - mony_3 = '0000000000' + mony_2 = self.mony_to_hex(mony, 5) elif amount == 3: - mony_1 = '0000000000' - mony_2 = '0000000000' - mony_3 = mony + mony_3 = self.mony_to_hex(mony, 5) else: raise AFTBadAmount - + self.AFT_register() + if lock_timeout is None: + lock_timeout = self.lock_time + self.last_AFT_lock_status = False + if lock_timeout > 0: + lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + if lock_data == None or lock_data == False: + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False + if lock_data['game_lock_status'] != '00': + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False last_transaction = self.AFT_format_transaction() len_transaction_id = hex(len(last_transaction) // 2)[2:] if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='11', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key, transfer_flag='00') - new_cmd = [] - count = 0 - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 + times=my_time, transfer_flag='00') + cmd = '72' + hex(int(len(cmd) // 2))[2:] + cmd + new_cmd = self.cmd_to_list(cmd) + # count = 0 + # for i in range(int(len(cmd) / 2)): + # new_cmd.append(int(cmd[count:count + 2], 16)) + # count += 2 response = None - self.AFT_register() - if lock_timeout > 0: - self.AFT_game_lock(lock_timeout, condition=1) + # self.AFT_register() + # if lock_timeout == 0: + # lock_timeout = self.lock_time + # if lock_timeout > 0: + # lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + # if lock_data['game_lock_status'] != '00': + # self.log.warning('EMG is not locked') + # return None data = self._send_command(new_cmd, crc_need=True, size=82) if (data is not None): a = int(self.hexlify(self.bytearray(data[26:27])), 16) @@ -1818,9 +1844,9 @@ def AFT_jp(self, mony, amount=1, lock_timeout=0, games=None, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), @@ -1832,53 +1858,61 @@ def AFT_jp(self, mony, amount=1, lock_timeout=0, games=None, **kwargs): # self.log.warning('AFT UNREGISTER ERROR: won to host') return response - def AFT_initial_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): + def AFT_initial_out(self, mony=None, amount=1, lock_timeout=None, **kwargs): # self.lock_emg(lock_time=500, condition=1) if self.denom > 0.01: return None my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') if mony == None: - mony = str(self.current_credits(denom=False)) - else: - mony = str(int((mony / self.denom))) - mony = mony.replace('.', '') - mony = '0' * (10 - len(mony)) + mony + mony = self.current_credits(denom=True) + mony_1 = mony_2 = mony_3 = self.mony_to_hex(0, 5) if amount == 1: - mony_1 = mony - mony_2 = '0000000000' - mony_3 = '0000000000' + mony_1 = self.mony_to_hex(mony, 5) elif amount == 2: - mony_1 = '0000000000' - mony_2 = mony - mony_3 = '0000000000' + mony_2 = self.mony_to_hex(mony, 5) elif amount == 3: - mony_1 = '0000000000' - mony_2 = '0000000000' - mony_3 = mony + mony_3 = self.mony_to_hex(mony, 5) else: raise AFTBadAmount - + self.AFT_register() + if lock_timeout is None: + lock_timeout = self.lock_time + self.last_AFT_lock_status = False + if lock_timeout > 0: + lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + if lock_data == None or lock_data == False: + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False + if lock_data['game_lock_status'] != '00': + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False last_transaction = self.AFT_format_transaction() len_transaction_id = hex(len(last_transaction) // 2)[2:] if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='00', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key, transfer_flag='0a') - new_cmd = [] - count = 0 - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 + times=my_time, transfer_flag='0a') + cmd = '72' + hex(int(len(cmd) // 2))[2:] + cmd + new_cmd = self.cmd_to_list(cmd) response = None - self.AFT_register() - if lock_timeout > 0: - self.AFT_game_lock(lock_timeout, condition=1) + # self.AFT_register() + # if lock_timeout == 0: + # lock_timeout = self.lock_time + # if lock_timeout > 0: + # lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + # if lock_data['game_lock_status'] != '00': + # self.log.warning('EMG is not locked') + # return None try: data = self._send_command(new_cmd, crc_need=True, size=82) if (data is not None): @@ -1889,9 +1923,9 @@ def AFT_initial_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), @@ -1905,53 +1939,61 @@ def AFT_initial_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): # self.log.warning('AFT UNREGISTER ERROR: out') return response - def AFT_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): + def AFT_out(self, mony=None, amount=1, lock_timeout=None, **kwargs): # self.lock_emg(lock_time=500, condition=1) if self.denom > 0.01: return None my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') if mony == None: - mony = str(self.current_credits(denom=False)) - else: - mony = str(int((mony / self.denom))) - mony = mony.replace('.', '') - mony = '0' * (10 - len(mony)) + mony + mony = self.current_credits(denom=True) + mony_1 = mony_2 = mony_3 = self.mony_to_hex(0, 5) if amount == 1: - mony_1 = mony - mony_2 = '0000000000' - mony_3 = '0000000000' + mony_1 = self.mony_to_hex(mony, 5) elif amount == 2: - mony_1 = '0000000000' - mony_2 = mony - mony_3 = '0000000000' + mony_2 = self.mony_to_hex(mony, 5) elif amount == 3: - mony_1 = '0000000000' - mony_2 = '0000000000' - mony_3 = mony + mony_3 = self.mony_to_hex(mony, 5) else: raise AFTBadAmount - + self.AFT_register() + if lock_timeout is None: + lock_timeout = self.lock_time + self.last_AFT_lock_status = False + if lock_timeout > 0: + lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + if lock_data == None or lock_data == False: + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False + if lock_data['game_lock_status'] != '00': + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False last_transaction = self.AFT_format_transaction() len_transaction_id = hex(len(last_transaction) // 2)[2:] if len(len_transaction_id) < 2: len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '{index}00{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key, transfer_flag='00') - new_cmd = [] - count = 0 - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 + times=my_time, transfer_flag='00') + cmd = '72' + hex(int(len(cmd) // 2))[2:] + cmd + new_cmd = self.cmd_to_list(cmd) response = None - self.AFT_register() - if lock_timeout > 0: - self.AFT_game_lock(lock_timeout, condition=1) + # self.AFT_register() + # if lock_timeout == 0: + # lock_timeout = self.lock_time + # if lock_timeout > 0: + # lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + # if lock_data['game_lock_status'] != '00': + # self.log.warning('EMG is not locked') + # return None try: data = self._send_command(new_cmd, crc_need=True, size=82) if (data is not None): @@ -1962,9 +2004,9 @@ def AFT_out(self, mony=None, amount=1, lock_timeout=0, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), @@ -1982,23 +2024,7 @@ def AFT_cashout_enable(self, amount=1, **kwargs): my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') - mony = '0000000000' - - if amount == 1: - mony_1 = mony - mony_2 = '0000000000' - mony_3 = '0000000000' - elif amount == 2: - mony_1 = '0000000000' - mony_2 = mony - mony_3 = '0000000000' - elif amount == 3: - mony_1 = '0000000000' - mony_2 = '0000000000' - mony_3 = mony - else: - raise AFTBadAmount - + mony_1 = mony_2 = mony_3 = self.mony_to_hex(0, 5) last_transaction = self.AFT_format_transaction() len_transaction_id = hex(len(last_transaction) // 2)[2:] if len(len_transaction_id) < 2: @@ -2006,15 +2032,12 @@ def AFT_cashout_enable(self, amount=1, **kwargs): elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}00{index}{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '00{index}{transfer_code}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='80', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key, transfer_flag='02') - new_cmd = [] - count = 0 - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 + times=my_time, transfer_flag='02') + cmd = '72' + hex(int(len(cmd) // 2))[2:] + cmd + new_cmd = self.cmd_to_list(cmd) self.AFT_register() response = None @@ -2028,9 +2051,9 @@ def AFT_cashout_enable(self, amount=1, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), @@ -2052,7 +2075,7 @@ def AFT_cashout_enable(self, amount=1, **kwargs): pass return True - def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): + def AFT_won(self, mony, amount=1, games=None, lock_timeout=None, **kwargs): if self.denom > 0.01: return None @@ -2079,26 +2102,31 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') - mony = str(int((mony / self.denom))) - mony = mony.replace('.', '') - mony = '0' * (10 - len(mony)) + mony + mony_1 = mony_2 = mony_3 = self.mony_to_hex(0, 5) if amount == 1: - mony_1 = mony - mony_2 = '0000000000' - mony_3 = '0000000000' + mony_1 = self.mony_to_hex(mony, 5) elif amount == 2: - mony_1 = '0000000000' - mony_2 = mony - mony_3 = '0000000000' + mony_2 = self.mony_to_hex(mony, 5) elif amount == 3: - mony_1 = '0000000000' - mony_2 = '0000000000' - mony_3 = mony + mony_3 = self.mony_to_hex(mony, 5) else: raise AFTBadAmount - # if lock == True: - # self.lock_emg(lock_time=500, condition=0) - # self.lock_emg() + self.AFT_register() + if lock_timeout is None: + lock_timeout = self.lock_time + self.last_AFT_lock_status = False + if lock_timeout > 0: + lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + if lock_data == None or lock_data == False: + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False + if lock_data['game_lock_status'] != '00': + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False last_transaction = self.AFT_format_transaction() len_transaction_id = hex(int(len(last_transaction) // 2))[2:] @@ -2107,21 +2135,15 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{transfer_code}{index}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '{transfer_code}{index}{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='0000', index='10', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key, transfer_flag='00') + times=my_time, transfer_flag='00') + cmd = '72' + hex(int(len(cmd) // 2))[2:] + cmd - new_cmd = [] - count = 0 - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 + new_cmd = self.cmd_to_list(cmd) response = None - self.AFT_register() - if lock_timeout > 0: - self.AFT_game_lock(lock_timeout, condition=3) try: data = self._send_command(new_cmd, crc_need=True, size=82) if (data is not None): @@ -2132,9 +2154,9 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), @@ -2147,29 +2169,36 @@ def AFT_won(self, mony, amount=1, games=None, lock_timeout=0, **kwargs): # self.log.warning('AFT UNREGISTER ERROR: won') return response - def AFT_in(self, mony, amount=1, lock_timeout=0, **kwargs): + def AFT_in(self, mony, amount=1, lock_timeout=None, **kwargs): if self.denom > 0.01: return None my_time = datetime.datetime.now() my_time = datetime.datetime.strftime(my_time, '%m%d%Y') - mony = str(int((mony / self.denom))) - mony = mony.replace('.', '') - mony = '0' * (10 - len(mony)) + mony + mony_1 = mony_2 = mony_3 = self.mony_to_hex(0, 5) if amount == 1: - mony_1 = mony - mony_2 = '0000000000' - mony_3 = '0000000000' + mony_1 = self.mony_to_hex(mony, 5) elif amount == 2: - mony_1 = '0000000000' - mony_2 = mony - mony_3 = '0000000000' + mony_2 = self.mony_to_hex(mony, 5) elif amount == 3: - mony_1 = '0000000000' - mony_2 = '0000000000' - mony_3 = mony + mony_3 = self.mony_to_hex(mony, 5) else: raise AFTBadAmount - + self.AFT_register() + if lock_timeout is None: + lock_timeout = self.lock_time + self.last_AFT_lock_status = False + if lock_timeout > 0: + lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + if lock_data == None or lock_data == False: + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False + if lock_data['game_lock_status'] != '00': + self.log.warning('EMG is not locked') + self.last_AFT_lock_status = True + data = self.AFT_clean_transaction_poll() + return False last_transaction = self.AFT_format_transaction() len_transaction_id = hex(int(len(last_transaction) // 2))[2:] # raise KeyError(last_transaction, len_transaction_id) @@ -2177,24 +2206,21 @@ def AFT_in(self, mony, amount=1, lock_timeout=0, **kwargs): len_transaction_id = '0' + len_transaction_id elif len(len_transaction_id) % 2 == 1: len_transaction_id = '0' + len_transaction_id - cmd = '72{my_key}{transfer_code}{index}00{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( + cmd = '{transfer_code}{index}00{mony_1}{mony_2}{mony_3}{transfer_flag}{asett}{key}{len_transaction}{transaction}{times}0C0000'.format( transfer_code='00', index='00', mony_1=mony_1, mony_2=mony_2, mony_3=mony_3, asett=self.asset_number, key=self.reg_key, len_transaction=len_transaction_id, transaction=last_transaction, - times=my_time, my_key=self.my_key, transfer_flag='00') - new_cmd = [] - count = 0 - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 - + times=my_time, transfer_flag='00') + cmd = '72' + hex(int(len(cmd) // 2))[2:] + cmd + new_cmd = self.cmd_to_list(cmd) + response = None # self.AFT_register() + # if lock_timeout == 0: + # lock_timeout = self.lock_time # if lock_timeout > 0: - # self.AFT_game_lock(lock_timeout, condition=0) - response = None - self.AFT_register() - - if lock_timeout > 0: - self.AFT_game_lock(lock_timeout, condition=0) + # lock_data = self.AFT_game_lock_and_status_request(lock_timeout=lock_timeout) + # if lock_data['game_lock_status'] != '00': + # self.log.warning('EMG is not locked') + # return None try: data = self._send_command(new_cmd, crc_need=True, size=82) if (data is not None): @@ -2205,9 +2231,9 @@ def AFT_in(self, mony, amount=1, lock_timeout=0, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), @@ -2232,10 +2258,7 @@ def AFT_clean_transaction_poll(self, register=False, **kwargs): # time.sleep(0.7) cmd = '7202FF00' count = 0 - new_cmd = [] - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 + new_cmd = self.cmd_to_list(cmd) response = None try: data = self._send_command(new_cmd, crc_need=True, size=90) @@ -2247,14 +2270,17 @@ def AFT_clean_transaction_poll(self, register=False, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), 'Transaction ID': self.hexlify(self.bytearray(data[27:(27 + a)])) } + if self.last_AFT_lock_status == True: + response['Transfer status'] = 'Gaming machine not locked (transfer specified lock required)' + return response if register == True: # try: self.AFT_unregister() @@ -2263,7 +2289,7 @@ def AFT_clean_transaction_poll(self, register=False, **kwargs): elif hex(self.transaction)[2:] == response['Transaction ID']: return response else: - if self.aft_get_last_transaction == True: + if self.aft_check_last_transaction == True: raise BadTransactionID('last: %s, new:%s ' % ( hex(self.transaction)[2:], response['Transaction ID'])) else: @@ -2271,14 +2297,16 @@ def AFT_clean_transaction_poll(self, register=False, **kwargs): hex(self.transaction)[2:], response['Transaction ID'])) except BadCRC: pass + if self.last_AFT_lock_status: + self.last_AFT_lock_status = False return False - def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfer_type=0x00, cashable_amount=0, - restricted_amount=0, non_restricted_amount=0, transfer_flags=0x00, - asset_number=b'\x00\x00\x00\x00\x00', registration_key=0, transaction_ID_lenght=0x00, + def AFT_transfer_funds(self, security_code=44, transfer_code=00, transaction_index=00, transfer_type=00, cashable_amount=0, + restricted_amount=0, non_restricted_amount=0, transfer_flags=00, + asset_number=b'0000000000', registration_key=0, transaction_ID_lenght=0x00, transaction_ID='', expiration=0, pool_ID=0, reciept_data='', lock_timeout=0, **kwargs): # 72 - cmd = [0x72, 0x00] + cmd = [0x72, security_code] cmd.append(transfer_code) cmd.append(transaction_index) cmd.append(transfer_type) @@ -2298,7 +2326,8 @@ def AFT_transfer_funds(self, transfer_code=0x00, transaction_index=0x00, transfe cmd.extend(self.bcd_coder_array(lock_timeout, 2)) cmd[1] = len(transaction_ID) + len(transaction_ID) + 53 - + new_cmd = self.cmd_to_list(cmd) + cmd = new_cmd data = self._send_command(cmd, crc_need=True) if (data is not None): aft_statement['transaction_buffer_position'] = int(self.hexlify(self.bytearray(data[2:3])), 16) @@ -2343,7 +2372,7 @@ def AFT_get_last_transaction(self, **kwargs): self.log.warning('AFT no transaction') if (data is not None): try: - # if self.aft_get_last_transaction == False: + # if self.aft_check_last_transaction == False: # raise ValueError count = int(self.hexlify(self.bytearray(data[26:27])), 16) @@ -2372,9 +2401,12 @@ def AFT_get_last_transaction(self, **kwargs): #if not self.transaction: transaction = int('2020202020202020202020202020202021', 16) self.log.warning('AFT no transaction') + self.transaction = transaction return transaction - def AFT_format_transaction(self, get_from_emg=False, **kwargs): + def AFT_format_transaction(self, get_from_emg=None, **kwargs): + if get_from_emg is None: + get_from_emg = self.get_aft_transaction_from_EMG if get_from_emg == True: self.transaction = self.AFT_get_last_transaction() self.transaction += 1 @@ -2386,9 +2418,12 @@ def AFT_format_transaction(self, get_from_emg=False, **kwargs): count += 2 tmp.reverse() for i in range(len(tmp)): - if int(tmp[i], 16) >= 124: + if int(tmp[i], 16) >= 126: tmp[i] = '20' - tmp[i + 1] = hex(int(tmp[i + 1], 16) + 1)[2:] + if int(tmp[i + 1], 16) + 1 <= 32: + tmp[i + 1] = '20' + else: + tmp[i + 1] = hex(int(tmp[i + 1], 16) + 1)[2:] tmp.reverse() response = '' for i in tmp: @@ -2448,34 +2483,33 @@ def AFT_register_gaming_machine(self, reg_code=0xff, **kwargs): return aft_statement return None - def AFT_game_lock(self, lock_timeout=100, condition='01', **kwargs): - return self.AFT_game_lock_and_status_request(lock_code='00', lock_timeout=lock_timeout, - condition=condition) - - def AFT_game_unlock(self, **kwargs): - return self.AFT_game_lock_and_status_request(lock_code='80') + # def AFT_game_lock(self, lock_timeout=100, condition='01', **kwargs): + # return self.AFT_game_lock_and_status_request(lock_code='00', lock_timeout=lock_timeout, + # condition=condition) + # + # def AFT_game_unlock(self, **kwargs): + # return self.AFT_game_lock_and_status_request(lock_code='80') - def AFT_game_lock_and_status_request(self, lock_code='00', lock_time=0, condition='01', **kwargs): + def AFT_game_lock_and_status_request(self, lock_code='00', lock_timeout=200, condition='01', **kwargs): # 74 - lock_time = str(lock_time) - if len(lock_time) == 1: - lock_time = '000%s' % (lock_time) - elif len(lock_time) == 2: - lock_time = '00%s' % (lock_time) - elif len(lock_time) == 3: - lock_time = '0%s' % (lock_time) - elif len(lock_time) == 4: - lock_time = '%s' % (lock_time) - else: - raise ValueError('Invalid time') + try: + lock_time = self.mony_to_hex(lock_timeout, 2, False) + except Exception as e: + raise ValueError(e.__str__()) + # if len(lock_time) == 1: + # lock_time = '000%s' % (lock_time) + # elif len(lock_time) == 2: + # lock_time = '00%s' % (lock_time) + # elif len(lock_time) == 3: + # lock_time = '0%s' % (lock_time) + # elif len(lock_time) == 4: + # lock_time = '%s' % (lock_time) + # else: + # raise ValueError('Invalid time') cmd = '74%s%s%s' % (lock_code, condition, lock_time) - new_cmd = [] - count = 0 - for i in range(int(len(cmd) / 2)): - new_cmd.append(int(cmd[count:count + 2], 16)) - count += 2 + new_cmd = self.cmd_to_list(cmd) response = self._send_command(new_cmd, crc_need=True, size=40) - if (response): + if (response is not None): aft_statement = {} aft_statement['asset_number'] = str(self.hexlify(self.bytearray(response[2:6]))) aft_statement['game_lock_status'] = str(self.hexlify(self.bytearray(response[6:7]))) @@ -2503,9 +2537,9 @@ def AFT_cansel_request(self, **kwargs): 'Transfer status': AFT_TRANSFER_STATUS[self.hexlify(self.bytearray(data[3:4]))], 'Receipt status': AFT_RECEIPT_STATUS[self.hexlify(self.bytearray(data[4:5]))], 'Transfer type': AFT_TRANSFER_TYPE[self.hexlify(self.bytearray(data[5:6]))], - 'Cashable amount': int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, - 'Restricted amount': int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, - 'Nonrestricted amount': int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, + 'Cashable amount': round(int(self.hexlify(self.bytearray(data[6:11]))) * self.denom, 2), + 'Restricted amount': round(int(self.hexlify(self.bytearray(data[11:16]))) * self.denom, 2), + 'Nonrestricted amount': round(int(self.hexlify(self.bytearray(data[16:21]))) * self.denom, 2), 'Transfer flags': self.hexlify(self.bytearray(data[21:22])), 'Asset number': self.hexlify(self.bytearray(data[22:26])), 'Transaction ID length': self.hexlify(self.bytearray(data[26:27])), @@ -2624,19 +2658,20 @@ def initiate_legacy_bonus_pay(self, mony, tax='00', games=None, **kwargs): if game_selected == None: return None elif game_selected == 0: - return None + return 'NoGame' elif game_selected < 0: - return None - - cmd = str(int(round(mony / self.denom, 2))) - # cmd = cmd.replace('.', '') - cmd = '0' * (8 - len(cmd)) + cmd - my_cmd = cmd + tax - cmd = [0x8A] - count = 0 - for i in range(int(len(my_cmd) / 2)): - cmd.append(int(my_cmd[count:count + 2], 16)) - count += 2 + return 'NoGame' + cmd = '8A' + self.mony_to_hex(mony, 4) + tax + cmd = self.cmd_to_list(cmd) + # cmd = str(int(round(mony / self.denom, 2))) + # # cmd = cmd.replace('.', '') + # cmd = '0' * (8 - len(cmd)) + cmd + # my_cmd = cmd + tax + # cmd = [0x8A] + # count = 0 + # for i in range(int(len(my_cmd) / 2)): + # cmd.append(int(my_cmd[count:count + 2], 16)) + # count += 2 if (self._send_command(cmd, True, crc_need=True) == self.adress): return True # else: @@ -2692,9 +2727,10 @@ def meters_95_98(self, **kwargs): # 99 return - def legacy_bonus_meters(self, denom=True, n=0, **kwargs): + def legacy_bonus_meters(self, denom=True, game_number='0000', **kwargs): # 9A - cmd = [0x9A, ((n >> 8) & 0xFF), (n & 0xFF)] + game_number = int(game_number, 16) + cmd = [0x9A, ((game_number >> 8) & 0xFF), (game_number & 0xFF)] # cmd.extend([(n&0xFF), ((n>>8)&0xFF)]) # cmd=[0x19] data = self._send_command(cmd, crc_need=True, size=18) @@ -2819,8 +2855,6 @@ def event_response_to_long_poll(self, **kwargs): # FF return - def bcd_coder_array(self, value=0, lenght=4, **kwargs): - return self.int_to_bcd(value, lenght) def bytearray(self, data): return data.hex() @@ -2829,7 +2863,11 @@ def hexlify(self, data): data = data.replace('-', '') return data - def int_to_bcd(self, number=0, lenght=5, **kwargs): + + def bcd_coder_array(self, value=0, lenght=5): + return self.int_to_bcd(value, lenght) + + def int_to_bcd(self, number=0, lenght=5): n = 0 m = 0 bval = 0 @@ -2839,7 +2877,7 @@ def int_to_bcd(self, number=0, lenght=5, **kwargs): result.extend([0x00]) while (p >= 0): if (number != 0): - digit = number % 10 + digit = int(number % 10) number = number / 10 m = m + 1 else: @@ -2854,6 +2892,20 @@ def int_to_bcd(self, number=0, lenght=5, **kwargs): n = n + 1 return result + def mony_to_hex(self, mony=0, lenght=5, denom=True): + if denom is True: + mony = str(int((mony / self.denom))) + else: + mony = str(int(mony)) + mony = mony.replace('.', '') + lenght = lenght * 2 + mony = '0' * (lenght - len(mony)) + mony + return mony + + def cmd_to_list(self, cmd): + intArray = list(map(lambda x: int(x, 16), + [cmd[i:i + 2] for i in range(0, len(cmd), 2)])) + return intArray class SAS_USB(Sas): @@ -2886,7 +2938,7 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, self.log.debug(buf_header) # time.sleep(0.04) self.connection.write([self.poll_adress, self.adress]) - time.sleep(0.02) + time.sleep(self.sleep_time) # self.close() self.connection.parity = serial.PARITY_SPACE # self.open() @@ -2942,12 +2994,27 @@ def _send_command(self, command, no_response=False, timeout=None, crc_need=True, busy = False return None +def test_aft(types='in', mony=1, port='/dev/ttyS4'): + sas = Sas(port) + print(sas.start()) + print(sas.gaming_machine_ID()) + sas.transaction = sas.AFT_get_last_transaction() + if types == 'in': + print(sas.AFT_in(mony)) + elif types == 'out': + print(sas.AFT_out()) + elif types == 'won': + print(sas.AFT_won(mony)) + print(sas.AFT_clean_transaction_poll()) if __name__ == '__main__': sas = Sas('/dev/ttyS4') + sas.mony_to_hex(10.00) print(sas.start()) print(sas.gaming_machine_ID()) sas.transaction = sas.AFT_get_last_transaction() - while True: - print(sas.send_meters_10_15()) - print(sas.total_dollar_value_of_bills_meter()) + print (sas.AFT_in(10, lock_timeout=10)) + # print(sas.AFT_clean_transaction_poll()) + # while True: + # print(sas.send_meters_10_15()) + # print(sas.total_dollar_value_of_bills_meter()) From 14638bc91fe33e49fc71c8108a82a87c9e905783 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Tue, 30 Sep 2025 19:47:22 +0300 Subject: [PATCH 10/11] Update sas.py Fix From 95d273f2d97be210c984333c61372955bedb8eb6 Mon Sep 17 00:00:00 2001 From: Grigor Kolev Date: Tue, 30 Sep 2025 19:52:08 +0300 Subject: [PATCH 11/11] Update sas.py FIX