From 4fd0550de3287124208ef257fd4606e630f7287f Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Fri, 22 Nov 2024 23:32:18 +0300 Subject: [PATCH] ... --- net/adc_device_netclient.h | 195 ++++++++++++++++++++++--------------- 1 file changed, 117 insertions(+), 78 deletions(-) diff --git a/net/adc_device_netclient.h b/net/adc_device_netclient.h index 96ebe25..0efa20e 100644 --- a/net/adc_device_netclient.h +++ b/net/adc_device_netclient.h @@ -151,8 +151,77 @@ public: } + // general-purpose server communication methods + + // blocking + template + R serverCall(ServerResponseType& rtype, std::string_view key, ArgTs&&... args) + { + typename netservice_t::send_msg_t bytes; + + AdcDeviceProtoMessage msg(bytes); + msg.setKeyValue(key, std::forward(args)...); + + return getFromServer(key, bytes, rtype); + } + + template + default_server_resp_t serverCall(ServerResponseType& rtype, std::string_view key, ArgTs&&... args) + { + return serverCall(rtype, key, std::forward(args)...); + } + + + // asynchronous + template CallbackT, typename... ArgTs> + auto asyncServerCall(std::string_view key, CallbackT&& callback_func, ArgTs&&... args) + { + auto bytes = std::shared_ptr(); + + AdcDeviceProtoMessage msg(*bytes); + msg.setKeyValue(key, std::forward(args)...); + + asyncSendRecv(*bytes, [bytes, key, wrapper = traits::adc_pf_wrapper(std::forward(callback_func)), + this](auto err, auto rmsg) mutable { + if (err) { + _clientPtr->logError("An error occured while receiving server respond: {}", + netservice_t::formattableError(err)); + } else { + try { + ServerResponseType type; + auto attrs = checkserverCall(key, rmsg, type); + + std::forward(std::get<0>(wrapper))(type, attrs); + + } catch (const std::system_error& err) { + _clientPtr->logError("An error occured while getting server respond: {}", err.what()); + } + } + }); + } + + // ADC device helper methods (blocking) + // send client HELLO-message + template + R clientHello(ServerResponseType& rtype, SenderNameT&& name, ParamTs&&... params) + { + // expected respond: ACK HELLO ... + // return HELLO ... (or error description 'code category what') + return serverCall(rtype, constants::ADC_DEVICE_NETPROTO_KEY_HELLO, std::forward(name), + std::forward(params)...); + } + + template + default_server_resp_t clientHello(ServerResponseType& rtype, SenderNameT&& name, ParamTs&&... params) + { + return clientHello(rtype, std::forward(name), + std::forward(params)...); + } + // get names of devices template @@ -160,7 +229,7 @@ public: { // expected respond: ACK NAMES DEV1 DEV2 ... // return DEV1 DEV2 ... (or error description 'code category what') - return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, rtype); + return serverCall(rtype, constants::ADC_DEVICE_NETPROTO_KEY_NAMES); } default_server_resp_t deviceNames(ServerResponseType& rtype) @@ -170,51 +239,49 @@ public: // bind device to the client template - R bindDevice(DevNameT&& dev_name, ServerResponseType& rtype) + R bindDevice(ServerResponseType& rtype, DevNameT&& dev_name) { // expected respond: ACK DEVICE DEV_NAME // return DEV_NAME (or error description 'code category what') - return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_DEVICE, rtype, - std::forward(dev_name)); + return serverCall(rtype, constants::ADC_DEVICE_NETPROTO_KEY_DEVICE, std::forward(dev_name)); } template - default_server_resp_t bindDevice(DevNameT&& dev_name, ServerResponseType& rtype) + default_server_resp_t bindDevice(ServerResponseType& rtype, DevNameT&& dev_name) { - return bindDevice(std::forward(dev_name), rtype); + return bindDevice(rtype, std::forward(dev_name)); } // execute a command template - R exec(CmdNameT&& cmd_name, ServerResponseType& rtype) + R exec(ServerResponseType& rtype, CmdNameT&& cmd_name) { // expected respond: ACK CMD CMD_NAME // return CMD_NAME ... (or error description 'code category what') - return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_CMD, rtype, std::forward(cmd_name)); + return serverCall(rtype, constants::ADC_DEVICE_NETPROTO_KEY_CMD, std::forward(cmd_name)); } template - default_server_resp_t exec(CmdNameT&& cmd_name, ServerResponseType& rtype) + default_server_resp_t exec(ServerResponseType& rtype, CmdNameT&& cmd_name) { - return exec(std::forward(cmd_name), rtype); + return exec(rtype, std::forward(cmd_name)); } // get an attribute value template - R getAttr(AttrNameT&& attr_name, ServerResponseType& rtype) + R getAttr(ServerResponseType& rtype, AttrNameT&& attr_name) { // expected respond: ACK GET ATTR_NAME ATTR_VALUE // return ATTR_NAME ATTR_VALUE (or error description 'code category what') - return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_GET, rtype, - std::forward(attr_name)); + return serverCall(rtype, constants::ADC_DEVICE_NETPROTO_KEY_GET, std::forward(attr_name)); } template - default_server_resp_t getAttr(AttrNameT&& attr_name, ServerResponseType& rtype) + default_server_resp_t getAttr(ServerResponseType& rtype, AttrNameT&& attr_name) { - return getAttr(std::forward(attr_name), rtype); + return getAttr(rtype, std::forward(attr_name)); } @@ -227,8 +294,8 @@ public: { // expected respond: ACK SET ATTR_NAME ATTR_VALUE // return ATTR_NAME ATTR_VALUE (or error description 'code category what') - return deviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_SET, rtype, std::forward(value), - std::forward(values)...); + return serverCall(constants::ADC_DEVICE_NETPROTO_KEY_SET, rtype, std::forward(attr_name), + std::forward(value), std::forward(values)...); } template @@ -243,32 +310,40 @@ public: // ADC device helper methods (asynchronous) + template CallbackT, + traits::adc_input_char_range SenderNameT, + typename... ParamTs> + auto asyncClientHello(CallbackT&& callback_func, SenderNameT&& name, ParamTs&&... params) + { + return asyncServerCall(constants::ADC_DEVICE_NETPROTO_KEY_HELLO, std::forward(callback_func), + std::forward(name), std::forward(params)...); + } + template CallbackT> auto asyncDeviceNames(CallbackT&& callback_func) { - return asyncDeviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, - std::forward(callback_func)); + return asyncServerCall(constants::ADC_DEVICE_NETPROTO_KEY_NAMES, std::forward(callback_func)); } template CallbackT, traits::adc_input_char_range DevNameT> auto asyncBindDevice(CallbackT&& callback_func, DevNameT&& dev_name) { - return asyncDeviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_DEVICE, - std::forward(callback_func), std::forward(dev_name)); + return asyncServerCall(constants::ADC_DEVICE_NETPROTO_KEY_DEVICE, std::forward(callback_func), + std::forward(dev_name)); } template CallbackT, traits::adc_input_char_range CmdNameT> auto asyncExec(CallbackT&& callback_func, CmdNameT&& cmd_name) { - return asyncDeviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_CMD, std::forward(callback_func), - std::forward(cmd_name)); + return asyncServerCall(constants::ADC_DEVICE_NETPROTO_KEY_CMD, std::forward(callback_func), + std::forward(cmd_name)); } template CallbackT, traits::adc_input_char_range AttrNameT> auto asyncGetAttr(CallbackT&& callback_func, AttrNameT&& attr_name) { - return asyncDeviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_GET, std::forward(callback_func), - std::forward(attr_name)); + return asyncServerCall(constants::ADC_DEVICE_NETPROTO_KEY_GET, std::forward(callback_func), + std::forward(attr_name)); } template CallbackT, @@ -277,9 +352,9 @@ public: typename... ValueTs> auto asyncSetAttr(CallbackT&& callback_func, AttrNameT&& attr_name, ValueT&& value, ValueTs&&... values) { - return asyncDeviceFuncHelper(constants::ADC_DEVICE_NETPROTO_KEY_SET, std::forward(callback_func), - std::forward(attr_name), std::forward(value), - std::forward(values)...); + return asyncServerCall(constants::ADC_DEVICE_NETPROTO_KEY_SET, std::forward(callback_func), + std::forward(attr_name), std::forward(value), + std::forward(values)...); } protected: @@ -297,7 +372,7 @@ public: // helper methods template - R checkServerRespond(std::string_view key, const auto& bytes, ServerResponseType& type) const + R checkserverCall(std::string_view key, const auto& bytes, ServerResponseType& type) const { AdcDeviceProtoMessage dev_msg(bytes); @@ -321,47 +396,9 @@ public: { auto rbytes = sendRecv(bytes); - return checkServerRespond(key, rbytes, type); + return checkserverCall(key, rbytes, type); } - template - R deviceFuncHelper(std::string_view key, ServerResponseType& rtype, ArgTs&&... args) - { - typename netservice_t::send_msg_t bytes; - - AdcDeviceProtoMessage msg(bytes); - msg.setKeyValue(key, std::forward(args)...); - - return getFromServer(key, bytes, rtype); - } - - - template CallbackT, typename... ArgTs> - auto asyncDeviceFuncHelper(std::string_view key, CallbackT&& callback_func, ArgTs&&... args) - { - auto bytes = std::shared_ptr(); - - AdcDeviceProtoMessage msg(*bytes); - msg.setKeyValue(key, std::forward(args)...); - - asyncSendRecv(*bytes, [bytes, key, wrapper = traits::adc_pf_wrapper(std::forward(callback_func)), - this](auto err, auto rmsg) mutable { - if (err) { - _clientPtr->logError("An error occured while receiving server respond: {}", - netservice_t::formattableError(err)); - } else { - try { - ServerResponseType type; - auto attrs = checkServerRespond(key, rmsg, type); - - std::forward(std::get<0>(wrapper))(type, attrs); - - } catch (const std::system_error& err) { - _clientPtr->logError("An error occured while getting server respond: {}", err.what()); - } - } - }); - } template auto sendRecv(const SendMsgT& send_msg) @@ -394,6 +431,8 @@ public: }; +/* A HELPER CLASS TO IMPLEMENT AN SIMPLE QUEUE FOR DEVICE ATTRIBUTE GET/SET OPERATIONS AND COMMAND EXECUTION */ + template > class AdcNetClientSendQueue { @@ -415,13 +454,13 @@ public: return *this; } - template - AdcNetClientSendQueue& addToQueue(std::string key, ElemTs&&... elems) + template + AdcNetClientSendQueue& addToQueue(std::string key, ArgTs&&... elems) { - if constexpr (sizeof...(ElemTs)) { + if constexpr (sizeof...(ArgTs)) { _queue.push({key, ArgRangeT()}); - addToQueueHelper(std::get<1>(_queue.back()), std::forward(elems)...); + addToQueueHelper(std::get<1>(_queue.back()), std::forward(elems)...); } return *this; @@ -463,17 +502,17 @@ public: protected: std::queue _queue; - template - void addToQueueHelper(ArgRangeT& args, ElemT&& elem, ElemTs&&... elems) + template + void addToQueueHelper(ArgRangeT& args, ArgT&& elem, ArgTs&&... elems) { using el_t = std::ranges::range_value_t; - if constexpr (std::same_as>) { + if constexpr (std::same_as>) { std::ranges::copy(std::ranges::single_view(elem), std::back_inserter(args)); } else { std::span sp; - if constexpr (std::is_array_v>) { + if constexpr (std::is_array_v>) { sp = std::string_view(elem); } else { sp = std::span(elem); @@ -488,8 +527,8 @@ protected: std::back_inserter(args)); } - if constexpr (sizeof...(ElemTs)) { - addToQueue(args, std::forward(elems)...); + if constexpr (sizeof...(ArgTs)) { + addToQueue(args, std::forward(elems)...); } } };