218 lines
9.0 KiB
C++
218 lines
9.0 KiB
C++
#pragma once
|
|
|
|
#include <string_view>
|
|
#include <unordered_set>
|
|
#include "mcc_angle.h"
|
|
|
|
namespace mcc::network
|
|
{
|
|
|
|
/*
|
|
* network communication message format:
|
|
* <keyword>[[<key-param-delim>]param1[param-param-delim][param2]...]<stop-seq>
|
|
* e.g.
|
|
* "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_SEQ = " ";
|
|
static constexpr std::string_view MCC_COMMPROTO_PARAMPARAM_DELIM_SEQ = " ";
|
|
|
|
|
|
/* server special keywords */
|
|
|
|
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_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"; // 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";
|
|
|
|
|
|
static constexpr MccCoordPairKind mcc_str2pairkind(std::string_view spair)
|
|
{
|
|
return spair == MCC_COMMPROTO_COORD_KIND_RADEC_ICRS ? MccCoordPairKind::COORDS_KIND_RADEC_ICRS
|
|
: spair == MCC_COMMPROTO_COORD_KIND_RADEC ? MccCoordPairKind::COORDS_KIND_RADEC_APP
|
|
: spair == MCC_COMMPROTO_COORD_KIND_HADEC ? MccCoordPairKind::COORDS_KIND_HADEC_APP
|
|
: spair == MCC_COMMPROTO_COORD_KIND_AZZD ? MccCoordPairKind::COORDS_KIND_AZZD
|
|
: spair == MCC_COMMPROTO_COORD_KIND_AZALT ? MccCoordPairKind::COORDS_KIND_AZALT
|
|
: spair == MCC_COMMPROTO_COORD_KIND_XY ? MccCoordPairKind::COORDS_KIND_XY
|
|
: MccCoordPairKind::COORDS_KIND_GENERIC;
|
|
}
|
|
|
|
/* keywords */
|
|
|
|
// NOTE: THE COORDINATES AND TIME-RELATED QUANTITIES CAN BE EXPRESSED IN THE TWO FORMAT:
|
|
// 1) fixed-point real number, e.g. 123.43987537359 or -0.09775
|
|
// 2) sexagesimal number, e.g. 10:43:43.12 or -123:54:12.435
|
|
//
|
|
// 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
|
|
// BE EXPRESSED AS '+/-DEGREES:ARCMINUTES:ARCSECONDS'
|
|
|
|
|
|
// format of output coordinates:
|
|
// "COORDFMT FMT-type\n"
|
|
// e.g.:
|
|
// "COORDFMT SGM\n"
|
|
// "COORDFMT\n"
|
|
//
|
|
// server must return "ACK" or "ERROR INVPAR" in the case of 'set'-operation and
|
|
// "ACK COORDFMT FMT-type" in the case of 'get'-operation
|
|
// e.g.:
|
|
// "COORDFMT FIX\n" -> "ACK\n"
|
|
// "COORDFMT SXT\n" -> "ERROR INVPAR\n" (invalid parameter of format type)
|
|
// "COORDFMT\n" -> "ACK COORDFMT FIX\n"
|
|
//
|
|
|
|
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 (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";
|
|
|
|
|
|
// set/get target coordinates
|
|
// "TRAGET X-coord Y-coord XY-kind\n", if 'XY-kind' is omitted then one should assume RADEC_ICRS
|
|
// e.g.:
|
|
// "TARGET 12.7683487 10:23:09.75 AZZD\n"
|
|
// "TARGET HADEC\n"
|
|
// "TARGET\n"
|
|
//
|
|
// server must return "ACK" or "ERROR INVPAR" in the case of 'set'-operation and
|
|
// "ACK TARGET X-coord Y-coord XY-kind" in the case of 'get'-operation
|
|
// e.g.:
|
|
// "TARGET 12.7683487 10:23:09.75 AZZD\n" -> "ACK\n"
|
|
// "TARGET 12.7683487 10:23:09.75 AZZE\n" -> "ERROR INVPAR\n" (invalid parameter of coordinates pair kind)
|
|
//
|
|
// "TARGET HADEC\n" -> "ACK TARGET 20:21:56.32 -01:32:34.2 HADEC\n"
|
|
// "TARGET\n" -> "ACK TARGET 20:21:56.32 -01:32:34.2 RADEC_ICRS\n"
|
|
//
|
|
|
|
static constexpr std::string_view MCC_COMMPROTO_KEYWORD_TARGET_STR = "TARGET";
|
|
|
|
// get mount coordinates:
|
|
// "MOUNT coord-kind", if 'coord-kind' is omitted then coordinates are according to mount type,
|
|
// i.e., HADEC for equathorial-type mount and AZZD for alt-azimuthal one
|
|
// e.g.:
|
|
// "MOUNT RADEC\n" (get mount current apparent RA and DEC mount coordinates)
|
|
//
|
|
// server must return "ACK MOUNT X-coord Y-coord XY-kind" or "ERROR INVPAR"
|
|
// e.g.
|
|
// "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" -> "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";
|
|
|
|
|
|
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
|