From 5bbf53a37608a313a355ffd2b1c1aa01dcb9ec90 Mon Sep 17 00:00:00 2001 From: Bjarne von Horn Date: Tue, 11 Mar 2025 19:07:01 +0100 Subject: [PATCH 1/3] Fix FakeEtherCAT Domain activation. --- fake_lib/fakeethercat.cpp | 8 +++++++- fake_lib/fakeethercat.h | 2 +- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/fake_lib/fakeethercat.cpp b/fake_lib/fakeethercat.cpp index b60b1994..d7eb006a 100644 --- a/fake_lib/fakeethercat.cpp +++ b/fake_lib/fakeethercat.cpp @@ -105,7 +105,7 @@ ec_domain::ec_domain(rtipc *rtipc, const char *prefix, ec_master_t *master) : rt { } -int ec_domain::activate(int domain_id) +int ec_domain::activate() { std::unordered_set slaves; @@ -211,6 +211,12 @@ int ecrt_domain_state( int ec_master::activate() { + for (auto &domain : domains) + { + if (domain.activate()) + return -1; + } + { std::ofstream out(rt_ipc_dir + "/" + rt_ipc_name + "_slaves.json"); if (!out.is_open()) diff --git a/fake_lib/fakeethercat.h b/fake_lib/fakeethercat.h index 71bd21dc..ff83dbd2 100644 --- a/fake_lib/fakeethercat.h +++ b/fake_lib/fakeethercat.h @@ -180,7 +180,7 @@ public: return const_cast(data.data()); } - int activate(int domain_id); + int activate(); int process(); int queue(); From 7036da66f415b1b698ea0a147211914ba9932ddd Mon Sep 17 00:00:00 2001 From: Bjarne von Horn Date: Tue, 11 Mar 2025 19:07:47 +0100 Subject: [PATCH 2/3] Add EtherCAT Master id to rtipc directory. Currently, having multiple rtipc instances with the same cache directory in one application does not work. So we use one directory per master instance. --- fake_lib/fakeethercat.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fake_lib/fakeethercat.cpp b/fake_lib/fakeethercat.cpp index d7eb006a..80f769d1 100644 --- a/fake_lib/fakeethercat.cpp +++ b/fake_lib/fakeethercat.cpp @@ -420,16 +420,16 @@ static const char *getName() return "FakeEtherCAT"; } -static const char *getRtIpcDir() +static std::string getRtIpcDir(int idx) { if (const auto ans = getenv("FAKE_EC_HOMEDIR")) { - return ans; + return ans + std::string("/") + std::to_string(idx); } - return "/tmp/FakeEtherCAT"; + return "/tmp/FakeEtherCAT/" + std::to_string(idx); } -ec_master::ec_master(int id) : rt_ipc_dir(getRtIpcDir()), rt_ipc_name(getName()), rt_ipc(rtipc_create(rt_ipc_name.c_str(), rt_ipc_dir.c_str())), id_(id) +ec_master::ec_master(int id) : rt_ipc_dir(getRtIpcDir(id)), rt_ipc_name(getName()), rt_ipc(rtipc_create(rt_ipc_name.c_str(), rt_ipc_dir.c_str())), id_(id) { } From 5f75f566ce6c1f82f5af749c7109232a76686ffc Mon Sep 17 00:00:00 2001 From: Bjarne von Horn Date: Wed, 12 Mar 2025 14:08:26 +0100 Subject: [PATCH 3/3] Create rtipc directories on startup --- fake_lib/README.md | 3 ++- fake_lib/fakeethercat.cpp | 31 ++++++++++++++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/fake_lib/README.md b/fake_lib/README.md index 0b8c76d9..3ceb1a91 100644 --- a/fake_lib/README.md +++ b/fake_lib/README.md @@ -65,13 +65,14 @@ export FAKE_EC_HOMEDIR=/tmp/FakeEtherCAT rm -rf $FAKE_EC_HOMEDIR mkdir -p $FAKE_EC_HOMEDIR ``` +For each master instance, one subdirectory named by the master id is created. ### Spin up your application Now it's time to simply launch your application. You will notice that the PDO configuration will be dumped at stderr. The path displayed is the path of the RtIPC variable in the following format: -`$FAKE_EC_PREFIX/$MASTER_ID/$DOMAIN_ID/$ALIAS$POSITION/$PDO`. +`$FAKE_EC_PREFIX/$MASTER_ID/$ALIAS$POSITION/$PDO`. ## How to emulate EtherCAT slaves diff --git a/fake_lib/fakeethercat.cpp b/fake_lib/fakeethercat.cpp index 80f769d1..ca588db8 100644 --- a/fake_lib/fakeethercat.cpp +++ b/fake_lib/fakeethercat.cpp @@ -30,6 +30,7 @@ #include #include #include +#include static std::ostream &operator<<(std::ostream &os, const sdo_address &a) { @@ -420,13 +421,37 @@ static const char *getName() return "FakeEtherCAT"; } +static int mkpath(const std::string &file_path) +{ + if (file_path.empty()) + return 0; + + std::size_t offset = 0; + do + { + offset = file_path.find('/', offset + 1); + const auto subpath = file_path.substr(0, offset); + if (mkdir(subpath.c_str(), 0755) == -1) + { + if (errno != EEXIST) + { + return -1; + } + } + } while (offset != std::string::npos); + return 0; +} + static std::string getRtIpcDir(int idx) { - if (const auto ans = getenv("FAKE_EC_HOMEDIR")) + std::string ans; + if (const auto e = getenv("FAKE_EC_HOMEDIR")) { - return ans + std::string("/") + std::to_string(idx); + ans = e + std::string("/") + std::to_string(idx); } - return "/tmp/FakeEtherCAT/" + std::to_string(idx); + ans = "/tmp/FakeEtherCAT/" + std::to_string(idx); + mkpath(ans); + return ans; } ec_master::ec_master(int id) : rt_ipc_dir(getRtIpcDir(id)), rt_ipc_name(getName()), rt_ipc(rtipc_create(rt_ipc_name.c_str(), rt_ipc_dir.c_str())), id_(id)