API¶
Devices¶
devices
module contains:
get
andset
physical process’s API methodssend
andreceive
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
.
- Devices with no networking capabilities have to set
- Ethernet/IP subset through
cpppo
, use idenip
- Mode 0: client only.
- Mode 1: tcp enip server.
- Ethernet/IP subset through
- Modbus through
pymodbus
, use idmodbus
- Mode 0: client only.
- Mode 1: tcp modbus server.
- Modbus through
- List of supported backends:
- Sqlite through
sqlite3
- Sqlite through
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 notNone
) is adict
containing 3 keys:name
: addresses a str identifying the protocol name (eg:enip
)mode
: int identifying the server mode (eg: mode equals1
)server
: ifmode
equals0
is empty,- otherwise it addresses a dict containing the server information such as its address, and a list of data to serve.
state
is adict
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
ifwhat
is not atuple
-
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
ifwhat
is not atuple
-
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
orTypeError
ifwhat
is not atuple
-
set
(what, value)[source]¶ Set (write) a physical process state value.
The
value
to be set (Eg: drive an actuator) is identified by thewhat
tuple, and it is assumed to be already initialize. Indeedset
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
ifwhat
is not atuple
-
-
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
-
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
-
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
-
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
-
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
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.