1+ // Copyright (c) 2023-2025 Gold87 and other Elastic contributors
2+ // This software can be modified and/or shared under the terms
3+ // defined by the Elastic license:
4+ // https://github.com/Gold872/elastic-dashboard/blob/main/LICENSE
5+
6+ // 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
7+
8+ package org .carlmontrobotics .lib199 ;
9+
10+ import com .fasterxml .jackson .annotation .JsonProperty ;
11+ import com .fasterxml .jackson .core .JsonProcessingException ;
12+ import com .fasterxml .jackson .databind .ObjectMapper ;
13+ import edu .wpi .first .networktables .NetworkTableInstance ;
14+ import edu .wpi .first .networktables .PubSubOption ;
15+ import edu .wpi .first .networktables .StringPublisher ;
16+ import edu .wpi .first .networktables .StringTopic ;
17+
18+ public final class Elastic {
19+ private static final StringTopic notificationTopic =
20+ NetworkTableInstance .getDefault ().getStringTopic ("/Elastic/RobotNotifications" );
21+ private static final StringPublisher notificationPublisher =
22+ notificationTopic .publish (PubSubOption .sendAll (true ), PubSubOption .keepDuplicates (true ));
23+ private static final StringTopic selectedTabTopic =
24+ NetworkTableInstance .getDefault ().getStringTopic ("/Elastic/SelectedTab" );
25+ private static final StringPublisher selectedTabPublisher =
26+ selectedTabTopic .publish (PubSubOption .keepDuplicates (true ));
27+ private static final ObjectMapper objectMapper = new ObjectMapper ();
28+
29+ /**
30+ * Represents the possible levels of notifications for the Elastic dashboard. These levels are
31+ * used to indicate the severity or type of notification.
32+ */
33+ public enum NotificationLevel {
34+ /** Informational Message */
35+ INFO ,
36+ /** Warning message */
37+ WARNING ,
38+ /** Error message */
39+ ERROR
40+ }
41+
42+ /**
43+ * Sends an notification to the Elastic dashboard. The notification is serialized as a JSON string
44+ * before being published.
45+ *
46+ * @param notification the {@link Notification} object containing notification details
47+ */
48+ public static void sendNotification (Notification notification ) {
49+ try {
50+ notificationPublisher .set (objectMapper .writeValueAsString (notification ));
51+ } catch (JsonProcessingException e ) {
52+ e .printStackTrace ();
53+ }
54+ }
55+
56+ /**
57+ * Selects the tab of the dashboard with the given name. If no tab matches the name, this will
58+ * have no effect on the widgets or tabs in view.
59+ *
60+ * <p>If the given name is a number, Elastic will select the tab whose index equals the number
61+ * provided.
62+ *
63+ * @param tabName the name of the tab to select
64+ */
65+ public static void selectTab (String tabName ) {
66+ selectedTabPublisher .set (tabName );
67+ }
68+
69+ /**
70+ * Selects the tab of the dashboard at the given index. If this index is greater than or equal to
71+ * the number of tabs, this will have no effect.
72+ *
73+ * @param tabIndex the index of the tab to select.
74+ */
75+ public static void selectTab (int tabIndex ) {
76+ selectTab (Integer .toString (tabIndex ));
77+ }
78+
79+ /**
80+ * Represents an notification object to be sent to the Elastic dashboard. This object holds
81+ * properties such as level, title, description, display time, and dimensions to control how the
82+ * notification is displayed on the dashboard.
83+ */
84+ public static class Notification {
85+ @ JsonProperty ("level" )
86+ private NotificationLevel level ;
87+
88+ @ JsonProperty ("title" )
89+ private String title ;
90+
91+ @ JsonProperty ("description" )
92+ private String description ;
93+
94+ @ JsonProperty ("displayTime" )
95+ private int displayTimeMillis ;
96+
97+ @ JsonProperty ("width" )
98+ private double width ;
99+
100+ @ JsonProperty ("height" )
101+ private double height ;
102+
103+ /**
104+ * Creates a new Notification with all default parameters. This constructor is intended to be
105+ * used with the chainable decorator methods
106+ *
107+ * <p>Title and description fields are empty.
108+ */
109+ public Notification () {
110+ this (NotificationLevel .INFO , "" , "" );
111+ }
112+
113+ /**
114+ * Creates a new Notification with all properties specified.
115+ *
116+ * @param level the level of the notification (e.g., INFO, WARNING, ERROR)
117+ * @param title the title text of the notification
118+ * @param description the descriptive text of the notification
119+ * @param displayTimeMillis the time in milliseconds for which the notification is displayed
120+ * @param width the width of the notification display area
121+ * @param height the height of the notification display area, inferred if below zero
122+ */
123+ public Notification (
124+ NotificationLevel level ,
125+ String title ,
126+ String description ,
127+ int displayTimeMillis ,
128+ double width ,
129+ double height ) {
130+ this .level = level ;
131+ this .title = title ;
132+ this .displayTimeMillis = displayTimeMillis ;
133+ this .description = description ;
134+ this .height = height ;
135+ this .width = width ;
136+ }
137+
138+ /**
139+ * Creates a new Notification with default display time and dimensions.
140+ *
141+ * @param level the level of the notification
142+ * @param title the title text of the notification
143+ * @param description the descriptive text of the notification
144+ */
145+ public Notification (NotificationLevel level , String title , String description ) {
146+ this (level , title , description , 3000 , 350 , -1 );
147+ }
148+
149+ /**
150+ * Creates a new Notification with a specified display time and default dimensions.
151+ *
152+ * @param level the level of the notification
153+ * @param title the title text of the notification
154+ * @param description the descriptive text of the notification
155+ * @param displayTimeMillis the display time in milliseconds
156+ */
157+ public Notification (
158+ NotificationLevel level , String title , String description , int displayTimeMillis ) {
159+ this (level , title , description , displayTimeMillis , 350 , -1 );
160+ }
161+
162+ /**
163+ * Creates a new Notification with specified dimensions and default display time. If the height
164+ * is below zero, it is automatically inferred based on screen size.
165+ *
166+ * @param level the level of the notification
167+ * @param title the title text of the notification
168+ * @param description the descriptive text of the notification
169+ * @param width the width of the notification display area
170+ * @param height the height of the notification display area, inferred if below zero
171+ */
172+ public Notification (
173+ NotificationLevel level , String title , String description , double width , double height ) {
174+ this (level , title , description , 3000 , width , height );
175+ }
176+
177+ /**
178+ * Updates the level of this notification
179+ *
180+ * @param level the level to set the notification to
181+ */
182+ public void setLevel (NotificationLevel level ) {
183+ this .level = level ;
184+ }
185+
186+ /**
187+ * @return the level of this notification
188+ */
189+ public NotificationLevel getLevel () {
190+ return level ;
191+ }
192+
193+ /**
194+ * Updates the title of this notification
195+ *
196+ * @param title the title to set the notification to
197+ */
198+ public void setTitle (String title ) {
199+ this .title = title ;
200+ }
201+
202+ /**
203+ * Gets the title of this notification
204+ *
205+ * @return the title of this notification
206+ */
207+ public String getTitle () {
208+ return title ;
209+ }
210+
211+ /**
212+ * Updates the description of this notification
213+ *
214+ * @param description the description to set the notification to
215+ */
216+ public void setDescription (String description ) {
217+ this .description = description ;
218+ }
219+
220+ public String getDescription () {
221+ return description ;
222+ }
223+
224+ /**
225+ * Updates the display time of the notification
226+ *
227+ * @param seconds the number of seconds to display the notification for
228+ */
229+ public void setDisplayTimeSeconds (double seconds ) {
230+ setDisplayTimeMillis ((int ) Math .round (seconds * 1000 ));
231+ }
232+
233+ /**
234+ * Updates the display time of the notification in milliseconds
235+ *
236+ * @param displayTimeMillis the number of milliseconds to display the notification for
237+ */
238+ public void setDisplayTimeMillis (int displayTimeMillis ) {
239+ this .displayTimeMillis = displayTimeMillis ;
240+ }
241+
242+ /**
243+ * Gets the display time of the notification in milliseconds
244+ *
245+ * @return the number of milliseconds the notification is displayed for
246+ */
247+ public int getDisplayTimeMillis () {
248+ return displayTimeMillis ;
249+ }
250+
251+ /**
252+ * Updates the width of the notification
253+ *
254+ * @param width the width to set the notification to
255+ */
256+ public void setWidth (double width ) {
257+ this .width = width ;
258+ }
259+
260+ /**
261+ * Gets the width of the notification
262+ *
263+ * @return the width of the notification
264+ */
265+ public double getWidth () {
266+ return width ;
267+ }
268+
269+ /**
270+ * Updates the height of the notification
271+ *
272+ * <p>If the height is set to -1, the height will be determined automatically by the dashboard
273+ *
274+ * @param height the height to set the notification to
275+ */
276+ public void setHeight (double height ) {
277+ this .height = height ;
278+ }
279+
280+ /**
281+ * Gets the height of the notification
282+ *
283+ * @return the height of the notification
284+ */
285+ public double getHeight () {
286+ return height ;
287+ }
288+
289+ /**
290+ * Modifies the notification's level and returns itself to allow for method chaining
291+ *
292+ * @param level the level to set the notification to
293+ * @return the current notification
294+ */
295+ public Notification withLevel (NotificationLevel level ) {
296+ this .level = level ;
297+ return this ;
298+ }
299+
300+ /**
301+ * Modifies the notification's title and returns itself to allow for method chaining
302+ *
303+ * @param title the title to set the notification to
304+ * @return the current notification
305+ */
306+ public Notification withTitle (String title ) {
307+ setTitle (title );
308+ return this ;
309+ }
310+
311+ /**
312+ * Modifies the notification's description and returns itself to allow for method chaining
313+ *
314+ * @param description the description to set the notification to
315+ * @return the current notification
316+ */
317+ public Notification withDescription (String description ) {
318+ setDescription (description );
319+ return this ;
320+ }
321+
322+ /**
323+ * Modifies the notification's display time and returns itself to allow for method chaining
324+ *
325+ * @param seconds the number of seconds to display the notification for
326+ * @return the current notification
327+ */
328+ public Notification withDisplaySeconds (double seconds ) {
329+ return withDisplayMilliseconds ((int ) Math .round (seconds * 1000 ));
330+ }
331+
332+ /**
333+ * Modifies the notification's display time and returns itself to allow for method chaining
334+ *
335+ * @param displayTimeMillis the number of milliseconds to display the notification for
336+ * @return the current notification
337+ */
338+ public Notification withDisplayMilliseconds (int displayTimeMillis ) {
339+ setDisplayTimeMillis (displayTimeMillis );
340+ return this ;
341+ }
342+
343+ /**
344+ * Modifies the notification's width and returns itself to allow for method chaining
345+ *
346+ * @param width the width to set the notification to
347+ * @return the current notification
348+ */
349+ public Notification withWidth (double width ) {
350+ setWidth (width );
351+ return this ;
352+ }
353+
354+ /**
355+ * Modifies the notification's height and returns itself to allow for method chaining
356+ *
357+ * @param height the height to set the notification to
358+ * @return the current notification
359+ */
360+ public Notification withHeight (double height ) {
361+ setHeight (height );
362+ return this ;
363+ }
364+
365+ /**
366+ * Modifies the notification's height and returns itself to allow for method chaining
367+ *
368+ * <p>This will set the height to -1 to have it automatically determined by the dashboard
369+ *
370+ * @return the current notification
371+ */
372+ public Notification withAutomaticHeight () {
373+ setHeight (-1 );
374+ return this ;
375+ }
376+
377+ /**
378+ * Modifies the notification to disable the auto dismiss behavior
379+ *
380+ * <p>This sets the display time to 0 milliseconds
381+ *
382+ * <p>The auto dismiss behavior can be re-enabled by setting the display time to a number
383+ * greater than 0
384+ *
385+ * @return the current notification
386+ */
387+ public Notification withNoAutoDismiss () {
388+ setDisplayTimeMillis (0 );
389+ return this ;
390+ }
391+ }
392+ }
0 commit comments