Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion src/software/gameplay_tests/simulated_test_fixture.py
Original file line number Diff line number Diff line change
Expand Up @@ -591,7 +591,8 @@ def simulated_test_runner():
running_in_realtime=args.enable_thunderscope and not args.ci_mode,
) as yellow_fs:
with Gamecontroller(
suppress_logs=(not args.show_gamecontroller_logs)
suppress_logs=(not args.show_gamecontroller_logs),
parallelized=True,
) as gamecontroller:
blue_fs.setup_proto_unix_io(blue_full_system_proto_unix_io)
yellow_fs.setup_proto_unix_io(yellow_full_system_proto_unix_io)
Expand Down
1 change: 1 addition & 0 deletions src/software/thunderscope/binary_context_managers/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ py_library(
"//software/networking:ssl_proto_communication",
"//software/thunderscope:util",
"//software/thunderscope/common:thread_safe_circular_buffer",
requirement("netifaces"),
],
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
import logging
import os
import time
import netifaces

from subprocess import Popen
from typing import Any

Expand Down Expand Up @@ -44,15 +46,18 @@ def __init__(
suppress_logs: bool = False,
use_conventional_port: bool = False,
automate_referee: bool = False,
parallelized: bool = False,
) -> None:
"""Run Gamecontroller

:param suppress_logs: True if logs should be suppressed
:param use_conventional_port: True when using static referee port. False for dynamic port assignments.
:param automate_referee: True if referee commands should be automated
:param automate_referee: True if referee commands should be automated.
:param parallelized: True when this is one of many Gamecontrollers running at once.
"""
self.suppress_logs = suppress_logs
self.automate_referee = automate_referee
self.parallelized = parallelized

self.use_conventional_port = use_conventional_port
self.referee_port = None
Expand Down Expand Up @@ -109,17 +114,20 @@ def __enter__(self) -> Gamecontroller:

command += ["-publishAddress", f"{self.REFEREE_IP}:{self.referee_port}"]
command += ["-ciAddress", f"localhost:{self.ci_port}"]
command += [
"-address",
"localhost:0",
"-autorefAddress",
"localhost:0",
"-remoteControlAddress",
"localhost:0",
"-teamAddress",
"localhost:0",
"-backendOnly",
]
if self.parallelized:
# One of many GCs running at once: no web UI and all-dynamic ports so
# instances don't collide on the fixed UI / autoref ports.
command += [
"-address",
"localhost:0",
"-autorefAddress",
"localhost:0",
"-remoteControlAddress",
"localhost:0",
"-teamAddress",
"localhost:0",
"-backendOnly",
]

if self.suppress_logs:
with open(os.devnull, "w") as fp:
Expand Down Expand Up @@ -245,15 +253,10 @@ def __send_referee_command(data: Referee) -> None:
if autoref_proto_unix_io is not None:
autoref_proto_unix_io.send_proto(Referee, data)

if is_current_platform_macos():
loopback_iface = "en0"
else:
loopback_iface = "lo"

self.receive_referee_command = tbots_cpp.SSLRefereeProtoListener(
Gamecontroller.REFEREE_IP,
self.referee_port,
loopback_iface,
self.__get_referee_multicast_interface(),
__send_referee_command,
True,
)
Expand Down Expand Up @@ -630,3 +633,19 @@ def __update_robot_count(
robot_states[removed_robot_ids.get_nowait()].CopyFrom(place_state)
except queue.Empty:
return

@staticmethod
def __get_referee_multicast_interface() -> str:
"""Determine the network interface to join the referee multicast group on.

:return: the name of the interface to receive referee multicast on
"""
if not is_current_platform_macos():
return "lo"

default = netifaces.gateways().get("default", {}).get(netifaces.AF_INET)
if default:
# default is a (gateway_ip, interface_name) tuple
return default[1]

raise RuntimeError("Could not determine the default network interface on macOS")
Loading