001/* 002 * Copyright (C) Cross The Road Electronics. All rights reserved. 003 * License information can be found in CTRE_LICENSE.txt 004 * For support and suggestions contact support@ctr-electronics.com or file 005 * an issue tracker at https://github.com/CrossTheRoadElec/Phoenix-Releases 006 */ 007package com.ctre.phoenix6; 008 009import com.ctre.phoenix6.jni.CANBusJNI; 010 011/** 012 * Class for getting information about an available CAN bus. 013 */ 014public class CANBus { 015 /** 016 * Contains status information about a CAN bus. 017 */ 018 public static class CANBusStatus { 019 /** 020 * Status code response of getting the data 021 */ 022 public StatusCode Status; 023 024 /** 025 * CAN bus utilization, from 0.0 to 1.0 026 */ 027 public float BusUtilization; 028 /** 029 * Bus off count 030 */ 031 public int BusOffCount; 032 /** 033 * Transmit buffer full count 034 */ 035 public int TxFullCount; 036 /** 037 * Receive Error Counter (REC) 038 */ 039 public int REC; 040 /** 041 * Transmit Error Counter (TEC) 042 */ 043 public int TEC; 044 } 045 046 private final String _name; 047 private final CANBusStatus _status = new CANBusStatus(); 048 private final CANBusJNI _jni = new CANBusJNI(); 049 050 /** 051 * Creates a new CAN bus with the given name. 052 * 053 * @param canbus Name of the CAN bus. Possible CAN bus strings are: 054 * <ul> 055 * <li>"rio" for the native roboRIO CAN bus 056 * <li>CANivore name or serial number 057 * <li>SocketCAN interface (non-FRC Linux only) 058 * <li>"*" for any CANivore seen by the program 059 * <li>empty string (default) to select the default for the system: 060 * <ul> 061 * <li>"rio" on roboRIO 062 * <li>"can0" on Linux 063 * <li>"*" on Windows 064 * </ul> 065 * </ul> 066 */ 067 public CANBus(String canbus) { 068 _name = canbus; 069 } 070 071 /** 072 * Creates a new CAN bus using the default for the system: 073 * <ul> 074 * <li>"rio" on roboRIO 075 * <li>"can0" on Linux 076 * <li>"*" on Windows 077 * </ul> 078 */ 079 public CANBus() { 080 this(""); 081 } 082 083 /** 084 * Creates a new CAN bus with the given name, and loads an associated 085 * hoot file for replay (equivalent to {@link HootReplay#loadFile}). 086 * <p> 087 * Only one hoot log may be replayed at a time. As a result, only one 088 * CAN bus should be constructed with a hoot file. 089 * <p> 090 * When using relative paths, the file path is typically relative 091 * to the top-level folder of the robot project. 092 * 093 * @param canbus Name of the CAN bus. Possible CAN bus strings are: 094 * <ul> 095 * <li>"rio" for the native roboRIO CAN bus 096 * <li>CANivore name or serial number 097 * <li>SocketCAN interface (non-FRC Linux only) 098 * <li>"*" for any CANivore seen by the program 099 * <li>empty string (default) to select the default for the system: 100 * <ul> 101 * <li>"rio" on roboRIO 102 * <li>"can0" on Linux 103 * <li>"*" on Windows 104 * </ul> 105 * </ul> 106 * @param hootFilepath Path and name of the hoot file to load 107 */ 108 public CANBus(String canbus, String hootFilepath) { 109 this(canbus); 110 HootReplay.loadFile(hootFilepath); 111 } 112 113 /** 114 * Get the name used to construct this CAN bus. 115 * 116 * @return Name of the CAN bus 117 */ 118 public String getName() { 119 return _name; 120 } 121 122 /** 123 * Gets whether the network is CAN FD. 124 * 125 * @return True if the network is CAN FD 126 */ 127 public boolean isNetworkFD() { 128 return CANBusJNI.JNI_IsNetworkFD(_name); 129 } 130 131 /** 132 * Gets the status of the CAN bus, including the 133 * bus utilization and the error counters. 134 * <p> 135 * This can block for up to 0.001 seconds (1 ms). 136 * <p> 137 * This function refreshes and returns a cached object. 138 * 139 * @return Status of the CAN bus 140 */ 141 public CANBusStatus getStatus() { 142 var err = _jni.JNI_GetStatus(_name); 143 144 _status.BusUtilization = _jni.busUtilization; 145 _status.BusOffCount = _jni.busOffCount; 146 _status.TxFullCount = _jni.txFullCount; 147 _status.REC = _jni.rec; 148 _status.TEC = _jni.tec; 149 150 if (err != 0) { 151 _status.Status = StatusCode.InvalidNetwork; 152 } else { 153 _status.Status = StatusCode.OK; 154 } 155 return _status; 156 } 157 158 /** 159 * Gets whether the network is CAN FD. 160 * 161 * @deprecated The CANBus static methods are deprecated 162 * for removal in 2026. Construct a new CANBus instance 163 * and call {@link #isNetworkFD()} instead. 164 * 165 * @param canbus Name of the CAN bus 166 * @return True if the network is CAN FD 167 */ 168 @Deprecated(forRemoval = true) 169 public static boolean isNetworkFD(String canbus) { 170 return CANBusJNI.JNI_IsNetworkFD(canbus); 171 } 172 /** 173 * Gets the status of the CAN bus, including the 174 * bus utilization and the error counters. 175 * <p> 176 * This function returns a new object every call. 177 * As a result, we recommend that this is not called 178 * inside a tight loop. 179 * 180 * @deprecated The CANBus static methods are deprecated 181 * for removal in 2026. Construct a new CANBus instance 182 * and call {@link #getStatus()} instead. 183 * 184 * @param canbus Name of the CAN bus 185 * @return Status of the CAN bus 186 */ 187 @Deprecated(forRemoval = true) 188 public static CANBusStatus getStatus(String canbus) { 189 var jni = new CANBusJNI(); 190 var err = jni.JNI_GetStatus(canbus); 191 192 var status = new CANBusStatus(); 193 status.BusUtilization = jni.busUtilization; 194 status.BusOffCount = jni.busOffCount; 195 status.TxFullCount = jni.txFullCount; 196 status.REC = jni.rec; 197 status.TEC = jni.tec; 198 199 if (err != 0) { 200 status.Status = StatusCode.InvalidNetwork; 201 } else { 202 status.Status = StatusCode.OK; 203 } 204 return status; 205 } 206}