lewis.adapters.modbus

This module provides components to expose a Device via a Modbus-interface. The following resources were used as guidelines and references for implementing the protocol:

Note

For an example how Modbus can be used in the current implementation, please look at lewis/examples/modbus_device.

Members

MBEX

Modbus standard exception codes

ModbusAdapter

ModbusBasicDataBank

A basic ModbusDataBank instance.

ModbusDataBank

Preliminary DataBank implementation for Modbus.

ModbusDataStore

Convenience struct to hold the four types of DataBanks in Modbus

ModbusHandler

ModbusInterface

ModbusProtocol

This class implements the Modbus TCP Protocol.

ModbusServer

ModbusTCPFrame

This class models a frame of the Modbus TCP protocol.

class lewis.adapters.modbus.MBEX[source]

Bases: object

Modbus standard exception codes

class lewis.adapters.modbus.ModbusAdapter(options=None)[source]

Bases: Adapter

handle(cycle_delay=0.1) None[source]

This function is called on each cycle of a simulation. It should process requests that are made via the protocol that exposes the device. The time spent processing should be approximately cycle_delay seconds, during which the adapter may block the current process. It is desirable to stick to the provided time, but deviations are permissible if necessary due to the way the protocol works.

Parameters:

cycle_delay – Approximate time spent processing requests.

property is_running

This property indicates whether the Adapter’s server is running and listening. The result of calls to start_server() and stop_server() should be reflected as expected.

start_server() None[source]

This method must be re-implemented to start the infrastructure required for the protocol in question. These startup operations are not supposed to be carried out on construction of the adapter in order to preserve control over when services are started during a run of a simulation.

Note

This method may be called multiple times over the lifetime of the Adapter, so it is important to make sure that this does not cause problems.

See also

See stop_server() for shutting down the adapter.

stop_server() None[source]

This method must be re-implemented to stop and tear down anything that has been setup in start_server(). This method should close all connections to clients that have been established since the adapter has been started.

Note

This method may be called multiple times over the lifetime of the Adapter, so it is important to make sure that this does not cause problems.

class lewis.adapters.modbus.ModbusBasicDataBank(default_value=0, start_addr=0, last_addr=65535)[source]

Bases: ModbusDataBank

A basic ModbusDataBank instance.

This type of DataBank simply serves as a memory space for Modbus requests to read from and write to. It does not support binding addresses to attributes or functions of the device or interface. Example usage:

di = ModbusBasicDataBank(False, 0x1000, 0x1FFF)
Parameters:
  • default_value – Value to initialize memory with

  • start_addr – First valid address

  • last_addr – Last valid address

class lewis.adapters.modbus.ModbusDataBank(**kwargs)[source]

Bases: object

Preliminary DataBank implementation for Modbus.

This is a very generic implementation of a databank for Modbus. It’s meant to set the groundwork for future implementations. Only derived classes should be instantiated, not this class directly. The signature of this __init__ method is subject to change.

Parameters:

kwargs – Configuration

get(addr, count)[source]

Read list of count values at addr memory location in DataBank.

Parameters:
  • addr – Address to read from

  • count – Number of entries to retrieve

Returns:

list of entry values

Raises:

IndexError – Raised if address range falls outside valid range

set(addr, values) None[source]

Write list values to addr memory location in DataBank.

Parameters:
  • addr – Address to write to

  • values – list of values to write

Raises:

IndexError – Raised if address range falls outside valid range

class lewis.adapters.modbus.ModbusDataStore(di=None, co=None, ir=None, hr=None)[source]

Bases: object

Convenience struct to hold the four types of DataBanks in Modbus

class lewis.adapters.modbus.ModbusInterface[source]

Bases: InterfaceBase

property adapter

Adapter type that is required to process and expose interfaces of this type. Must be implemented in subclasses.

class lewis.adapters.modbus.ModbusProtocol(sender, datastore)[source]

Bases: object

This class implements the Modbus TCP Protocol.

The user of this class should provide a ModbusDataStore instance that will be used to fulfill read and write requests, and a callable sender which accepts one bytearray parameter. The sender will be called whenever a response frame is generated, with a bytearray containing the response frame as the parameter.

Processing occurs when the user calls ModbusProtocol.process(), passing in the raw frame data to process as a bytearray. The data may include multiple frames and partial frame fragments. Any data that could not be processed (due to incomplete frames) is buffered for the next call to process.

Parameters:
  • sender – callable that accepts one bytearray parameter, called to send responses.

  • datastore – ModbusDataStore instance to reference when processing requests

process(data, device_lock) None[source]

Process as much of given data as possible.

Any remainder, in case there is an incomplete frame at the end, is stored so that processing may continue where it left off when more data is provided.

Parameters:
  • data – Incoming byte data. Must be compatible with bytearray.

  • device_lock – threading.Lock instance that is acquired for device interaction.

class lewis.adapters.modbus.ModbusTCPFrame(stream=None)[source]

Bases: object

This class models a frame of the Modbus TCP protocol.

It may be a request, a response or an exception. Typically, requests are constructed using the init method, while responses and exceptions are constructed by called create_request or create_exception on an instance that is a request.

Note that data from the passed in bytearray stream is consumed. That is, bytes will be removed from the front of the bytearray if construction is successful.

Parameters:

stream – bytearray to consume data from to construct this frame.

Raises:

EOFError – Not enough data for complete frame; no data consumed.

create_exception(code)[source]

Create an exception frame based on this frame.

Parameters:

code – Modbus exception code to use for this exception

Returns:

ModbusTCPFrame instance that represents an exception

create_response(data=None)[source]

Create a response frame based on this frame.

Parameters:

data – Data section of response as bytearray. If None, request data section is kept.

Returns:

ModbusTCPFrame instance that represents a response

from_bytearray(stream) None[source]

Constructs this frame from input data stream, consuming as many bytes as necessary from the beginning of the stream.

If stream does not contain enough data to construct a complete modbus frame, an EOFError is raised and no data is consumed.

Parameters:

stream – bytearray to consume data from to construct this frame.

Raises:

EOFError – Not enough data for complete frame; no data consumed.

is_valid()[source]

Check integrity and validity of this frame.

Returns:

bool True if this frame is structurally valid.

to_bytearray()[source]

Convert this frame into its bytearray representation.

Returns:

bytearray representation of this frame.