Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,7 @@
*.exe
*.out
*.app
.pioenvs
.piolibdeps
.clang_complete
.gcc-flags.json
94 changes: 51 additions & 43 deletions src/ModbusSlave.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,39 +141,75 @@ int Modbus::poll() {
return 0;
}

// check unit-id
if (bufIn[0] != unitID) return 0;

/**
* Validate buffer.
*/
// check minimum length.
if (lengthIn < 8) return 0;

// this removes the null character that sometimes
// is get from the SoftwareSerial on the "nano"
if(lengthIn > 8 && bufIn[lengthIn-1] == 0) lengthIn--;

// check unit-id
if (bufIn[0] != unitID) return 0;
/**
* Get the Function code.
*/
fc = bufIn[1];

// check crc.
crc = word(bufIn[lengthIn - 1], bufIn[lengthIn - 2]);
if (calcCRC(bufIn, lengthIn - 2) != crc) return 0;
/**
* Get message address and length/status.
*/
address = word(bufIn[2], bufIn[3]); // first register.
length = word(bufIn[4], bufIn[5]); // number of registers to act upone or status.

/**
* Parse command
* Output length sanity check, and remove trailing noise from message.
*/
fc = bufIn[1];
switch (fc) {
case FC_READ_COILS: // read coils (digital out state)
case FC_READ_DISCRETE_INPUT: // read input state (digital in)
address = word(bufIn[2], bufIn[3]); // coil to set.
length = word(bufIn[4], bufIn[5]);
case FC_READ_HOLDING_REGISTERS: // read holding registers (analog out state)
case FC_READ_INPUT_REGISTERS: // read input registers (analog in)
// sanity check.
if (length > MAX_BUFFER) return 0;

// ignore tailing nulls.
lengthIn = 8;

break;
case FC_WRITE_COIL:
status = length; // 0xff00 - on, 0x0000 - off

// ignore tailing nulls.
lengthIn = 8;

break;
case FC_WRITE_MULTIPLE_REGISTERS:
// sanity check.
if (length > MAX_BUFFER) return 0;

// check command length.
if (lengthIn != 8) return 0;
// check buffer in size.
if (lengthIn < (int)(7 + length * 2 + 2)) return 0;

// ignore tailing nulls.
lengthIn = (int)(7 + length * 2 + 2);

break;
default:
// unknown command
return 0;
break;
}

// check crc.
crc = word(bufIn[lengthIn - 1], bufIn[lengthIn - 2]);
if (calcCRC(bufIn, lengthIn - 2) != crc) return 0;

/**
* Parse command
*/
switch (fc) {
case FC_READ_COILS: // read coils (digital out state)
case FC_READ_DISCRETE_INPUT: // read input state (digital in)
// build valid empty answer.
lengthOut = 3 + (length - 1) / 8 + 1 + 2;
bufOut[2] = (length - 1) / 8 + 1;
Expand All @@ -188,15 +224,6 @@ int Modbus::poll() {
break;
case FC_READ_HOLDING_REGISTERS: // read holding registers (analog out state)
case FC_READ_INPUT_REGISTERS: // read input registers (analog in)
address = word(bufIn[2], bufIn[3]); // first register.
length = word(bufIn[4], bufIn[5]); // number of registers to read.

// sanity check.
if (length > MAX_BUFFER) return 0;

// check command length.
if (lengthIn != 8) return 0;

// build valid empty answer.
lengthOut = 3 + 2 * length + 2;
bufOut[2] = 2 * length;
Expand All @@ -210,12 +237,6 @@ int Modbus::poll() {
}
break;
case FC_WRITE_COIL: // write one coil (digital out)
address = word(bufIn[2], bufIn[3]); // coil to set
status = word(bufIn[4], bufIn[5]); // 0xff00 - on, 0x0000 - off

// check command length.
if (lengthIn != 8) return 0;

// build valid empty answer.
lengthOut = 8;
memcpy(bufOut + 2, bufIn + 2, 4);
Expand All @@ -226,15 +247,6 @@ int Modbus::poll() {
}
break;
case FC_WRITE_MULTIPLE_REGISTERS: // write holding registers (analog out)
address = word(bufIn[2], bufIn[3]); // first register
length = word(bufIn[4], bufIn[5]); // number of registers to set

// sanity check.
if (length > MAX_BUFFER) return 0;

// check command length
if (lengthIn != (7 + length * 2 + 2)) return 0;

// build valid empty answer.
lengthOut = 8;
memcpy(bufOut + 2, bufIn + 2, 4);
Expand All @@ -244,10 +256,6 @@ int Modbus::poll() {
cbVector[CB_WRITE_MULTIPLE_REGISTERS](fc, address, length);
}
break;
default:
// unknown command
return 0;
break;
}

/**
Expand Down