...
This commit is contained in:
parent
f14b4fdc10
commit
9cde583688
@ -141,7 +141,10 @@ namespace adc
|
|||||||
struct AdcDeviceAttributeErrorCategory : public std::error_category {
|
struct AdcDeviceAttributeErrorCategory : public std::error_category {
|
||||||
AdcDeviceAttributeErrorCategory() : std::error_category() {}
|
AdcDeviceAttributeErrorCategory() : std::error_category() {}
|
||||||
|
|
||||||
const char* name() const noexcept { return "ADC_DEVICE_ATTRIBUTE_CATEGORY"; }
|
const char* name() const noexcept
|
||||||
|
{
|
||||||
|
return "ADC_DEVICE_ATTRIBUTE_CATEGORY";
|
||||||
|
}
|
||||||
|
|
||||||
std::string message(int ec) const
|
std::string message(int ec) const
|
||||||
{
|
{
|
||||||
@ -416,16 +419,25 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
virtual ~AdcDeviceAttribute() { _clearFunc(); }
|
virtual ~AdcDeviceAttribute()
|
||||||
|
{
|
||||||
|
_clearFunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* PUBLIC METHODS */
|
/* PUBLIC METHODS */
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
IdentT ident() const { return _ident; }
|
IdentT ident() const
|
||||||
|
{
|
||||||
|
return _ident;
|
||||||
|
}
|
||||||
|
|
||||||
AccessType accessType() const { return _accessType; }
|
AccessType accessType() const
|
||||||
|
{
|
||||||
|
return _accessType;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
template <traits::adc_attr_convfunc_c FromFuncT, traits::adc_attr_convfunc_c ToFuncT>
|
template <traits::adc_attr_convfunc_c FromFuncT, traits::adc_attr_convfunc_c ToFuncT>
|
||||||
@ -601,6 +613,11 @@ public:
|
|||||||
// throw std::system_error(AdcDeviceAttributeErrorCode::ERROR_INVALID_SERIALIZED_TYPE);
|
// throw std::system_error(AdcDeviceAttributeErrorCode::ERROR_INVALID_SERIALIZED_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default_serialized_t serialize()
|
||||||
|
{
|
||||||
|
return serialize<default_serialized_t>();
|
||||||
|
}
|
||||||
|
|
||||||
template <typename SerializedT>
|
template <typename SerializedT>
|
||||||
AdcDeviceAttribute& deserialize(const SerializedT& sval)
|
AdcDeviceAttribute& deserialize(const SerializedT& sval)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -131,8 +131,11 @@ protected:
|
|||||||
};
|
};
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DeviceWrapper() {
|
DeviceWrapper() : _id()
|
||||||
|
{
|
||||||
// null device
|
// null device
|
||||||
|
std::string_view is{"NULL-DEVICE"};
|
||||||
|
std::ranges::copy(_id, std::back_inserter(_id));
|
||||||
};
|
};
|
||||||
|
|
||||||
template <interfaces::adc_device_c DeviceT,
|
template <interfaces::adc_device_c DeviceT,
|
||||||
|
|||||||
@ -307,9 +307,7 @@ public:
|
|||||||
// start accepting remote connections, create and start given network session
|
// start accepting remote connections, create and start given network session
|
||||||
// It must be assumed that this is asynchronous operation!!!
|
// It must be assumed that this is asynchronous operation!!!
|
||||||
template <interfaces::adc_netsession_c SessionT, typename... AcceptorCtorArgTs>
|
template <interfaces::adc_netsession_c SessionT, typename... AcceptorCtorArgTs>
|
||||||
void start(const typename SessionT::netsession_ident_t& id,
|
void start(SessionT::netsession_ident_t id, SessionT::netsession_ctx_t sess_ctx, AcceptorCtorArgTs&&... ctor_args)
|
||||||
const typename SessionT::netsession_ctx_t& sess_ctx,
|
|
||||||
AcceptorCtorArgTs&&... ctor_args)
|
|
||||||
{
|
{
|
||||||
if (!_isListening<SessionT>[this][id]) {
|
if (!_isListening<SessionT>[this][id]) {
|
||||||
auto acceptor = std::make_shared<typename SessionT::netservice_t::acceptor_t>(
|
auto acceptor = std::make_shared<typename SessionT::netservice_t::acceptor_t>(
|
||||||
@ -322,7 +320,7 @@ public:
|
|||||||
_isListening<SessionT>[this][id] = false;
|
_isListening<SessionT>[this][id] = false;
|
||||||
});
|
});
|
||||||
|
|
||||||
doAccept<SessionT>(acceptor, id, sess_ctx);
|
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
||||||
}
|
}
|
||||||
|
|
||||||
// only once per SessionT
|
// only once per SessionT
|
||||||
@ -369,15 +367,16 @@ protected:
|
|||||||
server_ident_t _serverIdent;
|
server_ident_t _serverIdent;
|
||||||
|
|
||||||
template <typename SessionT, typename AT, typename IDT, typename CTXT>
|
template <typename SessionT, typename AT, typename IDT, typename CTXT>
|
||||||
void doAccept(std::shared_ptr<AT> acceptor, const IDT& id, const CTXT& sess_ctx)
|
void doAccept(std::shared_ptr<AT> acceptor, IDT id, CTXT sess_ctx)
|
||||||
{
|
{
|
||||||
acceptor->asyncAccept([acceptor, &id, &sess_ctx, this](auto ec, typename SessionT::netservice_t srv) mutable {
|
acceptor->asyncAccept([acceptor, id = std::move(id), sess_ctx = std::move(sess_ctx), this](
|
||||||
|
auto ec, typename SessionT::netservice_t srv) mutable {
|
||||||
if (!ec) {
|
if (!ec) {
|
||||||
auto sess = std::make_shared<SessionT>(id, std::move(srv), sess_ctx);
|
auto sess = std::make_shared<SessionT>(id, std::move(srv), sess_ctx);
|
||||||
startSession(sess);
|
startSession(sess);
|
||||||
|
|
||||||
_isListening<SessionT>[this][id] = true;
|
_isListening<SessionT>[this][id] = true;
|
||||||
doAccept<SessionT>(acceptor, id, sess_ctx);
|
doAccept<SessionT>(acceptor, std::move(id), std::move(sess_ctx));
|
||||||
} else {
|
} else {
|
||||||
_isListening<SessionT>[this][id] = false;
|
_isListening<SessionT>[this][id] = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,86 @@
|
|||||||
#include <cxxopts.hpp>
|
#include <cxxopts.hpp>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "../device/adc_device.h"
|
||||||
|
#include "../device/adc_device_attribute.h"
|
||||||
|
#include "../device/adc_device_command.h"
|
||||||
#include "../net/adc_endpoint.h"
|
#include "../net/adc_endpoint.h"
|
||||||
#include "../net/adc_netproto.h"
|
#include "../net/adc_netproto.h"
|
||||||
#include "../net/asio/adc_device_netserver_asio.h"
|
#include "../net/asio/adc_device_netserver_asio.h"
|
||||||
|
|
||||||
|
|
||||||
|
class Device1 : public adc::AdcGenericDevice<std::string,
|
||||||
|
adc::AdcDeviceAttribute<std::string>,
|
||||||
|
adc::AdcDeviceCommand<std::string>>
|
||||||
|
{
|
||||||
|
typedef adc::AdcGenericDevice<std::string, adc::AdcDeviceAttribute<std::string>, adc::AdcDeviceCommand<std::string>>
|
||||||
|
base_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <adc::traits::adc_char_range R>
|
||||||
|
Device1(R&& id) : base_t(id)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
||||||
|
this->_ident = std::forward<R>(id);
|
||||||
|
} else {
|
||||||
|
std::ranges::copy(std::forward<R>(id), std::back_inserter(this->_ident));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Device2
|
||||||
|
: public adc::AdcGenericDevice<std::string, adc::AdcDeviceAttribute<size_t>, adc::AdcDeviceCommand<std::string>>
|
||||||
|
{
|
||||||
|
typedef adc::AdcGenericDevice<std::string, adc::AdcDeviceAttribute<size_t>, adc::AdcDeviceCommand<std::string>>
|
||||||
|
base_t;
|
||||||
|
|
||||||
|
public:
|
||||||
|
template <adc::traits::adc_char_range R>
|
||||||
|
Device2(R&& id) : base_t(id)
|
||||||
|
{
|
||||||
|
if constexpr (std::is_array_v<std::decay_t<R>>) {
|
||||||
|
this->_ident = std::forward<R>(id);
|
||||||
|
} else {
|
||||||
|
std::ranges::copy(std::forward<R>(id), std::back_inserter(this->_ident));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
using t_t = std::tuple<float, std::string>;
|
||||||
|
static t_t tuple_val{7.7, "TUPVAL"};
|
||||||
|
|
||||||
|
t_t gt()
|
||||||
|
{
|
||||||
|
return tuple_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
void st(const t_t& v)
|
||||||
|
{
|
||||||
|
tuple_val = v;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char* argv[])
|
int main(int argc, char* argv[])
|
||||||
{
|
{
|
||||||
|
/* CREATE AND INIT DEVICES */
|
||||||
|
int dev1_val1 = 1;
|
||||||
|
|
||||||
|
Device1 dev1("DEVICE#1");
|
||||||
|
Device2 dev2("DEVICE#2");
|
||||||
|
|
||||||
|
// device#1
|
||||||
|
dev1.addCommand({"DEV1::COM1", []() { std::cout << "EXEC DEV1::COM1\n"; }});
|
||||||
|
dev1.addAttribute(
|
||||||
|
{"DEV1::ATTR1", [&dev1_val1]() { return dev1_val1; }, [&dev1_val1](const int& v) { dev1_val1 = v; }});
|
||||||
|
|
||||||
|
dev1.addAttribute({"DEV1::ATTR2", gt, st});
|
||||||
|
|
||||||
|
// device#2
|
||||||
|
// read-only attr
|
||||||
|
dev2.addAttribute({0x1, [&dev1_val1]() { return dev1_val1; }});
|
||||||
|
// write-only
|
||||||
|
dev2.addAttribute({0x2, [&dev1_val1](const int& v) { dev1_val1 = v; }});
|
||||||
|
|
||||||
|
|
||||||
/* COMMANDLINE OPTS */
|
/* COMMANDLINE OPTS */
|
||||||
cxxopts::Options options(argv[0], "ADC-library test device network server (ASIO implementation)\n");
|
cxxopts::Options options(argv[0], "ADC-library test device network server (ASIO implementation)\n");
|
||||||
|
|
||||||
@ -14,10 +88,14 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
options.add_options()("h,help", "Print usage");
|
options.add_options()("h,help", "Print usage");
|
||||||
options.add_options()(
|
options.add_options()(
|
||||||
"endpoints", "endpoints server will be listening for",
|
"endpoints",
|
||||||
cxxopts::value<std::vector<std::string>>()->default_value("local://stream/ADC_ASIO_TEST_SERVER"));
|
"endpoints server will be listening for. For 'local' endpoint the '@' symbol at the beginning of the path "
|
||||||
// cxxopts::value<std::vector<std::string>>()->default_value("local://stream/@ADC_ASIO_TEST_SERVER"));
|
"means "
|
||||||
|
"abstract namespace socket.",
|
||||||
|
cxxopts::value<std::vector<std::string>>()->default_value("local://stream/@ADC_ASIO_TEST_SERVER"));
|
||||||
|
|
||||||
|
|
||||||
|
options.positional_help("[endpoint0] [enpoint1] ... [endpointN]");
|
||||||
options.parse_positional({"endpoints"});
|
options.parse_positional({"endpoints"});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -25,6 +103,11 @@ int main(int argc, char* argv[])
|
|||||||
|
|
||||||
if (opt_result["help"].count()) {
|
if (opt_result["help"].count()) {
|
||||||
std::cout << options.help();
|
std::cout << options.help();
|
||||||
|
std::cout << "\n";
|
||||||
|
std::cout << "[endpoint0] [enpoint1] ... [endpointN] - endpoints server will be listening for. For 'local' "
|
||||||
|
"endpoint the '@' symbol at the beginning of the path "
|
||||||
|
"means abstract namespace socket."
|
||||||
|
<< "\n";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,6 +119,10 @@ int main(int argc, char* argv[])
|
|||||||
adc::impl::AdcDeviceNetServerASIO server("TEST SRV", io_ctx);
|
adc::impl::AdcDeviceNetServerASIO server("TEST SRV", io_ctx);
|
||||||
server.setupSignals();
|
server.setupSignals();
|
||||||
|
|
||||||
|
server.addDevice(&dev1);
|
||||||
|
server.addDevice(&dev2, adc::traits::adc_char_identity<std::string>{},
|
||||||
|
adc::utils::AdcDefaultValueConverter<>::serialize<std::string, Device2::attr_ident_t>);
|
||||||
|
|
||||||
auto epnt = opt_result["endpoints"].as<std::vector<std::string>>();
|
auto epnt = opt_result["endpoints"].as<std::vector<std::string>>();
|
||||||
|
|
||||||
for (auto& ep : epnt) {
|
for (auto& ep : epnt) {
|
||||||
|
|||||||
@ -96,7 +96,9 @@ TEST_CASE("[ADC NET MESSAGE]")
|
|||||||
std::cout << std::boolalpha << "IS UDP: " << prs.isUDP() << "\n";
|
std::cout << std::boolalpha << "IS UDP: " << prs.isUDP() << "\n";
|
||||||
|
|
||||||
std::cout << "\n";
|
std::cout << "\n";
|
||||||
std::string bs = "local://seqpaCKet:dwe/tmp.dev/213";
|
std::string bs = "local://seqpaCKet:dwe/@tmp.dev/213";
|
||||||
|
auto it = std::ranges::find(bs, '@');
|
||||||
|
*it = '\0';
|
||||||
std::cout << "EPT CHAR RANGE: " << bs << "\n";
|
std::cout << "EPT CHAR RANGE: " << bs << "\n";
|
||||||
prs = AdcEndpointParser(bs);
|
prs = AdcEndpointParser(bs);
|
||||||
std::cout << std::boolalpha << "IS VALID: " << prs.isValid() << "\n";
|
std::cout << std::boolalpha << "IS VALID: " << prs.isValid() << "\n";
|
||||||
@ -104,6 +106,7 @@ TEST_CASE("[ADC NET MESSAGE]")
|
|||||||
std::cout << "HOST: [" << prs.host() << "]\n";
|
std::cout << "HOST: [" << prs.host() << "]\n";
|
||||||
std::cout << "PORT: [" << prs.port() << "]\n";
|
std::cout << "PORT: [" << prs.port() << "]\n";
|
||||||
std::cout << "PATH: [" << prs.path() << "]\n";
|
std::cout << "PATH: [" << prs.path() << "]\n";
|
||||||
|
std::cout << "PATH SZ: [" << prs.path().size() << "]\n";
|
||||||
std::cout << std::boolalpha << "IS LOCAL STREAM: " << prs.isLocalStream() << "\n";
|
std::cout << std::boolalpha << "IS LOCAL STREAM: " << prs.isLocalStream() << "\n";
|
||||||
std::cout << std::boolalpha << "IS LOCAL SEQPACKET: " << prs.isLocalSeqpacket() << "\n";
|
std::cout << std::boolalpha << "IS LOCAL SEQPACKET: " << prs.isLocalSeqpacket() << "\n";
|
||||||
std::cout << std::boolalpha << "IS UDP: " << prs.isUDP() << "\n";
|
std::cout << std::boolalpha << "IS UDP: " << prs.isUDP() << "\n";
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user