fix mem problems
This commit is contained in:
parent
2db84fb720
commit
e58f3fc139
@ -4,8 +4,10 @@ project(Ranczo-IO)
|
||||
set(CMAKE_CXX_STANDARD 23)
|
||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
||||
|
||||
add_compile_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer)
|
||||
add_link_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer)
|
||||
# add_compile_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer)
|
||||
# add_link_options(-g -fsanitize=address,undefined,float-divide-by-zero,float-cast-overflow,null -fsanitize-address-use-after-scope -fno-sanitize-recover=all -fno-sanitize=alignment -fno-omit-frame-pointer)
|
||||
|
||||
add_compile_options(-g -fno-omit-frame-pointer)
|
||||
|
||||
include(CheckIPOSupported)
|
||||
check_ipo_supported(RESULT supported OUTPUT error)
|
||||
@ -106,8 +108,10 @@ FetchContent_Declare(fmt
|
||||
FetchContent_MakeAvailable(fmt)
|
||||
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
|
||||
add_compile_definitions(BOOST_ASIO_ENABLE_HANDLER_TRACKING=1)
|
||||
# add_compile_definitions(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
|
||||
|
||||
add_subdirectory(libs)
|
||||
add_subdirectory(services)
|
||||
add_subdirectory(tests)
|
||||
|
||||
# 139929 bartosz+ 20 0 20,0t 157036 57964 S 0,0 1,0 0:02.58 ranczo-io_flor
|
||||
|
||||
@ -16,6 +16,7 @@ set(MODBUS_INCLUDES "${MODBUS_PREFIX}/include")
|
||||
|
||||
file(MAKE_DIRECTORY "${MODBUS_PREFIX}")
|
||||
file(MAKE_DIRECTORY "${MODBUS_BUILD}")
|
||||
file(MAKE_DIRECTORY "${MODBUS_INCLUDES}")
|
||||
|
||||
# Some environments need -fPIC for static archives used in shared libs
|
||||
set(_LIBMODBUS_ENV "CFLAGS=-fPIC" "CPPFLAGS=-fPIC" "CXXFLAGS=-fPIC")
|
||||
|
||||
@ -1,14 +1,17 @@
|
||||
#include "spdlog/spdlog.h"
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
#include <cstdint>
|
||||
#include <modbus/modbus.h>
|
||||
#include "config.hpp"
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
#include <ranczo-io/utils/modbus.hpp>
|
||||
|
||||
#include <boost/asio.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/this_coro.hpp>
|
||||
#include <boost/smart_ptr/shared_ptr.hpp>
|
||||
|
||||
#include <modbus/modbus.h>
|
||||
|
||||
#include <cerrno>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
@ -31,7 +34,7 @@ awaitable_expected< void > ModbusTcpContext::async_connect() {
|
||||
return unexpected(errno_errc());
|
||||
std::unique_ptr< modbus_t, CtxDeleter > ctx(raw);
|
||||
|
||||
if(::modbus_connect(ctx.get()) == -1){
|
||||
if(::modbus_connect(ctx.get()) == -1) {
|
||||
spdlog::error("Modbus failed to conenct to {}:{}", host_.c_str(), port_);
|
||||
return unexpected(errno_errc());
|
||||
}
|
||||
@ -108,31 +111,17 @@ awaitable_expected< T > ModbusTcpContext::async_call(Maker && maker) {
|
||||
std::move(initiator), asio::use_awaitable_t<>{});
|
||||
}
|
||||
|
||||
struct ModbusDeviceLog{
|
||||
int unit;
|
||||
uint16_t address;
|
||||
std::string ctx;
|
||||
ModbusDeviceLog(int unit, uint16_t address, std::string_view ctx): unit{unit}, address{address}, ctx{ctx.data(), ctx.size()} {
|
||||
spdlog::trace("Modbus BEGIN {}/{} : {}", unit, address, ctx);
|
||||
}
|
||||
~ModbusDeviceLog(){
|
||||
spdlog::trace("Modbus END {}/{} : {}", unit, address, ctx);
|
||||
}
|
||||
};
|
||||
|
||||
awaitable_expected< uint16_t > ModbusDevice::async_read_holding_register(uint16_t address) {
|
||||
address -= 1;
|
||||
ModbusDeviceLog _{unit_id_, address, "async_read_holding_register"};
|
||||
auto ctx = ctx_; // kopia shared_ptr dla bezpieczeństwa w tasku
|
||||
co_return co_await ctx->call_with_lock< std::uint16_t >([this, address](modbus_t * c) -> expected< std::uint16_t > {
|
||||
ModbusDeviceLog _{unit_id_, address, "async_read_holding_register:lambda"};
|
||||
if(::modbus_set_slave(c, unit_id_) == -1){
|
||||
if(::modbus_set_slave(c, unit_id_) == -1) {
|
||||
spdlog::error("Modbus modbus_set_slave for {}/{} failed with {}", unit_id_, address, errno);
|
||||
return unexpected(errno_errc());
|
||||
}
|
||||
uint16_t val = 0;
|
||||
int rc = ::modbus_read_registers(c, static_cast< int >(address), 1, &val);
|
||||
if(rc == -1){
|
||||
if(rc == -1) {
|
||||
spdlog::error("Modbus modbus_read_registers for {}/{} failed with {}", unit_id_, address, errno);
|
||||
return unexpected(errno_errc());
|
||||
}
|
||||
@ -140,20 +129,20 @@ awaitable_expected< uint16_t > ModbusDevice::async_read_holding_register(uint16_
|
||||
});
|
||||
}
|
||||
|
||||
awaitable_expected<void> ModbusDevice::async_write_coil(uint16_t address, bool value) {
|
||||
awaitable_expected< void > ModbusDevice::async_write_coil(uint16_t address, bool value) {
|
||||
auto ctx = ctx_;
|
||||
ModbusDeviceLog _{unit_id_, address, "async_write_coil"};
|
||||
co_return co_await ctx->call_with_lock<void>(
|
||||
[this, address, value](modbus_t* c) -> expected<void> {
|
||||
ModbusDeviceLog _{unit_id_, address, "async_write_coil:lambda"};
|
||||
if (::modbus_set_slave(c, unit_id_) == -1)
|
||||
return unexpected(errno_errc());
|
||||
const int rc = ::modbus_write_bit(c, static_cast<int>(address), value ? 1 : 0);
|
||||
if (rc == -1)
|
||||
return unexpected(errno_errc());
|
||||
return {};
|
||||
}
|
||||
);
|
||||
co_return co_await ctx->call_with_lock< void >([this, address, value](modbus_t * c) -> expected< void > {
|
||||
if(::modbus_set_slave(c, unit_id_) == -1){
|
||||
spdlog::error("Modbus modbus_set_slave for {}/{} failed with {}", unit_id_, address, errno);
|
||||
return unexpected(errno_errc());
|
||||
}
|
||||
const int rc = ::modbus_write_bit(c, static_cast< int >(address), value ? 1 : 0);
|
||||
if(rc == -1){
|
||||
spdlog::error("Modbus modbus_write_bit for {}/{} failed with {}", unit_id_, address, errno);
|
||||
return unexpected(errno_errc());
|
||||
}
|
||||
return {};
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace ranczo
|
||||
|
||||
@ -1,20 +1,19 @@
|
||||
#include <boost/algorithm/string/compare.hpp>
|
||||
#include <boost/regex/config.hpp>
|
||||
#include <map>
|
||||
#include <optional>
|
||||
#include <ranczo-io/utils/mqtt_client.hpp>
|
||||
|
||||
#include <boost/algorithm/string/compare.hpp>
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/asio/associated_executor.hpp>
|
||||
#include <boost/asio/co_spawn.hpp>
|
||||
#include <boost/asio/detached.hpp>
|
||||
#include <boost/asio/io_context.hpp>
|
||||
#include <boost/asio/signal_set.hpp>
|
||||
#include <boost/asio/strand.hpp>
|
||||
#include <boost/asio/this_coro.hpp>
|
||||
#include <boost/asio/use_future.hpp>
|
||||
|
||||
#include <boost/json/serialize.hpp>
|
||||
|
||||
#include <boost/algorithm/string/split.hpp>
|
||||
#include <boost/regex/config.hpp>
|
||||
|
||||
#include <spdlog/spdlog.h>
|
||||
|
||||
@ -48,9 +47,6 @@ namespace ranczo {
|
||||
using namespace std::chrono_literals;
|
||||
using namespace std::string_view_literals;
|
||||
|
||||
std::atomic< bool > running = true;
|
||||
boost::asio::io_context * g_io = nullptr;
|
||||
|
||||
struct ZoneInfo {
|
||||
std::string room;
|
||||
int zone; // no _zone
|
||||
@ -132,41 +128,34 @@ inline ranczo::awaitable_expected< void > forward_floor_temperature_all_rooms(ra
|
||||
co_return ranczo::_void{};
|
||||
}
|
||||
|
||||
void signal_handler(int signum) {
|
||||
spdlog::warn("Signal received: {}, stopping io_context...", signum);
|
||||
running = false;
|
||||
if(g_io) {
|
||||
g_io->stop(); // <--- This stops io_context.run()
|
||||
}
|
||||
}
|
||||
|
||||
int main() {
|
||||
spdlog::set_level(spdlog::level::trace);
|
||||
std::vector< std::shared_ptr< ranczo::TemperatureController > > _heaters;
|
||||
|
||||
boost::asio::io_context io_context;
|
||||
g_io = &io_context;
|
||||
|
||||
// Register signal handler
|
||||
spdlog::info("Registering signal handlers");
|
||||
std::signal(SIGINT, signal_handler);
|
||||
std::signal(SIGTERM, signal_handler);
|
||||
|
||||
|
||||
// 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();
|
||||
|
||||
spdlog::info("Create Modbus TCP context");
|
||||
auto modbus_relayBoardsCtx = ranczo::ModbusTcpContext::create(io_context, // używamy istniejącego io_context
|
||||
"192.168.10.10", // host Modbus TCP
|
||||
2502, // port Modbus TCP
|
||||
1 // rozmiar puli dla libmodbus
|
||||
);
|
||||
|
||||
boost::asio::any_io_executor io_executor = io_context.get_executor();
|
||||
|
||||
|
||||
auto fut = boost::asio::co_spawn(
|
||||
io_executor,
|
||||
[modbus_relayBoardsCtx]() -> ranczo::awaitable_expected< void > { co_return co_await modbus_relayBoardsCtx->async_connect(); },
|
||||
boost::asio::use_future);
|
||||
|
||||
boost::asio::executor_work_guard< boost::asio::io_context::executor_type > work_guard = boost::asio::make_work_guard(io_context);
|
||||
|
||||
std::jthread io_thread([&] {
|
||||
spdlog::info("io_context thread started");
|
||||
io_context.run();
|
||||
@ -216,7 +205,7 @@ int main() {
|
||||
spdlog::debug("make_ramp_thermostat {} / {} : create Relay Thermostat", room, zone);
|
||||
return std::make_shared< ranczo::RelayThermostat >(io_executor, mqttClient, std::move(relay), std::move(thermo), room, zone);
|
||||
};
|
||||
|
||||
|
||||
// // Floor 0
|
||||
_heaters.emplace_back(make_ramp_thermostat("livingroom"sv, 1, make_relay(16, 2))); // 3 strefy
|
||||
_heaters.emplace_back(make_ramp_thermostat("livingroom"sv, 2, make_relay(16, 10)));
|
||||
@ -242,11 +231,32 @@ int main() {
|
||||
|
||||
/// TODO czujnik temperatury
|
||||
// _heaters.emplace_back(relayThermostatFactory("corridor_up"sv, 1, relay(0, 0)));
|
||||
|
||||
|
||||
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");
|
||||
|
||||
_heaters.clear(); // remove all heaters
|
||||
mqttProxyClient.cancel();
|
||||
modbusDevices.clear();
|
||||
// modbus_relayBoardsCtx->async_close();
|
||||
|
||||
work_guard.reset();
|
||||
io_context.stop(); // ok na tym samym wątku
|
||||
spdlog::info("Graceful shutdown posted");
|
||||
});
|
||||
|
||||
stop_promise.set_value(); // pobudzi main
|
||||
});
|
||||
|
||||
for(auto & heater : _heaters) {
|
||||
co_spawn(io_context, heater->start(), boost::asio::detached);
|
||||
}
|
||||
|
||||
|
||||
if(io_thread.joinable())
|
||||
io_thread.join();
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user