mirror of
https://github.com/PhotonVision/photonvision
synced 2026-06-22 01:11:40 +00:00
Merge branch 'dev'
This commit is contained in:
@@ -10,23 +10,13 @@
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-java:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-jni:linuxathena:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-jni:linuxraspbian:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-jni:linuxx86-64:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-jni:windowsx86-64:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cameraserver:cameraserver-java:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-java:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxathena:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxraspbian:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxx86-64:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:windowsx86-64:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.wpiutil:wpiutil-java:2019.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2019.opencv:opencv-java:3.4.4-5" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2019.opencv:opencv-jni:windowsx86-64:3.4.4-5" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2019.opencv:opencv-jni:linuxx86-64:3.4.4-5" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2019.opencv:opencv-jni:linuxathena:3.4.4-5" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2019.opencv:opencv-jni:linuxraspbian:3.4.4-5" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cameraserver:cameraserver-java:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-java:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:osxx86-64:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxraspbian:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxx86-64:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:windowsx86-64:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.wpiutil:wpiutil-java:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: io.javalin:javalin:3.4.1" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.3.31" level="project" />
|
||||
<orderEntry type="library" name="Maven: org.jetbrains.kotlin:kotlin-stdlib:1.3.31" level="project" />
|
||||
@@ -66,13 +56,13 @@
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-jni:linuxx86-64:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-jni:osxx86-64:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cscore:cscore-jni:windowsx86-64:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cameraserver:cameraserver-java:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-java:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:osxx86-64:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxraspbian:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxx86-64:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:windowsx86-64:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.wpiutil:wpiutil-java:2019.4.1-176-ga5650b9" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.cameraserver:cameraserver-java:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-java:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:osxx86-64:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxraspbian:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:linuxx86-64:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.ntcore:ntcore-jni:windowsx86-64:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.wpiutil:wpiutil-java:2019.4.1-200-g2271570" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2020.opencv:opencv-java:3.4.7-1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2020.opencv:opencv-jni:linuxaarch64bionic:3.4.7-1" level="project" />
|
||||
<orderEntry type="library" name="Maven: edu.wpi.first.thirdparty.frc2020.opencv:opencv-jni:linuxraspbian:3.4.7-1" level="project" />
|
||||
|
||||
28
Main/pom.xml
28
Main/pom.xml
@@ -5,7 +5,7 @@
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.chameleon-vision.main</groupId>
|
||||
<artifactId>chameleon-vision</artifactId>
|
||||
<version>1.1.0-BETA</version>
|
||||
<version>1.1.3-BETA</version>
|
||||
<build>
|
||||
<plugins>
|
||||
<!--setup for java jdk 12-->
|
||||
@@ -116,37 +116,37 @@
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.cscore</groupId>
|
||||
<artifactId>cscore-java</artifactId>
|
||||
<version>2019.4.1-200-g2271570</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
</dependency>
|
||||
<!--frc cscore interface libs-->
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.cscore</groupId>
|
||||
<artifactId>cscore-jni</artifactId>
|
||||
<version>2019.4.1-200-g2271570</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>linuxaarch64bionic</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.cscore</groupId>
|
||||
<artifactId>cscore-jni</artifactId>
|
||||
<version>2019.4.1-200-g2271570</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>linuxraspbian</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.cscore</groupId>
|
||||
<artifactId>cscore-jni</artifactId>
|
||||
<version>2019.4.1-200-g2271570</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>linuxx86-64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.cscore</groupId>
|
||||
<artifactId>cscore-jni</artifactId>
|
||||
<version>2019.4.1-200-g2271570</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>osxx86-64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.cscore</groupId>
|
||||
<artifactId>cscore-jni</artifactId>
|
||||
<version>2019.4.1-200-g2271570</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>windowsx86-64</classifier>
|
||||
</dependency>
|
||||
|
||||
@@ -154,39 +154,39 @@
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.cameraserver</groupId>
|
||||
<artifactId>cameraserver-java</artifactId>
|
||||
<version>2019.4.1-176-ga5650b9</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
</dependency>
|
||||
|
||||
<!--frc network table java libs-->
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.ntcore</groupId>
|
||||
<artifactId>ntcore-java</artifactId>
|
||||
<version>2019.4.1-176-ga5650b9</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
</dependency>
|
||||
|
||||
<!--frc network tables interface libs-->
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.ntcore</groupId>
|
||||
<artifactId>ntcore-jni</artifactId>
|
||||
<version>2019.4.1-176-ga5650b9</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>osxx86-64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.ntcore</groupId>
|
||||
<artifactId>ntcore-jni</artifactId>
|
||||
<version>2019.4.1-176-ga5650b9</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>linuxraspbian</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.ntcore</groupId>
|
||||
<artifactId>ntcore-jni</artifactId>
|
||||
<version>2019.4.1-176-ga5650b9</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>linuxx86-64</classifier>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.ntcore</groupId>
|
||||
<artifactId>ntcore-jni</artifactId>
|
||||
<version>2019.4.1-176-ga5650b9</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
<classifier>windowsx86-64</classifier>
|
||||
</dependency>
|
||||
|
||||
@@ -194,7 +194,7 @@
|
||||
<dependency>
|
||||
<groupId>edu.wpi.first.wpiutil</groupId>
|
||||
<artifactId>wpiutil-java</artifactId>
|
||||
<version>2019.4.1-176-ga5650b9</version>
|
||||
<version>2019.4.1-213-g56d782b</version>
|
||||
</dependency>
|
||||
|
||||
<!-- WPI OpenCV for all supported platforms -->
|
||||
|
||||
@@ -1,15 +1,18 @@
|
||||
package com.chameleonvision;
|
||||
|
||||
import com.chameleonvision.network.NetworkManager;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.util.Utilities;
|
||||
import com.chameleonvision.vision.camera.CameraManager;
|
||||
import com.chameleonvision.vision.process.VisionProcess;
|
||||
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 {
|
||||
|
||||
@@ -17,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<LogMessage> {
|
||||
|
||||
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();
|
||||
@@ -43,6 +63,7 @@ public class Main {
|
||||
break;
|
||||
case NT_SERVERMODE_KEY:
|
||||
case NETWORK_MANAGE_KEY:
|
||||
case IGNORE_ROOT:
|
||||
// nothing
|
||||
}
|
||||
|
||||
@@ -77,29 +98,53 @@ public class Main {
|
||||
case NETWORK_MANAGE_KEY:
|
||||
manageNetwork = false;
|
||||
break;
|
||||
case IGNORE_ROOT:
|
||||
ignoreRoot = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (CurrentPlatform.equals(Platform.UNSUPPORTED)) {
|
||||
System.err.printf("Sorry, this platform is not supported. Give these details to the developers.\n%s\n", CurrentPlatform.toString());
|
||||
return;
|
||||
} else {
|
||||
System.out.printf("Starting Chameleon Vision on platform %s\n", CurrentPlatform.toString());
|
||||
}
|
||||
|
||||
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 {
|
||||
if (CurrentPlatform.equals(Platform.LINUX_ARM64))
|
||||
CameraServerJNI.forceLoad();
|
||||
CameraServerCvJNI.forceLoad();
|
||||
} catch (IOException e) {
|
||||
var errorStr = SettingsManager.getCurrentPlatform().equals(SettingsManager.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 {
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
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() {
|
||||
String[] clearArgs = { "addr", "flush", "dev", networkInterface.name };
|
||||
try {
|
||||
int clearRetCode = shell.execute("ip", clearArgs);
|
||||
int dhcpRetCode = shell.execute("dhclient", networkInterface.name);
|
||||
return clearRetCode == 0 && dhcpRetCode == 0;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setHostname(String newHostname) {
|
||||
String[] setHostnameArgs = { "set-hostname", newHostname };
|
||||
try {
|
||||
var setHostnameRetCode = shell.execute("hostnamectl", setHostnameArgs);
|
||||
return setHostnameRetCode == 0;
|
||||
} catch(Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean setStatic(String ipAddress, String netmask, String gateway, String broadcast) {
|
||||
try {
|
||||
String[] clearArgs = { "addr", "flush", "dev", networkInterface.name };
|
||||
String[] setIPArgs = { "addr", "add", String.format("%s/%s", ipAddress, netmask), "broadcast", broadcast, "dev", networkInterface.name };
|
||||
String[] setGatewayArgs = { "route", "replace", "default", "via", gateway, "dev", networkInterface.name };
|
||||
|
||||
int clearRetCode = shell.execute("ip", clearArgs);
|
||||
int setIPRetCode = shell.execute("ip", setIPArgs);
|
||||
int setGatewayRetCode = shell.execute("ip", setGatewayArgs);
|
||||
|
||||
return clearRetCode == 0 && setIPRetCode == 0 && setGatewayRetCode == 0;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
|
||||
List<java.net.NetworkInterface> netInterfaces;
|
||||
try {
|
||||
netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
|
||||
} catch (SocketException e) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<java.net.NetworkInterface> goodInterfaces = new ArrayList<>();
|
||||
|
||||
for (var netInterface : netInterfaces) {
|
||||
if (netInterface.getDisplayName().contains("lo")) continue;
|
||||
if (!netInterface.isUp()) continue;
|
||||
goodInterfaces.add(netInterface);
|
||||
}
|
||||
return goodInterfaces;
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package com.chameleonvision.network;
|
||||
|
||||
public enum NetworkIPMode {
|
||||
DHCP,
|
||||
STATIC,
|
||||
UNKNOWN
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
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;
|
||||
}
|
||||
|
||||
if (networking == null) {
|
||||
throw new RuntimeException("Failed to detect platform!");
|
||||
}
|
||||
|
||||
List<java.net.NetworkInterface> interfaces = new ArrayList<>();
|
||||
List<NetworkInterface> 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);
|
||||
}
|
||||
}
|
||||
@@ -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<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException;
|
||||
|
||||
}
|
||||
@@ -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<java.net.NetworkInterface> getNetworkInterfaces() throws SocketException {
|
||||
var netInterfaces = Collections.list(java.net.NetworkInterface.getNetworkInterfaces());
|
||||
|
||||
List<java.net.NetworkInterface> 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;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.chameleonvision.vision;
|
||||
package com.chameleonvision.settings;
|
||||
|
||||
public class GeneralSettings {
|
||||
public int team_number = 1577;
|
||||
@@ -1,9 +1,12 @@
|
||||
package com.chameleonvision.settings;
|
||||
|
||||
import java.net.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
|
||||
import com.chameleonvision.util.Utilities;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
public class NetworkSettings {
|
||||
@@ -51,20 +54,26 @@ public class NetworkSettings {
|
||||
}
|
||||
}
|
||||
|
||||
public static byte[] GetTeamNumberIPBytes(int teamNumber) {
|
||||
return new byte[]{(byte) (teamNumber / 100), (byte) (teamNumber % 100)};
|
||||
}
|
||||
|
||||
public static String getAdapter() {
|
||||
try {//TODO fix windows get adapter
|
||||
Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
|
||||
for (NetworkInterface netint : Collections.list(nets)) {
|
||||
Enumeration<InetAddress> ee = netint.getInetAddresses();
|
||||
for (InetAddress addr : Collections.list(ee))
|
||||
if (addr instanceof Inet4Address)
|
||||
if ((addr.getAddress()[0] & 0xFF) == 192 && (addr.getAddress()[1] & 0xFF) == 168) {
|
||||
if (addr instanceof Inet4Address) {
|
||||
var addrString = addr.toString();
|
||||
if ((addr.getAddress()[0] & 0xFF) == 10 && (addr.getAddress()[1] & 0xFF) == 168) {
|
||||
System.out.println("found robot network interface at " + netint.getName() + " ip: " + addr.getHostAddress());
|
||||
return netint.getName();
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (SocketException e) {
|
||||
System.err.println("Socket exception while trying to find current ip");
|
||||
System.err.println("Socket exception while trying to find current IP");
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.chameleonvision.settings;
|
||||
|
||||
import com.chameleonvision.util.ShellExec;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public enum Platform {
|
||||
WINDOWS_64("Windows x64"),
|
||||
LINUX_64("Linux x64"),
|
||||
LINUX_RASPBIAN("Linux Raspbian"),
|
||||
LINUX_ARM64("Linux ARM64"),
|
||||
MACOS_64("Mac OS x64"),
|
||||
UNSUPPORTED("Unsupported Platform");
|
||||
|
||||
public final String value;
|
||||
|
||||
Platform(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
private static final String OS_NAME = System.getProperty("os.name");
|
||||
private static final String OS_ARCH = System.getProperty("os.arch");
|
||||
|
||||
public boolean isWindows() {
|
||||
return this == WINDOWS_64;
|
||||
}
|
||||
|
||||
public boolean isLinux() {
|
||||
return this == LINUX_64 || this == LINUX_RASPBIAN || this == LINUX_ARM64;
|
||||
}
|
||||
|
||||
public boolean isMac() {
|
||||
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;
|
||||
}
|
||||
|
||||
private static boolean isRaspbian() {
|
||||
try (BufferedReader reader = Files.newBufferedReader(Paths.get("/etc/os-release"))) {
|
||||
String value = reader.readLine();
|
||||
return value.contains("Raspbian");
|
||||
} catch (IOException ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static Platform getCurrentPlatform() {
|
||||
if (OS_NAME.contains("Windows")) {
|
||||
if (OS_ARCH.equals("amd64")) return Platform.WINDOWS_64;
|
||||
}
|
||||
|
||||
if (OS_NAME.contains("Linux")) {
|
||||
if (OS_ARCH.equals("amd64")) return Platform.LINUX_64;
|
||||
if (isRaspbian()) return Platform.LINUX_RASPBIAN;
|
||||
if (OS_ARCH.contains("aarch")) return Platform.LINUX_ARM64;
|
||||
}
|
||||
|
||||
if (OS_NAME.contains("Mac")) {
|
||||
if (OS_ARCH.equals("amd64")) return Platform.MACOS_64;
|
||||
}
|
||||
|
||||
System.out.printf("Unknown Platform! OS: %s, Architecture: %s", OS_NAME, OS_ARCH);
|
||||
return Platform.UNSUPPORTED;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
if (this.equals(UNSUPPORTED)) {
|
||||
return String.format("Unknown Platform. OS: %s, Architecture: %s", OS_NAME, OS_ARCH);
|
||||
} else {
|
||||
return this.value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
package com.chameleonvision.settings;
|
||||
|
||||
import com.chameleonvision.FileHelper;
|
||||
import com.chameleonvision.vision.GeneralSettings;
|
||||
import com.chameleonvision.network.NetworkManager;
|
||||
import com.chameleonvision.util.FileHelper;
|
||||
import com.chameleonvision.vision.camera.CameraManager;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
@@ -15,21 +15,22 @@ import java.nio.file.Paths;
|
||||
|
||||
public class SettingsManager {
|
||||
public static final Path SettingsPath = Paths.get(System.getProperty("user.dir"), "settings");
|
||||
public static com.chameleonvision.vision.GeneralSettings GeneralSettings;
|
||||
public static com.chameleonvision.settings.GeneralSettings GeneralSettings;
|
||||
|
||||
private SettingsManager() {}
|
||||
|
||||
public static void initialize(boolean manageNetwork) {
|
||||
public static void initialize() {
|
||||
initGeneralSettings();
|
||||
if (manageNetwork) {
|
||||
NetworkSettings netSettings = new NetworkSettings();
|
||||
netSettings.hostname = GeneralSettings.hostname;
|
||||
netSettings.gateway = GeneralSettings.gateway;
|
||||
netSettings.netmask = GeneralSettings.netmask;
|
||||
netSettings.connectionType = GeneralSettings.connection_type;
|
||||
netSettings.ip = GeneralSettings.ip;
|
||||
netSettings.run();
|
||||
}
|
||||
// if (manageNetwork) {
|
||||
|
||||
// NetworkSettings netSettings = new NetworkSettings();
|
||||
// netSettings.hostname = GeneralSettings.hostname;
|
||||
// netSettings.gateway = GeneralSettings.gateway;
|
||||
// netSettings.netmask = GeneralSettings.netmask;
|
||||
// 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();
|
||||
@@ -38,49 +39,10 @@ public class SettingsManager {
|
||||
}
|
||||
}
|
||||
|
||||
public enum Platform {
|
||||
WINDOWS_64("Windows x64"),
|
||||
LINUX_64("Linux x64"),
|
||||
LINUX_RASPBIAN("Linux Raspbian"),
|
||||
LINUX_AARCH64("Linux ARM 64bit"),
|
||||
MACOS_64("Mac OS x64"),
|
||||
UNSUPPORTED("Unsupported Platform");
|
||||
|
||||
public final String value;
|
||||
|
||||
Platform(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
}
|
||||
|
||||
public static Platform getCurrentPlatform() {
|
||||
var osName = System.getProperty("os.name");
|
||||
var osArch = System.getProperty("os.arch");
|
||||
|
||||
if (osName.contains("Windows")) {
|
||||
if (osArch.equals("amd64")) return Platform.WINDOWS_64;
|
||||
return Platform.UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (osName.contains("Linux")) {
|
||||
if (osArch.equals("amd64")) return Platform.LINUX_64;
|
||||
if (osArch.contains("rasp")) return Platform.LINUX_RASPBIAN;
|
||||
if (osArch.contains("aarch")) return Platform.LINUX_64;
|
||||
return Platform.UNSUPPORTED;
|
||||
}
|
||||
|
||||
if (osName.contains("Mac")) {
|
||||
if (osArch.equals("amd64")) return Platform.MACOS_64;
|
||||
return Platform.UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Platform.UNSUPPORTED;
|
||||
}
|
||||
|
||||
private static void initGeneralSettings() {
|
||||
FileHelper.CheckPath(SettingsPath);
|
||||
try {
|
||||
GeneralSettings = new Gson().fromJson(new FileReader(Paths.get(SettingsPath.toString(), "settings.json").toString()), com.chameleonvision.vision.GeneralSettings.class);
|
||||
GeneralSettings = new Gson().fromJson(new FileReader(Paths.get(SettingsPath.toString(), "settings.json").toString()), com.chameleonvision.settings.GeneralSettings.class);
|
||||
} catch (FileNotFoundException e) {
|
||||
GeneralSettings = new GeneralSettings();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.chameleonvision;
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
@@ -1,15 +1,24 @@
|
||||
package com.chameleonvision.Handler;
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.lang.Math;
|
||||
import org.apache.commons.math3.util.FastMath;
|
||||
|
||||
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);
|
||||
}
|
||||
public static double toSlope(double angle){
|
||||
return FastMath.atan(FastMath.toRadians(angle - 90));
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.chameleonvision;
|
||||
package com.chameleonvision.util;
|
||||
|
||||
public class MemoryManager {
|
||||
|
||||
151
Main/src/main/java/com/chameleonvision/util/ShellExec.java
Normal file
151
Main/src/main/java/com/chameleonvision/util/ShellExec.java
Normal file
@@ -0,0 +1,151 @@
|
||||
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 in current folder, and wait for process to end
|
||||
* @param command command ("c:/some/folder/script.bat" or "some/folder/script.sh")
|
||||
* @param args 0..n command line arguments
|
||||
* @return process exit code
|
||||
*/
|
||||
public int execute(String command, String... args) throws IOException {
|
||||
return execute(command, null, true, args);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.chameleonvision.util;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class Utilities {
|
||||
private Utilities() {}
|
||||
|
||||
@@ -8,4 +11,30 @@ public class Utilities {
|
||||
|
||||
return ip.matches(PATTERN);
|
||||
}
|
||||
|
||||
public static List<Byte> getDigitBytes(int num) {
|
||||
List<Byte> digits = new ArrayList<>();
|
||||
collectDigitBytes(num, digits);
|
||||
return digits;
|
||||
}
|
||||
|
||||
private static void collectDigitBytes(int num, List<Byte> digits) {
|
||||
if (num / 10 > 0) {
|
||||
collectDigitBytes( num / 10, digits);
|
||||
}
|
||||
digits.add((byte) (num % 10));
|
||||
}
|
||||
|
||||
public static List<Integer> getDigits(int num) {
|
||||
List<Integer> digits = new ArrayList<Integer>();
|
||||
collectDigits(num, digits);
|
||||
return digits;
|
||||
}
|
||||
|
||||
private static void collectDigits(int num, List<Integer> digits) {
|
||||
if(num / 10 > 0) {
|
||||
collectDigits(num / 10, digits);
|
||||
}
|
||||
digits.add(num % 10);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
package com.chameleonvision.vision.camera;
|
||||
|
||||
import com.chameleonvision.CameraException;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.settings.Platform;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.web.ServerHandler;
|
||||
import edu.wpi.cscore.*;
|
||||
import edu.wpi.first.cameraserver.CameraServer;
|
||||
import org.opencv.core.Mat;
|
||||
import org.springframework.core.env.Environment;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
@@ -18,7 +16,7 @@ public class Camera {
|
||||
private static final double DEFAULT_FOV = 60.8;
|
||||
private static final int MINIMUM_FPS = 30;
|
||||
private static final int MINIMUM_WIDTH = 320;
|
||||
private static final int MINIMUM_HEIGHT = 240;
|
||||
private static final int MINIMUM_HEIGHT = 200;
|
||||
private static final int MAX_INIT_MS = 1500;
|
||||
|
||||
public final String name;
|
||||
@@ -67,12 +65,11 @@ public class Camera {
|
||||
this.pipelines = pipelines;
|
||||
|
||||
// set up video modes according to minimums
|
||||
if (SettingsManager.getCurrentPlatform() == SettingsManager.Platform.WINDOWS_64 && !UsbCam.isConnected()) {
|
||||
if (Platform.getCurrentPlatform() == Platform.WINDOWS_64 && !UsbCam.isConnected()) {
|
||||
System.out.print("Waiting on camera... ");
|
||||
long initTimeout = System.nanoTime();
|
||||
while(!UsbCam.isConnected())
|
||||
{
|
||||
//TODO add a time sleep, can wait only so long before giving up
|
||||
if (((System.nanoTime() - initTimeout) / 1e6 ) >= MAX_INIT_MS) {
|
||||
break;
|
||||
}
|
||||
@@ -81,7 +78,7 @@ public class Camera {
|
||||
System.out.printf("Camera initialized in %.2fms\n", initTimeMs);
|
||||
}
|
||||
var trueVideoModes = UsbCam.enumerateVideoModes();
|
||||
availableVideoModes = Arrays.stream(trueVideoModes).filter(v -> v.fps >= MINIMUM_FPS && v.width >= MINIMUM_WIDTH && v.height >= MINIMUM_HEIGHT && v.pixelFormat == VideoMode.PixelFormat.kYUYV).toArray(VideoMode[]::new);
|
||||
availableVideoModes = Arrays.stream(trueVideoModes).filter(v -> v.fps >= MINIMUM_FPS && v.width >= MINIMUM_WIDTH && v.height >= MINIMUM_HEIGHT).toArray(VideoMode[]::new);
|
||||
if (availableVideoModes.length == 0) {
|
||||
System.err.println("Camera not supported!");
|
||||
throw new RuntimeException(new CameraException(CameraException.CameraExceptionType.BAD_CAMERA));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package com.chameleonvision;
|
||||
package com.chameleonvision.vision.camera;
|
||||
|
||||
public class CameraException extends Exception {
|
||||
public enum CameraExceptionType {
|
||||
@@ -19,7 +19,7 @@ public class CameraException extends Exception {
|
||||
}
|
||||
}
|
||||
|
||||
public CameraException(CameraExceptionType camExceptionType) {
|
||||
CameraException(CameraExceptionType camExceptionType) {
|
||||
super(camExceptionType.toString());
|
||||
}
|
||||
}
|
||||
@@ -1,9 +1,7 @@
|
||||
package com.chameleonvision.vision.camera;
|
||||
|
||||
import com.chameleonvision.CameraException;
|
||||
import com.chameleonvision.FileHelper;
|
||||
import com.chameleonvision.util.FileHelper;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.GeneralSettings;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.vision.process.VisionProcess;
|
||||
import com.google.gson.Gson;
|
||||
@@ -15,7 +13,6 @@ import org.opencv.videoio.VideoCapture;
|
||||
import java.io.*;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -121,7 +118,7 @@ public class CameraManager {
|
||||
public static List<String> getResolutionList() throws CameraException {
|
||||
if (!SettingsManager.GeneralSettings.curr_camera.equals("")) {
|
||||
return Arrays.stream(CameraManager.getCamera(SettingsManager.GeneralSettings.curr_camera).getAvailableVideoModes())
|
||||
.map(res -> String.format("%s X %s at %s fps", res.width, res.height, res.fps)).collect(Collectors.toList());
|
||||
.map(res -> String.format("%s X %s at %s fps using %s ", res.width, res.height, res.fps, res.pixelFormat.toString())).collect(Collectors.toList());
|
||||
}
|
||||
throw new CameraException(CameraException.CameraExceptionType.NO_CAMERA);
|
||||
}
|
||||
|
||||
@@ -1,93 +1,103 @@
|
||||
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.*;
|
||||
import org.opencv.imgproc.Imgproc;
|
||||
import org.opencv.imgproc.Moments;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@SuppressWarnings("WeakerAccess")
|
||||
public class CVProcess {
|
||||
|
||||
private final CameraValues CamVals;
|
||||
private HashMap<String, Integer> TargetGrouping = new HashMap<>() {{
|
||||
private final CameraValues cameraValues;
|
||||
private HashMap<String, Integer> targetGrouping = new HashMap<>() {{
|
||||
put("Single", 1);
|
||||
put("Dual", 2);
|
||||
put("Triple", 3);
|
||||
put("Quadruple", 4);
|
||||
put("Quintuple", 5);
|
||||
}};
|
||||
private Mat Kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));
|
||||
private Mat kernel = Imgproc.getStructuringElement(Imgproc.MORPH_RECT, new Size(5, 5));
|
||||
private Size blur = new Size(1,1);
|
||||
private Mat hsvImage = new Mat();
|
||||
private List<MatOfPoint> FoundContours = new ArrayList<>();
|
||||
private List<MatOfPoint> foundContours = new ArrayList<>();
|
||||
private Mat binaryMat = new Mat();
|
||||
private List<MatOfPoint> FilteredContours = new ArrayList<>();
|
||||
private Comparator<RotatedRect> SortByCentermostComparator = Comparator.comparingDouble(this::calcDistance);
|
||||
private List<RotatedRect> FinalCountours = new ArrayList<>();
|
||||
private Mat intersectMatA = new Mat();
|
||||
private Mat intersectMatB = new Mat();
|
||||
private List<MatOfPoint> filteredContours = new ArrayList<>();
|
||||
private Comparator<RotatedRect> sortByCentermostComparator = Comparator.comparingDouble(this::calcDistance);
|
||||
private Comparator<MatOfPoint> sortByMomentsX = Comparator.comparingDouble(this::calcMomentsX);
|
||||
private List<RotatedRect> finalCountours = new ArrayList<>();
|
||||
private MatOfPoint2f intersectMatA = new MatOfPoint2f();
|
||||
private MatOfPoint2f intersectMatB = new MatOfPoint2f();
|
||||
|
||||
CVProcess(CameraValues camVals) {
|
||||
CamVals = camVals;
|
||||
CVProcess(CameraValues cameraValues) {
|
||||
this.cameraValues = cameraValues;
|
||||
}
|
||||
|
||||
void HSVThreshold(Mat srcImage, Mat dst, @NotNull Scalar hsvLower, @NotNull Scalar hsvUpper, boolean shouldErode, boolean shouldDilate) {
|
||||
void hsvThreshold(Mat srcImage, Mat dst, @NotNull Scalar hsvLower, @NotNull Scalar hsvUpper, boolean shouldErode, boolean shouldDilate) {
|
||||
Imgproc.cvtColor(srcImage, hsvImage, Imgproc.COLOR_RGB2HSV, 3);
|
||||
Imgproc.blur(hsvImage, hsvImage, blur);
|
||||
Core.inRange(hsvImage, hsvLower, hsvUpper, dst);
|
||||
if (shouldErode) {
|
||||
Imgproc.erode(dst, dst, Kernel);
|
||||
Imgproc.erode(dst, dst, kernel);
|
||||
}
|
||||
if (shouldDilate) {
|
||||
Imgproc.dilate(dst, dst, Kernel);
|
||||
Imgproc.dilate(dst, dst, kernel);
|
||||
}
|
||||
hsvImage.release();
|
||||
}
|
||||
|
||||
List<MatOfPoint> FindContours(Mat src) {
|
||||
List<MatOfPoint> findContours(Mat src) {
|
||||
src.copyTo(binaryMat);
|
||||
FoundContours.clear();
|
||||
Imgproc.findContours(binaryMat, FoundContours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);
|
||||
foundContours.clear();
|
||||
Imgproc.findContours(binaryMat, foundContours, new Mat(), Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_TC89_L1);
|
||||
binaryMat.release();
|
||||
return FoundContours;
|
||||
return foundContours;
|
||||
}
|
||||
|
||||
List<MatOfPoint> FilterContours(List<MatOfPoint> InputContours, List<Integer> area, List<Double> ratio, List<Integer> extent) {
|
||||
for (MatOfPoint Contour : InputContours) {
|
||||
List<MatOfPoint> filterContours(List<MatOfPoint> inputContours, List<Integer> area, List<Double> ratio, List<Integer> extent) {
|
||||
for (MatOfPoint Contour : inputContours) {
|
||||
try {
|
||||
double contourArea = Imgproc.contourArea(Contour);
|
||||
double minArea = (MathHandler.sigmoid(area.get(0)) * CamVals.ImageArea) / 100;
|
||||
double maxArea = (MathHandler.sigmoid(area.get(1)) * CamVals.ImageArea) / 100;
|
||||
if (contourArea <= minArea || contourArea >= maxArea) {
|
||||
double AreaRatio = (contourArea / cameraValues.ImageArea)*100;
|
||||
double minArea = (MathHandler.sigmoid(area.get(0)));
|
||||
double maxArea = (MathHandler.sigmoid(area.get(1)));
|
||||
if (AreaRatio < minArea || AreaRatio > maxArea) {
|
||||
continue;
|
||||
}
|
||||
var rect = Imgproc.minAreaRect(new MatOfPoint2f(Contour.toArray()));
|
||||
|
||||
var targetFullness = contourArea;
|
||||
double minExtent = (double) (extent.get(0) * rect.size.area())/ 100;
|
||||
double minExtent = (double) (extent.get(0) * rect.size.area()) / 100;
|
||||
double maxExtent = (double) (extent.get(1) * rect.size.area()) / 100;
|
||||
if (targetFullness <= minExtent || contourArea >= maxExtent) {
|
||||
continue;
|
||||
}
|
||||
double aspectRatio = rect.size.width / rect.size.height;//TODO i think aspectRatio is inverted
|
||||
Rect bb = Imgproc.boundingRect(Contour);
|
||||
double aspectRatio = (bb.width / bb.height);
|
||||
if (aspectRatio < ratio.get(0) || aspectRatio > ratio.get(1)) {
|
||||
continue;
|
||||
}
|
||||
FilteredContours.add(Contour);
|
||||
filteredContours.add(Contour);
|
||||
} catch (Exception e) {
|
||||
System.err.println("Error while filtering contours");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return FilteredContours;
|
||||
return filteredContours;
|
||||
}
|
||||
|
||||
private double calcDistance(RotatedRect rect) {
|
||||
return FastMath.sqrt(FastMath.pow(CamVals.CenterX - rect.center.x, 2) + FastMath.pow(CamVals.CenterY - rect.center.y, 2));
|
||||
return FastMath.sqrt(FastMath.pow(cameraValues.CenterX - rect.center.x, 2) + FastMath.pow(cameraValues.CenterY - rect.center.y, 2));
|
||||
}
|
||||
|
||||
RotatedRect SortTargetsToOne(List<RotatedRect> inputRects, String sortMode) {
|
||||
private double calcMomentsX(MatOfPoint c){
|
||||
Moments m = Imgproc.moments(c);
|
||||
return (m.get_m10()/m.get_m00());
|
||||
}
|
||||
RotatedRect sortTargetsToOne(List<RotatedRect> inputRects, String sortMode) {
|
||||
switch (sortMode) {
|
||||
case "Largest":
|
||||
return Collections.max(inputRects, Comparator.comparing(rect -> rect.size.area()));
|
||||
@@ -102,22 +112,23 @@ public class CVProcess {
|
||||
case "Rightmost":
|
||||
return Collections.max(inputRects, Comparator.comparing(rect -> rect.center.x));
|
||||
case "Centermost":
|
||||
return Collections.min(inputRects, SortByCentermostComparator);
|
||||
return Collections.min(inputRects, sortByCentermostComparator);
|
||||
default:
|
||||
return inputRects.get(0); // default to whatever the first contour is, but this should never happen
|
||||
}
|
||||
}
|
||||
|
||||
List<RotatedRect> GroupTargets(List<MatOfPoint> InputContours, String IntersectionPoint, String TargetGroup) {
|
||||
FinalCountours.clear();
|
||||
if (!TargetGroup.equals("Single")) {
|
||||
for (var i = 0; i < InputContours.size(); i++) {
|
||||
List<Point> FinalContourList = new ArrayList<>(InputContours.get(i).toList());
|
||||
for (var c = 0; c < (TargetGrouping.get(TargetGroup) - 1); c++) {
|
||||
List<RotatedRect> groupTargets(List<MatOfPoint> inputContours, String intersectionPoint, String targetGroup) {
|
||||
finalCountours.clear();
|
||||
if (!targetGroup.equals("Single")) {
|
||||
inputContours.sort(sortByMomentsX);
|
||||
for (var i = 0; i < inputContours.size(); i++) {
|
||||
List<Point> FinalContourList = new ArrayList<>(inputContours.get(i).toList());
|
||||
for (var c = 0; c < (targetGrouping.get(targetGroup) - 1); c++) {
|
||||
try {
|
||||
MatOfPoint firstContour = InputContours.get(i + c);
|
||||
MatOfPoint secondContour = InputContours.get(i + c + 1);
|
||||
if (IsIntersecting(firstContour, secondContour, IntersectionPoint)) {
|
||||
MatOfPoint firstContour = inputContours.get(i + c);
|
||||
MatOfPoint secondContour = inputContours.get(i + c + 1);
|
||||
if (isIntersecting(firstContour, secondContour, intersectionPoint)) {
|
||||
FinalContourList.addAll(secondContour.toList());
|
||||
}
|
||||
else{
|
||||
@@ -130,7 +141,7 @@ public class CVProcess {
|
||||
contour.fromList(FinalContourList);
|
||||
if (contour.cols() != 0 && contour.rows() != 0) {
|
||||
RotatedRect rect = Imgproc.minAreaRect(contour);
|
||||
FinalCountours.add(rect);
|
||||
finalCountours.add(rect);
|
||||
}
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
FinalContourList.clear();
|
||||
@@ -140,41 +151,37 @@ public class CVProcess {
|
||||
}
|
||||
|
||||
} else {
|
||||
for (MatOfPoint inputContour : InputContours) {
|
||||
for (MatOfPoint inputContour : inputContours) {
|
||||
MatOfPoint2f contour = new MatOfPoint2f();
|
||||
contour.fromArray(inputContour.toArray());
|
||||
if (contour.cols() != 0 && contour.rows() != 0) {
|
||||
RotatedRect rect = Imgproc.minAreaRect(contour);
|
||||
FinalCountours.add(rect);
|
||||
finalCountours.add(rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
return FinalCountours;
|
||||
return finalCountours;
|
||||
}
|
||||
|
||||
private boolean IsIntersecting(MatOfPoint ContourOne, MatOfPoint ContourTwo, String IntersectionPoint) {
|
||||
private boolean isIntersecting(MatOfPoint ContourOne, MatOfPoint ContourTwo, String IntersectionPoint) {
|
||||
if (IntersectionPoint.equals("None")) {
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
Imgproc.fitLine(ContourOne, intersectMatA, Imgproc.CV_DIST_L2, 0, 0.01, 0.01);
|
||||
Imgproc.fitLine(ContourTwo, intersectMatB, Imgproc.CV_DIST_L2, 0, 0.01, 0.01);
|
||||
double vxA = intersectMatA.get(0, 0)[0];
|
||||
double vyA = intersectMatA.get(1, 0)[0];
|
||||
double x0A = intersectMatA.get(2, 0)[0];
|
||||
double y0A = intersectMatA.get(3, 0)[0];
|
||||
double mA = vyA / vxA;
|
||||
double vxB = intersectMatB.get(0, 0)[0];
|
||||
double vyB = intersectMatB.get(1, 0)[0];
|
||||
double x0B = intersectMatB.get(2, 0)[0];
|
||||
double y0B = intersectMatB.get(3, 0)[0];
|
||||
double mB = vyB / vxB;
|
||||
double bA = y0A - (mA*x0A);
|
||||
double bB = y0B - (mB*x0B);
|
||||
intersectMatA.fromArray(ContourOne.toArray());
|
||||
intersectMatB.fromArray(ContourTwo.toArray());
|
||||
RotatedRect a = Imgproc.fitEllipse(intersectMatA);
|
||||
RotatedRect b = Imgproc.fitEllipse(intersectMatB);
|
||||
double mA = MathHandler.toSlope(a.angle);
|
||||
double mB = MathHandler.toSlope(b.angle);
|
||||
double x0A = a.center.x;
|
||||
double y0A = a.center.y;
|
||||
double x0B = b.center.x;
|
||||
double y0B = b.center.y;
|
||||
double intersectionX = ((mA * x0A) - y0A - (mB * x0B) + y0B )/ (mA - mB);
|
||||
double intersectionY = (mA * (intersectionX - x0A)) + y0A;
|
||||
double massX = intersectionX + 1;
|
||||
double massY = intersectionY + ((mA + bA + mB +bB) / 2);
|
||||
double massX = (x0A + x0B) / 2;
|
||||
double massY = (y0A + y0B) / 2;
|
||||
switch (IntersectionPoint) {
|
||||
case "Up": {
|
||||
if (intersectionY < massY) {
|
||||
|
||||
@@ -3,7 +3,6 @@ package com.chameleonvision.vision.process;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.vision.camera.Camera;
|
||||
import com.chameleonvision.web.Server;
|
||||
import com.chameleonvision.web.ServerHandler;
|
||||
import edu.wpi.cscore.VideoException;
|
||||
import edu.wpi.first.networktables.*;
|
||||
@@ -31,14 +30,15 @@ public class VisionProcess implements Runnable {
|
||||
private Pipeline currentPipeline;
|
||||
private CVProcess cvProcess;
|
||||
// pipeline process items
|
||||
private List<MatOfPoint> FoundContours = new ArrayList<>();
|
||||
private List<MatOfPoint> FilteredContours = new ArrayList<>();
|
||||
private List<RotatedRect> GroupedContours = new ArrayList<>();
|
||||
private List<MatOfPoint> foundContours = new ArrayList<>();
|
||||
private List<MatOfPoint> filteredContours = new ArrayList<>();
|
||||
private List<RotatedRect> groupedContours = new ArrayList<>();
|
||||
private Mat cameraInputMat = new Mat();
|
||||
private Mat hsvThreshMat = new Mat();
|
||||
private Mat streamOutputMat = new Mat();
|
||||
private Scalar contourRectColor = new Scalar(255, 0, 0);
|
||||
private long TimeStamp = 0;
|
||||
private Scalar BoxRectColor = new Scalar(0, 0, 233);
|
||||
private long timeStamp = 0;
|
||||
|
||||
public VisionProcess(Camera processCam) {
|
||||
camera = processCam;
|
||||
@@ -53,8 +53,8 @@ public class VisionProcess implements Runnable {
|
||||
ntDistanceEntry = ntTable.getEntry("distance");
|
||||
ntTimeStampEntry = ntTable.getEntry("timestamp");
|
||||
ntValidEntry = ntTable.getEntry("is_valid");
|
||||
ntDriverModeEntry.addListener(this::DriverModeListener, EntryListenerFlags.kUpdate);
|
||||
ntPipelineEntry.addListener(this::PipelineListener, EntryListenerFlags.kUpdate);
|
||||
ntDriverModeEntry.addListener(this::driverModeListener, EntryListenerFlags.kUpdate);
|
||||
ntPipelineEntry.addListener(this::pipelineListener, EntryListenerFlags.kUpdate);
|
||||
ntDriverModeEntry.setBoolean(false);
|
||||
ntPipelineEntry.setNumber(camera.getCurrentPipelineIndex());
|
||||
|
||||
@@ -63,7 +63,7 @@ public class VisionProcess implements Runnable {
|
||||
cameraProcess = new CameraProcess(camera);
|
||||
}
|
||||
|
||||
private void DriverModeListener(EntryNotification entryNotification) {
|
||||
private void driverModeListener(EntryNotification entryNotification) {
|
||||
if (entryNotification.value.getBoolean()) {
|
||||
camera.setExposure(25);
|
||||
camera.setBrightness(15);
|
||||
@@ -74,7 +74,7 @@ public class VisionProcess implements Runnable {
|
||||
}
|
||||
}
|
||||
|
||||
private void PipelineListener(EntryNotification entryNotification) {
|
||||
private void pipelineListener(EntryNotification entryNotification) {
|
||||
var ntPipelineIndex = (int) entryNotification.value.getDouble();
|
||||
if (camera.getPipelines().containsKey(ntPipelineIndex)) {
|
||||
// camera.setEntryNotification.value.getString());
|
||||
@@ -104,20 +104,29 @@ public class VisionProcess implements Runnable {
|
||||
List<MatOfPoint> drawnContour = new ArrayList<>();
|
||||
Point[] vertices = new Point[4];
|
||||
contourRect.points(vertices);
|
||||
drawnContour.add(new MatOfPoint(vertices));
|
||||
MatOfPoint contour = new MatOfPoint(vertices);
|
||||
drawnContour.add(contour);
|
||||
Rect box = Imgproc.boundingRect(contour);
|
||||
Imgproc.drawContours(inputMat, drawnContour, 0, contourRectColor, 3);
|
||||
Imgproc.circle(inputMat, contourRect.center, 3, contourRectColor);
|
||||
Imgproc.rectangle(inputMat,new Point(box.x, box.y), new Point((box.x + box.width),(box.y + box.height)), BoxRectColor,2);
|
||||
}
|
||||
|
||||
private void updateNetworkTables(PipelineResult pipelineResult) {
|
||||
ntValidEntry.setBoolean(pipelineResult.IsValid);
|
||||
if (pipelineResult.IsValid) {
|
||||
ntValidEntry.setBoolean(true);
|
||||
ntYawEntry.setNumber(pipelineResult.Yaw);
|
||||
ntPitchEntry.setNumber(pipelineResult.Pitch);
|
||||
ntDistanceEntry.setNumber(pipelineResult.Area);
|
||||
ntTimeStampEntry.setNumber(timeStamp);
|
||||
NetworkTableInstance.getDefault().flush();
|
||||
} else {
|
||||
ntYawEntry.setNumber(0.0);
|
||||
ntPitchEntry.setNumber(0.0);
|
||||
ntDistanceEntry.setNumber(0.0);
|
||||
ntTimeStampEntry.setNumber(timeStamp);
|
||||
ntValidEntry.setBoolean(false);
|
||||
}
|
||||
ntTimeStampEntry.setNumber(TimeStamp);
|
||||
}
|
||||
|
||||
private PipelineResult runVisionProcess(Mat inputImage, Mat outputImage) {
|
||||
@@ -136,20 +145,20 @@ public class VisionProcess implements Runnable {
|
||||
Scalar hsvLower = new Scalar(currentPipeline.hue.get(0), currentPipeline.saturation.get(0), currentPipeline.value.get(0));
|
||||
Scalar hsvUpper = new Scalar(currentPipeline.hue.get(1), currentPipeline.saturation.get(1), currentPipeline.value.get(1));
|
||||
|
||||
cvProcess.HSVThreshold(inputImage, hsvThreshMat, hsvLower, hsvUpper, currentPipeline.erode, currentPipeline.dilate);
|
||||
cvProcess.hsvThreshold(inputImage, hsvThreshMat, hsvLower, hsvUpper, currentPipeline.erode, currentPipeline.dilate);
|
||||
|
||||
if (currentPipeline.is_binary == 1) {
|
||||
Imgproc.cvtColor(hsvThreshMat, outputImage, Imgproc.COLOR_GRAY2BGR, 3);
|
||||
} else {
|
||||
inputImage.copyTo(outputImage);
|
||||
}
|
||||
FoundContours = cvProcess.FindContours(hsvThreshMat);
|
||||
if (FoundContours.size() > 0) {
|
||||
FilteredContours = cvProcess.FilterContours(FoundContours, currentPipeline.area, currentPipeline.ratio, currentPipeline.extent);
|
||||
if (FilteredContours.size() > 0) {
|
||||
GroupedContours = cvProcess.GroupTargets(FilteredContours, currentPipeline.target_intersection, currentPipeline.target_group);
|
||||
if (GroupedContours.size() > 0) {
|
||||
var finalRect = cvProcess.SortTargetsToOne(GroupedContours, currentPipeline.sort_mode);
|
||||
foundContours = cvProcess.findContours(hsvThreshMat);
|
||||
if (foundContours.size() > 0) {
|
||||
filteredContours = cvProcess.filterContours(foundContours, currentPipeline.area, currentPipeline.ratio, currentPipeline.extent);
|
||||
if (filteredContours.size() > 0) {
|
||||
groupedContours = cvProcess.groupTargets(filteredContours, currentPipeline.target_intersection, currentPipeline.target_group);
|
||||
if (groupedContours.size() > 0) {
|
||||
var finalRect = cvProcess.sortTargetsToOne(groupedContours, currentPipeline.sort_mode);
|
||||
// System.out.printf("Largest Contour Area: %.2f\n", finalRect.size.area());
|
||||
pipelineResult.RawPoint = finalRect;
|
||||
pipelineResult.IsValid = true;
|
||||
@@ -188,9 +197,9 @@ public class VisionProcess implements Runnable {
|
||||
while (!Thread.interrupted()) {
|
||||
startTime = System.nanoTime();
|
||||
if ((startTime - lastFrameEndNanosec) * 1e-6 >= 1000.0 / maxFps + 3) { // 3 additional fps to allow for overhead
|
||||
FoundContours.clear();
|
||||
FilteredContours.clear();
|
||||
GroupedContours.clear();
|
||||
foundContours.clear();
|
||||
filteredContours.clear();
|
||||
groupedContours.clear();
|
||||
|
||||
// update FPS for ui only every 0.5 seconds
|
||||
if ((startTime - fpsLastTime) * 1e-6 >= 500) {
|
||||
@@ -204,7 +213,7 @@ public class VisionProcess implements Runnable {
|
||||
|
||||
currentPipeline = camera.getCurrentPipeline();
|
||||
// start fps counter right before grabbing input frame
|
||||
TimeStamp = cameraProcess.getLatestFrame(cameraInputMat);
|
||||
timeStamp = cameraProcess.getLatestFrame(cameraInputMat);
|
||||
if (cameraInputMat.cols() == 0 && cameraInputMat.rows() == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,8 @@
|
||||
package com.chameleonvision.web;
|
||||
|
||||
import com.chameleonvision.CameraException;
|
||||
import com.chameleonvision.vision.camera.CameraException;
|
||||
import com.chameleonvision.settings.SettingsManager;
|
||||
import com.chameleonvision.vision.Pipeline;
|
||||
import com.chameleonvision.vision.camera.Camera;
|
||||
import com.chameleonvision.vision.camera.CameraManager;
|
||||
import com.google.gson.JsonArray;
|
||||
import edu.wpi.cscore.VideoException;
|
||||
import io.javalin.websocket.WsCloseContext;
|
||||
import io.javalin.websocket.WsConnectContext;
|
||||
|
||||
2
New client/chameleon-client/.browserslistrc
Normal file
2
New client/chameleon-client/.browserslistrc
Normal file
@@ -0,0 +1,2 @@
|
||||
> 1%
|
||||
last 2 versions
|
||||
17
New client/chameleon-client/.eslintrc.js
Normal file
17
New client/chameleon-client/.eslintrc.js
Normal file
@@ -0,0 +1,17 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
node: true
|
||||
},
|
||||
'extends': [
|
||||
'plugin:vue/essential',
|
||||
'eslint:recommended'
|
||||
],
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
},
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
}
|
||||
}
|
||||
21
New client/chameleon-client/.gitignore
vendored
Normal file
21
New client/chameleon-client/.gitignore
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
.DS_Store
|
||||
node_modules
|
||||
/dist
|
||||
|
||||
# local env files
|
||||
.env.local
|
||||
.env.*.local
|
||||
|
||||
# Log files
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
29
New client/chameleon-client/README.md
Normal file
29
New client/chameleon-client/README.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# chameleon-client
|
||||
|
||||
## Project setup
|
||||
```
|
||||
npm install
|
||||
```
|
||||
|
||||
### Compiles and hot-reloads for development
|
||||
```
|
||||
npm run serve
|
||||
```
|
||||
|
||||
### Compiles and minifies for production
|
||||
```
|
||||
npm run build
|
||||
```
|
||||
|
||||
### Run your tests
|
||||
```
|
||||
npm run test
|
||||
```
|
||||
|
||||
### Lints and fixes files
|
||||
```
|
||||
npm run lint
|
||||
```
|
||||
|
||||
### Customize configuration
|
||||
See [Configuration Reference](https://cli.vuejs.org/config/).
|
||||
5
New client/chameleon-client/babel.config.js
Normal file
5
New client/chameleon-client/babel.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
presets: [
|
||||
'@vue/app'
|
||||
]
|
||||
}
|
||||
18481
New client/chameleon-client/package-lock.json
generated
Normal file
18481
New client/chameleon-client/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
33
New client/chameleon-client/package.json
Normal file
33
New client/chameleon-client/package.json
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
"name": "chameleon-client",
|
||||
"version": "0.1.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"serve": "vue-cli-service serve",
|
||||
"build": "vue-cli-service build",
|
||||
"lint": "vue-cli-service lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"core-js": "^2.6.5",
|
||||
"material-design-icons-iconfont": "^5.0.1",
|
||||
"vue": "^2.6.10",
|
||||
"vue-native-websocket": "^2.0.13",
|
||||
"vue-router": "^3.0.3",
|
||||
"vuetify": "^2.0.0",
|
||||
"vuex": "^3.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@mdi/font": "^4.4.95",
|
||||
"@vue/cli-plugin-babel": "^3.11.0",
|
||||
"@vue/cli-plugin-eslint": "^3.11.0",
|
||||
"@vue/cli-service": "^3.11.0",
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.16.0",
|
||||
"eslint-plugin-vue": "^5.0.0",
|
||||
"sass": "^1.17.4",
|
||||
"sass-loader": "^7.1.0",
|
||||
"vue-cli-plugin-vuetify": "^0.6.3",
|
||||
"vue-template-compiler": "^2.6.10",
|
||||
"vuetify-loader": "^1.2.2"
|
||||
}
|
||||
}
|
||||
5
New client/chameleon-client/postcss.config.js
Normal file
5
New client/chameleon-client/postcss.config.js
Normal file
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
autoprefixer: {}
|
||||
}
|
||||
}
|
||||
336
New client/chameleon-client/public/Roboto.css
Normal file
336
New client/chameleon-client/public/Roboto.css
Normal file
@@ -0,0 +1,336 @@
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local('Roboto Thin'), local('Roboto-Thin'), url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxFIzIFKw.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local('Roboto Thin'), local('Roboto-Thin'), url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxMIzIFKw.woff2) format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local('Roboto Thin'), local('Roboto-Thin'), url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxEIzIFKw.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local('Roboto Thin'), local('Roboto-Thin'), url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxLIzIFKw.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local('Roboto Thin'), local('Roboto-Thin'), url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxHIzIFKw.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local('Roboto Thin'), local('Roboto-Thin'), url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxGIzIFKw.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
src: local('Roboto Thin'), local('Roboto-Thin'), url(https://fonts.gstatic.com/s/roboto/v20/KFOkCnqEu92Fr1MmgVxIIzI.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fCRc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fABc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fCBc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fBxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fCxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fChc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: local('Roboto Light'), local('Roboto-Light'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmSU5fBBc4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu72xKOzY.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu5mxKOzY.woff2) format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu7mxKOzY.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4WxKOzY.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu7WxKOzY.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu7GxKOzY.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: local('Roboto'), local('Roboto-Regular'), url(https://fonts.gstatic.com/s/roboto/v20/KFOmCnqEu92Fr1Mu4mxK.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fCRc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fABc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fCBc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fCxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fChc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
src: local('Roboto Medium'), local('Roboto-Medium'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmEU9fBBc4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfCRc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfABc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfCBc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfBxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfCxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfChc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: local('Roboto Bold'), local('Roboto-Bold'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmWUlfBBc4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* cyrillic-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmYUtfCRc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F;
|
||||
}
|
||||
/* cyrillic */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmYUtfABc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116;
|
||||
}
|
||||
/* greek-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmYUtfCBc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+1F00-1FFF;
|
||||
}
|
||||
/* greek */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmYUtfBxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0370-03FF;
|
||||
}
|
||||
/* vietnamese */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmYUtfCxc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0102-0103, U+0110-0111, U+1EA0-1EF9, U+20AB;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmYUtfChc4EsA.woff2) format('woff2');
|
||||
unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: 'Roboto';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
src: local('Roboto Black'), local('Roboto-Black'), url(https://fonts.gstatic.com/s/roboto/v20/KFOlCnqEu92Fr1MmYUtfBBc4.woff2) format('woff2');
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
BIN
New client/chameleon-client/public/favicon.png
Normal file
BIN
New client/chameleon-client/public/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
18
New client/chameleon-client/public/index.html
Normal file
18
New client/chameleon-client/public/index.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<link rel="icon" href="<%= BASE_URL %>favicon.png">
|
||||
<title>Chameleon Vision</title>
|
||||
<link rel="stylesheet" href="<%= BASE_URL %>Roboto.css">
|
||||
</head>
|
||||
<body>
|
||||
<noscript>
|
||||
<strong>We're sorry but Chameleon Vision doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
|
||||
</noscript>
|
||||
<div id="app"></div>
|
||||
<!-- built files will be auto injected -->
|
||||
</body>
|
||||
</html>
|
||||
86
New client/chameleon-client/src/App.vue
Normal file
86
New client/chameleon-client/src/App.vue
Normal file
@@ -0,0 +1,86 @@
|
||||
<template>
|
||||
<v-app>
|
||||
<v-app-bar app clipped-left dark>
|
||||
<img class="imgClass" src="./assets/logo.png">
|
||||
<v-toolbar-title id="title">Chameleon Vision</v-toolbar-title>
|
||||
<div class="flex-grow-1"></div>
|
||||
<v-toolbar-items>
|
||||
<v-tabs dark height="64" slider-color="#4baf62">
|
||||
<v-tab to="Vision">Vision</v-tab>
|
||||
<v-tab to="Settings">Settings</v-tab>
|
||||
</v-tabs>
|
||||
</v-toolbar-items>
|
||||
</v-app-bar>
|
||||
<v-content>
|
||||
<v-container fluid fill-height>
|
||||
<v-layout>
|
||||
<v-flex>
|
||||
<router-view></router-view>
|
||||
</v-flex>
|
||||
</v-layout>
|
||||
</v-container>
|
||||
</v-content>
|
||||
</v-app>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'App',
|
||||
|
||||
components: {
|
||||
|
||||
},
|
||||
methods:{
|
||||
handleMessage(key,val){
|
||||
switch(key){
|
||||
default:{
|
||||
this.$store.commit(key,value);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
data: () => ({
|
||||
|
||||
}),
|
||||
created(){
|
||||
this.$options.sockets.onmessage = (data) =>{
|
||||
try{
|
||||
let message = JSON.parse(data.data);
|
||||
for(let prop in message){
|
||||
if(message.hasOwnProperty(prop)){
|
||||
this.handleMessage(prop,message[prop]);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch{
|
||||
console.error('error: ' + data.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style>
|
||||
html{
|
||||
overflow-y: hidden !important;
|
||||
}
|
||||
.imgClass{
|
||||
width: auto;
|
||||
height: 58px;
|
||||
vertical-align: middle;
|
||||
padding-right: 5px;
|
||||
}
|
||||
.tabClass{
|
||||
color: #4baf62;
|
||||
}
|
||||
.container{
|
||||
background-color: #212121;
|
||||
padding: 0!important;
|
||||
}
|
||||
#title{
|
||||
color:#4baf62;
|
||||
}
|
||||
span{
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
BIN
New client/chameleon-client/src/assets/logo.png
Normal file
BIN
New client/chameleon-client/src/assets/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
31
New client/chameleon-client/src/components/cv-icon.vue
Normal file
31
New client/chameleon-client/src/components/cv-icon.vue
Normal file
@@ -0,0 +1,31 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-tooltip :right="right" :bottom="!right" nudge-right="10">
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-icon @click="handleClick" v-on="on" :color="color">{{text}}</v-icon>
|
||||
</template>
|
||||
<span>{{tooltip}}</span>
|
||||
</v-tooltip>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Icon',
|
||||
props:['color','tooltip','text','right'],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
handleClick(){
|
||||
this.$emit('click');
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
38
New client/chameleon-client/src/components/cv-input.vue
Normal file
38
New client/chameleon-client/src/components/cv-input.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col :cols="2">
|
||||
<span>{{name}}</span>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field dark v-model="localValue" class="mt-0 pt-0" hide-details single-line :disabled="disabled"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Input',
|
||||
props:['name','value','disabled'],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
localValue:{
|
||||
get(){
|
||||
return this.value;
|
||||
},
|
||||
set(value){
|
||||
this.$emit('input',value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col :cols="2">
|
||||
<span>{{name}}</span>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-text-field dark v-model="localValue" class="mt-0 pt-0" hide-details single-line type="number" style="width: 70px"></v-text-field>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'NumberInput',
|
||||
props:['name','value'],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
localValue:{
|
||||
get(){
|
||||
return this.value;
|
||||
},
|
||||
set(value){
|
||||
this.$emit('input',value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
33
New client/chameleon-client/src/components/cv-radio.vue
Normal file
33
New client/chameleon-client/src/components/cv-radio.vue
Normal file
@@ -0,0 +1,33 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-radio-group row v-model="localValue" dark :mandatory="true">
|
||||
<v-radio color="#4baf62" v-for="(name,index) in list" :label="name" v-bind:key="index" :value="index"></v-radio>
|
||||
</v-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Radio',
|
||||
props:['value','list'],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
localValue:{
|
||||
get(){
|
||||
return this.value;
|
||||
},
|
||||
set(value){
|
||||
this.$emit('input',value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col :cols="2">
|
||||
<span>{{name}}</span>
|
||||
</v-col>
|
||||
<v-col :cols="10">
|
||||
<v-range-slider v-model="localValue" :max="max" :min="min" hide-details class="align-center" dark color="#4baf62" :step="step">
|
||||
<template v-slot:prepend>
|
||||
<v-text-field v-model="localValue[0]" class="mt-0 pt-0" hide-details single-line type="number" style="width: 50px" :step="step"></v-text-field>
|
||||
</template>
|
||||
|
||||
<template v-slot:append>
|
||||
<v-text-field v-model="localValue[1]" class="mt-0 pt-0" hide-details single-line type="number" style="width: 50px" :step="step"></v-text-field>
|
||||
</template>
|
||||
</v-range-slider>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'RangeSlider',
|
||||
props:['name','min','max','value','step'],
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
localValue:{
|
||||
get(){
|
||||
return this.value;
|
||||
},
|
||||
set(value){
|
||||
this.$emit('input',value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
45
New client/chameleon-client/src/components/cv-select.vue
Normal file
45
New client/chameleon-client/src/components/cv-select.vue
Normal file
@@ -0,0 +1,45 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col :cols="3">
|
||||
<span>{{name}}</span>
|
||||
</v-col>
|
||||
<v-col :cols="9">
|
||||
<v-select v-model="localValue" :items="indexList" item-text="name" item-value="index" dark color="#4baf62" item-color="green" dense :disabled="disabled"></v-select>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Select',
|
||||
props:['list','name','value','disabled'],
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
localValue:{
|
||||
get(){
|
||||
return this.value;
|
||||
},
|
||||
set(value){
|
||||
this.$emit('input',value)
|
||||
}
|
||||
},
|
||||
indexList(){
|
||||
let list = []
|
||||
for(let i=0 ; i<this.list.length; i++){
|
||||
list.push({
|
||||
name:this.list[i],
|
||||
index:i});
|
||||
}
|
||||
return list;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
</style>
|
||||
44
New client/chameleon-client/src/components/cv-slider.vue
Normal file
44
New client/chameleon-client/src/components/cv-slider.vue
Normal file
@@ -0,0 +1,44 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col :cols="2">
|
||||
<span>{{name}}</span>
|
||||
</v-col>
|
||||
<v-col :cols="10">
|
||||
<v-slider v-model="localValue" dark class="align-center" :max="max" :min="min" hide-details color="#4baf62" :step="step">
|
||||
<template v-slot:append>
|
||||
<v-text-field dark v-model="localValue" class="mt-0 pt-0" hide-details single-line type="number" style="width: 50px" :step="step"></v-text-field>
|
||||
</template>
|
||||
</v-slider>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Slider',
|
||||
props:['min','max','name','value','step'],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
},
|
||||
computed:{
|
||||
localValue:{
|
||||
get(){
|
||||
return this.value;
|
||||
},
|
||||
set(value){
|
||||
this.$emit('input',value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
38
New client/chameleon-client/src/components/cv-switch.vue
Normal file
38
New client/chameleon-client/src/components/cv-switch.vue
Normal file
@@ -0,0 +1,38 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col :cols="2">
|
||||
<span>{{name}}</span>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-switch v-model="localValue" color="#4baf62"></v-switch>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'CVSwitch',
|
||||
props:['name','value'],
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
localValue:{
|
||||
get(){
|
||||
return this.value;
|
||||
},
|
||||
set(value){
|
||||
this.$emit('input',value)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
15
New client/chameleon-client/src/main.js
Normal file
15
New client/chameleon-client/src/main.js
Normal file
@@ -0,0 +1,15 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import router from './router'
|
||||
import store from './store'
|
||||
import vuetify from './plugins/vuetify';
|
||||
import VueNativeSock from 'vue-native-websocket';
|
||||
Vue.config.productionTip = false;
|
||||
// Vue.use(VueNativeSock,'ws://' + location.host + '/websocket',{format: 'json'});
|
||||
Vue.use(VueNativeSock,'ws://'+location.hostname+':8888/websocket',{format:'JSON'});
|
||||
new Vue({
|
||||
router,
|
||||
store,
|
||||
vuetify,
|
||||
render: h => h(App)
|
||||
}).$mount('#app')
|
||||
13
New client/chameleon-client/src/plugins/vuetify.js
Normal file
13
New client/chameleon-client/src/plugins/vuetify.js
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
import '@mdi/font/css/materialdesignicons.css';
|
||||
import 'material-design-icons-iconfont/dist/material-design-icons.css'
|
||||
import Vue from 'vue';
|
||||
import Vuetify from 'vuetify/lib';
|
||||
Vue.use(Vuetify);
|
||||
|
||||
export default new Vuetify({
|
||||
icons: {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
27
New client/chameleon-client/src/router.js
Normal file
27
New client/chameleon-client/src/router.js
Normal file
@@ -0,0 +1,27 @@
|
||||
import Vue from 'vue'
|
||||
import Router from 'vue-router'
|
||||
Vue.use(Router)
|
||||
|
||||
function lazyLoad(view){
|
||||
return() => import(`@/views/${view}.vue`)
|
||||
}
|
||||
export default new Router({
|
||||
mode: 'history',
|
||||
base: process.env.BASE_URL,
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
redirect:'/Vision'
|
||||
},
|
||||
{
|
||||
path: '/Vision',
|
||||
name: 'Vision',
|
||||
component: lazyLoad('Camera')
|
||||
},
|
||||
{
|
||||
path: '/Settings',
|
||||
name: 'Settings',
|
||||
component: lazyLoad('Settings')
|
||||
}
|
||||
]
|
||||
})
|
||||
62
New client/chameleon-client/src/store.js
Normal file
62
New client/chameleon-client/src/store.js
Normal file
@@ -0,0 +1,62 @@
|
||||
import Vue from 'vue'
|
||||
import Vuex from 'vuex'
|
||||
|
||||
Vue.use(Vuex)
|
||||
|
||||
const set = key => (state,val) =>{
|
||||
state[key] = val
|
||||
};
|
||||
|
||||
export default new Vuex.Store({
|
||||
state: {
|
||||
settings:{},
|
||||
pipeline:{
|
||||
Exposure:0,
|
||||
Brightness:0,
|
||||
Orientation:0,
|
||||
Hue:[0,15],
|
||||
Saturation:[0,15],
|
||||
Value:[0,25],
|
||||
Erode:false,
|
||||
Dilate:false,
|
||||
Area:[0,12],
|
||||
Ratio:[0,12],
|
||||
Extent:[0,12],
|
||||
TargetGrouping:0,
|
||||
TargetIntersection:0,
|
||||
SortMode:0
|
||||
},
|
||||
cameraSettings:{},
|
||||
resolutionList:[],
|
||||
port:1181,
|
||||
currentCameraIndex:0,
|
||||
currentPipelineIndex:0,
|
||||
cameraList:[],
|
||||
pipelinelist:[],
|
||||
point:{}
|
||||
},
|
||||
mutations: {
|
||||
settings: set('settings'),
|
||||
pipeline: set('pipeline'),
|
||||
cameraSettings: set('cameraSettings'),
|
||||
resolutionList: set('resolutionList'),
|
||||
port: set('port'),
|
||||
currentCameraIndex: set('currentCameraIndex'),
|
||||
currentPipelineIndex: set('currentPipelineIndex'),
|
||||
cameraList: set('cameraList'),
|
||||
pipelinelist: set('cameraList'),
|
||||
point:set('point')
|
||||
},
|
||||
actions: {
|
||||
settings: state => state.settings,
|
||||
pipeline: state => state.pipeline,
|
||||
cameraSettings: state =>state.cameraSettings,
|
||||
resolutionList: state =>state.resolutionList,
|
||||
port: state =>state.port,
|
||||
currentCameraIndex: state =>state.currentCameraIndex,
|
||||
currentPipelineIndex: state =>state.currentPipelineIndex,
|
||||
cameraList: state =>state.cameraList,
|
||||
pipelinelist: state =>state.pipelinelist,
|
||||
point: state =>state.point,
|
||||
}
|
||||
})
|
||||
192
New client/chameleon-client/src/views/Camera.vue
Normal file
192
New client/chameleon-client/src/views/Camera.vue
Normal file
@@ -0,0 +1,192 @@
|
||||
<template>
|
||||
<div>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col :cols="3" class="colsClass">
|
||||
<div style="padding-left:30px">
|
||||
<CVselect name="Camera" v-model="currentCameraIndex" :list="cameraList"></CVselect>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col :cols="1">
|
||||
<CVicon color="white" text="edit" tooltip="Edit camera name"></CVicon>
|
||||
</v-col>
|
||||
<v-col :cols="3" class="colsClass">
|
||||
<CVselect name="Pipeline" :list="pipelineList" v-model="currentPipelineIndex"></CVselect>
|
||||
</v-col>
|
||||
<v-col :cols="1" class="colsClass">
|
||||
<v-menu offset-y dark auto>
|
||||
<template v-slot:activator="{ on }">
|
||||
<v-icon color="white" @click="test" v-on="on">menu</v-icon>
|
||||
</template>
|
||||
<v-list dense>
|
||||
<v-list-item @click="test">
|
||||
<v-list-item-title>
|
||||
<CVicon color="white" :right="true" text="edit" tooltip="Edit pipeline name"></CVicon>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="test">
|
||||
<v-list-item-title>
|
||||
<CVicon color="white" :right="true" text="add" tooltip="Add new pipeline"></CVicon>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="test">
|
||||
<v-list-item-title>
|
||||
<CVicon color="red darken-2" :right="true" text="delete" tooltip="Delete pipeline"></CVicon>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
<v-list-item @click="test">
|
||||
<v-list-item-title>
|
||||
<CVicon color="white" :right="true" text="mdi-content-copy" tooltip="Duplicate pipeline"></CVicon>
|
||||
</v-list-item-title>
|
||||
</v-list-item>
|
||||
</v-list>
|
||||
</v-menu>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
<v-row>
|
||||
<v-col cols="6" class="colsClass">
|
||||
<v-tabs fixed-tabs background-color="#212121" dark height="50" slider-color="#4baf62" v-model="selectedTab">
|
||||
<v-tab>Input</v-tab>
|
||||
<v-tab>Threshold</v-tab>
|
||||
<v-tab>Contours</v-tab>
|
||||
<v-tab>Output</v-tab>
|
||||
</v-tabs>
|
||||
<div style="padding-left:30px">
|
||||
<component v-model="pipeline" :is="selectedComponent"></component>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col cols="6" class="colsClass">
|
||||
<div>
|
||||
<v-tabs background-color="#212121" dark height="50" slider-color="#4baf62" centered style="padding-bottom:10px">
|
||||
<v-tab>Normal</v-tab>
|
||||
<v-tab>Threshold</v-tab>
|
||||
</v-tabs>
|
||||
<div class="videoClass">
|
||||
<img :src="steamAdress">
|
||||
</div>
|
||||
<h5 id="Point">{{point}}</h5>
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import InputTab from './CameraViewes/InputTab'
|
||||
import ThresholdTab from './CameraViewes/ThresholdTab'
|
||||
import ContoursTab from './CameraViewes/ContoursTab'
|
||||
import OutputTab from './CameraViewes/OutputTab'
|
||||
import CVselect from '../components/cv-select'
|
||||
import CVicon from '../components/cv-icon'
|
||||
export default {
|
||||
name: 'CameraTab',
|
||||
components:{
|
||||
InputTab,
|
||||
ThresholdTab,
|
||||
ContoursTab,
|
||||
OutputTab,
|
||||
CVselect,
|
||||
CVicon
|
||||
},
|
||||
methods:{
|
||||
test(){
|
||||
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedTab:0,
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
selectedComponent(){
|
||||
switch(this.selectedTab){
|
||||
case 0:
|
||||
return "InputTab";
|
||||
case 1:
|
||||
return "ThresholdTab";
|
||||
case 2:
|
||||
return "ContoursTab";
|
||||
case 3:
|
||||
return "OutputTab";
|
||||
}
|
||||
},
|
||||
point:{
|
||||
get:function(){
|
||||
let p = this.$store.state.point.calulated;
|
||||
if(p !== undefined){
|
||||
return ("Pitch: " + parseFloat(p['pitch']).toFixed(2) + " Yaw: " + parseFloat(p['yaw']).toFixed(2) + " FPS: " + parseFloat(p['fps']).toFixed(2))
|
||||
} else{
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
},
|
||||
currentCameraIndex:{
|
||||
get(){
|
||||
return this.$store.state.currentCameraIndex;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('currentCameraIndex',value);
|
||||
}
|
||||
},
|
||||
currentPipelineIndex:{
|
||||
get(){
|
||||
return this.$store.state.currentPipelineIndex;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('currentPipelineIndex',value);
|
||||
}
|
||||
},
|
||||
cameraList:{
|
||||
get(){
|
||||
return this.$store.state.cameraList;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('cameraList',value);
|
||||
}
|
||||
},
|
||||
pipelineList:{
|
||||
get(){
|
||||
return this.$store.state.pipelinelist;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('pipelinelist',value);
|
||||
}
|
||||
},
|
||||
pipeline:{
|
||||
get(){
|
||||
return this.$store.state.pipeline;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('pipeline',value);
|
||||
}
|
||||
},
|
||||
steamAdress: {
|
||||
get: function(){
|
||||
return "http://"+location.hostname + ":"+ this.$store.state.port +"/stream.mjpg";
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.colsClass{
|
||||
padding: 0 !important;
|
||||
|
||||
}
|
||||
.videoClass{
|
||||
text-align: center;
|
||||
}
|
||||
.videoClass img{
|
||||
height: auto !important;
|
||||
width: 75%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#Point{
|
||||
padding-top: 5px;
|
||||
text-align: center;
|
||||
color: #f4f4f4;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,39 @@
|
||||
<template>
|
||||
<div>
|
||||
<CVrangeSlider v-model="value.Area" name="Area" :min="0" :max="100" :step="0.1"></CVrangeSlider>
|
||||
<CVrangeSlider v-model="value.Ratio" name="Ratio (W/H)" :min="0" :max="100" :step="0.1"></CVrangeSlider>
|
||||
<CVrangeSlider v-model="value.Extent" name="Extent" :min="0" :max="100"></CVrangeSlider>
|
||||
<CVselect name="Target Group" :list="['Single','Dual','Triple','Quadruple','Quintuple']" v-model="value.TargetGrouping"></CVselect>
|
||||
<CVselect name="Target Intersection" :list="['None','Up','Down','Left','Right']" :disabled="isDisabled" v-model="value.TargetIntersection"></CVselect>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CVrangeSlider from '../../components/cv-range-slider'
|
||||
import CVselect from '../../components/cv-select'
|
||||
export default {
|
||||
name: 'Contours',
|
||||
props:['value'],
|
||||
components:{
|
||||
CVrangeSlider,
|
||||
CVselect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
isDisabled(){
|
||||
if(this.value.TargetGrouping === 0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<CVslider name="Exposure" v-model="value.Exposure" :min="0" :max="100"></CVslider>
|
||||
<CVslider name="Brightness" v-model="value.Brightness" :min="0" :max="100"></CVslider>
|
||||
<CVselect name="Orientation" v-model="value.Orientation" :list="['Normal','Inverted']"></CVselect>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CVslider from '../../components/cv-slider'
|
||||
import rangeSlider from '../../components/cv-range-slider'
|
||||
import CVselect from '../../components/cv-select'
|
||||
import CVswitch from '../../components/cv-switch'
|
||||
export default {
|
||||
name: 'Input',
|
||||
props:['value'],
|
||||
components:{
|
||||
CVslider,
|
||||
rangeSlider,
|
||||
CVselect,
|
||||
CVswitch
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
t:0,
|
||||
a:1
|
||||
}
|
||||
},
|
||||
methods:{
|
||||
},
|
||||
computed:{}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,37 @@
|
||||
<template>
|
||||
<div>
|
||||
<CVselect name="SortMode" v-model="value.SortMode" :list="['Largest','Smallest','Highest','Lowest','Rightmost','Leftmost','Closest']"></CVselect>
|
||||
<span>Calibrate:</span><v-divider dark color="white"></v-divider>
|
||||
<v-row align="center" justify="start">
|
||||
<v-col style="padding-right:0px" :cols="3">
|
||||
<v-btn small color="#4baf62">Take Point A</v-btn>
|
||||
</v-col>
|
||||
<v-col style="margin-left:0px" :cols="3">
|
||||
<v-btn small color="#4baf62">Take Point B</v-btn>
|
||||
</v-col>
|
||||
<v-col>
|
||||
<v-btn small color="yellow darken-3">Clear All Points</v-btn>
|
||||
</v-col>
|
||||
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CVselect from '../../components/cv-select'
|
||||
export default {
|
||||
name: 'Output',
|
||||
props:['value'],
|
||||
components:{
|
||||
CVselect
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
</style>
|
||||
@@ -0,0 +1,32 @@
|
||||
<template>
|
||||
<div>
|
||||
<CVrangeSlider v-model="value.Hue" name="Hue" :min="0" :max="180"></CVrangeSlider>
|
||||
<CVrangeSlider v-model="value.Saturation" name="Saturation" :min="0" :max="255"></CVrangeSlider>
|
||||
<CVrangeSlider v-model="value.Value" name="Value" :min="0" :max="255"></CVrangeSlider>
|
||||
<CVswitch v-model="value.Erode" name="Erode"></CVswitch>
|
||||
<CVswitch v-model="value.Dilate" name="Dilate"></CVswitch>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CVrangeSlider from '../../components/cv-range-slider'
|
||||
import CVswitch from '../../components/cv-switch'
|
||||
export default {
|
||||
name: 'Threshold',
|
||||
props:['value'],
|
||||
components:{
|
||||
CVrangeSlider,
|
||||
CVswitch
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
67
New client/chameleon-client/src/views/Settings.vue
Normal file
67
New client/chameleon-client/src/views/Settings.vue
Normal file
@@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-row align="center">
|
||||
<v-col cols="6" class="colsClass">
|
||||
<v-tabs fixed-tabs background-color="#212121" dark height="50" slider-color="#4baf62" v-model="selectedTab">
|
||||
<v-tab to="">General</v-tab>
|
||||
<v-tab to="">Cameras</v-tab>
|
||||
</v-tabs>
|
||||
<div style="padding-left:30px">
|
||||
<component :is="selectedComponent"></component>
|
||||
</div>
|
||||
</v-col>
|
||||
<v-col v-show="selectedTab === 1" class="colsClass">
|
||||
<div class="videoClass">
|
||||
<img :src="steamAdress">
|
||||
</div>
|
||||
</v-col>
|
||||
</v-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import General from './SettingsViewes/General'
|
||||
import Cameras from './SettingsViewes/Cameras'
|
||||
|
||||
export default {
|
||||
name: 'SettingsTab',
|
||||
components:{
|
||||
General,
|
||||
Cameras,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
selectedTab:0,
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
selectedComponent(){
|
||||
switch(this.selectedTab){
|
||||
case 0:
|
||||
return "General";
|
||||
case 1:
|
||||
return "Cameras";
|
||||
}
|
||||
},
|
||||
steamAdress: {
|
||||
get: function(){
|
||||
return "http://"+location.hostname + ":"+ this.$store.state.port +"/stream.mjpg";
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.videoClass{
|
||||
text-align: center;
|
||||
}
|
||||
.videoClass img{
|
||||
height: auto !important;
|
||||
width: 75%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
.colsClass{
|
||||
padding: 0 !important;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,62 @@
|
||||
<template>
|
||||
<div>
|
||||
<CVselect name="Camera" :list="cameraList"></CVselect>
|
||||
<CVselect name="Resulotion" v-model="cameraSettings.resolution" :list="resolutionList"></CVselect>
|
||||
<CVselect name="Stream Resulotion" v-model="cameraSettings.streamResolution" :list="['1:1','1:2','1:4','1:6']"></CVselect>
|
||||
<CVnumberinput name="Diagonal FOV" v-model="cameraSettings.fov" ></CVnumberinput>
|
||||
<v-btn style="margin-top:10px" small color="#4baf62">Save Camera Settings</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CVselect from '../../components/cv-select'
|
||||
import CVnumberinput from '../../components/cv-number-input'
|
||||
export default {
|
||||
name: 'CameraSettings',
|
||||
components:{
|
||||
CVselect,
|
||||
CVnumberinput
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
currentCameraIndex:{
|
||||
get(){
|
||||
return this.$store.state.currentCameraIndex;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('currentCameraIndex',value);
|
||||
}
|
||||
},
|
||||
cameraList:{
|
||||
get(){
|
||||
return this.$store.state.cameraList;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('cameraList',value);
|
||||
}
|
||||
},
|
||||
resolutionList:{
|
||||
get(){
|
||||
return this.$store.state.resolutionList;
|
||||
}
|
||||
},
|
||||
cameraSettings:{
|
||||
get(){
|
||||
return this.$store.state.cameraSettings;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('cameraSettings',value);
|
||||
}
|
||||
},
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<div>
|
||||
<CVnumberinput name="Team Number"></CVnumberinput>
|
||||
<CVradio v-model="settings.connectionType" :list="['DHCP','Static']"></CVradio>
|
||||
<v-divider color="white"></v-divider>
|
||||
<CVinput name="IP" v-model="settings.ip" :disabled="isDisabled"></CVinput>
|
||||
<CVinput name="NetMask" v-model="settings.netmask" :disabled="isDisabled"></CVinput>
|
||||
<CVinput name="Gateway" v-model="settings.gateway" :disabled="isDisabled"></CVinput>
|
||||
<v-divider color="white"></v-divider>
|
||||
<CVinput name="Hostname" v-model="settings.hostname"></CVinput>
|
||||
<v-btn style="margin-top:10px" small color="#4baf62">Save General Settings</v-btn>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import CVnumberinput from '../../components/cv-number-input'
|
||||
import CVradio from '../../components/cv-radio'
|
||||
import CVinput from '../../components/cv-input'
|
||||
export default {
|
||||
name: 'General',
|
||||
components:{
|
||||
CVnumberinput,
|
||||
CVradio,
|
||||
CVinput
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
computed:{
|
||||
isDisabled(){
|
||||
if(this.settings.connectionType === 0){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
settings:{
|
||||
get(){
|
||||
return this.$store.state.settings;
|
||||
},
|
||||
set(value){
|
||||
this.$store.commit('settings',value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="" scoped>
|
||||
|
||||
</style>
|
||||
121
chameleon-client/package-lock.json
generated
121
chameleon-client/package-lock.json
generated
@@ -985,7 +985,8 @@
|
||||
"@types/q": {
|
||||
"version": "1.5.2",
|
||||
"resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.2.tgz",
|
||||
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw=="
|
||||
"integrity": "sha512-ce5d3q03Ex0sy4R14722Rmt6MT07Ua+k4FwDfdcToYJcMKNtRVQvJ6JCAPdAmAnbRb6CsX6aYb9m96NGod9uTw==",
|
||||
"dev": true
|
||||
},
|
||||
"@vue/babel-helper-vue-jsx-merge-props": {
|
||||
"version": "1.0.0",
|
||||
@@ -1887,6 +1888,7 @@
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
@@ -1931,6 +1933,7 @@
|
||||
"version": "1.0.10",
|
||||
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
|
||||
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"sprintf-js": "~1.0.2"
|
||||
}
|
||||
@@ -2434,7 +2437,8 @@
|
||||
"boolbase": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24="
|
||||
"integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=",
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
@@ -2744,6 +2748,7 @@
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
@@ -2939,6 +2944,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
|
||||
"integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/q": "^1.5.1",
|
||||
"chalk": "^2.4.1",
|
||||
@@ -2974,6 +2980,7 @@
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
@@ -2981,7 +2988,8 @@
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=",
|
||||
"dev": true
|
||||
},
|
||||
"color-string": {
|
||||
"version": "1.5.3",
|
||||
@@ -3458,6 +3466,7 @@
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/css-select/-/css-select-2.0.2.tgz",
|
||||
"integrity": "sha512-dSpYaDVoWaELjvZ3mS6IKZM/y2PMPa/XYoEfYNZePL4U/XgyxZNroHEHReDx/d+VgXh9VbCTtFqLkFbmeqeaRQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "^1.0.0",
|
||||
"css-what": "^2.1.2",
|
||||
@@ -3468,7 +3477,8 @@
|
||||
"css-select-base-adapter": {
|
||||
"version": "0.1.1",
|
||||
"resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
|
||||
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w=="
|
||||
"integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==",
|
||||
"dev": true
|
||||
},
|
||||
"css-selector-tokenizer": {
|
||||
"version": "0.7.1",
|
||||
@@ -3525,6 +3535,7 @@
|
||||
"version": "1.0.0-alpha.33",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.33.tgz",
|
||||
"integrity": "sha512-SPt57bh5nQnpsTBsx/IXbO14sRc9xXu5MtMAVuo0BaQQmyf0NupNPPSoMaqiAF5tDFafYsTkfeH4Q/HCKXkg4w==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mdn-data": "2.0.4",
|
||||
"source-map": "^0.5.3"
|
||||
@@ -3539,7 +3550,8 @@
|
||||
"css-what": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.3.tgz",
|
||||
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg=="
|
||||
"integrity": "sha512-a+EPoD+uZiNfh+5fxw2nO9QwFa6nJe2Or35fGY6Ipw1R3R4AGz1d1TEZrCegvw2YTmZ0jXirGYlzxxpYSHwpEg==",
|
||||
"dev": true
|
||||
},
|
||||
"cssesc": {
|
||||
"version": "2.0.0",
|
||||
@@ -3628,6 +3640,7 @@
|
||||
"version": "3.5.1",
|
||||
"resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz",
|
||||
"integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"css-tree": "1.0.0-alpha.29"
|
||||
},
|
||||
@@ -3636,6 +3649,7 @@
|
||||
"version": "1.0.0-alpha.29",
|
||||
"resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz",
|
||||
"integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"mdn-data": "~1.1.0",
|
||||
"source-map": "^0.5.3"
|
||||
@@ -3644,7 +3658,8 @@
|
||||
"mdn-data": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz",
|
||||
"integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA=="
|
||||
"integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3740,6 +3755,7 @@
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
|
||||
"integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"object-keys": "^1.0.12"
|
||||
}
|
||||
@@ -3925,6 +3941,7 @@
|
||||
"version": "0.2.1",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.1.tgz",
|
||||
"integrity": "sha512-sK3ujri04WyjwQXVoK4PU3y8ula1stq10GJZpqHIUgoGZdsGzAGu65BnU3d08aTVSvO7mGPZUc0wTEDL+qGE0Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"entities": "^2.0.0"
|
||||
@@ -3933,7 +3950,8 @@
|
||||
"domelementtype": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
|
||||
"integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ=="
|
||||
"integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3945,7 +3963,8 @@
|
||||
"domelementtype": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
|
||||
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w=="
|
||||
"integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
|
||||
"dev": true
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "2.4.2",
|
||||
@@ -3960,6 +3979,7 @@
|
||||
"version": "1.7.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
|
||||
"integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dom-serializer": "0",
|
||||
"domelementtype": "1"
|
||||
@@ -4097,7 +4117,8 @@
|
||||
"entities": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
|
||||
"integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw=="
|
||||
"integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==",
|
||||
"dev": true
|
||||
},
|
||||
"errno": {
|
||||
"version": "0.1.7",
|
||||
@@ -4129,6 +4150,7 @@
|
||||
"version": "1.13.0",
|
||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.13.0.tgz",
|
||||
"integrity": "sha512-vDZfg/ykNxQVwup/8E1BZhVzFfBxs9NqMzGcvIJrqg5k2/5Za2bWo40dK2J1pgLngZ7c+Shh8lwYtLGyrwPutg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"es-to-primitive": "^1.2.0",
|
||||
"function-bind": "^1.1.1",
|
||||
@@ -4142,6 +4164,7 @@
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.0.tgz",
|
||||
"integrity": "sha512-qZryBOJjV//LaxLTV6UC//WewneB3LcXOL9NP++ozKVXsIIIpm/2c13UDiD9Jp2eThsecw9m3jPqDwTyobcdbg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-callable": "^1.1.4",
|
||||
"is-date-object": "^1.0.1",
|
||||
@@ -4157,7 +4180,8 @@
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||
"dev": true
|
||||
},
|
||||
"eslint": {
|
||||
"version": "5.16.0",
|
||||
@@ -4634,7 +4658,8 @@
|
||||
"esprima": {
|
||||
"version": "4.0.1",
|
||||
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A=="
|
||||
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
|
||||
"dev": true
|
||||
},
|
||||
"esquery": {
|
||||
"version": "1.0.1",
|
||||
@@ -5590,10 +5615,10 @@
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"deep-extend": "0.6.0",
|
||||
"ini": "1.3.5",
|
||||
"minimist": "1.2.0",
|
||||
"strip-json-comments": "2.0.1"
|
||||
"deep-extend": "^0.6.0",
|
||||
"ini": "~1.3.0",
|
||||
"minimist": "^1.2.0",
|
||||
"strip-json-comments": "~2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"minimist": {
|
||||
@@ -5728,7 +5753,8 @@
|
||||
"function-bind": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz",
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A=="
|
||||
"integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==",
|
||||
"dev": true
|
||||
},
|
||||
"functional-red-black-tree": {
|
||||
"version": "1.0.1",
|
||||
@@ -5888,6 +5914,7 @@
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
|
||||
"integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"function-bind": "^1.1.1"
|
||||
}
|
||||
@@ -5912,12 +5939,14 @@
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||
"dev": true
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.0.tgz",
|
||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q="
|
||||
"integrity": "sha1-uhqPGvKg/DllD1yFA2dwQSIGO0Q=",
|
||||
"dev": true
|
||||
},
|
||||
"has-value": {
|
||||
"version": "1.0.0",
|
||||
@@ -6528,7 +6557,8 @@
|
||||
"is-callable": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.4.tgz",
|
||||
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA=="
|
||||
"integrity": "sha512-r5p9sxJjYnArLjObpjA4xu5EKI3CuKHkJXMhT7kwbpUyIFD1n5PMAsoPvWnvtZiNz7LjkYDRZhd7FlI0eMijEA==",
|
||||
"dev": true
|
||||
},
|
||||
"is-ci": {
|
||||
"version": "1.2.1",
|
||||
@@ -6574,7 +6604,8 @@
|
||||
"is-date-object": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz",
|
||||
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY="
|
||||
"integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=",
|
||||
"dev": true
|
||||
},
|
||||
"is-descriptor": {
|
||||
"version": "0.1.6",
|
||||
@@ -6695,6 +6726,7 @@
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz",
|
||||
"integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has": "^1.0.1"
|
||||
}
|
||||
@@ -6724,6 +6756,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.2.tgz",
|
||||
"integrity": "sha512-HS8bZ9ox60yCJLH9snBpIwv9pYUAkcuLhSA1oero1UB5y9aiQpRA8y2ex945AOtCZL1lJDeIk3G5LthswI46Lw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-symbols": "^1.0.0"
|
||||
}
|
||||
@@ -6830,6 +6863,7 @@
|
||||
"version": "3.13.1",
|
||||
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.13.1.tgz",
|
||||
"integrity": "sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"argparse": "^1.0.7",
|
||||
"esprima": "^4.0.0"
|
||||
@@ -7257,7 +7291,8 @@
|
||||
"mdn-data": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
|
||||
"integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA=="
|
||||
"integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==",
|
||||
"dev": true
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
@@ -7708,6 +7743,7 @@
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
|
||||
"integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"boolbase": "~1.0.0"
|
||||
}
|
||||
@@ -7772,7 +7808,8 @@
|
||||
"object-keys": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="
|
||||
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
|
||||
"dev": true
|
||||
},
|
||||
"object-visit": {
|
||||
"version": "1.0.1",
|
||||
@@ -7798,6 +7835,7 @@
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz",
|
||||
"integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"es-abstract": "^1.5.1"
|
||||
@@ -7815,6 +7853,7 @@
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.0.tgz",
|
||||
"integrity": "sha512-8mf0nKLAoFX6VlNVdhGj31SVYpaNFtUnuoOXWyFEstsWRgU837AK+JYM0iAxwkSzGRbwn8cbFmgbyxj1j4VbXg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.3",
|
||||
"es-abstract": "^1.12.0",
|
||||
@@ -8941,7 +8980,8 @@
|
||||
"q": {
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
|
||||
"integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc="
|
||||
"integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=",
|
||||
"dev": true
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.5.2",
|
||||
@@ -9458,7 +9498,8 @@
|
||||
"sax": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
|
||||
"integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==",
|
||||
"dev": true
|
||||
},
|
||||
"schema-utils": {
|
||||
"version": "0.4.7",
|
||||
@@ -10017,7 +10058,8 @@
|
||||
"sprintf-js": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw="
|
||||
"integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=",
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.1",
|
||||
@@ -10047,7 +10089,8 @@
|
||||
"stable": {
|
||||
"version": "0.1.8",
|
||||
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
|
||||
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w=="
|
||||
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
|
||||
"dev": true
|
||||
},
|
||||
"stackframe": {
|
||||
"version": "1.0.4",
|
||||
@@ -10239,6 +10282,7 @@
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
@@ -10249,18 +10293,11 @@
|
||||
"integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q=",
|
||||
"dev": true
|
||||
},
|
||||
"svg-to-vue": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/svg-to-vue/-/svg-to-vue-0.4.0.tgz",
|
||||
"integrity": "sha512-g/ZHtEFf4QDsDtTk9tuYX/MJ2HESTUBMTkuLoffQGQ3xMtlmD9Ec4YyTgmMkP1P8QJtWWu2FiGdOnlKaXc/X/Q==",
|
||||
"requires": {
|
||||
"svgo": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"svgo": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.0.tgz",
|
||||
"integrity": "sha512-MLfUA6O+qauLDbym+mMZgtXCGRfIxyQoeH6IKVcFslyODEe/ElJNwr0FohQ3xG4C6HK6bk3KYPPXwHVJk3V5NQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.1",
|
||||
"coa": "^2.0.2",
|
||||
@@ -10736,7 +10773,8 @@
|
||||
"unquote": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
|
||||
"integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ="
|
||||
"integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=",
|
||||
"dev": true
|
||||
},
|
||||
"unset-value": {
|
||||
"version": "1.0.0",
|
||||
@@ -10877,6 +10915,7 @@
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
|
||||
"integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"define-properties": "^1.1.2",
|
||||
"object.getownpropertydescriptors": "^2.0.3"
|
||||
@@ -13660,8 +13699,7 @@
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.2.4",
|
||||
@@ -17840,15 +17878,6 @@
|
||||
"loader-utils": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"vue-svg-loader": {
|
||||
"version": "0.12.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-svg-loader/-/vue-svg-loader-0.12.0.tgz",
|
||||
"integrity": "sha512-pg8H6iKCj+DAC7FZuxdfGJMHiFpJPv/YyoN1M7Iqlf+Hu4eU6Q/W/sEFx978syQA+aOx0NXrp+uQUAajqQvXbQ==",
|
||||
"requires": {
|
||||
"loader-utils": "^1.2.3",
|
||||
"svg-to-vue": "^0.4.0"
|
||||
}
|
||||
},
|
||||
"vue-template-compiler": {
|
||||
"version": "2.6.10",
|
||||
"resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.10.tgz",
|
||||
|
||||
0
chameleon-client/src/assets/logo.png
Executable file → Normal file
0
chameleon-client/src/assets/logo.png
Executable file → Normal file
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
@@ -1,17 +1,17 @@
|
||||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Vue from 'vue';
|
||||
import App from './App.vue';
|
||||
import VueRouter from 'vue-router';
|
||||
import iView from 'iview';
|
||||
import router from "./routes";
|
||||
import '../theme/index.less';
|
||||
import VueNativeSock from 'vue-native-websocket';
|
||||
import locale from 'iview/dist/locale/en-US';
|
||||
import {store} from './store'
|
||||
import {store} from './store';
|
||||
|
||||
Vue.use(VueRouter);
|
||||
Vue.use(iView , { locale });
|
||||
Vue.use(VueNativeSock,'ws://'+location.hostname+':8888/websocket',{format:'JSON'});
|
||||
Vue.config.productionTip = false
|
||||
Vue.config.productionTip = false;
|
||||
|
||||
new Vue({
|
||||
router,
|
||||
|
||||
Reference in New Issue
Block a user