Skip to content
GitLab
Projects Groups Snippets
  • /
  • Help
    • Help
    • Support
    • Community forum
    • Submit feedback
    • Contribute to GitLab
  • Sign in
  • V VWS-Spielwiese
  • Project information
    • Project information
    • Activity
    • Labels
    • Members
  • Repository
    • Repository
    • Files
    • Commits
    • Branches
    • Tags
    • Contributors
    • Graph
    • Compare
  • Issues 0
    • Issues 0
    • List
    • Boards
    • Service Desk
    • Milestones
  • Merge requests 0
    • Merge requests 0
  • CI/CD
    • CI/CD
    • Pipelines
    • Jobs
    • Schedules
  • Deployments
    • Deployments
    • Environments
    • Releases
  • Packages and registries
    • Packages and registries
    • Package Registry
    • Container Registry
    • Infrastructure Registry
  • Monitor
    • Monitor
    • Incidents
  • Analytics
    • Analytics
    • Value stream
    • CI/CD
    • Repository
  • Wiki
    • Wiki
  • Snippets
    • Snippets
  • Activity
  • Graph
  • Create a new issue
  • Jobs
  • Commits
  • Issue Boards
Collapse sidebar
  • VWS-Demo
  • VWS-Spielwiese
  • Wiki
  • Implementation
  • Light Animator walkthrough

Light Animator walkthrough · Changes

Page history
Introduce subdirectories authored Feb 25, 2022 by Oliver Parczyk's avatar Oliver Parczyk
Hide whitespace changes
Inline Side-by-side
implementation/Light-Animator-walkthrough.md 0 → 100644
View page @ c8d85f61
Here, I'll walk you through the implementation of the [Light Animator](What-am-I-looking-at-here#light-animator). Additional startup procedures are explained in the documentation for the `start_component.sh` and the `run_demo.sh` scripts.
We'll skip the license headers, imports and comments, as they are either pretty much self explanatory or not the product of conscious development effort.
# ILightAnimator
The discussed file can be found [here](https://gitlab.hrz.tu-chemnitz.de/vws-demo/vws-spielwiese/-/blob/6d65d24412bda2e555e70a4f9581eb142096bd49/basyx.lichterkette/src/main/java/de/olipar/basyx/lichterkette/ILightAnimator.java).
This interface defines what methods a light animator has to provide:
| Method | Purpose |
| --------------------- | ---------------------------------------------------------------- |
| `staticLight()` | Instruct all found light controllers to turn on all their lights |
| `animation1()` | Orchestrate all found light controllers to play animation 1 |
| `animation2()` | Orchestrate all found light controllers to play animation 2 |
| `deactivate()` | Stop controlling any light controllers until reactivation |
| `updateControllers()` | Refresh the list of known light controllers to orchestrate |
| `isActive()` | Return whether this animator is active or not. |
# LightAnimator
The discussed file can be found [here](https://gitlab.hrz.tu-chemnitz.de/vws-demo/vws-spielwiese/-/blob/6d65d24412bda2e555e70a4f9581eb142096bd49/basyx.lichterkette/src/main/java/de/olipar/basyx/lichterkette/LightAnimator.java).
```java
public class LightAnimator implements ILightAnimator {
```
Just like the LightController, its currently the only implementation of its interface in this demo. It provides all the methods specified above.
```java
private boolean isActive = false;
private boolean isStaticLight = false;
private boolean isAnimation1 = false;
private boolean isAnimation2 = false;
private int animationState = 0;
```
It starts off very similar, too, by defining a few internal variables. Of note here is the `animationState`, which will be used to cycle through the animations defined later.
```java
private final double updatePeriod = 3.0D;
```
Similarly an update period is defined (in seconds). It is the minimum amount of time to be waited between applying state changes.
```java
private final AASRegistryProxy registry;
private ConnectedAssetAdministrationShellManager manager;
private List<ISubmodel> lightControllers = new LinkedList<ISubmodel>();
```
We also use a registry proxy and AAS Manager to fill our list of Submodels of light controllers, comparable to how the light controller fills its list of lights.
```java
private boolean isStale = true;
```
If this is set to true, the list of light controllers will be updated on the next main loop.
```java
public LightAnimator(final AASRegistryProxy registry) {
this.registry = registry;
this.manager = new ConnectedAssetAdministrationShellManager(registry);
```
Then, we enter the constructor. it sets the registry to the one given and with it instantiates an AAS manager.
```java
new Thread(() -> {
while (true) {
```
We then create our main work thread, which consists of the main loop of the animator.
```java
try {
Thread.sleep((long) (updatePeriod * 1000));
} catch (InterruptedException e) {
e.printStackTrace();
}
if (isActive) {
```
At the start, we wait for at least our defined `updatePeriod` seconds and if we're not active, just go back to sleep, like the light controller does, too.
```java
if (isStale) {
System.out.println("Controller list of this animator is stale. Updating...");
this.updateControllerList();
isStale = false;
}
```
If the list of light controllers is marked stale, it is being updated via the `updateControllerList()` method explained below.
We then enter a `try`-block. Inside, our possible states are executed accordingly, utilizing methods declared below. Note that when we are to orchestrate static lighting, `allLights()` is only called once, as the `animationState` is not set to zero but incremented.
Animation1 Switches on all lights, then only the red ones, then only the green ones and back to all lights on repeat.
Animation2 switches between blinking lights and all lights being switched on
```java
catch (ResourceNotFoundException e) {
if (!isStale) {
System.out.println("Invoking a controller failed. List will be updated on next update while active.");
}
isStale = true;
}
```
If we can't reach an endpoint, then we'll issue a warning and update our list of available controllers on the next iteration.
```java
}).start();
```
Then we start the work thread.
```java
private void activate() {
if (!isActive) {
System.out.println("Light animator activated");
isActive = true;
}
}
```
This method is used internally to log the activation of the light animator, if an animation or static lighting is invoked.
```java
private void redLight() {
for (ISubmodel controller : lightControllers) {
((IOperation) controller.getSubmodelElement("redLight")).invoke();
}
}
```
Following that, there are four methods defined, that are used inside the main loop to make it more readable. They encapsulate the actual incokation of the Operations exposed by the controllers.
```java
public void updateControllers() {
isStale = true;
}
```
This method is exposed by the interface to update the local list of available controllers. It sets `isStale` to `true`, causing an update on the next update period. This is to not cause concurrent modification of the list while iterating through it.
```java
public void updateControllerList() {
lightControllers.clear();
```
This method actually updates the list of controllers found in the environment. It starts by clearing the existing list.
```java
for (AASDescriptor iter : registry.lookupAll()) {
if (iter.getIdShort().contains("lightController")) {
```
We then look up all registered AAS and filter for those, whose idShort contains the string "lightController"
```java
for (SubmodelDescriptor controllerModel : iter.getSubmodelDescriptors()) {
if (controllerModel.getIdShort().equals("lightControllerSM")) {
```
Having found such, its Submodels are searched for one, whose shortId equals "lightControllerSM"
```java
ISubmodel submodel = manager.retrieveSubmodel(iter.getIdentifier(), controllerModel.getIdentifier());
lightControllers.add(submodel);
```
Now that we have found a compatible the AAS with a submodel we want, we use the manager to add it to our list.
This, too, could probably be done more elegantly by looking for implementations of Types of AAS and Submodels, but that is left to a possible [future project](TODO).
```java
public void animation1() {
activate();
isAnimation1 = true;
isAnimation2 = false;
isStaticLight = false;
animationState = 0;
}
```
Then, four methods like above are defined, setting internal states in order to expose the correct orchestration done in the main work loop.
These should be pretty much self explanatory.
Only thing of note here, is that upon deactivation, the light animator orchestrates all known light controllers to also deactivate.
# LightAnimatorSubmodelProvider
Please read the walkthrough of the [lightControllerSubmodelProvider](Light-Controller-walkthrough#lightcontrollersubmodelprovider). It only differs by assigned ids and in the number of Properties and Operations defined. It is also quite extensively commented, so this section would only be a repetition.
You can find the file [here](https://gitlab.hrz.tu-chemnitz.de/vws-demo/vws-spielwiese/-/blob/6d65d24412bda2e555e70a4f9581eb142096bd49/basyx.lichterkette/src/main/java/de/olipar/basyx/lichterkette/LightAnimatorSubmodelProvider.java).
\ No newline at end of file
Clone repository
  • Passwords
  • Proprietary Protocol
  • Raspberry Pi as WiFi AP
  • What am I looking at here
  • follow up II
    • Analysis of existing IIoT technologies
    • Display
    • RFID reader
  • follow up
    • C Sharp Module walkthrough
    • C Sharp Module
    • Demonstration Stand
    • Display
    • Dockerization
    • Sensors
    • Testing other registries
  • Home
View All Pages

Impressum · Nutzungsbedingungen · Datenschutz