Program Listing for File hardware_monitor.hpp

Return to documentation for file (hardware_monitor.hpp)

#ifndef HW_MON_FRONTEND_H_
#define HW_MON_FRONTEND_H_

#include <cstdint>
#include <memory>

#include "config.hpp"
#include "hardware_monitor_backend.hpp"
#include "bus.hpp"
#include "publisher.hpp"
#include "network/utility.hpp"
#include "config/config_register.hpp"
#include "ers/ers.h"

using namespace std::chrono_literals;

template <class DEV>
class HwMonitor
{
    public:
        using device_pair = std::pair<std::shared_ptr<DEV>, std::shared_ptr<DEV>>;

        HwMonitor(const std::vector<device_pair> & device_pairs, const ConfigRegister & c);

        bool publish_monitor_info();

    private:
        HwMonBackend<DEV> m_backend;
        Bus m_bus;
        uint64_t m_fid;
        std::unique_ptr<Publisher> m_publisher;
};


template <class DEV>
HwMonitor<DEV>::HwMonitor(const std::vector<HwMonitor<DEV>::device_pair> & device_pairs, const ConfigRegister &c)
    : m_backend(device_pairs, c.extra_mon),
      m_bus{c.bus_dir, c.bus_group, "register-mon-"+std::to_string(c.dconfs.at(0).dev_no), c.verbose_bus},
      m_fid(c.fid_mon)
{
    constexpr int net_pages{16};
    constexpr int net_page_size{4096};
    constexpr int net_page_timeout{0};
    auto fid_mon = Elink(c.fid_mon);

    unsigned int mon_interval_us = 1e6*c.mon_interval;
    ERS_INFO(std::format("Hardware monitoring poll period {} s.", c.mon_interval));
    m_publisher = network::utility::create_buffered_publisher(c.network_mode, c.local_ip, c.port_mon,
        net_pages, net_page_size, net_page_timeout, UINT32_MAX, "HWMonitor", 0ms);
    m_bus.publish(std::vector<felixbus::FelixBusElinkInfo>{felixbus::FelixBusElinkInfo{
        .fid = fid_mon.fid,
        .ip = c.local_ip,
        .port = static_cast<std::uint16_t>(c.port_mon),
        .unbuffered = false,
        .pubsub = true,
        .tcp = c.network_mode == NetworkMode::tcp,
        .stream = fid_mon.has_streams,
        .netio_pages = net_pages,
        .netio_pagesize = net_page_size,
    }});
    m_publisher->set_periodic_callback(mon_interval_us, [this]{return publish_monitor_info();});
}


template <class DEV>
bool HwMonitor<DEV>::publish_monitor_info()
{
    std::string msg = m_backend.get_monitor_data();
    auto msg_ptr = reinterpret_cast<uint8_t*>(msg.data());
    std::array<iovec, 2> net_msg;
    uint8_t status = 0;
    net_msg[0].iov_len = 1;
    net_msg[0].iov_base = &status;
    net_msg[1].iov_len = msg.length();
    net_msg[1].iov_base = msg_ptr;
    //The publish function that takes a pointer to the data message
    //assumes that the first byte is the status byte.
    std::ignore = m_publisher->publish(m_fid, net_msg, 0, 0, 0);
    std::ignore = m_publisher->flush(m_fid);
    //This function must return false otherwise the callback is invoked again.
    //TODO: the publisher set_periodic_callback is designed for felix-tohost.
    return false;
}


#endif /* HW_MON_FRONTEND_H_ */