This commit is contained in:
2025-09-24 18:23:17 +03:00
parent b1a48d2b77
commit f729799335
5 changed files with 203 additions and 83 deletions

View File

@@ -1,38 +1,39 @@
#pragma once
#include <string_view>
#include <unordered_set>
#include "mcc_angle.h"
namespace mcc
namespace mcc::network
{
/*
* network communication message format:
* keyword[[key-param-delim]param1[param-param-delim][param2]...]<stop-seq>
* <keyword>[[<key-param-delim>]param1[param-param-delim][param2]...]<stop-seq>
* e.g.
* "target 12:23:45.56 00:32:21.978\n"
* "TARGET 12:23:45.56 00:32:21.978\n"
*/
/* message */
static constexpr std::string_view MCC_COMMPROTO_STOP_SEQ = "\n";
static constexpr std::string_view MCC_COMMPROTO_KEYPARAM_DELIM_DEQ = " ";
static constexpr std::string_view MCC_COMMPROTO_PARAMPARAM_DELIM_DEQ = " ";
static constexpr std::string_view MCC_COMMPROTO_KEYPARAM_DELIM_SEQ = " ";
static constexpr std::string_view MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ = " ";
/* server special response keywords */
/* server special keywords */
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ACK = "ACK"; // ACK
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ERROR = "ERROR"; // mount operational error
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR = "ACK"; // ACK
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR = "ERROR"; // mount operational error
// pre-defined errors
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ERROR_INVKEY = "INVKEY"; // invalid keyword
static constexpr std::string_view MCC_COMMPROTO_SERVER_RESP_ERROR_INVPAR = "INVPAR"; // invalid parameter
static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVKEY_STR = "INVKEY"; // invalid keyword
static constexpr std::string_view MCC_COMMPROTO_SERVER_ERROR_INVPAR_STR = "INVPAR"; // invalid parameter
/* predefined parameters */
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC_ICRS = "RADEC_ICRS";
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_RADEC = "RADEC"; // apparent RA and DEC
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_HADEC = "HADEC";
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_HADEC = "HADEC"; // apparent HA and DEC
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZZD = "AZZD";
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_AZALT = "AZALT";
static constexpr std::string_view MCC_COMMPROTO_COORD_KIND_XY = "XY";
@@ -58,7 +59,7 @@ static constexpr MccCoordPairKind mcc_str2pairkind(std::string_view spair)
// IN THE FIRST CASE ALL NUMBERS MUST BE INTERPRETATED AS DEGREES,
// IN THE SECOND CASE NUMBERS MUST BE INTERPRETATED ACCORDING TO ITS TYPE:
// ALL TIME-RELATED QUANTITIES AND RA/HA COORDINATES MUST BE EXPRESSED
// IN FORMAT 'HOURS:MINUTES:SECONDS' WHILE DEC/ALT/AZ/ZD COORDINATES MUST
// IN FORMAT 'HOURS:MINUTES:SECONDS', WHILE DEC/ALT/AZ/ZD COORDINATES MUST
// BE EXPRESSED AS '+/-DEGREES:ARCMINUTES:ARCSECONDS'
@@ -80,7 +81,14 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_STR = "COORDFMT
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_SEXGM_STR = "SGM"; // sexagesimal
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDFMT_FIXED_STR = "FIX"; // fixed point
// precision of returned coordinates
// precision (number of decimal places) of returned coordinates:
// "COORDPREC seconds-prec arcseconds-prec\n"
// seconds-prec - precision of hour-based coordinates (RA and HA) or time-related quantities
// arcseconds-prec - precision of degree-based coordinates (DEC, AZ, ZD, ALT)
// precision must be given as non-negative integer number
// e.g.
// "COORDPREC 2 1\n" (output sexagesimal RA=12:34:56.67, DEC=32:54:21.9)
//
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_COORDPREC_STR = "COORDPREC";
@@ -111,14 +119,99 @@ static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TARGET_STR = "TARGET";
//
// server must return "ACK MOUNT X-coord Y-coord XY-kind" or "ERROR INVPAR"
// e.g.
// "MOUNT AZALT\n" -> "AC MOUNT 1.2332325 54.23321312 AZALT\n"
// "MOUNT AZALT\n" -> "ACK MOUNT 1.2332325 54.23321312 AZALT\n"
// "MOUNT AZAL\n" -> "ERROR INVPAR\n" (invalid parameter of coordinates pair kind)
// "MOUNT\n" -> "AC MOUNT 1.2332325 54.23321312 AZZD\n" for alt-azimuthal mount
// "MOUNT\n" -> "AC MOUNT 1.2332325 54.23321312 HADEC\n" for equathorial mount
// "MOUNT\n" -> "ACK MOUNT 1.2332325 54.23321312 AZZD\n" for alt-azimuthal mount
// "MOUNT\n" -> "ACK MOUNT 1.2332325 54.23321312 HADEC\n" for equathorial mount
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_MOUNT_STR = "MOUNT";
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TELEMTRY_STR = "TELEMETRY";
} // namespace mcc
static const std::unordered_set MCC_COMMPROTO_VALID_KEYS = {
MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR, MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR, MCC_COMMPROTO_KEYWORD_COORDFMT_STR,
MCC_COMMPROTO_KEYWORD_COORDPREC_STR, MCC_COMMPROTO_KEYWORD_TARGET_STR, MCC_COMMPROTO_KEYWORD_MOUNT_STR,
MCC_COMMPROTO_KEYWORD_TELEMTRY_STR};
auto MCC_COMMPROTO_KEYWORD_SERVER_ACK_HASH =
std::unordered_set<std::string_view>::hasher{}(MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR);
auto MCC_COMMPROTO_KEYWORD_SERVER_ERROR_HASH =
std::unordered_set<std::string_view>::hasher{}(MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR);
template <traits::mcc_input_char_range IR, traits::mcc_range_of_output_char_range OT>
std::string_view mcc_parse_netmsg(IR&& netmsg, OT& parse_res, bool from_server = false)
{
if (std::ranges::size(std::forward<IR>(netmsg)) == 0) {
return "";
};
std::string_view ret;
auto found = std::ranges::search(std::forward<IR>(netmsg), MCC_COMMPROTO_KEYPARAM_DELIM_SEQ);
auto it = MCC_COMMPROTO_VALID_KEYS.find({netmsg.begin(), found.begin()});
if (it == MCC_COMMPROTO_VALID_KEYS.end()) {
return "";
}
ret = *it;
if (from_server) { // only ACK and ERROR
auto ok = std::ranges::search(netmsg.begin(), found.begin(), MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.begin(),
MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.end());
if (ok) {
ret = MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR;
}
ok = std::ranges::search(netmsg.begin(), found.begin(), MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.begin(),
MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.end());
if (ok) {
ret = MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR;
} else {
return "";
}
}
// if (found.empty()) { // no parameters?
// if (from_server) {
// auto ok = std::ranges::search(netmsg.begin(), found.begin(),
// MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.begin(),
// MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR.end());
// if (ok) {
// ret = MCC_COMMPROTO_KEYWORD_SERVER_ACK_STR;
// }
// ok = std::ranges::search(netmsg.begin(), found.begin(), MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.begin(),
// MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR.end());
// if (ok) {
// ret = MCC_COMMPROTO_KEYWORD_SERVER_ERROR_STR;
// } else {
// return "";
// }
// } else {
// if (!MCC_COMMPROTO_VALID_KEYS.contains({netmsg.begin(), found.begin()})) {
// return "";
// }
// }
// } else {
// if (std::distance(netmsg.begin(), found.begin()) == 0) { // an empty keyword
// return "";
// }
// }
auto pars = std::forward<IR>(netmsg) | std::views::drop(std::distance(netmsg.begin(), found.end())) |
std::views::split(MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ);
OT res;
for (auto const& el : pars) {
std::back_inserter(res) = {el.begin(), el.end()};
}
parse_res = std::move(res);
return ret;
}
} // namespace mcc::network