From fa9f5f8cd77c8e903a217b739ce3877c51017cb2 Mon Sep 17 00:00:00 2001 From: Tim <73599525+timtogan@users.noreply.github.com> Date: Sun, 7 Dec 2025 00:15:23 -0800 Subject: [PATCH 1/4] added ElasticLib --- .../org/carlmontrobotics/lib199/Elastic.java | 392 ++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 src/main/java/org/carlmontrobotics/lib199/Elastic.java diff --git a/src/main/java/org/carlmontrobotics/lib199/Elastic.java b/src/main/java/org/carlmontrobotics/lib199/Elastic.java new file mode 100644 index 0000000..b803d10 --- /dev/null +++ b/src/main/java/org/carlmontrobotics/lib199/Elastic.java @@ -0,0 +1,392 @@ +// Copyright (c) 2023-2025 Gold87 and other Elastic contributors +// This software can be modified and/or shared under the terms +// defined by the Elastic license: +// https://github.com/Gold872/elastic-dashboard/blob/main/LICENSE + +// From: https://frc-elastic.gitbook.io/docs/additional-features-and-references/robot-notifications-with-elasticlib and https://github.com/Gold872/elastic-dashboard/blob/main/elasticlib/Elastic.java + +package org.carlmontrobotics.lib199; + +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import edu.wpi.first.networktables.NetworkTableInstance; +import edu.wpi.first.networktables.PubSubOption; +import edu.wpi.first.networktables.StringPublisher; +import edu.wpi.first.networktables.StringTopic; + +public final class Elastic { + private static final StringTopic notificationTopic = + NetworkTableInstance.getDefault().getStringTopic("/Elastic/RobotNotifications"); + private static final StringPublisher notificationPublisher = + notificationTopic.publish(PubSubOption.sendAll(true), PubSubOption.keepDuplicates(true)); + private static final StringTopic selectedTabTopic = + NetworkTableInstance.getDefault().getStringTopic("/Elastic/SelectedTab"); + private static final StringPublisher selectedTabPublisher = + selectedTabTopic.publish(PubSubOption.keepDuplicates(true)); + private static final ObjectMapper objectMapper = new ObjectMapper(); + + /** + * Represents the possible levels of notifications for the Elastic dashboard. These levels are + * used to indicate the severity or type of notification. + */ + public enum NotificationLevel { + /** Informational Message */ + INFO, + /** Warning message */ + WARNING, + /** Error message */ + ERROR + } + + /** + * Sends an notification to the Elastic dashboard. The notification is serialized as a JSON string + * before being published. + * + * @param notification the {@link Notification} object containing notification details + */ + public static void sendNotification(Notification notification) { + try { + notificationPublisher.set(objectMapper.writeValueAsString(notification)); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + } + + /** + * Selects the tab of the dashboard with the given name. If no tab matches the name, this will + * have no effect on the widgets or tabs in view. + * + *

If the given name is a number, Elastic will select the tab whose index equals the number + * provided. + * + * @param tabName the name of the tab to select + */ + public static void selectTab(String tabName) { + selectedTabPublisher.set(tabName); + } + + /** + * Selects the tab of the dashboard at the given index. If this index is greater than or equal to + * the number of tabs, this will have no effect. + * + * @param tabIndex the index of the tab to select. + */ + public static void selectTab(int tabIndex) { + selectTab(Integer.toString(tabIndex)); + } + + /** + * Represents an notification object to be sent to the Elastic dashboard. This object holds + * properties such as level, title, description, display time, and dimensions to control how the + * notification is displayed on the dashboard. + */ + public static class Notification { + @JsonProperty("level") + private NotificationLevel level; + + @JsonProperty("title") + private String title; + + @JsonProperty("description") + private String description; + + @JsonProperty("displayTime") + private int displayTimeMillis; + + @JsonProperty("width") + private double width; + + @JsonProperty("height") + private double height; + + /** + * Creates a new Notification with all default parameters. This constructor is intended to be + * used with the chainable decorator methods + * + *

Title and description fields are empty. + */ + public Notification() { + this(NotificationLevel.INFO, "", ""); + } + + /** + * Creates a new Notification with all properties specified. + * + * @param level the level of the notification (e.g., INFO, WARNING, ERROR) + * @param title the title text of the notification + * @param description the descriptive text of the notification + * @param displayTimeMillis the time in milliseconds for which the notification is displayed + * @param width the width of the notification display area + * @param height the height of the notification display area, inferred if below zero + */ + public Notification( + NotificationLevel level, + String title, + String description, + int displayTimeMillis, + double width, + double height) { + this.level = level; + this.title = title; + this.displayTimeMillis = displayTimeMillis; + this.description = description; + this.height = height; + this.width = width; + } + + /** + * Creates a new Notification with default display time and dimensions. + * + * @param level the level of the notification + * @param title the title text of the notification + * @param description the descriptive text of the notification + */ + public Notification(NotificationLevel level, String title, String description) { + this(level, title, description, 3000, 350, -1); + } + + /** + * Creates a new Notification with a specified display time and default dimensions. + * + * @param level the level of the notification + * @param title the title text of the notification + * @param description the descriptive text of the notification + * @param displayTimeMillis the display time in milliseconds + */ + public Notification( + NotificationLevel level, String title, String description, int displayTimeMillis) { + this(level, title, description, displayTimeMillis, 350, -1); + } + + /** + * Creates a new Notification with specified dimensions and default display time. If the height + * is below zero, it is automatically inferred based on screen size. + * + * @param level the level of the notification + * @param title the title text of the notification + * @param description the descriptive text of the notification + * @param width the width of the notification display area + * @param height the height of the notification display area, inferred if below zero + */ + public Notification( + NotificationLevel level, String title, String description, double width, double height) { + this(level, title, description, 3000, width, height); + } + + /** + * Updates the level of this notification + * + * @param level the level to set the notification to + */ + public void setLevel(NotificationLevel level) { + this.level = level; + } + + /** + * @return the level of this notification + */ + public NotificationLevel getLevel() { + return level; + } + + /** + * Updates the title of this notification + * + * @param title the title to set the notification to + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * Gets the title of this notification + * + * @return the title of this notification + */ + public String getTitle() { + return title; + } + + /** + * Updates the description of this notification + * + * @param description the description to set the notification to + */ + public void setDescription(String description) { + this.description = description; + } + + public String getDescription() { + return description; + } + + /** + * Updates the display time of the notification + * + * @param seconds the number of seconds to display the notification for + */ + public void setDisplayTimeSeconds(double seconds) { + setDisplayTimeMillis((int) Math.round(seconds * 1000)); + } + + /** + * Updates the display time of the notification in milliseconds + * + * @param displayTimeMillis the number of milliseconds to display the notification for + */ + public void setDisplayTimeMillis(int displayTimeMillis) { + this.displayTimeMillis = displayTimeMillis; + } + + /** + * Gets the display time of the notification in milliseconds + * + * @return the number of milliseconds the notification is displayed for + */ + public int getDisplayTimeMillis() { + return displayTimeMillis; + } + + /** + * Updates the width of the notification + * + * @param width the width to set the notification to + */ + public void setWidth(double width) { + this.width = width; + } + + /** + * Gets the width of the notification + * + * @return the width of the notification + */ + public double getWidth() { + return width; + } + + /** + * Updates the height of the notification + * + *

If the height is set to -1, the height will be determined automatically by the dashboard + * + * @param height the height to set the notification to + */ + public void setHeight(double height) { + this.height = height; + } + + /** + * Gets the height of the notification + * + * @return the height of the notification + */ + public double getHeight() { + return height; + } + + /** + * Modifies the notification's level and returns itself to allow for method chaining + * + * @param level the level to set the notification to + * @return the current notification + */ + public Notification withLevel(NotificationLevel level) { + this.level = level; + return this; + } + + /** + * Modifies the notification's title and returns itself to allow for method chaining + * + * @param title the title to set the notification to + * @return the current notification + */ + public Notification withTitle(String title) { + setTitle(title); + return this; + } + + /** + * Modifies the notification's description and returns itself to allow for method chaining + * + * @param description the description to set the notification to + * @return the current notification + */ + public Notification withDescription(String description) { + setDescription(description); + return this; + } + + /** + * Modifies the notification's display time and returns itself to allow for method chaining + * + * @param seconds the number of seconds to display the notification for + * @return the current notification + */ + public Notification withDisplaySeconds(double seconds) { + return withDisplayMilliseconds((int) Math.round(seconds * 1000)); + } + + /** + * Modifies the notification's display time and returns itself to allow for method chaining + * + * @param displayTimeMillis the number of milliseconds to display the notification for + * @return the current notification + */ + public Notification withDisplayMilliseconds(int displayTimeMillis) { + setDisplayTimeMillis(displayTimeMillis); + return this; + } + + /** + * Modifies the notification's width and returns itself to allow for method chaining + * + * @param width the width to set the notification to + * @return the current notification + */ + public Notification withWidth(double width) { + setWidth(width); + return this; + } + + /** + * Modifies the notification's height and returns itself to allow for method chaining + * + * @param height the height to set the notification to + * @return the current notification + */ + public Notification withHeight(double height) { + setHeight(height); + return this; + } + + /** + * Modifies the notification's height and returns itself to allow for method chaining + * + *

This will set the height to -1 to have it automatically determined by the dashboard + * + * @return the current notification + */ + public Notification withAutomaticHeight() { + setHeight(-1); + return this; + } + + /** + * Modifies the notification to disable the auto dismiss behavior + * + *

This sets the display time to 0 milliseconds + * + *

The auto dismiss behavior can be re-enabled by setting the display time to a number + * greater than 0 + * + * @return the current notification + */ + public Notification withNoAutoDismiss() { + setDisplayTimeMillis(0); + return this; + } + } +} \ No newline at end of file From ef648054d6df9870166ee9433f74c51484a3d734 Mon Sep 17 00:00:00 2001 From: Tim <73599525+timtogan@users.noreply.github.com> Date: Sun, 7 Dec 2025 19:15:47 -0800 Subject: [PATCH 2/4] added some documentation for the elastic class --- src/main/java/org/carlmontrobotics/lib199/Elastic.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/org/carlmontrobotics/lib199/Elastic.java b/src/main/java/org/carlmontrobotics/lib199/Elastic.java index b803d10..d8d20de 100644 --- a/src/main/java/org/carlmontrobotics/lib199/Elastic.java +++ b/src/main/java/org/carlmontrobotics/lib199/Elastic.java @@ -14,6 +14,12 @@ import edu.wpi.first.networktables.PubSubOption; import edu.wpi.first.networktables.StringPublisher; import edu.wpi.first.networktables.StringTopic; +/** + * A class that provides methods for interacting with the Elastic dashboard, including sending + * notifications and selecting tabs. This taken striaght from the official Elastic documentation + * (see https://frc-elastic.gitbook.io/docs/additional-features-and-references/robot-notifications-with-elasticlib for documentation + * and for original code https://github.com/Gold872/elastic-dashboard/blob/main/elasticlib/Elastic.java) + */ public final class Elastic { private static final StringTopic notificationTopic = From c04004c1fcc642bc7b7cfbac83fbb89b12cf7dbb Mon Sep 17 00:00:00 2001 From: CoolSpy3 <55305038+CoolSpy3@users.noreply.github.com> Date: Sat, 27 Dec 2025 16:04:12 -0800 Subject: [PATCH 3/4] fix typo Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/main/java/org/carlmontrobotics/lib199/Elastic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/carlmontrobotics/lib199/Elastic.java b/src/main/java/org/carlmontrobotics/lib199/Elastic.java index d8d20de..b872ae8 100644 --- a/src/main/java/org/carlmontrobotics/lib199/Elastic.java +++ b/src/main/java/org/carlmontrobotics/lib199/Elastic.java @@ -16,7 +16,7 @@ import edu.wpi.first.networktables.StringTopic; /** * A class that provides methods for interacting with the Elastic dashboard, including sending - * notifications and selecting tabs. This taken striaght from the official Elastic documentation + * notifications and selecting tabs. This taken straight from the official Elastic documentation * (see https://frc-elastic.gitbook.io/docs/additional-features-and-references/robot-notifications-with-elasticlib for documentation * and for original code https://github.com/Gold872/elastic-dashboard/blob/main/elasticlib/Elastic.java) */ From bbe6188b048dbddfd9c86c3e09fa358fa71e0b4e Mon Sep 17 00:00:00 2001 From: Tim <73599525+timtogan@users.noreply.github.com> Date: Sat, 27 Dec 2025 16:16:22 -0800 Subject: [PATCH 4/4] moved Elastic to vendorLibs --- .../org/carlmontrobotics/lib199/{ => vendorLibs}/Elastic.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename src/main/java/org/carlmontrobotics/lib199/{ => vendorLibs}/Elastic.java (99%) diff --git a/src/main/java/org/carlmontrobotics/lib199/Elastic.java b/src/main/java/org/carlmontrobotics/lib199/vendorLibs/Elastic.java similarity index 99% rename from src/main/java/org/carlmontrobotics/lib199/Elastic.java rename to src/main/java/org/carlmontrobotics/lib199/vendorLibs/Elastic.java index b872ae8..8c8cca4 100644 --- a/src/main/java/org/carlmontrobotics/lib199/Elastic.java +++ b/src/main/java/org/carlmontrobotics/lib199/vendorLibs/Elastic.java @@ -5,7 +5,7 @@ // From: https://frc-elastic.gitbook.io/docs/additional-features-and-references/robot-notifications-with-elasticlib and https://github.com/Gold872/elastic-dashboard/blob/main/elasticlib/Elastic.java -package org.carlmontrobotics.lib199; +package org.carlmontrobotics.lib199.vendorLibs; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonProcessingException;