This commit is contained in:
Timur A. Fatkhullin 2025-01-26 23:59:22 +03:00
parent 6e4e776ecf
commit e8dfb0de5a
3 changed files with 88 additions and 9 deletions

View File

@ -12,4 +12,5 @@ set(COMM_PROTO_LIB_SRC comm_proto.h comm_proto.cpp)
set(COMM_PROTO_LIB comm_proto)
add_library(${COMM_PROTO_LIB} STATIC ${COMM_PROTO_LIB_SRC}
control_proto.h)
control_proto.h
control_proto.cpp)

65
cxx/control_proto.cpp Normal file
View File

@ -0,0 +1,65 @@
#include "control_proto.h"
#include <ranges>
namespace BM700
{
void ControlProtoParser::generateCommMap()
{
for (auto& cmd : CONTROL_PROTO_VALID_COMMAND) {
ControlProtoParser::_userFunc[cmd] = {};
}
}
ControlProtoParser::ControlProtoParser()
{
// generate user functions table only once
if (ControlProtoParser::_userFunc.empty()) {
generateCommMap();
}
}
std::optional<ControlProtoParser::parse_result_t> ControlProtoParser::parse(std::string_view command)
{
std::optional<ControlProtoParser::parse_result_t> ret = std::nullopt;
auto found = std::ranges::search(command, CONTROL_PROTO_COMM_ARG_DELIM_SEQ);
if (found.empty()) { // no command arguments
if (ControlProtoParser::_userFunc.find(command) != ControlProtoParser::_userFunc.end()) {
ret = ControlProtoParser::parse_result_t{command, {}};
}
} else {
if (ControlProtoParser::_userFunc.find(std::string_view(command.begin(), found.begin())) !=
ControlProtoParser::_userFunc.end()) {
ret = ControlProtoParser::parse_result_t{command, {}};
auto args = command | std::views::drop(std::distance(command.begin(), found.end())) |
std::views::split(CONTROL_PROTO_ARG_DELIM_SEQ);
for (const auto& el : args) {
ret->args.emplace_back(el.begin(), el.end());
}
}
}
return ret;
}
bool ControlProtoParser::exec(std::string_view command)
{
auto r = parse(command);
if (r) {
auto func = ControlProtoParser::_userFunc[r->cmd];
if (func) {
func(r->cmd, r->args);
return true;
}
}
return false;
}
} // namespace BM700

View File

@ -1,6 +1,7 @@
#pragma once
#include <functional>
#include <optional>
#include <string_view>
namespace BM700
@ -42,33 +43,45 @@ static constexpr std::string_view CONTROL_PROTO_STR_TAG_MAXALT = "tagMAXALT";
// moving
static constexpr std::string_view CONTROL_PROTO_STR_SLEW_AZALT = "slewAZALT";
static constexpr std::string_view CONTROL_PROTO_STR_SLEW_RADEC = "slewRADEC";
static constexpr std::string_view CONTROL_PROTO_STR_SLEW_XVEL = "slewXVEL";
static constexpr std::string_view CONTROL_PROTO_STR_SLEW_YVEL = "slewYVEL";
static constexpr std::string_view CONTROL_PROTO_STR_SLEW_XVEL = "slewXVEL"; // velocity along Az/RA
static constexpr std::string_view CONTROL_PROTO_STR_SLEW_YVEL = "slewYVEL"; // velocity along ALT/DEC
static constexpr std::string_view CONTROL_PROTO_STR_TRACK_XVEL = "trackXVEL";
static constexpr std::string_view CONTROL_PROTO_STR_TRACK_YVEL = "trackYVEL";
static constexpr std::string_view CONTROL_PROTO_STR_STOP = "stop";
static constexpr std::array CONTROL_PROTO_VALID_COMMAND = {CONTROL_PROTO_STR_SLEW_AZALT, CONTROL_PROTO_STR_SLEW_RADEC};
class ControlProtoParser
{
public:
typedef std::function<void(std::string_view, std::vector<std::string_view>)> user_func_t;
// typedef std::pair<std::string_view, std::vector<std::string_view>> parse_result_t;
struct parse_result_t {
std::string_view cmd;
std::vector<std::string_view> args;
};
ControlProtoParser() {}
ControlProtoParser();
virtual ~ControlProtoParser() = default;
template <std::convertible_to<user_func_t> FT>
bool addUserFunc(std::string_view command, FT&& func)
{
auto res = _userFunc.try_emplace(command, std::forward<FT>(func));
return res.second;
// _userFunc[command] = std::forward<FT>(func);
if (auto res = _userFunc.find(command); res != _userFunc.end()) {
*res = std::forward<FT>(func);
return true;
} else {
return false;
}
}
bool parse(std::string_view command);
std::optional<parse_result_t> parse(std::string_view command);
bool exec(std::string_view command);
protected:
static std::unordered_map<std::string_view, user_func_t> _userFunc;
static void generateCommMap();
inline static std::unordered_map<std::string_view, user_func_t> _userFunc;
};