asibfm700_config.h: rewrite mount config class (now it is descentant of

mcc::impl::MccKeyValueHolder)
This commit is contained in:
2026-05-19 17:23:17 +03:00
parent 363050009f
commit ed0fefbc75
2 changed files with 238 additions and 7 deletions

View File

@@ -121,20 +121,17 @@ set(ASIBFM700_LIB_SRC
asibfm700_common.h
asibfm700_servocontroller.h
asibfm700_servocontroller.cpp
)
set(ASIBFM700_LIB asibfm700mount)
add_library(
${ASIBFM700_LIB}
STATIC
${ASIBFM700_LIB_SRC}
asibfm700_mount.h
asibfm700_mount.cpp
asibfm700_configfile.h
asibfm700_netserver.cpp
asibfm700_netserver.h
asibfm700_config.h
)
set(ASIBFM700_LIB asibfm700mount)
add_library(${ASIBFM700_LIB} STATIC ${ASIBFM700_LIB_SRC})
# add_dependencies(${ASIBFM700_LIB} mcc)
target_include_directories(${ASIBFM700_LIB} PUBLIC ${CMAKE_BINARY_DIR}) # LibSidServo headers

234
asibfm700_config.h Normal file
View File

@@ -0,0 +1,234 @@
#pragma once
#include <mcc/mcc_keyvalue.h>
#include <mcc/mcc_pcm.h>
#include <filesystem>
namespace asibfm700
{
template <mcc::impl::mcc_variant_valid_type_c T>
struct config_record_t : mcc::impl::mcc_simple_kv_record_t<T> {
std::vector<std::string_view> head_comment;
std::string_view inline_comment;
};
template <mcc::impl::mcc_variant_valid_type_c T>
static config_record_t<T> make_config_record(
std::string_view key,
T value,
std::vector<std::string_view> hcomm = {},
std::string_view icomm = {},
mcc::impl::mcc_serialization_params_t const& spars = mcc::impl::mcc_serialization_params_t{})
{
return config_record_t<T>{key, value, value, spars, hcomm, icomm};
}
static auto Asibfm700MountConfigurationDefaults = std::make_tuple(
/* geographic coordinates of the observation site */
make_config_record("siteLatitude", mcc::impl::MccAngle(43.646711_degs), {"site latitude in degrees"}),
make_config_record("siteLongitude", mcc::impl::MccAngle(41.440732_degs), {"site longitude in degrees"}),
make_config_record("siteElevation", 2070.0, {"site elevation in meters"}),
/* celestial coordinate transformation */
make_config_record("refractWavelength", 0.55, {"wavelength at which refraction is calculated (in mkm)"}),
make_config_record("leapSecondFilename", std::string(), {"an empty filename means default precompiled string"}),
make_config_record("bulletinAFilename", std::string(), {"an empty filename means default precompiled string"}),
/* pointing correction model */
// PCM type
make_config_record(
"pcmType",
mcc::impl::MccDefaultPCMType::PCM_TYPE_GEOMETRY,
{"PCM type:", "a case-sensetive string:", " GEOMETRY - 'classic' geometry-based correction coefficients",
" GEOMETRY-BSPLINE - previous one and additional 2D B-spline corrections",
" BSPLINE - pure 2D B-spline corrections"}),
// PCM geometrical coefficients
make_config_record("pcmGeomCoeffs",
std::vector<double>{0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0},
{"PCM geometrical coefficients"}),
// make_config_record("pcmBsplineDegree", std::vector<size_t>{3, 3}, {"PCM B-spline degrees"}),
// PCM B-spline knots along X-axis (HA-angle or azimuth). By default from 0 to 2*PI radians
// NOTE: The first and last values are interpretated as border knots!!!
// Thus the array length must be equal to or greater than 2!
make_config_record("pcmBsplineXknots",
std::vector<double>{0.0, 0.6981317, 1.3962634, 2.0943951, 2.7925268, 3.4906585, 4.1887902,
4.88692191, 5.58505361, 6.28318531},
{"PCM B-spline knots along X-axis (HA-angle or azimuth). By default from 0 to 2*PI radians",
"NOTE: The first and last values are interpretated as border knots!!!",
" Thus the array length must be equal to or greater than 2!"}),
// PCM B-spline knots along Y-axis (declination or zenithal distance). By default from -PI/6 to PI/2 radians
// NOTE: The first and last values are interpretated as border knots!!!
// Thus the array length must be equal to or greater than 2!
make_config_record(
"pcmBsplineYknots",
std::vector<double>{-0.52359878, -0.29088821, -0.05817764, 0.17453293, 0.40724349, 0.63995406, 0.87266463,
1.10537519, 1.33808576, 1.57079633},
{"PCM B-spline knots along Y-axis (declination or zenithal distance). By default from -PI/6 to PI/2 radians",
"NOTE: The first and last values are interpretated as border knots!!!",
" Thus the array length must be equal to or greater than 2!"}),
// PCM B-spline coeffs for along X-axis (HA-angle or azimuth)
make_config_record("pcmBsplineXcoeffs", std::vector<double>{}, {"PCM B-spline coeffs for along X-axis (HA-angle)"}),
// PCM B-spline coeffs for along Y-axis (declination or zenithal distance)
make_config_record("pcmBsplineYcoeffs",
std::vector<double>{},
{"PCM B-spline coeffs for along Y-axis (declination angle)"}));
class Asibfm700MountConfiguration : public mcc::impl::MccKeyValueHolder<decltype(Asibfm700MountConfigurationDefaults)>
{
using base_t = mcc::impl::MccKeyValueHolder<decltype(Asibfm700MountConfigurationDefaults)>;
public:
Asibfm700MountConfiguration() : base_t(Asibfm700MountConfigurationDefaults)
{
// fill comments
auto get_comm = [this]<size_t I>() {
auto& rec = std::get<I>(Asibfm700MountConfigurationDefaults);
for (auto const& comm : rec.head_comment) {
if (comm.size()) {
_headComment[_hashes[I]].emplace_back(std::string{comm.begin(), comm.end()});
} else {
_headComment[_hashes[I]].emplace_back(std::nullopt);
}
}
_inlineComment[_hashes[I]] = rec.inline_comment;
};
[&, this]<size_t... Is>(std::index_sequence<Is...>) {
(get_comm.template operator()<Is>(), ...);
}(std::make_index_sequence<Asibfm700MountConfiguration::NUMBER_OF_RECORDS>{});
}
~Asibfm700MountConfiguration() = default;
std::error_code load(const std::filesystem::path& path)
{
std::string buffer;
std::error_code ec;
auto sz = std::filesystem::file_size(path, ec);
if (!ec && sz) {
std::ifstream fst(path);
try {
buffer.resize(sz);
fst.read(buffer.data(), sz);
fst.close();
ec = base_t::fromCharRange(buffer);
if (!ec) {
// remove possible spaces in filenames
std::string val = getValue<std::string>("leapSecondFilename").value_or("");
auto fname = mcc::utils::trimSpaces(val);
setValue("leapSecondFilename", fname);
val = getValue<std::string>("bulletinAFilename").value_or("");
fname = mcc::utils::trimSpaces(val);
setValue("bulletinAFilename", fname);
val = getValue<std::string>("MountDevPath").value_or(std::string{});
fname = mcc::utils::trimSpaces(val);
setValue("MountDevPath", fname);
val = getValue<std::string>("EncoderDevPath").value_or(std::string{});
fname = mcc::utils::trimSpaces(val);
setValue("EncoderDevPath", fname);
val = getValue<std::string>("EncoderXDevPath").value_or(std::string{});
fname = mcc::utils::trimSpaces(val);
setValue("EncoderXDevPath", fname);
val = getValue<std::string>("EncoderYDevPath").value_or(std::string{});
fname = mcc::utils::trimSpaces(val);
setValue("EncoderYDevPath", fname);
val = getValue<std::string>("slewingPathFilename").value_or(std::string{});
fname = mcc::utils::trimSpaces(val);
setValue("slewingPathFilename", fname);
val = getValue<std::string>("trackingPathFilename").value_or(std::string{});
fname = mcc::utils::trimSpaces(val);
setValue("trackingPathFilename", fname);
}
} catch (std::ios_base::failure const& ex) {
ec = ex.code();
} catch (std::length_error const& ex) {
ec = std::make_error_code(std::errc::no_buffer_space);
} catch (std::bad_alloc const& ex) {
ec = std::make_error_code(std::errc::not_enough_memory);
} catch (...) {
ec = std::make_error_code(std::errc::operation_canceled);
}
_lastConfigPath = path;
}
return ec;
}
std::error_code reloadCurrentConfig()
{
return load(_lastConfigPath);
}
std::error_code save(const std::filesystem::path& path)
{
std::error_code ec;
std::string buff;
ec = toCharRange(buff);
if (ec) {
return ec;
}
std::ofstream fst(path, std::ios_base::trunc);
if (!fst.is_open()) {
ec = std::make_error_code(std::errc::io_error);
} else {
try {
fst << buff;
} catch (std::ios_base::failure const& ex) {
ec = ex.code();
} catch (...) {
ec = std::make_error_code(std::errc::operation_canceled);
}
}
return ec;
}
std::error_code save()
{
return save(_lastConfigPath);
}
std::filesystem::path configFilename() const
{
return _lastConfigPath;
}
private:
std::filesystem::path _lastConfigPath{};
};
} // namespace asibfm700