ranczo-io/services/temperature_svc/main.cpp
2025-11-28 08:01:54 +01:00

156 lines
5.9 KiB
C++

#include <boost/asio.hpp>
#include <boost/asio/associated_executor.hpp>
#include <boost/asio/awaitable.hpp>
#include <boost/asio/co_spawn.hpp>
#include <boost/asio/detached.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/strand.hpp>
#include <boost/asio/this_coro.hpp>
#include <filesystem>
#include <memory_resource>
#include <span>
#include <string>
#include <tuple>
#include <vector>
#include <ranczo-io/utils/config.hpp>
#include <ranczo-io/utils/modbus.hpp>
#include <ranczo-io/utils/mqtt_client.hpp>
#include "measurement_publisher.hpp"
#include "ds18b20_sensor.hpp"
#include "ranczo-io/utils/memory_resource.hpp"
#include "spdlog/common.h"
#include "spdlog/spdlog.h"
using namespace std::chrono_literals;
using namespace std::string_view_literals;
namespace fs = std::filesystem;
std::vector< std::tuple< std::string_view, std::string_view, Type > > mapping = {
{"28-012113ed0fef", "beadroom_zone1", Type::floor}, // home/beadroom/sensor/floor/1/temperature
{"28-0121142e6c88", "beadroom_zone2", Type::floor}, // home/beadroom/sensor/floor/2/temperature
{"28-0119513810ff", "maciek_room", Type::floor},
{"28-0119516f39ff", "bathroom_guest", Type::floor},
{"28-012113f4d852", "bathroom_private", Type::floor},
{"28-0119517084ff", "office", Type::floor}, // home/office/sensor/floor/1/temperature
{"28-0119514282ff", "aska_room", Type::floor},
{"28-01195141aeff", "playroom", Type::floor},
{"28-011951477dff", "living_room", Type::air}, // home/beadroom/sensor/air/1/temperature
{"28-0b2398fcaed3", "living_room_zone1", Type::floor},
{"28-0b23990cdefb", "living_room_zone2", Type::floor},
{"28-012113f7d95d", "wardrobe", Type::floor},
{"28-0118790a57ff", "corridor", Type::floor},
{"28-3c01d6077b9c", "utility_room", Type::floor}
};
std::vector< std::tuple< std::string_view, std::string_view, Type > > mappingOld = {
{"28-012113ed0fef", "beadroom_zone1", Type::floor},
{"28-0121142e6c88", "beadroom_zone2", Type::floor},
{"28-0119513810ff", "maciekRoom", Type::floor},
{"28-0119516f39ff", "bathroom_1", Type::floor}, // bathroom_guast
{"28-012113f4d852", "bathroom_2", Type::floor}, // bathroom_private
{"28-0119517084ff", "office", Type::floor},
{"28-0119514282ff", "askaRoom", Type::floor},
{"28-01195141aeff", "playroom", Type::floor},
{"28-011951477dff", "livingroom", Type::air}, // living_room air ?? gdzie jest ten termometr???????
{"28-0b2398fcaed3", "livingroom_zone1", Type::floor},
{"28-0b23990cdefb", "livingroom_zone2", Type::floor},
{"28-012113f7d95d", "wardrobe", Type::floor},
{"28-0118790a57ff", "corridor", Type::floor},
{"28-3c01d6077b9c", "utilityRoom", Type::floor}
};
int main() {
using namespace ranczo;
boost::asio::io_context io_context;
memory_resource::HeapPoolResource _pool{1024 * 1024 * 1024}; // 1M
std::pmr::set_default_resource(&_pool);
// Register signal handler
spdlog::set_level(spdlog::level::info);
spdlog::debug("Debug Registering signal handlers");
spdlog::info("Registering signal handlers");
// promisa do „zatrzymaj program”
std::promise< void > stop_promise;
auto stop_future = stop_promise.get_future();
boost::asio::executor_work_guard< boost::asio::io_context::executor_type > work_guard = boost::asio::make_work_guard(io_context);
boost::asio::any_io_executor io_executor = io_context.get_executor();
SettingsStore store{"temperature_svc.db", io_executor, 1};
ComponentSettingsStore mqttconfig{store, "mqtt"};
ComponentSettingsStore mappingConfig{store, "mapping"};
if(not mqttconfig.contains("host"))
mqttconfig.save("host", "192.168.10.10");
if(not mqttconfig.contains("port"))
mqttconfig.save("port", 2502);
std::jthread io_thread([&] {
spdlog::info("io_context thread started");
io_context.run();
spdlog::info("io_context thread finished");
});
// create a modbus client to use with all internal objects
AsyncMqttClient mqttClient{io_executor};
MqttMeasurementPublisher pub{mqttClient, std::span{mapping}, std::span{mappingOld}, &_pool};
// const fs::path w1_root = "/home/bartoszek/mnt/w1remote/devices";
const fs::path w1_root = "/sys/devices";
std::pmr::vector< fs::path > bus_paths{&_pool};
spdlog::info("Iterating paths");
for(auto & entry : fs::directory_iterator(w1_root)) {
auto pos = entry.path().filename().string().rfind("w1_bus_master", 0);
if(pos != std::string::npos) {
bus_paths.push_back(entry.path());
}
}
spdlog::info("Iterating paths end");
if(bus_paths.empty()) {
spdlog::error("Nie znaleziono żadnych magistral 1-Wire");
return 1;
}
std::pmr::vector< ranczo::OneWireBus > buses{&_pool};
buses.reserve(bus_paths.size());
for(auto & bus : bus_paths) {
spdlog::info("found search bus {} ", bus.string());
auto strand = boost::asio::make_strand(io_context);
auto & bus_obj = buses.emplace_back(strand, pub, bus.string(), std::chrono::seconds(5));
boost::asio::co_spawn(strand, bus_obj.run(), boost::asio::detached);
}
boost::asio::signal_set signals(io_context, SIGINT, SIGTERM);
signals.async_wait([&](const boost::system::error_code & ec, int signo) {
if(ec)
return; // canceled podczas shutdown
spdlog::warn("Signal {} received", signo);
// Zainicjuj graceful shutdown na wątku io_context (bezpiecznie):
boost::asio::post(io_context, [&] {
spdlog::info("Graceful shutdown start");
mqttClient.cancel();
work_guard.reset();
io_context.stop(); // ok na tym samym wątku
spdlog::info("Graceful shutdown posted");
});
stop_promise.set_value(); // pobudzi main
});
if(io_thread.joinable())
io_thread.join();
return 0;
}