001/*----------------------------------------------------------------------------*/
002/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
003/* Open Source Software - may be modified and shared by FRC teams. The code   */
004/* must be accompanied by the FIRST BSD license file in the root directory of */
005/* the project.                                                               */
006/*----------------------------------------------------------------------------*/
007
008package edu.wpi.first.wpilibj.smartdashboard;
009
010import java.nio.ByteBuffer;
011import java.util.HashMap;
012import java.util.Map;
013import java.util.Set;
014
015import edu.wpi.first.networktables.NetworkTable;
016import edu.wpi.first.networktables.NetworkTableEntry;
017import edu.wpi.first.networktables.NetworkTableInstance;
018import edu.wpi.first.wpilibj.HLUsageReporting;
019import edu.wpi.first.wpilibj.Sendable;
020
021/**
022 * The {@link SmartDashboard} class is the bridge between robot programs and the SmartDashboard on
023 * the laptop.
024 *
025 * <p>When a value is put into the SmartDashboard here, it pops up on the SmartDashboard on the
026 * laptop. Users can put values into and get values from the SmartDashboard.
027 */
028public class SmartDashboard {
029  /**
030   * The {@link NetworkTable} used by {@link SmartDashboard}.
031   */
032  private static final NetworkTable table =
033      NetworkTableInstance.getDefault().getTable("SmartDashboard");
034
035  private static class Data {
036    Data(Sendable sendable) {
037      m_sendable = sendable;
038    }
039
040    final Sendable m_sendable;
041    final SendableBuilderImpl m_builder = new SendableBuilderImpl();
042  }
043
044  /**
045   * A table linking tables in the SmartDashboard to the {@link Sendable} objects they
046   * came from.
047   */
048  private static final Map<String, Data> tablesToData = new HashMap<>();
049
050  static {
051    HLUsageReporting.reportSmartDashboard();
052  }
053
054  /**
055   * Maps the specified key to the specified value in this table. The key can not be null. The value
056   * can be retrieved by calling the get method with a key that is equal to the original key.
057   *
058   * @param key  the key
059   * @param data the value
060   * @throws IllegalArgumentException If key is null
061   */
062  public static synchronized void putData(String key, Sendable data) {
063    Data sddata = tablesToData.get(key);
064    if (sddata == null || sddata.m_sendable != data) {
065      if (sddata != null) {
066        sddata.m_builder.stopListeners();
067      }
068      sddata = new Data(data);
069      tablesToData.put(key, sddata);
070      NetworkTable dataTable = table.getSubTable(key);
071      sddata.m_builder.setTable(dataTable);
072      data.initSendable(sddata.m_builder);
073      sddata.m_builder.updateTable();
074      sddata.m_builder.startListeners();
075      dataTable.getEntry(".name").setString(key);
076    }
077  }
078
079  /**
080   * Maps the specified key (where the key is the name of the {@link NamedSendable}
081   * to the specified value in this table. The value can be retrieved by
082   * calling the get method with a key that is equal to the original key.
083   *
084   * @param value the value
085   * @throws IllegalArgumentException If key is null
086   */
087  public static void putData(Sendable value) {
088    putData(value.getName(), value);
089  }
090
091  /**
092   * Returns the value at the specified key.
093   *
094   * @param key the key
095   * @return the value
096   * @throws IllegalArgumentException  if the key is null
097   */
098  public static synchronized Sendable getData(String key) {
099    Data data = tablesToData.get(key);
100    if (data == null) {
101      throw new IllegalArgumentException("SmartDashboard data does not exist: " + key);
102    } else {
103      return data.m_sendable;
104    }
105  }
106
107  /**
108   * Gets the entry for the specified key.
109   * @param key the key name
110   * @return Network table entry.
111   */
112  public static NetworkTableEntry getEntry(String key) {
113    return table.getEntry(key);
114  }
115
116  /**
117   * Checks the table and tells if it contains the specified key.
118   *
119   * @param key the key to search for
120   * @return true if the table as a value assigned to the given key
121   */
122  public static boolean containsKey(String key) {
123    return table.containsKey(key);
124  }
125
126  /**
127   * Get the keys stored in the SmartDashboard table of NetworkTables.
128   *
129   * @param types bitmask of types; 0 is treated as a "don't care".
130   * @return keys currently in the table
131   */
132  public static Set<String> getKeys(int types) {
133    return table.getKeys(types);
134  }
135
136  /**
137   * Get the keys stored in the SmartDashboard table of NetworkTables.
138   *
139   * @return keys currently in the table.
140   */
141  public static Set<String> getKeys() {
142    return table.getKeys();
143  }
144
145  /**
146   * Makes a key's value persistent through program restarts.
147   * The key cannot be null.
148   *
149   * @param key the key name
150   */
151  public static void setPersistent(String key) {
152    getEntry(key).setPersistent();
153  }
154
155  /**
156   * Stop making a key's value persistent through program restarts.
157   * The key cannot be null.
158   *
159   * @param key the key name
160   */
161  public static void clearPersistent(String key) {
162    getEntry(key).clearPersistent();
163  }
164
165  /**
166   * Returns whether the value is persistent through program restarts.
167   * The key cannot be null.
168   *
169   * @param key the key name
170   * @return True if the value is persistent.
171   */
172  public static boolean isPersistent(String key) {
173    return getEntry(key).isPersistent();
174  }
175
176  /**
177   * Sets flags on the specified key in this table. The key can
178   * not be null.
179   *
180   * @param key the key name
181   * @param flags the flags to set (bitmask)
182   */
183  public static void setFlags(String key, int flags) {
184    getEntry(key).setFlags(flags);
185  }
186
187  /**
188   * Clears flags on the specified key in this table. The key can
189   * not be null.
190   *
191   * @param key the key name
192   * @param flags the flags to clear (bitmask)
193   */
194  public static void clearFlags(String key, int flags) {
195    getEntry(key).clearFlags(flags);
196  }
197
198  /**
199   * Returns the flags for the specified key.
200   *
201   * @param key the key name
202   * @return the flags, or 0 if the key is not defined
203   */
204  public static int getFlags(String key) {
205    return getEntry(key).getFlags();
206  }
207
208  /**
209   * Deletes the specified key in this table. The key can
210   * not be null.
211   *
212   * @param key the key name
213   */
214  public static void delete(String key) {
215    table.delete(key);
216  }
217
218  /**
219   * Put a boolean in the table.
220   * @param key the key to be assigned to
221   * @param value the value that will be assigned
222   * @return False if the table key already exists with a different type
223   */
224  public static boolean putBoolean(String key, boolean value) {
225    return getEntry(key).setBoolean(value);
226  }
227
228  /**
229   * Gets the current value in the table, setting it if it does not exist.
230   * @param key the key
231   * @param defaultValue the default value to set if key does not exist.
232   * @return False if the table key exists with a different type
233   */
234  public static boolean setDefaultBoolean(String key, boolean defaultValue) {
235    return getEntry(key).setDefaultBoolean(defaultValue);
236  }
237
238  /**
239   * Returns the boolean the key maps to. If the key does not exist or is of
240   *     different type, it will return the default value.
241   * @param key the key to look up
242   * @param defaultValue the value to be returned if no value is found
243   * @return the value associated with the given key or the given default value
244   *     if there is no value associated with the key
245   */
246  public static boolean getBoolean(String key, boolean defaultValue) {
247    return getEntry(key).getBoolean(defaultValue);
248  }
249
250  /**
251   * Put a number in the table.
252   * @param key the key to be assigned to
253   * @param value the value that will be assigned
254   * @return False if the table key already exists with a different type
255   */
256  public static boolean putNumber(String key, double value) {
257    return getEntry(key).setDouble(value);
258  }
259
260  /**
261   * Gets the current value in the table, setting it if it does not exist.
262   * @param key the key
263   * @param defaultValue the default value to set if key does not exist.
264   * @return False if the table key exists with a different type
265   */
266  public static boolean setDefaultNumber(String key, double defaultValue) {
267    return getEntry(key).setDefaultDouble(defaultValue);
268  }
269
270  /**
271   * Returns the number the key maps to. If the key does not exist or is of
272   *     different type, it will return the default value.
273   * @param key the key to look up
274   * @param defaultValue the value to be returned if no value is found
275   * @return the value associated with the given key or the given default value
276   *     if there is no value associated with the key
277   */
278  public static double getNumber(String key, double defaultValue) {
279    return getEntry(key).getDouble(defaultValue);
280  }
281
282  /**
283   * Put a string in the table.
284   * @param key the key to be assigned to
285   * @param value the value that will be assigned
286   * @return False if the table key already exists with a different type
287   */
288  public static boolean putString(String key, String value) {
289    return getEntry(key).setString(value);
290  }
291
292  /**
293   * Gets the current value in the table, setting it if it does not exist.
294   * @param key the key
295   * @param defaultValue the default value to set if key does not exist.
296   * @return False if the table key exists with a different type
297   */
298  public static boolean setDefaultString(String key, String defaultValue) {
299    return getEntry(key).setDefaultString(defaultValue);
300  }
301
302  /**
303   * Returns the string the key maps to. If the key does not exist or is of
304   *     different type, it will return the default value.
305   * @param key the key to look up
306   * @param defaultValue the value to be returned if no value is found
307   * @return the value associated with the given key or the given default value
308   *     if there is no value associated with the key
309   */
310  public static String getString(String key, String defaultValue) {
311    return getEntry(key).getString(defaultValue);
312  }
313
314  /**
315   * Put a boolean array in the table.
316   * @param key the key to be assigned to
317   * @param value the value that will be assigned
318   * @return False if the table key already exists with a different type
319   */
320  public static boolean putBooleanArray(String key, boolean[] value) {
321    return getEntry(key).setBooleanArray(value);
322  }
323
324  /**
325   * Put a boolean array in the table.
326   * @param key the key to be assigned to
327   * @param value the value that will be assigned
328   * @return False if the table key already exists with a different type
329   */
330  public static boolean putBooleanArray(String key, Boolean[] value) {
331    return getEntry(key).setBooleanArray(value);
332  }
333
334  /**
335   * Gets the current value in the table, setting it if it does not exist.
336   * @param key the key
337   * @param defaultValue the default value to set if key does not exist.
338   * @return False if the table key exists with a different type
339   */
340  public static boolean setDefaultBooleanArray(String key, boolean[] defaultValue) {
341    return getEntry(key).setDefaultBooleanArray(defaultValue);
342  }
343
344  /**
345   * Gets the current value in the table, setting it if it does not exist.
346   * @param key the key
347   * @param defaultValue the default value to set if key does not exist.
348   * @return False if the table key exists with a different type
349   */
350  public static boolean setDefaultBooleanArray(String key, Boolean[] defaultValue) {
351    return getEntry(key).setDefaultBooleanArray(defaultValue);
352  }
353
354  /**
355   * Returns the boolean array the key maps to. If the key does not exist or is
356   *     of different type, it will return the default value.
357   * @param key the key to look up
358   * @param defaultValue the value to be returned if no value is found
359   * @return the value associated with the given key or the given default value
360   *     if there is no value associated with the key
361   */
362  public static boolean[] getBooleanArray(String key, boolean[] defaultValue) {
363    return getEntry(key).getBooleanArray(defaultValue);
364  }
365
366  /**
367   * Returns the boolean array the key maps to. If the key does not exist or is
368   *     of different type, it will return the default value.
369   * @param key the key to look up
370   * @param defaultValue the value to be returned if no value is found
371   * @return the value associated with the given key or the given default value
372   *     if there is no value associated with the key
373   */
374  public static Boolean[] getBooleanArray(String key, Boolean[] defaultValue) {
375    return getEntry(key).getBooleanArray(defaultValue);
376  }
377
378  /**
379   * Put a number array in the table.
380   * @param key the key to be assigned to
381   * @param value the value that will be assigned
382   * @return False if the table key already exists with a different type
383   */
384  public static boolean putNumberArray(String key, double[] value) {
385    return getEntry(key).setDoubleArray(value);
386  }
387
388  /**
389   * Put a number array in the table.
390   * @param key the key to be assigned to
391   * @param value the value that will be assigned
392   * @return False if the table key already exists with a different type
393   */
394  public static boolean putNumberArray(String key, Double[] value) {
395    return getEntry(key).setNumberArray(value);
396  }
397
398  /**
399   * Gets the current value in the table, setting it if it does not exist.
400   * @param key the key
401   * @param defaultValue the default value to set if key does not exist.
402   * @return False if the table key exists with a different type
403   */
404  public static boolean setDefaultNumberArray(String key, double[] defaultValue) {
405    return getEntry(key).setDefaultDoubleArray(defaultValue);
406  }
407
408  /**
409   * Gets the current value in the table, setting it if it does not exist.
410   * @param key the key
411   * @param defaultValue the default value to set if key does not exist.
412   * @return False if the table key exists with a different type
413   */
414  public static boolean setDefaultNumberArray(String key, Double[] defaultValue) {
415    return getEntry(key).setDefaultNumberArray(defaultValue);
416  }
417
418  /**
419   * Returns the number array the key maps to. If the key does not exist or is
420   *     of different type, it will return the default value.
421   * @param key the key to look up
422   * @param defaultValue the value to be returned if no value is found
423   * @return the value associated with the given key or the given default value
424   *     if there is no value associated with the key
425   */
426  public static double[] getNumberArray(String key, double[] defaultValue) {
427    return getEntry(key).getDoubleArray(defaultValue);
428  }
429
430  /**
431   * Returns the number array the key maps to. If the key does not exist or is
432   *     of different type, it will return the default value.
433   * @param key the key to look up
434   * @param defaultValue the value to be returned if no value is found
435   * @return the value associated with the given key or the given default value
436   *     if there is no value associated with the key
437   */
438  public static Double[] getNumberArray(String key, Double[] defaultValue) {
439    return getEntry(key).getDoubleArray(defaultValue);
440  }
441
442  /**
443   * Put a string array in the table.
444   * @param key the key to be assigned to
445   * @param value the value that will be assigned
446   * @return False if the table key already exists with a different type
447   */
448  public static boolean putStringArray(String key, String[] value) {
449    return getEntry(key).setStringArray(value);
450  }
451
452  /**
453   * Gets the current value in the table, setting it if it does not exist.
454   * @param key the key
455   * @param defaultValue the default value to set if key does not exist.
456   * @return False if the table key exists with a different type
457   */
458  public static boolean setDefaultStringArray(String key, String[] defaultValue) {
459    return getEntry(key).setDefaultStringArray(defaultValue);
460  }
461
462  /**
463   * Returns the string array the key maps to. If the key does not exist or is
464   *     of different type, it will return the default value.
465   * @param key the key to look up
466   * @param defaultValue the value to be returned if no value is found
467   * @return the value associated with the given key or the given default value
468   *     if there is no value associated with the key
469   */
470  public static String[] getStringArray(String key, String[] defaultValue) {
471    return getEntry(key).getStringArray(defaultValue);
472  }
473
474  /**
475   * Put a raw value (byte array) in the table.
476   * @param key the key to be assigned to
477   * @param value the value that will be assigned
478   * @return False if the table key already exists with a different type
479   */
480  public static boolean putRaw(String key, byte[] value) {
481    return getEntry(key).setRaw(value);
482  }
483
484  /**
485   * Put a raw value (bytes from a byte buffer) in the table.
486   * @param key the key to be assigned to
487   * @param value the value that will be assigned
488   * @param len the length of the value
489   * @return False if the table key already exists with a different type
490   */
491  public static boolean putRaw(String key, ByteBuffer value, int len) {
492    return getEntry(key).setRaw(value, len);
493  }
494
495  /**
496   * Gets the current value in the table, setting it if it does not exist.
497   * @param key the key
498   * @param defaultValue the default value to set if key does not exist.
499   * @return False if the table key exists with a different type
500   */
501  public static boolean setDefaultRaw(String key, byte[] defaultValue) {
502    return getEntry(key).setDefaultRaw(defaultValue);
503  }
504
505  /**
506   * Returns the raw value (byte array) the key maps to. If the key does not
507   *     exist or is of different type, it will return the default value.
508   * @param key the key to look up
509   * @param defaultValue the value to be returned if no value is found
510   * @return the value associated with the given key or the given default value
511   *     if there is no value associated with the key
512   */
513  public static byte[] getRaw(String key, byte[] defaultValue) {
514    return getEntry(key).getRaw(defaultValue);
515  }
516
517  /**
518   * Puts all sendable data to the dashboard.
519   */
520  public static synchronized void updateValues() {
521    for (Data data : tablesToData.values()) {
522      data.m_builder.updateTable();
523    }
524  }
525}