#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 ptrNewAdapter = std::make_shared(); 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 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 guard( m_mapTcpMutex ); m_mapTcp.insert( { createEndPoint( config ), ptrNewAdapter } ); // === End Critical Section === } else if( config.getType() == ConnectionType::CT_SERIAL ) { // === Critical Section === std::lock_guard 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 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 guard( m_mapTcpMutex ); m_mapTcp.erase( endpoint ); // === End Critical Section === } else { // === Critical Section === std::lock_guard 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 ModbusConnections::getConnection( const ConnectionPort portName, const std::string &endpoint ) { return this->connectionExist( portName, endpoint ); } std::shared_ptr 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 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 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 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() ); }