Motion Master 6.0.0-alpha.111
Next-generation motion control software
Loading...
Searching...
No Matches
device.h
Go to the documentation of this file.
1#pragma once
2
3#include <chrono>
4#include <cstdint>
5#include <cstring>
6#include <deque>
7#include <expected>
8#include <format>
9#include <map>
10#include <memory>
11#include <mutex>
12#include <nlohmann/json_fwd.hpp>
13#include <optional>
14#include <span>
15#include <string>
16#include <type_traits>
17#include <unordered_map>
18#include <utility>
19#include <variant>
20#include <vector>
21
24#include "node/pdo_mapping.h"
25
26namespace mm::node {
27
31struct ProcessData;
32
36class ParameterCache;
37
43
71
75 uint16_t index = 0;
76 std::map<uint8_t, DeviceParameterValue> values;
77
81 template <typename T>
82 std::expected<T, std::string> get(uint8_t subindex) const {
83 auto it = values.find(subindex);
84 if (it == values.end()) {
85 return std::unexpected(
86 std::format("object 0x{:04X} has no readable subindex {:02X}", index, subindex));
87 }
88 if (const auto* p = std::get_if<T>(&it->second)) {
89 return *p;
90 }
91 return std::unexpected(
92 std::format("parameter 0x{:04X}:{:02X} holds a different type", index, subindex));
93 }
94};
95
120class Device {
121 public:
134 ProcessData* processData = nullptr, const ParameterCache* parameterCache = nullptr);
135
137 uint16_t slavePosition() const;
138
143 const std::string& name() const;
144
151 std::string productName() const;
152
154 uint32_t vendorId() const;
155
157 uint32_t productCode() const;
158
160 uint32_t revisionNumber() const;
161
163 uint32_t serialNumber() const;
164
171 bool isCia402() const;
172
183 bool mailboxActive() const;
184
192 bool supportsCoe() const;
193
197 bool supportsEsc() const;
198
201 bool supportsLocate() const;
202
205 std::optional<uint8_t> escType() const;
206
209 bool mailboxWriteOnce() const;
210
212 std::expected<void, std::string> locate(bool on) const;
213
216 std::expected<mm::comm::FieldbusDriver::FirmwareActivation, std::string> activateFirmware(
217 std::chrono::steady_clock::duration timeout) const;
218
226 bool exchangesProcessData() const;
227
236 std::expected<std::vector<uint8_t>, std::string> readSdo(uint16_t index, uint8_t subindex) const;
237
248 std::expected<void, std::string> writeSdo(uint16_t index, uint8_t subindex,
249 std::span<const uint8_t> data) const;
250
259 std::expected<std::vector<uint8_t>, mm::comm::FoeError> readFile(
260 const std::string& filename,
261 std::chrono::milliseconds timeout = mm::comm::kFoeReadTimeout) const;
262
268 std::expected<void, mm::comm::FoeError> writeFile(const std::string& filename,
269 std::span<const uint8_t> data) const;
270
278 std::expected<void, std::string> readRegister(uint16_t address, std::span<uint8_t> data) const;
279
287 std::expected<void, std::string> writeRegister(uint16_t address,
288 std::span<const uint8_t> data) const;
289
297 std::expected<std::vector<uint8_t>, std::string> readSii() const;
298
308 std::expected<void, std::string> writeSii(std::span<const uint8_t> data) const;
309
330 std::expected<void, std::string> initializeParameters(bool readValues = false,
331 bool useCompleteAccess = true);
332
347 std::expected<void, std::string> readFlatPdoMapping();
348
350 const FlatPdoMapping& flatPdoMapping() const;
351
360 std::expected<PdoMapping, std::string> readPdoMapping();
361
391 std::expected<void, std::string> writePdoMapping(const PdoMapping& mapping);
392
405 std::expected<DeviceParameterValue, std::string> setValueFromBytes(
406 uint16_t index, uint8_t subindex, std::span<const uint8_t> bytes);
407
414 bool hasParameters() const;
415
427 bool parametersUnavailable() const;
428
434 std::vector<DeviceParameter> parametersOrdered() const;
435
448 std::optional<DeviceParameter> parameter(uint16_t index, uint8_t subindex) const;
449
464 std::optional<DeviceParameterValue> parameterValue(uint16_t index, uint8_t subindex) const;
465
475 std::optional<uint16_t> dataType(uint16_t index, uint8_t subindex) const;
476
495 std::expected<DeviceParameterValue, std::string> readParameter(uint16_t index, uint8_t subindex);
496
516 std::expected<void, std::string> readAllParameters(bool useCompleteAccess = true);
517
538 std::expected<ObjectValues, std::string> readObject(uint16_t index,
539 bool useCompleteAccess = true);
540
560 std::expected<void, std::string> writeParameter(uint16_t index, uint8_t subindex,
561 const DeviceParameterValue& newValue);
562
576 template <typename T>
577 std::expected<void, std::string> writeValue(uint16_t index, uint8_t subindex, T newValue) {
578 return writeParameter(index, subindex, DeviceParameterValue{newValue});
579 }
580
592 template <typename T>
593 std::expected<T, std::string> readValue(uint16_t index, uint8_t subindex) {
594 auto v = readParameter(index, subindex);
595 if (!v) {
596 return std::unexpected(v.error());
597 }
598 if (const auto* p = std::get_if<T>(&*v)) {
599 return *p;
600 }
601 return std::unexpected(
602 std::format("parameter 0x{:04X}:{:02X} holds a different type", index, subindex));
603 }
604
609 template <typename T>
610 std::expected<T, std::string> readValue(ObjectAddress<T> address) {
611 return readValue<T>(address.index, address.subindex);
612 }
613
615 template <typename T>
616 std::expected<void, std::string> writeValue(ObjectAddress<T> address, T newValue) {
617 return writeValue<T>(address.index, address.subindex, std::move(newValue));
618 }
619
642 template <typename T>
643 std::expected<T, std::string> readCachedValue(uint16_t index, uint8_t subindex) {
644 {
645 std::lock_guard<std::mutex> lock(*parametersMutex_);
646 if (const DeviceParameter* p = findParameter(index, subindex);
647 p && p->syncState == SyncState::Synced) {
648 return p->getValue<T>();
649 }
650 }
651 return readValue<T>(index, subindex); // never read: fetch once — readValue marks it Synced.
652 }
653
668 DeviceParameter* findParameter(uint16_t index, uint8_t subindex);
669
671 const DeviceParameter* findParameter(uint16_t index, uint8_t subindex) const;
672
700 template <typename T>
701 std::optional<T> value(uint16_t index, uint8_t subindex) const {
702 const DeviceParameter* p = findParameter(index, subindex);
703 if (p == nullptr) {
704 return std::nullopt;
705 }
706 return p->scalar<T>();
707 }
708
734 template <typename T>
735 bool setValue(uint16_t index, uint8_t subindex, T newValue) {
736 static_assert(std::is_arithmetic_v<T>, "the cell holds arithmetic types only");
737 static_assert(sizeof(T) <= sizeof(uint64_t), "the cell holds at most eight bytes");
738 const DeviceParameter* p = findParameter(index, subindex);
739 if (p == nullptr || !std::holds_alternative<T>(defaultValueForDataType(p->dataType))) {
740 return false;
741 }
742 uint64_t bits = 0;
743 std::memcpy(&bits, &newValue, sizeof(T));
744 p->storeBits(bits);
745 return true;
746 }
747
752 template <typename T>
753 std::optional<T> value(ObjectAddress<T> address) const {
754 return value<T>(address.index, address.subindex);
755 }
756
758 template <typename T>
759 bool setValue(ObjectAddress<T> address, T newValue) {
760 return setValue<T>(address.index, address.subindex, newValue);
761 }
762
763 private:
781 void publishParameters(std::unordered_map<uint32_t, DeviceParameter>&& built);
782
793 void readParameterValues(std::vector<DeviceParameter>& defs, bool useCompleteAccess);
794
799 void markReadFailed(uint16_t index, uint8_t subindex, uint16_t declaredType);
800
810 bool recordDeclaredSubindexRead(bool ok);
811
815 bool declaredSubindexReadsWorthTrying() const;
816
834 bool readObjectComplete(uint16_t index, std::span<const uint8_t> subindices,
835 bool useCompleteAccess);
836
845 std::expected<std::vector<PdoMappingObject>, std::string> readPdoAssignment(
846 uint16_t assignmentIndex);
847
858 std::expected<FlatPdoMapping, std::string> readSiiPdoMapping();
859
870 std::expected<std::vector<DeviceParameter>, std::string> buildSiiParameterDefinitions();
871
872 uint16_t slavePosition_;
874 // Live process-data runtime, or nullptr for SDO-only operation. Injected by DeviceManager so
875 // read/writeParameter can prefer PDO over SDO while exchanging. Non-owning; the owner
876 // (DeviceManager) outlives every Device it created. A raw pointer keeps Device
877 // move-constructible.
878 ProcessData* processData_ = nullptr;
879 // On-disk parameter-definition cache, or nullptr to always enumerate live. Non-owning; owned by
880 // DeviceManager, which outlives every Device. Consulted only by initializeParameters.
881 const ParameterCache* parameterCache_ = nullptr;
882 std::string name_;
883 uint32_t vendorId_;
884 uint32_t productCode_;
885 uint32_t revisionNumber_;
886 uint32_t serialNumber_;
887 // EEPROM mailbox-protocol bits, copied at construction. Immutable like the identity fields above,
888 // and cached for the same reason the constructor explains: reading it from the driver on demand
889 // would take the control-plane mutex and so block behind whatever bus operation holds it.
890 uint16_t mailboxProtocols_ = 0;
891 // Transport capabilities, copied at construction for the reason given above.
892 bool supportsEsc_ = true;
893 bool supportsLocate_ = false;
894 std::optional<uint8_t> escType_;
895 bool mailboxWriteOnce_ = false;
896 // Guards parameters_ (and caSupport_) against the off-RT monitoring threads (the refresher
897 // refreshes cached values, the sampler reads them) racing the control-plane thread.
898 //
899 // **Never held across bus I/O.** Every method that reads or writes the bus — readParameter,
900 // writeParameter, readObjectComplete, readAllParameters, initializeParameters — takes it, decides
901 // what to transfer, releases it for the transfer, and re-takes it to commit. That is not a
902 // micro-optimisation: a mailbox transfer queues behind the driver's control-plane mutex, which an
903 // FoE file transfer holds for its whole multi-second duration, so a lock held across "one mailbox
904 // round-trip" is in fact held for as long as any unrelated bus traffic takes. With a background
905 // parameter refresh and a user on the FoE page — the ordinary configuration, not a rare one —
906 // that stalled every cached read of the device.
907 //
908 // The rule this imposes on callers: a DeviceParameter* must never be carried across the release,
909 // because initializeParameters replaces the whole map. Re-find after the transfer, and treat a
910 // miss (or a changed dataType) as "re-enumerated mid-transfer" rather than assuming it cannot
911 // happen.
912 //
913 // Held by unique_ptr because std::mutex is neither movable nor copyable, and Device is moved
914 // into DeviceManager's std::vector<Device> (which relocates on growth). The indirection keeps
915 // Device move-constructible (the pointer moves); a Device is never copied, only moved.
916 std::unique_ptr<std::mutex> parametersMutex_;
917
920 std::expected<void, std::string> readParameterDefinitions(bool readValues,
921 bool useCompleteAccess);
922
927 bool parametersUnavailable_ = false;
928 // The cells themselves, and they are never destroyed while this Device lives. A re-enumeration
929 // rebuilds the *map* above, reuses every cell whose declaration is unchanged, and appends a cell
930 // for anything new; it never erases one. So a DeviceParameter* held by a published process image
931 // stays valid across a re-enumeration — which is the point, because buildProcessImage resolves
932 // that pointer once and the RT decode dereferences it every cycle without re-checking anything.
933 // A cyclic task's own lookups are valid for the body of one cycle, not across cycles: the Device
934 // dies with its DeviceSet once the last holder releases it.
935 //
936 // A deque because the standard says an insertion at either end invalidates iterators but leaves
937 // *references* to existing elements valid ([deque.modifiers]) — and pointers into it are exactly
938 // what everything above holds. It allocates in blocks, so a cell costs no allocation of its own.
939 //
940 // std::vector is not an option and reserve() does not rescue it: the count is unknown until the
941 // dictionary is read, a later enumeration can add objects a firmware update introduced, and the
942 // one growth past capacity would dangle every pointer at once, silently and far from the cause.
943 // std::list and vector<unique_ptr<DeviceParameter>> are address-stable too, at one allocation per
944 // cell and an extra indirection, for nothing gained: nothing indexes this container, and no code
945 // on the RT path iterates it (the decode walks the image's entries instead).
946 //
947 // Behind a unique_ptr so that moving a Device — DeviceManager builds its vector<Device> by
948 // emplacing — never moves the deque object itself, and the question of whether a moved deque
949 // preserves element addresses never has to be asked.
950 std::unique_ptr<std::deque<DeviceParameter>> cells_;
951 // (index, subindex) -> the cell that holds that object's value. Replaced wholesale by
952 // publishParameters; the cells it points at outlive every replacement.
953 std::unordered_map<uint32_t, DeviceParameter*> parameters_;
954 // Maps kept alive because the RT cycle did not drain before they were replaced. A cyclic task may
955 // still be walking one, and freeing it then is a use-after-free. They are only ever added
956 // to, which is bounded by how many times a drain fails — an emergency that is logged each time.
957 std::vector<std::unordered_map<uint32_t, DeviceParameter*>> retiredMaps_;
958 FlatPdoMapping flatPdoMapping_;
959 // Discovered Complete Access support (the probe outcome), shared by every grouped read for the
960 // device's lifetime. Read and written only under parametersMutex_.
962 // Whether this device serves a subindex above its object's stated count -- see
963 // DeclaredSubindexReads. Learned by the read sweeps and kept for the device's lifetime. Read and
964 // written only under parametersMutex_.
966};
967
977void to_json(nlohmann::json& j, const Device& d);
978
996std::expected<int, std::string> reconcileDetectedModules(const Device& device);
997
998} // namespace mm::node
Abstract interface for an EtherCAT fieldbus driver.
Definition fieldbus_driver.h:474
Represents a single node on the fieldbus.
Definition device.h:120
bool setValue(uint16_t index, uint8_t subindex, T newValue)
Sets a scalar parameter's value as T. Lock-free, non-allocating.
Definition device.h:735
std::expected< void, std::string > locate(bool on) const
Starts or stops blinking this device's LEDs. Delegates to FieldbusDriver::locate.
Definition device.cc:106
std::expected< void, std::string > writeSdo(uint16_t index, uint8_t subindex, std::span< const uint8_t > data) const
Writes an object dictionary entry to the device (CoE SDO download).
Definition device.cc:124
std::expected< DeviceParameterValue, std::string > readParameter(uint16_t index, uint8_t subindex)
Reads a parameter value, keeping the cached store in sync.
Definition device.cc:1111
std::expected< void, std::string > readRegister(uint16_t address, std::span< uint8_t > data) const
Reads bytes from an ESC register on this device.
Definition device.cc:139
std::expected< std::vector< uint8_t >, mm::comm::FoeError > readFile(const std::string &filename, std::chrono::milliseconds timeout=mm::comm::kFoeReadTimeout) const
Reads a file from this device via File over EtherCAT (FoE).
Definition device.cc:129
DeviceParameter * findParameter(uint16_t index, uint8_t subindex)
Parameter lookup by (index, subindex). O(1); nullptr if absent. Takes no lock.
Definition device.cc:1091
std::expected< void, std::string > initializeParameters(bool readValues=false, bool useCompleteAccess=true)
Enumerates the device's CoE object dictionary and populates parameters().
Definition device.cc:157
std::optional< DeviceParameterValue > parameterValue(uint16_t index, uint8_t subindex) const
Returns a copy of a parameter's last known value. No bus access.
Definition device.cc:1064
std::expected< T, std::string > readCachedValue(uint16_t index, uint8_t subindex)
Read-once typed accessor for objects the caller knows are immutable.
Definition device.h:643
uint32_t serialNumber() const
Serial number from EEPROM.
Definition device.cc:72
std::expected< void, std::string > writeParameter(uint16_t index, uint8_t subindex, const DeviceParameterValue &newValue)
Writes a parameter value, always updating the cache first.
Definition device.cc:1387
std::expected< std::vector< uint8_t >, std::string > readSdo(uint16_t index, uint8_t subindex) const
Reads an object dictionary entry from the device (CoE SDO upload).
Definition device.cc:119
bool mailboxWriteOnce() const
Whether the driver writes each mailbox request to this device once. Copied from SlaveInfo at construc...
Definition device.cc:74
std::expected< void, std::string > readAllParameters(bool useCompleteAccess=true)
Refreshes the cached value of every readable parameter, keeping the list intact.
Definition device.cc:1178
std::expected< mm::comm::FieldbusDriver::FirmwareActivation, std::string > activateFirmware(std::chrono::steady_clock::duration timeout) const
Makes this device apply the firmware files written to it in BOOT. Delegates to FieldbusDriver::activa...
Definition device.cc:110
bool hasParameters() const
Whether the object dictionary is enumerated (thread-safe; no bus access).
Definition device.cc:612
bool supportsEsc() const
Whether the device has an EtherCAT Slave Controller: SII, ESC registers, DC and the ESC diagnostics....
Definition device.cc:102
bool supportsCoe() const
Whether the slave advertises a CoE mailbox — a fixed capability, not a live check.
Definition device.cc:98
std::expected< void, std::string > writePdoMapping(const PdoMapping &mapping)
Writes a new PDO mapping to the device via SDO, then reads it back to verify.
Definition device.cc:964
std::expected< void, std::string > writeRegister(uint16_t address, std::span< const uint8_t > data) const
Writes bytes to an ESC register on this device.
Definition device.cc:144
const std::string & name() const
Human-readable node name from SII EEPROM.
Definition device.cc:60
std::expected< void, std::string > writeValue(uint16_t index, uint8_t subindex, T newValue)
Typed convenience wrapper for writeParameter.
Definition device.h:577
bool setValue(ObjectAddress< T > address, T newValue)
setValue<T>() addressed by an ObjectAddress. Lock-free, non-allocating.
Definition device.h:759
std::optional< DeviceParameter > parameter(uint16_t index, uint8_t subindex) const
Looks up one parameter by (index, subindex) and returns a copy of it. O(1).
Definition device.cc:1073
uint32_t revisionNumber() const
Revision number from EEPROM.
Definition device.cc:71
const FlatPdoMapping & flatPdoMapping() const
Returns the device's PDO mapping. Empty until readFlatPdoMapping() succeeds.
Definition device.cc:864
bool exchangesProcessData() const
Whether the device is in a process-data-exchanging state (SAFE-OP or OP, error bit clear).
Definition device.cc:115
std::expected< PdoMapping, std::string > readPdoMapping()
Reads the device's PDO mapping grouped by mapping object (0x16xx / 0x1Axx).
Definition device.cc:718
std::vector< DeviceParameter > parametersOrdered() const
Returns all parameters sorted ascending by (index, subindex).
Definition device.cc:1052
bool parametersUnavailable() const
Whether any initializeParameters call on this device failed since it was scanned (thread-safe; no bus...
Definition device.cc:617
bool supportsLocate() const
Whether locate can blink this device's LEDs. Copied from FieldbusDriver::supportsLocate at constructi...
Definition device.cc:104
std::expected< void, std::string > readFlatPdoMapping()
Reads the device's PDO mapping from its assignment and mapping objects.
Definition device.cc:818
std::expected< DeviceParameterValue, std::string > setValueFromBytes(uint16_t index, uint8_t subindex, std::span< const uint8_t > bytes)
Sets the parameter's value from its raw on-the-wire bytes (the bytes-domain setter).
Definition device.cc:1033
std::expected< ObjectValues, std::string > readObject(uint16_t index, bool useCompleteAccess=true)
Reads every readable sub-entry of one object and returns the decoded values.
Definition device.cc:1334
std::expected< T, std::string > readValue(ObjectAddress< T > address)
readValue<T>() addressed by an ObjectAddress. Blocking; off the RT thread only.
Definition device.h:610
std::optional< uint8_t > escType() const
The low byte of ESC register 0x0000, the slave controller family, or empty when the driver could not ...
Definition device.cc:73
bool mailboxActive() const
Whether the device's CoE/SDO mailbox is currently active (AL state PRE-OP, SAFE-OP,...
Definition device.cc:86
uint32_t productCode() const
Product code from EEPROM.
Definition device.cc:70
std::expected< void, std::string > writeSii(std::span< const uint8_t > data) const
Writes a raw SII (EEPROM) image to this device.
Definition device.cc:153
std::expected< T, std::string > readValue(uint16_t index, uint8_t subindex)
Typed convenience wrapper for readParameter.
Definition device.h:593
std::expected< void, std::string > writeValue(ObjectAddress< T > address, T newValue)
writeValue<T>() addressed by an ObjectAddress. Blocking; off the RT thread only.
Definition device.h:616
bool isCia402() const
Whether this device implements the CiA402 drive profile.
Definition device.cc:76
uint16_t slavePosition() const
Returns the 1-based position of this node on the fieldbus.
Definition device.cc:59
std::string productName() const
Canonical product name, independent of the SII EEPROM contents.
Definition device.cc:61
std::optional< uint16_t > dataType(uint16_t index, uint8_t subindex) const
Returns a parameter's declared ETG.1020 data-type code, thread-safely (cache lock).
Definition device.cc:1082
std::optional< T > value(uint16_t index, uint8_t subindex) const
Reads a scalar parameter's current value as T. Lock-free, non-allocating.
Definition device.h:701
uint32_t vendorId() const
Vendor ID from EEPROM.
Definition device.cc:69
std::optional< T > value(ObjectAddress< T > address) const
value<T>() addressed by an ObjectAddress. Lock-free, non-allocating.
Definition device.h:753
std::expected< void, mm::comm::FoeError > writeFile(const std::string &filename, std::span< const uint8_t > data) const
Writes a file to this device via File over EtherCAT (FoE).
Definition device.cc:134
std::expected< std::vector< uint8_t >, std::string > readSii() const
Reads this device's raw Slave Information Interface (SII / EEPROM) image.
Definition device.cc:149
On-disk cache of CoE parameter definitions, keyed by device identity.
Definition parameter_cache.h:52
driver
Definition config.h:230
mailboxStatusFmmu useCompleteAccess parameterCache
Definition config.h:245
uint8_t subindex
Definition esi_entry.cc:283
constexpr std::chrono::milliseconds kFoeReadTimeout
How long a file read waits for the slave's answer, unless the caller asks for longer.
Definition fieldbus_driver.h:39
Definition bus_health_source.h:7
std::variant< int8_t, int16_t, int32_t, int64_t, uint8_t, uint16_t, uint32_t, uint64_t, float, double, std::string, std::vector< uint8_t > > DeviceParameterValue
Decoded value of a single device parameter (CoE object dictionary entry).
Definition device_parameter.h:33
DeviceParameterValue defaultValueForDataType(uint16_t dataType)
Returns a zero-equivalent value for the given ETG.1020 dataType.
Definition device_parameter.cc:60
void to_json(nlohmann::json &j, const Cia402Status &s)
Serialises a Cia402Status. Emits state/modeName as human-readable strings alongside the numeric statu...
Definition cia402_drive.cc:13
DeclaredSubindexReads
Whether a device serves the subindices an array or a record declares but does not hold.
Definition device.h:70
@ Synced
value matches the device (last successful read or write).
CompleteAccessSupport
Runtime discovery state of CoE Complete Access support. CA is optional in CoE and the EEPROM capabili...
Definition device.h:42
std::expected< int, std::string > reconcileDetectedModules(const Device &device)
Reconciles a device's Configured Module Ident List with its Detected list.
Definition device.cc:1480
std::chrono::milliseconds timeout
Definition somanet_procedures.cc:464
std::size_t bytes
Definition spoe_connection.cc:24
A structured FoE failure. String-like where a caller only forwards it (operator<<,...
Definition foe_error.h:110
A single object dictionary entry held by a Device.
Definition device_parameter.h:195
SyncState syncState
Freshness of the value relative to the device.
Definition device_parameter.h:215
void storeBits(uint64_t v) const
Stores the scalar cell. Lock-free, non-allocating, relaxed — safe from the RT loop.
Definition device_parameter.h:230
uint16_t dataType
ETG.1020 data type code (e.g. 0x0007 = UNSIGNED32).
Definition device_parameter.h:200
std::optional< T > scalar() const
Reads the value as T straight out of the cell. Lock-free, non-allocating.
Definition device_parameter.h:253
A device's complete PDO mapping across both directions.
Definition pdo_mapping.h:62
The address of one object-dictionary entry, carrying the type that entry holds.
Definition device_parameter.h:63
uint16_t index
CoE object index.
Definition device_parameter.h:64
uint8_t subindex
CoE object subindex.
Definition device_parameter.h:65
Decoded values of one object's readable sub-entries, as returned by Device::readObject.
Definition device.h:74
std::map< uint8_t, DeviceParameterValue > values
Decoded value per readable subindex.
Definition device.h:76
uint16_t index
CoE object index the values belong to.
Definition device.h:75
std::expected< T, std::string > get(uint8_t subindex) const
Returns the value of subindex as T — type-exact, like DeviceParameter::getValue.
Definition device.h:82
A device's desired PDO configuration to write and assign — the write-side input to Device::writePdoMa...
Definition pdo_mapping.h:89
The live process-data runtime: the published image, the cross-thread exchange buffers,...
Definition process_data.h:36