mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-20 00:51:42 +00:00
[examples] DigitalCommunication, I2CCommunication: Add tests (#4865)
This commit is contained in:
@@ -14,10 +14,10 @@ import edu.wpi.first.wpilibj.TimedRobot;
|
||||
*/
|
||||
public class Robot extends TimedRobot {
|
||||
// define ports for digitalcommunication with light controller
|
||||
private static final int kAlliancePort = 0;
|
||||
private static final int kEnabledPort = 1;
|
||||
private static final int kAutonomousPort = 2;
|
||||
private static final int kAlertPort = 3;
|
||||
static final int kAlliancePort = 0;
|
||||
static final int kEnabledPort = 1;
|
||||
static final int kAutonomousPort = 2;
|
||||
static final int kAlertPort = 3;
|
||||
|
||||
private final DigitalOutput m_allianceOutput = new DigitalOutput(kAlliancePort);
|
||||
private final DigitalOutput m_enabledOutput = new DigitalOutput(kEnabledPort);
|
||||
@@ -39,4 +39,14 @@ public class Robot extends TimedRobot {
|
||||
var matchTime = DriverStation.getMatchTime();
|
||||
m_alertOutput.set(matchTime <= 30 && matchTime >= 25);
|
||||
}
|
||||
|
||||
/** Close all resources. */
|
||||
@Override
|
||||
public void close() {
|
||||
m_allianceOutput.close();
|
||||
m_enabledOutput.close();
|
||||
m_autonomousOutput.close();
|
||||
m_alertOutput.close();
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -803,7 +803,8 @@
|
||||
"name": "Digital Communication Sample",
|
||||
"description": "An example program that communicates with external devices (such as an Arduino) using the roboRIO's DIO",
|
||||
"tags": [
|
||||
"Digital"
|
||||
"Digital",
|
||||
"Unit Testing"
|
||||
],
|
||||
"foldername": "digitalcommunication",
|
||||
"gradlebase": "java",
|
||||
|
||||
@@ -6,6 +6,7 @@ package edu.wpi.first.wpilibj.examples.i2ccommunication;
|
||||
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
import edu.wpi.first.wpilibj.I2C;
|
||||
import edu.wpi.first.wpilibj.I2C.Port;
|
||||
import edu.wpi.first.wpilibj.TimedRobot;
|
||||
|
||||
/**
|
||||
@@ -13,9 +14,10 @@ import edu.wpi.first.wpilibj.TimedRobot;
|
||||
* code using the roboRIO's I2C port.
|
||||
*/
|
||||
public class Robot extends TimedRobot {
|
||||
private static int kDeviceAddress = 4;
|
||||
static final Port kPort = Port.kOnboard;
|
||||
private static final int kDeviceAddress = 4;
|
||||
|
||||
private static I2C m_arduino = new I2C(I2C.Port.kOnboard, kDeviceAddress);
|
||||
private final I2C m_arduino = new I2C(kPort, kDeviceAddress);
|
||||
|
||||
private void writeString(String input) {
|
||||
// Creates a char array from the input string
|
||||
@@ -30,7 +32,7 @@ public class Robot extends TimedRobot {
|
||||
}
|
||||
|
||||
// Writes bytes over I2C
|
||||
m_arduino.transaction(data, data.length, null, 0);
|
||||
m_arduino.transaction(data, data.length, new byte[] {}, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -54,4 +56,11 @@ public class Robot extends TimedRobot {
|
||||
|
||||
writeString(stateMessage.toString());
|
||||
}
|
||||
|
||||
/** Close all resources. */
|
||||
@Override
|
||||
public void close() {
|
||||
m_arduino.close();
|
||||
super.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.wpilibj.examples.digitalcommunication;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import edu.wpi.first.hal.AllianceStationID;
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.simulation.DIOSim;
|
||||
import edu.wpi.first.wpilibj.simulation.DriverStationSim;
|
||||
import edu.wpi.first.wpilibj.simulation.SimHooks;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.parallel.ResourceLock;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
@ResourceLock("timing")
|
||||
class DigitalCommunicationTest {
|
||||
private Robot m_robot;
|
||||
private Thread m_thread;
|
||||
private final DIOSim m_allianceOutput = new DIOSim(Robot.kAlliancePort);
|
||||
private final DIOSim m_enabledOutput = new DIOSim(Robot.kEnabledPort);
|
||||
private final DIOSim m_autonomousOutput = new DIOSim(Robot.kAutonomousPort);
|
||||
private final DIOSim m_alertOutput = new DIOSim(Robot.kAlertPort);
|
||||
|
||||
@BeforeEach
|
||||
void startThread() {
|
||||
HAL.initialize(500, 0);
|
||||
SimHooks.pauseTiming();
|
||||
DriverStationSim.resetData();
|
||||
m_robot = new Robot();
|
||||
m_thread = new Thread(m_robot::startCompetition);
|
||||
m_thread.start();
|
||||
SimHooks.stepTiming(0.0); // Wait for Notifiers
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void stopThread() {
|
||||
m_robot.endCompetition();
|
||||
try {
|
||||
m_thread.interrupt();
|
||||
m_thread.join();
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
m_robot.close();
|
||||
m_allianceOutput.resetData();
|
||||
m_enabledOutput.resetData();
|
||||
m_autonomousOutput.resetData();
|
||||
m_alertOutput.resetData();
|
||||
}
|
||||
|
||||
@EnumSource(AllianceStationID.class)
|
||||
@ParameterizedTest(name = "alliance[{index}]: {0}")
|
||||
void allianceTest(AllianceStationID alliance) {
|
||||
DriverStationSim.setAllianceStationId(alliance);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_allianceOutput.getInitialized());
|
||||
assertFalse(m_allianceOutput.getIsInput());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
assertEquals(alliance.name().startsWith("Red"), m_allianceOutput.getValue());
|
||||
}
|
||||
|
||||
@ValueSource(booleans = {true, false})
|
||||
@ParameterizedTest(name = "enabled[{index}]: {0}")
|
||||
void enabledTest(boolean enabled) {
|
||||
DriverStationSim.setEnabled(enabled);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_enabledOutput.getInitialized());
|
||||
assertFalse(m_enabledOutput.getIsInput());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
assertEquals(enabled, m_enabledOutput.getValue());
|
||||
}
|
||||
|
||||
@ValueSource(booleans = {true, false})
|
||||
@ParameterizedTest(name = "autonomous[{index}]: {0}")
|
||||
void autonomousTest(boolean autonomous) {
|
||||
DriverStationSim.setAutonomous(autonomous);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_autonomousOutput.getInitialized());
|
||||
assertFalse(m_autonomousOutput.getIsInput());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
assertEquals(autonomous, m_autonomousOutput.getValue());
|
||||
}
|
||||
|
||||
@ValueSource(doubles = {45.0, 27.0, 23.0})
|
||||
@ParameterizedTest(name = "alert[{index}]: {0}s")
|
||||
void alertTest(double matchTime) {
|
||||
DriverStationSim.setMatchTime(matchTime);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_alertOutput.getInitialized());
|
||||
assertFalse(m_alertOutput.getIsInput());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
assertEquals(matchTime <= 30 && matchTime >= 25, m_alertOutput.getValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
// Copyright (c) FIRST and other WPILib contributors.
|
||||
// Open Source Software; you can modify and/or share it under the terms of
|
||||
// the WPILib BSD license file in the root directory of this project.
|
||||
|
||||
package edu.wpi.first.wpilibj.examples.i2ccommunication;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertTimeoutPreemptively;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import edu.wpi.first.hal.AllianceStationID;
|
||||
import edu.wpi.first.hal.HAL;
|
||||
import edu.wpi.first.wpilibj.DriverStation;
|
||||
import edu.wpi.first.wpilibj.simulation.CallbackStore;
|
||||
import edu.wpi.first.wpilibj.simulation.DriverStationSim;
|
||||
import edu.wpi.first.wpilibj.simulation.I2CSim;
|
||||
import edu.wpi.first.wpilibj.simulation.SimHooks;
|
||||
import java.time.Duration;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.parallel.ResourceLock;
|
||||
import org.junit.jupiter.params.ParameterizedTest;
|
||||
import org.junit.jupiter.params.provider.EnumSource;
|
||||
import org.junit.jupiter.params.provider.ValueSource;
|
||||
|
||||
@ResourceLock("timing")
|
||||
class I2CCommunicationTest {
|
||||
private Robot m_robot;
|
||||
private Thread m_thread;
|
||||
private final I2CSim m_i2c = new I2CSim(Robot.kPort.value);
|
||||
private CompletableFuture<String> m_future;
|
||||
private CallbackStore m_callback;
|
||||
|
||||
@BeforeEach
|
||||
void startThread() {
|
||||
HAL.initialize(500, 0);
|
||||
SimHooks.pauseTiming();
|
||||
DriverStationSim.resetData();
|
||||
m_future = new CompletableFuture<>();
|
||||
m_callback =
|
||||
m_i2c.registerWriteCallback(
|
||||
(name, buffer, count) -> m_future.complete(new String(buffer, 0, count)));
|
||||
m_robot = new Robot();
|
||||
m_thread = new Thread(m_robot::startCompetition);
|
||||
m_thread.start();
|
||||
SimHooks.stepTiming(0.0); // Wait for Notifiers
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
void stopThread() {
|
||||
m_robot.endCompetition();
|
||||
try {
|
||||
m_thread.interrupt();
|
||||
m_thread.join();
|
||||
} catch (InterruptedException ex) {
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
m_robot.close();
|
||||
m_callback.close();
|
||||
m_i2c.resetData();
|
||||
}
|
||||
|
||||
@EnumSource(AllianceStationID.class)
|
||||
@ParameterizedTest(name = "alliance[{index}]: {0}")
|
||||
void allianceTest(AllianceStationID alliance) {
|
||||
DriverStationSim.setAllianceStationId(alliance);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_i2c.getInitialized());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
String str = assertTimeoutPreemptively(Duration.ofMillis(20L), () -> m_future.get());
|
||||
char expected = alliance.name().startsWith("Red") ? 'R' : 'B';
|
||||
|
||||
assertEquals(expected, str.charAt(0));
|
||||
}
|
||||
|
||||
@ValueSource(booleans = {true, false})
|
||||
@ParameterizedTest(name = "enabled[{index}]: {0}")
|
||||
void enabledTest(boolean enabled) {
|
||||
DriverStationSim.setEnabled(enabled);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_i2c.getInitialized());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
String str = assertTimeoutPreemptively(Duration.ofMillis(20L), () -> m_future.get());
|
||||
char expected = enabled ? 'E' : 'D';
|
||||
|
||||
assertEquals(expected, str.charAt(1));
|
||||
}
|
||||
|
||||
@ValueSource(booleans = {true, false})
|
||||
@ParameterizedTest(name = "autonomous[{index}]: {0}")
|
||||
void autonomousTest(boolean autonomous) {
|
||||
DriverStationSim.setAutonomous(autonomous);
|
||||
DriverStationSim.notifyNewData();
|
||||
|
||||
assertTrue(m_i2c.getInitialized());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
String str = assertTimeoutPreemptively(Duration.ofMillis(20L), () -> m_future.get());
|
||||
char expected = autonomous ? 'A' : 'T';
|
||||
|
||||
assertEquals(expected, str.charAt(2));
|
||||
}
|
||||
|
||||
@ValueSource(doubles = {112.0, 45.0, 27.0, 23.0, 3.0})
|
||||
@ParameterizedTest(name = "matchTime[{index}]: {0}s")
|
||||
void matchTimeTest(double matchTime) {
|
||||
DriverStationSim.setMatchTime(matchTime);
|
||||
DriverStationSim.notifyNewData();
|
||||
assertTrue(m_i2c.getInitialized());
|
||||
|
||||
SimHooks.stepTiming(0.02);
|
||||
|
||||
String str = assertTimeoutPreemptively(Duration.ofMillis(20L), () -> m_future.get());
|
||||
String expected = String.format("%03d", (int) DriverStation.getMatchTime());
|
||||
|
||||
assertEquals(expected, str.substring(3));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user