From 3db2f30ea710da4fb160cfc98ba6625e3635b775 Mon Sep 17 00:00:00 2001 From: Banks Troutman Date: Sun, 6 Oct 2019 17:26:17 -0400 Subject: [PATCH] Continued rework of networking, added root check --- Main/chameleon-vision.iml | 38 ++--- .../main/java/com/chameleonvision/Main.java | 41 ++++- .../network/LinuxNetworking.java | 99 ++++++++++++ .../{settings => }/network/NetworkIPMode.java | 2 +- .../network/NetworkInterface.java | 57 +++++++ .../network/NetworkManager.java | 122 +++++++++++++++ .../network/SysNetworking.java | 37 +++++ .../network/WindowsNetworking.java | 57 +++++++ .../chameleonvision/settings/Platform.java | 29 +++- .../settings/SettingsManager.java | 10 +- .../settings/network/INetworking.java | 14 -- .../settings/network/LinuxNetworking.java | 37 ----- .../settings/network/NetworkInterface.java | 23 --- .../settings/network/NetworkManager.java | 40 ----- .../settings/network/WindowsNetworking.java | 83 ----------- .../{Handler => util}/MathHandler.java | 9 +- .../com/chameleonvision/util/ShellExec.java | 141 ++++++++++++++++++ .../vision/process/CVProcess.java | 2 +- 18 files changed, 607 insertions(+), 234 deletions(-) create mode 100644 Main/src/main/java/com/chameleonvision/network/LinuxNetworking.java rename Main/src/main/java/com/chameleonvision/{settings => }/network/NetworkIPMode.java (54%) create mode 100644 Main/src/main/java/com/chameleonvision/network/NetworkInterface.java create mode 100644 Main/src/main/java/com/chameleonvision/network/NetworkManager.java create mode 100644 Main/src/main/java/com/chameleonvision/network/SysNetworking.java create mode 100644 Main/src/main/java/com/chameleonvision/network/WindowsNetworking.java delete mode 100644 Main/src/main/java/com/chameleonvision/settings/network/INetworking.java delete mode 100644 Main/src/main/java/com/chameleonvision/settings/network/LinuxNetworking.java delete mode 100644 Main/src/main/java/com/chameleonvision/settings/network/NetworkInterface.java delete mode 100644 Main/src/main/java/com/chameleonvision/settings/network/NetworkManager.java delete mode 100644 Main/src/main/java/com/chameleonvision/settings/network/WindowsNetworking.java rename Main/src/main/java/com/chameleonvision/{Handler => util}/MathHandler.java (84%) create mode 100644 Main/src/main/java/com/chameleonvision/util/ShellExec.java diff --git a/Main/chameleon-vision.iml b/Main/chameleon-vision.iml index d285b15a4..f29e8915e 100644 --- a/Main/chameleon-vision.iml +++ b/Main/chameleon-vision.iml @@ -10,23 +10,13 @@ - - - - - - - - - - - - - - - - - + + + + + + + @@ -66,13 +56,13 @@ - - - - - - - + + + + + + + diff --git a/Main/src/main/java/com/chameleonvision/Main.java b/Main/src/main/java/com/chameleonvision/Main.java index e380eec0a..4b47c7db3 100644 --- a/Main/src/main/java/com/chameleonvision/Main.java +++ b/Main/src/main/java/com/chameleonvision/Main.java @@ -1,16 +1,18 @@ package com.chameleonvision; +import com.chameleonvision.network.NetworkManager; import com.chameleonvision.settings.Platform; import com.chameleonvision.settings.SettingsManager; -import com.chameleonvision.settings.network.NetworkManager; import com.chameleonvision.util.Utilities; import com.chameleonvision.vision.camera.CameraManager; import com.chameleonvision.web.Server; import edu.wpi.cscore.CameraServerCvJNI; import edu.wpi.cscore.CameraServerJNI; +import edu.wpi.first.networktables.LogMessage; import edu.wpi.first.networktables.NetworkTableInstance; import java.io.IOException; +import java.util.function.Consumer; public class Main { @@ -18,14 +20,31 @@ public class Main { private static final String NT_SERVERMODE_KEY = "--nt-servermode"; // no args for this setting private static final String NT_CLIENTMODESERVER_KEY = "--nt-client-server"; // expects String representing an IP address (hostnames will be rejected!) private static final String NETWORK_MANAGE_KEY = "--unmanage-network"; // no args for this setting + private static final String IGNORE_ROOT = "--ignore-root"; // no args for this setting private static final int DEFAULT_PORT = 8888; private static int webserverPort = DEFAULT_PORT; private static boolean ntServerMode = false; private static boolean manageNetwork = true; + private static boolean ignoreRoot = false; private static String ntClientModeServer = null; + private static class NTLogger implements Consumer { + + private boolean hasReportedConnectionFailure = false; + + @Override + public void accept(LogMessage logMessage) { + if (!hasReportedConnectionFailure && logMessage.message.contains("timed out")) { + System.err.println("NT Connection has failed!"); + hasReportedConnectionFailure = true; + } + } + } + + public static final Platform CurrentPlatform = Platform.getCurrentPlatform(); + private static void handleArgs(String[] args) { for (int i = 0; i < args.length; i++) { var key = args[i].toLowerCase(); @@ -44,6 +63,7 @@ public class Main { break; case NT_SERVERMODE_KEY: case NETWORK_MANAGE_KEY: + case IGNORE_ROOT: // nothing } @@ -78,6 +98,8 @@ public class Main { case NETWORK_MANAGE_KEY: manageNetwork = false; break; + case IGNORE_ROOT: + ignoreRoot = true; } } } @@ -85,23 +107,36 @@ public class Main { public static void main(String[] args) { handleArgs(args); + if (!CurrentPlatform.isRoot()) { + if (ignoreRoot) { + // TODO: should we do this? + // manageNetwork = false; + System.out.println("Ignoring root, network will not be managed!"); + } else { + System.err.println("This program must be run as root!"); + return; + } + } + // Attempt to load the JNI Libraries try { CameraServerJNI.forceLoad(); CameraServerCvJNI.forceLoad(); } catch (IOException e) { - var errorStr = Platform.getCurrentPlatform().equals(Platform.UNSUPPORTED) ? "Unsupported platform!" : "Failed to load JNI Libraries!"; + var errorStr = CurrentPlatform.equals(Platform.UNSUPPORTED) ? "Unsupported platform!" : "Failed to load JNI Libraries!"; throw new RuntimeException(errorStr); } if (CameraManager.initializeCameras()) { - SettingsManager.initialize(manageNetwork); + SettingsManager.initialize(); + NetworkManager.initialize(manageNetwork); CameraManager.initializeThreads(); if (ntServerMode) { System.out.println("Starting NT Server"); NetworkTableInstance.getDefault().startServer(); } else { + NetworkTableInstance.getDefault().addLogger(new NTLogger(), 0, 255); // to hide error messages if (ntClientModeServer != null) { NetworkTableInstance.getDefault().startClient(ntClientModeServer); } else { diff --git a/Main/src/main/java/com/chameleonvision/network/LinuxNetworking.java b/Main/src/main/java/com/chameleonvision/network/LinuxNetworking.java new file mode 100644 index 000000000..e22722324 --- /dev/null +++ b/Main/src/main/java/com/chameleonvision/network/LinuxNetworking.java @@ -0,0 +1,99 @@ +package com.chameleonvision.network; + +import com.chameleonvision.settings.NetworkSettings; +import com.chameleonvision.settings.SettingsManager; +import com.chameleonvision.util.ShellExec; + +import java.io.BufferedOutputStream; +import java.io.IOException; +import java.net.InetAddress; +import java.net.SocketException; +import java.net.UnknownHostException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class LinuxNetworking extends SysNetworking { + + private ShellExec shell = new ShellExec(true, true); + + @Override + public boolean setDHCP() { + var ifaceName = networkInterface.name; + var ethResetCmd = String.format("ifconfig %s 0.0.0.0 0.0.0.0", ifaceName); + var dhclientCmd = String.format("dhclient %s", ifaceName); + + + // ifconfig eth0 0.0.0.0 0.0.0.0 + try { + int retCode = shell.execute("ifconfig", null, true, ifaceName, "0.0.0.0", "0.0.0.0"); + while (!shell.isOutputCompleted() && !shell.isErrorCompleted()) {} + var out = shell.getOutput(); + var err = shell.getError(); + if (retCode != 0) return false; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + + try { + int retCode = shell.execute("dhclient", null, true, ifaceName); + while (!shell.isOutputCompleted() && !shell.isErrorCompleted()) {} + var out = shell.getOutput(); + var err = shell.getError(); + if (retCode != 0) return false; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + + return true; + } + + @Override + public boolean setHostname(String newHostname) { + var cmdString = String.format("hostnamectl set-hostname %s", newHostname); + + try { + var process = Runtime.getRuntime().exec(cmdString); + var returnCode = shell.execute("hostnamectl", null, true, "set-hostname", newHostname); + return returnCode == 0; + } catch(Exception e) { + e.printStackTrace(); + return false; + } + } + + @Override + public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) { + try { + int clearRetCode = shell.execute("ip addr flush dev", null, true, networkInterface.name); + int setIPRetCode = shell.execute(String.format("ip addr add %s/%s broadcast %s dev %s", ipAddress, netmask, broadcast, networkInterface.name), null, true); + int setGatewayRetCode = shell.execute(String.format("ip route replace default via %s dev %s", gateway, networkInterface.name), null, false); + return clearRetCode == 0 && setIPRetCode == 0 && setGatewayRetCode == 0; + } catch (IOException e) { + e.printStackTrace(); + return false; + } + } + + @Override + public List getNetworkInterfaces() throws SocketException { + List netInterfaces; + try { + netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces()); + } catch (SocketException e) { + return null; + } + + List goodInterfaces = new ArrayList<>(); + + for (var netInterface : netInterfaces) { + if (netInterface.getDisplayName().contains("lo")) continue; + if (!netInterface.isUp()) continue; + goodInterfaces.add(netInterface); + } + return goodInterfaces; + + } +} diff --git a/Main/src/main/java/com/chameleonvision/settings/network/NetworkIPMode.java b/Main/src/main/java/com/chameleonvision/network/NetworkIPMode.java similarity index 54% rename from Main/src/main/java/com/chameleonvision/settings/network/NetworkIPMode.java rename to Main/src/main/java/com/chameleonvision/network/NetworkIPMode.java index b3e28ee36..ec5a376d3 100644 --- a/Main/src/main/java/com/chameleonvision/settings/network/NetworkIPMode.java +++ b/Main/src/main/java/com/chameleonvision/network/NetworkIPMode.java @@ -1,4 +1,4 @@ -package com.chameleonvision.settings.network; +package com.chameleonvision.network; public enum NetworkIPMode { DHCP, diff --git a/Main/src/main/java/com/chameleonvision/network/NetworkInterface.java b/Main/src/main/java/com/chameleonvision/network/NetworkInterface.java new file mode 100644 index 000000000..75b5f7224 --- /dev/null +++ b/Main/src/main/java/com/chameleonvision/network/NetworkInterface.java @@ -0,0 +1,57 @@ +package com.chameleonvision.network; + +import com.chameleonvision.settings.GeneralSettings; + +import java.net.InetAddress; +import java.net.InterfaceAddress; + +public class NetworkInterface { + public final String name; + public final String displayName; + public final String IPAddress; + public final String Netmask; + public final String Gateway; + public final String Broadcast; + + public NetworkInterface(java.net.NetworkInterface inetface, InterfaceAddress ifaceAddress) { + name = inetface.getName(); + displayName = inetface.getDisplayName(); + + var inetAddress = ifaceAddress.getAddress(); + IPAddress = inetAddress.getHostAddress(); + Netmask = getIPv4LocalNetMask(ifaceAddress); + + // TODO: hack to "get" gateway, this is gross and bad, pls fix + var splitIPAddr = IPAddress.split("\\."); + splitIPAddr[3] = "1"; + Gateway = String.join(".", splitIPAddr); + splitIPAddr[3] = "255"; + Broadcast = String.join(".", splitIPAddr); + } + + private static String getIPv4LocalNetMask(InterfaceAddress interfaceAddress) { + var netPrefix = interfaceAddress.getNetworkPrefixLength(); + try { + // Since this is for IPv4, it's 32 bits, so set the sign value of + // the int to "negative"... + int shiftby = (1<<31); + // For the number of bits of the prefix -1 (we already set the sign bit) + for (int i = netPrefix - 1; i > 0; i--) { + // Shift the sign right... Java makes the sign bit sticky on a shift... + // So no need to "set it back up"... + shiftby = (shiftby >> 1); + } + // Transform the resulting value in xxx.xxx.xxx.xxx format, like if + /// it was a standard address... + String maskString = ((shiftby >> 24) & 255) + "." + ((shiftby >> 16) & 255) + "." + ((shiftby >> 8) & 255) + "." + (shiftby & 255); + // Return the address thus created... + return maskString; +// return InetAddress.getByName(maskString); + } + catch(Exception e) { + e.printStackTrace(); + } + // Something went wrong here... + return null; + } +} diff --git a/Main/src/main/java/com/chameleonvision/network/NetworkManager.java b/Main/src/main/java/com/chameleonvision/network/NetworkManager.java new file mode 100644 index 000000000..a287e98c1 --- /dev/null +++ b/Main/src/main/java/com/chameleonvision/network/NetworkManager.java @@ -0,0 +1,122 @@ +package com.chameleonvision.network; + + +import com.chameleonvision.settings.NetworkSettings; +import com.chameleonvision.settings.Platform; +import com.chameleonvision.settings.SettingsManager; + +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class NetworkManager { + private NetworkManager() {} + + protected static SysNetworking networking; + protected static NetworkInterface botInterface = null; + private static boolean isManaged = false; + + public static void initialize(boolean manage) { + isManaged = manage; + if (!isManaged) { + return; + } + + Platform platform = Platform.getCurrentPlatform(); + + if (platform.isLinux()) { + networking = new LinuxNetworking(); + } else if (platform.isWindows()) { +// networking = new WindowsNetworking(); + System.out.println("Windows networking is not yet supported. Running unmanaged."); + return; + } + + List interfaces = new ArrayList<>(); + List goodInterfaces = new ArrayList<>(); + + try { + interfaces = networking.getNetworkInterfaces(); + } catch (SocketException e) { + e.printStackTrace(); + } + + var teamBytes = NetworkSettings.GetTeamNumberIPBytes(SettingsManager.GeneralSettings.team_number); + + if (interfaces.size() > 0) { + for (var inetface : interfaces) { + for (var inetfaceAddr : inetface.getInterfaceAddresses()) { + var rawAddr = inetfaceAddr.getAddress().getAddress(); + if (rawAddr.length > 4) continue; + if (rawAddr[1] == teamBytes[0] && rawAddr[2] == teamBytes[1]) { + goodInterfaces.add(new NetworkInterface(inetface, inetfaceAddr)); + } + } + } + + if (goodInterfaces.size() == 0) { + isManaged = false; + System.err.println("No valid network interfaces found! Staying unmanaged."); + return; + } + + botInterface = goodInterfaces.get(0); + networking.setNetworkInterface(botInterface); + } else { + isManaged = false; + System.err.println("No valid network interfaces found! Staying unmanaged."); + return; + } + + if(!loadFromGeneralSettings()) { + isManaged = false; + System.err.println("Failed to load network settings. Staying unmanaged!"); + } + } + + private static boolean loadFromGeneralSettings() { + if (!isManaged) { + return true; + } + + var genSettings = SettingsManager.GeneralSettings; + boolean isStatic = genSettings.connection_type.toLowerCase().equals("Static"); + + if (isStatic) { + var splitIPAddr = genSettings.ip.split("\\."); + splitIPAddr[3] = "255"; + var broadcast = String.join(".", splitIPAddr); + if (!setStatic(genSettings.ip, genSettings.netmask, genSettings.gateway, broadcast)) { + return false; + } + } else { + if (!setDHCP()) { + return false; + } + } + + return setHostname(genSettings.hostname); + } + + private static boolean setDHCP() { + if (!isManaged) { + return true; + } + return networking.setDHCP(); + } + + private static boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) { + if (!isManaged) { + return true; + } + return networking.setStatic(ipAddress, netmask, gateway, broadcast); + } + + private static boolean setHostname(String hostname) { + if (!isManaged) { + return true; + } + return networking.setHostname(hostname); + } +} diff --git a/Main/src/main/java/com/chameleonvision/network/SysNetworking.java b/Main/src/main/java/com/chameleonvision/network/SysNetworking.java new file mode 100644 index 000000000..91684e775 --- /dev/null +++ b/Main/src/main/java/com/chameleonvision/network/SysNetworking.java @@ -0,0 +1,37 @@ +package com.chameleonvision.network; + +import com.chameleonvision.util.ShellExec; + +import java.io.IOException; +import java.net.SocketException; +import java.util.List; +import java.util.Scanner; + +public abstract class SysNetworking { + + NetworkInterface networkInterface; + ShellExec shell = new ShellExec(true, true); + + public String getHostname() { + try { + var retCode = shell.execute("hostname", null, true); + if (retCode == 0) { + while(!shell.isOutputCompleted()) {} + return shell.getOutput(); + } else { + return null; + } + } catch (IOException e) { + return null; + } + } + + public void setNetworkInterface(NetworkInterface networkInterface) { + this.networkInterface = networkInterface; + } + public abstract boolean setDHCP(); + public abstract boolean setHostname(String hostname); + public abstract boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast); + public abstract List getNetworkInterfaces() throws SocketException; + +} diff --git a/Main/src/main/java/com/chameleonvision/network/WindowsNetworking.java b/Main/src/main/java/com/chameleonvision/network/WindowsNetworking.java new file mode 100644 index 000000000..d6ccd829b --- /dev/null +++ b/Main/src/main/java/com/chameleonvision/network/WindowsNetworking.java @@ -0,0 +1,57 @@ +package com.chameleonvision.network; + +import com.chameleonvision.settings.NetworkSettings; +import com.chameleonvision.settings.SettingsManager; + +import java.net.SocketException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class WindowsNetworking extends SysNetworking { + + @Override + public boolean setDHCP() { + return false; + } + + @Override + public boolean setHostname(String newHostname) { + var currentHostname = getHostname(); + + if (getHostname() == null) { + return false; + } + + String command = String.format("wmic computersystem where name=\"%s\" call rename name=\"%s\"", currentHostname, newHostname); + + try { + var process = Runtime.getRuntime().exec(command); + var returnCode = process.waitFor(); + return returnCode == 0; + } catch(Exception e) { + return false; + } + } + + @Override + public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) { + return false; + } + + @Override + public List getNetworkInterfaces() throws SocketException { + var netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces()); + + List goodInterfaces = new ArrayList<>(); + + for (var netInterface : netInterfaces) { + if (netInterface.getDisplayName().toLowerCase().contains("bluetooth")) continue; + if (netInterface.getDisplayName().toLowerCase().contains("virtual")) continue; + if (netInterface.getDisplayName().toLowerCase().contains("loopback")) continue; + if (!netInterface.isUp()) continue; + goodInterfaces.add(netInterface); + } + return goodInterfaces; + } +} diff --git a/Main/src/main/java/com/chameleonvision/settings/Platform.java b/Main/src/main/java/com/chameleonvision/settings/Platform.java index 12acdd962..1709a6ebd 100644 --- a/Main/src/main/java/com/chameleonvision/settings/Platform.java +++ b/Main/src/main/java/com/chameleonvision/settings/Platform.java @@ -1,10 +1,14 @@ package com.chameleonvision.settings; +import com.chameleonvision.util.ShellExec; + +import java.io.IOException; + public enum Platform { WINDOWS_64("Windows x64"), LINUX_64("Linux x64"), LINUX_RASPBIAN("Linux Raspbian"), - LINUX_AARCH64("Linux ARM 64bit"), + LINUX_AARCH64("Linux For Tegra"), MACOS_64("Mac OS x64"), UNSUPPORTED("Unsupported Platform"); @@ -26,6 +30,29 @@ public enum Platform { return this == MACOS_64; } + private static ShellExec shell = new ShellExec(true, false); + + public boolean isRoot() { + if (isLinux() || isMac()) { + try { + shell.execute("id", null, true, "-u"); + } catch (IOException e) { + e.printStackTrace(); + } + while (!shell.isOutputCompleted()) {} + if (shell.getExitCode() == 0) { + var out = shell.getOutput(); + out = out.split("\n")[0]; + return out.equals("0"); + } + } else if (isWindows()) { + return true; + } else { + return true; + } + return false; + } + public static Platform getCurrentPlatform() { var osName = System.getProperty("os.name"); var osArch = System.getProperty("os.arch"); diff --git a/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java b/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java index 1fbaf09d9..6a2a3c310 100644 --- a/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java +++ b/Main/src/main/java/com/chameleonvision/settings/SettingsManager.java @@ -1,6 +1,6 @@ package com.chameleonvision.settings; -import com.chameleonvision.settings.network.NetworkManager; +import com.chameleonvision.network.NetworkManager; import com.chameleonvision.util.FileHelper; import com.chameleonvision.vision.camera.CameraManager; import com.google.gson.Gson; @@ -19,10 +19,10 @@ public class SettingsManager { private SettingsManager() {} - public static void initialize(boolean manageNetwork) { + public static void initialize() { initGeneralSettings(); - if (manageNetwork) { - NetworkManager.init(); +// if (manageNetwork) { + // NetworkSettings netSettings = new NetworkSettings(); // netSettings.hostname = GeneralSettings.hostname; // netSettings.gateway = GeneralSettings.gateway; @@ -30,7 +30,7 @@ public class SettingsManager { // netSettings.connectionType = GeneralSettings.connection_type; // netSettings.ip = GeneralSettings.ip; // netSettings.run(); - } +// } var allCameras = CameraManager.getAllCamerasByName(); if (!allCameras.containsKey(GeneralSettings.curr_camera) && allCameras.size() > 0) { var cam = allCameras.entrySet().stream().findFirst().get().getValue(); diff --git a/Main/src/main/java/com/chameleonvision/settings/network/INetworking.java b/Main/src/main/java/com/chameleonvision/settings/network/INetworking.java deleted file mode 100644 index e34e736d3..000000000 --- a/Main/src/main/java/com/chameleonvision/settings/network/INetworking.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.chameleonvision.settings.network; - -import java.net.SocketException; -import java.util.List; - -public interface INetworking { - String getHostname(); - NetworkIPMode getIPMode(); - boolean setDHCP(); - boolean setHostname(String hostname); - boolean setStatic(String ipAddress, String netmask, String gateway); - List getNetworkInterfaces() throws SocketException; - -} diff --git a/Main/src/main/java/com/chameleonvision/settings/network/LinuxNetworking.java b/Main/src/main/java/com/chameleonvision/settings/network/LinuxNetworking.java deleted file mode 100644 index 9b664826b..000000000 --- a/Main/src/main/java/com/chameleonvision/settings/network/LinuxNetworking.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.chameleonvision.settings.network; - -import java.net.SocketException; -import java.util.List; - -public class LinuxNetworking implements INetworking { - - @Override - public String getHostname() { - return null; - } - - @Override - public NetworkIPMode getIPMode() { - return null; - } - - @Override - public boolean setDHCP() { - return false; - } - - @Override - public boolean setHostname(String hostname) { - return false; - } - - @Override - public boolean setStatic(String ipAddress, String netmask, String gateway) { - return false; - } - - @Override - public List getNetworkInterfaces() throws SocketException { - return null; - } -} diff --git a/Main/src/main/java/com/chameleonvision/settings/network/NetworkInterface.java b/Main/src/main/java/com/chameleonvision/settings/network/NetworkInterface.java deleted file mode 100644 index 57e7adbbe..000000000 --- a/Main/src/main/java/com/chameleonvision/settings/network/NetworkInterface.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.chameleonvision.settings.network; - -import com.chameleonvision.settings.NetworkSettings; -import com.chameleonvision.settings.SettingsManager; - -import java.net.InetAddress; -import java.util.Collections; - -public class NetworkInterface { - public final String name; - public final String displayName; -// public NetworkIPMode IPMode; -// public String IPAddress; -// public String Netmask; -// public String Gateway; - - public NetworkInterface(java.net.NetworkInterface inetface) { - - name = inetface.getName(); - displayName = inetface.getDisplayName(); - - } -} diff --git a/Main/src/main/java/com/chameleonvision/settings/network/NetworkManager.java b/Main/src/main/java/com/chameleonvision/settings/network/NetworkManager.java deleted file mode 100644 index 08bea3db9..000000000 --- a/Main/src/main/java/com/chameleonvision/settings/network/NetworkManager.java +++ /dev/null @@ -1,40 +0,0 @@ -package com.chameleonvision.settings.network; - - -import com.chameleonvision.settings.Platform; - -import java.net.SocketException; -import java.util.ArrayList; -import java.util.List; - -public class NetworkManager { - private NetworkManager() {} - - private static INetworking networking; - - public static void init() { - Platform platform = Platform.getCurrentPlatform(); - - if (platform.isLinux()) { - networking = new LinuxNetworking(); - } else if (platform.isWindows()) { - networking = new WindowsNetworking(); - } - - List interfaces = new ArrayList<>(); - - try { - interfaces = networking.getNetworkInterfaces(); - } catch (SocketException e) { - e.printStackTrace(); - } - - if (interfaces != null) { - for (var inetface : interfaces) { - if (inetface.displayName.toLowerCase().contains("asus")) { -// networking.setHostname("BIGRIG"); - } - } - } - } -} diff --git a/Main/src/main/java/com/chameleonvision/settings/network/WindowsNetworking.java b/Main/src/main/java/com/chameleonvision/settings/network/WindowsNetworking.java deleted file mode 100644 index 9dfd9df2c..000000000 --- a/Main/src/main/java/com/chameleonvision/settings/network/WindowsNetworking.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.chameleonvision.settings.network; - -import com.chameleonvision.settings.NetworkSettings; -import com.chameleonvision.settings.SettingsManager; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.net.InetAddress; -import java.net.SocketException; -import java.net.UnknownHostException; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; - -public class WindowsNetworking implements INetworking { - - @Override - public String getHostname() { - try { - InetAddress localhost = InetAddress.getLocalHost(); - return localhost.getHostName().split("/")[0]; - } catch (UnknownHostException e) { - return null; - } - } - - @Override - public NetworkIPMode getIPMode() { - return NetworkIPMode.UNKNOWN; - } - - @Override - public boolean setDHCP() { - return false; - } - - @Override - public boolean setHostname(String newHostname) { - var currentHostname = getHostname(); - - if (getHostname() == null) { - return false; - } - - String command = String.format("wmic computersystem where name=\"%s\" call rename name=\"%s\"", currentHostname, newHostname); - - try { - var process = Runtime.getRuntime().exec(command); - var returnCode = process.waitFor(); - return returnCode == 0; - } catch(Exception e) { - return false; - } - } - - @Override - public boolean setStatic(String ipAddress, String netmask, String gateway) { - return false; - } - - @Override - public List getNetworkInterfaces() throws SocketException { - var netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces()); - - List goodInterfaces = new ArrayList<>(); - - var teamBytes = NetworkSettings.GetTeamNumberIPBytes(SettingsManager.GeneralSettings.team_number); - - for (var inetface : netInterfaces) { - if (inetface.getDisplayName().toLowerCase().contains("bluetooth")) continue; - if (inetface.getDisplayName().toLowerCase().contains("virtual")) continue; - if (inetface.getDisplayName().toLowerCase().contains("loopback")) continue; - if (!inetface.isUp()) continue; - for (var inetAddr : Collections.list(inetface.getInetAddresses())) { - var rawAddr = inetAddr.getAddress(); - if (rawAddr[1] == teamBytes[0] && rawAddr[2] == teamBytes[1]) { - goodInterfaces.add(new NetworkInterface(inetface)); - } - } - } - return goodInterfaces; - } -} diff --git a/Main/src/main/java/com/chameleonvision/Handler/MathHandler.java b/Main/src/main/java/com/chameleonvision/util/MathHandler.java similarity index 84% rename from Main/src/main/java/com/chameleonvision/Handler/MathHandler.java rename to Main/src/main/java/com/chameleonvision/util/MathHandler.java index 40971fffc..651c84da9 100644 --- a/Main/src/main/java/com/chameleonvision/Handler/MathHandler.java +++ b/Main/src/main/java/com/chameleonvision/util/MathHandler.java @@ -1,15 +1,20 @@ -package com.chameleonvision.Handler; +package com.chameleonvision.util; + import java.lang.Math; + public class MathHandler { - MathHandler(){} + MathHandler() {} + public static double sigmoid(double x){ double bias = 0; double a = 5; double b = -0.05; double k = 200; + if (x < 50){ bias = -1.338; } + return ((k / (1 + Math.pow(Math.E,(a + (b * x))))) + bias); } } diff --git a/Main/src/main/java/com/chameleonvision/util/ShellExec.java b/Main/src/main/java/com/chameleonvision/util/ShellExec.java new file mode 100644 index 000000000..65a7c4f47 --- /dev/null +++ b/Main/src/main/java/com/chameleonvision/util/ShellExec.java @@ -0,0 +1,141 @@ +package com.chameleonvision.util; + +import java.io.*; + +/** + * Execute external process and optionally read output buffer. + */ +public class ShellExec { + private int exitCode; + private boolean readOutput, readError; + private StreamGobbler errorGobbler, outputGobbler; + + public ShellExec() { + this(false, false); + } + + public ShellExec(boolean readOutput, boolean readError) { + this.readOutput = readOutput; + this.readError = readError; + } + + /** + * Execute a command. + * @param command command ("c:/some/folder/script.bat" or "some/folder/script.sh") + * @param workdir working directory or NULL to use command folder + * @param wait wait for process to end + * @param args 0..n command line arguments + * @return process exit code + */ + public int execute(String command, String workdir, boolean wait, String...args) throws IOException { + String[] cmdArr; + if (args != null && args.length > 0) { + cmdArr = new String[1+args.length]; + cmdArr[0] = command; + System.arraycopy(args, 0, cmdArr, 1, args.length); + } else { + cmdArr = new String[] { command }; + } + + ProcessBuilder pb = new ProcessBuilder(cmdArr); + File workingDir = (workdir==null ? new File(command).getParentFile() : new File(workdir) ); + pb.directory(workingDir); + + Process process = pb.start(); + + // Consume streams, older jvm's had a memory leak if streams were not read, + // some other jvm+OS combinations may block unless streams are consumed. + errorGobbler = new StreamGobbler(process.getErrorStream(), readError); + outputGobbler = new StreamGobbler(process.getInputStream(), readOutput); + errorGobbler.start(); + outputGobbler.start(); + + exitCode = 0; + if (wait) { + try { + process.waitFor(); + exitCode = process.exitValue(); + } catch (InterruptedException ignored) { } + } + return exitCode; + } + + public int getExitCode() { + return exitCode; + } + + public boolean isOutputCompleted() { + return (outputGobbler != null && outputGobbler.isCompleted()); + } + + public boolean isErrorCompleted() { + return (errorGobbler != null && errorGobbler.isCompleted()); + } + + public String getOutput() { + return (outputGobbler != null ? outputGobbler.getOutput() : null); + } + + public String getError() { + return (errorGobbler != null ? errorGobbler.getOutput() : null); + } + +//******************************************** +//******************************************** + + /** + * StreamGobbler reads inputstream to "gobble" it. + * This is used by Executor class when running + * a commandline applications. Gobblers must read/purge + * INSTR and ERRSTR process streams. + * http://www.javaworld.com/javaworld/jw-12-2000/jw-1229-traps.html?page=4 + */ + @SuppressWarnings("WeakerAccess") + private class StreamGobbler extends Thread { + private InputStream is; + private StringBuilder output; + private volatile boolean completed; // mark volatile to guarantee a thread safety + + public StreamGobbler(InputStream is, boolean readStream) { + this.is = is; + this.output = (readStream ? new StringBuilder(256) : null); + } + + public void run() { + completed = false; + try { + String NL = System.getProperty("line.separator", "\r\n"); + + InputStreamReader isr = new InputStreamReader(is); + BufferedReader br = new BufferedReader(isr); + String line; + while ( (line = br.readLine()) != null) { + if (output != null) + output.append(line).append(NL); + } + } catch (IOException ex) { + // ex.printStackTrace(); + } + completed = true; + } + + /** + * Get inputstream buffer or null if stream + * was not consumed. + * @return + */ + public String getOutput() { + return (output != null ? output.toString() : null); + } + + /** + * Is input stream completed. + * @return + */ + public boolean isCompleted() { + return completed; + } + + } + +} diff --git a/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java b/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java index d701efbf5..80063f605 100644 --- a/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java +++ b/Main/src/main/java/com/chameleonvision/vision/process/CVProcess.java @@ -1,7 +1,7 @@ package com.chameleonvision.vision.process; import com.chameleonvision.vision.camera.CameraValues; -import com.chameleonvision.Handler.MathHandler; +import com.chameleonvision.util.MathHandler; import org.apache.commons.math3.util.FastMath; import org.jetbrains.annotations.NotNull; import org.opencv.core.*;