Name updated, Categories folder to ModbuPoints, less generic to be self documented
This commit is contained in:
86
lib/Core/ModbusPoints/Modbus_Coil.h
Normal file
86
lib/Core/ModbusPoints/Modbus_Coil.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @file Modbus_Coil.h
|
||||
* @brief Defines the Modbus_Coil class for handling Modbus coils.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-04
|
||||
*
|
||||
* This file contains the definition of the Modbus_Coil class, which is a specific
|
||||
* implementation of the Modbus_Point for handling coils (digital outputs).
|
||||
*/
|
||||
#ifndef Modbus_Coil_h
|
||||
#define Modbus_Coil_h
|
||||
#include "Modbus_Point.h"
|
||||
|
||||
/**
|
||||
* @class Modbus_Coil
|
||||
* @brief Represents a Modbus coil point.
|
||||
*
|
||||
* This class provides a concrete implementation for a Modbus coil,
|
||||
* which is a single bit digital output. It inherits from Modbus_Point
|
||||
* and implements its virtual functions for coil-specific operations.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_Coil : public Modbus_Point<T>{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the Modbus_Coil class.
|
||||
* @param server Pointer to the ModbusIP server instance.
|
||||
* @param address The Modbus address of the coil.
|
||||
* @param value The initial value of the coil.
|
||||
* @param description A description of the coil.
|
||||
*/
|
||||
Modbus_Coil(T* server, int address, int value, const char* description);
|
||||
|
||||
/**
|
||||
* @brief Adds the coil to the Modbus server.
|
||||
*/
|
||||
void addToModbusServer() override;
|
||||
|
||||
/**
|
||||
* @brief Sets the internal value of the coil.
|
||||
* @param value The new value for the coil.
|
||||
*/
|
||||
void setValue(int value) override;
|
||||
|
||||
/**
|
||||
* @brief Gets the current internal value of the coil.
|
||||
* @return The current value of the coil.
|
||||
*/
|
||||
int getValue() const override;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Modbus_Coil<T>::Modbus_Coil(T* server, int address, int value, const char* description)
|
||||
: Modbus_Point<T>(server, address, value, description) {}
|
||||
|
||||
/**
|
||||
* @brief Adds the coil to the Modbus server's register map.
|
||||
* This method uses the underlying Modbus library to register a new coil
|
||||
* at the specified address with its initial value.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Coil<T>::addToModbusServer(){
|
||||
this->_server->addCoil(this->_address, this->_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the coil on the Modbus server.
|
||||
* This method directly calls the Modbus library function to write the
|
||||
* new value to the coil's address.
|
||||
* @param value The new value for the coil.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Coil<T>::setValue(int value){
|
||||
this->_server->Coil(this->_address, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current value of the coil from the Modbus server.
|
||||
* @return The current value.
|
||||
*/
|
||||
template<typename T>
|
||||
int Modbus_Coil<T>::getValue() const{
|
||||
return this->_server->Coil(this->_address);
|
||||
}
|
||||
|
||||
#endif
|
||||
115
lib/Core/ModbusPoints/Modbus_FloatDecorator.h
Normal file
115
lib/Core/ModbusPoints/Modbus_FloatDecorator.h
Normal file
@@ -0,0 +1,115 @@
|
||||
/**
|
||||
* @file Modbus_FloatDecorator.h
|
||||
* @brief Defines the Modbus_FloatDecorator class for handling 32-bit float values.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-05
|
||||
*
|
||||
* This file contains the definition for a decorator that combines two 16-bit
|
||||
* Modbus registers to represent a single 32-bit floating-point value.
|
||||
*/
|
||||
#ifndef Modbus_FloatDecorator_h
|
||||
#define Modbus_FloatDecorator_h
|
||||
#include <stdint.h>
|
||||
#include "Modbus_PointDecorator.h"
|
||||
|
||||
/**
|
||||
* @union cracked_float_t
|
||||
* @brief A union to easily convert between a 32-bit float and two 16-bit integers.
|
||||
*
|
||||
* This union allows for type-punning between a `float` and an array of two
|
||||
* `int16_t` values. This simplifies splitting a float into high and low words
|
||||
* for Modbus transmission or reconstructing it from two registers.
|
||||
*/
|
||||
typedef union{
|
||||
float v; /**< @brief The value as a 32-bit float. */
|
||||
int16_t as_int[2]; /**< @brief The value as two 16-bit integers. */
|
||||
} cracked_float_t;
|
||||
|
||||
/**
|
||||
* @class Modbus_FloatDecorator
|
||||
* @brief A decorator that combines two 16-bit registers into a 32-bit float.
|
||||
*
|
||||
* This class wraps two consecutive Modbus_Point objects (a low-word and a
|
||||
* high-word point) and treats them as a single 32-bit float value. It
|
||||
* overrides the necessary methods to handle reading, writing, and value
|
||||
* conversion across both underlying registers.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_FloatDecorator : public Modbus_PointDecorator<T> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new Modbus_FloatDecorator object.
|
||||
* @param point A pointer to the Modbus_Point for the low-order word (LSW).
|
||||
* @param highOrderPoint A pointer to the Modbus_Point for the high-order word.
|
||||
*/
|
||||
Modbus_FloatDecorator(Modbus_Point<T>* point, Modbus_Point<T>* highOrderPoint)
|
||||
: Modbus_PointDecorator<T>(point), _highOrderPoint(highOrderPoint) {}
|
||||
|
||||
/**
|
||||
* @brief Returns the logical type of the point.
|
||||
* @return Always returns `PointType::FLOAT`.
|
||||
*/
|
||||
PointType getType() const override { return PointType::FLOAT; }
|
||||
|
||||
/**
|
||||
* @brief Sets the 32-bit float value by casting an integer.
|
||||
* This method is an override for the base class and calls `setFloatValue`.
|
||||
* @param value The integer value to set (will be cast to float).
|
||||
*/
|
||||
void setValue(int value) override {
|
||||
setFloatValue(static_cast<float>(value));
|
||||
}
|
||||
/**
|
||||
* @brief Sets the 32-bit float value by splitting it into two 16-bit words.
|
||||
*
|
||||
* This method uses a union to split the float into two 16-bit integers
|
||||
* and then writes these values to the two underlying Modbus points.
|
||||
*
|
||||
* @note The order of `as_int[0]` (LSW) and `as_int[1]` (MSW) might need to be
|
||||
* swapped depending on the endianness of the target Modbus device.
|
||||
* @param value The 32-bit float value to set.
|
||||
*/
|
||||
void setFloatValue(float value) {
|
||||
cracked_float_t buffer;
|
||||
buffer.v = value;
|
||||
this->_point->setValue(buffer.as_int[0]);
|
||||
_highOrderPoint->setValue(buffer.as_int[1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the 32-bit float value, cast to an integer.
|
||||
* @return The integer representation of the full float value.
|
||||
*/
|
||||
int getValue() const override {
|
||||
return static_cast<int>(getFloatValue());
|
||||
}
|
||||
/**
|
||||
* @brief Gets the combined 32-bit float value from the two registers.
|
||||
*
|
||||
* This method reads the 16-bit integer values from the two underlying
|
||||
* Modbus points and uses a union to reconstruct the 32-bit float value.
|
||||
*
|
||||
* @return The reconstructed 32-bit float value.
|
||||
*/
|
||||
float getFloatValue() const {
|
||||
cracked_float_t buffer;
|
||||
// Read the two 16-bit words from the underlying points and combine them.
|
||||
// Note: This assumes a specific word order (endianness).
|
||||
buffer.as_int[0] = this->_point->getValue();
|
||||
buffer.as_int[1] = _highOrderPoint->getValue();
|
||||
return buffer.v;
|
||||
}
|
||||
|
||||
// --- Housekeeping Methods ---
|
||||
|
||||
/** @brief Adds both underlying registers to the Modbus server. */
|
||||
void addToModbusServer() override {
|
||||
this->_point->addToModbusServer();
|
||||
_highOrderPoint->addToModbusServer();
|
||||
}
|
||||
|
||||
private:
|
||||
Modbus_Point<T>* _highOrderPoint; /**< @brief Pointer to the Modbus_Point for the high-order word. */
|
||||
};
|
||||
|
||||
#endif
|
||||
90
lib/Core/ModbusPoints/Modbus_Hreg.h
Normal file
90
lib/Core/ModbusPoints/Modbus_Hreg.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* @file Modbus_Hreg.h
|
||||
* @brief Defines the Modbus_Hreg class for handling Modbus holding registers.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-04
|
||||
*
|
||||
* This file contains the definition of the Modbus_Hreg class, which is a specific
|
||||
* implementation of the Modbus_Point for handling holding registers (16-bit).
|
||||
*/
|
||||
#ifndef Modbus_Hreg_h
|
||||
#define Modbus_Hreg_h
|
||||
|
||||
#include "Modbus_Point.h"
|
||||
|
||||
/**
|
||||
* @class Modbus_Hreg
|
||||
* @brief Represents a Modbus holding register point.
|
||||
*
|
||||
* This class provides a concrete implementation for a Modbus holding register,
|
||||
* which is a 16-bit read/write register. It inherits from Modbus_Point
|
||||
* and implements its virtual functions for holding register-specific operations.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_Hreg : public Modbus_Point<T>{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the Modbus_Hreg class.
|
||||
* @param server Pointer to the ModbusIP server instance.
|
||||
* @param address The Modbus address of the holding register.
|
||||
* @param value The initial value of the holding register.
|
||||
* @param description A description of the holding register.
|
||||
*/
|
||||
Modbus_Hreg(T* server, int address, int value, const char* description);
|
||||
|
||||
/**
|
||||
* @brief Adds the holding register to the Modbus server.
|
||||
*/
|
||||
void addToModbusServer() override;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the holding register on the Modbus server.
|
||||
* @param value The new value for the holding register.
|
||||
*/
|
||||
void setValue(int value) override;
|
||||
|
||||
/**
|
||||
* @brief Gets the current value of the holding register from the Modbus server.
|
||||
* @return The current value of the holding register.
|
||||
*/
|
||||
int getValue() const override;
|
||||
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Modbus_Hreg<T>::Modbus_Hreg(T* server, int address, int value, const char* description)
|
||||
: Modbus_Point<T>(server, address, value, description) {}
|
||||
|
||||
/**
|
||||
* @brief Adds the holding register to the Modbus server's register map.
|
||||
* This method uses the underlying Modbus library to register a new holding
|
||||
* register at the specified address with its initial value.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Hreg<T>::addToModbusServer() {
|
||||
this->_server->addHreg(this->_address, this->_value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the holding register on the Modbus server.
|
||||
* This method directly calls the Modbus library function to write the
|
||||
* new value to the holding register's address.
|
||||
* @param value The new 16-bit value for the register.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Hreg<T>::setValue(int value) {
|
||||
this->_server->Hreg(this->_address, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current value of the holding register from the Modbus server.
|
||||
* @return The current 16-bit value from the register.
|
||||
*/
|
||||
template<typename T>
|
||||
int Modbus_Hreg<T>::getValue() const {
|
||||
return this->_server->Hreg(this->_address);
|
||||
}
|
||||
#endif
|
||||
86
lib/Core/ModbusPoints/Modbus_Ireg.h
Normal file
86
lib/Core/ModbusPoints/Modbus_Ireg.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @file Modbus_Ireg.h
|
||||
* @brief Defines the Modbus_Ireg class for handling Modbus Input Registers.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-04
|
||||
*
|
||||
* This file contains the definition of the Modbus_Ireg class, which is a specific
|
||||
* implementation of the Modbus_Point for handling input registers (16-bit read-only).
|
||||
*/
|
||||
#ifndef Modbus_Ireg_h
|
||||
#define Modbus_Ireg_h
|
||||
|
||||
#include "Modbus_Point.h"
|
||||
|
||||
/**
|
||||
* @class Modbus_Ireg
|
||||
* @brief Represents a Modbus Input Register point.
|
||||
*
|
||||
* This class provides a concrete implementation for a Modbus input register,
|
||||
* which is a 16-bit read-only register. It inherits from Modbus_Point
|
||||
* and implements its virtual functions for input register-specific operations.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_Ireg : public Modbus_Point<T>{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the Modbus_Ireg class.
|
||||
* @param server Pointer to the ModbusIP server instance.
|
||||
* @param address The Modbus address of the input register.
|
||||
* @param value The initial value of the input register.
|
||||
* @param description A description of the input register.
|
||||
*/
|
||||
Modbus_Ireg(T* server, int address, int value, const char* description);
|
||||
|
||||
/**
|
||||
* @brief Adds the input register to the Modbus server.
|
||||
*/
|
||||
void addToModbusServer() override;
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the input register on the Modbus server.
|
||||
* @param value The new value for the input register.
|
||||
*/
|
||||
void setValue(int value) override;
|
||||
/**
|
||||
* @brief Gets the current value of the input register from the Modbus server.
|
||||
* @return The current value of the input register.
|
||||
*/
|
||||
int getValue() const override;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Modbus_Ireg<T>::Modbus_Ireg(T* server, int address, int value, const char* description)
|
||||
: Modbus_Point<T>(server, address, value, description){}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the input register on the Modbus server.
|
||||
* This method directly calls the Modbus library function to write the
|
||||
* new value to the input register's address. This is how the emulator's
|
||||
* internal logic updates the value that a Modbus master can read.
|
||||
* @param value The new 16-bit value for the register.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Ireg<T>::setValue(int value){
|
||||
this->_server->Ireg(this->_address, value);
|
||||
}
|
||||
/**
|
||||
* @brief Gets the current value of the input register from the Modbus server.
|
||||
* @return The current 16-bit value from the register.
|
||||
*/
|
||||
template<typename T>
|
||||
int Modbus_Ireg<T>::getValue() const {
|
||||
return this->_server->Ireg(this->_address);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds the input register to the Modbus server's register map.
|
||||
* This method uses the underlying Modbus library to register a new input
|
||||
* register at the specified address with its initial value.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Ireg<T>::addToModbusServer(){
|
||||
this->_server->addIreg(this->_address, this->_value);
|
||||
}
|
||||
|
||||
#endif
|
||||
86
lib/Core/ModbusPoints/Modbus_Ists.h
Normal file
86
lib/Core/ModbusPoints/Modbus_Ists.h
Normal file
@@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @file Modbus_Ists.h
|
||||
* @brief Defines the Modbus_Ists class for handling Modbus Input Status (Discrete Inputs).
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-04
|
||||
*
|
||||
* This file contains the definition of the Modbus_Ists class, which is a specific
|
||||
* implementation of the Modbus_Point for handling discrete inputs (read-only coils).
|
||||
*/
|
||||
#ifndef Modbus_Ists_h
|
||||
#define Modbus_Ists_h
|
||||
|
||||
#include "Modbus_Point.h"
|
||||
|
||||
/**
|
||||
* @class Modbus_Ists
|
||||
* @brief Represents a Modbus Input Status (Discrete Input) point.
|
||||
*
|
||||
* This class provides a concrete implementation for a Modbus discrete input,
|
||||
* which is a single bit read-only value. It inherits from Modbus_Point
|
||||
* and implements its virtual functions for discrete input-specific operations.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_Ists : public Modbus_Point<T>{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor for the Modbus_Ists class.
|
||||
* @param server Pointer to the ModbusIP server instance.
|
||||
* @param address The Modbus address of the discrete input.
|
||||
* @param value The initial value of the discrete input.
|
||||
* @param description A description of the discrete input.
|
||||
*/
|
||||
Modbus_Ists(T* server, int address, int value, const char* description);
|
||||
|
||||
/**
|
||||
* @brief Adds the discrete input to the Modbus server.
|
||||
*/
|
||||
void addToModbusServer() override;
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the discrete input on the Modbus server.
|
||||
* @param value The new value for the discrete input.
|
||||
*/
|
||||
void setValue(int value) override;
|
||||
/**
|
||||
* @brief Gets the current value of the discrete input from the Modbus server.
|
||||
* @return The current value of the discrete input.
|
||||
*/
|
||||
int getValue() const override;
|
||||
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Modbus_Ists<T>::Modbus_Ists(T* server, int address, int value, const char* description)
|
||||
: Modbus_Point<T>(server, address, value, description) {}
|
||||
|
||||
/**
|
||||
* @brief Sets the value of the discrete input on the Modbus server.
|
||||
* This method directly calls the Modbus library function to write the
|
||||
* new value to the discrete input's address. This is how the emulator's
|
||||
* internal logic updates the value that a Modbus master can read.
|
||||
* @param value The new value for the discrete input.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Ists<T>::setValue(int value){
|
||||
this->_server->Ists(this->_address, value);
|
||||
}
|
||||
/**
|
||||
* @brief Gets the current value of the discrete input from the Modbus server.
|
||||
* @return The current value.
|
||||
*/
|
||||
template<typename T>
|
||||
int Modbus_Ists<T>::getValue() const{
|
||||
return this->_server->Ists(this->_address);
|
||||
}
|
||||
/**
|
||||
* @brief Adds the discrete input to the Modbus server's register map.
|
||||
* This method uses the underlying Modbus library to register a new discrete
|
||||
* input at the specified address with its initial value.
|
||||
*/
|
||||
template<typename T>
|
||||
void Modbus_Ists<T>::addToModbusServer(){
|
||||
this->_server->addIsts(this->_address, this->_value);
|
||||
}
|
||||
|
||||
#endif
|
||||
97
lib/Core/ModbusPoints/Modbus_LongDecorator.h
Normal file
97
lib/Core/ModbusPoints/Modbus_LongDecorator.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
* @file Modbus_LongDecorator.h
|
||||
* @brief Defines the Modbus_LongDecorator class for handling 32-bit long values.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-05
|
||||
*
|
||||
* This file contains the definition for a decorator that combines two 16-bit
|
||||
* Modbus registers to represent a single 32-bit long integer value.
|
||||
*/
|
||||
#ifndef Modbus_LongDecorator_h
|
||||
#define Modbus_LongDecorator_h
|
||||
|
||||
#include "Modbus_PointDecorator.h"
|
||||
|
||||
/**
|
||||
* @class Modbus_LongDecorator
|
||||
* @brief A decorator that combines two 16-bit registers into a 32-bit long.
|
||||
*
|
||||
* This class wraps two consecutive Modbus_Point objects (a low-word and a
|
||||
* high-word point) and treats them as a single 32-bit long integer. It
|
||||
* overrides the necessary methods to handle reading, writing, and value
|
||||
* conversion across both underlying registers.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_LongDecorator : public Modbus_PointDecorator<T> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new Modbus_LongDecorator.
|
||||
* @param point A pointer to the Modbus_Point for the low-order word (LSW).
|
||||
* @param highOrderPoint A pointer to the Modbus_Point for the high-order word (MSW).
|
||||
*/
|
||||
Modbus_LongDecorator(Modbus_Point<T>* point, Modbus_Point<T>* highOrderPoint)
|
||||
: Modbus_PointDecorator<T>(point), _highOrderPoint(highOrderPoint) {}
|
||||
|
||||
/**
|
||||
* @brief Returns the logical type of the point.
|
||||
* @return Always returns `PointType::LONG`.
|
||||
*/
|
||||
PointType getType() const override { return PointType::LONG; }
|
||||
|
||||
// --- Housekeeping Methods ---
|
||||
|
||||
/** @brief Adds both underlying registers to the Modbus server. */
|
||||
void addToModbusServer() override {
|
||||
this->_point->addToModbusServer();
|
||||
_highOrderPoint->addToModbusServer();
|
||||
}
|
||||
|
||||
|
||||
|
||||
// --- Value Getters and Setters ---
|
||||
|
||||
/**
|
||||
* @brief Sets the 32-bit long value by splitting it into two 16-bit words.
|
||||
* This method is an override for the base class and calls `setLongValue`.
|
||||
* @param value The integer value to set (will be cast to long).
|
||||
*/
|
||||
void setValue(int value) override {
|
||||
setLongValue(static_cast<long>(value));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the 32-bit long value by splitting it into two 16-bit words.
|
||||
*
|
||||
* This method uses bitwise operations to extract the low word (Least
|
||||
* Significant Word) and the high word (Most Significant Word) from the
|
||||
* 32-bit long value. It then writes these 16-bit words to their
|
||||
* respective underlying Modbus points.
|
||||
*
|
||||
* @param value The 32-bit long value to set.
|
||||
*/
|
||||
void setLongValue(long value) {
|
||||
this->_point->setValue(value & 0xFFFF); // Low Word (LSW)
|
||||
_highOrderPoint->setValue((value >> 16) & 0xFFFF); // High Word (MSW)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the combined 32-bit long value from the two registers.
|
||||
* This method reads the 16-bit values from the two underlying Modbus points
|
||||
* and reconstructs the 32-bit long value using bitwise operations.
|
||||
* @return The reconstructed 32-bit long value.
|
||||
*/
|
||||
long getLongValue() const {
|
||||
long lsw = this->_point->getValue();
|
||||
long msw = _highOrderPoint->getValue();
|
||||
return (msw << 16) | lsw;
|
||||
}
|
||||
|
||||
/** @brief Gets the 32-bit long value, cast to an integer. */
|
||||
int getValue() const override {
|
||||
return static_cast<int>(getLongValue());
|
||||
}
|
||||
private:
|
||||
Modbus_Point<T>* _highOrderPoint; /**< @brief Pointer to the Modbus_Point for the high-order word. */
|
||||
};
|
||||
|
||||
#endif
|
||||
100
lib/Core/ModbusPoints/Modbus_Point.h
Normal file
100
lib/Core/ModbusPoints/Modbus_Point.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* @file Modbus_Point.h
|
||||
* @brief Defines the abstract base class for all Modbus points.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-04
|
||||
*
|
||||
* This file contains the definition of the abstract Modbus_Point class, which
|
||||
* serves as the base for all specific Modbus point types (Coils, Registers, etc.).
|
||||
* It defines the common interface for interacting with Modbus points.
|
||||
*/
|
||||
#ifndef Modbus_Point_h
|
||||
#define Modbus_Point_h
|
||||
#include <string.h>
|
||||
/**
|
||||
* @enum PointType
|
||||
* @brief Identifies the logical type of a Modbus point.
|
||||
*
|
||||
* This enum is used to distinguish between simple points and decorated points
|
||||
* that represent more complex data types like floats or longs.
|
||||
*/
|
||||
enum class PointType {
|
||||
GENERIC, /**< @brief A standard, non-decorated point. */
|
||||
FLOAT, /**< @brief A point decorated to handle 32-bit float values. */
|
||||
LONG, /**< @brief A point decorated to handle 32-bit long integer values. */
|
||||
SCALE /**< @brief A point decorated to apply a scaling factor (e.g., 10x). */
|
||||
};
|
||||
|
||||
/**
|
||||
* @class Modbus_Point
|
||||
* @brief Abstract base class representing a single point in the Modbus map.
|
||||
*
|
||||
* This class defines the common interface and data for all types of Modbus
|
||||
* points. Concrete implementations (e.g., Modbus_Coil, Modbus_Hreg) and decorators
|
||||
* must inherit from this class and implement its pure virtual functions.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_Point{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new Modbus_Point object.
|
||||
* @param server Pointer to the Modbus server instance (e.g., ModbusIP or ModbusRTU).
|
||||
* @param address The Modbus address of the point.
|
||||
* @param value The initial value of the point.
|
||||
* @param description A descriptive name for the point.
|
||||
*/
|
||||
Modbus_Point(T* server, int address, int value, const char* description);
|
||||
|
||||
// --- Getters ---
|
||||
/** @brief Gets a pointer to the Modbus server instance. */
|
||||
T* getServer() const { return _server; }
|
||||
/** @brief Gets the Modbus address of the point. */
|
||||
int getAddress() const { return _address; }
|
||||
/** @brief Gets the initial value assigned to the point at creation. */
|
||||
int getInitialValue() const { return _value; }
|
||||
/** @brief Gets the descriptive name of the point. */
|
||||
const char* getDescription() const { return _description; }
|
||||
|
||||
// --- Virtual Interface ---
|
||||
|
||||
/** @brief Returns the logical type of the point (e.g., FLOAT, LONG). */
|
||||
virtual PointType getType() const { return PointType::GENERIC; }
|
||||
/** @brief Pure virtual function to add the point to the Modbus server's register map. */
|
||||
virtual void addToModbusServer() = 0;
|
||||
|
||||
/** @brief Pure virtual function to set the point's value on the Modbus server. */
|
||||
virtual void setValue(int value) = 0;
|
||||
/** @brief Pure virtual function to get the point's value from the Modbus server. */
|
||||
virtual int getValue() const = 0;
|
||||
|
||||
// --- Dirty Flag ---
|
||||
|
||||
/**
|
||||
* @brief Checks if the point's value has changed since the last write.
|
||||
* @return True if the value is dirty, false otherwise.
|
||||
*/
|
||||
bool isDirty() const { return _dirty; }
|
||||
/**
|
||||
* @brief Sets the dirty flag for the point.
|
||||
* @param dirty The new state of the dirty flag.
|
||||
*/
|
||||
void setDirty(bool dirty) { _dirty = dirty; }
|
||||
|
||||
/** @brief Virtual destructor to ensure proper cleanup of derived classes. */
|
||||
virtual ~Modbus_Point() = default;
|
||||
|
||||
protected:
|
||||
T* _server; /**< @brief Pointer to the global Modbus server instance. */
|
||||
int _address; /**< @brief The Modbus address of this point. */
|
||||
int _value; /**< @brief The current internal value of this point. */
|
||||
char _description[35]; /**< @brief A descriptive name for this point. */
|
||||
bool _dirty = false; /**< @brief Flag to track if the value has changed and needs to be written. */
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
Modbus_Point<T>::Modbus_Point(T* server, int address, int value, const char* description)
|
||||
: _server(server), _address(address), _value(value) {
|
||||
strncpy(_description, description, sizeof(_description) - 1);
|
||||
_description[sizeof(_description) - 1] = '\0';
|
||||
}
|
||||
#endif
|
||||
82
lib/Core/ModbusPoints/Modbus_PointDecorator.h
Normal file
82
lib/Core/ModbusPoints/Modbus_PointDecorator.h
Normal file
@@ -0,0 +1,82 @@
|
||||
/**
|
||||
* @file Modbus_PointDecorator.h
|
||||
* @brief Defines the base decorator class for Modbus points.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-05
|
||||
*
|
||||
* This file contains the definition for Modbus_PointDecorator, which is the
|
||||
* abstract base class for all decorators in the Decorator design pattern.
|
||||
* It wraps a Modbus_Point and forwards all calls to it by default.
|
||||
*/
|
||||
#ifndef Modbus_PointDecorator_h
|
||||
#define Modbus_PointDecorator_h
|
||||
#include "Modbus_Point.h"
|
||||
|
||||
/**
|
||||
* @class Modbus_PointDecorator
|
||||
* @brief An abstract base class for decorating Modbus_Point objects.
|
||||
*
|
||||
* This class follows the Decorator pattern. It wraps a `Modbus_Point` object
|
||||
* and provides a default implementation for all virtual methods that simply
|
||||
* delegate the call to the wrapped object. Concrete decorators should inherit
|
||||
* from this class and override the specific methods they need to modify.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_PointDecorator : public Modbus_Point<T>{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new Modbus_PointDecorator object.
|
||||
*
|
||||
* Initializes the base Modbus_Point with the properties of the wrapped point
|
||||
* and stores a pointer to the wrapped point.
|
||||
*
|
||||
* @note The decorator does not take ownership of the wrapped point. The
|
||||
* caller is responsible for managing its lifecycle.
|
||||
*
|
||||
* @param point A pointer to the Modbus_Point object to be decorated.
|
||||
*/
|
||||
Modbus_PointDecorator(Modbus_Point<T>* point) : Modbus_Point<T>(
|
||||
point->getServer(),
|
||||
point->getAddress(),
|
||||
point->getInitialValue(),
|
||||
point->getDescription()),
|
||||
_point(point) {}
|
||||
|
||||
/**
|
||||
* @brief Virtual destructor.
|
||||
* Does not delete the wrapped `_point` as it does not own it.
|
||||
*/
|
||||
virtual ~Modbus_PointDecorator() = default;
|
||||
|
||||
// --- Delegated Methods ---
|
||||
// These methods simply forward the call to the wrapped _point object.
|
||||
// Concrete decorators can override them to add new behavior.
|
||||
|
||||
/**
|
||||
* @brief Delegates the call to add the point to the Modbus server.
|
||||
* Forwards the `addToModbusServer` call to the wrapped `Modbus_Point` object.
|
||||
*/
|
||||
void addToModbusServer() override{
|
||||
_point->addToModbusServer();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Delegates the call to set the point's value.
|
||||
* Forwards the `setValue` call to the wrapped `Modbus_Point` object.
|
||||
*/
|
||||
void setValue(int value) override {
|
||||
_point->setValue(value);
|
||||
}
|
||||
/**
|
||||
* @brief Delegates the call to get the point's value.
|
||||
* Forwards the `getValue` call to the wrapped `Modbus_Point` object.
|
||||
* @return The value from the wrapped point.
|
||||
*/
|
||||
int getValue() const override{
|
||||
return _point->getValue();
|
||||
}
|
||||
|
||||
protected:
|
||||
Modbus_Point<T>* _point; /**< @brief Pointer to the wrapped Modbus_Point object. */
|
||||
};
|
||||
#endif
|
||||
120
lib/Core/ModbusPoints/Modbus_PointFactory.h
Normal file
120
lib/Core/ModbusPoints/Modbus_PointFactory.h
Normal file
@@ -0,0 +1,120 @@
|
||||
/**
|
||||
* @file Modbus_PointFactory.h
|
||||
* @brief Defines the factory function for creating Modbus_Point objects.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-05
|
||||
*
|
||||
* This file provides the interface for a factory function that simplifies the
|
||||
* creation of various Modbus_Point types (e.g., Coils, Holding Registers) and
|
||||
* their decorators (e.g., for scaling, float, or long values).
|
||||
*/
|
||||
#ifndef Modbus_PointFactory_h
|
||||
#define Modbus_PointFactory_h
|
||||
#include "Modbus_Point.h"
|
||||
#include "Modbus_Coil.h"
|
||||
#include "Modbus_Ists.h"
|
||||
#include "Modbus_Ireg.h"
|
||||
#include "Modbus_Hreg.h"
|
||||
#include "Modbus_ScaleDecorator.h"
|
||||
#include "Modbus_LongDecorator.h"
|
||||
#include "Modbus_FloatDecorator.h"
|
||||
#include <Arduino.h>
|
||||
|
||||
|
||||
/**
|
||||
* @brief Creates and decorates a Modbus_Point object based on its type.
|
||||
*
|
||||
* This factory function acts as a centralized point for instantiating different
|
||||
* concrete Modbus_Point classes and applying decorators (e.g., for scaling,
|
||||
* floats, or longs). It encapsulates the logic for building both simple
|
||||
* single-register points and complex multi-register points.
|
||||
*
|
||||
* @tparam T The type of the Modbus server object (e.g., ModbusIP, ModbusRTU).
|
||||
* @param server Pointer to the Modbus server instance.
|
||||
* @param category An integer code representing the type of Modbus point to create
|
||||
* (e.g., COIL, HR, HR_FLOAT).
|
||||
* @param address The starting Modbus address for the point. For multi-register
|
||||
* types (float, long), this factory will also use `address + 1`.
|
||||
* @param value The initial value for the point. Note: This is ignored for
|
||||
* multi-register types, which are initialized to 0.
|
||||
* @param description A descriptive name for the point.
|
||||
* @return A pointer to the newly created Modbus_Point object.
|
||||
* @retval Modbus_Point* A pointer to the fully constructed (and possibly
|
||||
* decorated) Modbus point. The caller is responsible for
|
||||
* managing the memory of this object.
|
||||
* @retval nullptr If the category code is not recognized.
|
||||
*/
|
||||
template<typename T>
|
||||
Modbus_Point<T>* createModbus_Point(T* server, int category, int address, int value, const char* description);
|
||||
|
||||
/**
|
||||
* @brief Implementation of the Modbus_Point factory function.
|
||||
*
|
||||
* This function contains the switch-case logic to determine which concrete
|
||||
* Modbus_Point class to instantiate and which decorators to apply.
|
||||
*/
|
||||
template<typename T>
|
||||
Modbus_Point<T>* createModbus_Point(T* server, int category, int address, int value, const char* description) {
|
||||
switch (category) {
|
||||
case COIL:
|
||||
Serial.printf("Creating Coil: %s\n", description);
|
||||
return new Modbus_Coil<T>(server, address, value, description);
|
||||
|
||||
case DI:
|
||||
Serial.printf("Creating Digital Input: %s\n", description);
|
||||
return new Modbus_Ists<T>(server, address, value, description);
|
||||
|
||||
case IR:
|
||||
Serial.printf("Creating Input Register: %s\n", description);
|
||||
return new Modbus_Ireg<T>(server, address, value, description);
|
||||
|
||||
case IR_10X: {
|
||||
Serial.printf("Creating Scaled Input Register (10x): %s\n", description);
|
||||
Modbus_Point<T>* point = new Modbus_Ireg<T>(server, address, value, description);
|
||||
return new Modbus_ScaleDecorator<T>(point);
|
||||
}
|
||||
case IR_LONG: {
|
||||
Serial.printf("Creating Input Register Long: %s\n", description);
|
||||
// Create the low and high word registers for the 32-bit long
|
||||
Modbus_Point<T>* point = new Modbus_Ireg<T>(server, address, 0, description);
|
||||
Modbus_Point<T>* highOrderPoint = new Modbus_Ireg<T>(server, address + 1, 0, "");
|
||||
return new Modbus_LongDecorator<T>(point, highOrderPoint);
|
||||
}
|
||||
case IR_FLOAT: {
|
||||
Serial.printf("Creating Input Register Float: %s\n", description);
|
||||
// Create the low and high word registers for the 32-bit float
|
||||
Modbus_Point<T>* point = new Modbus_Ireg<T>(server, address, 0, description);
|
||||
Modbus_Point<T>* highOrderPoint = new Modbus_Ireg<T>(server, address + 1, 0, "");
|
||||
return new Modbus_FloatDecorator<T>(point, highOrderPoint);
|
||||
}
|
||||
case HR:
|
||||
Serial.printf("Creating Holding Register: %s\n", description);
|
||||
return new Modbus_Hreg<T>(server, address, value, description);
|
||||
|
||||
case HR_10x: {
|
||||
Serial.printf("Creating Scaled Holding Register (10x): %s\n", description);
|
||||
// Create a base holding register and wrap it with the scaling decorator
|
||||
Modbus_Point<T>* point = new Modbus_Hreg<T>(server, address, value, description);
|
||||
return new Modbus_ScaleDecorator<T>(point);
|
||||
}
|
||||
case HR_LONG: {
|
||||
Serial.printf("Creating Holding Register Long: %s\n", description);
|
||||
// Create the low and high word registers for the 32-bit long
|
||||
Modbus_Point<T>* point = new Modbus_Hreg<T>(server, address, 0, description);
|
||||
Modbus_Point<T>* highOrderPoint = new Modbus_Hreg<T>(server, address + 1 , 0, "");
|
||||
return new Modbus_LongDecorator<T>(point, highOrderPoint);
|
||||
}
|
||||
case HR_FLOAT: {
|
||||
Serial.printf("Creating Holding Register Float: %s\n", description);
|
||||
// Create the low and high word registers for the 32-bit float
|
||||
Modbus_Point<T>* point = new Modbus_Hreg<T>(server, address, 0, description);
|
||||
Modbus_Point<T>* highOrderPoint = new Modbus_Hreg<T>(server, address + 1 , 0, "");
|
||||
return new Modbus_FloatDecorator<T>(point, highOrderPoint);
|
||||
}
|
||||
default:
|
||||
Serial.printf("ERROR: Unknown Modbus category %d for '%s'\n", category, description);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
60
lib/Core/ModbusPoints/Modbus_ScaleDecorator.h
Normal file
60
lib/Core/ModbusPoints/Modbus_ScaleDecorator.h
Normal file
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* @file Modbus_ScaleDecorator.h
|
||||
* @brief Defines the Modbus_ScaleDecorator class for scaling Modbus point values.
|
||||
* @author Emmanuel Hernandez Cruz
|
||||
* @date 2025-09-05
|
||||
*
|
||||
* This file contains the definition for a decorator that applies a 10x scaling
|
||||
* factor to a Modbus point. This is useful for representing decimal values
|
||||
* in integer registers (e.g., storing 12.3 as 123).
|
||||
*/
|
||||
#ifndef Modbus_ScaleDecorator_h
|
||||
#define Modbus_ScaleDecorator_h
|
||||
|
||||
#include "Modbus_PointDecorator.h"
|
||||
|
||||
/**
|
||||
* @class Modbus_ScaleDecorator
|
||||
* @brief A decorator that multiplies/divides a Modbus point's value by 10.
|
||||
*
|
||||
* This class wraps a Modbus_Point and intercepts its `getValue` and `setValue`
|
||||
* calls to implement fixed-point arithmetic. It allows a 16-bit integer
|
||||
* register to represent a value with one decimal place (e.g., storing the
|
||||
* logical value 12.3 as the integer 123).
|
||||
*
|
||||
* - `setValue(123)` will store the integer `123` in the underlying point.
|
||||
* - `getValue()` will read `123` from the underlying point and return `12`.
|
||||
*/
|
||||
template<typename T>
|
||||
class Modbus_ScaleDecorator : public Modbus_PointDecorator<T> {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructs a new Modbus_ScaleDecorator.
|
||||
* @param point A pointer to the Modbus_Point object to be decorated.
|
||||
*/
|
||||
Modbus_ScaleDecorator<T>(Modbus_Point<T>* point) : Modbus_PointDecorator<T>(point) {}
|
||||
|
||||
/**
|
||||
* @brief Sets the raw integer value on the underlying point.
|
||||
* This method directly passes the provided integer value to the wrapped
|
||||
* Modbus point. It is intended to be used with values that are already
|
||||
* scaled (e.g., to set a logical value of 25.5, call `setValue(255)`).
|
||||
* @param value The scaled integer value to store (e.g., 123 to represent 12.3).
|
||||
*/
|
||||
void setValue(int value) override {
|
||||
this->_point->setValue(value * 10);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the integer part of the logical value.
|
||||
* This method retrieves the raw integer from the underlying point and
|
||||
* divides it by 10 to get the integer component of the logical value.
|
||||
* @return The integer part of the logical value (e.g., returns 12 if the
|
||||
* stored value is 123).
|
||||
*/
|
||||
int getValue() const override {
|
||||
return this->_point->getValue() / 10;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user