APIs, concepts, guides, and more
print-network-topology.cpp
/* This sample app demonstrates how to print the network topology
including nodes, states, and configuration details.
*/
#include <iomanip>
#include <iostream>
#include <map>
#include <sstream>
#include <vector>
#include "helpers.h" // import our helper functions.
#include "config.h" // import our configuration.
#include "rsi.h" // import our RapidCode Library.
using namespace RSI::RapidCode; // Import the RapidCode namespace
// map of the RSINetworkType enum to string
static const std::map<RSINetworkType, std::string> RSINetworkTypeMap = {
{RSINetworkType::RSINetworkTypeSTRING, "RSINetworkTypeSTRING"},
{RSINetworkType::RSINetworkTypeDUAL_STRING, "RSINetworkTypeDUAL_STRING"},
{RSINetworkType::RSINetworkTypeRING, "RSINetworkTypeRING"}
};
// map of the RSINetworkState enum to string
static const std::map<RSINetworkState, std::string> RSINetworkStateMap = {
{RSINetworkState::RSINetworkStateUNINITIALIZED, "RSINetworkStateUNINITIALIZED"},
{RSINetworkState::RSINetworkStateDISCOVERING, "RSINetworkStateDISCOVERING"},
{RSINetworkState::RSINetworkStateDISCOVERED, "RSINetworkStateDISCOVERED"},
{RSINetworkState::RSINetworkStatePREOPERATIONAL, "RSINetworkStatePREOPERATIONAL"},
{RSINetworkState::RSINetworkStateOPERATIONAL, "RSINetworkStateOPERATIONAL"},
{RSINetworkState::RSINetworkStateERROR, "RSINetworkStateERROR"},
{RSINetworkState::RSINetworkStateSHUTDOWN, "RSINetworkStateSHUTDOWN"},
{RSINetworkState::RSINetworkStateSTARTING, "RSINetworkStateSTARTING"}
};
// constants for reading the device type from the Mdp
struct MdpConstants
{
static constexpr int DEVICE_TYPE_INDEX = 0x1000;
static constexpr int DEVICE_TYPE_SUB_INDEX = 0;
static constexpr int DEVICE_TYPE_BYTE_SIZE = 4;
};
// helper function to get the list of network nodes from the controller
static std::vector<RapidCodeNetworkNode *> GetNodeList(MotionController *controller)
{
std::vector<RapidCodeNetworkNode *> nodes;
for (int i = 0; i < controller->NetworkNodeCountGet(); ++i)
{
RapidCodeNetworkNode *node = controller->NetworkNodeGet(i);
if (node == nullptr)
{
throw std::runtime_error("Error creating the network node, it is null.");
}
if (!node->Exists())
{
throw std::runtime_error("The network node should exist after we get it.");
}
nodes.push_back(node);
}
return nodes;
}
// helper function to get the device type of a node from the Mdp
static std::string GetDeviceType(RapidCodeNetworkNode *node)
{
std::string deviceType = "";
try
{
uint32_t deviceTypeValue =
node->ServiceChannelRead(MdpConstants::DEVICE_TYPE_INDEX, MdpConstants::DEVICE_TYPE_SUB_INDEX, MdpConstants::DEVICE_TYPE_BYTE_SIZE);
std::ostringstream deviceTypeStream;
deviceTypeStream << "0x" << std::uppercase << std::setfill('0') << std::setw(8) << std::hex << deviceTypeValue;
deviceType = deviceTypeStream.str();
}
catch (std::exception err)
{
deviceType = "Exception trying to read device type";
}
return deviceType;
}
// helper function to read the information of a node into a string
static std::string ReadNodeInfo(RapidCodeNetworkNode *node)
{
std::ostringstream nodeInfo;
nodeInfo << "\n"; // for spacing
nodeInfo << "Node[" << node->NumberGet() << "] - " << node->NameGet() << " ______________________________________________\n";
nodeInfo << " Vendor: " << node->VendorNameGet();
nodeInfo << " Product: " << node->ProductNameGet() << "\n";
nodeInfo << " VendorID: 0x" << std::hex << std::setw(8) << std::setfill('0') << node->VendorIdGet();
nodeInfo << " ProductCode: 0x" << std::setw(8) << node->ProductCodeGet() << "\n";
nodeInfo << " HardwareRev: 0x" << std::setw(8) << node->RevisionGet();
nodeInfo << " SerialNumber: " << node->SerialNumberGet() << "\n";
nodeInfo << " StationAlias: 0x" << std::setw(8) << node->StationAliasGet();
nodeInfo << " AxisCount: " << std::dec << node->AxisCountGet() << "\n";
nodeInfo << " DeviceType: " << GetDeviceType(node);
nodeInfo << " (For Mdp by reading SDO 0x" << std::hex << std::setw(4) << MdpConstants::DEVICE_TYPE_INDEX << ")\n";
nodeInfo << " SegmentCount: " << node->SegmentCountGet() << "\n";
nodeInfo << " DI: " << node->DigitalInCountGet();
nodeInfo << " DO: " << node->DigitalOutCountGet();
nodeInfo << " AI: " << node->AnalogInCountGet();
nodeInfo << " AO: " << node->AnalogOutCountGet() << "\n";
return nodeInfo.str();
}
int main()
{
const std::string SAMPLE_APP_NAME = "📜 Utilities: Print Network Topology";
// print a start message to indicate that the sample app has started
Helpers::PrintHeader(SAMPLE_APP_NAME);
/* RAPIDCODE INITIALIZATION */
// Create the controller
int exitCode = -1; // Set the exit code to an error value.
try // Ensure that the controller is deleted if an error occurs.
{
Helpers::CheckErrors(controller);
/* SAMPLE APP BODY */
// Get the nodes
std::vector<RapidCodeNetworkNode *> nodes = GetNodeList(controller);
// Print the network topology
std::ostringstream topologyInfo;
// Add the overview information
topologyInfo << "EtherCAT: " << std::to_string(nodes.size());
topologyInfo << " Nodes, " << RSINetworkTypeMap.at(controller->NetworkTypeGet());
topologyInfo << " " << RSINetworkStateMap.at(controller->NetworkStateGet()) << "\n";
// Add information for each node
for (RapidCodeNetworkNode *node : nodes)
{
topologyInfo << ReadNodeInfo(node);
}
// Add network input information
topologyInfo << "\nNetworkInputs count: " << controller->NetworkInputCountGet() << " _________________________________\n";
for (int i = 0; i < controller->NetworkInputCountGet(); ++i)
{
topologyInfo << " [" << i << "] - " << std::setw(70) << controller->NetworkInputNameGet(i);
topologyInfo << " Bits: " << controller->NetworkInputBitSizeGet(i) << "\n";
}
// Add network output information
topologyInfo << "NetworkOutputs count: " << controller->NetworkOutputCountGet() << " _________________________________\n";
for (int i = 0; i < controller->NetworkOutputCountGet(); ++i)
{
topologyInfo << " [" << i << "] - " << std::setw(70) << controller->NetworkOutputNameGet(i);
topologyInfo << " Bits: " << controller->NetworkOutputBitSizeGet(i) << "\n";
}
// Print the accumulated string
std::cout << topologyInfo.str() << std::endl;
exitCode = 0;
}
catch (const std::exception &ex)
{
std::cerr << ex.what() << std::endl;
exitCode = -1;
}
// delete the controller as the program exits to ensure memory is deallocated in the correct order
controller->Delete();
// print a message to indicate the sample app has finished and if it was successful or not
Helpers::PrintFooter(SAMPLE_APP_NAME, exitCode);
return exitCode;
}
static MotionController * Create(CreationParameters *creationParameters)
Initialize and start the RMP EtherCAT controller.
Represents the RMP soft motion controller. This class provides an interface to general controller con...
Definition rsi.h:800
@ RSINetworkStatePREOPERATIONAL
EtherCAT preoperational.
Definition rsienums.h:572
@ RSINetworkStateSHUTDOWN
EtherCAT was shutdown or stopped, must restart.
Definition rsienums.h:575
@ RSINetworkStateDISCOVERED
EtherCAT nodes discovered but not started.
Definition rsienums.h:571
@ RSINetworkStateDISCOVERING
EtherCAT network is in the process of discovering nodes.
Definition rsienums.h:570
@ RSINetworkStateOPERATIONAL
EtherCAT operational, good state.
Definition rsienums.h:573
@ RSINetworkStateSTARTING
EtherCAT is starting.
Definition rsienums.h:576
@ RSINetworkStateUNINITIALIZED
EtherCAT not yet started.
Definition rsienums.h:569
@ RSINetworkTypeRING
A Ring topology is a chain of linked Node(s) going from the Controllers Out port to the In port.
Definition rsienums.h:629
@ RSINetworkTypeSTRING
A String topology is chain of linked Node(s) to the Controller from the In or Out port.
Definition rsienums.h:627
@ RSINetworkTypeDUAL_STRING
A Dual String topology is two chained links of Node(s) to the Controller from the In and Out ports.
Definition rsienums.h:628
MotionController::CreationParameters GetCreationParameters()
Returns a MotionController::CreationParameters object with user-defined parameters.
Definition config.h:68
void CheckErrors(RapidCodeObject *rsiObject, const std::source_location &location=std::source_location::current())
Checks for errors in the given RapidCodeObject and throws an exception if any non-warning errors are ...
Definition helpers.h:32
void PrintHeader(std::string sampleAppName)
[NetworkShutdown]
Definition helpers.h:146
void PrintFooter(std::string sampleAppName, int exitCode)
[PrintHeader]
Definition helpers.h:162
CreationParameters for MotionController::Create.
Definition rsi.h:866