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.hal; 006 007/** 008 * A wrapper around a simulator device handle. 009 * 010 * <p>Teams: if you are using this class, you are likely confusing it for {@link 011 * edu.wpi.first.wpilibj.simulation.SimDeviceSim}. 012 * 013 * <p>Vendors: This class should be used from inside the device class to define the 014 * properties/fields of the device. Use {@link #create} to get a SimDevice object, then use {@link 015 * #createDouble(String, Direction, double)} or similar to define the device's fields. See {@link 016 * edu.wpi.first.wpilibj.ADXRS450_Gyro} for an example implementation. 017 */ 018public class SimDevice implements AutoCloseable { 019 /** Sim device direction. */ 020 public enum Direction { 021 /** Input direction for simulation devices. */ 022 kInput(SimDeviceJNI.kInput), 023 /** Output direction for simulation devices. */ 024 kOutput(SimDeviceJNI.kOutput), 025 /** Bidirectional direction for simulation devices. */ 026 kBidir(SimDeviceJNI.kBidir); 027 028 /** The native value of this Direction. */ 029 public final int m_value; 030 031 Direction(int value) { 032 m_value = value; 033 } 034 } 035 036 /** 037 * Creates a simulated device. 038 * 039 * <p>The device name must be unique. Returns null if the device name already exists. If multiple 040 * instances of the same device are desired, recommend appending the instance/unique identifier in 041 * brackets to the base name, e.g. "device[1]". 042 * 043 * <p>Using a device name of the form "Type:Name" will create a WebSockets node with a type value 044 * of "Type" and a device value of "Name" 045 * 046 * <p>null is returned if not in simulation. 047 * 048 * @param name device name 049 * @return simulated device object 050 */ 051 public static SimDevice create(String name) { 052 int handle = SimDeviceJNI.createSimDevice(name); 053 if (handle <= 0) { 054 return null; 055 } 056 return new SimDevice(handle); 057 } 058 059 /** 060 * Creates a simulated device. 061 * 062 * <p>The device name must be unique. Returns null if the device name already exists. This is a 063 * convenience method that appends index in brackets to the device name, e.g. passing index=1 064 * results in "device[1]" for the device name. 065 * 066 * <p>Using a device name of the form "Type:Name" will create a WebSockets node with a type value 067 * of "Type" and a device value of "Name" 068 * 069 * <p>null is returned if not in simulation. 070 * 071 * @param name device name 072 * @param index device index number to append to name 073 * @return simulated device object 074 */ 075 public static SimDevice create(String name, int index) { 076 return create(name + "[" + index + "]"); 077 } 078 079 /** 080 * Creates a simulated device. 081 * 082 * <p>The device name must be unique. Returns null if the device name already exists. This is a 083 * convenience method that appends index and channel in brackets to the device name, e.g. passing 084 * index=1 and channel=2 results in "device[1,2]" for the device name. 085 * 086 * <p>Using a device name of the form "Type:Name" will create a WebSockets node with a type value 087 * of "Type" and a device value of "Name" 088 * 089 * <p>null is returned if not in simulation. 090 * 091 * @param name device name 092 * @param index device index number to append to name 093 * @param channel device channel number to append to name 094 * @return simulated device object 095 */ 096 public static SimDevice create(String name, int index, int channel) { 097 return create(name + "[" + index + "," + channel + "]"); 098 } 099 100 /** 101 * Wraps a simulated device handle as returned by SimDeviceJNI.createSimDevice(). 102 * 103 * @param handle simulated device handle 104 */ 105 public SimDevice(int handle) { 106 m_handle = handle; 107 } 108 109 @Override 110 public void close() { 111 SimDeviceJNI.freeSimDevice(m_handle); 112 } 113 114 /** 115 * Get the internal device handle. 116 * 117 * @return internal handle 118 */ 119 public int getNativeHandle() { 120 return m_handle; 121 } 122 123 /** 124 * Get the name of the simulated device. 125 * 126 * @return the name 127 */ 128 public String getName() { 129 return SimDeviceJNI.getSimDeviceName(m_handle); 130 } 131 132 /** 133 * Creates a value on the simulated device. 134 * 135 * <p>Returns null if not in simulation. 136 * 137 * @param name value name 138 * @param direction input/output/bidir (from perspective of user code) 139 * @param initialValue initial value 140 * @return simulated value object 141 */ 142 public SimValue createValue(String name, Direction direction, HALValue initialValue) { 143 int handle = SimDeviceJNI.createSimValue(m_handle, name, direction.m_value, initialValue); 144 if (handle <= 0) { 145 return null; 146 } 147 return new SimValue(handle); 148 } 149 150 /** 151 * Creates an int value on the simulated device. 152 * 153 * <p>Returns null if not in simulation. 154 * 155 * @param name value name 156 * @param direction input/output/bidir (from perspective of user code) 157 * @param initialValue initial value 158 * @return simulated double value object 159 */ 160 public SimInt createInt(String name, Direction direction, int initialValue) { 161 int handle = SimDeviceJNI.createSimValueInt(m_handle, name, direction.m_value, initialValue); 162 if (handle <= 0) { 163 return null; 164 } 165 return new SimInt(handle); 166 } 167 168 /** 169 * Creates a long value on the simulated device. 170 * 171 * <p>Returns null if not in simulation. 172 * 173 * @param name value name 174 * @param direction input/output/bidir (from perspective of user code) 175 * @param initialValue initial value 176 * @return simulated double value object 177 */ 178 public SimLong createLong(String name, Direction direction, long initialValue) { 179 int handle = SimDeviceJNI.createSimValueLong(m_handle, name, direction.m_value, initialValue); 180 if (handle <= 0) { 181 return null; 182 } 183 return new SimLong(handle); 184 } 185 186 /** 187 * Creates a double value on the simulated device. 188 * 189 * <p>Returns null if not in simulation. 190 * 191 * @param name value name 192 * @param direction input/output/bidir (from perspective of user code) 193 * @param initialValue initial value 194 * @return simulated double value object 195 */ 196 public SimDouble createDouble(String name, Direction direction, double initialValue) { 197 int handle = SimDeviceJNI.createSimValueDouble(m_handle, name, direction.m_value, initialValue); 198 if (handle <= 0) { 199 return null; 200 } 201 return new SimDouble(handle); 202 } 203 204 /** 205 * Creates an enumerated value on the simulated device. 206 * 207 * <p>Enumerated values are always in the range 0 to numOptions-1. 208 * 209 * <p>Returns null if not in simulation. 210 * 211 * @param name value name 212 * @param direction input/output/bidir (from perspective of user code) 213 * @param options array of option descriptions 214 * @param initialValue initial value (selection) 215 * @return simulated enum value object 216 */ 217 public SimEnum createEnum(String name, Direction direction, String[] options, int initialValue) { 218 int handle = 219 SimDeviceJNI.createSimValueEnum(m_handle, name, direction.m_value, options, initialValue); 220 if (handle <= 0) { 221 return null; 222 } 223 return new SimEnum(handle); 224 } 225 226 /** 227 * Creates an enumerated value on the simulated device with double values. 228 * 229 * <p>Enumerated values are always in the range 0 to numOptions-1. 230 * 231 * <p>Returns null if not in simulation. 232 * 233 * @param name value name 234 * @param direction input/output/bidir (from perspective of user code) 235 * @param options array of option descriptions 236 * @param optionValues array of option values (must be the same size as options) 237 * @param initialValue initial value (selection) 238 * @return simulated enum value object 239 */ 240 public SimEnum createEnumDouble( 241 String name, Direction direction, String[] options, double[] optionValues, int initialValue) { 242 int handle = 243 SimDeviceJNI.createSimValueEnumDouble( 244 m_handle, name, direction.m_value, options, optionValues, initialValue); 245 if (handle <= 0) { 246 return null; 247 } 248 return new SimEnum(handle); 249 } 250 251 /** 252 * Creates a boolean value on the simulated device. 253 * 254 * <p>Returns null if not in simulation. 255 * 256 * @param name value name 257 * @param direction input/output/bidir (from perspective of user code) 258 * @param initialValue initial value 259 * @return simulated boolean value object 260 */ 261 public SimBoolean createBoolean(String name, Direction direction, boolean initialValue) { 262 int handle = 263 SimDeviceJNI.createSimValueBoolean(m_handle, name, direction.m_value, initialValue); 264 if (handle <= 0) { 265 return null; 266 } 267 return new SimBoolean(handle); 268 } 269 270 private final int m_handle; 271}