istatecallback.h 3.98 KB
#ifndef OSDEV_COMPONENTS_MQTT_ISTATECALLBACK_H
#define OSDEV_COMPONENTS_MQTT_ISTATECALLBACK_H

// std
#include <ostream>

// boost
#include <boost/signals2.hpp>

namespace osdev {
namespace components {
namespace mqtt {

/*!
 *  \brief  Struct introduces a typed client identifier.
 */
struct ClientIdentifier
{
    /*!
     *  \brief Construct a ClientIdentifier
     *  \param id The client id. Default is empty.
     */
    explicit ClientIdentifier(const std::string& id = "")
        : m_id(id)
    {
    }

    const std::string m_id; ///< Client identifier
};

/*!
 *  \brief  Enumeration of state codes.
 *          The states Unknown, CommunicationFailure, GeneralFailure, Good
 *          and Shutdown are used to communicate state about the server
 *          that is connected to. The states ConnectionFailure and Unregister
 *          communicate state about the client.
 */
enum class StateEnum
{
    Unknown,              ///< State of underlying data source is unknown.
    CommunicationFailure, ///< No communication with underlying data source.
    GeneralFailure,       ///< Some failure in the underlying data source.
    Good,                 ///< Underlying data source is available.
    Shutdown,             ///< Underlying data source is shutting down.
    ConnectionFailure,    ///< Client connection has failed.
    Unregister            ///< Client is being unregistered.
};

/*!
 *  \brief  Stream a StateEnum value
 */
std::ostream& operator<<(std::ostream& os, StateEnum rhs);

/*!
 *  \brief  Type for identifying state change callbacks.
 */
using StateChangeCallbackHandle = std::uint32_t;

class IStateCallback;

/*!
 *  \brief  Create an id for an IStateCallback object.
 *  \param  idStatic    - Static part of the id (name of the class).
 *  \param  clientId    - Client identifier. Can contain information on how
 *                        the client is used for instance. If the id is empty
 *                        it is not used.
 *  \param  idDynamic   - Dynamic part (object address).
 *  \return identifier as string
 */
std::string createIdentifier(const std::string& idStatic, const ClientIdentifier& clientId, const IStateCallback* idDynamic);

/*!
 *  \brief  State callback interface.
 *          When a client implements this interface it can be registered on a
 *          server in order to handle state changes from the underlying data source.
 *  \note   When the client is destroyed it is expected that it unregisters itself by calling
 *          clearAllStateChangeCallbacks().
 */
class IStateCallback
{
public:
    using SigStateChange = boost::signals2::signal<void(const IStateCallback*, StateEnum)>;
    using SlotStateChange = SigStateChange::slot_type;

    virtual ~IStateCallback();

    /*!
     *  \brief Get a string that identifies this interface.
     */
    virtual std::string clientId() const = 0;

    /*!
     *  \brief  Register a callback function that is called when the status changes.
     *  \param  cb  - The callback function to register.
     *  \return handle to the registered callback.
     *  \note   Make sure that the callback function lives longer than the IStateCallback object.
     *          Otherwise unregister callback function before it is destroyed.
     */
    virtual StateChangeCallbackHandle registerStateChangeCallback(const SlotStateChange& cb) = 0;

    /*!
     *  \brief  Unregister a previously registered callback function.
     *          If the callback function was not registered nothing happens.
     *  \param  handle  - Identifies the callback function to to unregister.
     */
    virtual void unregisterStateChangeCallback(StateChangeCallbackHandle handle) = 0;

    /*!
     *  \brief  Remove all the registered callback functions.
     */
    virtual void clearAllStateChangeCallbacks() = 0;

    /*!
     *  \brief  retuns the latest state received.
     */
    virtual StateEnum state() const = 0;
};

}       // End namespace mqtt
}       // End namespace components
}       // End namespace osdev

#endif  // OSDEV_COMPONENTS_MQTT_ISTATECALLBACK_H