A display and a script to show the data of the different sensors were already added as part of the first follow up. You can find the documentation here. Displaying the values was realized with a python script and a system service and no Basyx implementation existed for the LCD. Therefore, it was not possible to show a custom text. The display now is fully integrated into the Basyx environment and has its own AAS with invokable operations to do so.
## Implementation Basyx
The concept of the implementation is compareable to the one for the light or sensor implementation. An interface ```IDisplay``` as well as the class ```Display``` implementig it are used. The `LcdDisplayController` creates the displays and uses the `DisplaySubmodelProvider` to create, register and upload the AAS as well as host and register the submodules.
### General
While the Basyx part is written in Java, python scripts are used to access the LCD. The LCD is directly connected to the Raspberry Pi running the Basyx implementation. But it is possible to use another device to access the display and run the python scripts. In this case one Rasperry Pi could control multiple displays instead of one. The communication between the controller and the displays is realized with MQTT.
### IDisplay
The file can be found here. The interface includes these methods:
| Method | Purpose |
|-----|-----------|
| `displayText(String text)` | Display a custom text passed as argument. |
| `cycleSensorValues()` | Cycle through data of the sensors. |
### LcdDisplay
The file can be found here. The class implements the interface `IDisplay`.
```java
@Override
publicbooleandisplayText(Stringtext){
try{
publishMqtt("display/Lcd_0/text",text);
returntrue;
}
catch(Exceptione){
logger.error("Displaying text failed: ",e);
}
returnfalse;
}
```
```java
@Override
publicbooleancycleSensorValues(){
try{
publishMqtt("display/Lcd_0/cycle"," ");
returntrue;
}
catch(Exceptione){
logger.error("Start of cycling sensor values failed: ",e);
}
returnfalse;
}
```
In both methods a MQTT message is published using the corresponding topic. The argument of `displayText()` is passed on as payload of the message. The `mqtt_handler` listens for these messages and starts the respective python script.
Because an input variable is necessary to pass the text which will be displayed, a propterty is initialized and its modeling kind and value type are set. The defined function passes the first argument to `displayText()`. Using the function and the property the second operation is added to the submodel.
The created submodel is returned and used to host, upload and register it in the following step.
Because the `hostUploadAndRegister()` method is almost the same for all submodelProviders in this project, I moved it into a seperate class called `GeneralSubmodelProvider`. The `DisplaySubmodelProvider` extends this class and passes the created submodel for the LCD to the function of its super class.
## Implementation Python
### mqtt_handler.py
In this script, a paho MQTT client is implemented. Depending on the received message a corresponding python script for displaying something is started.
```python
brokerAddress=environ.get('MQTTBROKERHOST')
proc=None
```
The broker address is retrieved from the environment variable and an empty variable for the currently running process is defined.
```python
defon_connect(client,userdata,flags,rc):
client.subscribe("display/Lcd_0/cycle")
client.subscribe("display/Lcd_0/text")
```
The function is used to subscribe to the necessary topics.
The payload of the given message is decoded. Depending on the topic different processes are started. If a message with the topic `display/Lcd_0/cycle` is received, `cycle_lcd.py` will be run. If the topic is `display/Lcd_0/text`, `display_text_lcd.py` is started with the payload of the message as argument.
```python
client=mqtt.Client("display")
client.on_connect=on_connect
client.on_message=on_message
client.connect(brokerAddress)
client.loop_forever()
```
A MQTT client is initialized and the previous functions are assigned as on_connect and on_message. `on_connect` is executed when the client connects to the broker and `on_message` every time a message is received. The client connects to the broker and `client.loop_forever()` enables to run the script indefinitly. Furthermore, the function handles automatic reconnects.
### display_text_lcd.py
After setting all the pins and the settings for the LCD, text an be displayed.
```python
lines=sys.argv[1].split(',')
foridx,lineinenumerate(lines):
display.text(f"{line}",0,(idx)*8,1)
display.show()
```
The text to display is the second entry of the sys argv list. The input should be comma-separated. Each entry will be displayed in a new line. `display.show()` needs to be called. Otherwise nothing will be displayed.
### cycle_lcd.py
This script is the script `display.pi`. Nothing was changed.
## HTTP/REST
To for example invoke the cycle on a LCD called `Lcd_0` the following URL can be used for a POST request:
For displaying custom text use e.g.: ```http://main.local:4001/aasServer/shells/urn:de.olipar.basyx:lcd-monitor.local:Lcd_0/aas/submodels/display/submodel/submodelElements/displayText/invoke```
The json body should look like this:
```json
{
"requestId" : "1",
"inputArguments": [
{
"value": {
"idShort": "textToDisplay",
"valueType": "string",
"value": "theTextYouWantToDisplay",
"modelType": {
"name": "Property"
}
}
}
],
"timeout" : 5000
}
```
The second value parameter should contain the text to display. To show multiple lines of text, separate the parts by commas.