Skip to content
Permalink
Browse files

better debug output in FAST. handle more reset commands

  • Loading branch information...
jabdoa2 committed May 12, 2019
1 parent bb7d268 commit c79a36b312d33c5cc546e4d9637f51ccef3ddcaf
@@ -134,6 +134,10 @@ def _parse_msg(self, msg):
"""
raise NotImplementedError("Implement!")

def __repr__(self):
"""Return str representation."""
return self.port

@asyncio.coroutine
def _socket_reader(self):
while True:
@@ -152,5 +156,5 @@ def _socket_reader(self):
return

if self.debug:
self.log.debug("Received: %s (%s)", resp, "".join(" 0x%02x" % b for b in resp))
self.log.debug("%s received: %s (%s)", self, resp, "".join(" 0x%02x" % b for b in resp))
self._parse_msg(resp)
@@ -63,17 +63,17 @@ def __init__(self, machine):
self.hw_switch_data = None
self.io_boards = {} # type: Dict[int, FastIoBoard]

self.fast_commands = {'ID': lambda x: None, # processor ID
'WX': lambda x: None, # watchdog
'NI': lambda x: None, # node ID
'RX': lambda x: None, # RGB cmd received
'RA': lambda x: None, # RGB all cmd received
'RF': lambda x: None, # RGB fade cmd received
'DX': lambda x: None, # DMD cmd received
'SX': lambda x: None, # sw config received
'LX': lambda x: None, # lamp cmd received
'PX': lambda x: None, # segment cmd received
'WD': lambda x: None, # watchdog
self.fast_commands = {'ID': lambda x, y: None, # processor ID
'WX': lambda x, y: None, # watchdog
'NI': lambda x, y: None, # node ID
'RX': lambda x, y: None, # RGB cmd received
'RA': lambda x, y: None, # RGB all cmd received
'RF': lambda x, y: None, # RGB fade cmd received
'DX': lambda x, y: None, # DMD cmd received
'SX': lambda x, y: None, # sw config received
'LX': lambda x, y: None, # lamp cmd received
'PX': lambda x, y: None, # segment cmd received
'WD': lambda x, y: None, # watchdog
'SA': self.receive_sa, # all switch states
'/N': self.receive_nw_open, # nw switch open
'-N': self.receive_nw_closed, # nw switch closed
@@ -211,31 +211,29 @@ def _update_watchdog(self):
"""Send Watchdog command."""
self.net_connection.send('WD:' + str(hex(self.config['watchdog']))[2:])

def process_received_message(self, msg: str):
def process_received_message(self, msg: str, remote_processor: str):
"""Send an incoming message from the FAST controller to the proper method for servicing.
Args:
msg: messaged which was received
"""
if msg == "!SRE":
# ignore system interrupt
self.log.info("Received system interrupt.")
self.log.info("Received system interrupt from %s.", remote_processor)
return

if msg[2:3] == ':':
cmd = msg[0:2]
payload = msg[3:].replace('\r', '')
else: # pragma: no cover
self.log.warning("Received malformed message: %s", msg)
self.log.warning("Received malformed message: %s from %s", msg, remote_processor)
return

# Can't use try since it swallows too many errors for now
if cmd in self.fast_commands:
self.fast_commands[cmd](payload)
self.fast_commands[cmd](payload, remote_processor)
else: # pragma: no cover
self.log.warning("Received unknown serial command? %s. (This is ok"
" to ignore for now while the FAST platform is "
"in development)", msg)
self.log.warning("Received unknown serial command? %s from %s.", msg, remote_processor)

@asyncio.coroutine
def _connect_to_hardware(self):
@@ -296,52 +294,57 @@ def get_hw_switch_states(self):
"""Return hardware states."""
return self.hw_switch_data

def receive_nw_open(self, msg):
def receive_nw_open(self, msg, remote_processor):
"""Process network switch open.
Args:
msg: switch number
"""
assert remote_processor == "NET"
self.machine.switch_controller.process_switch_by_num(state=0,
num=(msg, 1),
platform=self)

def receive_nw_closed(self, msg):
def receive_nw_closed(self, msg, remote_processor):
"""Process network switch closed.
Args:
msg: switch number
"""
assert remote_processor == "NET"
self.machine.switch_controller.process_switch_by_num(state=1,
num=(msg, 1),
platform=self)

def receive_local_open(self, msg):
def receive_local_open(self, msg, remote_processor):
"""Process local switch open.
Args:
msg: switch number
"""
assert remote_processor == "NET"
self.machine.switch_controller.process_switch_by_num(state=0,
num=(msg, 0),
platform=self)

def receive_local_closed(self, msg):
def receive_local_closed(self, msg, remote_processor):
"""Process local switch closed.
Args:
msg: switch number
"""
assert remote_processor == "NET"
self.machine.switch_controller.process_switch_by_num(state=1,
num=(msg, 0),
platform=self)

def receive_sa(self, msg):
def receive_sa(self, msg, remote_processor):
"""Receive all switch states.
Args:
msg: switch states as bytearray
"""
assert remote_processor == "NET"
self.debug_log("Received SA: %s", msg)

hw_states = dict()
@@ -821,11 +824,11 @@ def clear_hw_rule(self, switch, coil):

driver.clear_autofire(driver.get_config_cmd(), driver.number)

def receive_bootloader(self, msg):
def receive_bootloader(self, msg, remote_processor):
"""Process bootloader message."""
self.debug_log("Got Bootloader message: %s", msg)
self.debug_log("Got Bootloader message: %s from", msg, remote_processor)
if msg in ('00', '02'):
self.error_log("The FAST Nano rebooted. Unfortunately, that means that is lost all it's state (such as "
"hardware rules or switch configs). This is likely cause by an unstable power supply but it "
"might as well be a firmware bug. MPF will exit now.")
self.machine.stop("FAST Nano rebooted during game")
self.error_log("The FAST %s processor rebooted. Unfortunately, that means that it lost all it's state "
"(such as hardware rules or switch configs). This is likely cause by an unstable power "
"supply but it might as well be a firmware bug. MPF will exit now.", remote_processor)
self.machine.stop("FAST {} rebooted during game".format(remote_processor))
@@ -180,22 +180,29 @@ def _identify_connection(self):
self.write_task.add_done_callback(self._done)

@asyncio.coroutine
def query_fast_io_boards(self):
"""Query the NET processor to see if any FAST IO boards are connected.
If so, queries the IO boards to log them and make sure they're the proper firmware version.
"""
# reset CPU early
def reset_net_cpu(self):
"""Reset the NET CPU."""
self.platform.debug_log('Resetting NET CPU.')
self.writer.write('BR:\r'.encode())
msg = ''
while msg != 'BR:P\r' and not msg.startswith('XX:'):
while msg != 'BR:P\r' and not msg.endswith('!B:02\r'):
msg = (yield from self.readuntil(b'\r')).decode()
self.platform.debug_log("Got: {}".format(msg))
if msg != 'BR:P\r':
self.platform.warning_log("Reset on the NET CPU failed (this might be normal on older firmwares)")

yield from asyncio.sleep(.1, loop=self.machine.clock.loop)
@asyncio.coroutine
def query_fast_io_boards(self):
"""Query the NET processor to see if any FAST IO boards are connected.
If so, queries the IO boards to log them and make sure they're the proper firmware version.
"""
# reset CPU early
try:
yield from asyncio.wait_for(self.reset_net_cpu(), 5, loop=self.machine.clock.loop)
except asyncio.TimeoutError:
self.platform.warning_log("Reset of NET CPU failed. This might be a firmware bug in your version.")
yield from asyncio.sleep(.1, loop=self.machine.clock.loop)
else:
self.platform.debug_log("Reset successful")

self.platform.debug_log('Reading all switches.')
self.writer.write('SA:\r'.encode())
@@ -205,7 +212,7 @@ def query_fast_io_boards(self):
if not msg.startswith('SA:'):
self.platform.log.warning("Got unexpected message from FAST: {}".format(msg))

self.platform.process_received_message(msg)
self.platform.process_received_message(msg, "NET")
self.platform.debug_log('Querying FAST IO boards...')

firmware_ok = True
@@ -294,6 +301,10 @@ def _socket_writer(self):

self._send(msg)

def __repr__(self):
"""Return str representation."""
return "{} ({})".format(self.port, self.remote_processor)

def _parse_msg(self, msg):
self.received_msg += msg

@@ -322,4 +333,4 @@ def _parse_msg(self, msg):
continue

if msg.decode() not in self.ignored_messages:
self.platform.process_received_message(msg.decode())
self.platform.process_received_message(msg.decode(), self.remote_processor)
@@ -165,7 +165,7 @@ def setUp(self):
"RF:00": "RF:P",
}
self.net_cpu.expected_commands = {
'BR:': 'BR:P',
'BR:': 'ä!B:02',
'ID:': 'ID:NET FP-CPU-002-1 01.03',
'NN:00': 'NN:00,FP-I/O-3208-2 ,01.00,08,20,04,06,00,00,00,00', # 3208 board
'NN:01': 'NN:01,FP-I/O-0804-1 ,01.00,04,08,04,06,00,00,00,00', # 0804 board
@@ -498,7 +498,7 @@ def _test_switch_changes(self):
self.assertFalse(self.switch_hit)

self.machine.events.add_handler("s_test_active", self._switch_hit_cb)
self.machine.default_platform.process_received_message("-N:07")
self.machine.default_platform.process_received_message("-N:07", "NET")
self.advance_time_and_run(1)

self.assertTrue(self.switch_hit)
@@ -509,7 +509,7 @@ def _test_switch_changes(self):
self.assertFalse(self.switch_hit)
self.assertTrue(self.machine.switch_controller.is_active("s_test"))

self.machine.default_platform.process_received_message("/N:07")
self.machine.default_platform.process_received_message("/N:07", "NET")
self.advance_time_and_run(1)
self.assertFalse(self.switch_hit)
self.assertFalse(self.machine.switch_controller.is_active("s_test"))
@@ -524,13 +524,13 @@ def _test_switch_changes_nc(self):
self.assertFalse(self.switch_hit)
self.assertTrue(self.machine.switch_controller.is_active("s_test_nc"))

self.machine.default_platform.process_received_message("-N:1A")
self.machine.default_platform.process_received_message("-N:1A", "NET")
self.advance_time_and_run(1)
self.assertFalse(self.switch_hit)
self.assertFalse(self.machine.switch_controller.is_active("s_test_nc"))

self.machine.events.add_handler("s_test_nc_active", self._switch_hit_cb)
self.machine.default_platform.process_received_message("/N:1A")
self.machine.default_platform.process_received_message("/N:1A", "NET")
self.advance_time_and_run(1)

self.assertTrue(self.machine.switch_controller.is_active("s_test_nc"))

0 comments on commit c79a36b

Please sign in to comment.
You can’t perform that action at this time.