156 lines
5.9 KiB
C++
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;
|
|
}
|