mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-19 00:41:41 +00:00
Fix incorrect hostname on non-managed devices (#2203)
I have all sorts of weird adapters from npcap and Hyper-V that don't have MAC addresses, so I'm simplifying the logic down so that it always tries to find _any_ adapter with a MAC address, but attempts to see if it can find what adapter is in use right now and use the MAC address from that. This also unpublishes old MAC address topics, which wasn't done before.
This commit is contained in:
@@ -253,6 +253,8 @@ public class NetworkTablesManager {
|
||||
String mac = NetworkUtils.getMacAddress();
|
||||
if (!mac.equals(currentMacAddress)) {
|
||||
logger.debug("MAC address changed! New MAC address is " + mac + ", was " + currentMacAddress);
|
||||
kCoprocTable.getSubTable(currentMacAddress).getEntry("hostname").unpublish();
|
||||
kCoprocTable.getSubTable(currentMacAddress).getEntry("cameraNames").unpublish();
|
||||
currentMacAddress = mac;
|
||||
}
|
||||
if (mac.isEmpty()) {
|
||||
@@ -260,7 +262,13 @@ public class NetworkTablesManager {
|
||||
return;
|
||||
}
|
||||
|
||||
String hostname = ConfigManager.getInstance().getConfig().getNetworkConfig().hostname;
|
||||
var config = ConfigManager.getInstance().getConfig();
|
||||
String hostname;
|
||||
if (config.getNetworkConfig().shouldManage) {
|
||||
hostname = config.getNetworkConfig().hostname;
|
||||
} else {
|
||||
hostname = CameraServerJNI.getHostname();
|
||||
}
|
||||
if (hostname == null || hostname.isEmpty()) {
|
||||
logger.error("Cannot check hostname and camera names, hostname is not set!");
|
||||
return;
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
|
||||
package org.photonvision.common.networking;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -218,40 +220,57 @@ public class NetworkUtils {
|
||||
return String.join(", ", addresses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a MAC address of a network interface. On devices where networking is managed by
|
||||
* PhotonVision, this will return the MAC address of the configured interface. Otherwise, this
|
||||
* will attempt to search for the network interface in current use and use that interface's MAC
|
||||
* address, and if that fails, it will return a MAC address from the first network interface with
|
||||
* a MAC address, as sorted by {@link NetworkInterface#networkInterfaces()}.
|
||||
*
|
||||
* @return The MAC address.
|
||||
*/
|
||||
public static String getMacAddress() {
|
||||
var config = ConfigManager.getInstance().getConfig().getNetworkConfig();
|
||||
if (config.networkManagerIface == null || config.networkManagerIface.isBlank()) {
|
||||
// This is a silly heuristic to find a network interface that PV might be using. It looks like
|
||||
// it works pretty well, but Hyper-V adapters still show up in the list. But we're using MAC
|
||||
// address as a semi-unique identifier, not as a source of truth, so this should be fine.
|
||||
// Hyper-V adapters seem to show up near the end of the list anyways, so it's super likely
|
||||
// we'll find the right adapter anyways
|
||||
try {
|
||||
for (var iface : NetworkInterface.networkInterfaces().toList()) {
|
||||
if (iface.isUp() && !iface.isVirtual() && !iface.isLoopback()) {
|
||||
byte[] mac = iface.getHardwareAddress();
|
||||
if (mac == null) {
|
||||
logger.error("No MAC address found for " + iface.getDisplayName());
|
||||
}
|
||||
try {
|
||||
// Not managed? See if we're connected to a network. General assumption is one interface in
|
||||
// use at a time
|
||||
if (config.networkManagerIface == null || config.networkManagerIface.isBlank()) {
|
||||
// Use NT client IP address to find the interface in use
|
||||
if (!config.runNTServer) {
|
||||
var conn = NetworkTableInstance.getDefault().getConnections();
|
||||
if (conn.length > 0 && !conn[0].remote_ip.equals("127.0.0.1")) {
|
||||
var addr = InetAddress.getByName(conn[0].remote_ip);
|
||||
return formatMacAddress(NetworkInterface.getByInetAddress(addr).getHardwareAddress());
|
||||
}
|
||||
}
|
||||
// Connected to a localhost server or we are the server? Try resolving ourselves. Only
|
||||
// returns a localhost address when there's no other interface available on Windows, but
|
||||
// like to return a localhost address on Linux
|
||||
var localIface = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
|
||||
if (localIface != null) {
|
||||
byte[] mac = localIface.getHardwareAddress();
|
||||
if (mac != null) {
|
||||
return formatMacAddress(mac);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Error getting MAC address:", e);
|
||||
// Fine. Just find something with a MAC address
|
||||
for (var iface : NetworkInterface.networkInterfaces().toList()) {
|
||||
if (iface.isUp() && iface.getHardwareAddress() != null) {
|
||||
return formatMacAddress(iface.getHardwareAddress());
|
||||
}
|
||||
}
|
||||
} else { // Managed? We should have a working interface available
|
||||
byte[] mac = NetworkInterface.getByName(config.networkManagerIface).getHardwareAddress();
|
||||
if (mac != null) {
|
||||
return formatMacAddress(mac);
|
||||
} else {
|
||||
logger.error("No MAC address found for " + config.networkManagerIface);
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
try {
|
||||
byte[] mac = NetworkInterface.getByName(config.networkManagerIface).getHardwareAddress();
|
||||
if (mac == null) {
|
||||
logger.error("No MAC address found for " + config.networkManagerIface);
|
||||
return "";
|
||||
}
|
||||
return formatMacAddress(mac);
|
||||
} catch (Exception e) {
|
||||
logger.error("Error getting MAC address for " + config.networkManagerIface, e);
|
||||
return "";
|
||||
logger.error("Error getting MAC address", e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String formatMacAddress(byte[] mac) {
|
||||
|
||||
Reference in New Issue
Block a user