This commit is contained in:
2022-12-15 15:26:57 +01:00
commit 0939c32c58
56 changed files with 10650 additions and 0 deletions

View File

@ -0,0 +1,424 @@
/*
This file is part of the ArduinoModbus library.
Copyright (c) 2018 Arduino SA. All rights reserved.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include <errno.h>
#include "ModbusClient.h"
ModbusClient::ModbusClient(unsigned long defaultTimeout) :
_mb(NULL),
_timeout(defaultTimeout),
_defaultId(0x00),
_transmissionBegun(false),
_values(NULL),
_available(0),
_read(0),
_availableForWrite(0),
_written(0)
{
}
ModbusClient::~ModbusClient()
{
if (_values != NULL) {
free(_values);
}
if (_mb != NULL) {
modbus_free(_mb);
}
}
int ModbusClient::begin(modbus_t* mb, int defaultId)
{
end();
_mb = mb;
_defaultId = defaultId;
if (_mb == NULL) {
return 0;
}
if (modbus_connect(_mb) != 0) {
modbus_free(_mb);
_mb = NULL;
return 0;
}
_transmissionBegun = false;
_available = 0;
_read = 0;
_availableForWrite = 0;
_written = 0;
modbus_set_error_recovery(_mb, MODBUS_ERROR_RECOVERY_PROTOCOL);
setTimeout(_timeout);
return 1;
}
void ModbusClient::end()
{
if (_values != NULL) {
free(_values);
_values = NULL;
}
if (_mb != NULL) {
modbus_close(_mb);
modbus_free(_mb);
_mb = NULL;
}
}
int ModbusClient::coilRead(int address)
{
return coilRead(_defaultId, address);
}
int ModbusClient::coilRead(int id, int address)
{
uint8_t value;
modbus_set_slave(_mb, id);
if (modbus_read_bits(_mb, address, 1, &value) < 0) {
return -1;
}
return value;
}
int ModbusClient::discreteInputRead(int address)
{
return discreteInputRead(_defaultId, address);
}
int ModbusClient::discreteInputRead(int id, int address)
{
uint8_t value;
modbus_set_slave(_mb, id);
if (modbus_read_input_bits(_mb, address, 1, &value) < 0) {
return -1;
}
return value;
}
long ModbusClient::holdingRegisterRead(int address)
{
return holdingRegisterRead(_defaultId, address);
}
long ModbusClient::holdingRegisterRead(int id, int address)
{
uint16_t value;
modbus_set_slave(_mb, id);
if (modbus_read_registers(_mb, address, 1, &value) < 0) {
return -1;
}
return value;
}
long ModbusClient::inputRegisterRead(int address)
{
return inputRegisterRead(_defaultId, address);
}
long ModbusClient::inputRegisterRead(int id, int address)
{
uint16_t value;
modbus_set_slave(_mb, id);
if (modbus_read_input_registers(_mb, address, 1, &value) < 0) {
return -1;
}
return value;
}
int ModbusClient::coilWrite(int address, uint8_t value)
{
return coilWrite(_defaultId, address, value);
}
int ModbusClient::coilWrite(int id, int address, uint8_t value)
{
modbus_set_slave(_mb, id);
if (modbus_write_bit(_mb, address, value) < 0) {
return 0;
}
return 1;
}
int ModbusClient::holdingRegisterWrite(int address, uint16_t value)
{
return holdingRegisterWrite(_defaultId, address, value);
}
int ModbusClient::holdingRegisterWrite(int id, int address, uint16_t value)
{
modbus_set_slave(_mb, id);
if (modbus_write_register(_mb, address, value) < 0) {
return 0;
}
return 1;
}
int ModbusClient::registerMaskWrite(int address, uint16_t andMask, uint16_t orMask)
{
return registerMaskWrite(_defaultId, address, andMask, orMask);
}
int ModbusClient::registerMaskWrite(int id, int address, uint16_t andMask, uint16_t orMask)
{
modbus_set_slave(_mb, id);
if (modbus_mask_write_register(_mb, address, andMask, orMask) < 0) {
return 0;
}
return 1;
}
int ModbusClient::beginTransmission(int type, int address, int nb)
{
return beginTransmission(_defaultId, type, address, nb);
}
int ModbusClient::beginTransmission(int id, int type, int address, int nb)
{
if ((type != COILS && type != HOLDING_REGISTERS) || nb < 1) {
errno = EINVAL;
return 0;
}
int valueSize = (type == COILS) ? sizeof(uint8_t) : sizeof(uint16_t);
_values = realloc(_values, nb * valueSize);
if (_values == NULL) {
errno = ENOMEM;
return 0;
}
memset(_values, 0x00, nb * valueSize);
_transmissionBegun = true;
_id = id;
_type = type;
_address = address;
_nb = nb;
_available = 0;
_read = 0;
_availableForWrite = nb;
_written = 0;
return 1;
}
int ModbusClient::write(unsigned int value)
{
if (!_transmissionBegun || _availableForWrite <= 0) {
return 0;
}
switch (_type) {
case COILS:
((uint8_t*)_values)[_written++] = value;
_availableForWrite--;
return 1;
case HOLDING_REGISTERS:
((uint16_t*)_values)[_written++] = value;
_availableForWrite--;
return 1;
default:
return 0;
}
return 1;
}
int ModbusClient::endTransmission()
{
if (!_transmissionBegun) {
return 0;
}
int result = -1;
modbus_set_slave(_mb, _id);
switch (_type) {
case COILS:
result = modbus_write_bits(_mb, _address, _nb, (const uint8_t*)_values);
break;
case HOLDING_REGISTERS:
result = modbus_write_registers(_mb, _address, _nb, (const uint16_t*)_values);
break;
default:
return 0;
}
_transmissionBegun = false;
_available = 0;
_read = 0;
_availableForWrite = 0;
_written = 0;
return (result < 0) ? 0 : 1;
}
int ModbusClient::requestFrom(int type, int address, int nb)
{
return requestFrom(_defaultId, type, address, nb);
}
int ModbusClient::requestFrom(int id, int type, int address, int nb)
{
if ((type != COILS && type != DISCRETE_INPUTS && type != HOLDING_REGISTERS && type != INPUT_REGISTERS)
|| (nb < 1)) {
errno = EINVAL;
return 0;
}
int valueSize = (type == COILS || type == DISCRETE_INPUTS) ? sizeof(uint8_t) : sizeof(uint16_t);
_values = realloc(_values, nb * valueSize);
if (_values == NULL) {
errno = ENOMEM;
return 0;
}
int result = -1;
modbus_set_slave(_mb, id);
switch (type) {
case COILS:
result = modbus_read_bits(_mb, address, nb, (uint8_t*)_values);
break;
case DISCRETE_INPUTS:
result = modbus_read_input_bits(_mb, address, nb, (uint8_t*)_values);
break;
case HOLDING_REGISTERS:
result = modbus_read_registers(_mb, address, nb, (uint16_t*)_values);
break;
case INPUT_REGISTERS:
result = modbus_read_input_registers(_mb, address, nb, (uint16_t*)_values);
break;
default:
break;
}
if (result == -1) {
return 0;
}
_transmissionBegun = false;
_type = type;
_available = nb;
_read = 0;
_availableForWrite = 0;
_written = 0;
return nb;
}
int ModbusClient::available()
{
return _available;
}
long ModbusClient::read()
{
if (_available <= 0) {
return -1;
}
long result = -1;
switch (_type) {
case COILS:
case DISCRETE_INPUTS:
result = ((uint8_t*)_values)[_read];
break;
case HOLDING_REGISTERS:
case INPUT_REGISTERS:
result = ((uint16_t*)_values)[_read];
break;
default:
break;
}
if (result != -1) {
_available--;
_read++;
}
return result;
}
const char* ModbusClient::lastError()
{
if (errno == 0) {
return NULL;
}
return modbus_strerror(errno);
}
void ModbusClient::setTimeout(unsigned long ms)
{
_timeout = ms;
if (_mb) {
modbus_set_response_timeout(_mb, _timeout / 1000, (_timeout % 1000) * 1000);
}
}