ModbusAdapter.h 5.46 KB
/*****************************************************************************
 * Copyright (c) 2022 Priva b.v.
 *****************************************************************************/

#pragma once

#include "ConnectionConfig.h"
#include "IModbusAdapter.h"

// std
#include <memory>
#include <variant>
#include <vector>

typedef modbus_t;

/// @brief The ModbusAdapter class represents a single modbus context. Each context will
///       result in an instance of this class. It is not intended to be
///       created directly but through a factory. The factory will create
///       the object and return the pointer to its interface.
class ModbusAdapter : public IModbusAdapter
{
public:
    /*!
     * \brief Default constructor
     */
    explicit ModbusAdapter();

    /*!
     * \brief Default destructor
     */
    virtual ~ModbusAdapter();

    /*!
     * \brief /// Create a modbus connection, accepting a configuration object.
     */
    bool ModbusConnect( const ConnectionConfig &config ) override;

    /*!
     * \brief   ModbusDisconnect
     *          Disconnect from the serial bus or the TCP connection, freeing its resources
     */
    bool ModbusDisconnect() override;

    /*!
     * \brief Read data from a modbus device given by its parameters.
     * \param   slaveId         - The Id of the ModbusDevice.
     * \param   functionCode    - The code describing the action we want to perform on the device.
     *                            Given by an enum, provided by the modbus-stack.
     * \param   startAddress    - Startaddres of the register we want to read.
     * \param   noOfItems       - The number of items we expect back.
     * \returns modbusData      - A vector holding each register in an entry in the same order as they are received.
     *                            Empty if no data was received.
     */
    modbusData ModbusReadData( int slaveId, int functionCode, int startAddress, int noOfItems ) override;

    /*!
     * \brief Read data from the holdregisters ( or keep-registers ) of a modbus device.
     * \param   slaveId         - The Id of the ModbusDevice.
     * \param   startAddress    - Startaddres of the register we want to read.
     * \param   noOfItems       - The number of items we expect back.
     * \returns modbusData      - A vector holding each register in an entry in the same order as they are received.
     *                            Empty if no data was received.
     */
    modbusData ModbusReadHoldReg( int slaveId, int startAddress, int noOfItems ) override;

    /*!
     * \brief Write data to the device.
     * \param slaveId           - The Id of the Modbus device
     * \param funtionCode       - The code describing the action we want to perform on the device
     *                            given by an enum, provided by the modbus-stack.
     * \param startAddress      - Startaddres of the register we want to read.
     * \param noOfItems         - The number of items we expect to be written
     * \param values            - The values we want to write to the given device. Each vector-entry represents a single byte
     *                            and they will be sent in sequence.
     */
    void ModBusWriteData( int slaveId, int functionCode, int startAddress, int noOfItems, std::vector<int>values ) override;

    /*!
     * \brief   Indicates if this connection is alive.
     * \return  True if alive, false if not.
     */
    bool isConnected() const override;

    /*!
     * \brief   returns the translated error code coming from the modbus stack.
     * \param   errnum          - error Number coming from the stack.
     * \return  The translated error as a string. Empty if not resolvable.
     */
    std::string ErrorString( int errorNumber ) const override;

private:    // Methods
    /*!
     *  Create and connect to a serial port.
     *
     *  @param serialport   - The serial port by name ( i.e. /dev/ttyUSB0 )
     *  @param baud         - The port speed in a serial port context ( default = 115200 )
     *  @param parity       - The parity. ( Default : None, no parity )
     *  @param dataBits     - The number of databits. RTU uses 8 (0 - 255), ASCII uses 7 (0 - 127). Default is RTU
     *  @param stopBits     - The number of stopbits used to detect the end of the frame. ( Default = 1 )
     *  @param timeOut      - Timeout in .1 secs. See the termios documentation for deviations on this.
     */
    bool    ModbusConnectRTU( const std::string &serialport, int baud, char parity, int dataBits, int stopBits, int timeOut );

    /*!
     * ConnectionConfig Constructor. Used to create a new TCP connection.
     *
     * @param ip            - The ip address of the ModBus device we want to connect to.
     * @param portnum       - The portnumber the ModBus device is using
     * @param timeOut       - Timeout in which a modbus device should respond.
     */
    bool    ModbusConnectTCP( const std::string &ip, int port, int timeOut = -1 );

private:    // Members
    ConnectionType              connectionType  { ConnectionType::CT_UNKNOWN }; ///> The type of connection this instance provides. Needed for administration
    bool                        connected { false };                            ///> Shows if the connection is still active.
    modbus_t                   *modbus;                                         ///> The actual low-level modbus instance as a raw-pointer.
                                                                                ///  ( unique_pointer gives an error on this struct )

};