198 lines
6.7 KiB
C++
198 lines
6.7 KiB
C++
#include <cxxopts.hpp>
|
|
#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_netproto.h"
|
|
#include "../net/asio/adc_device_netserver_asio.h"
|
|
|
|
#ifdef USE_SPDLOG_LIBRARY
|
|
#include <spdlog/sinks/stdout_color_sinks.h>
|
|
#include "../common/adc_spdlog.h"
|
|
#endif
|
|
|
|
typedef adc::impl::AdcDeviceNetServerASIO<std::string_view> server_t;
|
|
typedef adc::AdcDeviceAttribute<std::string, server_t::serialized_t> attr_t;
|
|
|
|
class Device1 : public adc::AdcGenericDevice<std::string,
|
|
adc::AdcDeviceAttribute<std::string, server_t::serialized_t>,
|
|
adc::AdcDeviceCommand<std::string>>
|
|
{
|
|
typedef adc::AdcGenericDevice<std::string,
|
|
adc::AdcDeviceAttribute<std::string, server_t::serialized_t>,
|
|
adc::AdcDeviceCommand<std::string>>
|
|
base_t;
|
|
|
|
public:
|
|
template <adc::traits::adc_char_range R>
|
|
Device1(R&& id) : base_t(id)
|
|
{
|
|
}
|
|
};
|
|
|
|
class Device2 : public adc::AdcGenericDevice<std::string,
|
|
adc::AdcDeviceAttribute<size_t, server_t::serialized_t>,
|
|
adc::AdcDeviceCommand<std::string>>
|
|
{
|
|
typedef adc::AdcGenericDevice<std::string,
|
|
adc::AdcDeviceAttribute<size_t, server_t::serialized_t>,
|
|
adc::AdcDeviceCommand<std::string>>
|
|
base_t;
|
|
|
|
public:
|
|
template <adc::traits::adc_char_range R>
|
|
Device2(R&& id) : base_t(id)
|
|
{
|
|
}
|
|
};
|
|
|
|
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[])
|
|
{
|
|
/* 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(Device1::attribute_t::makeArithAttr(
|
|
"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(0x1ul, [&dev1_val1]() { return dev1_val1; });
|
|
// write-only
|
|
// dev2.addAttribute(0xfful, [&dev1_val1](const int& v) { dev1_val1 = v; });
|
|
dev2.addAttribute(Device2::attribute_t::makeArithAttr(0xfful, [&dev1_val1](const int& v) { dev1_val1 = v; }));
|
|
|
|
|
|
double f = 7.7;
|
|
std::cout << "SET DEV1['DEV1::ATTR1'] to " << f;
|
|
dev1["DEV1::ATTR1"] = f;
|
|
std::cout << "\tRESULT ( " << dev1_val1 << " )\n";
|
|
|
|
dev1_val1 = 111;
|
|
std::cout << "GET DEV1['DEV1::ATTR1']";
|
|
float fl = dev1["DEV1::ATTR1"];
|
|
std::cout << "\tRESULT ( " << fl << " )\n";
|
|
|
|
f *= 3.3;
|
|
std::cout << "SET DEV2['0xff'] to " << f;
|
|
dev2[0xff] = f;
|
|
std::cout << "\tRESULT ( " << dev1_val1 << " )\n";
|
|
|
|
|
|
/* COMMANDLINE OPTS */
|
|
cxxopts::Options options(argv[0], "ADC-library test device network server (ASIO implementation)\n");
|
|
|
|
options.allow_unrecognised_options();
|
|
|
|
options.add_options()("h,help", "Print usage");
|
|
options.add_options()(
|
|
"endpoints",
|
|
"endpoints server will be listening for. For 'local' endpoint the '@' symbol at the beginning of the path "
|
|
"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"});
|
|
|
|
try {
|
|
auto opt_result = options.parse(argc, argv);
|
|
|
|
if (opt_result["help"].count()) {
|
|
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;
|
|
}
|
|
|
|
asio::io_context io_ctx;
|
|
|
|
asio::signal_set signals(io_ctx, SIGINT, SIGTERM);
|
|
signals.async_wait([&](std::error_code, int) { io_ctx.stop(); });
|
|
|
|
using server_t = adc::impl::AdcDeviceNetServerASIO<std::string, adc::AdcSpdlogLogger>;
|
|
std::shared_ptr<spdlog::logger> logger = spdlog::stdout_color_mt("console");
|
|
logger->set_level(spdlog::level::debug);
|
|
// server_t server("TEST SRV", io_ctx, logger, "[%Y-%m-%d %T.%e][%l]: %v");
|
|
server_t server("TEST SRV", io_ctx, logger);
|
|
// server.setAcceptTimeout(std::chrono::seconds(5));
|
|
|
|
// using server_t = adc::impl::AdcDeviceNetServerASIO<>;
|
|
// server_t server("TEST SRV", io_ctx);
|
|
// server.setLogLevel(server_t::logger_t::DEBUG_LEVEL);
|
|
|
|
|
|
server.setupSignals();
|
|
|
|
server.addDevice(&dev1);
|
|
server.addDevice(
|
|
&dev2, {},
|
|
// adc::traits::adc_char_identity<server_t::serialized_t>{},
|
|
adc::utils::AdcDefaultValueConverter<>::deserialize<Device2::attr_ident_t, server_t::serialized_t>);
|
|
|
|
auto epnt = opt_result["endpoints"].as<std::vector<std::string>>();
|
|
|
|
for (auto& ep : epnt) {
|
|
adc::AdcEndpoint epn(ep);
|
|
if (epn.isValid()) {
|
|
epn.makeAbstract('@');
|
|
// if (epn.isLocalSeqpacket() || epn.isLocalStream()) {
|
|
// if (epn.path()[0] == '@') { // replace '@' to '\0' (use of UNIX abstract namespace)
|
|
// auto it = std::ranges::find(ep, '@');
|
|
// *it = '\0';
|
|
// epn = adc::AdcEndpoint(ep);
|
|
// }
|
|
// }
|
|
|
|
// std::cout << "try to start listenning at '" << ep << "' ...";
|
|
|
|
server.start<adc::AdcStopSeqSessionProto<>>(epn);
|
|
|
|
// std::cout << "\tOK\n";
|
|
} else {
|
|
std::cerr << "Unrecognized endpoint: '" << ep << "'! Ignore!\n";
|
|
}
|
|
}
|
|
|
|
|
|
io_ctx.run();
|
|
|
|
} catch (const cxxopts::exceptions::exception& ex) {
|
|
std::cerr << "\nAn error occured while parsing input options: " << ex.what() << "\n";
|
|
return 127;
|
|
} catch (const std::system_error& ex) {
|
|
std::cerr << "\nAn error ocured: " << ex.what() << "\n";
|
|
std::cerr << "Category: " << ex.code().category().name() << "; message: " << ex.code().message() << "\n";
|
|
return 128;
|
|
}
|
|
|
|
return 0;
|
|
}
|