```"""
-----------------------------------------------------------

This is an example of building a custom payload builder
that can be used in the pymodbus library. Below is a
simple binary coded decimal builder and decoder.
"""
from struct import pack, unpack
from pymodbus.constants import Endian
from pymodbus.utilities import pack_bitstring
from pymodbus.utilities import unpack_bitstring
from pymodbus.exceptions import ParameterException

def convert_to_bcd(decimal):
""" Converts a decimal value to a bcd value

:param value: The decimal value to to pack into bcd
:returns: The number in bcd form
"""
place, bcd = 0, 0
while decimal > 0:
nibble = decimal % 10
bcd += nibble << place
decimal /= 10
place += 4
return bcd

def convert_from_bcd(bcd):
""" Converts a bcd value to a decimal value

:param value: The value to unpack from bcd
:returns: The number in decimal form
"""
place, decimal = 1, 0
while bcd > 0:
nibble = bcd & 0xf
decimal += nibble * place
bcd >>= 4
place *= 10
return decimal

def count_bcd_digits(bcd):
""" Count the number of digits in a bcd value

:param bcd: The bcd number to count the digits of
:returns: The number of digits in the bcd string
"""
count = 0
while bcd > 0:
count += 1
bcd >>= 4
return count

"""
A utility that helps build binary coded decimal payload
messages to be written with the various modbus messages.
example::

"""

""" Initialize a new instance of the payload builder

:param endian: The endianess of the payload
"""
self._endian  = endian

def __str__(self):
""" Return the payload buffer as a string

:returns: The payload buffer as a string
"""

def reset(self):
"""

def build(self):
""" Return the payload buffer as a list

This list is two bytes per element and can
thus be treated as a list of registers.

:returns: The payload buffer as a list
"""
string = str(self)
length = len(string)
string = string + ('\x00' * (length % 2))
return [string[i:i+2] for i in range(0, length, 2)]

""" Adds a collection of bits to be encoded

If these are less than a multiple of eight,
they will be left padded with 0 bits to make
it so.

:param value: The value to add to the buffer
"""
value = pack_bitstring(values)

""" Adds any 8bit numeric type to the buffer

:param value: The value to add to the buffer
"""
encoded = []
value = convert_to_bcd(value)
size = size or count_bcd_digits(value)
while size > 0:
nibble = value & 0xf
encoded.append(pack('B', nibble))
value >>= 4
size -= 1

""" Adds a string to the buffer

:param value: The value to add to the buffer
"""

"""
A utility that helps decode binary coded decimal payload
messages from a modbus reponse message. What follows is
a simple example::

first   = decoder.decode_int(2)
second  = decoder.decode_int(5) / 100
"""

""" Initialize a new payload decoder

"""
self._pointer = 0x00

@staticmethod
def fromRegisters(registers, endian=Endian.Little):
""" Initialize a payload decoder with the result of
reading a collection of registers from a modbus device.

The registers are treated as a list of 2 byte values.
We have to do this because of how the data has already
been decoded by the rest of the library.

:param registers: The register results to initialize with
:param endian: The endianess of the payload
"""
if isinstance(registers, list): # repack into flat binary
payload = ''.join(pack('>H', x) for x in registers)
raise ParameterException('Invalid collection of registers supplied')

@staticmethod
def fromCoils(coils, endian=Endian.Little):
""" Initialize a payload decoder with the result of
reading a collection of coils from a modbus device.

The coils are treated as a list of bit(boolean) values.

:param coils: The coil results to initialize with
:param endian: The endianess of the payload
"""
if isinstance(coils, list):
raise ParameterException('Invalid collection of coils supplied')

def reset(self):
""" Reset the decoder pointer back to the start
"""
self._pointer = 0x00

def decode_int(self, size=1):
""" Decodes a int or long from the buffer
"""
self._pointer += size
return convert_from_bcd(handle)

def decode_bits(self):
""" Decodes a byte worth of bits from the buffer
"""
self._pointer += 1
return unpack_bitstring(handle)

def decode_string(self, size=1):
""" Decodes a string from the buffer

:param size: The size of the string to decode
"""
self._pointer += size