@@ -293,6 +293,7 @@ def _write( self, address, value, **kwargs ):
293293 value = list ( value ) if multi else [ value ]
294294 writer = None
295295 unit = kwargs .pop ( 'unit' , self .unit )
296+ # The count is deduced from the size of .registers/.bits
296297 kwargs .update ( dev_id = unit )
297298 if 400001 <= address <= 465536 :
298299 # 400001-465536: Holding Registers
@@ -326,8 +327,8 @@ def _write( self, address, value, **kwargs ):
326327 pass
327328 if not writer :
328329 raise ParameterException ( "Invalid Modbus address for write: %d" % ( address ))
329-
330- result = self .client .execute ( no_response_expected = False , request = writer ( ** kwargs ) )
330+ request = writer ( ** kwargs )
331+ result = self .client .execute ( no_response_expected = False , request = request )
331332 if isinstance ( result , ExceptionResponse ):
332333 raise ModbusException ( str ( result ))
333334 assert isinstance ( result , ModbusResponse ), "Unexpected non-ModbusResponse: %r" % result
@@ -346,49 +347,71 @@ def _read( self, address, count=1, **kwargs ):
346347 raise PlcOffline ( "Modbus Read of PLC %s/%6d failed: Offline; Connect failure" % (
347348 self .description , address ))
348349
350+ unit = kwargs .pop ( 'unit' , self .unit )
351+ kwargs .update ( dev_id = unit , count = count )
352+
349353 # Use address to deduce Holding/Input Register or Coil/Status.
350354 reader = None
351- xformed = address
352355 if 400001 <= address <= 465536 :
353356 reader = ReadHoldingRegistersRequest
354- xformed -= 400001
357+ kwargs .update (
358+ address = address - 400001 ,
359+ )
355360 elif 300001 <= address <= 365536 :
356361 reader = ReadInputRegistersRequest
357- xformed -= 300001
362+ kwargs .update (
363+ address = address - 300001 ,
364+ )
358365 elif 100001 <= address <= 165536 :
359366 reader = ReadDiscreteInputsRequest
360- xformed -= 100001
367+ kwargs .update (
368+ address = address - 100001 ,
369+ )
361370 elif 40001 <= address <= 99999 :
362371 reader = ReadHoldingRegistersRequest
363- xformed -= 40001
372+ kwargs .update (
373+ address = address - 40001 ,
374+ )
364375 elif 30001 <= address <= 39999 :
365376 reader = ReadInputRegistersRequest
366- xformed -= 30001
377+ kwargs .update (
378+ address = address - 30001 ,
379+ )
367380 elif 10001 <= address <= 19999 :
368381 reader = ReadDiscreteInputsRequest
369- xformed -= 10001
382+ kwargs .update (
383+ address = address - 10001 ,
384+ )
370385 elif 1 <= address <= 9999 :
371386 reader = ReadCoilsRequest
372- xformed -= 1
387+ kwargs .update (
388+ address = address - 1 ,
389+ )
373390 else :
374391 # Invalid address
375392 pass
376393 if not reader :
377394 raise ParameterException ( "Invalid Modbus address for read: %d" % ( address ))
378395
379- unit = kwargs .pop ( 'unit' , self .unit )
380- request = reader ( address = xformed , count = count , dev_id = unit , ** kwargs )
396+ request = reader ( ** kwargs )
381397 log .debug ( "%s/%6d-%6d transformed to %s" , self .description , address , address + count - 1 ,
382398 request )
383399
384400 result = self .client .execute ( no_response_expected = False , request = request )
401+ log .debug ( "%s/%6d-%6d responded w/: %s" , self .description , address , address + count - 1 ,
402+ result )
385403 if isinstance ( result , ExceptionResponse ):
386404 # The remote PLC returned a response indicating it encountered an
387405 # error processing the request. Convert it to raise a ModbusException.
388406 raise ModbusException ( str ( result ))
389407 assert isinstance ( result , ModbusResponse ), "Unexpected non-ModbusResponse: %r" % result
390408
391- # The result may contain .bits or .registers, 1 or more values
392- values = result .bits if hasattr ( result , 'bits' ) else result .registers
393- return values if len ( values ) > 1 else values [0 ]
409+ # The result may contain .bits or .registers, 1 or more values. Unfortunately, pymodbus
410+ # puts the data in .bits or .registers, and doesn't supply a method to know which, unless we
411+ # decode the protocol here. Truncate response to requested count, as bits is unpacked
412+ # from bytes, and padded w/ undefined data.
413+ values = result .registers or result .bits
414+ log .debug ( "%s/%6d-%6d received: %r" , self .description , address , address + count - 1 ,
415+ values )
416+ return values [:count ] if count > 1 else values [0 ]
394417
0 commit comments