istatecallback.h 5.62 KB
/* ****************************************************************************
 * Copyright 2019 Open Systems Development BV                                 *
 *                                                                            *
 * Permission is hereby granted, free of charge, to any person obtaining a    *
 * copy of this software and associated documentation files (the "Software"), *
 * to deal in the Software without restriction, including without limitation  *
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,   *
 * and/or sell copies of the Software, and to permit persons to whom the      *
 * Software is furnished to do so, subject to the following conditions:       *
 *                                                                            *
 * The above copyright notice and this permission notice shall be included in *
 * all copies or substantial portions of the Software.                        *
 *                                                                            *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,   *
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL    *
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING    *
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER        *
 * DEALINGS IN THE SOFTWARE.                                                  *
 * ***************************************************************************/
#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