Commit f06536814dcb6c8ad686cb199a3070405069c161

Authored by Peter M. Groen
1 parent f8480708

Implmenting ModbusBase class

README.md
1 1 # modbus-cpp
2   -A TCP / RTU modbus library written in c++ as a header-only.
  2 +The goal was to write a TCP / RTU modbus library written in c++ as a header-only, but reality quickly followed suit.
  3 +To avoid large implementations in the header file and create a mess, I quickly decided to write it more conventional.
  4 +
  5 +
... ...
src/modbusbase.cpp
... ... @@ -7,4 +7,154 @@
7 7  
8 8 #include "modbusbase.h"
9 9  
  10 +int ModbusBase::readCoils(uint16_t address, uint16_t amount, bool *buffer)
  11 +{
  12 +
  13 +}
  14 +
  15 +int ModbusBase::readInputBits(uint16_t address, uint16_t amount, bool *buffer)
  16 +{
  17 +
  18 +}
  19 +
  20 +int ModbusBase::readHoldingRegisters(uint16_t address, uitn16_t amount, uint16_t *buffer)
  21 +{
  22 +
  23 +}
  24 +
  25 +int ModbusBase::readInputRegisters(uint16_t address, uint16_t amount, uint16_t *buffer)
  26 +{
  27 +
  28 +}
  29 +
  30 +int ModbusBase::writeCoil(uint16_t address, const bool &to_write)
  31 +{
  32 +
  33 +}
  34 +
  35 +int ModbusBase::writeRegister(uint16_t address, const uint16_t &value)
  36 +{
  37 +
  38 +}
  39 +
  40 +int ModbusBase::writeCoils(uint16_t address, uint16_t amount, const bool *value)
  41 +{
  42 +
  43 +}
  44 +
  45 +int ModbusBase::writeRegisters(uint16_t address, uint16_t amount, const uint16_t *value)
  46 +{
  47 +
  48 +}
  49 +
  50 +void ModbusBase::buildRequest(uint8_t *to_send, uint16_t address, int function_code) const
  51 +{
  52 + to_send[0] = (uint8_t)(m_msg_id >> 8u);
  53 + to_send[1] = (uint8_t)(m_msg_id & 0x00FFu);
  54 + to_send[2] = 0;
  55 + to_send[3] = 0;
  56 + to_send[4] = 0;
  57 + to_send[6] = (uint8_t)m_slaveId;
  58 + to_send[7] = (uint8_t)function_code;
  59 + to_send[8] = (uint8_t)(address >> 8u);
  60 + to_send[9] = (uint8_t)(address & 0x00FFu);
  61 +}
  62 +
  63 +int ModbusBase::modbusRead(uint16_t address, uint16_t amount, int function_code)
  64 +{
  65 + // TODO: Building the frames should be dependant on the chosen transport layer.. ( 256 for RTU, 260 for TCP )
  66 + // Declare as pure virtual and implement in the transport-specific class?
  67 + // For now we focus on TCP as it is easier to implement.
  68 + uint8_t to_send[12];
  69 + buildRequest(to_send, address, function_code);
  70 + to_send[5] = 6;
  71 + to_send[10] = (uint8_t)
  72 + }
  73 +}
  74 +
  75 +int ModbusBase::modbusWrite(uint16_t address, uint16_t amount, int function_code, const uint16_t *value)
  76 +{
  77 + // TODO: Building the frames should be dependant on the chosen transport layer.. ( 256 for RTU, 260 for TCP )
  78 + // Declare as pure virtual and implement in the transport-specific class?
  79 + // For now we focus on TCP as it is easier to implement.
  80 + int status = 0;
  81 + uint8_t *to_send;
  82 +
  83 + switch (function_code)
  84 + {
  85 + // Intentionally fall-through
  86 + case WRITE_COIL:
  87 + case WRITE_REG:
  88 + {
  89 + to_send = new uint8_t[12];
  90 + buildRequest(to_send, address, function_code);
  91 + to_send[5] = 6;
  92 + to_send[10] = (uint8_t)(value[0] >> 8u);
  93 + to_send[11] = (uint8_t)(value[0] & 0x00FFu);
  94 + status = modbusSend(to_send, 12);
  95 + break;
  96 + }
  97 + case WRITE_REGS:
  98 + {
  99 + to_send = new uint8_t[13 + 2 * amount];
  100 + buildRequest(to_send, address, function_code);
  101 + to_send[5] = (uint8_t)(7 + 2 * amount);
  102 + to_send[10] = (uint8_t)(amount >> 8u);
  103 + to_send[11] = (uint8_t)(amount & 0x00FFu);
  104 + to_send[12] = (uint8_t)(2 * amount);
  105 + for (int i = 0; i < amount; i++)
  106 + {
  107 + to_send[13 + 2 * i] = (uint8_t)(value[i] >> 8u);
  108 + to_send[14 + 2 * i] = (uint8_t)(value[i] & 0x00FFu);
  109 + }
  110 + status = modbusSend(to_send, 13 + 2 * amount);
  111 + break;
  112 + }
  113 + case WRITE_COILS:
  114 + {
  115 + to_send = new uint8_t[14 + ( amount - 1 ) / 8];
  116 + buildRequest(to_send, address, function_code);
  117 + to_send[5] = (uint8_t)(7 + ( amount + 7 ) / 8);
  118 + to_send[10] = (uint8_t)(amount >> 8u);
  119 + to_send[11] = (uint8_t)(amount & 0x00FFu);
  120 + to_send[12] = (uint8_t)((amount + 7) / 8);
  121 + for (int i = 0; i < (amount + 7) / 8; i++)
  122 + {
  123 + to_send[13 + i] = 0 // Init needed before summing.
  124 + }
  125 + for (int i = 0; i < amount; i++)
  126 + {
  127 + to_send[13 + i / 8] += (uint8_t)(value[i] << (i % 8u));
  128 + }
  129 + status = modbusSend(to_send, 13 + (amount - 1) / 8);
  130 + }
  131 + }
  132 + delete[] to_send;
  133 + return status;
  134 +}
  135 +
  136 +ssize_t ModbusBase::modbusSend(uint8_t *to_send, size_t length)
  137 +{
  138 +
  139 +}
  140 +
  141 +ssize_t ModbusBase::modbusReceive(uint8_t *buffer) const
  142 +{
  143 +
  144 +}
  145 +
  146 +void ModbusBase::modbusErrorHandle(const uint8_t *msg, int function_code)
  147 +{
  148 +
  149 +}
  150 +
  151 +void ModbusBase::setBadConnection()
  152 +{
  153 +
  154 +}
  155 +
  156 +void ModbusBase::setBadInput()
  157 +{
  158 +
  159 +}
10 160  
... ...
src/modbusbase.h
... ... @@ -55,7 +55,11 @@ public:
55 55 ModbusBase();
56 56 virtual ~ModbusBase();
57 57  
58   - void setSlaveId(int slave_id);
  58 + /*!
  59 + * Set slave id for this context
  60 + * \param slave_id - The slave id this system is known under.
  61 + */
  62 + void setSlaveId(int slave_id) { m_slaveId = slave_id; }
59 63  
60 64 // Pure virtuals. Override when inherited.
61 65 virtual bool Connect() const = 0;
... ... @@ -74,11 +78,26 @@ public:
74 78 int writeRegisters(uint16_t address, uint16_t amount, const uint16_t *value);
75 79  
76 80 private: // Methods
  81 + /*!
  82 + * Modbus Request Builder
  83 + * \param to_send - Message buffer to be send
  84 + * \param address - Reference Address
  85 + * \param function_code - Modbus Functional Code
  86 + */
77 87 void buildRequest(uint8_t *to_send, uint16_t address, int function_code) const;
78 88 int modbusRead(uint16_t address, uint16_t amount, int function_code);
  89 + /*!
  90 + * Write Request Builder and Sender
  91 + * \param address - Reference address
  92 + * \param amount - Amount of data to be written
  93 + * \param function_code - Modbus Functional Code
  94 + * \param value - Data to be written
  95 + *
  96 + * \return int
  97 + */
79 98 int modbusWrite(uint16_t address, uint16_t amount, int function_code, const uint16_t *value);
80   - ssize_t modbusSend(uint8_t *to_send, size_t length);
81   - ssize_t modbusReceive(uint8_t *buffer) const;
  99 + virtual ssize_t modbusSend(uint8_t *to_send, size_t length) = 0;
  100 + virtual ssize_t modbusReceive(uint8_t *buffer) const = 0;
82 101  
83 102 void modbusErrorHandle(const uint8_t *msg, int function_code);
84 103 void setBadConnection();
... ...