@@ -124,23 +124,6 @@ bool Modbus::regOutOfBounds (word address, word value) {
124124 return false ;
125125}
126126
127- // -------------------------------------------------------------------------------
128- int Modbus::setAdditionalServerData (const char data[]) {
129-
130- free (_additional_data);
131- if (data) {
132- size_t l = strlen (data) + 1 ;
133-
134- _additional_data = (char *) malloc (l);
135- if (_additional_data) {
136-
137- strcpy (_additional_data, data);
138- return l;
139- }
140- }
141- return 0 ;
142- }
143-
144127// -------------------------------------------------------------------------------
145128// protected
146129void Modbus::receivePDU (byte *frame) {
@@ -204,6 +187,7 @@ void Modbus::receivePDU (byte *frame) {
204187}
205188
206189// -------------------------------------------------------------------------------
190+ // private
207191void Modbus::exceptionResponse (byte fcode, byte excode) {
208192 // Clean frame buffer
209193 free (_frame);
@@ -215,6 +199,40 @@ void Modbus::exceptionResponse (byte fcode, byte excode) {
215199 _reply = MB_REPLY_NORMAL;
216200}
217201
202+ /* Func 06: Write Single Register
203+ Request
204+ Function code 1 Byte 0x06
205+ Register Address 2 Bytes 0x0000 to 0xFFFF
206+ Register Value 2 Bytes 0x0000 to 0xFFFF
207+ Response
208+ Function code 1 Byte 0x06
209+ Register Address 2 Bytes 0x0000 to 0xFFFF
210+ Register Value 2 Bytes 0x0000 to 0xFFFF
211+ */
212+ // -------------------------------------------------------------------------------
213+ // private
214+ void Modbus::writeSingleRegister (word reg, word value) {
215+
216+ if (hregOutOfBounds (reg, value)) {
217+ exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_VALUE);
218+ return ;
219+ }
220+
221+ // Check Address and execute (reg exists?)
222+ if (!setHreg (reg, value)) {
223+ exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_ADDRESS);
224+ return ;
225+ }
226+
227+ // Check for failure ? Why ???
228+ /*
229+ if (hreg (reg) != value) {
230+ exceptionResponse (MB_FC_WRITE_REG, MB_EX_SLAVE_FAILURE);
231+ return;
232+ }
233+ */
234+ _reply = MB_REPLY_ECHO; // reply with received frame
235+ }
218236
219237/*
220238 Func 03: Read Holding Registers
@@ -228,21 +246,23 @@ void Modbus::exceptionResponse (byte fcode, byte excode) {
228246 Register value N* x 2 Bytes
229247 N = Quantity of Registers
230248*/
249+ // -------------------------------------------------------------------------------
250+ // private
231251void Modbus::readRegisters (word startreg, word numregs) {
232252 // Check value (numregs)
233253 if (numregs < 1 || numregs > 125 ) {
234254 exceptionResponse (MB_FC_READ_REGS, MB_EX_ILLEGAL_VALUE);
235255 return ;
236256 }
237257
238- // Check Address
239- // *** See comments on readCoils method.
240- if (!searchRegister (startreg + TRegister::HregOffset)) {
241- exceptionResponse (MB_FC_READ_REGS, MB_EX_ILLEGAL_ADDRESS);
242- return ;
258+ // Check Address (startreg...startreg + numregs - 1)
259+ for (word k = 0 ; k < numregs; k++) {
260+ if (!searchRegister (startreg + TRegister::HregOffset + k)) {
261+ exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
262+ return ;
263+ }
243264 }
244265
245-
246266 // Clean frame buffer
247267 free (_frame);
248268 _len = 0 ;
@@ -275,39 +295,6 @@ void Modbus::readRegisters (word startreg, word numregs) {
275295 _reply = MB_REPLY_NORMAL;
276296}
277297
278- /* Func 06: Write Single Register
279- Request
280- Function code 1 Byte 0x06
281- Register Address 2 Bytes 0x0000 to 0xFFFF
282- Register Value 2 Bytes 0x0000 to 0xFFFF
283- Response
284- Function code 1 Byte 0x06
285- Register Address 2 Bytes 0x0000 to 0xFFFF
286- Register Value 2 Bytes 0x0000 to 0xFFFF
287- */
288- void Modbus::writeSingleRegister (word reg, word value) {
289-
290- if (hregOutOfBounds (reg, value)) {
291- exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_VALUE);
292- return ;
293- }
294-
295- // Check Address and execute (reg exists?)
296- if (!setHreg (reg, value)) {
297- exceptionResponse (MB_FC_WRITE_REG, MB_EX_ILLEGAL_ADDRESS);
298- return ;
299- }
300-
301- // Check for failure ?
302- /*
303- if (hreg (reg) != value) {
304- exceptionResponse (MB_FC_WRITE_REG, MB_EX_SLAVE_FAILURE);
305- return;
306- }
307- */
308- _reply = MB_REPLY_ECHO; // reply with received frame
309- }
310-
311298/* Func 16: Write Multiple registers
312299 Request
313300 Function code 1 Byte 0x10
@@ -321,14 +308,16 @@ void Modbus::writeSingleRegister (word reg, word value) {
321308 Starting Address 2 Bytes 0x0000 to 0xFFFF
322309 Quantity of Registers 2 Bytes 1 to 123 (0x7B)
323310*/
311+ // -------------------------------------------------------------------------------
312+ // private
324313void Modbus::writeMultipleRegisters (byte *frame, word startreg, word numoutputs, byte bytecount) {
325314 // Check value
326315 if (numoutputs < 1 || numoutputs > 123 || bytecount != 2 * numoutputs) {
327316 exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_VALUE);
328317 return ;
329318 }
330319
331- // Check Address (startreg...startreg + numregs)
320+ // Check Address (startreg...startreg + numregs - 1 )
332321 for (word k = 0 ; k < numoutputs; k++) {
333322 if (!searchRegister (startreg + TRegister::HregOffset + k)) {
334323 exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
@@ -380,21 +369,26 @@ void Modbus::writeMultipleRegisters (byte *frame, word startreg, word numoutputs
380369 Coil Status n Byte n = N or N+1
381370 N = Quantity of Outputs / 8, if the remainder is different of 0 -> N = N+1
382371*/
372+ // -------------------------------------------------------------------------------
373+ // private
383374void Modbus::readCoils (word startreg, word numregs) {
384375 // Check value (numregs)
385376 if (numregs < 1 || numregs > 2000 ) {
386377 exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_VALUE);
387378 return ;
388379 }
389380
390- // Check Address
391- // Check only startreg. Is this correct?
392381 // When I check all registers in range I got errors in ScadaBR
393382 // I think that ScadaBR request more than one in the single request
394383 // when you have more then one datapoint configured from same type.
395- if (!searchRegister (startreg + TRegister::CoilOffset)) {
396- exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_ADDRESS);
397- return ;
384+ // epsilonrt -> We absolutely must not return values that do not exist !!
385+
386+ // Check Address (startreg...startreg + numregs - 1)
387+ for (word k = 0 ; k < numregs; k++) {
388+ if (!searchRegister (startreg + TRegister::CoilOffset + k)) {
389+ exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
390+ return ;
391+ }
398392 }
399393
400394 // Clean frame buffer
@@ -452,18 +446,21 @@ void Modbus::readCoils (word startreg, word numregs) {
452446 N = Quantity of Inputs / 8 if the remainder is different of 0 N = N+1
453447 Error
454448*/
449+ // -------------------------------------------------------------------------------
450+ // private
455451void Modbus::readInputStatus (word startreg, word numregs) {
456452 // Check value (numregs)
457453 if (numregs < 0x0001 || numregs > 0x07D0 ) {
458454 exceptionResponse (MB_FC_READ_INPUT_STAT, MB_EX_ILLEGAL_VALUE);
459455 return ;
460456 }
461457
462- // Check Address
463- // *** See comments on readCoils method.
464- if (!searchRegister (startreg + TRegister::IstsOffset)) {
465- exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_ADDRESS);
466- return ;
458+ // Check Address (startreg...startreg + numregs - 1)
459+ for (word k = 0 ; k < numregs; k++) {
460+ if (!searchRegister (startreg + TRegister::IstsOffset + k)) {
461+ exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
462+ return ;
463+ }
467464 }
468465
469466 // Clean frame buffer
@@ -520,18 +517,21 @@ void Modbus::readInputStatus (word startreg, word numregs) {
520517 Input Registers N* x 2 Bytes
521518 N = Quantity of Input Registers
522519*/
520+ // -------------------------------------------------------------------------------
521+ // private
523522void Modbus::readInputRegisters (word startreg, word numregs) {
524523 // Check value (numregs)
525524 if (numregs < 0x0001 || numregs > 0x007D ) {
526525 exceptionResponse (MB_FC_READ_INPUT_REGS, MB_EX_ILLEGAL_VALUE);
527526 return ;
528527 }
529528
530- // Check Address
531- // *** See comments on readCoils method.
532- if (!searchRegister (startreg + TRegister::IregOffset)) {
533- exceptionResponse (MB_FC_READ_COILS, MB_EX_ILLEGAL_ADDRESS);
534- return ;
529+ // Check Address (startreg...startreg + numregs - 1)
530+ for (word k = 0 ; k < numregs; k++) {
531+ if (!searchRegister (startreg + TRegister::IregOffset + k)) {
532+ exceptionResponse (MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS);
533+ return ;
534+ }
535535 }
536536
537537 // Clean frame buffer
@@ -576,6 +576,8 @@ void Modbus::readInputRegisters (word startreg, word numregs) {
576576 Output Address 2 Bytes 0x0000 to 0xFFFF
577577 Output Value 2 Bytes 0x0000 or 0xFF00
578578*/
579+ // -------------------------------------------------------------------------------
580+ // private
579581void Modbus::writeSingleCoil (word reg, word status) {
580582 // Check value (status)
581583 if (status != 0xFF00 && status != 0x0000 ) {
@@ -584,16 +586,18 @@ void Modbus::writeSingleCoil (word reg, word status) {
584586 }
585587
586588 // Check Address and execute (reg exists?)
587- if (!setCoil (reg, ( bool ) status)) {
589+ if (!setCoil (reg, status != 0 )) {
588590 exceptionResponse (MB_FC_WRITE_COIL, MB_EX_ILLEGAL_ADDRESS);
589591 return ;
590592 }
591593
592- // Check for failure
594+ // Check for failure ?? Why ?
595+ /*
593596 if (coil (reg) != (bool) status) {
594597 exceptionResponse (MB_FC_WRITE_COIL, MB_EX_SLAVE_FAILURE);
595598 return;
596599 }
600+ */
597601
598602 _reply = MB_REPLY_ECHO; // reply with received frame
599603}
@@ -610,6 +614,8 @@ void Modbus::writeSingleCoil (word reg, word status) {
610614 Starting Address 2 Bytes 0x0000 to 0xFFFF
611615 Quantity of Outputs 2 Bytes 0x0001 to 0x07B0
612616*/
617+ // -------------------------------------------------------------------------------
618+ // private
613619void Modbus::writeMultipleCoils (byte *frame, word startreg, word numoutputs, byte bytecount) {
614620 // Check value
615621 word bytecount_calc = numoutputs / 8 ;
@@ -673,6 +679,8 @@ void Modbus::writeMultipleCoils (byte *frame, word startreg, word numoutputs, by
673679 Run Indicator Status 1 Byte 0x00 = OFF, 0xFF = ON
674680 Additional Data
675681*/
682+ // -------------------------------------------------------------------------------
683+ // private
676684void Modbus::reportServerId () {
677685 // Clean frame buffer
678686 free (_frame);
@@ -695,5 +703,22 @@ void Modbus::reportServerId() {
695703 _reply = MB_REPLY_NORMAL;
696704}
697705
706+ // -------------------------------------------------------------------------------
707+ int Modbus::setAdditionalServerData (const char data[]) {
708+
709+ free (_additional_data);
710+ if (data) {
711+ size_t l = strlen (data) + 1 ;
712+
713+ _additional_data = (char *) malloc (l);
714+ if (_additional_data) {
715+
716+ strcpy (_additional_data, data);
717+ return l;
718+ }
719+ }
720+ return 0 ;
721+ }
722+
698723// -------------------------------------------------------------------------------
699724#endif // USE_HOLDING_REGISTERS_ONLY not defined
0 commit comments