diff --git a/src/main/java/frc/robot/logging/Loggable.java b/src/main/java/frc/robot/logging/Loggable.java index 6b92266..8c5b84d 100644 --- a/src/main/java/frc/robot/logging/Loggable.java +++ b/src/main/java/frc/robot/logging/Loggable.java @@ -3,16 +3,16 @@ /** A class for a loggable subsystem. */ public interface Loggable { /** - * Sets up all the keys in the given Logger object. - * + * Sets up all the keys, getters, and setters in the given Logger object. * @param logger Logger class to setup keys in */ public abstract void setupLogging(Logger logger); /** * Logs data in the given Logger object. - * * @param logger Logger class to log data to + * @deprecated See {@link Logger#addAttribute(String, Supplier, Consumer)}. */ - public abstract void log(Logger logger); + @Deprecated(forRemoval = true) + public void log(Logger logger); } diff --git a/src/main/java/frc/robot/logging/LoggableCompressor.java b/src/main/java/frc/robot/logging/LoggableCompressor.java index e60328b..1821d70 100644 --- a/src/main/java/frc/robot/logging/LoggableCompressor.java +++ b/src/main/java/frc/robot/logging/LoggableCompressor.java @@ -14,11 +14,10 @@ public LoggableCompressor(PneumaticsModuleType moduleType) { @Override public void setupLogging(Logger logger) { - logger.addAttribute("PH/pressure"); + logger.addAttribute("PH/pressure", this::getPressure, null); } @Override public void log(Logger logger) { - logger.log("PH/pressure", this.getPressure()); } } diff --git a/src/main/java/frc/robot/logging/LoggablePowerDistribution.java b/src/main/java/frc/robot/logging/LoggablePowerDistribution.java index cde1a5f..2301fe1 100644 --- a/src/main/java/frc/robot/logging/LoggablePowerDistribution.java +++ b/src/main/java/frc/robot/logging/LoggablePowerDistribution.java @@ -13,12 +13,11 @@ public LoggablePowerDistribution(int module, ModuleType moduleType) { @Override public void setupLogging(Logger logger) { - logger.addAttribute("PDH/voltage"); + logger.addAttribute("PDH/voltage", this::getVoltage, null); } @Override public void log(Logger logger) { - logger.log("PDH/voltage", this.getVoltage()); } } diff --git a/src/main/java/frc/robot/logging/LoggableTimer.java b/src/main/java/frc/robot/logging/LoggableTimer.java index 0cb8d81..536fbb7 100644 --- a/src/main/java/frc/robot/logging/LoggableTimer.java +++ b/src/main/java/frc/robot/logging/LoggableTimer.java @@ -6,12 +6,11 @@ public class LoggableTimer extends Timer implements Loggable { @Override public void setupLogging(Logger logger) { - logger.addAttribute("Time"); + logger.addAttribute("Time", this::get, null); } @Override public void log(Logger logger) { - logger.log("Time", this.get()); } } diff --git a/src/main/java/frc/robot/logging/Logger.java b/src/main/java/frc/robot/logging/Logger.java index 57ff780..c54cca4 100644 --- a/src/main/java/frc/robot/logging/Logger.java +++ b/src/main/java/frc/robot/logging/Logger.java @@ -2,6 +2,9 @@ import edu.wpi.first.networktables.NetworkTable; import edu.wpi.first.networktables.NetworkTableInstance; +import edu.wpi.first.util.function.BooleanConsumer; +import edu.wpi.first.util.sendable.SendableBuilder; +import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard; import java.io.BufferedWriter; import java.io.File; @@ -12,13 +15,27 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.BooleanSupplier; +import java.util.function.Consumer; +import java.util.function.DoubleConsumer; +import java.util.function.DoubleSupplier; +import java.util.function.Supplier; /** Manages NetworkTable and file logging. */ public class Logger { + private static final String ERROR_MSG_ATTRIBUTE_ALREADY_EXISTS = + "Attribute \"%s\" already exists! Skipping!%n"; + private static final String TABLE_PREFIX = "Logging"; private String filename; private BufferedWriter log = null; + private Map> suppliers; private Map fields; private List loggables; + /** + * Our NetworkTable instance. + * @deprecated Use SmartDashboard Sendables instead. + */ + @Deprecated(forRemoval = true) private NetworkTable table; public Logger() { @@ -109,16 +126,86 @@ public boolean hasAttribute(String name) { /** * Adds an attribute to the logger. - * - * @param field - * @return + * @param field The key to add to the logger + * @return Whether the attribute was added */ public boolean addAttribute(String field) { if (hasAttribute(field)) { - // TODO: Output warning + System.out.printf(ERROR_MSG_ATTRIBUTE_ALREADY_EXISTS, field); + return false; // We already have this attribute + } + fields.put(field, ""); + + return true; + } + + /** + * Adds an attribute to the logger. + * @param field The key to add to the logger + * @param getter The function to get the value of the attribute + * @param setter The function to set the value of the attribute + * @return Whether the attribute was added + */ + public boolean addAttribute(String field, Supplier getter, Consumer setter) { + if (hasAttribute(field)) { + System.out.printf(ERROR_MSG_ATTRIBUTE_ALREADY_EXISTS, field); + return false; // We already have this attribute + } + SmartDashboard.putData((SendableBuilder builder) -> { + builder.setSmartDashboardType(TABLE_PREFIX); + builder.addStringProperty(field, getter != null ? getter::get : null, + setter != null ? setter::accept : null); + }); + + suppliers.put(field, getter::get); + fields.put(field, ""); + + return true; + } + + /** + * Adds an attribute to the logger. + * @param field The key to add to the logger + * @param getter The function to get the value of the attribute + * @param setter The function to set the value of the attribute + * @return Whether the attribute was added + */ + public boolean addAttribute(String field, DoubleSupplier getter, DoubleConsumer setter) { + if (hasAttribute(field)) { + System.out.printf(ERROR_MSG_ATTRIBUTE_ALREADY_EXISTS, field); return false; // We already have this attribute } + SmartDashboard.putData((SendableBuilder builder) -> { + builder.setSmartDashboardType(TABLE_PREFIX); + builder.addDoubleProperty(field, getter != null ? getter::getAsDouble : null, + setter != null ? setter::accept : null); + }); + suppliers.put(field, () -> Double.toString(getter.getAsDouble())); + fields.put(field, ""); + + return true; + } + + /** + * Adds an attribute to the logger. + * @param field The key to add to the logger + * @param getter The function to get the value of the attribute + * @param setter The function to set the value of the attribute + * @return Whether the attribute was added + */ + public boolean addAttribute(String field, BooleanSupplier getter, BooleanConsumer setter) { + if (hasAttribute(field)) { + System.out.printf(ERROR_MSG_ATTRIBUTE_ALREADY_EXISTS, field); + return false; // We already have this attribute + } + SmartDashboard.putData((SendableBuilder builder) -> { + builder.setSmartDashboardType(TABLE_PREFIX); + builder.addBooleanProperty(field, getter != null ? getter::getAsBoolean : null, + setter != null ? setter::accept : null); + }); + + suppliers.put(field, () -> Boolean.toString(getter.getAsBoolean())); fields.put(field, ""); return true; @@ -134,11 +221,12 @@ public void setup() { /** * Logs data to the Logger. - * * @param field Key being logged * @param data Number data to log * @return Whether the operation succeeded + * @deprecated Use {@link #addAttribute(String, DoubleSupplier, DoubleConsumer)} instead */ + @Deprecated(forRemoval = true) public boolean log(String field, double data) { if (!hasAttribute(field)) { return false; @@ -150,28 +238,29 @@ public boolean log(String field, double data) { /** * Logs data to the Logger - * * @param field key being logged * @param data String data to log * @return whether the operation succeeded + * @deprecated Use {@link #addAttribute(String, Supplier, Consumer)} instead */ + @Deprecated(forRemoval = true) public boolean log(String field, String data) { if (!hasAttribute(field)) { return false; } - table.getEntry(field).setString(data); fields.put(field, data); return true; } /** * Logs data to the Logger - * * @param field key being logged * @param data to log * @return whether the operation succeeded + * @deprecated Use {@link #addAttribute(String, Supplier, Consumer)} instead */ + @Deprecated(forRemoval = true) public boolean log(String field, Object data) { if (!hasAttribute(field)) { return false; @@ -250,6 +339,9 @@ public void setupLoggables() { * Calls the log method of all currently registered Loggables. */ public void log() { + for (Map.Entry> entry : this.suppliers.entrySet()) { + this.fields.put(entry.getKey(), entry.getValue().get()); + } for (Loggable l : loggables) { l.log(this); }