ReduxLib C++ 2025.0.0-beta2
Loading...
Searching...
No Matches
CanandDevice.h
1// Copyright (c) Redux Robotics and other contributors.
2// This is open source and can be modified and shared under the 3-clause BSD license.
3
4#pragma once
5#include <optional>
6#include <mutex>
7#include <condition_variable>
8#include <concepts>
9#include <limits>
10#include <utility>
11#include <span>
12#include <inttypes.h>
13#include "redux/canand/CanandAddress.h"
14#include "redux/canand/CanandFirmwareVersion.h"
15#include "units/time.h"
16#include <string>
17#include <vector>
18
19namespace redux::canand {
20
21/**
22 * The base class for all CAN-communicating Redux Robotics device classes.
23 * The ReduxLib vendordep does all CAN message parsing in the Java/C++ classes themselves. CanandDevice provides
24 * general facilities for sending and receiving CAN messages (abstracted from the actual underlying buses) as well as
25 * helper functions and constants common for all Redux CAN products.
26 *
27 * Classes implementing CanandDevice need to do the following:
28 * <ul>
29 * <li> Implement CanandDevice::getAddress (usually by instantiating a CanandAddress in the constructor and returning it)</li>
30 * <li> Implement CanandDevice::HandleMessage which will be called asynchronously whenever new CAN messages matching the object's CanandAddress get received by the robot </li>
31 * <li> Run redux::canand::AddCANListener(this) in the constructor so HandleMessage actually gets called at runtime </li>
32 * <li> Run redux::canand::RemoveCANListener(this) in the destructor. </li>
33 * </ul>
34*/
36 public:
37 /**
38 * A callback called when a Redux CAN message is received and should be parsed.
39 * Subclasses of CanandDevice should override this to update their internal state accordingly.
40 *
41 * <p>
42 * HandleMessage will be called on all Redux CAN packets received by the vendordep that match the CanandAddress
43 * returned by CanandDevice::GetAddress().
44 * </p>
45 *
46 * @param msg a reference to a CanandMessage representing the received message. The message may not have lifetime outside the function call.
47 *
48 */
49 virtual void HandleMessage(CanandMessage& msg) = 0;
50
51 /**
52 * Returns the reference to the CanandAddress representing the combination of CAN bus and
53 * CAN device ID that this CanandDevice refers to.
54 *
55 * <p>
56 * Implementing device subclasses should likely construct a new CanandAddress
57 * in their constructor and return it here.
58 * </p>
59 * @return a reference to the CanandAddress for the device.
60 */
61 virtual CanandAddress& GetAddress() = 0;
62
63 /**
64 * Checks whether or not the device has sent a message within the last timeout seconds.
65 * @param timeout window to check for message updates in seconds. Default 2
66 * @return true if there has been a message within the last timeout seconds, false if not
67 */
68 bool IsConnected(units::second_t timeout = 2_s);
69
70 /**
71 * Returns a canonical class-wide device name.
72 * @return std::string of a device type name
73 */
74 virtual inline std::string GetDeviceClassName() { return "CanandDevice"; }
75
76 /**
77 * Returns a nicely formatted name of the device, specific to its device address.
78 * @return std::string of a specific device name
79 */
80 std::string GetDeviceName();
81
82 /**
83 * Called before HandleMessage gets called to run some common logic.
84 * (Namely, handling setting receives and last message times)
85 *
86 * This function can be overridden to change or disable its logic.
87 *
88 * @param msg a CanandMessage representing the received message.
89 */
90 virtual void PreHandleMessage(CanandMessage& msg);
91
92 /**
93 * Checks the received firmware version.
94 *
95 * <p>
96 * If no firmware version has been received, complain to the driver station about potentially
97 * missing devices from the bus.
98 * </p>
99 * <p>
100 * If the reported firmware version is too old, also complain to the driver station.
101 * </p>
102 */
104
105 /**
106 * Returns the minimum firmware version this vendordep requires.
107 * @return minimum firmware version
108 */
110
111 /**
112 * Sends a CAN message to the CanandAddress.
113 *
114 * @param apiIndex the API index the message should have (between 0-31 inclusive)
115 * @param data 1-8 bytes of payload, as an array or pointer
116 * @param length the length of the the payload buffer
117 * @return if the operation was successful
118 */
119 inline bool SendCANMessage(uint8_t apiIndex, uint8_t* data, uint8_t length) {
120 return GetAddress().SendCANMessage(apiIndex, data, length);
121 }
122
123 /**
124 * Send a CAN message directly to the device, but properly length checked.
125 *
126 * @param msgId the individual API index to value to send
127 * @param data 1-8 byte payload std:span of std:byte
128 */
129 template<std::size_t len> requires(len < 8U)
130 void SendCANMessage(uint8_t msgId, std::span<std::byte,len> data) {
131 SendCANMessage(msgId, std::as_bytes(data), data.size_bytes());
132 }
133
134 private:
135 std::mutex settingRecvLock;
136 std::optional<CanandFirmwareVersion> receivedFirmwareVersion{std::nullopt};
137
138 /**
139 * The last received message timestamp.
140 * This is timed with respect to the FPGA timer and is updated before HandleMessage gets called
141 * (it's updated in preHandleMessage).
142 */
143 std::optional<units::second_t> lastMessageTs{std::nullopt};
144};
145
146
147/**
148 * Constants common to all CanandDevices
149 */
150namespace details {
151
152/** Message IDs common to all devices */
153class Message {
154 public:
155 /** Message id for setting control command */
156 static constexpr uint8_t kSettingCommand = 0x2;
157 /** Message id for update setting on device */
158 static constexpr uint8_t kSetSetting = 0x3;
159 /** Message id for setting value report from device */
160 static constexpr uint8_t kReportSetting = 0x4;
161 /** Message id for clear device sticky faults */
162 static constexpr uint8_t kClearStickyFaults = 0x5;
163 /** Message id for status frames */
164 static constexpr uint8_t kStatus = 0x6;
165 /** Message id for party mode */
166 static constexpr uint8_t kPartyMode = 0x7;
167};
168
169/** Setting command IDs common to all devices */
171 public:
172 /** Setting command id for Fetch all settings from device */
173 static constexpr uint8_t kFetchSettings = 0x0;
174 /** Setting command id for Reset everything to factory default */
175 static constexpr uint8_t kResetFactoryDefault = 0x1;
176 /** setting command for Fetch individual setting */
177 static constexpr uint8_t kFetchSettingValue = 0x2;
178};
179
180/** Setting indexes common to all devices */
181class Setting {
182 public:
183 /** Setting index for Status frame period (ms) */
184 static constexpr uint8_t kStatusFramePeriod = 0x4;
185 /** Setting index for Serial number */
186 static constexpr uint8_t kSerialNumber = 0x5;
187 /** Setting index for Firmware version */
188 static constexpr uint8_t kFirmwareVersion = 0x6;
189};
190
191/** List of settings as a std::vector for CanandSettings. */
192const std::vector<uint8_t> VDEP_SETTINGS = {
196};
197
198}
199}
Definition: CanandAddress.h:62
bool SendCANMessage(uint16_t apiIndex, uint8_t *data, uint8_t length)
Definition: CanandDevice.h:35
virtual void CheckReceivedFirmwareVersion()
virtual void PreHandleMessage(CanandMessage &msg)
bool IsConnected(units::second_t timeout=2_s)
virtual CanandAddress & GetAddress()=0
virtual CanandFirmwareVersion GetMinimumFirmwareVersion()
Definition: CanandDevice.h:109
virtual void HandleMessage(CanandMessage &msg)=0
bool SendCANMessage(uint8_t apiIndex, uint8_t *data, uint8_t length)
Definition: CanandDevice.h:119
virtual std::string GetDeviceClassName()
Definition: CanandDevice.h:74
void SendCANMessage(uint8_t msgId, std::span< std::byte, len > data)
Definition: CanandDevice.h:130
Definition: CanandMessage.h:26
Definition: CanandDevice.h:153
static constexpr uint8_t kClearStickyFaults
Definition: CanandDevice.h:162
static constexpr uint8_t kPartyMode
Definition: CanandDevice.h:166
static constexpr uint8_t kSetSetting
Definition: CanandDevice.h:158
static constexpr uint8_t kReportSetting
Definition: CanandDevice.h:160
static constexpr uint8_t kStatus
Definition: CanandDevice.h:164
static constexpr uint8_t kSettingCommand
Definition: CanandDevice.h:156
Definition: CanandDevice.h:170
static constexpr uint8_t kResetFactoryDefault
Definition: CanandDevice.h:175
static constexpr uint8_t kFetchSettings
Definition: CanandDevice.h:173
static constexpr uint8_t kFetchSettingValue
Definition: CanandDevice.h:177
Definition: CanandDevice.h:181
static constexpr uint8_t kSerialNumber
Definition: CanandDevice.h:186
static constexpr uint8_t kFirmwareVersion
Definition: CanandDevice.h:188
static constexpr uint8_t kStatusFramePeriod
Definition: CanandDevice.h:184
const std::vector< uint8_t > VDEP_SETTINGS
Definition: CanandDevice.h:192
Definition: CanandMessage.h:10
Definition: CanandFirmwareVersion.h:17