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;
006
007import edu.wpi.first.hal.FRCNetComm.tResourceType;
008import edu.wpi.first.hal.HAL;
009import edu.wpi.first.hal.PowerDistributionFaults;
010import edu.wpi.first.hal.PowerDistributionJNI;
011import edu.wpi.first.hal.PowerDistributionStickyFaults;
012import edu.wpi.first.hal.PowerDistributionVersion;
013import edu.wpi.first.util.sendable.Sendable;
014import edu.wpi.first.util.sendable.SendableBuilder;
015import edu.wpi.first.util.sendable.SendableRegistry;
016
017/**
018 * Class for getting voltage, current, temperature, power and energy from the Power Distribution
019 * Panel over CAN.
020 */
021public class PowerDistribution implements Sendable, AutoCloseable {
022  private final int m_handle;
023  private final int m_module;
024
025  public static final int kDefaultModule = PowerDistributionJNI.DEFAULT_MODULE;
026
027  public enum ModuleType {
028    kCTRE(PowerDistributionJNI.CTRE_TYPE),
029    kRev(PowerDistributionJNI.REV_TYPE);
030
031    public final int value;
032
033    ModuleType(int value) {
034      this.value = value;
035    }
036  }
037
038  /**
039   * Constructs a PowerDistribution.
040   *
041   * @param module The CAN ID of the PDP.
042   * @param moduleType Module type (CTRE or REV).
043   */
044  public PowerDistribution(int module, ModuleType moduleType) {
045    m_handle = PowerDistributionJNI.initialize(module, moduleType.value);
046    m_module = PowerDistributionJNI.getModuleNumber(m_handle);
047
048    HAL.report(tResourceType.kResourceType_PDP, m_module + 1);
049    SendableRegistry.addLW(this, "PowerDistribution", m_module);
050  }
051
052  /**
053   * Constructs a PowerDistribution.
054   *
055   * <p>Uses the default CAN ID (0 for CTRE and 1 for REV).
056   */
057  public PowerDistribution() {
058    m_handle = PowerDistributionJNI.initialize(kDefaultModule, PowerDistributionJNI.AUTOMATIC_TYPE);
059    m_module = PowerDistributionJNI.getModuleNumber(m_handle);
060
061    HAL.report(tResourceType.kResourceType_PDP, m_module + 1);
062    SendableRegistry.addLW(this, "PowerDistribution", m_module);
063  }
064
065  @Override
066  public void close() {
067    SendableRegistry.remove(this);
068  }
069
070  /**
071   * Gets the number of channel for this power distribution.
072   *
073   * @return Number of output channels.
074   */
075  public int getNumChannels() {
076    return PowerDistributionJNI.getNumChannels(m_handle);
077  }
078
079  /**
080   * Query the input voltage of the PDP.
081   *
082   * @return The voltage of the PDP in volts
083   */
084  public double getVoltage() {
085    return PowerDistributionJNI.getVoltage(m_handle);
086  }
087
088  /**
089   * Query the temperature of the PDP.
090   *
091   * @return The temperature of the PDP in degrees Celsius
092   */
093  public double getTemperature() {
094    return PowerDistributionJNI.getTemperature(m_handle);
095  }
096
097  /**
098   * Query the current of a single channel of the PDP.
099   *
100   * @param channel The PDP channel to query.
101   * @return The current of one of the PDP channels (channels 0-15) in Amperes
102   */
103  public double getCurrent(int channel) {
104    double current = PowerDistributionJNI.getChannelCurrent(m_handle, channel);
105
106    return current;
107  }
108
109  /**
110   * Query the current of all monitored PDP channels (0-15).
111   *
112   * @return The current of all the channels in Amperes
113   */
114  public double getTotalCurrent() {
115    return PowerDistributionJNI.getTotalCurrent(m_handle);
116  }
117
118  /**
119   * Query the total power drawn from the monitored PDP channels.
120   *
121   * @return the total power in Watts
122   */
123  public double getTotalPower() {
124    return PowerDistributionJNI.getTotalPower(m_handle);
125  }
126
127  /**
128   * Query the total energy drawn from the monitored PDP channels.
129   *
130   * @return the total energy in Joules
131   */
132  public double getTotalEnergy() {
133    return PowerDistributionJNI.getTotalEnergy(m_handle);
134  }
135
136  /** Reset the total energy to 0. */
137  public void resetTotalEnergy() {
138    PowerDistributionJNI.resetTotalEnergy(m_handle);
139  }
140
141  /** Clear all PDP sticky faults. */
142  public void clearStickyFaults() {
143    PowerDistributionJNI.clearStickyFaults(m_handle);
144  }
145
146  /**
147   * Gets module number (CAN ID).
148   *
149   * @return The module number (CAN ID).
150   */
151  public int getModule() {
152    return m_module;
153  }
154
155  public boolean getSwitchableChannel() {
156    return PowerDistributionJNI.getSwitchableChannel(m_handle);
157  }
158
159  public void setSwitchableChannel(boolean enabled) {
160    PowerDistributionJNI.setSwitchableChannel(m_handle, enabled);
161  }
162
163  PowerDistributionVersion getVersion() {
164    return PowerDistributionJNI.getVersion(m_handle);
165  }
166
167  PowerDistributionFaults getFaults() {
168    return PowerDistributionJNI.getFaults(m_handle);
169  }
170
171  PowerDistributionStickyFaults getStickyFaults() {
172    return PowerDistributionJNI.getStickyFaults(m_handle);
173  }
174
175  @Override
176  public void initSendable(SendableBuilder builder) {
177    builder.setSmartDashboardType("PowerDistribution");
178    int numChannels = getNumChannels();
179    for (int i = 0; i < numChannels; ++i) {
180      final int chan = i;
181      builder.addDoubleProperty(
182          "Chan" + i, () -> PowerDistributionJNI.getChannelCurrentNoError(m_handle, chan), null);
183    }
184    builder.addDoubleProperty(
185        "Voltage", () -> PowerDistributionJNI.getVoltageNoError(m_handle), null);
186    builder.addDoubleProperty(
187        "TotalCurrent", () -> PowerDistributionJNI.getTotalCurrent(m_handle), null);
188    builder.addBooleanProperty(
189        "SwitchableChannel",
190        () -> PowerDistributionJNI.getSwitchableChannelNoError(m_handle),
191        value -> PowerDistributionJNI.setSwitchableChannel(m_handle, value));
192  }
193}