title: '[Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 8 bytes (0 received)'
body: <p>I am trying to use my raspberry pi as a modbus slave and fetch data from my regular windows machine (representing the modbus master). Right now both slave and master are running on the same (windows) machine, to try things out beforehand.</p>
  
  <p>This is the modbus slave I've adapted to my needs from the pymodbus <a href="https://pymodbus.readthedocs.io/en/latest/source/example/updating_server.html" rel="nofollow noreferrer">updating server example</a>:</p>
  
  <pre><code>    #!/usr/bin/env python
  # --------------------------------------------------------------------------- #
  # import the modbus libraries we need
  # --------------------------------------------------------------------------- #
  from pymodbus.server.asynchronous import StartTcpServer
  from pymodbus.device import ModbusDeviceIdentification
  from pymodbus.datastore import ModbusSequentialDataBlock
  from pymodbus.datastore import ModbusSlaveContext, ModbusServerContext
  from pymodbus.transaction import ModbusRtuFramer, ModbusAsciiFramer
  
  # --------------------------------------------------------------------------- #
  # import the twisted libraries we need
  # --------------------------------------------------------------------------- #
  from twisted.internet.task import LoopingCall
  
  # --------------------------------------------------------------------------- #
  # configure the service logging
  # --------------------------------------------------------------------------- #
  import logging, random
  logging.basicConfig(format="%(message)s")
  log = logging.getLogger()
  log.setLevel(logging.INFO)
  
  # --------------------------------------------------------------------------- #
  # define your callback process
  # --------------------------------------------------------------------------- #
  def update_temperature(kw):
      context = kw["context"]
      slave = kw["slave_info"] 
      functionCode_read = 3
      functionCode_write = 6
  
      # coils     :   0x0000  : fc=01 (read) fc=05 (write)
      # inputs    :   0x2710  : fc=02 (read)
      # inp.reg.  :   0x7530  : fc=04 (read)  
      # hold.reg. :   0x9C40  : fc=03 (read) fc=06 (write)
  
      values = context[slave["id"]].getValues(functionCode_read, slave["holding_registers"])
      log.info("old temperature values: " + str(values))
  
      for i in range(len(values)): # 
          if values[i] &lt;= 16:
              values[i] = values[i]+1 if (random.random() &gt;= 0.3) else values[i]-1
          elif values[i] &gt;= 26:
              values[i] = values[i]+1 if (random.random() &gt;= 0.7) else values[i]-1
          else:
              values[i] = values[i]+1 if (random.random() &gt;= 0.5) else values[i]-1
  
      log.info("new temperature values: " + str(values))
      context[slave["id"]].setValues(functionCode_write, slave["holding_registers"], values)
  
  def update_window_contact(kw):
      context = kw["context"]
      slave = kw["slave_info"] 
      functionCode_read = 1
      functionCode_write = 5
  
      # coils     :   0x0000  : fc=01 (read) fc=05 (write)
      # inputs    :   0x2710  : fc=02 (read)
      # inp.reg.  :   0x7530  : fc=04 (read)  
      # hold.reg. :   0x9C40  : fc=03 (read) fc=06 (write)
  
      values = context[slave["id"]].getValues(functionCode_read, slave["coils"])
      log.info("old contact values: " + str(values))
  
      for i in range(len(values)):
          if values[i] == 0:
              values[i] = 1 if (random.random() &gt;= 0.95) else 0
          else: # value is 1
              values[i] = 0 if (random.random() &gt;= 0.95) else 1
  
      log.info("new contact values: " + str(values))
      context[slave["id"]].setValues(functionCode_write, slave["coils"], values)
  
  
  def run_updating_server():
      # ----------------------------------------------------------------------- # 
      # initializing devices
      # ----------------------------------------------------------------------- # 
      temperature_slave = { # temperature sensor
          "id": 0x01, 
          "coils": 0x0000,
          "inputs": 0x2710,
          "input_registers": 0x7530,
          "holding_registers": 0x9C40
      }
      contact_slave = { # window sensor
          "id": 0x02,
          "coils": 0x0000,
          "inputs": 0x2710,
          "input_registers": 0x7530,
          "holding_registers": 0x9C40
      } 
  
      store = {
          temperature_slave["id"]: ModbusSlaveContext( 
              co=ModbusSequentialDataBlock(address=temperature_slave["coils"], values=[None]),                  # coils  / discrete outp. (adress=0)
              di=ModbusSequentialDataBlock(address=temperature_slave["inputs"], values=[None]),              # inputs / discrete input (adress=10000)
              ir=ModbusSequentialDataBlock(address=temperature_slave["input_registers"], values=[None]),     # input register / analog input (adress=30000)
              hr=ModbusSequentialDataBlock(address=temperature_slave["holding_registers"], values=[16]),   # hold. register / analog outp. (adress=40000)
              zero_mode=True),
          contact_slave["id"]: ModbusSlaveContext( 
              co=ModbusSequentialDataBlock(address=temperature_slave["coils"], values=[1]),               # coils  / discrete outp. (adress=0)
              di=ModbusSequentialDataBlock(address=temperature_slave["inputs"], values=[None]),              # inputs / discrete input (adress=10000)
              ir=ModbusSequentialDataBlock(address=temperature_slave["input_registers"], values=[None]),     # input register / analog input (adress=30000)
              hr=ModbusSequentialDataBlock(address=temperature_slave["holding_registers"], values=[None]),     # hold. register / analog outp. (adress=40000)
              zero_mode=True)
      } 
      context = ModbusServerContext(slaves=store, single=False)
  
      # ----------------------------------------------------------------------- # 
      # initialize the server information
      # ----------------------------------------------------------------------- # 
      identity = ModbusDeviceIdentification()
      identity.VendorName = 'raspi2b'
      identity.ProductCode = 'r2b'
      identity.VendorUrl = 'http://hs-mannheim.de'
      identity.ProductName = 'Pymodbus Slave-Server'
      identity.ModelName = '2b'
      identity.MajorMinorRevision = '1.0.0'
  
      # ----------------------------------------------------------------------- # 
      # run the server you want
      # ----------------------------------------------------------------------- # 
      loop_temperature = LoopingCall(f=update_temperature, kw={"context":context, "slave_info": temperature_slave}) 
      loop_temperature.start(20, now=False) # initially delay by 1 sec
  
      loop_contact = LoopingCall(f=update_window_contact, kw={"context":context, "slave_info": contact_slave}) 
      loop_contact.start(20, now=False) # initially delay by 1 sec
  
      StartTcpServer(context, identity=identity, address=("localhost", 5020))
  
  if __name__ == "__main__":
      run_updating_server()
  </code></pre>
  
  <p>It basically just updates temperature values and a window sensor's on/off-values.
  Now when I try to fetch the data vie the modbus master, which I again adapted from the pymodbus <a href="https://pymodbus.readthedocs.io/en/latest/source/example/synchronous_client.html" rel="nofollow noreferrer">synchronous client example</a> I get an error that says:</p>
  
  <blockquote>
    <p>'[Input/Output] Modbus Error: [Invalid Message] Incomplete message received, expected at least 8 bytes (0 received)'
    from the assert-statement in line 48 and 52</p>
  </blockquote>
  
  <p>Here's my client implementation:</p>
  
  <pre><code>#!/usr/bin/env python
  # --------------------------------------------------------------------------- #
  # import the various server implementations
  # --------------------------------------------------------------------------- #
  from pymodbus.client.sync import ModbusTcpClient as ModbusClient
  from influxdb import InfluxDBClient
  # --------------------------------------------------------------------------- #
  # configure the client logging
  # --------------------------------------------------------------------------- #
  import logging, json, time
  FORMAT = ('%(asctime)-15s %(threadName)-15s '
            '%(levelname)-8s %(module)-15s:%(lineno)-8s %(message)s')
  logging.basicConfig(format=FORMAT)
  log = logging.getLogger()
  log.setLevel(logging.INFO)
  
  
  def run_sync_client():
      # ------------------------------------------------------------------------#
      # choose the client you want
      # ------------------------------------------------------------------------#
      client = ModbusClient("localhost", port=5020) #'192.168.0.10'
      client.connect()
  
      # ------------------------------------------------------------------------#
      # specify slave to query
      # ------------------------------------------------------------------------#
      temperature_slave = { # temperature sensor
          "id": 0x01, 
          "coils": 0x0000,
          "inputs": 0x2710,
          "input_registers": 0x7530,
          "holding_registers": 0x9C40
      }
      contact_slave = { # window sensor
          "id": 0x02,
          "coils": 0x0000,
          "inputs": 0x2710,
          "input_registers": 0x7530,
          "holding_registers": 0x9C41
      } 
  
      # ----------------------------------------------------------------------- #
      # example requests
      # ----------------------------------------------------------------------- #
      log.debug("Read from a Coil")
      co_data = client.read_coils(address=contact_slave["coils"], count=1, SLAVE=contact_slave["id"])
      assert(not co_data.isError())     # test that we are not an error
  
      log.debug("Read holding registers")
      hr_data = client.read_holding_registers(address=temperature_slave["holding_registers"], count=1, SLAVE=temperature_slave["id"])
      assert(not hr_data.isError())     # test that we are not an error
  
      # ----------------------------------------------------------------------- #
      # close the client
      # ----------------------------------------------------------------------- #
      client.close()
  
  if __name__ == "__main__":
      run_sync_client()
  </code></pre>
  
  <p>I don't think I've <em>fully</em> understood the modbus protocol, so I have a hard time figuring out why this error occurs. If somebody could help me understand it better and ideally solve this issue I'd be really glad.</p>