ModbusConnections.cpp 5.33 KB
#include "ModbusConnections.h"

ModbusConnections::ModbusConnections()
{

}

ModbusConnections::~ModbusConnections()
{
    if( m_mapSerial.size() > 0 )
    {
        // Iterate, remove and destroy ( Searching, Seek & Destroy )
    }

    if( m_mapTcp.size() > 0 )
    {
        // Iterate, remove and destroy ( Searching, Seek & Destroy )
    }
}

bool ModbusConnections::CreateConnection( const ConnectionConfig &config )
{
    std::shared_ptr<IModbusAdapter> ptrNewAdapter = std::make_shared<ModbusAdapter>();
    if( ptrNewAdapter == nullptr )
    {
        // Log a message and bail out
        return false;
    }

    // It looks like the pointer is valid. Time to connect.
    ptrNewAdapter->ModbusConnect( config );
    if( !ptrNewAdapter->isConnected() )
    {
        // Unsuccessful. Delete the object and return false
        ptrNewAdapter.reset();
        return false;
    }

    std::shared_ptr<IModbusAdapter> ptr = connectionExist( config.getPortEnum(), createEndPoint( config ) );
    if( ptr != nullptr )
    {
        if( !DeleteConnection( config.getPortEnum(), createEndPoint( config ) ) )
        {
            // Something went wrong here.. Our administration is "wonky" so report false and bail.
            // New connection is not created.
            ptrNewAdapter.reset();
            return false;
        }
    }

    if( config.getType() == ConnectionType::CT_TCP )
    {
        // === Critical Section ===
        std::lock_guard<std::mutex> guard( m_mapTcpMutex );
        m_mapTcp.insert( { createEndPoint( config ), ptrNewAdapter } );
        // === End Critical Section ===
    }
    else if( config.getType() == ConnectionType::CT_SERIAL )
    {
        // === Critical Section ===
        std::lock_guard<std::mutex> guard( m_mapSerialMutex );
        m_mapSerial.insert( { config.getPortEnum(), ptrNewAdapter } );
        // === End Critical Section ===
    }
    else
    {
        // No idea what the type is but not something we recognize.
        ptrNewAdapter.reset();
        return false;
    }
    return true;
}

bool ModbusConnections::DeleteConnection( const ConnectionPort portName, const std::string &endpoint )
{
    std::shared_ptr<IModbusAdapter> ptr = this->connectionExist( portName, endpoint );
    if( ptr == nullptr )
    {
        //  Seems like it is already gone. Shouldn't happen, but ok.
        return false;
    }

    // First remove it from the map.
    if( portName == ConnectionPort::CP_TCP )
    {
        // === Critical Section ===
        std::lock_guard<std::mutex> guard( m_mapTcpMutex );
        m_mapTcp.erase( endpoint );
        // === End Critical Section ===
    }
    else
    {
        // === Critical Section ===
        std::lock_guard<std::mutex> guard( m_mapSerialMutex );
        m_mapSerial.erase( portName );
        // === End Critical Section ===
    }

    // Call the disconnect for a clean exit.
    ptr->ModbusDisconnect();

    // Delete the pointer or decrease the ref-count
    ptr.reset();

    return true;
}

int ModbusConnections::ConnectionCount()
{
    return ( m_mapSerial.size() + m_mapTcp.size() );
}

std::shared_ptr<IModbusAdapter> ModbusConnections::getConnection( const ConnectionPort portName, const std::string &endpoint )
{
    return this->connectionExist( portName, endpoint );
}

std::shared_ptr<IModbusAdapter> ModbusConnections::getConnection( const ConnectionPort portName, const std::string &ipAddress, int tcpPortNumber )
{
    return this->connectionExist( portName, this->createEndPoint( ipAddress, tcpPortNumber ) );
}

AdapterList ModbusConnections::getConnections()
{
    AdapterList lstResult;

    {
        // === Critical Section ===
        std::lock_guard<std::mutex> guard(m_mapSerialMutex);
        // First we pick up the Serial Map
        for( auto const& [key, value] : m_mapSerial )
        {
            lstResult.push_back( value );
        }
        // === End Critical Section ===
    }

    {
        // === Critical Section ===
        std::lock_guard<std::mutex> guard(m_mapTcpMutex);
        // Next we pick all the entries in the tcp-map
        for( auto const& [key, value] : m_mapTcp )
        {
            lstResult.push_back( value );
        }
        // === End Critical Section ===
    }

    return lstResult;
}

std::shared_ptr<IModbusAdapter> ModbusConnections::connectionExist( const ConnectionPort portName, const std::string &endpoint )
{
    if( portName == ConnectionPort::CP_TCP )
    {
        auto search = m_mapTcp.find( endpoint );
        if( search != m_mapTcp.end() )
        {
            return search->second;
        }
        else
        {
            return nullptr;
        }
    }
    else
    {
        auto search = m_mapSerial.find( portName );
        if( search != m_mapSerial.end() )
        {
            return search->second;
        }
        else
        {
            return nullptr;
        }
    }
}

std::string ModbusConnections::createEndPoint( const std::string &ipAddress, int portNumber )
{
    if( portNumber > 0 && !ipAddress.empty() )
    {
        return std::string( "tcp://" + ipAddress + ":" + std::to_string( portNumber ) );
    }

    return std::string();
}

std::string ModbusConnections::createEndPoint( const ConnectionConfig &config )
{
    if( config.getType() != ConnectionType::CT_TCP )
    {
        // Early opt-out
        return std::string();
    }

    return createEndPoint( config.getIpAddress(), config.getTcpPort() );
}