@@ -288,6 +288,45 @@ def test_read_coils_multiple(self) -> None:
288288 self .assertTrue (all (isinstance (x , bool ) for x in coil_status ))
289289 self .assertEqual (coil_status , expectation_list )
290290
291+ # Reading coil data bits is reversed
292+ # see https://github.com/brainelectronics/micropython-modbus/issues/38
293+ #
294+ # Read/Write register at some location of definition
295+ # see https://github.com/brainelectronics/micropython-modbus/issues/35
296+ def test_read_coils_partially (self ) -> None :
297+ """Test reading coils partially of client"""
298+ coil_address = \
299+ self ._register_definitions ['COILS' ]['MANY_COILS' ]['register' ]
300+ coil_qty = \
301+ self ._register_definitions ['COILS' ]['MANY_COILS' ]['len' ]
302+ expectation_list_full = list (
303+ map (bool ,
304+ self ._register_definitions ['COILS' ]['MANY_COILS' ]['val' ])
305+ )
306+
307+ coil_qty_less_8 = randint (2 , 7 )
308+ coil_qty_more_8 = randint (8 , coil_qty - 1 )
309+ possibilities = [coil_qty_less_8 , coil_qty_more_8 ]
310+
311+ for partial_coil_qty in possibilities :
312+ with self .subTest (partial_coil_qty = partial_coil_qty ):
313+ expectation_list_partial = \
314+ expectation_list_full [:partial_coil_qty ]
315+
316+ coil_status = self ._host .read_coils (
317+ slave_addr = self ._client_addr ,
318+ starting_addr = coil_address ,
319+ coil_qty = partial_coil_qty )
320+
321+ self .test_logger .debug (
322+ 'Status of COIL {} length {}/{}: {}, expectation: {}' .
323+ format (coil_address , partial_coil_qty , coil_qty ,
324+ coil_status , expectation_list_partial ))
325+ self .assertIsInstance (coil_status , list )
326+ self .assertEqual (len (coil_status ), partial_coil_qty )
327+ self .assertTrue (all (isinstance (x , bool ) for x in coil_status ))
328+ self .assertEqual (coil_status , expectation_list_partial )
329+
291330 def test_read_discrete_inputs_single (self ) -> None :
292331 """Test reading discrete inputs of client"""
293332 ist_address = \
@@ -353,6 +392,39 @@ def test_read_discrete_inputs_multiple(self) -> None:
353392 self .assertTrue (all (isinstance (x , bool ) for x in input_status ))
354393 self .assertEqual (input_status , expectation_list )
355394
395+ # Read/Write register at some location of definition
396+ # see https://github.com/brainelectronics/micropython-modbus/issues/35
397+ def test_read_discrete_inputs_partially (self ) -> None :
398+ """Test reading discrete inputs partially of client"""
399+ ist_address = \
400+ self ._register_definitions ['ISTS' ]['ANOTHER_EXAMPLE_ISTS' ]['register' ] # noqa: E501
401+ input_qty = \
402+ self ._register_definitions ['ISTS' ]['ANOTHER_EXAMPLE_ISTS' ]['len' ]
403+ expectation_list_full = \
404+ self ._register_definitions ['ISTS' ]['ANOTHER_EXAMPLE_ISTS' ]['val' ]
405+
406+ input_qty_less = input_qty - 1
407+ possibilities = [input_qty_less ]
408+
409+ for partial_input_qty in possibilities :
410+ with self .subTest (partial_input_qty = partial_input_qty ):
411+ expectation_list_partial = \
412+ expectation_list_full [:partial_input_qty ]
413+
414+ input_status = self ._host .read_discrete_inputs (
415+ slave_addr = self ._client_addr ,
416+ starting_addr = ist_address ,
417+ input_qty = partial_input_qty )
418+
419+ self .test_logger .debug (
420+ 'Status of IST {} length {}/{}: {}, expectation: {}' .
421+ format (ist_address , partial_input_qty , input_qty ,
422+ input_status , expectation_list_partial ))
423+ self .assertIsInstance (input_status , list )
424+ self .assertEqual (len (input_status ), partial_input_qty )
425+ self .assertTrue (all (isinstance (x , bool ) for x in input_status ))
426+ self .assertEqual (input_status , expectation_list_partial )
427+
356428 def test_read_holding_registers_single (self ) -> None :
357429 """Test reading holding registers of client"""
358430 # read holding register with negative value
@@ -427,6 +499,40 @@ def test_read_holding_registers_multiple(self) -> None:
427499 self .assertTrue (all (isinstance (x , int ) for x in register_value ))
428500 self .assertEqual (register_value , expectation )
429501
502+ # Read/Write register at some location of definition
503+ # see https://github.com/brainelectronics/micropython-modbus/issues/35
504+ def test_read_holding_registers_partially (self ) -> None :
505+ """Test reading holding registers partially of client"""
506+ hreg_address = \
507+ self ._register_definitions ['HREGS' ]['ANOTHER_EXAMPLE_HREG' ]['register' ] # noqa: E501
508+ register_qty = \
509+ self ._register_definitions ['HREGS' ]['ANOTHER_EXAMPLE_HREG' ]['len' ]
510+ expectation_tuple_full = tuple (
511+ self ._register_definitions ['HREGS' ]['ANOTHER_EXAMPLE_HREG' ]['val' ]
512+ )
513+ register_qty_less = register_qty - 1
514+ possibilities = [register_qty_less ]
515+
516+ for partial_register_qty in possibilities :
517+ with self .subTest (partial_register_qty = partial_register_qty ):
518+ expectation_tuple_partial = \
519+ expectation_tuple_full [:partial_register_qty ]
520+
521+ register_value = self ._host .read_holding_registers (
522+ slave_addr = self ._client_addr ,
523+ starting_addr = hreg_address ,
524+ register_qty = partial_register_qty )
525+
526+ self .test_logger .debug (
527+ 'Status of HREG {} length {}/{}: {}, expectation: {}' .
528+ format (hreg_address , partial_register_qty , register_qty ,
529+ register_value , expectation_tuple_partial ))
530+ self .assertIsInstance (register_value , tuple )
531+ self .assertEqual (len (register_value ), partial_register_qty )
532+ self .assertTrue (all (isinstance (x , int )
533+ for x in register_value ))
534+ self .assertEqual (register_value , expectation_tuple_partial )
535+
430536 def test_read_input_registers_single (self ) -> None :
431537 """Test reading input registers of client"""
432538 ireg_address = \
@@ -475,6 +581,41 @@ def test_read_input_registers_multiple(self) -> None:
475581 self .assertTrue (all (isinstance (x , int ) for x in register_value ))
476582 self .assertEqual (register_value , expectation )
477583
584+ # Read/Write register at some location of definition
585+ # see https://github.com/brainelectronics/micropython-modbus/issues/35
586+ def test_read_input_registers_partially (self ) -> None :
587+ """Test reading input registers partially of client"""
588+ ireg_address = \
589+ self ._register_definitions ['IREGS' ]['ANOTHER_EXAMPLE_IREG' ]['register' ] # noqa: E501
590+ register_qty = \
591+ self ._register_definitions ['IREGS' ]['ANOTHER_EXAMPLE_IREG' ]['len' ]
592+ expectation_tuple_full = tuple (
593+ self ._register_definitions ['IREGS' ]['ANOTHER_EXAMPLE_IREG' ]['val' ]
594+ )
595+ register_qty_less = register_qty - 1
596+ possibilities = [register_qty_less ]
597+
598+ for partial_register_qty in possibilities :
599+ with self .subTest (partial_register_qty = partial_register_qty ):
600+ expectation_tuple_partial = \
601+ expectation_tuple_full [:partial_register_qty ]
602+
603+ register_value = self ._host .read_input_registers (
604+ slave_addr = self ._client_addr ,
605+ starting_addr = ireg_address ,
606+ register_qty = partial_register_qty ,
607+ signed = False )
608+
609+ self .test_logger .debug (
610+ 'Status of IREG {} length {}/{}: {}, expectation: {}' .
611+ format (ireg_address , partial_register_qty , register_qty ,
612+ register_value , expectation_tuple_partial ))
613+ self .assertIsInstance (register_value , tuple )
614+ self .assertEqual (len (register_value ), partial_register_qty )
615+ self .assertTrue (all (isinstance (x , int )
616+ for x in register_value ))
617+ self .assertEqual (register_value , expectation_tuple_partial )
618+
478619 def test_reset_client_data (self ) -> None :
479620 """Test resettig client data to default"""
480621 coil_address = \
0 commit comments