ReST (Representational State Transfer) is an often used technique in distributed environments to simplify the data exchange between devices. It is used in web-services and is one possibility to achieve M2M (Machine-to-Machine) communication.
The S7 Web Server & user-defined pages
The web server can easily be configured in Step 7, by enabling it and adding "user-defined pages". Activating the user-defined pages inside the user program is done by moving the "WWW" data block from the "Instructions" side-pane into the current program block (TIA Portal).
The following code snipped shows a simple user-defined page, which displays two temperature values and the current states of digital output 0 and digital output 1:
- The first two lines are samples for awp-commands and tell the web server that these tags can be written by the user-defined application (through a http/s post, using a form or another client)
- :="webHMIData".webHMI_AI0_TempCels: is a tag name inside the PLC, and will be replaced by the web server with the current value when the HTML is rendered (requested by the client)
- The form "posts" data to the web server to change the tags' values
Now the idea becomes clear: the web server renders the HTML file and replaces the tags with their values. The ReST interface can be designed by omitting HTML syntax and instead using "JSON syntax" (or XML, etc.). The same applies, tag names will be replaced by their current values.
To distinguish between user-defined pages/apps (HTML files) and the API-interface, I decided to not indicate these "JSON" files as HTML files, instead I configured the TIA Portal and the files to be of the file type ".io" (can be seen in the picture above, the TIA Portal allows to define "Files with dynamic content").
In this case I have designed a simple API which responses with a JSON string containing four values:
- DO0 : status of the digital output 0
- DO1 : status of the digital output 1
- temp0 : temperature measured at the analogue input 0 (voltage was converted to temperature in the PLC's user program)
- temp1 : temperature measured at the analogue input 0 (voltage was converted to temperature in the PLC's user program)
In addition to just read these values, I wanted to be able to change DO0 and DO1 using a http post. The following file (api.io) represents my API and allows reading and writing:
Again, the first two lines allow to change the tags using a http post and the third line is the JSON string which will be returned when the client requests data (can be accessed using a web browser, as shown in the picture below).
A Python Client for the API
Now, that the API is defined properly, it is time to access the data which is provided. Using a web application as shown above is one option, using a client written in Python is another option and will be discussed here.
Reading data from the API (assuming no access-protection is configured in the PLC)
Just calling the API
http://192.168.178.50/awp/AnalogInputs/api.io and the requested data will be returned as a JSON string. The following code shows how to read and parse the data using python requests and the python json library.
Generally, in critical environments it is necessary to access the resources via HTTPS to ensure data encryption and data integrity. Therefore s7certfile is important to be set, this ensures to connect to the requested PLC and not to an eavesdropper or man-in-the-middle. The certificate (public key) can be downloaded from the S7 or can be extracted from the browser, once it accessed the PLC over HTTPS and added the certificate exception for unknown CA's. When exporting the certificate from Firefox (e.g.) it is important to include the CA's (see picture below), otherwise
session.get() will reject the certificate.
Writing data - modifying tag values (assuming no access-protection is configured in the PLC)
Writing data to the API/PLC (api.io) works the same way, instead of using
session.post() will be used. As an extra parameter, a json string will be passed, containing the payload (tag name and desired tag value).
The procedure shown above works fine when no access protection for the web server is configured in the PLC. This should not be the case for productive environments, there users and groups with eligible access rights should be defined.
When access restrictions and user-privileges are configured properly, the user-defined pages hide behind a login form, which will automatically be displayed when accessing the PLC using HTTP/HTTPS. This means, that the previous designed web API will not be accessible, as well. Hence, an authentication identifier needs to be passed together with either the
session.get() or the
session.post() method. Details about this, can be read in the next article: Logging into Simatic S7-1200 web API using a python client (Part 2)
Project Files & Download
The whole project webHMI-DataProvider can be downloaded here, it contains:
- DataProvider : Step 7 TIA V14 Project for the Simatic S7-1212C AC/DCRly implementing the above introduced API
- PythonS7FormLoginSample : Python sample code which demonstrates how to login through the web form displayed on the S7 welcome page using python requests
- Simatic-S7-webHMI-PyClient : Sample application (Visual Studio 2017 project, Python Tkinter) demonstrating how to login on the S7 and read & modify tags through the above introduced/implemented API
- webHMI : HTML, CSS and api.io files where the above introduced web application and API consist off
- The web server and project is access protected username and password required
- Username: WebUser
- Password (also valid for Step 7 TIA Project): 123456789