From 4f3a3b7205b503d802ff166337fc70b091b813d5 Mon Sep 17 00:00:00 2001 From: Sam Carlberg Date: Tue, 1 Oct 2024 21:01:03 -0400 Subject: [PATCH] Add settings for configuring Epilogue logging (#34) * Populate new project settings from all known settings, instead of hardcoding only a few known ones * Add new epilogue config settings Log to disk, log to NT, and logging root are all now configurable --- src/bindings/Project.ts | 17 ++++++----- src/codegen/java/RobotGenerator.ts | 47 +++++++++++++++++++++++------- src/settings/Settings.ts | 24 +++++++++++++++ 3 files changed, 70 insertions(+), 18 deletions(-) diff --git a/src/bindings/Project.ts b/src/bindings/Project.ts index 699e9b2..11d67c8 100644 --- a/src/bindings/Project.ts +++ b/src/bindings/Project.ts @@ -12,6 +12,7 @@ import { BundledLaunchJson, BundledSettingsJson } from "../bundled_files/vscode" import { BundledWpilibCommandsV2 } from "../bundled_files/vendordeps" import { className } from "../codegen/java/util" import { generateSubsystem } from "../codegen/java/SubsystemGenerator" +import { ALL_SETTINGS } from "../settings/Settings" export type GeneratedFile = { name: string @@ -135,13 +136,15 @@ export const makeNewProject = (): Project => { subsystems: [], commands: [], generatedFiles: makeDefaultGeneratedFiles(), - settings: { - "robotbuilder.general.project_name": "", - "robotbuilder.general.team_number": null, - // "robotbuilder.general.cache_sensor_values": false, - "wpilib.epilogue.enabled": true, - }, - } + settings: { }, + } + + for (const categoryKey in ALL_SETTINGS) { + const category: SettingsCategory = ALL_SETTINGS[categoryKey] + category.settings.forEach(setting => { + project.settings[setting.key] = setting.defaultValue + }) + } // Update pregenerated files to give them a valid initial state // These files may need to be updated over time while the project is edited diff --git a/src/codegen/java/RobotGenerator.ts b/src/codegen/java/RobotGenerator.ts index 3eef99f..5c94443 100644 --- a/src/codegen/java/RobotGenerator.ts +++ b/src/codegen/java/RobotGenerator.ts @@ -13,7 +13,7 @@ export function generateRobotClass(project: Project): string { ${ project.settings["wpilib.epilogue.enabled"] ? "import edu.wpi.first.epilogue.Epilogue;" : "" } ${ project.settings["wpilib.epilogue.enabled"] ? "import edu.wpi.first.epilogue.Logged;" : "" } ${ project.settings["wpilib.epilogue.enabled"] ? "import edu.wpi.first.epilogue.NotLogged;" : "" } - import edu.wpi.first.wpilibj.RuntimeType; + ${ project.settings["wpilib.epilogue.enabled"] ? "import edu.wpi.first.epilogue.logging.*;" : "" } import edu.wpi.first.wpilibj.TimedRobot; import edu.wpi.first.wpilibj2.command.Command; import edu.wpi.first.wpilibj2.command.CommandScheduler; @@ -38,16 +38,8 @@ ${ ${ project.settings["wpilib.epilogue.enabled"] ? ` Epilogue.configure(config -> { - // TODO: Add a UI for customizing epilogue - - if (getRuntimeType() == RuntimeType.kRoboRIO) { - // Only log to networktables on a roboRIO 1 because of limited disk space. - // If the disk fills up, there's a real risk of getting locked out of the rio! - config.dataLogger = new NTDataLogger(NetworkTablesInstance.getDefault()); - } else { - // On a roboRIO 2 there's enough disk space to be able to safely log to disk - config.dataLogger = new FileSystemLogger(DataLogManager.getDataLog()); - } + ${ generateEpilogueLoggers(project) } + ${ generateEpilogueRoot(project) } }); ` : "" } @@ -182,3 +174,36 @@ function findCommand(project: Project, commandUUID: string): [Project | Subsyste return [] } + +function generateEpilogueLoggers(project: Project): string { + if (project.settings["wpilib.epilogue.log_to_disk"]) { + if (project.settings["wpilib.epilogue.log_to_nt"]) { + // Log to both backends; need a multilogger + return ` + config.dataLogger = new MultiLogger( + new NTDataLogger(NetworkTablesInstance.getDefault()), + new FileLogger(DataLogManager.getDataLog()) + ); + ` + } else { + // Just disk logging + return "config.dataLogger = new FileLogger(DataLogManager.getDataLog());" + } + } else if (project.settings["wpilib.epilogue.log_to_nt"]) { + // Just NT logging + return "config.dataLogger = new NTDataLogger(NetworkTableInstance.getDefault());" + } else { + return ` + // No logging backend. Data will be queried as normal, but will not be logged anywhere. + config.dataLogger = new NullLogger(); + ` + } +} + +function generateEpilogueRoot(project: Project): string { + let root: string | null = project.settings["wpilib.epilogue.logging_root"] + if (!root || root.trim().length === 0) { + root = "Robot" + } + return `config.root = "${ root }";` +} diff --git a/src/settings/Settings.ts b/src/settings/Settings.ts index a3b565f..4d2ff9b 100644 --- a/src/settings/Settings.ts +++ b/src/settings/Settings.ts @@ -52,5 +52,29 @@ registerCategory({ type: "boolean", defaultValue: true, }, + { + key: "wpilib.epilogue.log_to_disk", + name: "Log to Disk", + description: "Enables logging to the roboRIO's built in flash storage. Be very careful if using a roboRIO 1 due to its limited disk space. Accumulating too many log files may prevent access to the device and require a full re-flash", + required: false, + type: "boolean", + defaultValue: false, + }, + { + key: "wpilib.epilogue.log_to_nt", + name: "Log to Network", + description: "Enables logging to the network for DS-based applications to view or record", + required: false, + type: "boolean", + defaultValue: true, + }, + { + key: "wpilib.epilogue.logging_root", + name: "Logging Root", + description: `The root path under which logged data should appear. This is used by both file- and network-based logging. Defaults to "Robot" if unspecified or left blank`, + required: false, + type: "string", + defaultValue: "Robot", + }, ], })