def __init__(self, machine): self.log = logging.getLogger('switchplayer') if 'switchplayer' not in machine.config: machine.log.debug('"switchplayer:" section not found in ' 'machine configuration, so the Switch Player' 'plugin will not be used.') return self.machine = machine self.delay = DelayManager() self.current_step = 0 config_spec = ''' start_event: string|machine_reset_phase_3 start_delay: secs|0 ''' self.config = Config.process_config(config_spec, self.machine.config['switchplayer']) self.machine.events.add_handler(self.config['start_event'], self._start_event_callback) self.step_list = self.config['steps'] self.start_delay = self.config['start_delay']
def __init__(self, machine, name, config, receive_queue): self.log = logging.getLogger('BCPClient.' + name) self.log.info('Setting up BCP Client...') self.machine = machine self.name = name self.receive_queue = receive_queue config_spec = ''' host: string port: int|5050 connection_attempts: int|-1 require_connection: boolean|False ''' self.config = Config.process_config(config_spec, config) self.sending_queue = Queue() self.receive_thread = None self.sending_thread = None self.socket = None self.connection_attempts = 0 self.attempt_socket_connection = True self.send_goodbye = True self.bcp_commands = { 'hello': self.receive_hello, 'goodbye': self.receive_goodbye, } self.setup_client_socket()
def __init__(self, machine, name, config, receive_queue): self.log = logging.getLogger('BCPClient.' + name) self.log.info('Setting up BCP Client...') self.machine = machine self.name = name self.receive_queue = receive_queue config_spec = ''' host: string port: int|5050 connection_attempts: int|-1 require_connection: boolean|False ''' self.config = Config.process_config(config_spec, config) self.sending_queue = Queue() self.receive_thread = None self.sending_thread = None self.socket = None self.connection_attempts = 0 self.attempt_socket_connection = True self.send_goodbye = True self.bcp_commands = {'hello': self.receive_hello, 'goodbye': self.receive_goodbye, } self.setup_client_socket()
def __init__(self, machine, name, player, config): self.machine = machine self.name = name self.player = player self.handler_keys = set() self.enabled = False config_spec = ''' enable_events: list|None disable_events: list|None reset_events: list|None restart_on_complete: boolean|False disable_on_complete: boolean|True ''' self.config = Config.process_config(config_spec=config_spec, source=config) if 'events_when_complete' not in config: self.config['events_when_complete'] = ([ 'logicblock_' + self.name + '_complete' ]) else: self.config['events_when_complete'] = Config.string_to_list( config['events_when_complete']) if 'reset_each_ball' in config and config['reset_each_ball']: if 'ball_starting' not in self.config['reset_events']: self.config['reset_events'].append('ball_starting')
def __init__(self, machine, name, player, config): self.machine = machine self.name = name self.player = player self.handler_keys = set() self.enabled = False config_spec = ''' enable_events: list|None disable_events: list|None reset_events: list|None restart_events: list|None restart_on_complete: boolean|False disable_on_complete: boolean|True persist_state: boolean|False ''' self.config = Config.process_config(config_spec=config_spec, source=config) if 'events_when_complete' not in config: self.config['events_when_complete'] = ([ 'logicblock_' + self.name + '_complete']) else: self.config['events_when_complete'] = Util.string_to_list( config['events_when_complete'])
def __init__(self, machine): self.log = logging.getLogger("switch_player") if "switch_player" not in machine.config: machine.log.debug( '"switch_player:" section not found in ' "machine configuration, so the Switch Player" "plugin will not be used." ) return self.machine = machine self.delay = DelayManager() self.current_step = 0 config_spec = """ start_event: string|machine_reset_phase_3 start_delay: secs|0 """ self.config = Config.process_config(config_spec, self.machine.config["switch_player"]) self.machine.events.add_handler(self.config["start_event"], self._start_event_callback) self.step_list = self.config["steps"] self.start_delay = self.config["start_delay"]
def __init__(self, machine, name, player, config): self.machine = machine self.name = name self.player = player self.handler_keys = set() self.enabled = False config_spec = """ enable_events: list|None disable_events: list|None reset_events: list|None restart_on_complete: boolean|False disable_on_complete: boolean|True """ self.config = Config.process_config(config_spec=config_spec, source=config) if "events_when_complete" not in config: self.config["events_when_complete"] = ["logicblock_" + self.name + "_complete"] else: self.config["events_when_complete"] = Config.string_to_list(config["events_when_complete"]) if "reset_each_ball" in config and config["reset_each_ball"]: if "ball_starting" not in self.config["reset_events"]: self.config["reset_events"].append("ball_starting")
def __init__(self, machine): self.log = logging.getLogger('switch_player') if 'switch_player' not in machine.config: machine.log.debug('"switch_player:" section not found in ' 'machine configuration, so the Switch Player' 'plugin will not be used.') return self.machine = machine self.delay = DelayManager() self.current_step = 0 config_spec = ''' start_event: string|machine_reset_phase_3 start_delay: secs|0 ''' self.config = Config.process_config( config_spec, self.machine.config['switch_player']) self.machine.events.add_handler(self.config['start_event'], self._start_event_callback) self.step_list = self.config['steps'] self.start_delay = self.config['start_delay']
def _initialize(self): # Initializes the auditor. We do this separate from __init__() since # we need everything else to be setup first. config = """ save_events: list|ball_ended audit: list|None events: list|None player: list|None num_player_top_records: int|10 """ self.config = Config.process_config(config, self.machine.config["auditor"]) self.filename = os.path.join(self.machine.machine_path, self.machine.config["mpf"]["paths"]["audits"]) # todo add option for abs path outside of machine root self.current_audits = self.load_from_disk(self.filename) self.make_sure_path_exists(os.path.dirname(self.filename)) if not self.current_audits: self.current_audits = dict() # Make sure we have all the sections we need in our audit dict if "switches" not in self.current_audits: self.current_audits["switches"] = dict() if "events" not in self.current_audits: self.current_audits["events"] = dict() if "player" not in self.current_audits: self.current_audits["player"] = dict() # Make sure we have all the switches in our audit dict for switch in self.machine.switches: if switch.name not in self.current_audits["switches"]: self.current_audits["switches"][switch.name] = 0 # Make sure we have all the player stuff in our audit dict if "player" in self.config["audit"]: for item in self.config["player"]: if item not in self.current_audits["player"]: self.current_audits["player"][item] = dict() self.current_audits["player"][item]["top"] = list() self.current_audits["player"][item]["average"] = 0 self.current_audits["player"][item]["total"] = 0 # Register for the events the auditor needs to do its job self.machine.events.add_handler("game_starting", self.enable) self.machine.events.add_handler("game_ended", self.disable) if "player" in self.config["audit"]: self.machine.events.add_handler("game_ending", self.audit_player) # Enable the shots monitor Shot.monitor_enabled = True self.machine.register_monitor("shots", self.audit_shot)
def __init__(self, machine): if 'osc' not in machine.config: machine.log.debug('"OSC:" section not found in the machine ' 'configuration, so the OSC plugin will not ' 'be used.') return if not import_success: machine.log.warning('OSC plugin requires PyOSC which does not ' 'appear to be installed. No prob, but FYI ' 'that the OSC will not be available.') return self.log = logging.getLogger('osc') self.machine = machine config_spec = ''' client_port: int|8000 debug_messages: boolean|False ''' self.config = Config.process_config(config_spec, self.machine.config['osc']) if self.config['machine_ip'].upper() == 'AUTO': self.config['machine_ip'] = socket.gethostbyname( socket.gethostname()) if 'client_updates' in self.config: self.config['client_updates'] = self.config[ 'client_updates'].split(' ') else: self.config['client_updates'] = None self.OSC_clients = dict() self.client_needs_sync = False self.client_last_update_time = None self.last_loop_time = 1 self.client_mode = 'name' self.clients_to_delete = list() self.clients_to_add = list() # If this machine uses WPC driver boards then we can drive devices by # if self.machine.config['hardware']['driverboards'][0:3] == 'wpc': self.wpc = True else: self.wpc = False # register for events self.machine.events.add_handler('init_phase_4', self.start)
def __init__(self, machine): if 'osc' not in machine.config: machine.log.debug('"OSC:" section not found in the machine ' 'configuration, so the OSC plugin will not ' 'be used.') return if not import_success: machine.log.warning('OSC plugin requires PyOSC which does not ' 'appear to be installed. No prob, but FYI ' 'that the OSC will not be available.') return self.log = logging.getLogger('osc') self.machine = machine config_spec = ''' client_port: int|8000 debug_messages: boolean|False ''' self.config = Config.process_config(config_spec, self.machine.config['osc']) if self.config['machine_ip'].upper() == 'AUTO': self.config['machine_ip'] = socket.gethostbyname( socket.gethostname()) if 'client_updates' in self.config: self.config['client_updates'] = self.config['client_updates'].split( ' ') else: self.config['client_updates'] = None self.OSC_clients = dict() self.client_needs_sync = False self.client_last_update_time = None self.last_loop_time = 1 self.client_mode = 'name' self.clients_to_delete = list() self.clients_to_add = list() # If this machine uses WPC driver boards then we can drive devices by # if self.machine.config['hardware']['driverboards'][0:3] == 'wpc': self.wpc = True else: self.wpc = False # register for events self.machine.events.add_handler('init_phase_4', self.start)
def __init__(self, machine, name, player, config): self.log = logging.getLogger("Sequence." + name) self.log.debug("Creating Sequence LogicBlock") super(Sequence, self).__init__(machine, name, player, config) config_spec = """ events: list_of_lists """ self.config = Config.process_config(config_spec=config_spec, source=self.config) if "player_variable" not in config: self.config["player_variable"] = self.name + "_step" self.player[self.config["player_variable"]] = 0
def __init__(self, machine): super(HardwarePlatform, self).__init__(machine) self.log = logging.getLogger('SmartMatrix') self.log.info("Configuring SmartMatrix hardware interface.") self.dmd_frame = bytearray() self.queue = None config_spec = ''' port: string use_separate_thread: boolean|True ''' self.config = Config.process_config(config_spec=config_spec, source=self.machine.config['smartmatrix'])
def __init__(self, machine, name, player, config): self.log = logging.getLogger('Sequence.' + name) self.log.debug("Creating Sequence LogicBlock") super(Sequence, self).__init__(machine, name, player, config) config_spec = ''' events: list_of_lists ''' self.config = Config.process_config(config_spec=config_spec, source=self.config) if 'player_variable' not in config: self.config['player_variable'] = self.name + '_step' self.player[self.config['player_variable']] = 0
def __init__(self, machine): super(HardwarePlatform, self).__init__(machine) self.log = logging.getLogger('SmartMatrix') self.log.info("Configuring SmartMatrix hardware interface.") self.dmd_frame = bytearray() self.queue = None config_spec = ''' port: string use_separate_thread: boolean|True ''' self.config = Config.process_config( config_spec=config_spec, source=self.machine.config['smartmatrix'])
def __init__(self, machine, name, player, config): self.log = logging.getLogger("Accrual." + name) self.log.debug("Creating Accrual LogicBlock") super(Accrual, self).__init__(machine, name, player, config) config_spec = """ events: list_of_lists """ self.config = Config.process_config(config_spec=config_spec, source=self.config) if "player_variable" not in config: self.config["player_variable"] = self.name + "_status" # populate status list self.player[self.config["player_variable"]] = [False] * len(self.config["events"])
def __init__(self, machine, name, player, config): self.log = logging.getLogger('Sequence.' + name) self.log.debug("Creating Sequence LogicBlock") super(Sequence, self).__init__(machine, name, player, config) config_spec = ''' events: list_of_lists ''' self.config = Config.process_config(config_spec=config_spec, source=self.config) if 'player_variable' not in config: self.config['player_variable'] = self.name + '_step' self.player[self.config['player_variable']] = 0
def __init__(self, machine, name, player, config): self.log = logging.getLogger('Accrual.' + name) self.log.debug("Creating Accrual LogicBlock") super(Accrual, self).__init__(machine, name, player, config) config_spec = ''' events: list_of_lists ''' self.config = Config.process_config(config_spec=config_spec, source=self.config) if 'player_variable' not in config: self.config['player_variable'] = self.name + '_status' # populate status list self.player[self.config['player_variable']] = ( [False] * len(self.config['events']))
def __init__(self, machine, name, player, config): self.log = logging.getLogger('Accrual.' + name) self.log.debug("Creating Accrual LogicBlock") super(Accrual, self).__init__(machine, name, player, config) config_spec = ''' events: list_of_lists ''' self.config = Config.process_config(config_spec=config_spec, source=self.config) if 'player_variable' not in config: self.config['player_variable'] = self.name + '_status' # populate status list self.player[self.config['player_variable']] = ( [False] * len(self.config['events']))
def __init__(self, machine, name, player, config): self.log = logging.getLogger('Counter.' + name) self.log.debug("Creating Counter LogicBlock") super(Counter, self).__init__(machine, name, player, config) self.delay = DelayManager() self.ignore_hits = False self.hit_value = -1 config_spec = ''' count_events: list|None count_complete_value: int|None multiple_hit_window: ms|0 count_interval: int|1 direction: string|up starting_count: int|0 ''' self.config = Config.process_config(config_spec=config_spec, source=self.config) if 'event_when_hit' not in self.config: self.config['event_when_hit'] = ('counter_' + self.name + '_hit') if 'player_variable' not in self.config: self.config['player_variable'] = self.name + '_count' self.hit_value = self.config['count_interval'] if self.config['direction'] == 'down' and self.hit_value > 0: self.hit_value *= -1 elif self.config['direction'] == 'up' and self.hit_value < 0: self.hit_value *= -1 if not self.config['persist_state']: self.player[self.config['player_variable']] = ( self.config['starting_count'])
def __init__(self, machine, name, player, config): self.log = logging.getLogger('Counter.' + name) self.log.debug("Creating Counter LogicBlock") super(Counter, self).__init__(machine, name, player, config) self.delay = DelayManager() self.ignore_hits = False self.hit_value = -1 config_spec = ''' count_events: list|None count_complete_value: int|0 multiple_hit_window: ms|0 count_interval: int|1 direction: string|up starting_count: int|0 ''' self.config = Config.process_config(config_spec=config_spec, source=self.config) if 'event_when_hit' not in self.config: self.config['event_when_hit'] = ('counter_' + self.name + '_hit') if 'player_variable' not in self.config: self.config['player_variable'] = self.name + '_count' self.hit_value = self.config['count_interval'] if self.config['direction'] == 'down' and self.hit_value > 0: self.hit_value *= -1 elif self.config['direction'] == 'up' and self.hit_value < 0: self.hit_value *= -1 self.player[self.config['player_variable']] = ( self.config['starting_count'])
def __init__(self, machine, name, player, config): self.log = logging.getLogger("Counter." + name) self.log.debug("Creating Counter LogicBlock") super(Counter, self).__init__(machine, name, player, config) self.delay = DelayManager() self.ignore_hits = False self.hit_value = -1 config_spec = """ count_events: list|None count_complete_value: int|0 multiple_hit_window: ms|0 count_interval: int|1 direction: string|up starting_count: int|0 """ self.config = Config.process_config(config_spec=config_spec, source=self.config) if "event_when_hit" not in self.config: self.config["event_when_hit"] = "counter_" + self.name + "_hit" if "player_variable" not in self.config: self.config["player_variable"] = self.name + "_count" self.hit_value = self.config["count_interval"] if self.config["direction"] == "down" and self.hit_value > 0: self.hit_value *= -1 elif self.config["direction"] == "up" and self.hit_value < 0: self.hit_value *= -1 self.player[self.config["player_variable"]] = self.config["starting_count"]
def __init__(self, options): self.options = options self.log = logging.getLogger("MediaController") self.log.info("Media Controller Version %s", version.__version__) self.log.info("Backbox Control Protocol Version %s", version.__bcp_version__) self.log.info("Config File Version %s", version.__config_version__) python_version = sys.version_info self.log.info("Python version: %s.%s.%s", python_version[0], python_version[1], python_version[2]) self.log.info("Platform: %s", sys.platform) self.log.info("Python executable location: %s", sys.executable) self.log.info("32-bit Python? %s", sys.maxsize < 2**32) self.config = dict() self.done = False # todo self.machine_path = None self.asset_managers = dict() self.num_assets_to_load = 0 self.window = None self.window_manager = None self.pygame = False self.pygame_requested = False self.registered_pygame_handlers = dict() self.pygame_allowed_events = list() self.socket_thread = None self.receive_queue = Queue.Queue() self.sending_queue = Queue.Queue() self.crash_queue = Queue.Queue() self.game_modes = CaseInsensitiveDict() self.player_list = list() self.player = None self.HZ = 0 self.next_tick_time = 0 self.secs_per_tick = 0 Task.Create(self._check_crash_queue) self.bcp_commands = {'hello': self.bcp_hello, 'goodbye': self.bcp_goodbye, 'reset': self.reset, 'mode_start': self.bcp_mode_start, 'mode_stop': self.bcp_mode_stop, 'error': self.bcp_error, 'ball_start': self.bcp_ball_start, 'ball_end': self.bcp_ball_end, 'game_start': self.bcp_game_start, 'game_end': self.bcp_game_end, 'player_added': self.bcp_player_add, 'player_variable': self.bcp_player_variable, 'player_score': self.bcp_player_score, 'player_turn_start': self.bcp_player_turn_start, 'attract_start': self.bcp_attract_start, 'attract_stop': self.bcp_attract_stop, 'trigger': self.bcp_trigger, 'switch': self.bcp_switch, 'get': self.bcp_get, 'set': self.bcp_set, 'config': self.bcp_config, 'timer': self.bcp_timer } # load the MPF config & machine defaults self.config = ( Config.load_config_yaml(config=self.config, yaml_file=self.options['mcconfigfile'])) # Find the machine_files location. If it starts with a forward or # backward slash, then we assume it's from the mpf root. Otherwise we # assume it's from the subfolder location specified in the # mpfconfigfile location if (options['machinepath'].startswith('/') or options['machinepath'].startswith('\\')): machine_path = options['machinepath'] else: machine_path = os.path.join(self.config['mediacontroller']['paths'] ['machine_files'], options['machinepath']) self.machine_path = os.path.abspath(machine_path) # Add the machine folder to our path so we can import modules from it sys.path.append(self.machine_path) self.log.info("Machine folder: %s", machine_path) # Now find the config file location. Same as machine_file with the # slash uses to specify an absolute path if (options['configfile'].startswith('/') or options['configfile'].startswith('\\')): config_file = options['configfile'] else: if not options['configfile'].endswith('.yaml'): options['configfile'] += '.yaml' config_file = os.path.join(self.machine_path, self.config['mediacontroller']['paths'] ['config'], options['configfile']) self.log.info("Base machine config file: %s", config_file) # Load the machine-specific config self.config = Config.load_config_yaml(config=self.config, yaml_file=config_file) mediacontroller_config_spec = ''' exit_on_disconnect: boolean|True port: int|5050 ''' self.config['mediacontroller'] = ( Config.process_config(mediacontroller_config_spec, self.config['mediacontroller'])) self.events = EventManager(self) self.timing = Timing(self) # Load the media controller modules self.config['mediacontroller']['modules'] = ( self.config['mediacontroller']['modules'].split(' ')) for module in self.config['mediacontroller']['modules']: self.log.info("Loading module: %s", module) module_parts = module.split('.') exec('self.' + module_parts[0] + '=' + module + '(self)') # todo there's probably a more pythonic way to do this, and I know # exec() is supposedly unsafe, but meh, if you have access to put # malicious files in the system folder then you have access to this # code too. self.start_socket_thread() self.events.post("init_phase_1") self.events.post("init_phase_2") self.events.post("init_phase_3") self.events.post("init_phase_4") self.events.post("init_phase_5") self.reset()
def __init__(self, machine): super(HardwarePlatform, self).__init__(machine) self.log = logging.getLogger('FAST') self.log.debug("Configuring FAST hardware.") if not serial_imported: self.log.error('Could not import "pySerial". This is required for ' 'the FAST platform interface') sys.exit() # ---------------------------------------------------------------------- # Platform-specific hardware features. WARNING: Do not edit these. They # are based on what the FAST hardware can and cannot do. self.features['max_pulse'] = 255 # todo self.features['hw_timer'] = False self.features['hw_rule_coil_delay'] = True # todo self.features['variable_recycle_time'] = True # todo self.features['variable_debounce_time'] = True # todo self.features['hw_enable_auto_disable'] = True # Make the platform features available to everyone self.machine.config['platform'] = self.features # ---------------------------------------------------------------------- self.hw_rules = dict() self.dmd_connection = None self.net_connection = None self.rgb_connection = None self.fast_nodes = list() self.connection_threads = set() self.receive_queue = Queue.Queue() self.fast_leds = set() self.flag_led_tick_registered = False self.flag_switch_registered = False config_spec = ''' ports: list baud: int|921600 config_number_format: string|hex watchdog: ms|1000 default_debounce_open: ms|30 default_debounce_close: ms|30 debug: boolean|False ''' self.config = Config.process_config(config_spec=config_spec, source=self.machine.config['fast']) self.watchdog_command = 'WD:' + str(hex(self.config['watchdog']))[2:] self._connect_to_hardware() if 'config_number_format' not in self.machine.config['fast']: self.machine.config['fast']['config_number_format'] = 'int' self.machine_type = ( self.machine.config['hardware']['driverboards'].lower()) if self.machine_type == 'wpc': self.log.debug("Configuring the FAST Controller for WPC driver " "boards") elif self.machine_type == 'fast': self.log.debug( "Configuring FAST Controller for FAST driver boards.") self.wpc_switch_map = { # autogenerated, so not in order. Sorry :( 'SF8': '67', 'SF6': '65', 'SF7': '66', 'SF4': '63', 'SF5': '64', 'SF2': '61', 'SF3': '62', 'SF1': '60', 'S57': '26', 'S56': '25', 'S55': '24', 'S54': '23', 'S53': '22', 'S52': '21', 'S51': '20', 'S58': '27', 'S44': '1B', 'S45': '1C', 'S46': '1D', 'S47': '1E', 'S41': '18', 'S42': '19', 'S43': '1A', 'S48': '1F', 'S78': '37', 'S71': '30', 'S73': '32', 'S72': '31', 'S75': '34', 'S74': '33', 'S77': '36', 'S76': '35', 'S68': '2F', 'S66': '2d', 'S67': '2E', 'S64': '2B', 'S65': '2C', 'S62': '29', 'S63': '2A', 'S61': '28', 'S18': '07', 'S13': '02', 'S12': '01', 'S11': '00', 'S17': '06', 'S16': '05', 'S15': '04', 'S14': '03', 'S93': '42', 'S92': '41', 'S91': '40', 'S97': '46', 'S96': '45', 'S95': '44', 'S94': '43', 'S98': '47', 'S81': '38', 'S82': '39', 'S83': '3A', 'S84': '3B', 'S85': '3C', 'S86': '3D', 'S87': '3E', 'S88': '3F', 'SD4': '53', 'SD5': '54', 'SD6': '55', 'SD7': '56', 'SD1': '50', 'SD2': '51', 'SD3': '52', 'SD8': '57', 'S38': '17', 'S35': '14', 'S34': '13', 'S37': '16', 'S36': '15', 'S31': '10', 'S33': '12', 'S32': '11', 'S22': '09', 'S23': '0A', 'S21': '08', 'S26': '0D', 'S27': '0E', 'S24': '0B', 'S25': '0C', 'S28': '0F', 'DIP8': '5F', 'DIP1': '58', 'DIP3': '5A', 'DIP2': '59', 'DIP5': '5C', 'DIP4': '5B', 'DIP7': '5E', 'DIP6': '5D', } self.wpc_light_map = { 'L11': '00', 'L12': '01', 'L13': '02', 'L14': '03', 'L15': '04', 'L16': '05', 'L17': '06', 'L18': '07', 'L21': '08', 'L22': '09', 'L23': '0A', 'L24': '0B', 'L25': '0C', 'L26': '0D', 'L27': '0E', 'L28': '0F', 'L31': '10', 'L32': '11', 'L33': '12', 'L34': '13', 'L35': '14', 'L36': '15', 'L37': '16', 'L38': '17', 'L41': '18', 'L42': '19', 'L43': '1A', 'L44': '1B', 'L45': '1C', 'L46': '1D', 'L47': '1E', 'L48': '1F', 'L51': '20', 'L52': '21', 'L53': '22', 'L54': '23', 'L55': '24', 'L56': '25', 'L57': '26', 'L58': '27', 'L61': '28', 'L62': '29', 'L63': '2A', 'L64': '2B', 'L65': '2C', 'L66': '2D', 'L67': '2E', 'L68': '2F', 'L71': '30', 'L72': '31', 'L73': '32', 'L74': '33', 'L75': '34', 'L76': '35', 'L77': '36', 'L78': '37', 'L81': '38', 'L82': '39', 'L83': '3A', 'L84': '3B', 'L85': '3C', 'L86': '3D', 'L87': '3E', 'L88': '3F', } self.wpc_driver_map = { 'C01': '00', 'C02': '01', 'C03': '02', 'C04': '03', 'C05': '04', 'C06': '05', 'C07': '06', 'C08': '07', 'C09': '08', 'C10': '09', 'C11': '0A', 'C12': '0B', 'C13': '0C', 'C14': '0D', 'C15': '0E', 'C16': '0F', 'C17': '10', 'C18': '11', 'C19': '12', 'C20': '13', 'C21': '14', 'C22': '15', 'C23': '16', 'C24': '17', 'C25': '18', 'C26': '19', 'C27': '1A', 'C28': '1B', 'C29': '1C', 'C30': '1D', 'C31': '1E', 'C32': '1F', 'C33': '24', 'C34': '25', 'C35': '26', 'C36': '27', 'FLRM': '20', 'FLRH': '21', 'FLLM': '22', 'FLLH': '23', 'FURM': '24', 'FURH': '25', 'FULM': '26', 'FULH': '27', 'C37': '28', 'C38': '29', 'C39': '2A', 'C40': '2B', 'C41': '2C', 'C42': '2D', 'C43': '2E', 'C44': '2F', } self.wpc_gi_map = { 'G01': '00', 'G02': '01', 'G03': '02', 'G04': '03', 'G05': '04', 'G06': '05', 'G07': '06', 'G08': '07', } self.pwm8_to_hex_string = { 0: '00', 1: '01', 2: '88', 3: '92', 4: 'AA', 5: 'BA', 6: 'EE', 7: 'FE', 8: 'FF' } self.pwm8_to_int = { 0: 0, 1: 1, 2: 136, 3: 146, 4: 170, 5: 186, 6: 238, 7: 254, 8: 255 } # todo verify this list self.fast_commands = { 'ID': self.receive_id, # processor ID 'WX': self.receive_wx, # watchdog 'NN': self.receive_nn, # node id list 'NI': self.receive_ni, # node ID 'RX': self.receive_rx, # RGB cmd received 'DX': self.receive_dx, # DMD cmd received 'SX': self.receive_sx, # sw config received 'LX': self.receive_lx, # lamp cmd received 'PX': self.receive_px, # segment cmd received 'SA': self.receive_sa, # all switch states '/N': self.receive_nw_open, # nw switch open '-N': self.receive_nw_closed, # nw switch closed '/L': self.receive_local_open, # local sw open '-L': self.receive_local_closed, # local sw close 'WD': self.receive_wd, # watchdog }
def __init__(self, machine): super(HardwarePlatform, self).__init__(machine) self.log = logging.getLogger('FAST') self.log.debug("Configuring FAST hardware.") if not serial_imported: self.log.error('Could not import "pySerial". This is required for ' 'the FAST platform interface') sys.exit() # ---------------------------------------------------------------------- # Platform-specific hardware features. WARNING: Do not edit these. They # are based on what the FAST hardware can and cannot do. self.features['max_pulse'] = 255 # todo self.features['hw_timer'] = False self.features['hw_rule_coil_delay'] = True # todo self.features['variable_recycle_time'] = True # todo self.features['variable_debounce_time'] = True # todo self.features['hw_enable_auto_disable'] = True # Make the platform features available to everyone self.machine.config['platform'] = self.features # ---------------------------------------------------------------------- self.hw_rules = dict() self.dmd_connection = None self.net_connection = None self.rgb_connection = None self.fast_nodes = list() self.connection_threads = set() self.receive_queue = Queue.Queue() self.fast_leds = set() self.flag_led_tick_registered = False self.flag_switch_registered = False config_spec = ''' ports: list baud: int|921600 config_number_format: string|hex watchdog: ms|1000 default_debounce_open: ms|30 default_debounce_close: ms|30 debug: boolean|False ''' self.config = Config.process_config(config_spec=config_spec, source=self.machine.config['fast']) self.watchdog_command = 'WD:' + str(hex(self.config['watchdog']))[2:] self._connect_to_hardware() if 'config_number_format' not in self.machine.config['fast']: self.machine.config['fast']['config_number_format'] = 'int' self.machine_type = ( self.machine.config['hardware']['driverboards'].lower()) if self.machine_type == 'wpc': self.log.debug("Configuring the FAST Controller for WPC driver " "boards") elif self.machine_type == 'fast': self.log.debug("Configuring FAST Controller for FAST driver boards.") self.wpc_switch_map = { # autogenerated, so not in order. Sorry :( 'SF8': '67', 'SF6': '65', 'SF7': '66', 'SF4': '63', 'SF5': '64', 'SF2': '61', 'SF3': '62', 'SF1': '60', 'S57': '26', 'S56': '25', 'S55': '24', 'S54': '23', 'S53': '22', 'S52': '21', 'S51': '20', 'S58': '27', 'S44': '1B', 'S45': '1C', 'S46': '1D', 'S47': '1E', 'S41': '18', 'S42': '19', 'S43': '1A', 'S48': '1F', 'S78': '37', 'S71': '30', 'S73': '32', 'S72': '31', 'S75': '34', 'S74': '33', 'S77': '36', 'S76': '35', 'S68': '2F', 'S66': '2d', 'S67': '2E', 'S64': '2B', 'S65': '2C', 'S62': '29', 'S63': '2A', 'S61': '28', 'S18': '07', 'S13': '02', 'S12': '01', 'S11': '00', 'S17': '06', 'S16': '05', 'S15': '04', 'S14': '03', 'S93': '42', 'S92': '41', 'S91': '40', 'S97': '46', 'S96': '45', 'S95': '44', 'S94': '43', 'S98': '47', 'S81': '38', 'S82': '39', 'S83': '3A', 'S84': '3B', 'S85': '3C', 'S86': '3D', 'S87': '3E', 'S88': '3F', 'SD4': '53', 'SD5': '54', 'SD6': '55', 'SD7': '56', 'SD1': '50', 'SD2': '51', 'SD3': '52', 'SD8': '57', 'S38': '17', 'S35': '14', 'S34': '13', 'S37': '16', 'S36': '15', 'S31': '10', 'S33': '12', 'S32': '11', 'S22': '09', 'S23': '0A', 'S21': '08', 'S26': '0D', 'S27': '0E', 'S24': '0B', 'S25': '0C', 'S28': '0F', 'DIP8': '5F', 'DIP1': '58', 'DIP3': '5A', 'DIP2': '59', 'DIP5': '5C', 'DIP4': '5B', 'DIP7': '5E', 'DIP6': '5D', } self.wpc_light_map = { 'L11': '00', 'L12': '01', 'L13': '02', 'L14': '03', 'L15': '04', 'L16': '05', 'L17': '06', 'L18': '07', 'L21': '08', 'L22': '09', 'L23': '0A', 'L24': '0B', 'L25': '0C', 'L26': '0D', 'L27': '0E', 'L28': '0F', 'L31': '10', 'L32': '11', 'L33': '12', 'L34': '13', 'L35': '14', 'L36': '15', 'L37': '16', 'L38': '17', 'L41': '18', 'L42': '19', 'L43': '1A', 'L44': '1B', 'L45': '1C', 'L46': '1D', 'L47': '1E', 'L48': '1F', 'L51': '20', 'L52': '21', 'L53': '22', 'L54': '23', 'L55': '24', 'L56': '25', 'L57': '26', 'L58': '27', 'L61': '28', 'L62': '29', 'L63': '2A', 'L64': '2B', 'L65': '2C', 'L66': '2D', 'L67': '2E', 'L68': '2F', 'L71': '30', 'L72': '31', 'L73': '32', 'L74': '33', 'L75': '34', 'L76': '35', 'L77': '36', 'L78': '37', 'L81': '38', 'L82': '39', 'L83': '3A', 'L84': '3B', 'L85': '3C', 'L86': '3D', 'L87': '3E', 'L88': '3F', } self.wpc_driver_map = { 'C01': '00', 'C02': '01', 'C03': '02', 'C04': '03', 'C05': '04', 'C06': '05', 'C07': '06', 'C08': '07', 'C09': '08', 'C10': '09', 'C11': '0A', 'C12': '0B', 'C13': '0C', 'C14': '0D', 'C15': '0E', 'C16': '0F', 'C17': '10', 'C18': '11', 'C19': '12', 'C20': '13', 'C21': '14', 'C22': '15', 'C23': '16', 'C24': '17', 'C25': '18', 'C26': '19', 'C27': '1A', 'C28': '1B', 'C29': '1C', 'C30': '1D', 'C31': '1E', 'C32': '1F', 'C33': '24', 'C34': '25', 'C35': '26', 'C36': '27', 'FLRM': '20', 'FLRH': '21', 'FLLM': '22', 'FLLH': '23', 'FURM': '24', 'FURH': '25', 'FULM': '26', 'FULH': '27', 'C37': '28', 'C38': '29', 'C39': '2A', 'C40': '2B', 'C41': '2C', 'C42': '2D', 'C43': '2E', 'C44': '2F', } self.wpc_gi_map = { 'G01': '00', 'G02': '01', 'G03': '02', 'G04': '03', 'G05': '04', 'G06': '05', 'G07': '06', 'G08': '07', } self.pwm8_to_hex_string = { 0: '00', 1: '01', 2: '88', 3: '92', 4: 'AA', 5: 'BA', 6: 'EE', 7: 'FE', 8: 'FF' } self.pwm8_to_int = { 0: 0, 1: 1, 2: 136, 3: 146, 4: 170, 5: 186, 6: 238, 7: 254, 8: 255 } # todo verify this list self.fast_commands = {'ID': self.receive_id, # processor ID 'WX': self.receive_wx, # watchdog 'NN': self.receive_nn, # node id list 'NI': self.receive_ni, # node ID 'RX': self.receive_rx, # RGB cmd received 'DX': self.receive_dx, # DMD cmd received 'SX': self.receive_sx, # sw config received 'LX': self.receive_lx, # lamp cmd received 'PX': self.receive_px, # segment cmd received 'SA': self.receive_sa, # all switch states '/N': self.receive_nw_open, # nw switch open '-N': self.receive_nw_closed, # nw switch closed '/L': self.receive_local_open, # local sw open '-L': self.receive_local_closed, # local sw close 'WD': self.receive_wd, # watchdog }
def __init__(self, machine): super(HardwarePlatform, self).__init__(machine) self.log = logging.getLogger('FAST') self.log.info("Configuring FAST hardware.") if not serial_imported: self.log.error('Could not import "pySerial". This is required for ' 'the FAST platform interface') sys.exit() # ---------------------------------------------------------------------- # Platform-specific hardware features. WARNING: Do not edit these. They # are based on what the FAST hardware can and cannot do. self.features['max_pulse'] = 255 # todo self.features['hw_timer'] = False self.features['hw_rule_coil_delay'] = True # todo self.features['variable_recycle_time'] = True # todo self.features['variable_debounce_time'] = True # todo # Make the platform features available to everyone self.machine.config['platform'] = self.features # ---------------------------------------------------------------------- self.hw_rules = dict() self.dmd_connection = None self.net_connection = None self.rgb_connection = None self.fast_nodes = list() self.connection_threads = set() self.receive_queue = Queue.Queue() self.fast_leds = set() self.flag_led_tick_registered = False self.fast_io_boards = list() self.waiting_for_switch_data = False config_spec = ''' ports: list baud: int|921600 config_number_format: string|hex watchdog: ms|1000 default_debounce_open: ms|30 default_debounce_close: ms|30 debug: boolean|False ''' self.config = Config.process_config(config_spec=config_spec, source=self.machine.config['fast']) self.watchdog_command = 'WD:' + str(hex(self.config['watchdog']))[2:] self.machine_type = ( self.machine.config['hardware']['driverboards'].lower()) if self.machine_type == 'wpc': self.log.info("Configuring the FAST Controller for WPC driver " "board") else: self.log.info("Configuring FAST Controller for FAST IO boards.") self._connect_to_hardware() if 'config_number_format' not in self.machine.config['fast']: self.machine.config['fast']['config_number_format'] = 'int' self.wpc_switch_map = { # WPC HEX DEC 'S11': '00', #00 'S12': '01', #01 'S13': '02', #02 'S14': '03', #03 'S15': '04', #04 'S16': '05', #05 'S17': '06', #06 'S18': '07', #07 'S21': '08', #08 'S22': '09', #09 'S23': '0A', #10 'S24': '0B', #11 'S25': '0C', #12 'S26': '0D', #13 'S27': '0E', #14 'S28': '0F', #15 'S31': '10', #16 'S32': '11', #17 'S33': '12', #18 'S34': '13', #19 'S35': '14', #20 'S36': '15', #21 'S37': '16', #22 'S38': '17', #23 'S41': '18', #24 'S42': '19', #25 'S43': '1A', #26 'S44': '1B', #27 'S45': '1C', #28 'S46': '1D', #29 'S47': '1E', #30 'S48': '1F', #31 'S51': '20', #32 'S52': '21', #33 'S53': '22', #34 'S54': '23', #35 'S55': '24', #36 'S56': '25', #37 'S57': '26', #38 'S58': '27', #39 'S61': '28', #40 'S62': '29', #41 'S63': '2A', #42 'S64': '2B', #43 'S65': '2C', #44 'S66': '2D', #45 'S67': '2E', #46 'S68': '2F', #47 'S71': '30', #48 'S72': '31', #49 'S73': '32', #50 'S74': '33', #51 'S75': '34', #52 'S76': '35', #53 'S77': '36', #54 'S78': '37', #55 'S81': '38', #56 'S82': '39', #57 'S83': '3A', #58 'S84': '3B', #59 'S85': '3C', #60 'S86': '3D', #61 'S87': '3E', #62 'S88': '3F', #63 'S91': '40', #64 'S92': '41', #65 'S93': '42', #66 'S94': '43', #67 'S95': '44', #68 'S96': '45', #69 'S97': '46', #70 'S98': '47', #71 'S101': '48', #72 'S102': '49', #73 'S103': '4A', #74 'S104': '4B', #75 'S105': '4C', #76 'S106': '4D', #77 'S107': '4E', #78 'S108': '4F', #79 # Directs 'SD1': '50', #80 'SD2': '51', #81 'SD3': '52', #82 'SD4': '53', #83 'SD5': '54', #84 'SD6': '55', #85 'SD7': '56', #86 'SD8': '57', #87 # DIP switches 'DIP1': '58', #88 'DIP2': '59', #89 'DIP3': '5A', #90 'DIP4': '5B', #91 'DIP5': '5C', #92 'DIP6': '5D', #93 'DIP7': '5E', #94 'DIP8': '5F', #95 # Fliptronics 'SF1': '60', #96 'SF2': '61', #97 'SF3': '62', #98 'SF4': '63', #99 'SF5': '64', #100 'SF6': '65', #101 'SF7': '66', #102 'SF8': '67', #103 } self.wpc_light_map = { 'L11': '00', 'L12': '01', 'L13': '02', 'L14': '03', 'L15': '04', 'L16': '05', 'L17': '06', 'L18': '07', 'L21': '08', 'L22': '09', 'L23': '0A', 'L24': '0B', 'L25': '0C', 'L26': '0D', 'L27': '0E', 'L28': '0F', 'L31': '10', 'L32': '11', 'L33': '12', 'L34': '13', 'L35': '14', 'L36': '15', 'L37': '16', 'L38': '17', 'L41': '18', 'L42': '19', 'L43': '1A', 'L44': '1B', 'L45': '1C', 'L46': '1D', 'L47': '1E', 'L48': '1F', 'L51': '20', 'L52': '21', 'L53': '22', 'L54': '23', 'L55': '24', 'L56': '25', 'L57': '26', 'L58': '27', 'L61': '28', 'L62': '29', 'L63': '2A', 'L64': '2B', 'L65': '2C', 'L66': '2D', 'L67': '2E', 'L68': '2F', 'L71': '30', 'L72': '31', 'L73': '32', 'L74': '33', 'L75': '34', 'L76': '35', 'L77': '36', 'L78': '37', 'L81': '38', 'L82': '39', 'L83': '3A', 'L84': '3B', 'L85': '3C', 'L86': '3D', 'L87': '3E', 'L88': '3F', } self.wpc_driver_map = { 'C01': '00', 'C02': '01', 'C03': '02', 'C04': '03', 'C05': '04', 'C06': '05', 'C07': '06', 'C08': '07', 'C09': '08', 'C10': '09', 'C11': '0A', 'C12': '0B', 'C13': '0C', 'C14': '0D', 'C15': '0E', 'C16': '0F', 'C17': '10', 'C18': '11', 'C19': '12', 'C20': '13', 'C21': '14', 'C22': '15', 'C23': '16', 'C24': '17', 'C25': '18', 'C26': '19', 'C27': '1A', 'C28': '1B', 'C29': '1C', 'C30': '1D', 'C31': '1E', 'C32': '1F', 'C33': '24', 'C34': '25', 'C35': '26', 'C36': '27', 'FLRM': '20', 'FLRH': '21', 'FLLM': '22', 'FLLH': '23', 'FURM': '24', 'FURH': '25', 'FULM': '26', 'FULH': '27', 'C37': '28', 'C38': '29', 'C39': '2A', 'C40': '2B', 'C41': '2C', 'C42': '2D', 'C43': '2E', 'C44': '2F', } self.wpc_gi_map = { 'G01': '00', 'G02': '01', 'G03': '02', 'G04': '03', 'G05': '04', 'G06': '05', 'G07': '06', 'G08': '07', } # todo verify this list self.fast_commands = {'ID': self.receive_id, # processor ID 'WX': self.receive_wx, # watchdog 'NI': self.receive_ni, # node ID 'RX': self.receive_rx, # RGB cmd received 'DX': self.receive_dx, # DMD cmd received 'SX': self.receive_sx, # sw config received 'LX': self.receive_lx, # lamp cmd received 'PX': self.receive_px, # segment cmd received 'SA': self.receive_sa, # all switch states '/N': self.receive_nw_open, # nw switch open '-N': self.receive_nw_closed, # nw switch closed '/L': self.receive_local_open, # local sw open '-L': self.receive_local_closed, # local sw close 'WD': self.receive_wd, # watchdog }
def __init__(self, options): self.options = options self.log = logging.getLogger("MediaController") self.log.debug("Command line arguments: {}".format(self.options)) self.log.info("Media Controller Version %s", version.__version__) self.log.debug("Backbox Control Protocol Version %s", version.__bcp_version__) self.log.debug("Config File Version %s", version.__config_version__) python_version = sys.version_info if python_version[0] != 2 or python_version[1] != 7: self.log.error("Incorrect Python version. MPF requires Python 2.7." "x. You have Python %s.%s.%s.", python_version[0], python_version[1], python_version[2]) sys.exit() self.log.debug("Python version: %s.%s.%s", python_version[0], python_version[1], python_version[2]) self.log.debug("Platform: %s", sys.platform) self.log.debug("Python executable location: %s", sys.executable) self.log.debug("32-bit Python? %s", sys.maxsize < 2**32) self.active_debugger = dict() self.config = dict() self.done = False # todo self.machine_path = None self.asset_managers = dict() self.window = None self.window_manager = None self.pygame = False self.pygame_requested = False self.registered_pygame_handlers = dict() self.pygame_allowed_events = list() self.socket_thread = None self.receive_queue = Queue.Queue() self.sending_queue = Queue.Queue() self.crash_queue = Queue.Queue() self.modes = CaseInsensitiveDict() self.player_list = list() self.player = None self.HZ = 0 self.next_tick_time = 0 self.secs_per_tick = 0 self.machine_vars = CaseInsensitiveDict() self.machine_var_monitor = False self.tick_num = 0 self.delay = DelayManager() self._pc_assets_to_load = 0 self._pc_total_assets = 0 self.pc_connected = False Task.create(self._check_crash_queue) self.bcp_commands = {'ball_start': self.bcp_ball_start, 'ball_end': self.bcp_ball_end, 'config': self.bcp_config, 'error': self.bcp_error, 'get': self.bcp_get, 'goodbye': self.bcp_goodbye, 'hello': self.bcp_hello, 'machine_variable': self.bcp_machine_variable, 'mode_start': self.bcp_mode_start, 'mode_stop': self.bcp_mode_stop, 'player_added': self.bcp_player_add, 'player_score': self.bcp_player_score, 'player_turn_start': self.bcp_player_turn_start, 'player_variable': self.bcp_player_variable, 'reset': self.reset, 'set': self.bcp_set, 'shot': self.bcp_shot, 'switch': self.bcp_switch, 'timer': self.bcp_timer, 'trigger': self.bcp_trigger, } FileManager.init() self.config = dict() self._load_mc_config() self._set_machine_path() self._load_machine_config() # Find the machine_files location. If it starts with a forward or # backward slash, then we assume it's from the mpf root. Otherwise we # assume it's from the subfolder location specified in the # mpfconfig file location if (options['machine_path'].startswith('/') or options['machine_path'].startswith('\\')): machine_path = options['machine_path'] else: machine_path = os.path.join(self.config['media_controller']['paths'] ['machine_files'], options['machine_path']) self.machine_path = os.path.abspath(machine_path) # Add the machine folder to our path so we can import modules from it sys.path.append(self.machine_path) self.log.info("Machine folder: %s", machine_path) mediacontroller_config_spec = ''' exit_on_disconnect: boolean|True port: int|5050 ''' self.config['media_controller'] = ( Config.process_config(mediacontroller_config_spec, self.config['media_controller'])) self.events = EventManager(self, setup_event_player=False) self.timing = Timing(self) # Load the media controller modules self.config['media_controller']['modules'] = ( self.config['media_controller']['modules'].split(' ')) self.log.info("Loading Modules...") for module in self.config['media_controller']['modules']: self.log.debug("Loading module: %s", module) module_parts = module.split('.') exec('self.' + module_parts[0] + '=' + module + '(self)') # todo there's probably a more pythonic way to do this, and I know # exec() is supposedly unsafe, but meh, if you have access to put # malicious files in the system folder then you have access to this # code too. self.start_socket_thread() self.events.post("init_phase_1") self.events._process_event_queue() self.events.post("init_phase_2") self.events._process_event_queue() self.events.post("init_phase_3") self.events._process_event_queue() self.events.post("init_phase_4") self.events._process_event_queue() self.events.post("init_phase_5") self.events._process_event_queue() self.reset()
def _initialize(self): # Initializes the auditor. We do this separate from __init__() since # we need everything else to be setup first. config = ''' save_events: list|ball_ended audit: list|None events: list|None player: list|None num_player_top_records: int|10 ''' self.config = Config.process_config(config, self.machine.config['auditor']) self.current_audits = self.data_manager.get_data() if not self.current_audits: self.current_audits = dict() # Make sure we have all the sections we need in our audit dict if 'switches' not in self.current_audits: self.current_audits['switches'] = dict() if 'events' not in self.current_audits: self.current_audits['events'] = dict() if 'player' not in self.current_audits: self.current_audits['player'] = dict() # Make sure we have all the switches in our audit dict for switch in self.machine.switches: if (switch.name not in self.current_audits['switches'] and 'no_audit' not in switch.tags): self.current_audits['switches'][switch.name] = 0 # build the list of switches we should audit self.switchnames_to_audit = {x.name for x in self.machine.switches if 'no_audit' not in x.tags} # Make sure we have all the player stuff in our audit dict if 'player' in self.config['audit']: for item in self.config['player']: if item not in self.current_audits['player']: self.current_audits['player'][item] = dict() self.current_audits['player'][item]['top'] = list() self.current_audits['player'][item]['average'] = 0 self.current_audits['player'][item]['total'] = 0 # Register for the events the auditor needs to do its job self.machine.events.add_handler('game_starting', self.enable) self.machine.events.add_handler('game_ended', self.disable) if 'player' in self.config['audit']: self.machine.events.add_handler('game_ending', self.audit_player) # Enable the shots monitor Shot.monitor_enabled = True self.machine.register_monitor('shots', self.audit_shot) # Add the switches monitor self.machine.switch_controller.add_monitor(self.audit_switch)
def _initialize(self): # Initializes the auditor. We do this separate from __init__() since # we need everything else to be setup first. config = ''' save_events: list|ball_ended audit: list|None events: list|None player: list|None num_player_top_records: int|10 ''' self.config = Config.process_config(config, self.machine.config['auditor']) self.filename = os.path.join( self.machine.machine_path, self.machine.config['mpf']['paths']['audits']) # todo add option for abs path outside of machine root self.current_audits = self.load_from_disk(self.filename) self.make_sure_path_exists(os.path.dirname(self.filename)) if not self.current_audits: self.current_audits = dict() # Make sure we have all the sections we need in our audit dict if 'switches' not in self.current_audits: self.current_audits['switches'] = dict() if 'events' not in self.current_audits: self.current_audits['events'] = dict() if 'player' not in self.current_audits: self.current_audits['player'] = dict() # Make sure we have all the switches in our audit dict for switch in self.machine.switches: if switch.name not in self.current_audits['switches']: self.current_audits['switches'][switch.name] = 0 # Make sure we have all the player stuff in our audit dict if 'player' in self.config['audit']: for item in self.config['player']: if item not in self.current_audits['player']: self.current_audits['player'][item] = dict() self.current_audits['player'][item]['top'] = list() self.current_audits['player'][item]['average'] = 0 self.current_audits['player'][item]['total'] = 0 # Register for the events the auditor needs to do its job self.machine.events.add_handler('game_starting', self.enable) self.machine.events.add_handler('game_ended', self.disable) if 'player' in self.config['audit']: self.machine.events.add_handler('game_ending', self.audit_player) # Enable the shots monitor Shot.monitor_enabled = True self.machine.register_monitor('shots', self.audit_shot)
def _initialize(self): # Initializes the auditor. We do this separate from __init__() since # we need everything else to be setup first. config = ''' save_events: list|ball_ended audit: list|None events: list|None player: list|None num_player_top_records: int|10 ''' self.config = Config.process_config(config, self.machine.config['auditor']) self.filename = os.path.join(self.machine.machine_path, self.machine.config['mpf']['paths']['audits']) # todo add option for abs path outside of machine root self.current_audits = self.load_from_disk(self.filename) self.make_sure_path_exists(os.path.dirname(self.filename)) if not self.current_audits: self.current_audits = dict() # Make sure we have all the sections we need in our audit dict if ('shots' in self.config['audit'] and 'shots' not in self.current_audits): self.current_audits['shots'] = dict() if ('switches' in self.config['audit'] and 'switches' not in self.current_audits): self.current_audits['switches'] = dict() if ('events' in self.config['audit'] and 'events' not in self.current_audits): self.current_audits['events'] = dict() if ('player' in self.config['audit'] and 'player' not in self.current_audits): self.current_audits['player'] = dict() # Make sure we have all the switches in our audit dict for switch in self.machine.switches: if switch.name not in self.current_audits['switches']: self.current_audits['switches'][switch.name] = 0 # Make sure we have all the shots in our audit dict if hasattr(self.machine, 'shots'): for shot in self.machine.shots.shots: if shot.name not in self.current_audits['shots']: self.current_audits['shots'][shot.name] = 0 # Make sure we have all the player stuff in our audit dict if 'player' in self.config['audit']: for item in self.config['player']: if item not in self.current_audits['player']: self.current_audits['player'][item] = dict() self.current_audits['player'][item]['top'] = list() self.current_audits['player'][item]['average'] = 0 self.current_audits['player'][item]['total'] = 0 # Register for the events the auditor needs to do its job self.machine.events.add_handler('game_starting', self.enable) self.machine.events.add_handler('game_ended', self.disable) if 'player' in self.config['audit']: self.machine.events.add_handler('game_ending', self.audit_player) # Enable the shots monitor Shot.monitor_enabled = True self.machine.register_monitor('shots', self.audit_shot)