115 lines
4.8 KiB
C++
115 lines
4.8 KiB
C++
#ifndef MODBUS_TCP_CLIENT_H
|
|
#define MODBUS_TCP_CLIENT_H
|
|
|
|
#include <stdint.h>
|
|
#include <stdio.h>
|
|
#include <unistd.h>
|
|
#include <arpa/inet.h>
|
|
#include <sys/socket.h>
|
|
|
|
// Enum class for MODBUS function codes
|
|
enum class ModbusFunction : uint8_t {
|
|
READ_COIL = 0x01,
|
|
READ_DISCRETE_INPUT = 0x02,
|
|
READ_HOLDING_REGISTER = 0x03,
|
|
READ_INPUT_REGISTER = 0x04,
|
|
WRITE_SINGLE_COIL = 0x05,
|
|
WRITE_SINGLE_HOLDING_REGISTER = 0x06,
|
|
WRITE_MULTIPLE_COILS = 0x0F,
|
|
WRITE_MULTIPLE_HOLDING_REGISTERS = 0x10
|
|
};
|
|
|
|
enum class ModbusError {
|
|
NONE = 0, // No error
|
|
TIMEOUT, // No response from server
|
|
INVALID_RESPONSE, // Response does not match request
|
|
CONNECTION_LOST, // Connection issue
|
|
EXCEPTION_RESPONSE, // MODBUS Exception response (error code)
|
|
INVALID_REQUEST, // User tries doing something they shouldn't
|
|
};
|
|
|
|
|
|
class ModbusTCPClient {
|
|
public:
|
|
ModbusTCPClient(const char* ip, int port); // Extra constructor that does CANNOT use readAll() or writeAll()
|
|
ModbusTCPClient(const char* ip, int port, int numCoils, int numDI, int numIR, int numHR,
|
|
int startCoils = 0, int startDI = 0, int startIR = 0, int startHR = 0);
|
|
|
|
~ModbusTCPClient();
|
|
|
|
// Set the start address of each type. Either use this after creating the object or put them in the constructor
|
|
void setStartAddresses(int startCoils, int startDI, int startIR, int startHR);
|
|
|
|
bool connectServer();
|
|
void disconnectServer();
|
|
bool isConnected() const;
|
|
|
|
// Manually disconnectServer and return reconnectServer()
|
|
bool reconnectServer();
|
|
|
|
// Set the timeout for receiving responses
|
|
void setTimeout(int milliseconds);
|
|
|
|
// Setters (preferred to be used when calling writeAll())
|
|
void setCoil(int address, bool value);
|
|
void setHoldingRegister(int address, uint16_t value);
|
|
|
|
// Getters (preferred to be used when calling readAll())
|
|
bool getCoil(int address) const;
|
|
bool getDesiredCoil(int address) const; // Retrieves the "to be written" value
|
|
bool getDiscreteInput(int address) const;
|
|
uint16_t getHoldingRegister(int address) const;
|
|
uint16_t getDesiredHoldingRegister(int address) const; // Retrieves the "to be written" value
|
|
uint16_t getInputRegister(int address) const;
|
|
|
|
ModbusError readAll(); // Reads every coil, DI, IR, and HR
|
|
ModbusError writeAll(); // Writes every coil and HR
|
|
|
|
// Manual MODBUS TCP actions (not preferred to be called by user)
|
|
ModbusError readCoil(int address, bool &coilState);
|
|
ModbusError readMultipleCoils(int address, int count, bool coilStates[]);
|
|
|
|
ModbusError readDiscreteInput(int address, bool &discreteInput);
|
|
ModbusError readMultipleDiscreteInputs(int address, int count, bool discreteInputs[]);
|
|
|
|
ModbusError readHoldingRegister(int address, uint16_t &holdingRegister);
|
|
ModbusError readMultipleHoldingRegisters(int address, int count, uint16_t holdingRegisters[]);
|
|
|
|
ModbusError readInputRegister(int address, uint16_t &inputRegister);
|
|
ModbusError readMultipleInputRegisters(int address, int count, uint16_t inputRegisters[]);
|
|
|
|
ModbusError writeCoil(int address, bool value);
|
|
ModbusError writeMultipleCoils(int address, int count, const bool values[]);
|
|
|
|
ModbusError writeHoldingRegister(int address, uint16_t value);
|
|
ModbusError writeMultipleHoldingRegisters(int address, int count, const uint16_t values[]);
|
|
|
|
private:
|
|
// TCP settings
|
|
const char* serverIP;
|
|
int serverPort;
|
|
int socketFD;
|
|
uint16_t transactionID;
|
|
int timeoutMilliseconds = 2000; // Default 2 second timeout on receiving responses
|
|
|
|
// Storing MODBUS register information
|
|
int numCoils, numDiscreteInputs, numInputRegisters, numHoldingRegisters;
|
|
int startCoils, startDiscreteInputs, startInputRegisters, startHoldingRegisters; // The start address of each type of register
|
|
|
|
bool* coilsRead; // Stores the actual state of coils on the MODBUS server
|
|
bool* coilsWrite; // Stores the desired state of coils to be written
|
|
bool* discreteInputs; // Only read from the MODBUS server (no writes)
|
|
|
|
uint16_t* inputRegisters; // Only read from the MODBUS server
|
|
uint16_t* holdingRegistersRead; // Stores actual values from the MODBUS server
|
|
uint16_t* holdingRegistersWrite; // Stores desired values to write
|
|
|
|
bool sendRequest(uint8_t* request, int requestSize);
|
|
bool receiveResponse(uint8_t* response, int expectedSize);
|
|
|
|
void buildReadRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t startAddr, uint16_t quantity);
|
|
void buildWriteSingleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t value);
|
|
void buildWriteMultipleRequest(uint8_t* buffer, ModbusFunction functionCode, uint16_t address, uint16_t count, const void* values, uint8_t byteCount);
|
|
};
|
|
|
|
#endif // MODBUS_TCP_CLIENT_H
|