API

Devices

devices module contains:

  • get and set physical process’s API methods
  • send and receive network layer’s API methods
  • the user input validation code

Any device can be initialized with any couple of state and protocol dictionaries.

List of supported protocols and identifiers:
  • Devices with no networking capabilities have to set protocol equal
    to None.
  • Ethernet/IP subset through cpppo, use id enip
    • Mode 0: client only.
    • Mode 1: tcp enip server.
  • Modbus through pymodbus, use id modbus
    • Mode 0: client only.
    • Mode 1: tcp modbus server.
List of supported backends:
  • Sqlite through sqlite3

The consistency of the system should be guaranteed by the client, e.g., do NOT init two different PLCs referencing to two different states or speaking two different industrial protocols.

Device subclasses can be specialized overriding their public methods e.g., PLC pre_loop and main_loop methods.

class minicps.devices.Device(name, protocol, state, disk={}, memory={})[source]

Base class.

__init__(name, protocol, state, disk={}, memory={})[source]

Init a Device object.

Parameters:
  • name (str) – device name
  • protocol (dict) – used to set up the network layer API
  • state (dict) – used to set up the physical layer API
  • disk (dict) – persistent memory
  • memory (dict) – main memory

protocol (when is not None) is a dict containing 3 keys:

  • name: addresses a str identifying the protocol name (eg: enip)
  • mode: int identifying the server mode (eg: mode equals 1)
  • server: if mode equals 0 is empty,
    otherwise it addresses a dict containing the server information such as its address, and a list of data to serve.

state is a dict containing 2 keys:

  • path: full (LInux) path to the database (eg: /tmp/test.sqlite)
  • name: table name

Device construction example:

>>> device = Device(
>>>     name='dev',
>>>     protocol={
>>>         'name': 'enip',
>>>         'mode': 1,
>>>         'server': {
>>>             'address': '10.0.0.1',
>>>             'tags': (('SENSOR1', 1), ('SENSOR2', 1)),
>>>             }
>>>     state={
>>>         'path': '/path/to/db.sqlite',
>>>         'name': 'table_name',
>>>     }
>>> )
get(what)[source]

Get (read) a physical process state value.

Parameters:what (tuple) – field[s] identifier[s]
Returns:gotten value or TypeError if what is not a tuple
receive(what, address, **kwargs)[source]

Receive (read) a value from another network host.

kwargs dict is used to pass extra key-value pair according to the used protocol.

Parameters:
  • what (tuple) – field[s] identifier[s]
  • address (str) – ip[:port]
Returns:

received value or TypeError if what is not a tuple

send(what, value, address, **kwargs)[source]

Send (write) a value to another network host.

kwargs dict is used to pass extra key-value pair according to the used protocol.

Parameters:
  • what (tuple) – field[s] identifier[s]
  • value – value to be setted
  • address (str) – ip[:port]
Returns:

None or TypeError if what is not a tuple

set(what, value)[source]

Set (write) a physical process state value.

The value to be set (Eg: drive an actuator) is identified by the what tuple, and it is assumed to be already initialize. Indeed set is not able to create new physical process values.

Parameters:
  • what (tuple) – field[s] identifier[s]
  • value – value to be setted
Returns:

setted value or TypeError if what is not a tuple

class minicps.devices.HMI(name, protocol, state, disk={}, memory={})[source]

Human Machine Interface class.

HMI provides:
  • state APIs: e.g., get a water level indicator
  • network APIs: e.g., monitors a PLC’s tag
main_loop(sleep=0.5)[source]

HMI main loop.

Parameters:sleep (float) – second[s] to sleep after each iteration
class minicps.devices.PLC(name, protocol, state, disk={}, memory={})[source]

Programmable Logic Controller class.

PLC provides:
  • state APIs: e.g., drive an actuator
  • network APIs: e.g., communicate with another Device
main_loop(sleep=0.5)[source]

PLC main loop.

Parameters:sleep (float) – second[s] to sleep after each iteration
pre_loop(sleep=0.5)[source]

PLC boot process.

Parameters:sleep (float) – second[s] to sleep before returning
class minicps.devices.RTU(name, protocol, state, disk={}, memory={})[source]

RTU class.

RTU provides:
  • state APIs: e.g., drive an actuator
  • network APIs: e.g., communicate with another Device
main_loop(sleep=0.5)[source]

RTU main loop.

Parameters:sleep (float) – second[s] to sleep after each iteration
pre_loop(sleep=0.5)[source]

RTU boot process.

Parameters:sleep (float) – second[s] to sleep before returning
class minicps.devices.SCADAServer(name, protocol, state, disk={}, memory={})[source]

SCADAServer class.

SCADAServer provides:
  • state APIs: e.g., drive an actuator
  • network APIs: e.g., communicate with another Device
main_loop(sleep=0.5)[source]

SCADAServer main loop.

Parameters:sleep (float) – second[s] to sleep after each iteration
pre_loop(sleep=0.5)[source]

SCADAServer boot process.

Parameters:sleep (float) – second[s] to sleep before returning
class minicps.devices.Tank(name, protocol, state, section, level)[source]

Tank class.

Tank provides:
  • state APIs: e.g., set a water level indicator
__init__(name, protocol, state, section, level)[source]
Parameters:
  • name (str) – device name
  • protocol (dict) – used to set up the network layer API
  • state (dict) – used to set up the physical layer API
  • section (float) – cross section of the tank in m^2
  • level (float) – current level in m
main_loop(sleep=0.5)[source]

Tank main loop.

Parameters:sleep (float) – second[s] to sleep after each iteration
pre_loop(sleep=0.5)[source]

Tank pre_loop.

Parameters:sleep (float) – second[s] to sleep before returning

MiniCPS

MiniCPS is a container class, you can subclass it with a specialized version targeted for your CPS.

E.g., MyCPS(MiniCPS) once constructed runs an interactive simulation where each PLC device also run a webserver and the SCADA runs an FTP server.

class minicps.mcps.MiniCPS(name, net)[source]

Main container used to run the simulation.

__init__(name, net)[source]

MiniCPS initialization steps:

Parameters:
  • name (str) – CPS name
  • net (Mininet) – Mininet object
net object usually contains reference to:
  • the topology
  • the link shaping
  • the CPU allocation
  • the [remote] SDN controller