diff --git a/eSSP/constants.py b/eSSP/constants.py index a74d555..0a5202d 100644 --- a/eSSP/constants.py +++ b/eSSP/constants.py @@ -1,62 +1,93 @@ -SSP_RESPONSE_ERROR = 0xFF -SSP_RESPONSE_TIMEOUT = 0xFF -SSP_RESPONSE_OK = 0xF0 -ENABLED = 0x01 -DISABLED = 0x00 -SSP_POLL_RESET = 0xF1 -SSP_POLL_READ = 0xEF #next byte is channel (0 for unknown) -SSP_POLL_CREDIT = 0xEE #next byte is channel -SSP_POLL_REJECTING = 0xED -SSP_POLL_REJECTED = 0xEC -SSP_POLL_STACKING = 0xCC -SSP_POLL_STACKED = 0xEB -SSP_POLL_SAFE_JAM = 0xEA -SSP_POLL_UNSAFE_JAM = 0xE9 -SSP_POLL_DISABLED = 0xE8 -SSP_POLL_FRAUD_ATTEMPT = 0xE6 #next byte is channel -SSP_POLL_STACKER_FULL = 0xE7 -SSP_POLL_CLEARED_FROM_FRONT = 0xE1 -SSP_POLL_CLEARED_INTO_CASHBOX = 0xE2 -SSP_POLL_BARCODE_VALIDATE = 0xE5 -SSP_POLL_BARCODE_ACK = 0xD1 -SSP_POLL_CASH_BOX_REMOVED = 0xE3 -SSP_POLL_CASH_BOX_REPLACED = 0xE4 -SSP_POLL_DISPENSING = 0xDA -SSP_POLL_DISPENSED = 0xD2 -SSP_POLL_JAMMED = 0xD5 -SSP_POLL_HALTED = 0xD6 -SSP_POLL_FLOATING = 0xD7 -SSP_POLL_FLOATED = 0xD8 -SSP_POLL_TIMEOUT = 0xD9 -SSP_POLL_INCOMPLETE_PAYOUT = 0xDC -SSP_POLL_INCOMPLETE_FLOAT = 0xDD -SSP_POLL_CASHBOX_PAID = 0xDE -SSP_POLL_COIN_CREDIT = 0xDF -SSP_POLL_EMPTYING = 0xC2 -SSP_POLL_EMPTY = 0xC3 -SSP_POLL_COINS_LOW = 0xD3 -SSP_POLL_COINS_EMPTY = 0xD4 -SSP_POLL_CALIBRATION_FAIL = 0x83 -SSP_POLL_SMART_EMPTYING = 0xB3 -SSP_POLL_SMART_EMPTIED = 0xB4 -SSP_POLL_STORED = 0xDB -SSP_POLL_DISPENSING = 0xDA -SSP_POLL_DISPENSED = 0xD2 -SSP_POLL_JAMMED = 0xD5 -SSP_POLL_HALTED = 0xD6 -SSP_POLL_FLOATING = 0xD7 -SSP_POLL_FLOATED = 0xD8 -SSP_POLL_TIMEOUT = 0xD9 -SSP_POLL_CASHBOX_PAID = 0xDE -SSP_POLL_COIN_CREDIT = 0xDF -NO_FAILUE = 0x00 -SENSOR_FLAP = 0x01 -SENSOR_EXIT = 0x02 -SENSOR_COIL1 = 0x03 -SENSOR_COIL2 = 0x04 -NOT_INITIALISED = 0x05 -CHECKSUM_ERROR = 0x06 -COMMAND_RECAL = 0x07 -SSP6_OPTION_BYTE_DO = 0x58 -NO_EVENT = 0xF9 +from enum import Enum +class Status(Enum): + SSP_RESPONSE_ERROR = (0xFF, "Error") + SSP_RESPONSE_TIMEOUT = (0xFF, "Timeout") + SSP_RESPONSE_OK = (0xF0, "Ok") + ENABLED = (0x01, "Enabled") + DISABLED = (0x00, "Disabled") + SSP_POLL_RESET = (0xF1, "Poll Reset") + SSP_POLL_READ = (0xEF, "Read note") #next byte is channel (0 for unknown) + SSP_POLL_CREDIT = (0xEE, "Credit note") #next byte is channel + SSP_POLL_REJECTING = (0xED, "Reject") + SSP_POLL_REJECTED = (0xEC, "Rejected") + SSP_POLL_STACKING = (0xCC, "Stacking") + SSP_POLL_STACKED = (0xEB, "Stacked") + SSP_POLL_SAFE_JAM = (0xEA, "Safe Jam") + SSP_POLL_UNSAFE_JAM = (0xE9, "Unsafe Jam") + SSP_POLL_DISABLED = (0xE8, "Poll Disabled") + SSP_POLL_FRAUD_ATTEMPT = (0xE6, "Fraud Attempt") #next byte is channel + SSP_POLL_STACKER_FULL = (0xE7, "Stacker Full") + SSP_POLL_CLEARED_FROM_FRONT = (0xE1, "Cleared from front") + SSP_POLL_CLEARED_INTO_CASHBOX = (0xE2, "Cleared into cashbox") + SSP_POLL_BARCODE_VALIDATE = (0xE5, "Barcode Validate") + SSP_POLL_BARCODE_ACK = (0xD1, "Barcode ACK") + SSP_POLL_CASH_BOX_REMOVED = (0xE3, "Cashbox Removed") + SSP_POLL_CASH_BOX_REPLACED = (0xE4, "Cashbox Replaced") + SSP_POLL_DISPENSING = (0xDA, "Dispensing") + SSP_POLL_DISPENSED = (0xD2, "Dispensed") + SSP_POLL_JAMMED = (0xD5, "Jammed") + SSP_POLL_HALTED = (0xD6, "Halted") + SSP_POLL_FLOATING = (0xD7, "Floating") + SSP_POLL_FLOATED = (0xD8, "Floated") + SSP_POLL_TIMEOUT = (0xD9, "Timeout") + SSP_POLL_INCOMPLETE_PAYOUT = (0xDC, "Incomplete Payout") + SSP_POLL_INCOMPLETE_FLOAT = (0xDD, "Incomplete Float") + SSP_POLL_CASHBOX_PAID = (0xDE, "Cashbox paid") + SSP_POLL_COIN_CREDIT = (0xDF, "Coin credit") + SSP_POLL_EMPTYING = (0xC2, "Emptying") + SSP_POLL_EMPTY = (0xC3, "Empty") + SSP_POLL_COINS_LOW = (0xD3, "Coins low") + SSP_POLL_COINS_EMPTY = (0xD4, "Coins empty") + SSP_POLL_CALIBRATION_FAIL = (0x83, "Calibration Failed") + SSP_POLL_SMART_EMPTYING = (0xB3, "Smart emptying") + SSP_POLL_SMART_EMPTIED = (0xB4, "Smart emptied") + SSP_POLL_STORED = (0xDB, "Stored") + NO_FAILUE = (0x00, "No Failue") + SENSOR_FLAP = (0x01, "Sensor Flap") + SENSOR_EXIT = (0x02, "Sensor Exit") + SENSOR_COIL1 = (0x03, "Sensor coil 1") + SENSOR_COIL2 = (0x04, "Sensor coil 2") + NOT_INITIALISED = (0x05, "Not initialized") + CHECKSUM_ERROR = (0x06, "Checksum error") + COMMAND_RECAL = (0x07, "Command recall") + SSP6_OPTION_BYTE_DO = (0x58, "Option Byte DO") + NO_EVENT = (0xF9, "No event") + + def __init__(self, value, debug_message): + self.value = value + self.debug_message = debug_message + + def __int__(self): + return self.value + + def __str__(self): + return self.debug_message + + def __eq__(self, other): + return self.value == other + +class Actions(Enum): + + ROUTE_TO_CASHBOX = (0, "Route to cashbox") + ROUTE_TO_STORAGE = (1, "Route to storage") + PAYOUT = (2, "Payout") + PAYOUT_NEXT_NOTE_NV11 = (3, "Payout next note") + STACK_NEXT_NOTE_NV11 = (4, "Stack next note") + DISABLE_VALIDATOR = (5, "Disable validator") + DISABLE_PAYOUT = (6, "Disable payout") + GET_NOTE_AMOUNT = (7, "Get note amount") + EMPTY_STORAGE = (8, "Empty storage & cleaning indexes") + + def __init__(self, value, debug_message): + self.value = value + self.debug_message = debug_message + + def __int__(self): + return self.value + + def __str__(self): + return self.debug_message + + def __eq__(self, other): + return self.value == other \ No newline at end of file diff --git a/eSSP/eSSP.py b/eSSP/eSSP.py index 590c7c5..7d29361 100755 --- a/eSSP/eSSP.py +++ b/eSSP/eSSP.py @@ -1,104 +1,100 @@ -#!/usr/bin/env python3 +# !/usr/bin/env python3 from ctypes import * from time import sleep import threading +from six.moves import queue -from .constants import * +from .constants import Status, Actions -# CONSTANTS FOR SIGNALS AND COMMANDS -# C STRUCTURES - -class SSP6_CHANNEL_DATA(Structure): +class Ssp6ChannelData(Structure): _fields_ = [("security", c_ubyte), - ("value", c_uint), - ("cc", c_char*4)] + ("value", c_uint), + ("cc", c_char*4)] + -class SSP6_SETUP_REQUEST_DATA(Structure): +class Ssp6SetupRequestData(Structure): _fields_ = [("UnitType", c_ubyte), - ("FirmwareVersion", c_char*5), - ("NumberOfChannels", c_uint), - ("ChannelData", SSP6_CHANNEL_DATA*20), - ("RealValueMultiplier", c_ulong), - ("ProtocolVersion", c_ubyte)] + ("FirmwareVersion", c_char*5), + ("NumberOfChannels", c_uint), + ("ChannelData", Ssp6ChannelData*20), + ("RealValueMultiplier", c_ulong), + ("ProtocolVersion", c_ubyte)] + -class SSP_POLL_EVENT6(Structure): +class SspPollEvent6(Structure): _fields_ = [("event", c_ubyte), - ("data1", c_ulong), - ("data2", c_ulong), - ("cc", c_char*4)] + ("data1", c_ulong), + ("data2", c_ulong), + ("cc", c_char*4)] -class SSP_POLL_DATA6(Structure): - _fields_ = [("events", SSP_POLL_EVENT6*20), - ("event_count", c_ubyte)] -class eSSP: +class SspPollData6(Structure): + _fields_ = [("events", SspPollEvent6*20), + ("event_count", c_ubyte)] + + +class eSSP(object): """Encrypted Smiley Secure Protocol Class""" def __init__(self, com_port, spp_address="0", nv11=False, debug=False): self.debug = debug self.nv11 = nv11 - self.actions = "" + self.actions = queue.Queue() self.actions_args = {} self.response_data = {} self.events = [] - self.response_data['getnoteamount_response'] = 9999 # There can't be 9999 notes in the storage - self.sspC = self.essp.ssp_init(com_port.encode(), spp_address.encode(), debug) - self.poll = SSP_POLL_DATA6() - setup_req = SSP6_SETUP_REQUEST_DATA() - #Check if the validator is present - if self.essp.ssp6_sync(self.sspC) != SSP_RESPONSE_OK: + self.response_data['getnoteamount_response'] = 9999 # There can't be 9999 notes in the storage + self.sspC = self.essp.Status.SSP_init(com_port.encode(), spp_address.encode(), debug) + self.poll = SspPollData6() + setup_req = Ssp6SetupRequestData() + # Check if the validator is present + if self.essp.ssp6_sync(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("NO VALIDATOR FOUND") self.close() - return False else: self.print_debug("Validator Found !") - #Try to setup encryption - if self.essp.ssp6_setup_encryption(self.sspC, c_ulonglong(0x123456701234567)) == SSP_RESPONSE_OK: + # Try to setup encryption + if self.essp.ssp6_setup_encryption(self.sspC, c_ulonglong(0x123456701234567)) == Status.SSP_RESPONSE_OK: self.print_debug("Encryption Setup") else: self.print_debug("Encryption Failed") - #Checking the version, make sure we are using ssp version 6 - if self.essp.ssp6_host_protocol(self.sspC, 0x06) != SSP_RESPONSE_OK: + # Checking the version, make sure we are using ssp version 6 + if self.essp.ssp6_host_protocol(self.sspC, 0x06) != Status.SSP_RESPONSE_OK: self.print_debug(self.essp.ssp6_host_protocol(self.sspC, 0x06)) self.print_debug("Host Protocol Failed") self.close() - return False - #Get some information about the validator - if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != SSP_RESPONSE_OK: + # Get some information about the validator + if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != Status.SSP_RESPONSE_OK: self.print_debug("Setup Request Failed") self.close() - return False - + if self.debug: - print("Firmware %s "%(setup_req.FirmwareVersion.decode('utf8'))) + print("Firmware %s " % (setup_req.FirmwareVersion.decode('utf8'))) print("Channels : ") for i,channel in enumerate(setup_req.ChannelData): - print("Channel %s : %s %s"%(str(i+1),str(channel.value),channel.cc.decode())) + print("Channel %s : %s %s" % (str(i+1), str(channel.value), channel.cc.decode())) - #Enable the validator - if self.essp.ssp6_enable(self.sspC) != SSP_RESPONSE_OK: + # Enable the validator + if self.essp.ssp6_enable(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("Enable Failed") self.close() - return False if setup_req.UnitType == 0x03: for channel in enumerate(setup_req.ChannelData): - self.essp.ssp6_set_coinmech_inhibits(self.sspC, channel.value, channel.cc, ENABLED) + self.essp.ssp6_set_coinmech_inhibits(self.sspC, channel.value, channel.cc, Status.ENABLED) else: if setup_req.UnitType == 0x06 or setup_req.UnitType == 0x07: - #Enable the payout unit - if self.essp.ssp6_enable_payout(self.sspC, setup_req.UnitType) != SSP_RESPONSE_OK: + # Enable the payout unit + if self.essp.ssp6_enable_payout(self.sspC, setup_req.UnitType) != Status.SSP_RESPONSE_OK: self.print_debug("Payout Enable Failed") self.close() - return False # Set the inhibits ( enable all note acceptance ) - if self.essp.ssp6_set_inhibits(self.sspC,0xFF,0xFF) != SSP_RESPONSE_OK: + if self.essp.ssp6_set_inhibits(self.sspC, 0xFF, 0xFF) != Status.SSP_RESPONSE_OK: self.print_debug("Inhibits Failed") self.close() - return False t1 = threading.Thread(target=self.system_loop) t1.start() @@ -109,27 +105,26 @@ def close(self): def reject(self): """Reject the bill if there is one""" - if self.essp.ssp6_reject != SSP_RESPONSE_OK: + if self.essp.ssp6_reject != Status.SSP_RESPONSE_OK: self.print_debug("Error to reject bill OR nothing to reject") def do_actions(self): - ACTION_SIZE = len(self.actions) - i = 0 - while i < ACTION_SIZE: - self.print_debug(self.actions) - if self.actions[0] == "c": # Route to cashbox - if self.essp.ssp6_set_route(self.sspC, self.actions_args['routec_amount'], self.actions_args['routec_currency'], ENABLED) != SSP_RESPONSE_OK: + while self.actions: + action = self.actions.get() # get and delete + self.print_debug(Actions.action) + if action == Actions.ROUTE_TO_CASHBOX: # Route to cashbox + if self.essp.ssp6_set_route(self.sspC, self.actions_args['routec_amount'], self.actions_args['routec_currency'], Status.ENABLED) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Route to cashbox failed") - elif self.actions[0] == "s": # Route to storage - if self.essp.ssp6_set_route(self.sspC, self.actions_args['routes_amount'], self.actions_args['routes_currency'], DISABLED) != SSP_RESPONSE_OK: + elif action == Actions.ROUTE_TO_STORAGE: # Route to storage + if self.essp.ssp6_set_route(self.sspC, self.actions_args['routes_amount'], self.actions_args['routes_currency'], Status.ENABLED) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Route to storage failed") - elif self.actions[0] == "p": # Payout - if self.essp.ssp6_payout(self.sspC, self.actions_args['payout_amount'], self.actions_args['payout_currency'], SSP6_OPTION_BYTE_DO) != SSP_RESPONSE_OK: + elif action == Actions.PAYOUT: # Payout + if self.essp.ssp6_payout(self.sspC, self.actions_args['payout_amount'], self.actions_args['payout_currency'], Status.SSP6_OPTION_BYTE_DO) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Payout failed") - #Checking the error - response_data = cast(self.essp.ssp_get_response_data(self.sspC), POINTER(c_ubyte)) + # Checking the error + response_data = cast(self.essp.Status.SSP_get_response_data(self.sspC), POINTER(c_ubyte)) if response_data[1] == 0x01: self.print_debug("Not enough value in Smart Payout") elif response_data[1] == 0x02: @@ -137,54 +132,49 @@ def do_actions(self): elif response_data[1] == 0x03: self.print_debug("Smart Payout is busy") elif response_data[1] == 0x04: - self.print_debug("Smart Payout is disabled") + self.print_debug("Smart Payout is Status.ENABLED") - elif self.actions[0] == "y": # Payout next note ( NV11 only ) + elif action == Actions.PAYOUT_NEXT_NOTE_NV11: # Payout next note ( NV11 only ) self.print_debug("Payout next note") - setup_req = SSP6_SETUP_REQUEST_DATA() - if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != SSP_RESPONSE_OK: + setup_req = Ssp6SetupRequestData() + if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != Status.SSP_RESPONSE_OK: self.print_debug("Setup Request Failed") if setup_req.UnitType != 0x07: self.print_debug("Payout next note is only valid for NV11") - if self.essp.ssp6_payout_note(self.sspC) != SSP_RESPONSE_OK: + if self.essp.ssp6_payout_note(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("Payout next note failed") - elif self.actions[0] == "z": # Stack next note ( NV11 only ) - setup_req = SSP6_SETUP_REQUEST_DATA() - if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != SSP_RESPONSE_OK: + elif action == Actions.STACK_NEXT_NOTE_NV11: # Stack next note ( NV11 only ) + setup_req = Ssp6SetupRequestData() + if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != Status.SSP_RESPONSE_OK: self.print_debug("Setup Request Failed") - if setup_req.UnitType != 0x07: + if setup_req.UnitType != 0x07: # Maybe the version, or something ( taken from the SDK C code ) self.print_debug("Payout next note is only valid for NV11") - if self.essp.ssp6_stack_note(self.sspC) != SSP_RESPONSE_OK: + if self.essp.ssp6_stack_note(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("Stack next note failed") - elif self.actions[0] == "d": # Disable the validator - if self.essp.ssp6_disable(self.sspC) != SSP_RESPONSE_OK: + elif action == Actions.DISABLE_VALIDATOR: # Disable the validator + if self.essp.ssp6_disable(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Disable failed") - elif self.actions[0] == "D": # Disable the payout device - if self.essp.ssp6_disable_payout(self.sspC) != SSP_RESPONSE_OK: + elif action == Actions.DISABLE_PAYOUT: # Disable the payout device + if self.essp.ssp6_disable_payout(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Disable payout failed") - elif self.actions[0] == "g": # Get the note amount - if self.essp.ssp6_get_note_amount(self.sspC, self.actions_args['getnoteamount_amount'], self.actions_args['getnoteamount_currency']) != SSP_RESPONSE_OK: + elif action == Actions.GET_NOTE_AMOUNT: # Get the note amount + if self.essp.ssp6_get_note_amount(self.sspC, self.actions_args['getnoteamount_amount'], self.actions_args['getnoteamount_currency']) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Can't read the note amount") - self.response_data['getnoteamount_response'] = 9999 + self.response_data['getnoteamount_response'] = 9999 # There can't be 9999 notes else: - response_data = cast(self.essp.ssp_get_response_data(self.sspC), POINTER(c_ubyte)) + response_data = cast(self.essp.Status.SSP_get_response_data(self.sspC), POINTER(c_ubyte)) self.print_debug(response_data[1]) - self.response_data['getnoteamount_response'] = response_data[1] # The number of note + self.response_data['getnoteamount_response'] = response_data[1] # The number of note - elif self.actions[0] == "E": # Empty the storage ( Send all to the cashbox ) - if self.essp.ssp6_empty(self.sspC) != SSP_RESPONSE_OK: + elif action == Actions.EMPTY_STORAGE: # Empty the storage ( Send all to the cashbox ) + if self.essp.ssp6_empty(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Can't empty the storage") else: self.print_debug("Emptying, please wait...") - self.__clean_actions_list() - i+=1 - - def __clean_actions_list(self): - self.actions = self.actions[1:] def print_debug(self, text): if self.debug: @@ -192,134 +182,98 @@ def print_debug(self, text): def enable_validator(self): """Enable the validator""" - setup_req = SSP6_SETUP_REQUEST_DATA() - if self.essp.ssp6_enable(self.sspC) != SSP_RESPONSE_OK: + setup_req = Ssp6SetupRequestData() + if self.essp.ssp6_enable(self.sspC) != Status.SSP_RESPONSE_OK: self.print_debug("ERROR: Enable failed") return False - #SMART Hopper requires different inhibit commands, so use setup request to see if it is an SH - if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != SSP_RESPONSE_OK: + # SMART Hopper requires different inhibit commands, so use setup request to see if it is an SH + if self.essp.ssp6_setup_request(self.sspC, byref(setup_req)) != Status.SSP_RESPONSE_OK: self.print_debug("Setup request failed") return False if setup_req.UnitType == 0x03: - #SMART Hopper requires different inhibit commands + # SMART Hopper requires different inhibit commands for channel in setup_req.ChannelData: - self.essp.ssp6_set_coinmech_inhibits(self.sspC, channel.value, channel.cc, ENABLED) + self.essp.ssp6_set_coinmech_inhibits(self.sspC, channel.value, channel.cc, Status.ENABLED) else: - if self.essp.ssp6_set_inhibits(self.sspC, 0xFF, 0xFF) != SSP_RESPONSE_OK: + if self.essp.ssp6_set_inhibits(self.sspC, 0xFF, 0xFF) != Status.SSP_RESPONSE_OK: self.print_debug("Inhibits Failed") return False def parse_poll(self): """Parse the poll, for getting events""" + for events in self.poll.events: - if events.event == SSP_POLL_RESET: + try: + self.print_debug(Status.events.event) + except ValueError: + self.print_debug('Unknown status: {}'.format(events.event)) + + if events.event == Status.SSP_POLL_RESET: self.print_debug("Unit Reset") - if self.essp.ssp6_host_protocol(self.sspC, 0x06) != SSP_RESPONSE_OK: + if self.essp.ssp6_host_protocol(self.sspC, Status.CHECKSUM_ERROR) != Status.SSP_RESPONSE_OK: self.print_debug("Host Protocol Failed") self.close() - return (0,0,events.event) - elif events.event == SSP_POLL_READ: + + elif events.event == Status.SSP_POLL_READ: if events.data1 > 0: - self.print_debug("Note Read %s %s"%(events.data1,events.cc.decode())) - return (events.data1, events.cc.decode(), events.event) - elif events.event == SSP_POLL_CREDIT: - self.print_debug("Credit %s %s"%(events.data1,events.cc.decode())) - return (events.data1, events.cc.decode(), events.event) - elif events.event == SSP_POLL_INCOMPLETE_PAYOUT: - self.print_debug("Incomplete payout %s of %s %s" % (events.data1,events.data2, events.cc.decode())) - return (0,0,events.event) - elif events.event == SSP_POLL_INCOMPLETE_FLOAT: - self.print_debug("Incomplete float %s of %s %s"%(events.data1,events.data2,events.cc.decode())) - return (0,0,events.event) - elif events.event == SSP_POLL_REJECTING: - # Do nothing - return (0,0,events.event) - elif events.event == SSP_POLL_REJECTED: - self.print_debug("Note Rejected") - return (0,0,events.event) - elif events.event == SSP_POLL_STACKING: - # Do nothing - return (0,0,events.event) - elif events.event == SSP_POLL_STORED: - self.print_debug("Stored") - return (0,0,events.event) - elif events.event == SSP_POLL_STACKED: - self.print_debug("Stacked") - return (0,0,events.event) - elif events.event == SSP_POLL_SAFE_JAM: - self.print_debug("Safe Jam") - return (0,0,events.event) - elif events.event == SSP_POLL_UNSAFE_JAM: - self.print_debug("Unsafe Jam") - return (0,0,events.event) - elif events.event == SSP_POLL_DISABLED: - self.print_debug("VALIDATOR DISABLED") - return (0,0,events.event) - elif events.event == SSP_POLL_FRAUD_ATTEMPT: - self.print_debug("Fraud Attempt %s %s"%(events.data1,events.cc.decode())) - return (events.data1,events.cc.decode(),events.event) - elif events.event == SSP_POLL_STACKER_FULL: - self.print_debug("Stacker Full") - return (0,0,events.event) - elif events.event == SSP_POLL_CASH_BOX_REMOVED: - self.print_debug("Cashbox Removed") - return (0,0,events.event) - elif events.event == SSP_POLL_CASH_BOX_REPLACED: - self.print_debug("Cashbox Replaced") - return (0,0,events.event) - elif events.event == SSP_POLL_CLEARED_FROM_FRONT: - self.print_debug("Cleared from front") - return (0,0,events.event) - elif events.event == SSP_POLL_CLEARED_INTO_CASHBOX: - self.print_debug("Cleared into Cashbox") - return (0,0,events.event) - elif events.event == SSP_POLL_CALIBRATION_FAIL: + self.print_debug("Note Read %s %s" % (events.data1, events.cc.decode())) + return events.data1, events.cc.decode(), events.event + + elif events.event == Status.SSP_POLL_CREDIT: + self.print_debug("Credit %s %s" % (events.data1, events.cc.decode())) + return events.data1, events.cc.decode(), events.event + + elif events.event == Status.SSP_POLL_INCOMPLETE_PAYOUT: + self.print_debug("Incomplete payout %s of %s %s" % (events.data1, events.data2, events.cc.decode())) + + elif events.event == Status.SSP_POLL_INCOMPLETE_FLOAT: + self.print_debug("Incomplete float %s of %s %s" % (events.data1, events.data2, events.cc.decode())) + + elif events.event == Status.SSP_POLL_FRAUD_ATTEMPT: + self.print_debug("Fraud Attempt %s %s" % (events.data1, events.cc.decode())) + return events.data1, events.cc.decode(), events.event + + elif events.event == Status.SSP_POLL_CALIBRATION_FAIL: self.print_debug("Calibration fail :") - if events.data1 == NO_FAILUE: + if events.data1 == Status.NO_FAILUE: self.print_debug("No failure") - if events.data1 == SENSOR_FLAP: + if events.data1 == Status.SENSOR_FLAP: self.print_debug("Optical sensor flap") - if events.data1 == SENSOR_EXIT: + if events.data1 == Status.SENSOR_EXIT: self.print_debug("Optical sensor exit") - if events.data1 == SENSOR_COIL1: + if events.data1 == Status.SENSOR_COIL1: self.print_debug("Coil sensor 1") - if events.data1 == SENSOR_COIL2: + if events.data1 == Status.SENSOR_COIL2: self.print_debug("Coil sensor 2") - if events.data1 == NOT_INITIALISED: + if events.data1 == Status.NOT_INITIALISED: self.print_debug("Unit not initialised") - if events.data1 == CHECKSUM_ERROR: + if events.data1 == Status.CHECKSUM_ERROR: self.print_debug("Data checksum error") - if events.data1 == COMMAND_RECAL: + if events.data1 == Status.COMMAND_RECAL: self.print_debug("Recalibration by command required") self.essp.ssp6_run_calibration(self.sspC) - return (0,0,events.event) - elif events.event == SSP_POLL_EMPTYING: - self.print_debug("Started emptying") - return (0,0,events.event) - elif events.event == SSP_POLL_EMPTY: - self.print_debug("Finished emptying") - return (0,0,events.event) - - return (0,0,NO_EVENT) - - def system_loop(self): # Looping for getting the alive signal ( obligation in eSSP6 ) - while(1): + + return 0, 0, Status.events.event + return 0, 0, Status.NO_EVENT + + def system_loop(self): # Looping for getting the alive signal ( obligation in eSSP6 ) + while True: rsp_status = self.essp.ssp6_poll(self.sspC, byref(self.poll)) # Get the pool - if rsp_status != SSP_RESPONSE_OK: # If there's a problem, check wath is it - if rsp_status == SSP_RESPONSE_TIMEOUT: # Timeout + if rsp_status != Status.SSP_RESPONSE_OK: # If there's a problem, check wath is it + if rsp_status == Status.SSP_RESPONSE_TIMEOUT: # Timeout self.print_debug("SSP Poll Timeout") self.close() exit(0) else: if rsp_status == 0xFA: - #The self has responded with key not set, so we should try to negotiate one - if self.essp.ssp6_setup_encryption(self.sspC, c_ulonglong(0x123456701234567)) == SSP_RESPONSE_OK: + # The self has responded with key not set, so we should try to negotiate one + if self.essp.ssp6_setup_encryption(self.sspC, c_ulonglong(0x123456701234567)) == Status.SSP_RESPONSE_OK: self.print_debug("Encryption Setup") else: self.print_debug("Encryption Failed") else: - self.print_debug("SSP Poll Error",rsp_status) # Not theses two, stop the program + self.print_debug("SSP Poll Error", rsp_status) # Not theses two, stop the program return False self.events.append(self.parse_poll()) self.do_actions() @@ -331,56 +285,45 @@ def get_last_event(self): self.events.pop(len(self.events)-1) return event + def __action_helper(self, amount, currency, action, prefix): + self.actions.put(action) + self.actions_args['{}_amount'.format(prefix)] = amount*100 # TODO: This is one action at time, also, i think that the validator can receive one type of command at time, so to implement : user can send multiple request without waiting, but we store them and process them every time we send to the validator ( 0.5, 0.5, 0.5, etc. ) + self.actions_args['{}_currency'.format(prefix)] = currency.upper().encode() + def set_route_cashbox(self, amount, currency="CHF"): - """Set the bills in the cashbox - NV11: Set the bills <= amount in the cashbox""" - #if not isinstance(currency, bytes): - # raise ValueError("Currency must be a byte buffer") - self.actions+="c" - self.actions_args['routec_amount'] = amount*100 - self.actions_args['routec_currency'] = currency.upper().encode() + """Will set the route of in the cashbox + NV11: Will set the route of <= amount in the cashbox""" + self.__action_helper(amount, currency, Actions.ROUTE_TO_CASHBOX, "routec") def set_route_storage(self, amount, currency="CHF"): """Set the bills in the storage NV11: Set the bills <= amount in the storage""" - #if not isinstance(currency, bytes): - # raise ValueError("Currency must be a byte buffer") - self.actions+="s" - self.actions_args['routes_amount'] = amount*100 - self.actions_args['routes_currency'] = currency.upper().encode() + self.__action_helper(amount, currency, Actions.ROUTE_STORAGE, "routes") def payout(self, amount, currency="CHF"): """Payout note(s) for completing the amount passed in parameter""" - #if not isinstance(currency, bytes): - # raise ValueError("Currency must be a byte buffer") - self.actions+="p" - self.actions_args['payout_amount'] = amount*100 - self.actions_args['payout_currency'] = currency.upper().encode() + self.__action_helper(amount, currency, Actions.PAYOUT, "payout") def get_note_amount(self, amount, currency="CHF"): """Payout note(s) for completing the amount passed in parameter""" - #if not isinstance(currency, bytes): - # raise ValueError("Currency must be a byte buffer") - self.actions+="g" - self.actions_args['getnoteamount_amount'] = amount*100 - self.actions_args['getnoteamount_currency'] = currency.upper().encode() + self.__action_helper(amount, currency, Actions.GET_NOTE_AMOUNT, "getnoteamount") def reset(self): self.print_debug("Starting reset") self.essp.ssp6_reset(self.sspC) self.print_debug("Reset complet") - def nv11_payout(self): - self.actions+="y" + def nv11_payout_next_note(self): + self.actions.put(Actions.PAYOUT_NEXT_NOTE_NV11) - def nv11_stack(self): - self.actions+="z" + def nv11_stack_next_note(self): + self.actions.put(Actions.STACK_NEXT_NOTE_NV11) def empty_storage(self): - self.actions+="E" + self.actions.put(Actions.EMPTY_STORAGE) def disable_payout(self): - self.actions+="D" + self.actions.put(Actions.DISABLE_PAYOUT) def disable_validator(self): - self.actions+="d" + self.actions.put(Actions.DISABLE_VALIDATOR)