001// Copyright (c) FIRST and other WPILib contributors.
002// Open Source Software; you can modify and/or share it under the terms of
003// the WPILib BSD license file in the root directory of this project.
004
005package org.wpilib.driverstation;
006
007import org.wpilib.hardware.hal.AlertJNI;
008
009/**
010 * Persistent alert to be sent via NetworkTables. Alerts are tagged with a type of {@code ERROR},
011 * {@code WARNING}, or {@code INFO} to denote urgency. See {@link
012 * org.wpilib.driverstation.Alert.Level Level} for suggested usage of each type. Alerts can be
013 * displayed on supported dashboards, and are shown in a priority order based on type and recency of
014 * activation, with newly activated alerts first.
015 *
016 * <p>Alerts should be created once and stored persistently, then updated to "active" or "inactive"
017 * as necessary. {@link #set(boolean)} can be safely called periodically.
018 *
019 * <pre>
020 * class Robot {
021 *   Alert alert = new Alert("Something went wrong", Alert.Level.WARNING);
022 *
023 *   periodic() {
024 *     alert.set(...);
025 *   }
026 * }
027 * </pre>
028 *
029 * <p>Alternatively, alerts which are only used once at startup can be created and activated inline.
030 *
031 * <pre>
032 * public Robot() {
033 *   new Alert("Failed to load auto paths", Alert.Level.ERROR).set(true);
034 * }
035 * </pre>
036 */
037public class Alert implements AutoCloseable {
038  /** Represents an alert's level of urgency. */
039  public enum Level {
040    /**
041     * High priority alert - displayed first with a red "X" symbol. Use this type for problems which
042     * will seriously affect the robot's functionality and thus require immediate attention.
043     */
044    HIGH(AlertJNI.LEVEL_HIGH),
045
046    /**
047     * Medium priority alert - displayed second with a yellow "!" symbol. Use this type for problems
048     * which could affect the robot's functionality but do not necessarily require immediate
049     * attention.
050     */
051    MEDIUM(AlertJNI.LEVEL_MEDIUM),
052
053    /**
054     * Low priority alert - displayed last with a green "i" symbol. Use this type for problems which
055     * are unlikely to affect the robot's functionality, or any other alerts which do not fall under
056     * the other categories.
057     */
058    LOW(AlertJNI.LEVEL_LOW);
059
060    /** Alternate name for a high priority alert. */
061    public static final Level ERROR = HIGH;
062
063    /** Alternate name for a medium priority alert. */
064    public static final Level WARNING = MEDIUM;
065
066    /** Alternate name for a low priority alert. */
067    public static final Level INFO = LOW;
068
069    private final int m_value;
070
071    Level(int value) {
072      m_value = value;
073    }
074  }
075
076  private final Level m_type;
077  private int m_handle;
078
079  /**
080   * Creates a new alert in the default group - "Alerts". If this is the first to be instantiated,
081   * the appropriate entries will be added to NetworkTables.
082   *
083   * @param text Text to be displayed when the alert is active.
084   * @param type Alert urgency level.
085   */
086  public Alert(String text, Level type) {
087    this("Alerts", text, type);
088  }
089
090  /**
091   * Creates a new alert. If this is the first to be instantiated in its group, the appropriate
092   * entries will be added to NetworkTables.
093   *
094   * @param group Group identifier, used as the entry name in NetworkTables.
095   * @param text Text to be displayed when the alert is active.
096   * @param type Alert urgency level.
097   */
098  public Alert(String group, String text, Level type) {
099    m_type = type;
100    m_handle = AlertJNI.createAlert(group, text, type.m_value);
101  }
102
103  /**
104   * Sets whether the alert should currently be displayed. This method can be safely called
105   * periodically.
106   *
107   * @param active Whether to display the alert.
108   */
109  public void set(boolean active) {
110    AlertJNI.setAlertActive(m_handle, active);
111  }
112
113  /**
114   * Gets whether the alert is active.
115   *
116   * @return whether the alert is active.
117   */
118  public boolean get() {
119    return AlertJNI.isAlertActive(m_handle);
120  }
121
122  /**
123   * Updates current alert text. Use this method to dynamically change the displayed alert, such as
124   * including more details about the detected problem.
125   *
126   * @param text Text to be displayed when the alert is active.
127   */
128  public void setText(String text) {
129    AlertJNI.setAlertText(m_handle, text);
130  }
131
132  /**
133   * Gets the current alert text.
134   *
135   * @return the current text.
136   */
137  public String getText() {
138    return AlertJNI.getAlertText(m_handle);
139  }
140
141  /**
142   * Get the type of this alert.
143   *
144   * @return the type
145   */
146  public Level getType() {
147    return m_type;
148  }
149
150  @Override
151  public void close() {
152    AlertJNI.destroyAlert(m_handle);
153    m_handle = 0;
154  }
155}