add tests for control protocol and angle representation parsing

This commit is contained in:
Timur A. Fatkhullin 2025-02-03 23:03:07 +03:00
parent 61afd0f4a7
commit a2e2896f29
5 changed files with 133 additions and 18 deletions

View File

@ -3,15 +3,25 @@ cmake_minimum_required(VERSION 3.14)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
option(WITH_TESTS "Build tests" ON)
# Mount client-to-server communication protocol
# (extended LX200 protocol)
#
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}
# set(CNTR_PROTO_LIB_SRC comm_proto.h comm_proto.cpp)
set(CNTR_PROTO_LIB_SRC
control_proto.h
control_proto.cpp
utils.h)
utils.h
)
set(CNTR_PROTO_LIB comm_proto)
add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC})
if (WITH_TESTS)
set(CNTR_PROTO_TEST_APP cntr_proto_test)
add_executable(${CNTR_PROTO_TEST_APP} tests/cntr_proto_test.cpp)
target_link_libraries(${CNTR_PROTO_TEST_APP} ${CNTR_PROTO_LIB})
endif()

View File

@ -30,10 +30,8 @@ std::optional<ControlProtoParser::parse_result_t> ControlProtoParser::parse(std:
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, {}};
ret = ControlProtoParser::parse_result_t{{command.begin(), found.begin()}, {}};
if (ControlProtoParser::_userFunc.find(ret->cmd) != ControlProtoParser::_userFunc.end()) {
auto args = command | std::views::drop(std::distance(command.begin(), found.end())) |
std::views::split(CONTROL_PROTO_ARG_DELIM_SEQ);

View File

@ -41,10 +41,10 @@ static constexpr std::string_view CONTROL_PROTO_STR_TAG_MINALT = "tagMINALT";
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"; // 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_SLEW_AZALT = "slewAZALT"; // slew and stop
static constexpr std::string_view CONTROL_PROTO_STR_SLEW_RADEC = "slewRADEC"; // slew and track
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";
@ -52,8 +52,33 @@ static constexpr std::string_view CONTROL_PROTO_STR_STOP = "stop";
// site coordinates
static constexpr std::string_view CONTROL_PROTO_STR_SITE_LON = "siteLON";
static constexpr std::string_view CONTROL_PROTO_STR_SITE_LAT = "siteLAT";
static constexpr std::string_view CONTROL_PROTO_STR_SITE_ELEV = "siteELEV";
static constexpr std::array CONTROL_PROTO_VALID_COMMAND = {CONTROL_PROTO_STR_SLEW_AZALT, CONTROL_PROTO_STR_SLEW_RADEC};
// meteo
static constexpr std::string_view CONTROL_PROTO_STR_METEO_TEMP = "atmTEMP";
static constexpr std::string_view CONTROL_PROTO_STR_METEO_PRES = "atmPRES";
static constexpr std::string_view CONTROL_PROTO_STR_METEO_HUM = "atmHUM";
// PCS
// network setup:
// format: netCONF=<iface>:<IP-addr>/<net-mask>,<gateway>,<broadcast>
// netCONF=eth0:192.168.1.10/24,192.168.1.1,192.168.1.255
static constexpr std::string_view CONTROL_PROTO_STR_NET_CONF = "netCONF";
static constexpr std::array CONTROL_PROTO_VALID_COMMAND = {
CONTROL_PROTO_STR_TAG_AZ, CONTROL_PROTO_STR_TAG_ALT, CONTROL_PROTO_STR_TAG_AZALT,
CONTROL_PROTO_STR_TAG_RA, CONTROL_PROTO_STR_TAG_DEC, CONTROL_PROTO_STR_TAG_RADEC,
CONTROL_PROTO_STR_TEL_RA, CONTROL_PROTO_STR_TEL_DEC, CONTROL_PROTO_STR_TEL_RADEC,
CONTROL_PROTO_STR_UTC_DATE, CONTROL_PROTO_STR_LOC_DATE, CONTROL_PROTO_STR_UTC_TIME,
CONTROL_PROTO_STR_LOC_TIME, CONTROL_PROTO_STR_UTC_DT, CONTROL_PROTO_STR_LOC_DT,
CONTROL_PROTO_STR_JDN, CONTROL_PROTO_STR_TAG_MINALT, CONTROL_PROTO_STR_TAG_MAXALT,
CONTROL_PROTO_STR_SLEW_AZALT, CONTROL_PROTO_STR_SLEW_RADEC, CONTROL_PROTO_STR_SLEW_XVEL,
CONTROL_PROTO_STR_SLEW_YVEL, CONTROL_PROTO_STR_TRACK_XVEL, CONTROL_PROTO_STR_TRACK_YVEL,
CONTROL_PROTO_STR_STOP, CONTROL_PROTO_STR_SITE_LON, CONTROL_PROTO_STR_SITE_LAT,
CONTROL_PROTO_STR_SITE_ELEV, CONTROL_PROTO_STR_METEO_TEMP, CONTROL_PROTO_STR_METEO_PRES,
CONTROL_PROTO_STR_METEO_HUM, CONTROL_PROTO_STR_NET_CONF,
};
class ControlProtoParser
{

View File

@ -0,0 +1,76 @@
#include <iostream>
#include "../control_proto.h"
#include "../utils.h"
using namespace BM700;
void print_result(const std::optional<ControlProtoParser::parse_result_t>& res)
{
if (res.has_value()) {
std::cout << "CMD: " << res.value().cmd << "\n";
if (res->args.size()) {
std::cout << "ARGS: ";
for (auto const& el : res->args) {
std::cout << "'" << el << "' ";
}
std::cout << "\n";
} else {
std::cout << "NO ARGS\n";
}
} else {
std::cout << "Invalid command!\n";
}
}
void print_ang_result(std::string_view ang_str, bool hh = false)
{
std::cout << "ANG STRING: '" << ang_str << "'\n";
auto ang_res = mcc::utils::parsAngleString(ang_str, hh);
if (ang_res.has_value()) {
std::cout << "ANG: " << ang_res.value() << "\n";
} else {
std::cout << "INVALID ANGLE STRING!\n";
}
}
int main()
{
ControlProtoParser pr;
std::string cmd{CONTROL_PROTO_STR_TAG_MINALT.begin(), CONTROL_PROTO_STR_TAG_MINALT.end()};
cmd += "=10.324";
std::cout << "COMMAND STRING: " << cmd << "\n";
auto res = pr.parse(cmd);
print_result(res);
cmd = std::string(CONTROL_PROTO_STR_STOP.begin(), CONTROL_PROTO_STR_STOP.end());
std::cout << "\nCOMMAND STRING: " << cmd << "\n";
res = pr.parse(cmd);
print_result(res);
cmd = std::string(CONTROL_PROTO_STR_UTC_DATE.begin(), CONTROL_PROTO_STR_UTC_DATE.end());
cmd += "=2025-06-10,01:32:45.213";
std::cout << "\nCOMMAND STRING: " << cmd << "\n";
res = pr.parse(cmd);
print_result(res);
std::cout << "\n\n******* TEST ANGLE STRING PARSING *******\n";
cmd = " 10:00:00 ";
print_ang_result(cmd);
cmd = " -10:30:36 ";
print_ang_result(cmd);
cmd = "231.3467 ";
print_ang_result(cmd);
cmd = " 12:30:00 ";
print_ang_result(cmd, true);
return 0;
}

View File

@ -1,5 +1,6 @@
#pragma once
#include <charconv>
#include <ranges>
#include <regex>
@ -111,14 +112,19 @@ static std::optional<double> parsAngleString(R&& r, bool hms = false)
if (ok) {
auto str = trimSpaces(std::forward<R>(r));
auto parts = std::views::split(str, ":");
auto parts = std::views::split(str, std::string_view(":"));
double val;
double p1 = numFromStr<double>(parts[0]);
double p1 = numFromStr<double>(*parts.begin()).value();
val = std::abs(p1);
val += numFromStr<double>(parts[1]) / 60.0;
val += numFromStr<double>(parts[2]) / 3600.0;
double dv = 60.0;
for (auto const& v : parts | std::views::drop(1)) {
val += numFromStr<double>(v).value() / dv;
dv *= 60.0;
}
// val += numFromStr<double>(parts[1]) / 60.0;
// val += numFromStr<double>(parts[2]) / 3600.0;
if (p1 < 0) {
val = -val;
}