5#include "CanandSettings.h"
6#include "CanandDevice.h"
7#include "CanandUtils.h"
10#include <condition_variable>
13#include <frc/Errors.h>
52 uint64_t
value{0xffffffff'ffffffff};
81requires std::is_base_of<CanandSettings, T>::value
101 inline T
GetSettings(units::second_t timeout, units::second_t missingTimeout, uint32_t missingAttempts) {
104 std::unique_lock<std::mutex> lock(knownSettingsLock);
105 if (timeout > 0_ms) {
106 knownSettings.GetMap().clear();
111 [&]{
return knownSettings.AllSettingsReceived();});
113 if (missingAttempts < 1 || missingTimeout <= 0_ms) {
return T{knownSettings}; }
116 return T{knownSettings};
127 std::vector<uint8_t> missingNow;
128 std::vector<uint8_t> missingFinal;
131 std::unique_lock<std::mutex> lock(knownSettingsLock);
132 if (knownSettings.AllSettingsReceived())
return missingFinal;
133 for (uint8_t addr : knownSettings.SettingAddresses()) {
134 if (!knownSettings.GetMap().contains(addr)) {
135 missingNow.push_back(addr);
140 for (uint8_t addr : missingNow) {
142 for (
int i = 0; i < attempts && !value.IsValid(); i++) {
145 if (!value.IsValid()) {
146 missingFinal.push_back(addr);
158 std::unique_lock<std::mutex> lock(knownSettingsLock);
160 knownSettings.GetMap().clear();
177 inline T
SetSettings(T& settings, units::second_t timeout,
int attempts) {
179 std::unordered_map<uint8_t, uint64_t> values = settings.FilteredMap();
181 if (settings.IsEphemeral()) {
184 for (
auto& it: values) {
185 uint8_t addr = it.first;
187 std::lock_guard<std::mutex> guard(knownSettingsLock);
188 knownSettings.GetMap().erase(addr);
190 bool success =
false;
191 for (
int i = 0; i < attempts && !success; i++) {
196 missed_settings.GetMap()[addr] = values[addr];
200 return missed_settings;
213 if (!missed.IsEmpty()) {
214 FRC_ReportError(frc::err::Error,
"{} settings could not be applied to {}",
231 std::unique_lock<std::mutex> guard(knownSettingsLock);
232 if (clearKnown) knownSettings.GetMap().clear();
234 if (timeout > 0_ms) {
236 [&]{
return knownSettings.AllSettingsReceived();});
238 return T{knownSettings};
249 return T{knownSettings};
261 uint64_t settingValue = 0;
262 if (dataLength < 7)
return;
263 else if (dataLength >= 8) {
266 memcpy(&settingValue, data + 1, 6);
268 bool allSettingsFound =
false;
270 std::lock_guard<std::mutex> getSettingsGuard(knownSettingsLock);
271 knownSettings.GetMap()[data[0]] = settingValue;
272 allSettingsFound = knownSettings.AllSettingsReceived();
274 if (allSettingsFound) knownSettingsCV.notify_all();
278 std::lock_guard<std::mutex> settingRecvGuard(settingRecvLock);
280 settingRecvIdx = data[0];
281 settingRecvCode = flags;
282 settingRecvValue = 0;
283 memcpy(&settingRecvValue, data + 1, 6);
285 settingRecvCV.notify_all();
302 inline void SetSettingById(uint8_t settingId, uint8_t* value, uint8_t length, uint8_t flags) {
303 uint8_t data[8] = { 0 };
306 if (length > 6) length = 6;
307 memcpy(data + 1, value, length);
344 units::second_t timeout, uint8_t flags) {
346 std::unique_lock<std::mutex> lock(settingRecvLock);
348 if (timeout <= 0_ms) {
349 uint64_t longPayload = 0;
350 memcpy(&longPayload, payload, std::min((uint8_t) 6, length));
353 uint32_t prevCtr = settingRecvCtr;
356 return this->settingRecvIdx == settingIdx && this->settingRecvCtr != prevCtr;
378 units::second_t timeout, uint8_t flags) {
380 std::unique_lock<std::mutex> lock(settingRecvLock);
382 if (timeout <= 0_ms) {
385 uint32_t prevCtr = settingRecvCtr;
388 return this->settingRecvIdx == settingIdx && this->settingRecvCtr != prevCtr;
404 std::unique_lock<std::mutex> lock(settingRecvLock);
409 uint32_t prevCtr = settingRecvCtr;
412 return this->settingRecvIdx == settingIdx && this->settingRecvCtr != prevCtr;
431 std::mutex knownSettingsLock;
432 std::condition_variable knownSettingsCV;
434 std::mutex settingRecvLock;
435 std::condition_variable settingRecvCV;
436 uint32_t settingRecvCtr = 0;
437 uint8_t settingRecvIdx = 0;
438 uint8_t settingRecvCode = 0;
439 uint64_t settingRecvValue = 0;
Definition: CanandDevice.h:35
std::string GetDeviceName()
bool SendCANMessage(uint8_t apiIndex, uint8_t *data, uint8_t length)
Definition: CanandDevice.h:119
Definition: CanandMessage.h:26
uint8_t * GetData()
Definition: CanandMessage.h:91
uint8_t GetLength()
Definition: CanandMessage.h:97
Definition: CanandSettingsManager.h:82
void HandleSetting(CanandMessage &msg)
Definition: CanandSettingsManager.h:257
SettingResult ConfirmSetSetting(uint8_t settingIdx, uint64_t payload, units::second_t timeout, uint8_t flags)
Definition: CanandSettingsManager.h:377
T GetSettings(units::second_t timeout, units::second_t missingTimeout, uint32_t missingAttempts)
Definition: CanandSettingsManager.h:101
bool SetSettings(T &settings, units::second_t timeout)
Definition: CanandSettingsManager.h:211
SettingResult ConfirmSetSetting(uint8_t settingIdx, uint8_t *payload, uint8_t length, units::second_t timeout, uint8_t flags)
Definition: CanandSettingsManager.h:343
void SendSettingCommand(uint8_t settingCmdIdx)
Definition: CanandSettingsManager.h:425
T SetSettings(T &settings, units::second_t timeout, int attempts)
Definition: CanandSettingsManager.h:177
T SendReceiveSettingCommand(uint8_t cmd, units::second_t timeout, bool clearKnown)
Definition: CanandSettingsManager.h:230
SettingResult FetchSetting(uint8_t settingIdx, units::second_t timeout)
Definition: CanandSettingsManager.h:403
CanandSettingsManager(CanandDevice &dev)
Definition: CanandSettingsManager.h:88
std::vector< uint8_t > FetchMissingSettings(units::second_t timeout, int attempts)
Definition: CanandSettingsManager.h:126
void SetSettingById(uint8_t settingId, uint64_t value, uint8_t flags)
Definition: CanandSettingsManager.h:325
void SetSettingById(uint8_t settingId, uint8_t *value, uint8_t length, uint8_t flags)
Definition: CanandSettingsManager.h:302
T GetKnownSettings()
Definition: CanandSettingsManager.h:247
void StartFetchSettings()
Definition: CanandSettingsManager.h:157
Definition: CanandSettingsManager.h:69
static constexpr uint8_t kEphemeral
Definition: CanandSettingsManager.h:72
Definition: CanandSettingsManager.h:23
@ kError
Definition: CanandSettingsManager.h:31
@ kTimeout
Definition: CanandSettingsManager.h:29
@ kOk
Definition: CanandSettingsManager.h:33
@ kInvalid
Definition: CanandSettingsManager.h:27
Definition: CanandSettingsManager.h:40
int16_t result
Definition: CanandSettingsManager.h:57
constexpr SettingResult(uint64_t value, int16_t result)
Definition: CanandSettingsManager.h:47
constexpr bool IsValid()
Definition: CanandSettingsManager.h:63
uint64_t value
Definition: CanandSettingsManager.h:52
static constexpr uint8_t kSetSetting
Definition: CanandDevice.h:158
static constexpr uint8_t kSettingCommand
Definition: CanandDevice.h:156
static constexpr uint8_t kFetchSettings
Definition: CanandDevice.h:173
static constexpr uint8_t kFetchSettingValue
Definition: CanandDevice.h:177
constexpr std::chrono::duration< double, std::ratio< 1LL, 1LL > > toChronoSeconds(units::second_t seconds)
Definition: CanandUtils.h:94
Definition: CanandMessage.h:10