1111 "BinaryPayloadDecoder" ,
1212]
1313
14+ from array import array
15+
1416# pylint: disable=missing-type-doc
1517from struct import pack , unpack
1618
1921from pymodbus .logging import Log
2022from pymodbus .utilities import (
2123 pack_bitstring ,
24+ system_endian ,
2225 unpack_bitstring ,
2326)
2427
2528
26- WC = {"b" : 1 , "h" : 2 , "e" : 2 , "i" : 4 , "l" : 4 , "q" : 8 , "f" : 4 , "d" : 8 }
27-
28-
2929class BinaryPayloadBuilder :
3030 """A utility that helps build payload messages to be written with the various modbus messages.
3131
@@ -69,15 +69,14 @@ def _pack_words(self, fstring: str, value) -> bytes:
6969 :return:
7070 """
7171 value = pack (f"!{ fstring } " , value )
72- wordorder = WC .get (fstring .lower ()) // 2 # type: ignore[operator]
73- upperbyte = f"!{ wordorder } H"
74- payload = unpack (upperbyte , value )
75-
76- if self ._wordorder == Endian .LITTLE :
77- payload = payload [::- 1 ]
78-
79- fstring = self ._byteorder + "H"
80- return b"" .join (pack (fstring , word ) for word in payload )
72+ if Endian .LITTLE in {self ._byteorder , self ._wordorder }:
73+ value = array ("H" , value )
74+ if self ._byteorder == Endian .LITTLE :
75+ value .byteswap ()
76+ if self ._wordorder == Endian .LITTLE :
77+ value .reverse ()
78+ value = value .tobytes ()
79+ return value
8180
8281 def encode (self ) -> bytes :
8382 """Get the payload buffer encoded in bytes."""
@@ -99,15 +98,14 @@ def to_registers(self):
9998
10099 :returns: The register layout to use as a block
101100 """
102- # fstring = self._byteorder+"H"
103- fstring = "!H"
104- payload = self .build ()
105- if self ._repack :
106- payload = [unpack (self ._byteorder + "H" , value )[0 ] for value in payload ]
107- else :
108- payload = [unpack (fstring , value )[0 ] for value in payload ]
109- Log .debug ("{}" , payload )
110- return payload
101+ payload = array ("H" , b'' .join (self .build ()))
102+ swap = system_endian () != Endian .BIG
103+ if self ._repack and self ._byteorder == system_endian ():
104+ swap = False
105+ if swap :
106+ payload .byteswap ()
107+ Log .debug ("{}" , payload .tolist ())
108+ return payload .tolist ()
111109
112110 def to_coils (self ) -> list [bool ]:
113111 """Convert the payload buffer into a coil layout that can be used as a context block.
@@ -295,8 +293,10 @@ def fromRegisters(
295293 """
296294 Log .debug ("{}" , registers )
297295 if isinstance (registers , list ): # repack into flat binary
298- payload = b"" .join (pack ("!H" , x ) for x in registers )
299- return cls (payload , byteorder , wordorder )
296+ payload = array ("H" , registers )
297+ if system_endian () != Endian .BIG :
298+ payload .byteswap ()
299+ return cls (payload .tobytes (), byteorder , wordorder )
300300 raise ParameterException ("Invalid collection of registers supplied" )
301301
302302 @classmethod
@@ -324,7 +324,7 @@ def fromCoils(
324324 return cls (payload , byteorder )
325325 raise ParameterException ("Invalid collection of coils supplied" )
326326
327- def _unpack_words (self , fstring : str , handle ) -> bytes :
327+ def _unpack_words (self , handle ) -> bytes :
328328 """Unpack words based on the word order and byte order.
329329
330330 # ---------------------------------------------- #
@@ -336,15 +336,14 @@ def _unpack_words(self, fstring: str, handle) -> bytes:
336336 :param handle: Value to be unpacked
337337 :return:
338338 """
339- wc_value = WC . get ( fstring . lower ()) // 2 # type: ignore[operator]
340- handle = unpack ( f"! { wc_value } H" , handle )
341- if self ._wordorder == Endian .LITTLE :
342- handle = list ( reversed ( handle ) )
343-
344- # Repack as unsigned Integer
345- handle = [ pack ( self . _byteorder + "H" , p ) for p in handle ]
339+ if Endian . LITTLE in { self . _byteorder , self . _wordorder }:
340+ handle = array ( " H" , handle )
341+ if self ._byteorder == Endian .LITTLE :
342+ handle . byteswap ( )
343+ if self . _wordorder == Endian . LITTLE :
344+ handle . reverse ()
345+ handle = handle . tobytes ()
346346 Log .debug ("handle: {}" , handle )
347- handle = b"" .join (handle )
348347 return handle
349348
350349 def reset (self ):
@@ -377,15 +376,15 @@ def decode_32bit_uint(self):
377376 self ._pointer += 4
378377 fstring = "I"
379378 handle = self ._payload [self ._pointer - 4 : self ._pointer ]
380- handle = self ._unpack_words (fstring , handle )
379+ handle = self ._unpack_words (handle )
381380 return unpack ("!" + fstring , handle )[0 ]
382381
383382 def decode_64bit_uint (self ):
384383 """Decode a 64 bit unsigned int from the buffer."""
385384 self ._pointer += 8
386385 fstring = "Q"
387386 handle = self ._payload [self ._pointer - 8 : self ._pointer ]
388- handle = self ._unpack_words (fstring , handle )
387+ handle = self ._unpack_words (handle )
389388 return unpack ("!" + fstring , handle )[0 ]
390389
391390 def decode_8bit_int (self ):
@@ -407,39 +406,39 @@ def decode_32bit_int(self):
407406 self ._pointer += 4
408407 fstring = "i"
409408 handle = self ._payload [self ._pointer - 4 : self ._pointer ]
410- handle = self ._unpack_words (fstring , handle )
409+ handle = self ._unpack_words (handle )
411410 return unpack ("!" + fstring , handle )[0 ]
412411
413412 def decode_64bit_int (self ):
414413 """Decode a 64 bit signed int from the buffer."""
415414 self ._pointer += 8
416415 fstring = "q"
417416 handle = self ._payload [self ._pointer - 8 : self ._pointer ]
418- handle = self ._unpack_words (fstring , handle )
417+ handle = self ._unpack_words (handle )
419418 return unpack ("!" + fstring , handle )[0 ]
420419
421420 def decode_16bit_float (self ):
422421 """Decode a 16 bit float from the buffer."""
423422 self ._pointer += 2
424423 fstring = "e"
425424 handle = self ._payload [self ._pointer - 2 : self ._pointer ]
426- handle = self ._unpack_words (fstring , handle )
425+ handle = self ._unpack_words (handle )
427426 return unpack ("!" + fstring , handle )[0 ]
428427
429428 def decode_32bit_float (self ):
430429 """Decode a 32 bit float from the buffer."""
431430 self ._pointer += 4
432431 fstring = "f"
433432 handle = self ._payload [self ._pointer - 4 : self ._pointer ]
434- handle = self ._unpack_words (fstring , handle )
433+ handle = self ._unpack_words (handle )
435434 return unpack ("!" + fstring , handle )[0 ]
436435
437436 def decode_64bit_float (self ):
438437 """Decode a 64 bit float(double) from the buffer."""
439438 self ._pointer += 8
440439 fstring = "d"
441440 handle = self ._payload [self ._pointer - 8 : self ._pointer ]
442- handle = self ._unpack_words (fstring , handle )
441+ handle = self ._unpack_words (handle )
443442 return unpack ("!" + fstring , handle )[0 ]
444443
445444 def decode_string (self , size = 1 ):
0 commit comments