-
Notifications
You must be signed in to change notification settings - Fork 0
Network Alerts
Network Alerts are an extension of WPILib's Alert class. They automatically and periodically update the activation and message of an alert.
When using WPILib's Alert, you must store each alert in its own variable and manually update its activation and message periodically. This leads to repetitive code and can easily become a nightmare to keep track of (for example - if you forgot to update the activation of one alert, it will not be updated at all).
Network Alerts offers a simple ‘set-and-forget’ approach to alerts, in which the NetworkAlertsManager is responsible for updating and storing all of the alerts. You can just add alerts to the manager once, and it will take care of updating them for you.
This leads to cleaner code and allows you to focus on more important tasks than making sure that all of the alerts are update correctly.
- Eliminates manual periodic updates for alerts
- Reduces boilerplate code
- Keeps alert logic centralized and modular
- Makes the organization of the alerts cleaner
To update Network Alerts, add the following to your robotPeriodic() in Robot.java:
NetworkAlertsManager.update();This update all the
NetworkPeriodicAlerts that were added toNetworkAlertsManager
To create a Network Alert, you first need to create a NetworkAlertsGroup.
A NetworkAlertsGroup represent an alerts group (in WPILib's Alert, this is the equivalent of the optional group name parameter when creating an alert). Then, you can add an alert to it, and the group will add the alert to the manager itself.
To create a NetworkAlertsGroup, use:
new NetworkAlertsGroup(String groupName);Tip: You can also create a subgroup using:
group.getSubGroup(String subGroupName)
There is also a "default group" (called "NetworkAlerts"), which you can access by using:
NetworkAlertsGroup.defaultInstance;Using the default group is our personal preference, as it keeps all the Network Alerts in the same place on the Dashboard.
You can then add a Network Alert to the group. When adding a Network Alert to a group, the activation supplier is returned, for your convenience.
BooleanSupplier activation = group.addAlert(Supplier<String> messageSupplier, Supplier<String> activationSupplier, AlertType alertType);For example:
swerveAlertsGroup.addAlert(() -> "Gyro Is Disconnected!", () -> !isGyroConnected(), AlertType.kError);You can also use group.addAlert() to add an alert of a specific type. For example:
swerveAlertsGroup.addErrorAlert(() -> "Gyro Is Disconnected!", () -> !isGyroConnected());You can also create a NetworkPeriodicAlert manually, using:
new NetworkPeriodicAlert(NetworkAlertsGroup group, Supplier<String> messageSupplier, BooleanSupplier isActive, AlertType);For example:
NetworkPeriodicAlert alert = new NetworkPeriodicAlert(group, () -> "Gryo Is Dissconected!", () -> !isGyroConnected, AlertType.kError);Then, you can add the the alert to the manager:
NetworkAlertsManager.addNetworkPeriodicAlert(alert);We strongly encourage you to create (or use our own) Alerts Factory. An Alerts Factory is a static helper class with methods that interpret different hardware vendors' error codes (or anything else you may want to interpret) and "knows" how to create Network Alerts from them.
This is helpful because different hardware vendors use very different error codes, and you might need to translate those codes into meaningful alerts.
For example, this is our (simple) Alerts Factory.
package frc.robot.utils;
import java.util.function.BooleanSupplier;
import java.util.function.Supplier;
import com.ctre.phoenix6.StatusCode;
import com.revrobotics.REVLibError;
import com.revrobotics.spark.SparkBase.Faults;
import com.revrobotics.spark.SparkBase.Warnings;
import frc.lib.networkalerts.NetworkAlertsGroup;
public final class AlertsFactory {
/*
This will add all the different alert that a rev motor can generate, and return an array of their activations
(The order of the array is the order of the parameters)
*/
public static BooleanSupplier[] revMotor(NetworkAlertsGroup group, Supplier<REVLibError> configErrorSupplier,
Supplier<Warnings> warningSupplier, Supplier<Faults> errorSupplier, String prefix) {
BooleanSupplier[] alertsActivations = new BooleanSupplier[3];
alertsActivations[0] = revError(group, configErrorSupplier, prefix);
alertsActivations[1] = sparkMaxWarning(group, warningSupplier, prefix);
alertsActivations[2] = sparkMaxError(group, errorSupplier, prefix);
return alertsActivations;
}
/* This will add a `REVLibError` alert and return the alert's activation */
public static BooleanSupplier revError(NetworkAlertsGroup group, Supplier<REVLibError> errorSupplier, String prefix) {
return group.addErrorAlert(() -> prefix + ": " + errorSupplier.get().name(), () -> errorSupplier.get().value != 0);
}
/* This will add a spark max (rev) warning alert and return the alert's activation */
public static BooleanSupplier sparkMaxWarning(NetworkAlertsGroup group, Supplier<Warnings> warningSupplier, String prefix) {
Supplier<String> messageSupplier = () -> {
String message = prefix + ": ";
Warnings warning = warningSupplier.get();
if (warning.brownout) message += "brownout, ";
if (warning.escEeprom) message += "escEeprom, ";
if (warning.extEeprom) message += "extEeprom, ";
if (warning.hasReset) message += "hasReset, ";
if (warning.other) message += "other, ";
if (warning.overcurrent) message += "overcurrent, ";
if (warning.sensor) message += "sensor, ";
if (warning.stall) message += "stall, ";
return message;
};
return group.addWarningAlert(messageSupplier, () -> warningSupplier.get().rawBits != 0);
}
/* This will add a spark max (rev) error alert and return the alert's activation */
public static BooleanSupplier sparkMaxError(NetworkAlertsGroup group, Supplier<Faults> errorSupplier, String prefix) {
Supplier<String> messageSupplier = () -> {
String message = prefix + ": ";
Faults error = errorSupplier.get();
if (error.can) message += "can, ";
if (error.escEeprom) message += "escEeprom, ";
if (error.firmware) message += "firmware, ";
if (error.gateDriver) message += "gateDriver, ";
if (error.motorType) message += "motorType, ";
if (error.other) message += "other, ";
if (error.sensor) message += "sensor, ";
if (error.temperature) message += "temperature, ";
return message;
};
return group.addErrorAlert(messageSupplier, () -> errorSupplier.get().rawBits != 0);
}
/* This will add a warning phenix alert and return alert's activation */
public static BooleanSupplier phoenixWarning(NetworkAlertsGroup group, Supplier<StatusCode> statusSupplier, String prefix) {
return group.addWarningAlert(() -> prefix + ": " + statusSupplier.get().getName(), () -> statusSupplier.get().isWarning());
}
/* This will add an error phenix alert and return alert's activation */
public static BooleanSupplier phoenixError(NetworkAlertsGroup group, Supplier<StatusCode> statusSupplier, String prefix) {
return group.addErrorAlert(() -> prefix + ": " + statusSupplier.get().getName(), () -> statusSupplier.get().isError());
}
/*
This will add all the different alert that a phoenix motor can generate, and return an array of their activations
(The order of the array is the order of the parameters)
*/
public static BooleanSupplier[] phoenixMotor(NetworkAlertsGroup group, Supplier<StatusCode> statusSupplier, String prefix) {
BooleanSupplier[] alertsActivations = new BooleanSupplier[2];
alertsActivations[0] = phoenixWarning(group, statusSupplier, prefix);
alertsActivations[1] = phoenixError(group, statusSupplier, prefix);
return alertsActivations;
}
}REVLibError motorConfigError = motor.configure(motorConfig, ResetMode.kResetSafeParameters, PersistMode.kPersistParameters);
AlertsFactory.revMotor(NetworkAlertsGroup.defaultInstance, () -> motorConfigError, motor::getWarnings, motor::getFaults, "Funnel: Motor: ");