From ac23f92451490c1cea3e0133ecb91ae92ef4db63 Mon Sep 17 00:00:00 2001 From: Ryan Blue Date: Sat, 2 Sep 2023 02:34:18 -0400 Subject: [PATCH] [hal] Add GetTeamNumber (#5596) --- .../main/java/edu/wpi/first/hal/HALUtil.java | 8 +++ .../first/hal/simulation/RoboRioDataJNI.java | 9 ++++ hal/src/main/native/athena/HAL.cpp | 32 ++++++++++++ .../native/athena/mockdata/RoboRioData.cpp | 1 + hal/src/main/native/cpp/jni/HALUtil.cpp | 12 +++++ .../cpp/jni/simulation/RoboRioDataJNI.cpp | 50 +++++++++++++++++++ hal/src/main/native/include/hal/HALBase.h | 6 +++ .../include/hal/simulation/RoboRioData.h | 7 +++ hal/src/main/native/sim/HAL.cpp | 4 ++ .../main/native/sim/mockdata/RoboRioData.cpp | 2 + .../native/sim/mockdata/RoboRioDataInternal.h | 2 + .../src/main/native/cpp/RobotController.cpp | 4 ++ .../main/native/cpp/simulation/RoboRioSim.cpp | 17 +++++++ .../main/native/include/frc/RobotController.h | 7 +++ .../include/frc/simulation/RoboRioSim.h | 25 ++++++++++ .../native/cpp/simulation/RoboRioSimTest.cpp | 15 ++++++ .../wpi/first/wpilibj/RobotController.java | 9 ++++ .../first/wpilibj/simulation/RoboRioSim.java | 32 ++++++++++++ .../wpilibj/simulation/RoboRioSimTest.java | 17 +++++++ 19 files changed, 259 insertions(+) diff --git a/hal/src/main/java/edu/wpi/first/hal/HALUtil.java b/hal/src/main/java/edu/wpi/first/hal/HALUtil.java index e9e572e03d..11d9b4d74a 100644 --- a/hal/src/main/java/edu/wpi/first/hal/HALUtil.java +++ b/hal/src/main/java/edu/wpi/first/hal/HALUtil.java @@ -61,6 +61,14 @@ public final class HALUtil extends JNIWrapper { */ public static native String getComments(); + /** + * Returns the team number configured for the robot controller. + * + * @return team number, or 0 if not found. + * @see "HAL_GetTeamNumber" + */ + public static native int getTeamNumber(); + /** * Reads the microsecond-resolution timer on the FPGA. * diff --git a/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java b/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java index 0ed189be52..7f51331a79 100644 --- a/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java +++ b/hal/src/main/java/edu/wpi/first/hal/simulation/RoboRioDataJNI.java @@ -159,6 +159,15 @@ public class RoboRioDataJNI extends JNIWrapper { public static native void setCPUTemp(double cpuTemp); + public static native int registerTeamNumberCallback( + NotifyCallback callback, boolean initialNotify); + + public static native void cancelTeamNumberCallback(int uid); + + public static native int getTeamNumber(); + + public static native void setTeamNumber(int teamNumber); + public static native String getSerialNumber(); public static native void setSerialNumber(String serialNumber); diff --git a/hal/src/main/native/athena/HAL.cpp b/hal/src/main/native/athena/HAL.cpp index 44cff93f82..c59e9bbe03 100644 --- a/hal/src/main/native/athena/HAL.cpp +++ b/hal/src/main/native/athena/HAL.cpp @@ -47,6 +47,8 @@ static char roboRioCommentsString[64]; static size_t roboRioCommentsStringSize; static bool roboRioCommentsStringInitialized; +static int32_t teamNumber = -1; + static const volatile HAL_HMBData* hmbBuffer; #define HAL_HMB_TIMESTAMP_OFFSET 5 @@ -353,6 +355,36 @@ size_t HAL_GetComments(char* buffer, size_t size) { return toCopy; } +void InitializeTeamNumber(void) { + char hostnameBuf[25]; + auto status = gethostname(hostnameBuf, sizeof(hostnameBuf)); + if (status != 0) { + teamNumber = 0; + return; + } + + std::string_view hostname{hostnameBuf, sizeof(hostnameBuf)}; + + // hostname is frc-{TEAM}-roborio + // Split string around '-' (max of 2 splits), take the second element of the + // resulting array. + wpi::SmallVector elements; + wpi::split(hostname, elements, "-", 2); + if (elements.size() < 3) { + teamNumber = 0; + return; + } + + teamNumber = wpi::parse_integer(elements[1], 10).value_or(0); +} + +int32_t HAL_GetTeamNumber(void) { + if (teamNumber == -1) { + InitializeTeamNumber(); + } + return teamNumber; +} + uint64_t HAL_GetFPGATime(int32_t* status) { hal::init::CheckInit(); if (!hmbBuffer) { diff --git a/hal/src/main/native/athena/mockdata/RoboRioData.cpp b/hal/src/main/native/athena/mockdata/RoboRioData.cpp index 6b7424f5ed..216b948796 100644 --- a/hal/src/main/native/athena/mockdata/RoboRioData.cpp +++ b/hal/src/main/native/athena/mockdata/RoboRioData.cpp @@ -29,6 +29,7 @@ DEFINE_CAPI(int32_t, UserFaults5V, 0) DEFINE_CAPI(int32_t, UserFaults3V3, 0) DEFINE_CAPI(double, BrownoutVoltage, 6.75) DEFINE_CAPI(double, CPUTemp, 45.0) +DEFINE_CAPI(int32_t, TeamNumber, 0); int32_t HALSIM_RegisterRoboRioSerialNumberCallback( HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify) { diff --git a/hal/src/main/native/cpp/jni/HALUtil.cpp b/hal/src/main/native/cpp/jni/HALUtil.cpp index 76c05f8a44..6316a8c1f8 100644 --- a/hal/src/main/native/cpp/jni/HALUtil.cpp +++ b/hal/src/main/native/cpp/jni/HALUtil.cpp @@ -484,6 +484,18 @@ Java_edu_wpi_first_hal_HALUtil_getComments return MakeJString(env, std::string_view(comments, len)); } +/* + * Class: edu_wpi_first_hal_HALUtil + * Method: getTeamNumber + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_hal_HALUtil_getTeamNumber + (JNIEnv* env, jclass) +{ + return HAL_GetTeamNumber(); +} + /* * Class: edu_wpi_first_hal_HALUtil * Method: getFPGATime diff --git a/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp b/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp index d362194240..9555f59319 100644 --- a/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp +++ b/hal/src/main/native/cpp/jni/simulation/RoboRioDataJNI.cpp @@ -878,6 +878,56 @@ Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_setCPUTemp HALSIM_SetRoboRioCPUTemp(cpuTemp); } +/* + * Class: edu_wpi_first_hal_simulation_RoboRioDataJNI + * Method: registerTeamNumberCallback + * Signature: (Ljava/lang/Object;Z)I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_registerTeamNumberCallback + (JNIEnv* env, jclass, jobject callback, jboolean initialNotify) +{ + return sim::AllocateCallbackNoIndex( + env, callback, initialNotify, &HALSIM_RegisterRoboRioTeamNumberCallback); +} + +/* + * Class: edu_wpi_first_hal_simulation_RoboRioDataJNI + * Method: cancelTeamNumberCallback + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_cancelTeamNumberCallback + (JNIEnv* env, jclass, jint handle) +{ + return sim::FreeCallbackNoIndex(env, handle, + &HALSIM_CancelRoboRioTeamNumberCallback); +} + +/* + * Class: edu_wpi_first_hal_simulation_RoboRioDataJNI + * Method: getTeamNumber + * Signature: ()I + */ +JNIEXPORT jint JNICALL +Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_getTeamNumber + (JNIEnv*, jclass) +{ + return HALSIM_GetRoboRioTeamNumber(); +} + +/* + * Class: edu_wpi_first_hal_simulation_RoboRioDataJNI + * Method: setTeamNumber + * Signature: (I)V + */ +JNIEXPORT void JNICALL +Java_edu_wpi_first_hal_simulation_RoboRioDataJNI_setTeamNumber + (JNIEnv*, jclass, jint value) +{ + HALSIM_SetRoboRioTeamNumber(value); +} + /* * Class: edu_wpi_first_hal_simulation_RoboRioDataJNI * Method: getSerialNumber diff --git a/hal/src/main/native/include/hal/HALBase.h b/hal/src/main/native/include/hal/HALBase.h index 0b267ab624..1264c6aa3d 100644 --- a/hal/src/main/native/include/hal/HALBase.h +++ b/hal/src/main/native/include/hal/HALBase.h @@ -92,6 +92,12 @@ size_t HAL_GetSerialNumber(char* buffer, size_t size); */ size_t HAL_GetComments(char* buffer, size_t size); +/** + * Returns the team number configured for the robot controller. + * @return team number, or 0 if not found. + */ +int32_t HAL_GetTeamNumber(void); + /** * Returns the runtime type of the HAL. * diff --git a/hal/src/main/native/include/hal/simulation/RoboRioData.h b/hal/src/main/native/include/hal/simulation/RoboRioData.h index b43a4d1253..d191fcb41f 100644 --- a/hal/src/main/native/include/hal/simulation/RoboRioData.h +++ b/hal/src/main/native/include/hal/simulation/RoboRioData.h @@ -126,6 +126,13 @@ void HALSIM_CancelRoboRioBrownoutVoltageCallback(int32_t uid); double HALSIM_GetRoboRioBrownoutVoltage(void); void HALSIM_SetRoboRioBrownoutVoltage(double brownoutVoltage); +int32_t HALSIM_RegisterRoboRioTeamNumberCallback(HAL_NotifyCallback callback, + void* param, + HAL_Bool initialNotify); +void HALSIM_CancelRoboRioTeamNumberCallback(int32_t uid); +int32_t HALSIM_GetRoboRioTeamNumber(void); +void HALSIM_SetRoboRioTeamNumber(int32_t teamNumber); + int32_t HALSIM_RegisterRoboRioSerialNumberCallback( HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify); void HALSIM_CancelRoboRioSerialNumberCallback(int32_t uid); diff --git a/hal/src/main/native/sim/HAL.cpp b/hal/src/main/native/sim/HAL.cpp index 9e1df574c7..633226e911 100644 --- a/hal/src/main/native/sim/HAL.cpp +++ b/hal/src/main/native/sim/HAL.cpp @@ -288,6 +288,10 @@ size_t HAL_GetComments(char* buffer, size_t size) { return HALSIM_GetRoboRioComments(buffer, size); } +int32_t HAL_GetTeamNumber(void) { + return HALSIM_GetRoboRioTeamNumber(); +} + uint64_t HAL_GetFPGATime(int32_t* status) { return hal::GetFPGATime(); } diff --git a/hal/src/main/native/sim/mockdata/RoboRioData.cpp b/hal/src/main/native/sim/mockdata/RoboRioData.cpp index d18ea16657..9a9a1a1d38 100644 --- a/hal/src/main/native/sim/mockdata/RoboRioData.cpp +++ b/hal/src/main/native/sim/mockdata/RoboRioData.cpp @@ -33,6 +33,7 @@ void RoboRioData::ResetData() { userFaults3V3.Reset(0); brownoutVoltage.Reset(6.75); cpuTemp.Reset(45.0); + teamNumber.Reset(0); m_serialNumber = ""; m_comments = ""; } @@ -134,6 +135,7 @@ DEFINE_CAPI(int32_t, UserFaults5V, userFaults5V) DEFINE_CAPI(int32_t, UserFaults3V3, userFaults3V3) DEFINE_CAPI(double, BrownoutVoltage, brownoutVoltage) DEFINE_CAPI(double, CPUTemp, cpuTemp) +DEFINE_CAPI(int32_t, TeamNumber, teamNumber) int32_t HALSIM_RegisterRoboRioSerialNumberCallback( HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify) { diff --git a/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h b/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h index 7d02cfa56d..aef61bea74 100644 --- a/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h +++ b/hal/src/main/native/sim/mockdata/RoboRioDataInternal.h @@ -31,6 +31,7 @@ class RoboRioData { HAL_SIMDATAVALUE_DEFINE_NAME(UserFaults3V3) HAL_SIMDATAVALUE_DEFINE_NAME(BrownoutVoltage) HAL_SIMDATAVALUE_DEFINE_NAME(CPUTemp) + HAL_SIMDATAVALUE_DEFINE_NAME(TeamNumber) HAL_SIMCALLBACKREGISTRY_DEFINE_NAME(SerialNumber) HAL_SIMCALLBACKREGISTRY_DEFINE_NAME(Comments); @@ -59,6 +60,7 @@ class RoboRioData { SimDataValue brownoutVoltage{ 6.75}; SimDataValue cpuTemp{45.0}; + SimDataValue teamNumber{0}; int32_t RegisterSerialNumberCallback(HAL_RoboRioStringCallback callback, void* param, HAL_Bool initialNotify); diff --git a/wpilibc/src/main/native/cpp/RobotController.cpp b/wpilibc/src/main/native/cpp/RobotController.cpp index 5d38c57e85..d67f378fed 100644 --- a/wpilibc/src/main/native/cpp/RobotController.cpp +++ b/wpilibc/src/main/native/cpp/RobotController.cpp @@ -41,6 +41,10 @@ std::string RobotController::GetComments() { return std::string(comments, len); } +int32_t RobotController::GetTeamNumber() { + return HAL_GetTeamNumber(); +} + uint64_t RobotController::GetFPGATime() { int32_t status = 0; uint64_t time = HAL_GetFPGATime(&status); diff --git a/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp b/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp index d7e4086e9a..90d9651d39 100644 --- a/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp +++ b/wpilibc/src/main/native/cpp/simulation/RoboRioSim.cpp @@ -301,6 +301,23 @@ void RoboRioSim::SetCPUTemp(units::celsius_t cpuTemp) { HALSIM_SetRoboRioCPUTemp(cpuTemp.value()); } +std::unique_ptr RoboRioSim::RegisterTeamNumberCallback( + NotifyCallback callback, bool initialNotify) { + auto store = std::make_unique( + -1, callback, &HALSIM_CancelRoboRioTeamNumberCallback); + store->SetUid(HALSIM_RegisterRoboRioTeamNumberCallback( + &CallbackStoreThunk, store.get(), initialNotify)); + return store; +} + +int32_t RoboRioSim::GetTeamNumber() { + return HALSIM_GetRoboRioTeamNumber(); +} + +void RoboRioSim::SetTeamNumber(int32_t teamNumber) { + HALSIM_SetRoboRioTeamNumber(teamNumber); +} + std::string RoboRioSim::GetSerialNumber() { char serialNum[9]; size_t len = HALSIM_GetRoboRioSerialNumber(serialNum, sizeof(serialNum)); diff --git a/wpilibc/src/main/native/include/frc/RobotController.h b/wpilibc/src/main/native/include/frc/RobotController.h index 777af4129c..eadd1cf10d 100644 --- a/wpilibc/src/main/native/include/frc/RobotController.h +++ b/wpilibc/src/main/native/include/frc/RobotController.h @@ -63,6 +63,13 @@ class RobotController { */ static std::string GetComments(); + /** + * Returns the team number configured for the robot controller. + * + * @return team number, or 0 if not found. + */ + static int32_t GetTeamNumber(); + /** * Read the microsecond-resolution timer on the FPGA. * diff --git a/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h b/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h index aa9f66d1ef..64e81e1839 100644 --- a/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h +++ b/wpilibc/src/main/native/include/frc/simulation/RoboRioSim.h @@ -461,6 +461,31 @@ class RoboRioSim { */ static void SetCPUTemp(units::celsius_t cpuTemp); + /** + * Register a callback to be run whenever the team number changes. + * + * @param callback the callback + * @param initialNotify whether to call the callback with the initial state + * @return the CallbackStore object associated with this callback + */ + [[nodiscard]] + static std::unique_ptr RegisterTeamNumberCallback( + NotifyCallback callback, bool initialNotify); + + /** + * Get the team number. + * + * @return the team number. + */ + static int32_t GetTeamNumber(); + + /** + * Set the team number. + * + * @param teamNumber the new team number. + */ + static void SetTeamNumber(int32_t teamNumber); + /** * Get the serial number. * diff --git a/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp b/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp index 980cb8aa69..e42f38fd13 100644 --- a/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp +++ b/wpilibc/src/test/native/cpp/simulation/RoboRioSimTest.cpp @@ -222,6 +222,21 @@ TEST(RoboRioSimTest, SetCPUTemp) { EXPECT_EQ(kCPUTemp, RobotController::GetCPUTemp().value()); } +TEST(RoboRioSimTest, SetTeamNumber) { + RoboRioSim::ResetData(); + + IntCallback callback; + auto cbHandle = + RoboRioSim::RegisterTeamNumberCallback(callback.GetCallback(), false); + constexpr int kTeamNumber = 9999; + + RoboRioSim::SetTeamNumber(kTeamNumber); + EXPECT_TRUE(callback.WasTriggered()); + EXPECT_EQ(kTeamNumber, callback.GetLastValue()); + EXPECT_EQ(kTeamNumber, RoboRioSim::GetTeamNumber()); + EXPECT_EQ(kTeamNumber, RobotController::GetTeamNumber()); +} + TEST(RoboRioSimTest, SetSerialNumber) { const std::string kSerialNum = "Hello"; diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java index af44387159..bd529473a8 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/RobotController.java @@ -57,6 +57,15 @@ public final class RobotController { return HALUtil.getComments(); } + /** + * Returns the team number configured for the robot controller. + * + * @return team number, or 0 if not found. + */ + public static int getTeamNumber() { + return HALUtil.getTeamNumber(); + } + /** * Read the microsecond timer from the FPGA. * diff --git a/wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/RoboRioSim.java b/wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/RoboRioSim.java index 9b6f74bf8d..8b28b6ddf5 100644 --- a/wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/RoboRioSim.java +++ b/wpilibj/src/main/java/edu/wpi/first/wpilibj/simulation/RoboRioSim.java @@ -557,6 +557,38 @@ public final class RoboRioSim { RoboRioDataJNI.setCPUTemp(cpuTemp); } + /** + * Register a callback to be run whenever the team number changes. + * + * @param callback the callback + * @param initialNotify whether to call the callback with the initial state + * @return the {@link CallbackStore} object associated with this callback. Save a reference to + * this object so GC doesn't cancel the callback. + */ + public static CallbackStore registerTeamNumberCallback( + NotifyCallback callback, boolean initialNotify) { + int uid = RoboRioDataJNI.registerTeamNumberCallback(callback, initialNotify); + return new CallbackStore(uid, RoboRioDataJNI::cancelTeamNumberCallback); + } + + /** + * Get the team number. + * + * @return the team number. + */ + public static int getTeamNumber() { + return RoboRioDataJNI.getTeamNumber(); + } + + /** + * Set the team number. + * + * @param teamNumber the new team number. + */ + public static void setTeamNumber(int teamNumber) { + RoboRioDataJNI.setTeamNumber(teamNumber); + } + /** * Get the serial number. * diff --git a/wpilibj/src/test/java/edu/wpi/first/wpilibj/simulation/RoboRioSimTest.java b/wpilibj/src/test/java/edu/wpi/first/wpilibj/simulation/RoboRioSimTest.java index 6aaf43afaf..c016ec420c 100644 --- a/wpilibj/src/test/java/edu/wpi/first/wpilibj/simulation/RoboRioSimTest.java +++ b/wpilibj/src/test/java/edu/wpi/first/wpilibj/simulation/RoboRioSimTest.java @@ -226,6 +226,23 @@ class RoboRioSimTest { } } + @Test + void testTeamNumber() { + RoboRioSim.resetData(); + + IntCallback callback = new IntCallback(); + + try (CallbackStore cb = RoboRioSim.registerTeamNumberCallback(callback, false)) { + final int kTeamNumber = 9999; + + RoboRioSim.setTeamNumber(kTeamNumber); + assertTrue(callback.wasTriggered()); + assertEquals(kTeamNumber, callback.getSetValue()); + assertEquals(kTeamNumber, RoboRioSim.getTeamNumber()); + assertEquals(kTeamNumber, RobotController.getTeamNumber()); + } + } + @Test void testSerialNumber() { RoboRioSim.resetData();