161 lines
4.8 KiB
C++
161 lines
4.8 KiB
C++
#include "timer.hpp"
|
|
#include <boost/asio/associated_executor.hpp>
|
|
#include <boost/asio/co_spawn.hpp>
|
|
#include <boost/asio/detached.hpp>
|
|
#include <boost/asio/this_coro.hpp>
|
|
#include <memory>
|
|
#include <memory_resource>
|
|
#include <spdlog/spdlog.h>
|
|
|
|
#include <boost/asio.hpp>
|
|
#include <boost/asio/any_io_executor.hpp>
|
|
#include <boost/asio/basic_repeating_timer.hpp>
|
|
#include <boost/asio/spawn.hpp>
|
|
|
|
#include <boost/asio/strand.hpp>
|
|
#include <boost/date_time/posix_time/posix_time_duration.hpp>
|
|
#include <boost/system/error_code.hpp>
|
|
|
|
|
|
|
|
|
|
#include <vector>
|
|
|
|
namespace ranczo {
|
|
|
|
class IHeater {
|
|
public:
|
|
virtual ~IHeater() = default;
|
|
};
|
|
|
|
class HeaterBase : public IHeater {
|
|
private:
|
|
boost::asio::repeating_timer timer;
|
|
|
|
protected:
|
|
double _targetTemperature;
|
|
double _histeresis;
|
|
|
|
public:
|
|
virtual void tick() {
|
|
spdlog::info("ping");
|
|
};
|
|
|
|
HeaterBase(boost::asio::any_io_executor & io_executor) : timer{io_executor} {
|
|
timer.start(boost::posix_time::seconds{1}, [&](const boost::system::error_code & e) {
|
|
// TODO error handling
|
|
spdlog::debug("Running timer");
|
|
this->tick();
|
|
});
|
|
}
|
|
};
|
|
|
|
class IRelay {
|
|
public:
|
|
virtual ~IRelay() = default;
|
|
virtual void setState(bool on) = 0;
|
|
virtual void state() = 0;
|
|
};
|
|
|
|
class ResistiveFloorHeater : public HeaterBase {};
|
|
|
|
class ModbusRelay : public IRelay {};
|
|
|
|
/// TODO
|
|
/// * Przypisanie prze³±cznika do maty grzewczej
|
|
/// * Zapis danych w DB
|
|
/// * Zapis ustawieñ
|
|
/// * Nas³uchiwanie na MQTT
|
|
|
|
} // namespace ranczo
|
|
|
|
// Modified completion token that will prevent co_await from throwing exceptions.
|
|
|
|
|
|
using namespace std::chrono_literals;
|
|
using boost::asio::yield_context;
|
|
using timer = boost::asio::steady_timer;
|
|
|
|
static auto now = timer::clock_type::now;
|
|
|
|
// struct X : private boost::noncopyable {
|
|
// int _id;
|
|
// boost::asio::any_io_executor _executor;
|
|
// std::string _topic;
|
|
|
|
// X(boost::asio::any_io_executor io_executor, int id, std::string topic) : _executor{io_executor}, _c{_executor}, _id{id}, _topic{topic} {
|
|
// spdlog::info("X for id/topic {}/{} created", _id, _topic);
|
|
|
|
// spdlog::info("timer for id {} start", _id);
|
|
// co_spawn(_executor, run_timer_id(), boost::asio::detached);
|
|
|
|
// spdlog::info("mqtt for id/topic {}/{} start", _id, _topic);
|
|
// co_spawn(_executor, subscribe_and_receive(_c, _topic), boost::asio::detached);
|
|
// }
|
|
|
|
// ~X() {
|
|
// spdlog::info("X {} destroyed", _id);
|
|
// }
|
|
|
|
// boost::asio::awaitable< void > run_timer_id() {
|
|
// auto executor = co_await boost::asio::this_coro::executor;
|
|
// int counter{0};
|
|
// boost::asio::steady_timer timer{executor};
|
|
|
|
// while(true) {
|
|
// timer.expires_after(std::chrono::seconds(1));
|
|
// co_await timer.async_wait(boost::asio::use_awaitable);
|
|
// spdlog::info("Hello from {}:{}", counter++, _id);
|
|
// }
|
|
|
|
// co_return;
|
|
// }
|
|
// };
|
|
|
|
#include "mqtt_client.hpp"
|
|
|
|
#include <boost/json.hpp>
|
|
|
|
boost::asio::awaitable<void> spawn(ranczo::AsyncMqttClient & c1){
|
|
spdlog::info("SPAWN subscribe");
|
|
co_await c1.subscribe("home/corridor/floor/temperature",[](const boost::json::value &){
|
|
spdlog::info("cb called");
|
|
});
|
|
|
|
spdlog::info("SPAWN listen");
|
|
co_await c1.listen();
|
|
spdlog::info("SPAWN return");
|
|
co_return;
|
|
}
|
|
|
|
int main() {
|
|
spdlog::set_level(spdlog::level::trace);
|
|
std::vector< std::unique_ptr< ranczo::IHeater > > _heaters;
|
|
boost::asio::io_service io_service;
|
|
|
|
/// Strand powoduje ¿e zadania do niego przypisane zostaj± wykonane sekwencyjnie,
|
|
/// get_executor pobrany z io_service nie daje takiej mo¿liwo¶ci i wtedy mo¿na wykonywaæ zadania równloegle
|
|
// boost::asio::any_io_executor io_executor = io_service.get_executor();
|
|
boost::asio::any_io_executor io_executor = boost::asio::make_strand(io_service);
|
|
|
|
char buffer[2048];
|
|
std::pmr::monotonic_buffer_resource mbr(buffer, 2048, std::pmr::null_memory_resource());
|
|
// "home/corridor/floor/temperature"
|
|
// "home/utilityRoom/floor/temperature"
|
|
// "home/wardrobe/floor/temperature"
|
|
|
|
// ranczo::AsyncMqttClient c1{io_executor};
|
|
// c1.add_subscribtion("home/corridor/floor/temperature", [](const boost::json::value &) { spdlog::info("cb called"); });
|
|
|
|
ranczo::PeriodicTimer timer{io_executor, std::chrono::seconds{1}, []() { spdlog::info("timer called"); }};
|
|
|
|
// xes.emplace_back(std::allocate_shared< X >(alloc, io_executor, 1, "home/corridor/floor/temperature"));
|
|
// xes.emplace_back(std::allocate_shared< X >(alloc, io_executor, 2, "home/utilityRoom/floor/temperature"));
|
|
// xes.emplace_back(std::allocate_shared< X >(alloc, io_executor, 3, "home/wardrobe/floor/temperature"));
|
|
|
|
boost::asio::io_service::work work(io_service);
|
|
io_service.run();
|
|
|
|
return 0;
|
|
}
|