|
17 | 17 |
|
18 | 18 | package org.photonvision.common.networking; |
19 | 19 |
|
| 20 | +import edu.wpi.first.networktables.NetworkTableInstance; |
20 | 21 | import java.io.IOException; |
| 22 | +import java.net.InetAddress; |
21 | 23 | import java.net.NetworkInterface; |
22 | 24 | import java.util.ArrayList; |
23 | 25 | import java.util.List; |
@@ -218,40 +220,57 @@ public static String getIPAddresses(String iFaceName) { |
218 | 220 | return String.join(", ", addresses); |
219 | 221 | } |
220 | 222 |
|
| 223 | + /** |
| 224 | + * Gets a MAC address of a network interface. On devices where networking is managed by |
| 225 | + * PhotonVision, this will return the MAC address of the configured interface. Otherwise, this |
| 226 | + * will attempt to search for the network interface in current use and use that interface's MAC |
| 227 | + * address, and if that fails, it will return a MAC address from the first network interface with |
| 228 | + * a MAC address, as sorted by {@link NetworkInterface#networkInterfaces()}. |
| 229 | + * |
| 230 | + * @return The MAC address. |
| 231 | + */ |
221 | 232 | public static String getMacAddress() { |
222 | 233 | var config = ConfigManager.getInstance().getConfig().getNetworkConfig(); |
223 | | - if (config.networkManagerIface == null || config.networkManagerIface.isBlank()) { |
224 | | - // This is a silly heuristic to find a network interface that PV might be using. It looks like |
225 | | - // it works pretty well, but Hyper-V adapters still show up in the list. But we're using MAC |
226 | | - // address as a semi-unique identifier, not as a source of truth, so this should be fine. |
227 | | - // Hyper-V adapters seem to show up near the end of the list anyways, so it's super likely |
228 | | - // we'll find the right adapter anyways |
229 | | - try { |
230 | | - for (var iface : NetworkInterface.networkInterfaces().toList()) { |
231 | | - if (iface.isUp() && !iface.isVirtual() && !iface.isLoopback()) { |
232 | | - byte[] mac = iface.getHardwareAddress(); |
233 | | - if (mac == null) { |
234 | | - logger.error("No MAC address found for " + iface.getDisplayName()); |
235 | | - } |
| 234 | + try { |
| 235 | + // Not managed? See if we're connected to a network. General assumption is one interface in |
| 236 | + // use at a time |
| 237 | + if (config.networkManagerIface == null || config.networkManagerIface.isBlank()) { |
| 238 | + // Use NT client IP address to find the interface in use |
| 239 | + if (!config.runNTServer) { |
| 240 | + var conn = NetworkTableInstance.getDefault().getConnections(); |
| 241 | + if (conn.length > 0 && !conn[0].remote_ip.equals("127.0.0.1")) { |
| 242 | + var addr = InetAddress.getByName(conn[0].remote_ip); |
| 243 | + return formatMacAddress(NetworkInterface.getByInetAddress(addr).getHardwareAddress()); |
| 244 | + } |
| 245 | + } |
| 246 | + // Connected to a localhost server or we are the server? Try resolving ourselves. Only |
| 247 | + // returns a localhost address when there's no other interface available on Windows, but |
| 248 | + // like to return a localhost address on Linux |
| 249 | + var localIface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost()); |
| 250 | + if (localIface != null) { |
| 251 | + byte[] mac = localIface.getHardwareAddress(); |
| 252 | + if (mac != null) { |
236 | 253 | return formatMacAddress(mac); |
237 | 254 | } |
238 | 255 | } |
239 | | - } catch (Exception e) { |
240 | | - logger.error("Error getting MAC address:", e); |
241 | | - } |
242 | | - return ""; |
243 | | - } |
244 | | - try { |
245 | | - byte[] mac = NetworkInterface.getByName(config.networkManagerIface).getHardwareAddress(); |
246 | | - if (mac == null) { |
247 | | - logger.error("No MAC address found for " + config.networkManagerIface); |
248 | | - return ""; |
| 256 | + // Fine. Just find something with a MAC address |
| 257 | + for (var iface : NetworkInterface.networkInterfaces().toList()) { |
| 258 | + if (iface.isUp() && iface.getHardwareAddress() != null) { |
| 259 | + return formatMacAddress(iface.getHardwareAddress()); |
| 260 | + } |
| 261 | + } |
| 262 | + } else { // Managed? We should have a working interface available |
| 263 | + byte[] mac = NetworkInterface.getByName(config.networkManagerIface).getHardwareAddress(); |
| 264 | + if (mac != null) { |
| 265 | + return formatMacAddress(mac); |
| 266 | + } else { |
| 267 | + logger.error("No MAC address found for " + config.networkManagerIface); |
| 268 | + } |
249 | 269 | } |
250 | | - return formatMacAddress(mac); |
251 | 270 | } catch (Exception e) { |
252 | | - logger.error("Error getting MAC address for " + config.networkManagerIface, e); |
253 | | - return ""; |
| 271 | + logger.error("Error getting MAC address", e); |
254 | 272 | } |
| 273 | + return ""; |
255 | 274 | } |
256 | 275 |
|
257 | 276 | private static String formatMacAddress(byte[] mac) { |
|
0 commit comments