ifw-fcf 8.0.2
 
Loading...
Searching...
No Matches
fcfCommHelpers.hpp
Go to the documentation of this file.
1
23
24#ifndef IFW_FCF_DEVMGR_COMMON_FCF_COMM_HELPERS_HPP_
25#define IFW_FCF_DEVMGR_COMMON_FCF_COMM_HELPERS_HPP_
26
27#include <chrono>
28#include <functional>
29#include <stdexcept>
30#include <string>
31#include <utility>
32#include <variant>
33#include <vector>
34
35#include <fmt/format.h>
36
37#include <ifw/fnd/defs/iCommAdapter.hpp>
38
39#include <eso/uatools/ualib/client.hpp>
40
42
58 template <typename... Args>
59 std::vector<ifw::fnd::defs::CallArgument>
60 MakeCallArgs(Args&&... args) {
61 return {
62 ifw::fnd::defs::CallArgument{
63 /*name=*/"",
64 /*value=*/ifw::fnd::defs::Value(std::forward<Args>(args))
65 }...
66 };
67 }
68
83 inline void
84 CheckRpcReply(const ifw::fnd::defs::CallResult& result,
85 const std::string& what,
86 const std::function<std::string(short)>& error_message_fn) {
87 // Wire-level call failure (transport, BadInvalidState, ...).
88 if (result.status != ifw::fnd::defs::Status::Ok) {
89 throw std::runtime_error(fmt::format(
90 "RPC {} failed: {}", what, result.message));
91 }
92 // FCF convention: every device-controller RPC returns one
93 // short. A missing return slot means the ICD doesn't match what
94 // we sent.
95 if (result.output_arguments.empty()) {
96 throw std::runtime_error(fmt::format(
97 "RPC {} returned no output (ICD mismatch)", what));
98 }
99 const auto& out_val = result.output_arguments.front().data.value;
100 short reply = 0;
101 try {
102 reply = std::get<short>(out_val);
103 } catch (const std::bad_variant_access&) {
104 throw std::runtime_error(fmt::format(
105 "RPC {} return type does not match a short (check the ICD)",
106 what));
107 }
108 if (reply != 0) {
109 throw std::runtime_error(error_message_fn(reply));
110 }
111 }
112
130 inline constexpr std::chrono::milliseconds kRpcTimeout{60'000};
131
132 inline void
133 ExecuteRpcCall(ifw::fnd::defs::ICommAdapter& comm,
134 const std::string& method_node_id,
135 std::vector<ifw::fnd::defs::CallArgument> args,
136 const std::string& what,
137 const std::function<std::string(short)>& error_message_fn,
138 const std::string& object_node_id = "") {
139 ifw::fnd::defs::CallRequest req;
140 req.method = method_node_id;
141 req.input_arguments = std::move(args);
142 req.options.timeout = kRpcTimeout;
143 // OPC UA Call needs the parent object of the method. ualib can
144 // derive it from a dotted method NodeId, but FCF already knows it
145 // exactly (the '#'-decoded prefix), so pass it explicitly — this
146 // is both faster and unambiguous for servers whose method NodeId is
147 // not the dotted parent of the object.
148 if (!object_node_id.empty()) {
149 req.options.properties.Set("object", object_node_id);
150 }
151 auto res = comm.Call(req);
152 CheckRpcReply(res, what, error_message_fn);
153 }
154
155} // namespace ifw::fcf::devmgr::common
156
157#endif // IFW_FCF_DEVMGR_COMMON_FCF_COMM_HELPERS_HPP_
ActionMgr class source file.
Definition actionMgr.cpp:28
constexpr std::chrono::milliseconds kRpcTimeout
Convenience: call + check in one go. Most FCF RPC call sites become a single line with this.
Definition fcfCommHelpers.hpp:130
void ExecuteRpcCall(ifw::fnd::defs::ICommAdapter &comm, const std::string &method_node_id, std::vector< ifw::fnd::defs::CallArgument > args, const std::string &what, const std::function< std::string(short)> &error_message_fn, const std::string &object_node_id="")
Definition fcfCommHelpers.hpp:133
void CheckRpcReply(const ifw::fnd::defs::CallResult &result, const std::string &what, const std::function< std::string(short)> &error_message_fn)
Translate the short-typed reply of an FCF RPC call into a throw-if-non-zero check.
Definition fcfCommHelpers.hpp:84
std::vector< ifw::fnd::defs::CallArgument > MakeCallArgs(Args &&... args)
Build a vector of positional CallArguments from any number of typed values.
Definition fcfCommHelpers.hpp:60