ModbusConnections.h 4.99 KB
/****************************************************************************
 * Copyright (c) 2022 Priva B.V.
 ****************************************************************************/
#pragma once

// Flexblox
#include "IModbusAdapter.h"
#include "ModbusAdapter.h"

// std
#include <memory>
#include <mutex>
#include <string>
#include <unordered_map>

/// Easy replacement of template construction
using AdapterList = std::vector<std::shared_ptr<IModbusAdapter>>;

/*!
 * \brief The ModbusConnections class conatins a list of all modbus connections, Serial and TCP.
 *        To access a specific connection, use its portname and / or endpoint to return it's interface.
 */
class ModbusConnections
{
public:
    /*!
     * \brief Default CTor
     */
    explicit ModbusConnections();

    /*!
     * \brief Default DTor
     */
    virtual ~ModbusConnections();

    /*!
     * \brief Create a modbus connection as described by the connection object.
     * \param config    - The connection object describing the connection in detail.
     * \return  The result of the creation.
     *          True    = succesful.
     *          False   = Failed.
     */
    bool CreateConnection( const ConnectionConfig &config );

    /*!
     * \brief Remove the connection described by its portname and/or endpoint.
     * \param portName  - The portname as its enum
     * \param endpoint  - combination of ip-address and portname in endpoint-format
     *                    ( tcp://<ip_address>:<portNumber> )
     *                    ( i.e. tcp://127.0.0.1:501 )
     * \return
     */
    bool DeleteConnection( const ConnectionPort portName, const std::string &endpoint = std::string() );

    /*!
     * \brief Give the number of registered serial and tcp-connections combined.
     */
    int ConnectionCount();

    /*!
     * \brief Get the connection give by its parameters.
     * \param   portName    - The portname by its enum
     * \param   endpoint    - combination of ip-address and portname in endpoint-format
     *                          ( tcp://<ip_address>:<portNumber> )
     *                          ( i.e. tcp://127.0.0.1:501 )
     * \return  Valid Pointer to the Modbus Connection Interface. nullptr if the connection wasn't found.
     */
    std::shared_ptr<IModbusAdapter> getConnection( const ConnectionPort portName, const std::string &endpoint = std::string() );

    // Convenient functions
    /*!
     * \brief Get the connection given by its parameters. If applicable, ipaddress and portnumber will be used to create the endpoint.
     * \param   portName    - The portname by its enum
     * \param   ipAddress   - The ipaddress of the TCP-connection
     * \param   tcpPortNumber   - The portnumber of the TCP-connection
     * \return  Valid Pointer to the Modbus Connection Interface. nullptr if the connection wasn't found.
     */
    std::shared_ptr<IModbusAdapter> getConnection( const ConnectionPort portName, const std::string &ipAddress, int tcpPortNumber );

    /*!
     * \brief Returns a list of all registered connections by their interfaces. This is a mix of Serial and TCP-connections.
     */
    AdapterList getConnections();

private:
    /*!
     * \brief Check if a connection already exist.
     * \param portName  - The portName by its enum
     * \param endpoint  - The endpoint this connection was registered with.
     * \return  A valid pointer to the Interface if the connection exist. If the connection is unknown, it will return a nullptr.
     *          shared_ptr can manifest themselves as booleans, so "!ptr" is sufficient to check.
     */
    std::shared_ptr<IModbusAdapter> connectionExist( const ConnectionPort portName, const std::string &endpoint = std::string() );

    /*!
     * \brief Create the TCP endpoint based on the connections IP-address and portnumber
     * \param ipAddress     - The ipAddress as string.
     * \param portNumber    - The portnumber as integer.
     * \return  The endpoint in format : tcp://<ip_address>:<portNumber> i.e. tcp://127.0.0.1:501
     */
    std::string createEndPoint( const std::string &ipAddress, int portNumber );

    /*!
     * \brief Create the TCP endpoint based on the connections IP-address and portnumber extracted from the connection configuration.
     * \param config - The configuration object used to create the connection.
     * \return  The endpoint in format : tcp://<ip_address>:<portNumber> i.e. tcp://127.0.0.1:501
     */
    std::string createEndPoint( const ConnectionConfig &config );

private:
    std::mutex m_mapSerialMutex;                                                        ///< Mutex protecting the serialmap
    std::mutex m_mapTcpMutex;                                                           ///< Mutex protecting the TCPmap
    std::unordered_map<ConnectionPort, std::shared_ptr<IModbusAdapter>> m_mapSerial;    ///< Unordered map holding the Modbus connections By PortName
    std::unordered_map<std::string, std::shared_ptr<IModbusAdapter>>    m_mapTcp;       ///< Unordered map holding the Modbus connections By tcp://endpoint:port
};