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 edu.wpi.first.wpilibj.simulation;
006
007import edu.wpi.first.hal.SimBoolean;
008import edu.wpi.first.hal.SimDouble;
009import edu.wpi.first.hal.SimEnum;
010import edu.wpi.first.hal.SimInt;
011import edu.wpi.first.hal.SimLong;
012import edu.wpi.first.hal.SimValue;
013import edu.wpi.first.hal.simulation.SimDeviceCallback;
014import edu.wpi.first.hal.simulation.SimDeviceDataJNI;
015import edu.wpi.first.hal.simulation.SimValueCallback;
016
017/** Class to control the simulation side of a SimDevice. */
018public class SimDeviceSim {
019  private final int m_handle;
020
021  /**
022   * Constructs a SimDeviceSim.
023   *
024   * @param name name of the SimDevice
025   */
026  public SimDeviceSim(String name) {
027    this(SimDeviceDataJNI.getSimDeviceHandle(name));
028  }
029
030  /**
031   * Constructs a SimDeviceSim.
032   *
033   * @param name name of the SimDevice
034   * @param index device index number to append to name
035   */
036  public SimDeviceSim(String name, int index) {
037    this(name + "[" + index + "]");
038  }
039
040  /**
041   * Constructs a SimDeviceSim.
042   *
043   * @param name name of the SimDevice
044   * @param index device index number to append to name
045   * @param channel device channel number to append to name
046   */
047  public SimDeviceSim(String name, int index, int channel) {
048    this(name + "[" + index + "," + channel + "]");
049  }
050
051  /**
052   * Constructs a SimDeviceSim.
053   *
054   * @param handle the low level handle for the corresponding SimDevice
055   */
056  public SimDeviceSim(int handle) {
057    m_handle = handle;
058  }
059
060  /**
061   * Get the name of this object.
062   *
063   * @return name
064   */
065  public String getName() {
066    return SimDeviceDataJNI.getSimDeviceName(m_handle);
067  }
068
069  /**
070   * Get the property object with the given name.
071   *
072   * @param name the property name
073   * @return the property object
074   */
075  public SimValue getValue(String name) {
076    int handle = SimDeviceDataJNI.getSimValueHandle(m_handle, name);
077    if (handle <= 0) {
078      return null;
079    }
080    return new SimValue(handle);
081  }
082
083  /**
084   * Get the property object with the given name.
085   *
086   * @param name the property name
087   * @return the property object
088   */
089  public SimInt getInt(String name) {
090    int handle = SimDeviceDataJNI.getSimValueHandle(m_handle, name);
091    if (handle <= 0) {
092      return null;
093    }
094    return new SimInt(handle);
095  }
096
097  /**
098   * Get the property object with the given name.
099   *
100   * @param name the property name
101   * @return the property object
102   */
103  public SimLong getLong(String name) {
104    int handle = SimDeviceDataJNI.getSimValueHandle(m_handle, name);
105    if (handle <= 0) {
106      return null;
107    }
108    return new SimLong(handle);
109  }
110
111  /**
112   * Get the property object with the given name.
113   *
114   * @param name the property name
115   * @return the property object
116   */
117  public SimDouble getDouble(String name) {
118    int handle = SimDeviceDataJNI.getSimValueHandle(m_handle, name);
119    if (handle <= 0) {
120      return null;
121    }
122    return new SimDouble(handle);
123  }
124
125  /**
126   * Get the property object with the given name.
127   *
128   * @param name the property name
129   * @return the property object
130   */
131  public SimEnum getEnum(String name) {
132    int handle = SimDeviceDataJNI.getSimValueHandle(m_handle, name);
133    if (handle <= 0) {
134      return null;
135    }
136    return new SimEnum(handle);
137  }
138
139  /**
140   * Get the property object with the given name.
141   *
142   * @param name the property name
143   * @return the property object
144   */
145  public SimBoolean getBoolean(String name) {
146    int handle = SimDeviceDataJNI.getSimValueHandle(m_handle, name);
147    if (handle <= 0) {
148      return null;
149    }
150    return new SimBoolean(handle);
151  }
152
153  /**
154   * Get all options for the given enum.
155   *
156   * @param val the enum
157   * @return names of the different values for that enum
158   */
159  public static String[] getEnumOptions(SimEnum val) {
160    return SimDeviceDataJNI.getSimValueEnumOptions(val.getNativeHandle());
161  }
162
163  /**
164   * Get all data of this object.
165   *
166   * @return all data and fields of this object
167   */
168  public SimDeviceDataJNI.SimValueInfo[] enumerateValues() {
169    return SimDeviceDataJNI.enumerateSimValues(m_handle);
170  }
171
172  /**
173   * Get the native handle of this object.
174   *
175   * @return the handle used to refer to this object through JNI
176   */
177  public int getNativeHandle() {
178    return m_handle;
179  }
180
181  /**
182   * Register a callback to be run every time a new value is added to this device.
183   *
184   * @param callback the callback
185   * @param initialNotify should the callback be run with the initial state
186   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
187   *     this object so GC doesn't cancel the callback.
188   */
189  public CallbackStore registerValueCreatedCallback(
190      SimValueCallback callback, boolean initialNotify) {
191    int uid = SimDeviceDataJNI.registerSimValueCreatedCallback(m_handle, callback, initialNotify);
192    return new CallbackStore(uid, SimDeviceDataJNI::cancelSimValueCreatedCallback);
193  }
194
195  /**
196   * Register a callback to be run every time a value is changed on this device.
197   *
198   * @param value simulated value
199   * @param callback the callback
200   * @param initialNotify should the callback be run with the initial state
201   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
202   *     this object so GC doesn't cancel the callback.
203   */
204  public CallbackStore registerValueChangedCallback(
205      SimValue value, SimValueCallback callback, boolean initialNotify) {
206    int uid =
207        SimDeviceDataJNI.registerSimValueChangedCallback(
208            value.getNativeHandle(), callback, initialNotify);
209    return new CallbackStore(uid, SimDeviceDataJNI::cancelSimValueChangedCallback);
210  }
211
212  /**
213   * Register a callback for SimDouble.reset() and similar functions. The callback is called with
214   * the old value.
215   *
216   * @param value simulated value
217   * @param callback callback
218   * @param initialNotify ignored (present for consistency)
219   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
220   *     this object so GC doesn't cancel the callback.
221   */
222  public CallbackStore registerValueResetCallback(
223      SimValue value, SimValueCallback callback, boolean initialNotify) {
224    int uid =
225        SimDeviceDataJNI.registerSimValueResetCallback(
226            value.getNativeHandle(), callback, initialNotify);
227    return new CallbackStore(uid, SimDeviceDataJNI::cancelSimValueResetCallback);
228  }
229
230  /**
231   * Get all sim devices with the given prefix.
232   *
233   * @param prefix the prefix to filter sim devices
234   * @return all sim devices
235   */
236  public static SimDeviceDataJNI.SimDeviceInfo[] enumerateDevices(String prefix) {
237    return SimDeviceDataJNI.enumerateSimDevices(prefix);
238  }
239
240  /**
241   * Register a callback to be run every time a new {@link edu.wpi.first.hal.SimDevice} is created.
242   *
243   * @param prefix the prefix to filter sim devices
244   * @param callback the callback
245   * @param initialNotify should the callback be run with the initial state
246   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
247   *     this object so GC doesn't cancel the callback.
248   */
249  public static CallbackStore registerDeviceCreatedCallback(
250      String prefix, SimDeviceCallback callback, boolean initialNotify) {
251    int uid = SimDeviceDataJNI.registerSimDeviceCreatedCallback(prefix, callback, initialNotify);
252    return new CallbackStore(uid, SimDeviceDataJNI::cancelSimDeviceCreatedCallback);
253  }
254
255  /**
256   * Register a callback to be run every time a {@link edu.wpi.first.hal.SimDevice} is
257   * freed/destroyed.
258   *
259   * @param prefix the prefix to filter sim devices
260   * @param callback the callback
261   * @param initialNotify should the callback be run with the initial state
262   * @return the {@link CallbackStore} object associated with this callback. Save a reference to
263   *     this object so GC doesn't cancel the callback.
264   */
265  public static CallbackStore registerDeviceFreedCallback(
266      String prefix, SimDeviceCallback callback, boolean initialNotify) {
267    int uid = SimDeviceDataJNI.registerSimDeviceFreedCallback(prefix, callback, initialNotify);
268    return new CallbackStore(uid, SimDeviceDataJNI::cancelSimDeviceFreedCallback);
269  }
270
271  /** Reset all SimDevice data. */
272  public static void resetData() {
273    SimDeviceDataJNI.resetSimDeviceData();
274  }
275}