Skip to content

Commit d446229

Browse files
committed
Improve MAC address detection and fix incorrect hostname on non-managed devices
1 parent 674f6e2 commit d446229

File tree

2 files changed

+52
-28
lines changed

2 files changed

+52
-28
lines changed

photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,22 @@ private void checkHostnameAndCameraNames() {
253253
String mac = NetworkUtils.getMacAddress();
254254
if (!mac.equals(currentMacAddress)) {
255255
logger.debug("MAC address changed! New MAC address is " + mac + ", was " + currentMacAddress);
256+
kCoprocTable.getSubTable(currentMacAddress).getEntry("hostname").unpublish();
257+
kCoprocTable.getSubTable(currentMacAddress).getEntry("cameraNames").unpublish();
256258
currentMacAddress = mac;
257259
}
258-
if (mac.isEmpty()) {
260+
if (mac.equals("00-00-00-00-00-00")) {
259261
logger.error("Cannot check hostname and camera names, MAC address is not set!");
260262
return;
261263
}
262264

263-
String hostname = ConfigManager.getInstance().getConfig().getNetworkConfig().hostname;
265+
var config = ConfigManager.getInstance().getConfig();
266+
String hostname;
267+
if (config.getNetworkConfig().shouldManage) {
268+
hostname = config.getNetworkConfig().hostname;
269+
} else {
270+
hostname = CameraServerJNI.getHostname();
271+
}
264272
if (hostname == null || hostname.isEmpty()) {
265273
logger.error("Cannot check hostname and camera names, hostname is not set!");
266274
return;

photon-core/src/main/java/org/photonvision/common/networking/NetworkUtils.java

Lines changed: 42 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@
1717

1818
package org.photonvision.common.networking;
1919

20+
import edu.wpi.first.networktables.NetworkTableInstance;
2021
import java.io.IOException;
22+
import java.net.InetAddress;
2123
import java.net.NetworkInterface;
2224
import java.util.ArrayList;
2325
import java.util.List;
@@ -218,40 +220,54 @@ public static String getIPAddresses(String iFaceName) {
218220
return String.join(", ", addresses);
219221
}
220222

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+
*/
221232
public static String getMacAddress() {
222233
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 {
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
248+
byte[] mac =
249+
NetworkInterface.getByInetAddress(InetAddress.getLocalHost()).getHardwareAddress();
250+
if (mac != null) {
251+
return formatMacAddress(mac);
252+
}
253+
// Fine. Just find something with a MAC address
230254
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-
}
236-
return formatMacAddress(mac);
255+
if (iface.isUp() && iface.getHardwareAddress() != null) {
256+
return formatMacAddress(iface.getHardwareAddress());
237257
}
238258
}
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 "";
259+
} else { // Managed? We should have a working interface available
260+
byte[] mac = NetworkInterface.getByName(config.networkManagerIface).getHardwareAddress();
261+
if (mac != null) {
262+
return formatMacAddress(mac);
263+
} else {
264+
logger.error("No MAC address found for " + config.networkManagerIface);
265+
}
249266
}
250-
return formatMacAddress(mac);
251267
} catch (Exception e) {
252-
logger.error("Error getting MAC address for " + config.networkManagerIface, e);
253-
return "";
268+
logger.error("Error getting MAC address", e);
254269
}
270+
return "00-00-00-00-00-00";
255271
}
256272

257273
private static String formatMacAddress(byte[] mac) {

0 commit comments

Comments
 (0)