First commit

This commit is contained in:
marcel
2023-12-29 13:49:44 +01:00
commit 7d38f2cb37
261 changed files with 38553 additions and 0 deletions

View File

@@ -0,0 +1,616 @@
/*
Modbus.cpp - Source for Modbus Base Library
Copyright (C) 2014 André Sarmento Barbosa
Copyright (C) 2023 Pascal JEAN aka epsilonrt
*/
#include "Modbus.h"
//-------------------------------------------------------------------------------
Modbus::Modbus() :
_regs_head (0),
_regs_last (0),
_additional_data (0),
_frame (nullptr),
_len (0),
_reply (0),
_debug (nullptr) {
}
//-------------------------------------------------------------------------------
// private
TRegister *Modbus::searchRegister (word address) {
TRegister *reg = _regs_head;
//if there is no register configured, bail
if (reg == 0) {
return (0);
}
//scan through the linked list until the end of the list or the register is found.
//return the pointer.
do {
if (reg->address == address) {
return (reg);
}
reg = reg->next;
}
while (reg);
return (0);
}
//-------------------------------------------------------------------------------
// private
void Modbus::addReg (word address, word value) {
TRegister *newreg;
newreg = (TRegister *) malloc (sizeof (TRegister));
newreg->address = address;
newreg->value = value;
newreg->edata = 0;
newreg->next = 0;
if (_regs_head == 0) {
_regs_head = newreg;
_regs_last = _regs_head;
}
else {
//Assign the last register's next pointer to newreg.
_regs_last->next = newreg;
//then make temp the last register in the list.
_regs_last = newreg;
}
}
//-------------------------------------------------------------------------------
// private
bool Modbus::setReg (word address, word value) {
TRegister *reg;
//search for the register address
reg = searchRegister (address);
//if found then assign the register value to the new value.
if (reg) {
reg->value = value;
return true;
}
else {
return false;
}
}
//-------------------------------------------------------------------------------
// private
word Modbus::reg (word address) {
TRegister *reg;
reg = searchRegister (address);
if (reg) {
return (reg->value);
}
else {
return (0);
}
}
//-------------------------------------------------------------------------------
// private
bool Modbus::setRegBounds (word address, word min, word max) {
TRegister *reg;
reg = searchRegister (address);
if (reg) {
if (!reg->edata) {
reg->edata = new TExtData;
}
if (reg->edata) {
reg->edata->min = min;
reg->edata->max = max;
return true;
}
}
return false;
}
//-------------------------------------------------------------------------------
// private
bool Modbus::regOutOfBounds (word address, word value) {
TRegister *reg;
reg = searchRegister (address);
if (reg) {
if (reg->edata) {
return (value < reg->edata->min) || (value > reg->edata->max);
}
}
return false;
}
//-------------------------------------------------------------------------------
// protected
void Modbus::receivePDU (byte *frame) {
byte fcode = frame[0];
word field1 = (word) frame[1] << 8 | (word) frame[2];
word field2 = (word) frame[3] << 8 | (word) frame[4];
switch (fcode) {
case MB_FC_WRITE_REG:
//field1 = reg, field2 = value
writeSingleRegister (field1, field2);
break;
case MB_FC_WRITE_REGS:
//field1 = startreg, field2 = status
writeMultipleRegisters (frame, field1, field2, frame[5]);
break;
case MB_FC_READ_REGS:
//field1 = startreg, field2 = numregs
readRegisters (fcode, field1, field2);
break;
#ifndef USE_HOLDING_REGISTERS_ONLY
case MB_FC_READ_INPUT_REGS:
//field1 = startreg, field2 = numregs
readRegisters (fcode, field1, field2);
break;
case MB_FC_READ_INPUT_STAT:
case MB_FC_READ_COILS:
//field1 = startreg, field2 = numregs
readBits (fcode, field1, field2);
break;
case MB_FC_WRITE_COIL:
//field1 = reg, field2 = status
writeSingleCoil (field1, field2);
break;
case MB_FC_WRITE_COILS:
//field1 = startreg, field2 = numoutputs
writeMultipleCoils (frame, field1, field2, frame[5]);
break;
case MB_FC_REPORT_SERVER_ID:
reportServerId();
break;
#endif
default:
exceptionResponse (fcode, MB_EX_ILLEGAL_FUNCTION);
}
}
//-------------------------------------------------------------------------------
// private
void Modbus::exceptionResponse (const byte fcode, const byte excode) {
_len = 2;
_frame = (byte *) realloc (_frame, _len);
_frame[0] = fcode + 0x80;
_frame[1] = excode;
_reply = MB_REPLY_NORMAL;
}
/* Func 06: Write Single Register
Request
Function code 1 Byte 0x06
Register Address 2 Bytes 0x0000 to 0xFFFF
Register Value 2 Bytes 0x0000 to 0xFFFF
Response
Function code 1 Byte 0x06
Register Address 2 Bytes 0x0000 to 0xFFFF
Register Value 2 Bytes 0x0000 to 0xFFFF
*/
//-------------------------------------------------------------------------------
// private
void Modbus::writeSingleRegister (const word reg, const word value) {
if (hregOutOfBounds (reg, value)) {
exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_VALUE);
return;
}
//Check Address and execute (reg exists?)
if (!setHreg (reg, value)) {
exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_ADDRESS);
return;
}
//Check for failure ? Why ???
/*
if (hreg (reg) != value) {
exceptionResponse (MB_FC_WRITE_REG, MB_EX_SLAVE_FAILURE);
return;
}
*/
_reply = MB_REPLY_ECHO; // reply with received frame
}
/* Func 16: Write Multiple registers
Request
Function code 1 Byte 0x10
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Registers 2 Bytes 0x0001 to 0x007B
Byte Count 1 Byte 2 x N*
Registers Value N* x 2 Bytes value
N = Quantity of Registers
Response
Function code 1 Byte 0x10
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Registers 2 Bytes 1 to 123 (0x7B)
*/
//-------------------------------------------------------------------------------
// private
void Modbus::writeMultipleRegisters (const byte *frame, const word startreg, const word numoutputs, const byte bytecount) {
//Check value
if (numoutputs < 1 || numoutputs > 123 || bytecount != 2 * numoutputs) {
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_VALUE);
return;
}
//Check Address (startreg...startreg + numregs - 1)
for (word k = 0; k < numoutputs; k++) {
if (!searchRegister (startreg + TRegister::HregOffset + k)) {
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
return;
}
}
for (word i = 0; i < numoutputs; i++) {
word val = (word) frame[6 + i * 2] << 8 | (word) frame[7 + i * 2];
if (hregOutOfBounds (startreg + i, val)) {
exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_VALUE);
return;
}
setHreg (startreg + i, val);
}
//Clean frame buffer
free (_frame);
_len = 5;
_frame = (byte *) malloc (_len);
if (!_frame) {
exceptionResponse (MB_FC_WRITE_REGS, MB_EX_SLAVE_FAILURE);
return;
}
_frame[0] = MB_FC_WRITE_REGS;
_frame[1] = startreg >> 8;
_frame[2] = startreg & 0x00FF;
_frame[3] = numoutputs >> 8;
_frame[4] = numoutputs & 0x00FF;
_reply = MB_REPLY_NORMAL;
}
/*
Func 03: Read Holding Registers
Request
Function code 1 Byte 0x03
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Registers 2 Bytes 1 to 125 (0x7D)
Response
Function code 1 Byte 0x03
Byte count 1 Byte 2 x N*
Register value N* x 2 Bytes
N = Quantity of Registers
Func 04: Read Input Registers
Request
Function code 1 Byte 0x04
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Input Registers 2 Bytes 0x0001 to 0x007D
Response
Function code 1 Byte 0x04
Byte count 1 Byte 2 x N*
Input Registers N* x 2 Bytes
N = Quantity of Input Registers
*/
//-------------------------------------------------------------------------------
// private
void Modbus::readRegisters (const byte fcode, const word startreg, const word numregs) {
// Check value (numregs)
if (numregs < 1 || numregs > 0x7D) {
exceptionResponse (fcode, MB_EX_ILLEGAL_VALUE);
return;
}
// calculate the query reply message length
// for each register queried add 2 bytes
_len = 2 + numregs * 2;
_frame = (byte *) realloc (_frame, _len);
if (!_frame) {
exceptionResponse (fcode, MB_EX_SLAVE_FAILURE);
return;
}
_frame[0] = fcode;
_frame[1] = _len - 2; //byte count
const word offset = (fcode == MB_FC_READ_REGS) ? TRegister::HregOffset : TRegister::IregOffset;
for (word i = 0; i < numregs; i++) {
const word address = startreg + offset + i;
if (searchRegister (address)) {
// retrieve the value from the register bank for the current register
word val = reg (address);
// write the high byte of the register value
_frame[2 + i * 2] = val >> 8;
// write the low byte of the register value
_frame[3 + i * 2] = val & 0xFF;
}
else {
exceptionResponse (fcode, MB_EX_ILLEGAL_ADDRESS);
return;
}
}
_reply = MB_REPLY_NORMAL;
}
//-------------------------------------------------------------------------------
// protected
void Modbus::debugMessage (bool reply) {
if (_len && isDebug()) {
char str[3]; // buffer for sprintf
for (uint8_t i = 0; i < _len; i++) {
sprintf (str, "%02X", _frame[i]); // str stores the string representation of the byte, in hex form
_debug->write (!reply ? '[' : '<');
_debug->print (str);
_debug->write (!reply ? ']' : '>');
}
_debug->println ("");
}
}
#ifndef USE_HOLDING_REGISTERS_ONLY
//-------------------------------------------------------------------------------
/* Func 01: Read Coils
Request
Function code 1 Byte 0x01
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of coils 2 Bytes 1 to 2000 (0x7D0)
Response
Function code 1 Byte 0x01
Byte count 1 Byte N*
Coil Status n Byte n = N or N+1
N = Quantity of Outputs / 8, if the remainder is different of 0 -> N = N+1
Func 02: Read Discrete Inputs
Request
Function code 1 Byte 0x02
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Inputs 2 Bytes 1 to 2000 (0x7D0)
Response
Function code 1 Byte 0x02
Byte count 1 Byte N*
Input Status N* x 1 Byte
N = Quantity of Inputs / 8, if the remainder is different of 0 -> N = N+1
*/
//-------------------------------------------------------------------------------
// private
void Modbus::readBits (const byte fcode, const word startreg, const word numregs) {
//Check value (numregs)
if (numregs < 0x0001 || numregs > 0x07D0) {
exceptionResponse (fcode, MB_EX_ILLEGAL_VALUE);
return;
}
// Determine the message length = function type, byte count and
// for each group of 8 registers the message length increases by 1
_len = 2 + numregs / 8;
if (numregs % 8) {
_len++; // Add 1 to the message length for the partial byte.
}
_frame = (byte *) realloc (_frame, _len);
if (!_frame) {
exceptionResponse (fcode, MB_EX_SLAVE_FAILURE);
return;
}
_frame[0] = fcode;
_frame[1] = _len - 2; // byte count (_len - function code and byte count)
const word offset = (fcode == MB_FC_READ_COILS) ? TRegister::CoilOffset : TRegister::IstsOffset;
for (word i = 0; i < numregs; i++) {
const word address = startreg + offset + i;
if (searchRegister (address)) {
word byteIndex = (i / 8) + 2;
byte bitIndex = i % 8;
if (reg (address) == 0xFF00) {
bitSet (_frame[byteIndex], bitIndex);
}
else {
bitClear (_frame[byteIndex], bitIndex);
}
}
else {
exceptionResponse (fcode, MB_EX_ILLEGAL_ADDRESS);
return;
}
}
_reply = MB_REPLY_NORMAL;
}
/* Func 05: Write Single Coil
Request
Function code 1 Byte 0x05
Output Address 2 Bytes 0x0000 to 0xFFFF
Output Value 2 Bytes 0x0000 or 0xFF00
Response
Function code 1 Byte 0x05
Output Address 2 Bytes 0x0000 to 0xFFFF
Output Value 2 Bytes 0x0000 or 0xFF00
*/
//-------------------------------------------------------------------------------
// private
void Modbus::writeSingleCoil (const word reg, const word status) {
//Check value (status)
if (status != 0xFF00 && status != 0x0000) {
exceptionResponse (MB_FC_WRITE_COIL, MB_EX_ILLEGAL_VALUE);
return;
}
//Check Address and execute (reg exists?)
if (!setCoil (reg, status != 0)) {
exceptionResponse (MB_FC_WRITE_COIL, MB_EX_ILLEGAL_ADDRESS);
return;
}
//Check for failure ?? Why ?
/*
if (coil (reg) != (bool) status) {
exceptionResponse (MB_FC_WRITE_COIL, MB_EX_SLAVE_FAILURE);
return;
}
*/
_reply = MB_REPLY_ECHO; // reply with received frame
}
/* Func 15: Write Multiple Coils
Request
Function code 1 Byte 0x0F
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Outputs 2 Bytes 0x0001 to 0x07B0
Byte Count 1 Byte N* (Quantity of Outputs / 8, if the remainder is different of 0 -> N = N+1)
Outputs Value N* x 1 Byte
Response
Function code 1 Byte 0x0F
Starting Address 2 Bytes 0x0000 to 0xFFFF
Quantity of Outputs 2 Bytes 0x0001 to 0x07B0
*/
//-------------------------------------------------------------------------------
// private
void Modbus::writeMultipleCoils (const byte *frame, const word startreg, const word numoutputs, const byte bytecount) {
// Check value
word bytecount_calc = numoutputs / 8;
if (numoutputs % 8) {
bytecount_calc++;
}
if (numoutputs < 0x0001 || numoutputs > 0x07B0 || bytecount != bytecount_calc) {
exceptionResponse (MB_FC_WRITE_COILS, MB_EX_ILLEGAL_VALUE);
return;
}
for (word i = 0; i < numoutputs; i++) {
const word address = startreg + i;
if (searchRegister (address + TRegister::CoilOffset)) {
word byteIndex = (i / 8) + 6;
byte bitIndex = i % 8;
setCoil (address, bitRead (frame[byteIndex], bitIndex));
}
else {
exceptionResponse (MB_FC_WRITE_COILS, MB_EX_ILLEGAL_ADDRESS);
return;
}
}
_len = 5;
_frame = (byte *) realloc (_frame, _len);
if (!_frame) {
exceptionResponse (MB_FC_WRITE_COILS, MB_EX_SLAVE_FAILURE);
return;
}
_frame[0] = MB_FC_WRITE_COILS;
_frame[1] = startreg >> 8;
_frame[2] = startreg & 0x00FF;
_frame[3] = numoutputs >> 8;
_frame[4] = numoutputs & 0x00FF;
_reply = MB_REPLY_NORMAL;
}
/*
Func 17: Report Server ID
Request
Function code 1 Byte 0x11
Response
Function code 1 Byte 0x11
Byte Count 1 Byte
Server ID device specific
Run Indicator Status 1 Byte 0x00 = OFF, 0xFF = ON
Additional Data
*/
//-------------------------------------------------------------------------------
// private
void Modbus::reportServerId() {
_len = 4;
if (_additional_data) {
_len += strlen (_additional_data);
}
_frame = (byte *) realloc (_frame, _len);
if (!_frame) {
exceptionResponse (MB_FC_REPORT_SERVER_ID, MB_EX_SLAVE_FAILURE);
return;
}
_frame[0] = MB_FC_REPORT_SERVER_ID;
_frame[1] = _len - 2; //byte count
_frame[2] = 0x00; // Server ID
_frame[3] = 0xFF; // Run Indicator Status
if (_additional_data) { // Additional Data
strcpy ( (char *) &_frame[4], _additional_data);
}
_reply = MB_REPLY_NORMAL;
}
//-------------------------------------------------------------------------------
int Modbus::setAdditionalServerData (const char data[]) {
free (_additional_data);
if (data) {
size_t l = strlen (data) + 1;
_additional_data = (char *) malloc (l);
if (_additional_data) {
strcpy (_additional_data, data);
return l;
}
}
return 0;
}
//-------------------------------------------------------------------------------
#endif // USE_HOLDING_REGISTERS_ONLY not defined

View File

@@ -0,0 +1,357 @@
/*
Modbus.h - Header for Modbus Base Library
Copyright (C) 2014 André Sarmento Barbosa
Copyright (C) 2023 Pascal JEAN aka epsilonrt
*/
#include "Arduino.h"
#pragma once
#define MAX_REGS 32 // Unused !
#define MAX_FRAME 128 // Unused !
//#define USE_HOLDING_REGISTERS_ONLY
// Function Codes
enum {
MB_FC_READ_COILS = 0x01, ///< Read Coils (Output) Status 0xxxx
MB_FC_READ_INPUT_STAT = 0x02, ///< Read Input Status (Discrete Inputs) 1xxxx
MB_FC_READ_REGS = 0x03, ///< Read Holding Registers 4xxxx
MB_FC_READ_INPUT_REGS = 0x04, ///< Read Input Registers 3xxxx
MB_FC_WRITE_COIL = 0x05, ///< Write Single Coil (Output) 0xxxx
MB_FC_WRITE_REG = 0x06, ///< Preset Single Register 4xxxx
MB_FC_WRITE_COILS = 0x0F, ///< Write Multiple Coils (Outputs) 0xxxx
MB_FC_WRITE_REGS = 0x10, ///< Write block of contiguous registers 4xxxx
MB_FC_REPORT_SERVER_ID = 0x11, ///< Report Server ID
};
// Exception Codes
enum {
MB_EX_ILLEGAL_FUNCTION = 0x01, ///< Function Code not Supported
MB_EX_ILLEGAL_ADDRESS = 0x02, ///< Address not in Range
MB_EX_ILLEGAL_VALUE = 0x03, ///< Data Value not in Range
MB_EX_SLAVE_FAILURE = 0x04, ///< Slave Deive Fails to process request
};
// Reply Types
enum {
MB_REPLY_OFF = 0x01, ///< No reply
MB_REPLY_ECHO = 0x02, ///< Return the message from the bus master as an reply
MB_REPLY_NORMAL = 0x03, ///< Reply with adding slave data
};
#ifndef __DOXYGEN__
struct TExtData {
word min;
word max;
};
struct TRegister {
word address;
word value;
TExtData *edata;
TRegister *next;
enum {
CoilOffset = 1,
IstsOffset = 10001,
IregOffset = 30001,
HregOffset = 40001
};
};
#endif
/**
@class Modbus
@brief Modbus base class
*/
class Modbus {
#ifndef __DOXYGEN__
private:
TRegister *_regs_head;
TRegister *_regs_last;
char *_additional_data;
void readRegisters (const byte fcode, const word startreg, const word numregs);
void writeSingleRegister (const word reg, const word value);
void writeMultipleRegisters (const byte *frame, const word startreg, const word numoutputs, const byte bytecount);
void exceptionResponse (const byte fcode, const byte excode);
#ifndef USE_HOLDING_REGISTERS_ONLY
void readBits (const byte fcode, const word startreg, const word numregs);
void writeSingleCoil (const word reg, const word status);
void writeMultipleCoils (const byte *frame, const word startreg, const word numoutputs, const byte bytecount);
#endif
TRegister *searchRegister (word addr);
void addReg (word address, word value = 0);
bool setReg (word address, word value);
word reg (word address);
bool setRegBounds (word address, word min, word max);
bool regOutOfBounds (word address, word value);
// @deprecated
inline bool Reg (word address, word value) {
return setReg (address, value);
}
// @deprecated
inline word Reg (word address) {
return reg (address);
}
protected:
byte *_frame;
byte _len;
byte _reply;
Print *_debug;
void receivePDU (byte *frame);
void reportServerId();
void debugMessage (bool reply = false);
#endif
public:
/**
@brief Default constructor
*/
Modbus();
/**
@brief Add a holding register to the list
@param offset register offset (PDU addressing: 0-9999)
@param value default value
*/
inline void addHreg (word offset, word value = 0) {
this->addReg (offset + TRegister::HregOffset, value);
}
/**
@brief Change the value of a holding register
This value will be returned when bus read, the master can also modify it.
@param offset register offset (PDU addressing: 0-9999)
@param value new value
@return true, false if register not found.
*/
inline bool setHreg (word offset, word value) {
return setReg (offset + TRegister::HregOffset, value);
}
/**
@brief Return the value of a holding register
@param offset register offset (PDU addressing: 0-9999)
@return register value
*/
inline word hreg (word offset) {
return reg (offset + TRegister::HregOffset);
}
/**
@brief Sets the bounds of a holding register
@param offset register offset (PDU addressing: 0-9999)
@param min min value
@param max max value
@return true, false if register not found.
*/
inline bool setHregBounds (word offset, word min, word max) {
return setRegBounds (offset + TRegister::HregOffset, min, max);
}
/**
@brief Checks if the value is outside the bounds of a holging register
@param offset register offset (PDU addressing: 0-9999)
@param value value to check
@return true if the value is outside the bounds, false otherwise
*/
inline bool hregOutOfBounds (word offset, word value) {
return regOutOfBounds (offset + TRegister::HregOffset, value);
}
;
/**
@brief Change the value of a holding register
This value will be returned when bus read, the master can also modify it.
@deprecated removed in next major release, use setHreg() instead.
@param offset register offset (PDU addressing: 0-9999)
@param value new value
@return true, false if register not found.
*/
inline bool Hreg (word offset, word value) {
return setHreg (offset, value);
}
/**
@brief Return the value of a holding register
@deprecated removed in next major release, use hreg() instead.
@param offset register offset (PDU addressing: 0-9999)
@return register value
*/
inline word Hreg (word offset) {
return hreg (offset);
}
/**
@brief Enable debug mode
*/
inline void setDebug (Print &print) {
_debug = &print;
_debug->println ("Modbus: debug enabled....");
}
/**
@brief Returns true if debug mode is enabled
*/
inline bool isDebug () {
return _debug != nullptr;
}
/**
@brief Print a debug message, only if debug mode is enabled
@param msg message to print
*/
inline void debug (const char *msg) {
if (_debug) {
_debug->println (msg);
}
}
#ifndef USE_HOLDING_REGISTERS_ONLY
/**
@brief Add a coil
@param offset coil offset (PDU addressing: 0-9999)
@param value default value
*/
void addCoil (word offset, bool value = false) {
this->addReg (offset + TRegister::CoilOffset, value ? 0xFF00 : 0x0000);
}
/**
@brief Add a discrete input
@param offset input offset (PDU addressing: 0-9999)
@param value default value
*/
inline void addIsts (word offset, bool value = false) {
this->addReg (offset + TRegister::IstsOffset, value ? 0xFF00 : 0x0000);
}
/**
@brief Add a input register
@param offset register offset (PDU addressing: 0-9999)
@param value default value
*/
inline void addIreg (word offset, word value = 0) {
this->addReg (offset + TRegister::IregOffset, value);
}
/**
@brief Change the value of a coil
This value will be returned when bus read, the master can also modify it.
@param offset register offset (PDU addressing: 0-9999)
@param value new value
@return true, false if coil not found.
*/
inline bool setCoil (word offset, bool value) {
return setReg (offset + TRegister::CoilOffset, value ? 0xFF00 : 0x0000);
}
/**
@brief Change the value of a discrete input
This value will be returned when bus read,.
@param offset input offset (PDU addressing: 0-9999)
@param value new value
@return true, false if input not found.
*/
inline bool setIsts (word offset, bool value) {
return setReg (offset + TRegister::IstsOffset, value ? 0xFF00 : 0x0000);
}
/**
@brief Change the value of an input register
This value will be returned when bus read.
@param offset register offset (PDU addressing: 0-9999)
@param value new value
@return true, false if register not found.
*/
inline bool setIreg (word offset, word value) {
return setReg (offset + TRegister::IregOffset, value);
}
/**
@brief Return the value of a coil
@param offset register offset (PDU addressing: 0-9999)
@return coil value
*/
inline bool coil (word offset) {
return (reg (offset + TRegister::CoilOffset) == 0xFF00);
}
/**
@brief Return the value of a discrete input
@param offset input offset (PDU addressing: 0-9999)
@return input value
*/
inline bool ists (word offset) {
return (reg (offset + TRegister::IstsOffset) == 0xFF00);
}
/**
@brief Return the value of an input register
@param offset register offset (PDU addressing: 0-9999)
@return register value
*/
inline word ireg (word offset) {
return reg (offset + TRegister::IregOffset);
}
/**
@brief Change the value of a coil
This value will be returned when bus read, the master can also modify it.
@deprecated removed in next major release, use setCoil() instead.
@param offset register offset (PDU addressing: 0-9999)
@param value new value
@return true, false if coil not found.
*/
inline bool Coil (word offset, bool value) {
return setCoil (offset, value);
}
/**
@brief Change the value of a discrete input
This value will be returned when bus read,.
@deprecated removed in next major release, use setIsts() instead.
@param offset input offset (PDU addressing: 0-9999)
@param value new value
@return true, false if input not found.
*/
inline bool Ists (word offset, bool value) {
return setIsts (offset, value);
}
/**
@brief Change the value of an input register
This value will be returned when bus read.
@deprecated removed in next major release, use setIreg() instead.
@param offset register offset (PDU addressing: 0-9999)
@param value new value
@return true, false if register not found.
*/
inline bool Ireg (word offset, word value) {
return setIreg (offset, value);
}
/**
@brief Return the value of a coil
@deprecated removed in next major release, use coil() instead.
@param offset register offset (PDU addressing: 0-9999)
@return coil value
*/
inline bool Coil (word offset) {
return coil (offset);
}
/**
@brief Return the value of a discrete input
@deprecated removed in next major release, use ists() instead.
@param offset input offset (PDU addressing: 0-9999)
@return input value
*/
inline bool Ists (word offset) {
return ists (offset);
}
/**
@brief Return the value of an input register
@deprecated removed in next major release, use ireg() instead.
@param offset register offset (PDU addressing: 0-9999)
@return register value
*/
inline word Ireg (word offset) {
return ireg (offset);
}
/**
@brief Sets additional Data for Report Server ID function
@param data data string
@return the number of chars gets from data (249 max)
*/
int setAdditionalServerData (const char data[]);
#endif
};