diff --git a/build.gradle b/build.gradle
index 907a2097d..978b93278 100644
--- a/build.gradle
+++ b/build.gradle
@@ -41,5 +41,6 @@ spotless {
target "**/*.java"
licenseHeaderFile "$rootDir/LicenseHeader.txt"
targetExclude("photon-core/src/main/java/org/photonvision/PhotonVersion.java")
+ targetExclude("photon-lib/src/main/java/org/photonvision/PhotonVersion.java")
}
}
diff --git a/photon-core/build.gradle b/photon-core/build.gradle
index cf257268b..520f932d7 100644
--- a/photon-core/build.gradle
+++ b/photon-core/build.gradle
@@ -1,5 +1,4 @@
-import java.time.LocalDateTime
-import java.time.format.DateTimeFormatter
+import java.nio.file.Path
apply from: "${rootDir}/shared/common.gradle"
@@ -30,23 +29,8 @@ dependencies {
}
task writeCurrentVersionJava {
- String date = DateTimeFormatter.ofPattern("yyyy-M-d hh:mm:ss").format(LocalDateTime.now())
- File versionFile = new File(java.nio.file.Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java")
- .toAbsolutePath().toString())
- versionFile.delete()
- versionFile << "package org.photonvision;\n" +
- "\n" +
- "/*\n" +
- " * Autogenerated file! Do not manually edit this file. This version is regenerated\n" +
- " * any time the publish task is run, or when this file is deleted.\n" +
- " */\n" +
- "\n" +
- "@SuppressWarnings(\"ALL\")\n" +
- "public final class PhotonVersion {\n" +
- " public static final String versionString = \"${versionString}\";\n" +
- " public static final String buildDate = \"${date}\";\n" +
- " public static final boolean isRelease = !versionString.startsWith(\"dev\");\n" +
- "}"
+ writePhotonVersionFile(Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
+ versionString)
}
build.dependsOn writeCurrentVersionJava
diff --git a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java
index 6da54502f..fa6b48ab2 100644
--- a/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java
+++ b/photon-core/src/main/java/org/photonvision/common/dataflow/networktables/NetworkTablesManager.java
@@ -21,6 +21,7 @@ import edu.wpi.first.networktables.LogMessage;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableInstance;
import java.util.function.Consumer;
+import org.photonvision.PhotonVersion;
import org.photonvision.common.configuration.NetworkConfig;
import org.photonvision.common.logging.LogGroup;
import org.photonvision.common.logging.Logger;
@@ -62,16 +63,23 @@ public class NetworkTablesManager {
hasReportedConnectionFailure = false;
lastConnectMessageMillis = System.currentTimeMillis();
ScriptManager.queueEvent(ScriptEventType.kNTConnected);
+ getInstance().broadcastVersion();
}
}
}
+ private void broadcastVersion() {
+ kRootTable.getEntry("version").setString(PhotonVersion.versionString);
+ kRootTable.getEntry("buildDate").setString(PhotonVersion.buildDate);
+ }
+
public void setConfig(NetworkConfig config) {
if (config.runNTServer) {
setServerMode();
} else {
setClientMode(config.teamNumber);
}
+ broadcastVersion();
}
private void setClientMode(int teamNumber) {
@@ -86,11 +94,13 @@ public class NetworkTablesManager {
logger.error(
"[NetworkTablesManager] Could not connect to the robot! Will retry in the background...");
}
+ broadcastVersion();
}
private void setServerMode() {
logger.info("Starting NT Server");
ntInstance.stopClient();
ntInstance.startServer();
+ broadcastVersion();
}
}
diff --git a/photon-lib/build.gradle b/photon-lib/build.gradle
index b8a4f3c3e..33f9441ea 100644
--- a/photon-lib/build.gradle
+++ b/photon-lib/build.gradle
@@ -1,14 +1,19 @@
+import java.nio.file.Path
+
apply plugin: "cpp"
apply plugin: "java"
apply plugin: "google-test-test-suite"
apply plugin: "edu.wpi.first.NativeUtils"
apply from: "${rootDir}/shared/config.gradle"
+apply from: "${rootDir}/versioningHelper.gradle"
test {
useJUnitPlatform()
}
+def jniPlatforms = ['linuxaarch64bionic', 'linuxraspbian', 'linuxx86-64', 'osxx86-64', 'windowsx86-64']
+
// Apply Java configuration
dependencies {
compile project(":photon-targeting")
@@ -19,16 +24,15 @@ dependencies {
implementation "edu.wpi.first.wpilibj:wpilibj-java:$wpilibVersion"
implementation "edu.wpi.first.wpiutil:wpiutil-java:$wpilibVersion"
implementation "edu.wpi.first.wpimath:wpimath-java:$wpilibVersion"
- implementation "edu.wpi.first.hal:hal-java:$wpilibVersion"
implementation "edu.wpi.first.thirdparty.frc2020.opencv:opencv-java:3.4.7-2"
// NTCore
implementation "edu.wpi.first.ntcore:ntcore-java:$wpilibVersion"
- compile "edu.wpi.first.ntcore:ntcore-jni:$wpilibVersion:linuxaarch64bionic"
- compile "edu.wpi.first.ntcore:ntcore-jni:$wpilibVersion:linuxraspbian"
- compile "edu.wpi.first.ntcore:ntcore-jni:$wpilibVersion:linuxx86-64"
- compile "edu.wpi.first.ntcore:ntcore-jni:$wpilibVersion:osxx86-64"
- compile "edu.wpi.first.ntcore:ntcore-jni:$wpilibVersion:windowsx86-64"
+ jniPlatforms.each { compile "edu.wpi.first.ntcore:ntcore-jni:$wpilibVersion:$it" }
+
+ // HAL
+ implementation "edu.wpi.first.hal:hal-java:$wpilibVersion"
+ jniPlatforms.each {compile "edu.wpi.first.hal:hal-jni:$wpilibVersion:$it"}
// Junit
testImplementation("org.junit.jupiter:junit-jupiter-api:5.6.2")
@@ -102,4 +106,12 @@ task generateVendorJson() {
build.dependsOn generateVendorJson
+
+task writeCurrentVersionJava {
+ writePhotonVersionFile(Path.of("$projectDir", "src", "main", "java", "org", "photonvision", "PhotonVersion.java"),
+ versionString)
+}
+
+build.dependsOn writeCurrentVersionJava
+
apply from: "publish.gradle"
diff --git a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java
index 4cf88578a..d3a7914df 100644
--- a/photon-lib/src/main/java/org/photonvision/PhotonCamera.java
+++ b/photon-lib/src/main/java/org/photonvision/PhotonCamera.java
@@ -20,6 +20,7 @@ package org.photonvision;
import edu.wpi.first.networktables.NetworkTable;
import edu.wpi.first.networktables.NetworkTableEntry;
import edu.wpi.first.networktables.NetworkTableInstance;
+import edu.wpi.first.wpilibj.DriverStation;
import org.photonvision.common.dataflow.structures.Packet;
import org.photonvision.common.hardware.VisionLEDMode;
import org.photonvision.targeting.PhotonPipelineResult;
@@ -32,8 +33,10 @@ public class PhotonCamera {
final NetworkTableEntry outputSaveImgEntry;
final NetworkTableEntry pipelineIndexEntry;
final NetworkTableEntry ledModeEntry;
+ final NetworkTableEntry versionEntry;
final NetworkTable mainTable = NetworkTableInstance.getDefault().getTable("photonvision");
+ private final String path;
boolean driverMode;
int pipelineIndex;
@@ -47,12 +50,14 @@ public class PhotonCamera {
* @param rootTable The root table that the camera is broadcasting information over.
*/
public PhotonCamera(NetworkTable rootTable) {
+ path = rootTable.getPath();
rawBytesEntry = rootTable.getEntry("rawBytes");
driverModeEntry = rootTable.getEntry("driverMode");
inputSaveImgEntry = rootTable.getEntry("inputSaveImgCmd");
outputSaveImgEntry = rootTable.getEntry("outputSaveImgCmd");
pipelineIndexEntry = rootTable.getEntry("pipelineIndex");
ledModeEntry = mainTable.getEntry("ledMode");
+ versionEntry = mainTable.getEntry("version");
driverMode = driverModeEntry.getBoolean(false);
pipelineIndex = pipelineIndexEntry.getNumber(0).intValue();
@@ -74,6 +79,8 @@ public class PhotonCamera {
* @return The latest pipeline result.
*/
public PhotonPipelineResult getLatestResult() {
+ verifyVersion();
+
// Clear the packet.
packet.clear();
@@ -199,4 +206,20 @@ public class PhotonCamera {
public boolean hasTargets() {
return getLatestResult().hasTargets();
}
+
+ private void verifyVersion() {
+ String versionString = versionEntry.getString("");
+ if (versionString.equals("")) {
+ DriverStation.reportError(
+ "PhotonVision coprocessor at path " + path + " not found on NetworkTables!", true);
+ } else if (!PhotonVersion.versionMatches(versionString)) {
+ DriverStation.reportError(
+ "Photon version "
+ + PhotonVersion.versionString
+ + " does not match coprocessor version "
+ + versionString
+ + "!",
+ true);
+ }
+ }
}
diff --git a/photon-lib/src/test/java/org/photonvision/PhotonVersionTest.java b/photon-lib/src/test/java/org/photonvision/PhotonVersionTest.java
new file mode 100644
index 000000000..86e750f30
--- /dev/null
+++ b/photon-lib/src/test/java/org/photonvision/PhotonVersionTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+
+public class PhotonVersionTest {
+ public static final boolean versionMatches(String versionString, String other) {
+ String c = versionString;
+ Pattern p = Pattern.compile("v[0-9]+.[0-9]+.[0-9]+");
+ Matcher m = p.matcher(c);
+ if (m.find()) {
+ c = m.group(0);
+ } else {
+ return false;
+ }
+ m = p.matcher(other);
+ if (m.find()) {
+ other = m.group(0);
+ } else {
+ return false;
+ }
+ return c.equals(other);
+ }
+
+ @Test
+ public void testVersion() {
+ Assertions.assertTrue(versionMatches("v2021.1.6", "v2021.1.6"));
+ Assertions.assertTrue(versionMatches("dev-v2021.1.6", "v2021.1.6"));
+ Assertions.assertTrue(versionMatches("dev-v2021.1.6-5-gca49ea50", "v2021.1.6"));
+ Assertions.assertFalse(versionMatches("", "v2021.1.6"));
+ Assertions.assertFalse(versionMatches("v2021.1.6", ""));
+ }
+}
diff --git a/shared/PhotonVersion.java.in b/shared/PhotonVersion.java.in
new file mode 100644
index 000000000..3805b1393
--- /dev/null
+++ b/shared/PhotonVersion.java.in
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) Photon Vision.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+package org.photonvision;
+
+/*
+* Autogenerated file! Do not manually edit this file. This version is regenerated
+* any time the publish task is run, or when this file is deleted.
+*/
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+@SuppressWarnings("ALL")
+public final class PhotonVersion {
+ public static final String versionString = "${version}";
+ public static final String buildDate = "${date}";
+ public static final boolean isRelease = !versionString.startsWith("dev");
+
+ public static final boolean versionMatches(String other) {
+ String c = versionString;
+ Pattern p = Pattern.compile("v[0-9]+.[0-9]+.[0-9]+");
+ Matcher m = p.matcher(c);
+ if (m.find()) {
+ c = m.group(0);
+ } else {
+ return false;
+ }
+ m = p.matcher(other);
+ if (m.find()) {
+ other = m.group(0);
+ } else {
+ return false;
+ }
+ return c.equals(other);
+ }
+}
diff --git a/shared/common.gradle b/shared/common.gradle
index 2e1d176e4..bc395c2f9 100644
--- a/shared/common.gradle
+++ b/shared/common.gradle
@@ -1,3 +1,7 @@
+import java.nio.file.Path
+import java.time.LocalDateTime
+import java.time.format.DateTimeFormatter
+
// Plugins
apply plugin: "jacoco"
apply plugin: "java"
diff --git a/versioningHelper.gradle b/versioningHelper.gradle
index 957220bee..7fd635c9e 100644
--- a/versioningHelper.gradle
+++ b/versioningHelper.gradle
@@ -1,6 +1,6 @@
+import java.nio.file.Path
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
-import java.nio.file.Path
gradle.allprojects {
ext.getCurrentVersion = { ->
@@ -12,18 +12,28 @@ gradle.allprojects {
standardOutput = stdout
}
tagIsh = stdout.toString().trim().toLowerCase()
- } catch(Exception e) {
+ } catch (Exception e) {
tagIsh = "dev-Unknown"
}
// Dev tags: v2021.1.6-3-gf922466d
// We're specifically looking to capture the middle -3-
boolean isDev = tagIsh.matches(".*-[0-9]*-g[0-9a-f]*")
- if(isDev && !tagIsh.startsWith("dev-")) tagIsh = "dev-" + tagIsh
+ if (isDev && !tagIsh.startsWith("dev-")) tagIsh = "dev-" + tagIsh
println("Picked up version: " + tagIsh)
return tagIsh
}
- if(!ext.has("versionString")) {
+ if (!ext.has("versionString")) {
ext.versionString = getCurrentVersion()
}
+
+ ext.writePhotonVersionFile = { Path path, String version ->
+ println("Writing " + version + " to " + path.toAbsolutePath().toString())
+ String date = DateTimeFormatter.ofPattern("yyyy-M-d hh:mm:ss").format(LocalDateTime.now())
+ File versionFileOut = new File(path.toAbsolutePath().toString())
+ versionFileOut.delete()
+ def versionFileIn = file("${rootDir}/shared/PhotonVersion.java.in")
+ def read = versionFileIn.text.replace('${version}', version).replace('${date}', date)
+ versionFileOut.write(read)
+ }
}