Motion Master 6.0.0-alpha.50
Next-generation motion control software
Loading...
Searching...
No Matches
device_manager.h
Go to the documentation of this file.
1#pragma once
2
3#include <atomic>
4#include <chrono>
5#include <cstdint>
6#include <expected>
7#include <iosfwd>
8#include <memory>
9#include <nlohmann/json_fwd.hpp>
10#include <optional>
11#include <shared_mutex>
12#include <span>
13#include <string>
14#include <vector>
15
17#include "node/device.h"
20#include "node/process_image.h"
21
22namespace mm::node {
23
27struct ProcessData;
28
31 uint16_t slavePosition;
32 uint16_t alStatus;
33 uint16_t alState;
34 bool error;
35 uint16_t alStatusCode;
36};
37
39void to_json(nlohmann::json& j, const DeviceStateInfo& info);
40
47 uint16_t slavePosition = 0;
48 uint16_t index = 0;
49 uint8_t subindex = 0;
50 std::string name;
51 uint32_t bitOffset = 0;
52 uint16_t bitLength = 0;
53};
54
65 bool configured = false;
66 uint32_t outputBytes = 0;
67 uint32_t inputBytes = 0;
68 int expectedWkc = 0;
69 int lastWkc = 0;
70 bool healthy = false;
71 std::size_t generations = 0;
72 std::vector<ProcessImageObjectInfo> outputs;
73 std::vector<ProcessImageObjectInfo> inputs;
74};
75
77void to_json(nlohmann::json& j, const ProcessImageObjectInfo& obj);
78
80void to_json(nlohmann::json& j, const ProcessImageInfo& info);
81
87 uint16_t slavePosition = 0;
88 uint16_t index = 0;
89 uint8_t subindex = 0;
91};
92
100 uint16_t slavePosition = 0;
101 uint16_t index = 0;
102 uint8_t subindex = 0;
103 bool staged = false;
104 std::string error;
105};
106
108void to_json(nlohmann::json& j, const OutputStageResult& result);
109
117 std::string deviceName;
118 // Immutable identity, denormalised from the Device for this slave position (like deviceName) so
119 // the Configuration page can show it without a second endpoint. Zero when the slave is unknown.
120 uint32_t vendorId = 0;
121 uint32_t productCode = 0;
122 uint32_t revisionNumber = 0;
123 uint32_t serialNumber = 0;
124};
125
127void to_json(nlohmann::json& j, const SlaveConfigInfo& info);
128
138
140void to_json(nlohmann::json& j, const DeviceDiagnosticsInfo& info);
141
151
153void to_json(nlohmann::json& j, const DcSyncInfo& info);
154
166 bool useCompleteAccess = true;
169 std::string recorderDumpDir;
172 uint32_t recorderCapacity = 300000;
173};
174
182 public:
184
187
199 std::expected<void, std::string> init(std::unique_ptr<mm::comm::FieldbusDriver> driver,
200 const DeviceManagerConfig& config = {});
201
209
213 const ParameterCache& parameterCache() const;
214
220 std::expected<int, std::string> scan();
221
228 void reset();
229
232 bool initialised() const { return driver_ != nullptr; }
233
236 const std::vector<Device>& devices() const;
237
242 const Device* findDevice(uint16_t slavePosition) const;
243
253 Device* findDevice(uint16_t slavePosition);
254
261 uint64_t topologyGeneration() const;
262
279 std::expected<void, std::string> configureProcessData();
280
295 void exchangeProcessData();
296
298 bool processDataConfigured() const;
299
306 uint64_t processImageGeneration() const;
307
309 int lastWorkingCounter() const;
310
317 int expectedWorkingCounter() const;
318
324 bool processDataHealthy() const;
325
334
354 std::expected<std::string, std::string> dumpProcessData();
355
365 std::expected<std::string, std::string> dumpProcessDataBuffer();
366
372 std::vector<SlaveConfigInfo> busConfig() const;
373
391 std::expected<std::vector<DeviceStateInfo>, std::string> transitionToState(
392 const std::vector<uint16_t>& positions, mm::comm::EtherCatState targetState,
393 std::chrono::steady_clock::duration timeout);
394
403 std::expected<std::vector<DeviceStateInfo>, std::string> getDeviceStates(
404 const std::vector<uint16_t>& positions);
405
419 std::expected<std::vector<DeviceDiagnosticsInfo>, std::string> getDeviceDiagnostics(
420 const std::vector<uint16_t>& positions);
421
436 std::expected<std::vector<DcSyncInfo>, std::string> getDcSync(
437 const std::vector<uint16_t>& positions);
438
448 std::expected<mm::comm::ProcessDataWatchdogConfig, std::string> getProcessDataWatchdog(
449 uint16_t slavePosition);
450
464 std::expected<mm::comm::ProcessDataWatchdogConfig, std::string> setProcessDataWatchdog(
465 uint16_t slavePosition, std::chrono::nanoseconds timeout);
466
475 std::expected<void, std::string> initializeDeviceParameters(uint16_t slavePosition,
476 bool readValues);
477
488 std::expected<void, std::string> readAllDeviceParameters(uint16_t slavePosition);
489
501 std::expected<DeviceParameterValue, std::string> readDeviceParameter(uint16_t slavePosition,
502 uint16_t index,
503 uint8_t subindex);
504
519 std::expected<DeviceParameter, std::string> deviceParameterView(uint16_t slavePosition,
520 uint16_t index, uint8_t subindex,
521 bool refreshFromBus);
522
535 std::expected<void, std::string> writeDeviceParameter(uint16_t slavePosition, uint16_t index,
536 uint8_t subindex,
537 DeviceParameterValue newValue);
538
550 std::expected<void, std::string> writeDevicePdoMapping(uint16_t slavePosition,
551 const PdoMapping& mapping);
552
561 std::expected<PdoMapping, std::string> readDevicePdoMapping(uint16_t slavePosition);
562
578 std::vector<OutputStageResult> stageProcessDataOutputs(
579 std::span<const OutputStageRequest> requests);
580
581 // --- Off-thread sampling read surface (for monitoring) ---
582 //
583 // These let the monitoring sampler read live values from its own thread without ever blocking
584 // on the bus: SDO objects from the (refresher-fed) cache via value(); PDO objects decoded by
585 // the caller from recorder-ring records (recorderHead()/recorderOldestSeq()/readRecord()) using
586 // the layout pdoSampleSpec() captures. Thread-safe; they hand back copies, never device pointers.
587
593 std::optional<DeviceParameterValue> value(uint16_t slavePosition, uint16_t index,
594 uint8_t subindex) const;
595
599 bool isOutput;
600 uint32_t bitOffset;
601 uint16_t bitLength;
602 uint16_t dataType;
603 };
604
615 std::optional<PdoSampleSpec> pdoSampleSpec(uint16_t slavePosition, uint16_t index,
616 uint8_t subindex) const;
617
623 uint64_t recorderHead() const;
624
627 uint64_t recorderOldestSeq() const;
628
633 bool readRecord(uint64_t seq, ProcessDataRing::Record& out) const;
634
641 bool deviceExchangesProcessData(uint16_t slavePosition) const;
642
643 private:
645 struct DumpSpan {
646 uint64_t rows = 0;
647 uint64_t startSeq = 0;
648 uint64_t endSeq = 0;
649 };
650
657 std::expected<DumpSpan, std::string> serializeDump(std::ostream& out);
658
667 std::expected<void, std::string> remapProcessImage();
668
680 std::expected<std::vector<uint16_t>, std::string> resolveTargets(
681 const std::vector<uint16_t>& positions) const;
682
685 void updateExpectedWkc();
686
691 void stopExchange();
692
693 // Guards the non-RT mutable state — driver_, devices_, and the retained image generations —
694 // against the off-RT monitoring threads. Control-plane mutators (init/scan/reset/
695 // configureProcessData/transitionToState) take it exclusively; the position-based value
696 // reads called from other threads (readDeviceParameter/writeDeviceParameter) take it shared.
697 // The RT exchangeProcessData() never takes it (it is gated by the atomic image pointer
698 // instead), so the lock never touches the real-time path. Lock order, where both are taken:
699 // busMutex_ (here) before any Device-level parametersMutex_.
700 mutable std::shared_mutex busMutex_;
701 // Bumped under the exclusive lock on every scan()/reset(); see topologyGeneration().
702 std::atomic<uint64_t> topologyGeneration_{0};
703 // Bumped every time remapProcessImage() publishes a new image; see processImageGeneration().
704 std::atomic<uint64_t> processImageGeneration_{0};
705 std::unique_ptr<mm::comm::FieldbusDriver> driver_;
706 std::vector<Device> devices_;
707 std::unique_ptr<ProcessData> pd_;
708 // On-disk parameter-definition cache, shared by every Device (handed to each by pointer at
709 // scan()). Outlives the device set, which is rebuilt on every scan/reset. Configured at init().
710 ParameterCache parameterCache_;
711 // Runtime tuning captured at init(); drives recorder-ring sizing at configureProcessData.
712 DeviceManagerConfig config_;
713};
714
723void to_json(nlohmann::json& j, const DeviceManager& dm);
724
725} // namespace mm::node
Owns the fieldbus driver and node collection, and drives PDO exchange.
Definition device_manager.h:181
std::expected< mm::comm::ProcessDataWatchdogConfig, std::string > setProcessDataWatchdog(uint16_t slavePosition, std::chrono::nanoseconds timeout)
Sets the process-data (sync-manager) watchdog timeout of one device.
Definition device_manager.cc:925
uint64_t recorderOldestSeq() const
The oldest sequence number still present in the ring (max(0, head - capacity)). A cursor below this h...
Definition device_manager.cc:376
uint64_t topologyGeneration() const
Monotonic counter bumped every time the device set is rebuilt (scan / reset).
Definition device_manager.cc:206
std::expected< std::string, std::string > dumpProcessDataBuffer()
Serialises the recorder dump into an in-memory buffer — the same .mmpd bytes dumpProcessData writes t...
Definition device_manager.cc:574
uint64_t recorderHead() const
The recorder ring's next sequence number; recorderHead()-1 is the newest recorded cycle and recorderH...
Definition device_manager.cc:374
std::expected< int, std::string > scan()
Scans the bus for nodes and populates the device list.
Definition device_manager.cc:146
const ParameterCache & parameterCache() const
The on-disk parameter cache, for the management API (list / download / remove).
Definition device_manager.cc:144
bool readRecord(uint64_t seq, ProcessDataRing::Record &out) const
Copies the recorded cycle for seq into out. Thread-safe, lock-free.
Definition device_manager.cc:378
bool deviceExchangesProcessData(uint16_t slavePosition) const
Whether the device at slavePosition is currently exchanging (SAFE-OP/OP). Thread-safe; reads the driv...
Definition device_manager.cc:1060
std::expected< void, std::string > writeDeviceParameter(uint16_t slavePosition, uint16_t index, uint8_t subindex, DeviceParameterValue newValue)
Convenience: finds a device by position and writes one of its parameters.
Definition device_manager.cc:1107
int expectedWorkingCounter() const
The working counter expected from the devices currently exchanging (SAFE-OP/OP).
Definition device_manager.cc:394
std::expected< void, std::string > initializeDeviceParameters(uint16_t slavePosition, bool readValues)
Enumerates the CoE object dictionary of one device and populates its parameter map....
Definition device_manager.cc:936
const std::vector< Device > & devices() const
Returns the list of discovered devices.
Definition device_manager.cc:210
void exchangeProcessData()
Exchanges one cycle of process data: sends staged outputs, captures inputs.
Definition device_manager.cc:299
std::optional< PdoSampleSpec > pdoSampleSpec(uint16_t slavePosition, uint16_t index, uint8_t subindex) const
Resolves a PDO-mapped object's decode spec from the published image. Thread-safe.
Definition device_manager.cc:1037
std::expected< std::vector< DcSyncInfo >, std::string > getDcSync(const std::vector< uint16_t > &positions)
Reads live distributed-clock synchronisation status for a set of devices, resolving each slave's devi...
Definition device_manager.cc:886
DeviceManager()
Definition device_manager.cc:38
uint64_t processImageGeneration() const
Monotonic counter bumped every time a new process image is published (each (re)map).
Definition device_manager.cc:386
std::expected< DeviceParameterValue, std::string > readDeviceParameter(uint16_t slavePosition, uint16_t index, uint8_t subindex)
Convenience: finds a device by position and reads one of its parameters.
Definition device_manager.cc:1066
std::expected< std::vector< DeviceStateInfo >, std::string > getDeviceStates(const std::vector< uint16_t > &positions)
Reads the current AL state for a set of devices.
Definition device_manager.cc:838
std::expected< std::string, std::string > dumpProcessData()
Serialises the recorder's current span to a .mmpd dump file and returns its path.
Definition device_manager.cc:529
std::optional< DeviceParameterValue > value(uint16_t slavePosition, uint16_t index, uint8_t subindex) const
Returns a copy of a parameter's cached value, no bus access. Thread-safe.
Definition device_manager.cc:1027
std::vector< OutputStageResult > stageProcessDataOutputs(std::span< const OutputStageRequest > requests)
Stages a batch of output objects into the process image in one call.
Definition device_manager.cc:1147
bool processDataHealthy() const
Whether every device that should be exchanging is contributing to the cycle.
Definition device_manager.cc:398
std::expected< void, std::string > readAllDeviceParameters(uint16_t slavePosition)
Refreshes the cached value of every readable parameter of one device, in place.
Definition device_manager.cc:957
std::vector< SlaveConfigInfo > busConfig() const
Snapshots each slave's static ESC configuration (SM, FMMU, mailbox, DC) for the API.
Definition device_manager.cc:585
std::expected< PdoMapping, std::string > readDevicePdoMapping(uint16_t slavePosition)
Convenience: finds a device by position and reads its PDO mapping grouped by object.
Definition device_manager.cc:1136
std::expected< mm::comm::ProcessDataWatchdogConfig, std::string > getProcessDataWatchdog(uint16_t slavePosition)
Reads the process-data (sync-manager) watchdog configuration of one device.
Definition device_manager.cc:913
std::expected< void, std::string > init(std::unique_ptr< mm::comm::FieldbusDriver > driver, const DeviceManagerConfig &config={})
Takes ownership of driver and initialises it.
Definition device_manager.cc:113
bool processDataConfigured() const
Whether configureProcessData has published a process image for exchange.
Definition device_manager.cc:382
std::expected< std::vector< DeviceStateInfo >, std::string > transitionToState(const std::vector< uint16_t > &positions, mm::comm::EtherCatState targetState, std::chrono::steady_clock::duration timeout)
Transitions a set of devices to targetState, blocking until all arrive or timeout elapses,...
Definition device_manager.cc:649
void reset()
Stops the fieldbus driver and clears the device list.
Definition device_manager.cc:187
std::expected< void, std::string > writeDevicePdoMapping(uint16_t slavePosition, const PdoMapping &mapping)
Convenience: finds a device by position and writes its PDO mapping.
Definition device_manager.cc:1122
std::expected< std::vector< DeviceDiagnosticsInfo >, std::string > getDeviceDiagnostics(const std::vector< uint16_t > &positions)
Reads live ESC health diagnostics (link quality, error counters, watchdogs) for a set of devices,...
Definition device_manager.cc:860
std::expected< DeviceParameter, std::string > deviceParameterView(uint16_t slavePosition, uint16_t index, uint8_t subindex, bool refreshFromBus)
Returns a full parameter struct (value + metadata), optionally refreshed from the bus.
Definition device_manager.cc:1081
std::expected< void, std::string > configureProcessData()
Maps process data and publishes the process image for exchange.
Definition device_manager.cc:226
const Device * findDevice(uint16_t slavePosition) const
Finds a device by its 1-based bus position.
Definition device_manager.cc:212
~DeviceManager()
Defined out-of-line so unique_ptr<ProcessData> can hold an incomplete type.
void configureParameterCache(const ParameterCacheConfig &config)
Sets the on-disk parameter-cache policy and location.
Definition device_manager.cc:140
int lastWorkingCounter() const
The working counter from the most recent process-data exchange (0 before any).
Definition device_manager.cc:390
bool initialised() const
Whether a driver is currently held (i.e. init() has succeeded and reset() has not since been called).
Definition device_manager.h:232
ProcessImageInfo processImageInfo() const
Snapshots the published process image and its runtime health for the API.
Definition device_manager.cc:400
Represents a single node on the fieldbus.
Definition device.h:36
On-disk cache of CoE parameter definitions, keyed by device identity.
Definition parameter_cache.h:55
EtherCatState
EtherCAT Application Layer state values.
Definition fieldbus_driver.h:34
Definition http_server.h:16
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:24
void to_json(nlohmann::json &j, const Device &d)
Serialises a Device to JSON.
Definition device.cc:915
Live distributed-clock synchronisation status for one slave, read from its ESC.
Definition fieldbus_driver.h:290
Static ESC configuration snapshot for one slave, captured by configureProcessData.
Definition fieldbus_driver.h:228
Decoded health diagnostics for one slave, read live from its ESC registers.
Definition fieldbus_driver.h:265
A slave's live distributed-clock sync status plus its resolved device name.
Definition device_manager.h:147
mm::comm::DcSyncDiagnostics dcSync
Decoded DC sync status as read by the driver.
Definition device_manager.h:148
std::string deviceName
Device name for this slave position, empty if unknown.
Definition device_manager.h:149
A slave's live ESC health diagnostics plus its resolved device name.
Definition device_manager.h:134
std::string deviceName
Device name for this slave position, empty if unknown.
Definition device_manager.h:136
mm::comm::SlaveDiagnostics diagnostics
Decoded ESC counters as read by the driver.
Definition device_manager.h:135
Runtime tuning passed to DeviceManager::init. Every field has a sensible default, so a caller can pas...
Definition device_manager.h:158
bool useCompleteAccess
Definition device_manager.h:166
bool readObjectDictionaryOnPreop
Definition device_manager.h:162
uint32_t recorderCapacity
Definition device_manager.h:172
std::string recorderDumpDir
Definition device_manager.h:169
Everything needed to decode one PDO object from a raw process-image snapshot: which image it lives in...
Definition device_manager.h:598
uint16_t dataType
ETG.1020 data-type code, for decoding the extracted bytes.
Definition device_manager.h:602
uint16_t bitLength
Width of the value in bits.
Definition device_manager.h:601
bool isOutput
True if the object is in the output image (RxPDO), false for input.
Definition device_manager.h:599
uint32_t bitOffset
Absolute bit offset within that direction's image.
Definition device_manager.h:600
Current AL state snapshot for a single device.
Definition device_manager.h:30
uint16_t alStatus
Raw AL Status register (bits 3:0 = state, bit 4 = error indicator).
Definition device_manager.h:32
uint16_t slavePosition
1-based position on the fieldbus.
Definition device_manager.h:31
uint16_t alState
AL state decoded from alStatus (1=Init, 2=PreOp, 3=Boot, 4=SafeOp, 8=Op).
Definition device_manager.h:33
uint16_t alStatusCode
AL Status Code (ETG.1000.6 §6.4.1); non-zero when error is true.
Definition device_manager.h:35
bool error
True when the AL Status error indicator bit is set.
Definition device_manager.h:34
One object to stage into the output process image, as parsed from a batch write request.
Definition device_manager.h:86
DeviceParameterValue value
Value to write; coerced to the object's declared type.
Definition device_manager.h:90
uint16_t slavePosition
1-based bus position of the owning device.
Definition device_manager.h:87
uint16_t index
CoE object index.
Definition device_manager.h:88
uint8_t subindex
CoE object subindex.
Definition device_manager.h:89
Per-object outcome of a batch output stage.
Definition device_manager.h:99
bool staged
Whether the value was staged into the cyclic output image.
Definition device_manager.h:103
uint8_t subindex
Echoes the request.
Definition device_manager.h:102
uint16_t index
Echoes the request.
Definition device_manager.h:101
uint16_t slavePosition
Echoes the request.
Definition device_manager.h:100
std::string error
Empty on success; otherwise why the object was not staged.
Definition device_manager.h:104
Policy and location for the on-disk parameter cache.
Definition parameter_cache.h:28
A device's desired PDO configuration to write and assign — the write-side input to Device::writePdoMa...
Definition pdo_mapping.h:89
One recorded cycle, copied out by a reader. inputs / outputs are the raw IOmap bytes for that cycle (...
Definition process_data_ring.h:38
API-facing snapshot of the currently published process image and its runtime health.
Definition device_manager.h:64
std::vector< ProcessImageObjectInfo > inputs
Input-mapped objects in image order.
Definition device_manager.h:73
uint32_t outputBytes
Size of the output image (master→slave).
Definition device_manager.h:66
bool healthy
Whether the last working counter meets the expected value.
Definition device_manager.h:70
std::vector< ProcessImageObjectInfo > outputs
Output-mapped objects in image order.
Definition device_manager.h:72
std::size_t generations
Number of process images retained since the last reset().
Definition device_manager.h:71
int expectedWkc
Working counter expected from the devices currently exchanging.
Definition device_manager.h:68
uint32_t inputBytes
Size of the input image (slave→master).
Definition device_manager.h:67
bool configured
Whether an image is currently published for exchange.
Definition device_manager.h:65
int lastWkc
Working counter from the most recent exchange (0 before any).
Definition device_manager.h:69
One mapped object in the published process image, with its name resolved.
Definition device_manager.h:46
uint8_t subindex
CoE object subindex.
Definition device_manager.h:49
uint32_t bitOffset
Absolute bit offset within the direction's image.
Definition device_manager.h:51
uint16_t bitLength
Width of the value in bits.
Definition device_manager.h:52
uint16_t slavePosition
1-based bus position of the owning device.
Definition device_manager.h:47
std::string name
Object name, or empty if the OD has not been enumerated.
Definition device_manager.h:50
uint16_t index
CoE object index.
Definition device_manager.h:48
A slave's static ESC configuration plus its resolved device name.
Definition device_manager.h:115
std::string deviceName
Device name for this slave position, empty if unknown.
Definition device_manager.h:117
uint32_t serialNumber
Serial number from EEPROM.
Definition device_manager.h:123
uint32_t vendorId
Vendor ID from EEPROM.
Definition device_manager.h:120
uint32_t revisionNumber
Revision number from EEPROM.
Definition device_manager.h:122
uint32_t productCode
Product code from EEPROM.
Definition device_manager.h:121
mm::comm::SlaveConfig config
Raw ESC configuration as captured by the driver.
Definition device_manager.h:116