initial
This commit is contained in:
58
Dockerfile
Executable file
58
Dockerfile
Executable file
@@ -0,0 +1,58 @@
|
|||||||
|
####
|
||||||
|
# This Dockerfile is used in order to build a container that runs the Quarkus application in JVM mode
|
||||||
|
#
|
||||||
|
# Before building the container image run:
|
||||||
|
#
|
||||||
|
# mvn package
|
||||||
|
#
|
||||||
|
# Then, build the image with:
|
||||||
|
#
|
||||||
|
# docker build -f src/main/docker/Dockerfile.jvm -t quarkus/rest-client-quickstart-jvm .
|
||||||
|
#
|
||||||
|
# Then run the container using:
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 quarkus/rest-client-quickstart-jvm
|
||||||
|
#
|
||||||
|
# If you want to include the debug port into your docker image
|
||||||
|
# you will have to expose the debug port (default 5005) like this : EXPOSE 8080 5050
|
||||||
|
#
|
||||||
|
# Then run the container using :
|
||||||
|
#
|
||||||
|
# docker run -i --rm -p 8080:8080 -p 5005:5005 -e JAVA_ENABLE_DEBUG="true" quarkus/rest-client-quickstart-jvm
|
||||||
|
#
|
||||||
|
###
|
||||||
|
#FROM artifactory.intern.gec.io/docker/eclipse-temurin:17-alpine
|
||||||
|
FROM nexus.alm.oncite.io/docker/ubi9/openjdk-21:1.20
|
||||||
|
#ARG RUN_JAVA_VERSION=1.3.8
|
||||||
|
|
||||||
|
ENV LANG='en_US.UTF-8' LANGUAGE='en_US:en'
|
||||||
|
|
||||||
|
# Install java and the run-java script
|
||||||
|
# Also set up permissions for user `1001`
|
||||||
|
#RUN apk add --no-cache curl ca-certificates \
|
||||||
|
# && mkdir /deployments \
|
||||||
|
# && chown 1001 /deployments \
|
||||||
|
# && chmod "g+rwX" /deployments \
|
||||||
|
# && chown 1001:root /deployments \
|
||||||
|
# && curl https://repo1.maven.org/maven2/io/fabric8/run-java-sh/${RUN_JAVA_VERSION}/run-java-sh-${RUN_JAVA_VERSION}-sh.sh -o /deployments/run-java.sh \
|
||||||
|
# && chown 1001 /deployments/run-java.sh \
|
||||||
|
# && chmod 540 /deployments/run-java.sh \
|
||||||
|
# && echo "securerandom.source=file:/dev/urandom" >> $JAVA_HOME/lib/security/java.security
|
||||||
|
|
||||||
|
# Configure the JAVA_OPTIONS, you can add -XshowSettings:vm to also display the heap size.
|
||||||
|
#ENV JAVA_OPTIONS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||||
|
|
||||||
|
COPY --chown=185 target/quarkus-app/lib/ /deployments/lib/
|
||||||
|
COPY --chown=185 target/quarkus-app/*.jar /deployments/
|
||||||
|
COPY --chown=185 target/quarkus-app/app/ /deployments/app/
|
||||||
|
COPY --chown=185 target/quarkus-app/quarkus/ /deployments/quarkus/
|
||||||
|
|
||||||
|
#EXPOSE 8080 5005
|
||||||
|
#USER 1001
|
||||||
|
|
||||||
|
#ENTRYPOINT [ "/deployments/run-java.sh" ]
|
||||||
|
|
||||||
|
EXPOSE 8080
|
||||||
|
USER 185
|
||||||
|
ENV JAVA_OPTS="-Dquarkus.http.host=0.0.0.0 -Djava.util.logging.manager=org.jboss.logmanager.LogManager"
|
||||||
|
ENV JAVA_APP_JAR="/deployments/quarkus-run.jar"
|
||||||
2
lombok.config
Executable file
2
lombok.config
Executable file
@@ -0,0 +1,2 @@
|
|||||||
|
config.stopBubbling = true
|
||||||
|
lombok.addLombokGeneratedAnnotation = true
|
||||||
370
pom.xml
Executable file
370
pom.xml
Executable file
@@ -0,0 +1,370 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||||
|
xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>io.gec.raw</groupId>
|
||||||
|
<artifactId>connector</artifactId>
|
||||||
|
<name>raw.connector</name>
|
||||||
|
<version>2.0.0-SNAPSHOT</version>
|
||||||
|
<properties>
|
||||||
|
<compiler-plugin.version>3.13.0</compiler-plugin.version>
|
||||||
|
<maven.compiler.parameters>true</maven.compiler.parameters>
|
||||||
|
<maven.compiler.release>21</maven.compiler.release>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||||
|
<quarkus.platform.group-id>io.quarkus.platform</quarkus.platform.group-id>
|
||||||
|
<quarkus.platform.version>3.14.4</quarkus.platform.version>
|
||||||
|
<surefire-plugin.version>3.5.1</surefire-plugin.version>
|
||||||
|
<timestamp>${maven.build.timestamp}</timestamp>
|
||||||
|
<maven.build.timestamp.format>yyyyMMddHHmm</maven.build.timestamp.format>
|
||||||
|
<lombok.version>1.18.34</lombok.version>
|
||||||
|
<maven-resources-plugin.version>3.3.1</maven-resources-plugin.version>
|
||||||
|
<mockito.version>5.14.1</mockito.version>
|
||||||
|
<sonar.jacoco.reportFile>${project.build.directory}/jacoco.exec</sonar.jacoco.reportFile>
|
||||||
|
<sonar.coverage.jacoco.xmlReportPaths>${project.build.directory}/site/jacoco/jacoco.xml</sonar.coverage.jacoco.xmlReportPaths>
|
||||||
|
<sonar.coverage.exclusions>**/entity/**/*,**/dto/**/*,**/domain/**/*,**/flyway/**/*</sonar.coverage.exclusions>
|
||||||
|
<mapstruct.version>1.6.2</mapstruct.version>
|
||||||
|
</properties>
|
||||||
|
<dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${quarkus.platform.group-id}</groupId>
|
||||||
|
<artifactId>${quarkus.platform.artifact-id}</artifactId>
|
||||||
|
<version>${quarkus.platform.version}</version>
|
||||||
|
<type>pom</type>
|
||||||
|
<scope>import</scope>
|
||||||
|
</dependency>
|
||||||
|
<!-- overwrite protobuf version due to high risk CVE-2024-7254 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.protobuf</groupId>
|
||||||
|
<artifactId>protobuf-java</artifactId>
|
||||||
|
<version>3.25.5</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
</dependencyManagement>
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-micrometer-registry-prometheus</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-hibernate-orm-panache</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-hibernate-orm</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-jdbc-postgresql</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-vertx</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-arc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-flyway</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-rest</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-rest-jackson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-rest-client</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-rest-client-jackson</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-config-yaml</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-cache</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-smallrye-health</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-scheduler</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-resources-plugin</artifactId>
|
||||||
|
<version>${maven-resources-plugin.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.flywaydb</groupId>
|
||||||
|
<artifactId>flyway-database-postgresql</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
<scope>provided</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- testing -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-junit5</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-junit5-mockito</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-codec</groupId>
|
||||||
|
<artifactId>commons-codec</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-test-security</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-jacoco</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.rest-assured</groupId>
|
||||||
|
<artifactId>rest-assured</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-core</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-inline</artifactId>
|
||||||
|
<version>5.2.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.mockito</groupId>
|
||||||
|
<artifactId>mockito-junit-jupiter</artifactId>
|
||||||
|
<version>${mockito.version}</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- external -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.snmp4j</groupId>
|
||||||
|
<artifactId>snmp4j</artifactId>
|
||||||
|
<version>3.8.2</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.snmp4j</groupId>
|
||||||
|
<artifactId>snmp4j-agent</artifactId>
|
||||||
|
<version>3.8.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-net</groupId>
|
||||||
|
<artifactId>commons-net</artifactId>
|
||||||
|
<version>3.11.1</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>jakarta.validation</groupId>
|
||||||
|
<artifactId>jakarta.validation-api</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.hierynomus</groupId>
|
||||||
|
<artifactId>sshj</artifactId>
|
||||||
|
<version>0.39.0</version>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>org.slf4j</groupId>
|
||||||
|
<artifactId>org.slf4j.impl.MavenSimpleLoggerFactory</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.quarkus</groupId>
|
||||||
|
<artifactId>quarkus-opentelemetry</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.opentelemetry.instrumentation</groupId>
|
||||||
|
<artifactId>opentelemetry-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<resources>
|
||||||
|
<resource>
|
||||||
|
<directory>src/main/resources</directory>
|
||||||
|
<filtering>true</filtering>
|
||||||
|
</resource>
|
||||||
|
</resources>
|
||||||
|
<pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<version>0.8.12</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</pluginManagement>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>${quarkus.platform.group-id}</groupId>
|
||||||
|
<artifactId>quarkus-maven-plugin</artifactId>
|
||||||
|
<version>${quarkus.platform.version}</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>build</goal>
|
||||||
|
<goal>generate-code</goal>
|
||||||
|
<goal>generate-code-tests</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>${compiler-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<compilerArgs>
|
||||||
|
<arg>-parameters</arg>
|
||||||
|
</compilerArgs>
|
||||||
|
<annotationProcessorPaths>
|
||||||
|
<path>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<version>${lombok.version}</version>
|
||||||
|
</path>
|
||||||
|
<path>
|
||||||
|
<groupId>org.mapstruct</groupId>
|
||||||
|
<artifactId>mapstruct-processor</artifactId>
|
||||||
|
<version>${mapstruct.version}</version>
|
||||||
|
</path>
|
||||||
|
</annotationProcessorPaths>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-surefire-plugin</artifactId>
|
||||||
|
<version>${surefire-plugin.version}</version>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
|
<maven.home>${maven.home}</maven.home>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-failsafe-plugin</artifactId>
|
||||||
|
<version>${surefire-plugin.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>integration-test</goal>
|
||||||
|
<goal>verify</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<systemPropertyVariables>
|
||||||
|
<native.image.path>${project.build.directory}/${project.build.finalName}-runner</native.image.path>
|
||||||
|
<java.util.logging.manager>org.jboss.logmanager.LogManager</java.util.logging.manager>
|
||||||
|
<maven.home>${maven.home}</maven.home>
|
||||||
|
</systemPropertyVariables>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.jacoco</groupId>
|
||||||
|
<artifactId>jacoco-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/entity/**/*</exclude>
|
||||||
|
<exclude>**/dto/*</exclude>
|
||||||
|
<exclude>**/domain/*</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>pre-unit-test</id>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<skip>${skip.tests}</skip>
|
||||||
|
<append>true</append>
|
||||||
|
<exclClassLoaders>*QuarkusClassLoader</exclClassLoaders>
|
||||||
|
<destFile>${sonar.jacoco.reportFile}</destFile>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>pre-integration-test</id>
|
||||||
|
<goals>
|
||||||
|
<goal>prepare-agent-integration</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<skip>${skip.it}</skip>
|
||||||
|
<append>true</append>
|
||||||
|
<exclClassLoaders>*QuarkusClassLoader</exclClassLoaders>
|
||||||
|
<destFile>${sonar.jacoco.reportFile}</destFile>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
<execution>
|
||||||
|
<id>coverage-report</id>
|
||||||
|
<phase>post-integration-test</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>report</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<dataFile>${sonar.jacoco.reportFile}</dataFile>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<profiles>
|
||||||
|
<profile>
|
||||||
|
<id>native</id>
|
||||||
|
<activation>
|
||||||
|
<property>
|
||||||
|
<name>native</name>
|
||||||
|
</property>
|
||||||
|
</activation>
|
||||||
|
<properties>
|
||||||
|
<skipITs>false</skipITs>
|
||||||
|
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||||
|
<quarkus.package.jar.enabled>false</quarkus.package.jar.enabled>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessConfig;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessPinConfig;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigDTO;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemValueDTO;
|
||||||
|
import io.gec.raw.connector.exception.entity.SftpException;
|
||||||
|
import io.gec.raw.connector.ftp.control.FtpController;
|
||||||
|
import io.gec.raw.connector.ftp.domain.SftpData;
|
||||||
|
import io.gec.raw.connector.device.control.DeviceController;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AccessConfigController {
|
||||||
|
@Inject
|
||||||
|
FtpController ftpController;
|
||||||
|
@Inject
|
||||||
|
DeviceController deviceController;
|
||||||
|
@Inject
|
||||||
|
AccessConfigProvider accessConfigProvider;
|
||||||
|
|
||||||
|
public void sendAccessConfig(AccessConfigDTO accessConfigDTO,
|
||||||
|
UUID commSvcDeviceId,
|
||||||
|
List<ConnectionWorkItemValueDTO> accessWorkItemValues) throws SftpException {
|
||||||
|
Device rootDevice = deviceController.getDeviceByCommSvcId(commSvcDeviceId);
|
||||||
|
SftpData sftpData = ftpController.createSftpData(accessWorkItemValues, rootDevice.getDeviceURL());
|
||||||
|
|
||||||
|
AccessConfig accessConfig = accessConfigProvider.generateAccessConfig(accessConfigDTO, rootDevice.getDescription());
|
||||||
|
|
||||||
|
for (AccessPinConfig accessPinConfig : accessConfig.getEmergencyPinConfigs()) {
|
||||||
|
ftpController.putEmergencyPinFile(sftpData, accessPinConfig);
|
||||||
|
}
|
||||||
|
for (AccessPinConfig accessPinConfig : accessConfig.getOneTimePinConfigs()) {
|
||||||
|
ftpController.putOneTimePinFile(sftpData, accessPinConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
ftpController.putAccessConfigFile(sftpData, accessConfig.getContent());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessCodeEntry;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessUserRole;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessCardCodeDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.CardCodeType;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.HandleDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.KeypadDTO;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AccessConfigConverter {
|
||||||
|
|
||||||
|
public List<AccessCodeEntry> convertToAccessCodeEntries(List<KeypadDTO> keypads) {
|
||||||
|
if (keypads == null) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, List<AccessCardCodeDTO>> accessCardCodesMap = new LinkedHashMap<>();
|
||||||
|
for (KeypadDTO keypadDTO : keypads) {
|
||||||
|
addToAccessCardCodesMap(keypadDTO.getHandles(), accessCardCodesMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<CardCodeType, Map<String, AccessCodeEntry>> accessConfigData = new LinkedHashMap<>();
|
||||||
|
processAccessCardCodes(accessCardCodesMap, accessConfigData);
|
||||||
|
|
||||||
|
return accessConfigData.values().stream()
|
||||||
|
.flatMap(accessCodeEntryMap -> accessCodeEntryMap.values().stream())
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addToAccessCardCodesMap(List<HandleDTO> handles, Map<String, List<AccessCardCodeDTO>> accessCardCodesMap) {
|
||||||
|
if (handles == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (HandleDTO handleDTO : handles) {
|
||||||
|
List<AccessCardCodeDTO> accessCardCodes = accessCardCodesMap.computeIfAbsent(
|
||||||
|
handleDTO.getAccessDeviceSerialNr(),
|
||||||
|
handleSerialNumber -> new ArrayList<>());
|
||||||
|
accessCardCodes.addAll(handleDTO.getAccessCardCodes());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processAccessCardCodes(Map<String, List<AccessCardCodeDTO>> accessCardCodesMap,
|
||||||
|
Map<CardCodeType, Map<String, AccessCodeEntry>> accessConfigData) {
|
||||||
|
for (Map.Entry<String, List<AccessCardCodeDTO>> cardCodeEntry : accessCardCodesMap.entrySet()) {
|
||||||
|
String handleSerialNumber = cardCodeEntry.getKey();
|
||||||
|
List<AccessCardCodeDTO> accessCardCodes = cardCodeEntry.getValue();
|
||||||
|
|
||||||
|
processAccessCardCodes(accessCardCodes, handleSerialNumber, accessConfigData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processAccessCardCodes(List<AccessCardCodeDTO> accessCardCodes,
|
||||||
|
String handleSerialNumber,
|
||||||
|
Map<CardCodeType, Map<String, AccessCodeEntry>> accessConfigData) {
|
||||||
|
boolean isEmergencyPinCodeEntryCreated = false;
|
||||||
|
boolean isOneTimePinCodeEntryCreated = false;
|
||||||
|
|
||||||
|
for (AccessCardCodeDTO accessCardCodeDTO : accessCardCodes) {
|
||||||
|
CardCodeType type = accessCardCodeDTO.getType();
|
||||||
|
|
||||||
|
// Additional protection - one handle can have a maximum of one emergency PIN and a maximum of one one-time PIN
|
||||||
|
// If such protection is not applied before the connector receives this access configuration
|
||||||
|
// then only the first cardCode (PIN) from the list will be used.
|
||||||
|
if (!canCreateAccessCodeEntry(type, isEmergencyPinCodeEntryCreated, isOneTimePinCodeEntryCreated)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
isEmergencyPinCodeEntryCreated |= type == CardCodeType.EMERGENCY_PIN;
|
||||||
|
isOneTimePinCodeEntryCreated |= type == CardCodeType.ONE_TIME_PIN;
|
||||||
|
|
||||||
|
String value = accessCardCodeDTO.getValue();
|
||||||
|
|
||||||
|
Map<String, AccessCodeEntry> accessCodeEntries = accessConfigData.computeIfAbsent(type, cardCodeType -> new LinkedHashMap<>());
|
||||||
|
AccessCodeEntry accessCodeEntry = accessCodeEntries.computeIfAbsent(value, cardCodeValue -> createAccessCodeEntry(accessCardCodeDTO));
|
||||||
|
|
||||||
|
accessCodeEntry.addHandleSerialNumber(handleSerialNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean canCreateAccessCodeEntry(CardCodeType type, boolean isEmergencyPinCodeEntryCreated, boolean isOneTimePinCodeEntryCreated) {
|
||||||
|
if (type == CardCodeType.EMERGENCY_PIN && isEmergencyPinCodeEntryCreated) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (type == CardCodeType.ONE_TIME_PIN && isOneTimePinCodeEntryCreated) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccessCodeEntry createAccessCodeEntry(AccessCardCodeDTO accessCardCodeDTO) {
|
||||||
|
AccessCodeEntry accessCodeEntry = new AccessCodeEntry();
|
||||||
|
accessCodeEntry.setType(accessCardCodeDTO.getType());
|
||||||
|
accessCodeEntry.setValue(accessCardCodeDTO.getValue());
|
||||||
|
accessCodeEntry.setUserName(accessCardCodeDTO.getUserName());
|
||||||
|
accessCodeEntry.setAccessUserRole(getAccessUserRole(accessCardCodeDTO.getUserRole()));
|
||||||
|
accessCodeEntry.setValidationPeriod(accessCardCodeDTO.getValidationPeriod());
|
||||||
|
accessCodeEntry.setFromDatetime(accessCardCodeDTO.getFromDatetime());
|
||||||
|
|
||||||
|
return accessCodeEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccessUserRole getAccessUserRole(String userRole) {
|
||||||
|
if (AccessUserRole.ACCESS_ACKNOWLEDGE.getRoleName().equals(userRole)) {
|
||||||
|
return AccessUserRole.ACCESS_ACKNOWLEDGE;
|
||||||
|
}
|
||||||
|
return AccessUserRole.ACCESS_USER;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,275 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessCodeEntry;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessConfig;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessUserRole;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.*;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.apache.commons.codec.digest.Sha2Crypt;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
|
import java.time.Instant;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AccessConfigProvider {
|
||||||
|
@Inject
|
||||||
|
AccessConfigConverter accessConfigConverter;
|
||||||
|
@Inject
|
||||||
|
Clock clock;
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
|
||||||
|
private static final String ACCESS_FILE_HEADER = """
|
||||||
|
#------------- Access-File CMC-III -----------------
|
||||||
|
# Name :
|
||||||
|
# Location :
|
||||||
|
# Contact :
|
||||||
|
# IPv4-Address :
|
||||||
|
""";
|
||||||
|
private static final String TYPE_CODE_CONTENT_PATTERN = "Key:%s; User:%s; Information:%s; Handle:%s";
|
||||||
|
private static final String TYPE_CARD_CONTENT_PATTERN = "Crd:%s; User:%s; Information:%s; Handle:%s";
|
||||||
|
private static final String TYPE_EMERGENCY_PIN_CONTENT_PATTERN = "Key:emgy%s; User:%s; Information:%s; Handle:%s";
|
||||||
|
private static final String TYPE_ONE_TIME_PIN_CONTENT_PATTERN = "Key:code%s; User:%s; Information:%s; Handle:%s";
|
||||||
|
private static final String DEVICE_DESCRIPTION = "V3.17.30_5";
|
||||||
|
|
||||||
|
// AccessConfigDTO contains Access configuration, deviceDescription is used for switching between different CMC/PDU Firmware versions
|
||||||
|
public AccessConfig generateAccessConfig(AccessConfigDTO accessConfigDTO, String deviceDescription) {
|
||||||
|
AccessConfig accessConfig = new AccessConfig();
|
||||||
|
|
||||||
|
List<AccessCodeEntry> accessCodeEntries = accessConfigConverter.convertToAccessCodeEntries(accessConfigDTO.getKeypads());
|
||||||
|
String accessFileContent = prepareAccessConfigFileContent(accessConfigDTO, accessConfig, accessCodeEntries, deviceDescription);
|
||||||
|
|
||||||
|
accessConfig.setContent(accessFileContent);
|
||||||
|
|
||||||
|
logger.infof("Access config generated for Mgmt Device (ID:'%s')", accessConfigDTO.getMgmtDeviceComponentId());
|
||||||
|
|
||||||
|
return accessConfig;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String prepareAccessConfigFileContent(AccessConfigDTO accessConfigDTO,
|
||||||
|
AccessConfig accessConfig,
|
||||||
|
List<AccessCodeEntry> accessCodeEntries,
|
||||||
|
String deviceDescription) {
|
||||||
|
/*return new StringBuilder()
|
||||||
|
.append(ACCESS_FILE_HEADER)
|
||||||
|
.append(generateOptions(accessConfigDTO.getOptions(), deviceDescription))
|
||||||
|
.append(generateAccessCodeEntries(accessCodeEntries, accessConfig))
|
||||||
|
.append(generateKeypads(accessConfigDTO.getKeypads())).toString();*/
|
||||||
|
|
||||||
|
return new StringBuilder()
|
||||||
|
.append(ACCESS_FILE_HEADER)
|
||||||
|
.append(generateOptions(accessConfigDTO.getOptions(), deviceDescription))
|
||||||
|
.append(generateAccessCodeEntries(accessCodeEntries, accessConfig)).toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateOptions(OptionsDTO options, String deviceDescription) {
|
||||||
|
if (options == null) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder optionsContent = new StringBuilder();
|
||||||
|
if (deviceDescription.contains(DEVICE_DESCRIPTION)) {
|
||||||
|
if (options.isFourEyes()) {
|
||||||
|
optionsContent.append(String.format("4-Eyes:1,%s", options.getFourEyesTimeout())).append("\n");
|
||||||
|
}
|
||||||
|
if (options.isTwoFactor()) {
|
||||||
|
optionsContent.append(String.format("2-Factor:1,%s", options.getTwoFactorTimeout())).append("\n");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (options.isFourEyes()) {
|
||||||
|
optionsContent.append(String.format("4-Eyes:%s", options.getFourEyesTimeout())).append("\n");
|
||||||
|
}
|
||||||
|
if (options.isTwoFactor()) {
|
||||||
|
optionsContent.append(String.format("2-Factor:%s", options.getTwoFactorTimeout())).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return optionsContent.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateAccessCodeEntries(List<AccessCodeEntry> accessCodeEntries, AccessConfig accessConfig) {
|
||||||
|
if (accessCodeEntries.isEmpty()) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder accessCodesContent = new StringBuilder();
|
||||||
|
|
||||||
|
for (AccessCodeEntry accessCodeEntry : accessCodeEntries) {
|
||||||
|
|
||||||
|
switch (accessCodeEntry.getType()) {
|
||||||
|
case CODE -> addAccessCodeEntryForCodeType(accessCodesContent, accessCodeEntry);
|
||||||
|
case CARD -> addAccessCodeEntryForCardType(accessCodesContent, accessCodeEntry);
|
||||||
|
case EMERGENCY_PIN -> addAccessCodeEntryForEmergencyPinType(accessCodesContent, accessCodeEntry, accessConfig);
|
||||||
|
case ONE_TIME_PIN -> addAccessCodeEntryForOneTimePinType(accessCodesContent, accessCodeEntry, accessConfig);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessCodesContent.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAccessCodeEntryForCodeType(StringBuilder accessCodesContent, AccessCodeEntry accessCodeEntry) {
|
||||||
|
addAccessCodeEntry(
|
||||||
|
accessCodesContent,
|
||||||
|
TYPE_CODE_CONTENT_PATTERN,
|
||||||
|
accessCodeEntry.getValue(),
|
||||||
|
accessCodeEntry.getAccessUserRole(),
|
||||||
|
accessCodeEntry.getUserName(),
|
||||||
|
accessCodeEntry.getHandleSerialNumbers());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAccessCodeEntryForCardType(StringBuilder accessCodesContent, AccessCodeEntry accessCodeEntry) {
|
||||||
|
// cardCode format in CMC and PDU is 8 digits + 8 leading zeros
|
||||||
|
final String cardCode = accessCodeEntry.getValue();
|
||||||
|
String cardCodeValue = cardCode.length() == 8
|
||||||
|
? "00000000" + cardCode
|
||||||
|
: cardCode;
|
||||||
|
|
||||||
|
addAccessCodeEntry(
|
||||||
|
accessCodesContent,
|
||||||
|
TYPE_CARD_CONTENT_PATTERN,
|
||||||
|
cardCodeValue,
|
||||||
|
accessCodeEntry.getAccessUserRole(),
|
||||||
|
accessCodeEntry.getUserName(),
|
||||||
|
accessCodeEntry.getHandleSerialNumbers());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAccessCodeEntryForEmergencyPinType(StringBuilder accessCodesContent, AccessCodeEntry accessCodeEntry, AccessConfig accessConfig) {
|
||||||
|
for (String handleSerialNumber : accessCodeEntry.getHandleSerialNumbers()) {
|
||||||
|
final String pinFileContent = generatePinFileContent(accessCodeEntry.getValue());
|
||||||
|
accessConfig.addEmergencyPinConfig(handleSerialNumber, pinFileContent);
|
||||||
|
|
||||||
|
/*addAccessCodeEntry(
|
||||||
|
accessCodesContent,
|
||||||
|
TYPE_EMERGENCY_PIN_CONTENT_PATTERN,
|
||||||
|
handleSerialNumber,
|
||||||
|
AccessUserRole.ACCESS_USER,
|
||||||
|
accessCodeEntry.getUserName(),
|
||||||
|
Set.of(handleSerialNumber));*/
|
||||||
|
|
||||||
|
addAccessCodeEntry(
|
||||||
|
accessCodesContent,
|
||||||
|
TYPE_EMERGENCY_PIN_CONTENT_PATTERN,
|
||||||
|
handleSerialNumber,
|
||||||
|
AccessUserRole.ACCESS_USER,
|
||||||
|
accessCodeEntry.getUserName(),
|
||||||
|
accessCodeEntry.getHandleSerialNumbers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAccessCodeEntryForOneTimePinType(StringBuilder accessCodesContent, AccessCodeEntry accessCodeEntry, AccessConfig accessConfig) {
|
||||||
|
for (String handleSerialNumber : accessCodeEntry.getHandleSerialNumbers()) {
|
||||||
|
OffsetDateTime startDateTime = Optional.ofNullable(accessCodeEntry.getFromDatetime()).orElseGet(() -> OffsetDateTime.now(clock));
|
||||||
|
long expirationTime = getExpirationTime(accessCodeEntry.getValidationPeriod(), startDateTime);
|
||||||
|
|
||||||
|
if (isTimeExpired(expirationTime)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
final String pinFileContent = generatePinFileContent(
|
||||||
|
accessCodeEntry.getValue(),
|
||||||
|
startDateTime.toInstant().toEpochMilli(),
|
||||||
|
expirationTime);
|
||||||
|
accessConfig.addOneTimePinConfig(handleSerialNumber, pinFileContent);
|
||||||
|
|
||||||
|
/*addAccessCodeEntry(
|
||||||
|
accessCodesContent,
|
||||||
|
TYPE_ONE_TIME_PIN_CONTENT_PATTERN,
|
||||||
|
handleSerialNumber,
|
||||||
|
AccessUserRole.ACCESS_USER,
|
||||||
|
accessCodeEntry.getUserName(),
|
||||||
|
Set.of(handleSerialNumber));*/
|
||||||
|
|
||||||
|
addAccessCodeEntry(
|
||||||
|
accessCodesContent,
|
||||||
|
TYPE_ONE_TIME_PIN_CONTENT_PATTERN,
|
||||||
|
handleSerialNumber,
|
||||||
|
AccessUserRole.ACCESS_USER,
|
||||||
|
accessCodeEntry.getUserName(),
|
||||||
|
accessCodeEntry.getHandleSerialNumbers());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addAccessCodeEntry(StringBuilder accessCodesContent,
|
||||||
|
String contentPattern,
|
||||||
|
String cardCodeValue,
|
||||||
|
AccessUserRole accessUserRole,
|
||||||
|
String userName,
|
||||||
|
Set<String> handleSerialNumbers) {
|
||||||
|
if (StringUtils.isNotEmpty(contentPattern) && StringUtils.isNotEmpty(cardCodeValue)) {
|
||||||
|
String handles = String.join(",", handleSerialNumbers);
|
||||||
|
|
||||||
|
accessCodesContent.append(contentPattern.formatted(
|
||||||
|
cardCodeValue,
|
||||||
|
accessUserRole.getRoleName(),
|
||||||
|
userName,
|
||||||
|
handles
|
||||||
|
)).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generateKeypads(List<KeypadDTO> keypads) {
|
||||||
|
if (keypads == null) {
|
||||||
|
return StringUtils.EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
StringBuilder keypadsContent = new StringBuilder();
|
||||||
|
|
||||||
|
for (KeypadDTO keypadDTO : keypads) {
|
||||||
|
List<HandleDTO> handles = keypadDTO.getHandles();
|
||||||
|
|
||||||
|
String handleSerialNumbersValue = Optional.ofNullable(handles).stream()
|
||||||
|
.flatMap(Collection::stream)
|
||||||
|
.map(HandleDTO::getAccessDeviceSerialNr)
|
||||||
|
.collect(Collectors.joining(","));
|
||||||
|
|
||||||
|
if (!handleSerialNumbersValue.isEmpty()) {
|
||||||
|
keypadsContent.append(String.format("Keypad:%s; Handle:%s",
|
||||||
|
keypadDTO.getAccessDeviceSerialNr(),
|
||||||
|
handleSerialNumbersValue)).append("\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return keypadsContent.toString().trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generatePinFileContent(String accessCardCodeValue) {
|
||||||
|
return generatePinFileContent(accessCardCodeValue, 0L, -1L);
|
||||||
|
}
|
||||||
|
|
||||||
|
private String generatePinFileContent(String accessCardCodeValue, long startDateTime, long expirationTime) {
|
||||||
|
long startDateTimeInSeconds = TimeUnit.MILLISECONDS.toSeconds(startDateTime);
|
||||||
|
long expirationTimeInSeconds = expirationTime >= 0
|
||||||
|
? TimeUnit.MILLISECONDS.toSeconds(expirationTime)
|
||||||
|
: -1L; // forever
|
||||||
|
|
||||||
|
return Sha2Crypt.sha256Crypt(accessCardCodeValue.getBytes()) + "\t%d\t%d".formatted(startDateTimeInSeconds, expirationTimeInSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
private long getExpirationTime(Integer validationPeriod, OffsetDateTime startDateTime) {
|
||||||
|
if (validationPeriod == null) {
|
||||||
|
return 0L; // one-time
|
||||||
|
}
|
||||||
|
if (validationPeriod == 0) {
|
||||||
|
return 0L; // one-time
|
||||||
|
}
|
||||||
|
if (validationPeriod < 0) {
|
||||||
|
return -1L; // forever
|
||||||
|
}
|
||||||
|
|
||||||
|
return startDateTime
|
||||||
|
.plusSeconds(TimeUnit.HOURS.toSeconds(validationPeriod))
|
||||||
|
.toInstant()
|
||||||
|
.toEpochMilli();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isTimeExpired(long expirationTime) {
|
||||||
|
return expirationTime > 0 && Instant.now(clock).toEpochMilli() > expirationTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessDbDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.HandleDbDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.KeypadDbDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.OptionDbDTO;
|
||||||
|
import io.gec.raw.connector.access.utils.ParserHelper;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.regex.MatchResult;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AccessDbConfigParser {
|
||||||
|
private static final String REGEX = "'(.*?)'";
|
||||||
|
private static final String NOT_SUPPORTED_ELEMENT_WITH_INDEX = "Not supported element with index: ";
|
||||||
|
|
||||||
|
private final Pattern pattern = Pattern.compile(REGEX, Pattern.MULTILINE);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParserHelper parserHelper;
|
||||||
|
|
||||||
|
public AccessDbDTO parseFileContent(Path filePath) throws IOException {
|
||||||
|
List<HandleDbDTO> handleList = new ArrayList<>();
|
||||||
|
List<KeypadDbDTO> keypadList = new ArrayList<>();
|
||||||
|
OptionDbDTO optionDTO = null;
|
||||||
|
|
||||||
|
try (BufferedReader br = new BufferedReader(new FileReader(filePath.toFile()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
if (line.contains("INSERT INTO Handles")) {
|
||||||
|
handleList.add(createHandleDTO(matcher.results()));
|
||||||
|
} else if (line.contains("INSERT INTO Keypads")) {
|
||||||
|
keypadList.add(createKeypadDTO(matcher.results()));
|
||||||
|
} else if (line.contains("INSERT INTO Options")) {
|
||||||
|
optionDTO = createOptionDTO(matcher.results());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessDbDTO accessDbDTO = new AccessDbDTO();
|
||||||
|
accessDbDTO.setHandles(handleList);
|
||||||
|
accessDbDTO.setKeypads(keypadList);
|
||||||
|
accessDbDTO.setOptions(optionDTO);
|
||||||
|
return accessDbDTO;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private OptionDbDTO createOptionDTO(Stream<MatchResult> results) {
|
||||||
|
OptionDbDTO optionDTO = new OptionDbDTO();
|
||||||
|
List<MatchResult> matchResultList = results.toList();
|
||||||
|
for (int i = 0; i < matchResultList.size(); i++) {
|
||||||
|
switch (i) {
|
||||||
|
case 0 -> optionDTO.setEyes4(parserHelper.toBoolean(matchResultList.get(i).group(1)));
|
||||||
|
case 1 -> optionDTO.setWay2(parserHelper.toBoolean(matchResultList.get(i).group(1)));
|
||||||
|
case 2 -> optionDTO.setTimeout1(Integer.parseInt(matchResultList.get(i).group(1)));
|
||||||
|
case 3 -> optionDTO.setTimeout2(Integer.parseInt(matchResultList.get(i).group(1)));
|
||||||
|
default -> throw new IllegalArgumentException(NOT_SUPPORTED_ELEMENT_WITH_INDEX + i + " in Options data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return optionDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private KeypadDbDTO createKeypadDTO(Stream<MatchResult> results) {
|
||||||
|
KeypadDbDTO keypadDTO = new KeypadDbDTO();
|
||||||
|
List<MatchResult> matchResultList = results.toList();
|
||||||
|
for (int i = 0; i < matchResultList.size(); i++) {
|
||||||
|
switch (i) {
|
||||||
|
case 0 -> keypadDTO.setKeypad(matchResultList.get(i).group(1));
|
||||||
|
case 1 -> keypadDTO.setHandleList(Arrays.asList(matchResultList.get(i).group(1).split(",")));
|
||||||
|
default -> throw new IllegalArgumentException(NOT_SUPPORTED_ELEMENT_WITH_INDEX + i + " in Keypads data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return keypadDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private HandleDbDTO createHandleDTO(Stream<MatchResult> results) {
|
||||||
|
HandleDbDTO handleDTO = new HandleDbDTO();
|
||||||
|
List<MatchResult> matchResultList = results.toList();
|
||||||
|
for (int i = 0; i < matchResultList.size(); i++) {
|
||||||
|
switch (i) {
|
||||||
|
case 0 -> handleDTO.setType(matchResultList.get(i).group(1));
|
||||||
|
case 1 -> handleDTO.setCode(matchResultList.get(i).group(1));
|
||||||
|
case 2 -> handleDTO.setUser(matchResultList.get(i).group(1));
|
||||||
|
case 3 -> handleDTO.setInformation(matchResultList.get(i).group(1));
|
||||||
|
case 4 -> handleDTO.setHandleList(Arrays.asList(matchResultList.get(i).group(1).split(",")));
|
||||||
|
default -> throw new IllegalArgumentException(NOT_SUPPORTED_ELEMENT_WITH_INDEX + i + " in Handles data");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return handleDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.CardCodeType;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AccessCodeEntry {
|
||||||
|
private CardCodeType type;
|
||||||
|
private String value;
|
||||||
|
private String userName;
|
||||||
|
private AccessUserRole accessUserRole;
|
||||||
|
private Integer validationPeriod;
|
||||||
|
private OffsetDateTime fromDatetime;
|
||||||
|
private Set<String> handleSerialNumbers;
|
||||||
|
|
||||||
|
public void addHandleSerialNumber(String handleSerialNumber) {
|
||||||
|
if (handleSerialNumbers == null) {
|
||||||
|
handleSerialNumbers = new LinkedHashSet<>();
|
||||||
|
}
|
||||||
|
handleSerialNumbers.add(handleSerialNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.domain;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class AccessConfig {
|
||||||
|
@Setter
|
||||||
|
private String content;
|
||||||
|
private final List<AccessPinConfig> emergencyPinConfigs = new ArrayList<>();
|
||||||
|
private final List<AccessPinConfig> oneTimePinConfigs = new ArrayList<>();
|
||||||
|
|
||||||
|
public void addEmergencyPinConfig(String pinIdentifier, String content) {
|
||||||
|
emergencyPinConfigs.add(new AccessPinConfig(pinIdentifier, content));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addOneTimePinConfig(String pinIdentifier, String content) {
|
||||||
|
oneTimePinConfigs.add(new AccessPinConfig(pinIdentifier, content));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemStatus;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItemResult;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class AccessConfigWorkItemResult extends WorkItemResult {
|
||||||
|
private final AccessConfigWorkItemStatus status;
|
||||||
|
|
||||||
|
public AccessConfigWorkItemResult(AccessConfigWorkItemStatus status, String message) {
|
||||||
|
super(message);
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessConfigWorkItemResult(AccessConfigWorkItemStatus status) {
|
||||||
|
this(status, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemStatus;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record AccessConfigWorkItemStatusWrapper(UUID workItemId, AccessConfigWorkItemStatus status, String message) {
|
||||||
|
public AccessConfigWorkItemStatusWrapper(UUID workItemId, AccessConfigWorkItemStatus status) {
|
||||||
|
this(workItemId, status, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.domain;
|
||||||
|
|
||||||
|
public record AccessPinConfig(String pinIdentifier, String content) {
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.domain;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum AccessUserRole {
|
||||||
|
ACCESS_USER("AccessUser"),
|
||||||
|
ACCESS_ACKNOWLEDGE("AccessAck");
|
||||||
|
|
||||||
|
private final String roleName;
|
||||||
|
|
||||||
|
AccessUserRole(String roleName) {
|
||||||
|
this.roleName = roleName;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AccessCardCodeDTO {
|
||||||
|
private CardCodeType type;
|
||||||
|
private String value;
|
||||||
|
private String userName;
|
||||||
|
private Integer validationPeriod;
|
||||||
|
private String userRole;
|
||||||
|
private OffsetDateTime fromDatetime;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AccessConfigDTO {
|
||||||
|
private UUID mgmtDeviceComponentId;
|
||||||
|
private OptionsDTO options;
|
||||||
|
private List<KeypadDTO> keypads;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItem;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AccessConfigWorkItemDTO extends WorkItem {
|
||||||
|
private UUID id;
|
||||||
|
private AccessConfigWorkItemStatus status;
|
||||||
|
private AccessConfigDTO config;
|
||||||
|
private ConnectionWorkItemDTO connectionWorkItem;
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
public enum AccessConfigWorkItemStatus {
|
||||||
|
CREATED, IN_PROGRESS, QUEUED, SUCCESS, DEVICE_CONFIG_FAILURE
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import lombok.ToString;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@ToString
|
||||||
|
public class AccessConfigWorkItemUpdateDTO {
|
||||||
|
|
||||||
|
private AccessConfigWorkItemStatus status;
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
@@ -0,0 +1,15 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class AccessDbDTO {
|
||||||
|
List<HandleDbDTO> handles;
|
||||||
|
List<KeypadDbDTO> keypads;
|
||||||
|
OptionDbDTO options;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
public enum CardCodeType {
|
||||||
|
CARD, CODE, ONE_TIME_PIN, EMERGENCY_PIN
|
||||||
|
}
|
||||||
13
src/main/java/io/gec/raw/connector/access/configworkitem/dto/HandleDTO.java
Executable file
13
src/main/java/io/gec/raw/connector/access/configworkitem/dto/HandleDTO.java
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class HandleDTO {
|
||||||
|
private String accessDeviceSerialNr;
|
||||||
|
private List<AccessCardCodeDTO> accessCardCodes;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class HandleDbDTO {
|
||||||
|
private String type;
|
||||||
|
private String code;
|
||||||
|
private String user;
|
||||||
|
private String information;
|
||||||
|
private List<String> handleList;
|
||||||
|
|
||||||
|
}
|
||||||
13
src/main/java/io/gec/raw/connector/access/configworkitem/dto/KeypadDTO.java
Executable file
13
src/main/java/io/gec/raw/connector/access/configworkitem/dto/KeypadDTO.java
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class KeypadDTO {
|
||||||
|
private String accessDeviceSerialNr;
|
||||||
|
private List<HandleDTO> handles;
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class KeypadDbDTO {
|
||||||
|
private String keypad;
|
||||||
|
private List<String> handleList;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class OptionDbDTO {
|
||||||
|
private boolean eyes4;
|
||||||
|
private boolean way2;
|
||||||
|
private int timeout1;
|
||||||
|
private int timeout2;
|
||||||
|
|
||||||
|
}
|
||||||
13
src/main/java/io/gec/raw/connector/access/configworkitem/dto/OptionsDTO.java
Executable file
13
src/main/java/io/gec/raw/connector/access/configworkitem/dto/OptionsDTO.java
Executable file
@@ -0,0 +1,13 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
public class OptionsDTO {
|
||||||
|
private boolean fourEyes;
|
||||||
|
private boolean twoFactor;
|
||||||
|
private int fourEyesTimeout;
|
||||||
|
private int twoFactorTimeout;
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.handler;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.control.AccessConfigController;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessConfigWorkItemResult;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemStatus;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.domain.AccessConfigWorkItemStatusWrapper;
|
||||||
|
import io.gec.raw.connector.job.domain.JobResult;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItemWrapper;
|
||||||
|
import io.gec.raw.connector.job.dto.JobAction;
|
||||||
|
import io.gec.raw.connector.job.dto.JobStatus;
|
||||||
|
import io.gec.raw.connector.job.dto.JobType;
|
||||||
|
import io.gec.raw.connector.job.handler.WorkItemHandler;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.enterprise.context.control.ActivateRequestContext;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AccessConfigJobHandler extends WorkItemHandler<AccessConfigWorkItemDTO, AccessConfigWorkItemResult> {
|
||||||
|
@Inject
|
||||||
|
AccessConfigController accessConfigController;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Optional<AccessConfigWorkItemDTO> getWorkItem(UUID workItemId) {
|
||||||
|
return communicationServiceController.fetchAccessConfigWorkItem(workItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startProcessing(WorkItemWrapper<AccessConfigWorkItemDTO> workItemWrapper) {
|
||||||
|
var accessConfigWorkItemStatus = new AccessConfigWorkItemStatusWrapper(workItemWrapper.workItemId(), AccessConfigWorkItemStatus.IN_PROGRESS);
|
||||||
|
updateAccessConfigWorkItemStatus(accessConfigWorkItemStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ActivateRequestContext
|
||||||
|
@Override
|
||||||
|
protected AccessConfigWorkItemResult processWorkItem(WorkItemWrapper<AccessConfigWorkItemDTO> workItemWrapper) {
|
||||||
|
try {
|
||||||
|
logger.infof("Processing AccessConfigWorkItem (ID:'%s') ...", workItemWrapper.workItemId());
|
||||||
|
AccessConfigWorkItemDTO workItem = workItemWrapper.workItem();
|
||||||
|
accessConfigController.sendAccessConfig(
|
||||||
|
workItem.getConfig(),
|
||||||
|
workItem.getConnectionWorkItem().getDeviceId(),
|
||||||
|
workItem.getConnectionWorkItem().getConnectionPropertyValues());
|
||||||
|
|
||||||
|
return new AccessConfigWorkItemResult(AccessConfigWorkItemStatus.SUCCESS);
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.errorf(e, "Processing AccessConfigWorkItem (ID:'%s') - FAILED", workItemWrapper.workItemId());
|
||||||
|
return new AccessConfigWorkItemResult(AccessConfigWorkItemStatus.DEVICE_CONFIG_FAILURE, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finishProcessing(WorkItemWrapper<AccessConfigWorkItemDTO> workItemWrapper, AccessConfigWorkItemResult workItemResult) {
|
||||||
|
var accessConfigWorkItemStatus = new AccessConfigWorkItemStatusWrapper(
|
||||||
|
workItemWrapper.workItemId(),
|
||||||
|
workItemResult.getStatus(),
|
||||||
|
workItemResult.getMessage());
|
||||||
|
updateAccessConfigWorkItemStatus(accessConfigWorkItemStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JobResult mapToJobResult(AccessConfigWorkItemResult workItemResult) {
|
||||||
|
var workItemStatus = workItemResult.getStatus();
|
||||||
|
|
||||||
|
var jobStatus = switch (workItemStatus) {
|
||||||
|
case SUCCESS -> JobStatus.DONE;
|
||||||
|
case DEVICE_CONFIG_FAILURE -> JobStatus.FAILED;
|
||||||
|
default -> throw new IllegalStateException("Mapping to job result failed, unexpected value: " + workItemStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new JobResult(jobStatus, workItemResult.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobType getJobType() {
|
||||||
|
return JobType.ACCESS_CONFIG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobAction getJobAction() {
|
||||||
|
return JobAction.SET;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAccessConfigWorkItemStatus(AccessConfigWorkItemStatusWrapper accessConfigWorkItemStatus) {
|
||||||
|
var accessConfigWorkItemUpdateDTO = new AccessConfigWorkItemUpdateDTO();
|
||||||
|
accessConfigWorkItemUpdateDTO.setStatus(accessConfigWorkItemStatus.status());
|
||||||
|
accessConfigWorkItemUpdateDTO.setMessage(accessConfigWorkItemStatus.message());
|
||||||
|
|
||||||
|
communicationServiceController.updateAccessConfigWorkItem(accessConfigWorkItemStatus.workItemId(), accessConfigWorkItemUpdateDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
44
src/main/java/io/gec/raw/connector/access/configworkitem/utils/Bcd.java
Executable file
44
src/main/java/io/gec/raw/connector/access/configworkitem/utils/Bcd.java
Executable file
@@ -0,0 +1,44 @@
|
|||||||
|
package io.gec.raw.connector.access.configworkitem.utils;
|
||||||
|
|
||||||
|
public class Bcd {
|
||||||
|
|
||||||
|
public String decimalToBcd(long num) {
|
||||||
|
if (num < 0) throw new IllegalArgumentException(
|
||||||
|
"The method decimalToBcd doesn't support negative numbers." +
|
||||||
|
" Invalid argument: " + num);
|
||||||
|
|
||||||
|
int digits = 0;
|
||||||
|
|
||||||
|
long temp = num;
|
||||||
|
while (temp != 0) {
|
||||||
|
digits++;
|
||||||
|
temp /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
int byteLen = digits % 2 == 0 ? digits / 2 : (digits + 1) / 2;
|
||||||
|
|
||||||
|
byte[] bcd = new byte[byteLen];
|
||||||
|
|
||||||
|
for (int i = 0; i < digits; i++) {
|
||||||
|
byte tmp = (byte) (num % 10);
|
||||||
|
|
||||||
|
if (i % 2 == 0) {
|
||||||
|
bcd[i / 2] = tmp;
|
||||||
|
} else {
|
||||||
|
bcd[i / 2] |= (byte) (tmp << 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
num /= 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < byteLen / 2; i++) {
|
||||||
|
byte tmp = bcd[i];
|
||||||
|
bcd[i] = bcd[byteLen - i - 1];
|
||||||
|
bcd[byteLen - i - 1] = tmp;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String(bcd);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package io.gec.raw.connector.access.connectionworkitem.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemStatus;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItemResult;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class ConnectionWorkItemResult extends WorkItemResult {
|
||||||
|
private final ConnectionWorkItemStatus status;
|
||||||
|
|
||||||
|
public ConnectionWorkItemResult(ConnectionWorkItemStatus status, String message) {
|
||||||
|
super(message);
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ConnectionWorkItemResult(ConnectionWorkItemStatus status) {
|
||||||
|
this(status, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package io.gec.raw.connector.access.connectionworkitem.dto;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItem;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ConnectionWorkItemDTO extends WorkItem {
|
||||||
|
|
||||||
|
private UUID protocolId;
|
||||||
|
|
||||||
|
private UUID deviceId;
|
||||||
|
|
||||||
|
private ConnectionWorkItemStatus status;
|
||||||
|
|
||||||
|
private List<ConnectionWorkItemValueDTO> connectionPropertyValues;
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
package io.gec.raw.connector.access.connectionworkitem.dto;
|
||||||
|
|
||||||
|
public enum ConnectionWorkItemStatus {
|
||||||
|
CREATED,
|
||||||
|
IN_PROGRESS,
|
||||||
|
QUEUED,
|
||||||
|
SUCCESS,
|
||||||
|
DEVICE_CONNECTION_FAILURE
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package io.gec.raw.connector.access.connectionworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ConnectionWorkItemUpdateDTO {
|
||||||
|
private ConnectionWorkItemStatus status;
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package io.gec.raw.connector.access.connectionworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class ConnectionWorkItemValueDTO {
|
||||||
|
|
||||||
|
private UUID protocolPropertyId;
|
||||||
|
|
||||||
|
private String protocolPropertyValue;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package io.gec.raw.connector.access.connectionworkitem.handler;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.domain.ConnectionWorkItemResult;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemStatus;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.exception.entity.SftpException;
|
||||||
|
import io.gec.raw.connector.ftp.control.FtpController;
|
||||||
|
import io.gec.raw.connector.job.domain.JobResult;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItemWrapper;
|
||||||
|
import io.gec.raw.connector.job.dto.JobAction;
|
||||||
|
import io.gec.raw.connector.job.dto.JobStatus;
|
||||||
|
import io.gec.raw.connector.job.dto.JobType;
|
||||||
|
import io.gec.raw.connector.job.handler.WorkItemHandler;
|
||||||
|
import io.gec.raw.connector.device.control.DeviceController;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.enterprise.context.control.ActivateRequestContext;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class CheckConnectionJobHandler extends WorkItemHandler<ConnectionWorkItemDTO, ConnectionWorkItemResult> {
|
||||||
|
@Inject
|
||||||
|
FtpController ftpController;
|
||||||
|
@Inject
|
||||||
|
DeviceController deviceController;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Optional<ConnectionWorkItemDTO> getWorkItem(UUID workItemId) {
|
||||||
|
return communicationServiceController.fetchAccessConnectionWorkItem(workItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startProcessing(WorkItemWrapper<ConnectionWorkItemDTO> workItemWrapper) {
|
||||||
|
updateAccessWorkItemStatus(workItemWrapper.workItemId(), ConnectionWorkItemStatus.IN_PROGRESS);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ActivateRequestContext
|
||||||
|
@Override
|
||||||
|
protected ConnectionWorkItemResult processWorkItem(WorkItemWrapper<ConnectionWorkItemDTO> workItemWrapper) {
|
||||||
|
logger.infof("Processing ConnectionWorkItem (ID:'%s') ...", workItemWrapper.workItemId());
|
||||||
|
ConnectionWorkItemStatus accessWorkItemStatus;
|
||||||
|
ConnectionWorkItemDTO workItem = workItemWrapper.workItem();
|
||||||
|
try {
|
||||||
|
Device rootDevice = deviceController.getDeviceByCommSvcId(workItem.getDeviceId());
|
||||||
|
|
||||||
|
accessWorkItemStatus = ftpController.checkSftpConnection(workItem.getConnectionPropertyValues(), rootDevice.getDeviceURL())
|
||||||
|
? ConnectionWorkItemStatus.SUCCESS
|
||||||
|
: ConnectionWorkItemStatus.DEVICE_CONNECTION_FAILURE;
|
||||||
|
} catch (SftpException e) {
|
||||||
|
accessWorkItemStatus = ConnectionWorkItemStatus.DEVICE_CONNECTION_FAILURE;
|
||||||
|
logger.errorf(e, "Processing ConnectionWorkItem (ID:'%s') - FAILED", workItemWrapper.workItemId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return new ConnectionWorkItemResult(accessWorkItemStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finishProcessing(WorkItemWrapper<ConnectionWorkItemDTO> workItemWrapper, ConnectionWorkItemResult workItemResult) {
|
||||||
|
updateAccessWorkItemStatus(workItemWrapper.workItemId(), workItemResult.getStatus());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JobResult mapToJobResult(ConnectionWorkItemResult workItemResult) {
|
||||||
|
var workItemStatus = workItemResult.getStatus();
|
||||||
|
|
||||||
|
var jobStatus = switch (workItemStatus) {
|
||||||
|
case SUCCESS -> JobStatus.DONE;
|
||||||
|
case DEVICE_CONNECTION_FAILURE -> JobStatus.FAILED;
|
||||||
|
default -> throw new IllegalStateException("Mapping to job result failed, unexpected value: " + workItemStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new JobResult(jobStatus, workItemResult.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobType getJobType() {
|
||||||
|
return JobType.ACCESS_CONNECTION;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobAction getJobAction() {
|
||||||
|
return JobAction.EXECUTE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateAccessWorkItemStatus(UUID workItemId, ConnectionWorkItemStatus accessWorkItemStatus) {
|
||||||
|
var accessWorkItemUpdateDTO = new ConnectionWorkItemUpdateDTO();
|
||||||
|
accessWorkItemUpdateDTO.setStatus(accessWorkItemStatus);
|
||||||
|
|
||||||
|
communicationServiceController.updateAccessConnectionWorkItem(workItemId, accessWorkItemUpdateDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,225 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.AccessLogDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.AccessLogItemDTO;
|
||||||
|
import io.gec.raw.connector.access.utils.ParserHelper;
|
||||||
|
import io.gec.raw.connector.device.control.DeviceController;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.FileReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AccessLogParser {
|
||||||
|
private static final String REGEX_CMC =
|
||||||
|
"(((\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d)*\\+(\\d{2}):(\\d{2}))(.*))((Device (\\d+))\\s\\(([^\\(]*)\\)[:|\\s](.*))";
|
||||||
|
private static final String REGEX_CMC_ACCESS_CONFIG_MESSAGE =
|
||||||
|
"(((\\d{4})-(\\d{2})-(\\d{2})T(\\d{2}):(\\d{2}):(\\d{2})\\.(\\d)*\\+(\\d{2}):(\\d{2}))(.*))(Access\\sConfiguration(.*))";
|
||||||
|
|
||||||
|
private static final String REGEX_CMC3_V1 = "((\\d{4})-(\\d{2})-(\\d{2})/(\\d{2}):(\\d{2}):(\\d{2}))(.*)((Device (\\d+))\\s\\(([^\\(]*)\\)[:|\\s](.*))";
|
||||||
|
private static final String REGEX_CMC3_V2 = "((\\d{2})\\.(\\d{2})\\.(\\d{4})/(\\d{2}):(\\d{2}):(\\d{2}))(.*)((Device (\\d+))\\s\\(([^\\(]*)\\)[:|\\s](.*))";
|
||||||
|
private static final String REGEX_CMC3_ACCESS_CONFIG_MESSAGE_V1 = "((\\d{4})-(\\d{2})-(\\d{2})/(\\d{2}):(\\d{2}):(\\d{2}))(.*)(Configuration(.*))";
|
||||||
|
private static final String REGEX_CMC3_ACCESS_CONFIG_MESSAGE_V2 = "((\\d{2})\\.(\\d{2})\\.(\\d{4})/(\\d{2}):(\\d{2}):(\\d{2}))(.*)(Configuration(.*))";
|
||||||
|
|
||||||
|
private static final int CMC_DATE_TIME_INDEX = 2;
|
||||||
|
private static final int CMC_DEVICE_NAME_INDEX = 14;
|
||||||
|
private static final int CMC_DEVICE_NUMBER_INDEX = 15;
|
||||||
|
private static final int CMC_DEVICE_DESCRIPTION_INDEX = 16;
|
||||||
|
private static final int CMC_MESSAGE_INDEX = 17;
|
||||||
|
private static final int CMC_CONFIG_MESSAGE_INDEX = 13;
|
||||||
|
|
||||||
|
private static final int CMC3_DATE_TIME_INDEX = 1;
|
||||||
|
private static final int CMC3_DEVICE_NAME_INDEX = 10;
|
||||||
|
private static final int CMC3_DEVICE_NUMBER_INDEX = 11;
|
||||||
|
private static final int CMC3_DEVICE_DESCRIPTION_INDEX = 12;
|
||||||
|
private static final int CMC3_MESSAGE_INDEX = 13;
|
||||||
|
private static final int CMC3_CONFIG_MESSAGE_INDEX = 9;
|
||||||
|
|
||||||
|
private final Pattern patternCmc = Pattern.compile(REGEX_CMC, Pattern.MULTILINE);
|
||||||
|
private final Pattern patternAccessConfigCmcMessage = Pattern.compile(REGEX_CMC_ACCESS_CONFIG_MESSAGE, Pattern.MULTILINE);
|
||||||
|
|
||||||
|
private final Pattern patternCmc3V1 = Pattern.compile(REGEX_CMC3_V1, Pattern.MULTILINE);
|
||||||
|
private final Pattern patternCmc3V2 = Pattern.compile(REGEX_CMC3_V2, Pattern.MULTILINE);
|
||||||
|
private final Pattern patternAccessConfigCmc3MessageV1 = Pattern.compile(REGEX_CMC3_ACCESS_CONFIG_MESSAGE_V1, Pattern.MULTILINE);
|
||||||
|
private final Pattern patternAccessConfigCmc3MessageV2 = Pattern.compile(REGEX_CMC3_ACCESS_CONFIG_MESSAGE_V2, Pattern.MULTILINE);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ParserHelper parserHelper;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
DeviceController deviceController;
|
||||||
|
|
||||||
|
public AccessLogDTO parseCmcFileContent(Path filePath,
|
||||||
|
OffsetDateTime fromDateTime,
|
||||||
|
UUID rootDeviceId,
|
||||||
|
List<Integer> deviceNumberList) throws IOException {
|
||||||
|
List<AccessLogItemDTO> accessLogItems = new ArrayList<>();
|
||||||
|
HashMap<Integer, Device> devicesMap = new HashMap<>();
|
||||||
|
|
||||||
|
try (BufferedReader br = new BufferedReader(new FileReader(filePath.toFile()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
Matcher matcher = patternCmc.matcher(line);
|
||||||
|
if (matcher.find()) {
|
||||||
|
OffsetDateTime dateTime = parserHelper.getOffsetDateTimeFromString(matcher.group(CMC_DATE_TIME_INDEX));
|
||||||
|
|
||||||
|
if (!dateTime.isBefore(fromDateTime)
|
||||||
|
&& deviceNumberList.contains(Integer.parseInt(matcher.group(CMC_DEVICE_NUMBER_INDEX)))) {
|
||||||
|
accessLogItems.add(createAccessLogItemDTO(matcher, false, dateTime, rootDeviceId, devicesMap));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Matcher matcherAccessConfigMessage = patternAccessConfigCmcMessage.matcher(line);
|
||||||
|
if (matcherAccessConfigMessage.find()) {
|
||||||
|
OffsetDateTime dateTime = parserHelper.getOffsetDateTimeFromString(matcherAccessConfigMessage.group(CMC_DATE_TIME_INDEX));
|
||||||
|
|
||||||
|
if (!dateTime.isBefore(fromDateTime)) {
|
||||||
|
accessLogItems.add(createAccessLogItemDTOForConfigMessage(matcherAccessConfigMessage, false, dateTime));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessLogDTO accessLogDTO = new AccessLogDTO();
|
||||||
|
accessLogDTO.setAccessLogItems(accessLogItems);
|
||||||
|
|
||||||
|
return accessLogDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessLogDTO parseCmc3FileContent(Path filePath,
|
||||||
|
OffsetDateTime fromDateTime,
|
||||||
|
UUID rootDeviceId,
|
||||||
|
List<Integer> deviceNumberList) throws IOException {
|
||||||
|
List<AccessLogItemDTO> accessLogItems = new ArrayList<>();
|
||||||
|
HashMap<Integer, Device> devicesMap = new HashMap<>();
|
||||||
|
String dateTimeFormat = null;
|
||||||
|
|
||||||
|
try (BufferedReader br = new BufferedReader(new FileReader(filePath.toFile()))) {
|
||||||
|
String line;
|
||||||
|
while ((line = br.readLine()) != null) {
|
||||||
|
boolean accessLogEntry = false;
|
||||||
|
Optional<Matcher> matcherOptional = findMatcher(line, patternCmc3V1, patternCmc3V2);
|
||||||
|
|
||||||
|
if (matcherOptional.isPresent()) {
|
||||||
|
accessLogEntry = true;
|
||||||
|
} else {
|
||||||
|
matcherOptional = findMatcher(line, patternAccessConfigCmc3MessageV1, patternAccessConfigCmc3MessageV2);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matcherOptional.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Matcher matcher = matcherOptional.get();
|
||||||
|
|
||||||
|
dateTimeFormat = dateTimeFormat != null ? dateTimeFormat : getDateTimeFormat(matcher.pattern());
|
||||||
|
OffsetDateTime dateTime = parserHelper.parseDateTime(matcher.group(CMC3_DATE_TIME_INDEX), dateTimeFormat);
|
||||||
|
|
||||||
|
if (accessLogEntry) {
|
||||||
|
tryToAddAccessLogCmc3(matcher, fromDateTime, dateTime, rootDeviceId, deviceNumberList, devicesMap, accessLogItems);
|
||||||
|
} else {
|
||||||
|
tryToAddAccessConfigLogCmc3(matcher, fromDateTime, dateTime, accessLogItems);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AccessLogDTO accessLogDTO = new AccessLogDTO();
|
||||||
|
accessLogDTO.setAccessLogItems(accessLogItems);
|
||||||
|
|
||||||
|
return accessLogDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<Matcher> findMatcher(String line, Pattern... patterns) {
|
||||||
|
if (patterns == null) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
for (Pattern pattern : patterns) {
|
||||||
|
Matcher matcher = pattern.matcher(line);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
return Optional.of(matcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getDateTimeFormat(Pattern pattern) {
|
||||||
|
if (patternCmc3V2.equals(pattern) || patternAccessConfigCmc3MessageV2.equals(pattern)) {
|
||||||
|
return ParserHelper.DATETIME_DAY_MONTH_YEAR_WITH_DOTS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ParserHelper.DATETIME_YEAR_MONTH_DAY_WITH_HYPHENS;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryToAddAccessLogCmc3(Matcher matcher,
|
||||||
|
OffsetDateTime fromDateTime,
|
||||||
|
OffsetDateTime currentDateTime,
|
||||||
|
UUID rootDeviceId,
|
||||||
|
List<Integer> deviceNumberList,
|
||||||
|
HashMap<Integer, Device> devicesMap,
|
||||||
|
List<AccessLogItemDTO> accessLogItems) {
|
||||||
|
if (currentDateTime.isBefore(fromDateTime)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!deviceNumberList.contains(Integer.parseInt(matcher.group(CMC3_DEVICE_NUMBER_INDEX)))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
accessLogItems.add(createAccessLogItemDTO(matcher, true, currentDateTime, rootDeviceId, devicesMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void tryToAddAccessConfigLogCmc3(Matcher matcher,
|
||||||
|
OffsetDateTime fromDateTime,
|
||||||
|
OffsetDateTime currentDateTime,
|
||||||
|
List<AccessLogItemDTO> accessLogItems) {
|
||||||
|
if (currentDateTime.isBefore(fromDateTime)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
accessLogItems.add(createAccessLogItemDTOForConfigMessage(matcher, true, currentDateTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccessLogItemDTO createAccessLogItemDTOForConfigMessage(Matcher matcher, boolean isCmc3, OffsetDateTime currentDateTime) {
|
||||||
|
AccessLogItemDTO accessLogItemDTO = new AccessLogItemDTO();
|
||||||
|
accessLogItemDTO.setDateTime(currentDateTime);
|
||||||
|
accessLogItemDTO.setMessage(matcher.group(isCmc3 ? CMC3_CONFIG_MESSAGE_INDEX : CMC_CONFIG_MESSAGE_INDEX));
|
||||||
|
return accessLogItemDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccessLogItemDTO createAccessLogItemDTO(Matcher matcher,
|
||||||
|
boolean isCmc3,
|
||||||
|
OffsetDateTime currentDateTime,
|
||||||
|
UUID rootDeviceId,
|
||||||
|
HashMap<Integer, Device> devicesMap) {
|
||||||
|
AccessLogItemDTO accessLogItemDTO = new AccessLogItemDTO();
|
||||||
|
accessLogItemDTO.setDateTime(currentDateTime);
|
||||||
|
accessLogItemDTO.setDeviceName(matcher.group(isCmc3 ? CMC3_DEVICE_NAME_INDEX : CMC_DEVICE_NAME_INDEX));
|
||||||
|
int deviceNumber = Integer.parseInt(matcher.group(isCmc3 ? CMC3_DEVICE_NUMBER_INDEX : CMC_DEVICE_NUMBER_INDEX));
|
||||||
|
accessLogItemDTO.setDeviceNumber(deviceNumber);
|
||||||
|
accessLogItemDTO.setDeviceDescription(
|
||||||
|
matcher.group(isCmc3 ? CMC3_DEVICE_DESCRIPTION_INDEX : CMC_DEVICE_DESCRIPTION_INDEX));
|
||||||
|
accessLogItemDTO.setMessage(matcher.group(isCmc3 ? CMC3_MESSAGE_INDEX : CMC_MESSAGE_INDEX));
|
||||||
|
Device device;
|
||||||
|
if (devicesMap.containsKey(deviceNumber)) {
|
||||||
|
device = devicesMap.get(deviceNumber);
|
||||||
|
} else {
|
||||||
|
device = deviceController.getDeviceByDeviceIndex(rootDeviceId, deviceNumber);
|
||||||
|
devicesMap.put(deviceNumber, device);
|
||||||
|
}
|
||||||
|
if (device != null) {
|
||||||
|
accessLogItemDTO.setDeviceId(device.getCommServiceId());
|
||||||
|
}
|
||||||
|
|
||||||
|
return accessLogItemDTO;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemStatus;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItemResult;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class AccessLogWorkItemResult extends WorkItemResult {
|
||||||
|
private final LogWorkItemStatus status;
|
||||||
|
|
||||||
|
public AccessLogWorkItemResult(LogWorkItemStatus status, String message) {
|
||||||
|
super(message);
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public AccessLogWorkItemResult(LogWorkItemStatus status) {
|
||||||
|
this(status, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemStatus;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public record AccessLogWorkItemStatusWrapper(UUID workItemId, LogWorkItemStatus status, String message) {
|
||||||
|
public AccessLogWorkItemStatusWrapper(UUID workItemId, LogWorkItemStatus status) {
|
||||||
|
this(workItemId, status, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/java/io/gec/raw/connector/access/logworkitem/dto/AccessLogDTO.java
Executable file
15
src/main/java/io/gec/raw/connector/access/logworkitem/dto/AccessLogDTO.java
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AccessLogDTO {
|
||||||
|
UUID workItemId;
|
||||||
|
List<AccessLogItemDTO> accessLogItems;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class AccessLogItemDTO {
|
||||||
|
private OffsetDateTime dateTime;
|
||||||
|
private UUID deviceId;
|
||||||
|
private String deviceName;
|
||||||
|
private int deviceNumber;
|
||||||
|
private String deviceDescription;
|
||||||
|
private String message;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.dto;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItem;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class LogWorkItemDTO extends WorkItem {
|
||||||
|
private UUID id;
|
||||||
|
private ConnectionWorkItemDTO connectionWorkItem;
|
||||||
|
private LogWorkItemStatus status;
|
||||||
|
private OffsetDateTime dateFrom;
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.dto;
|
||||||
|
|
||||||
|
public enum LogWorkItemStatus {
|
||||||
|
CREATED,
|
||||||
|
IN_PROGRESS,
|
||||||
|
DONE,
|
||||||
|
DEVICE_ACCESS_FAILURE,
|
||||||
|
LOG_FETCH_FAILURE,
|
||||||
|
LOG_PARSE_FAILURE
|
||||||
|
}
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class LogWorkItemUpdateDTO {
|
||||||
|
|
||||||
|
private LogWorkItemStatus status;
|
||||||
|
private String message;
|
||||||
|
}
|
||||||
@@ -0,0 +1,120 @@
|
|||||||
|
package io.gec.raw.connector.access.logworkitem.handler;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.logworkitem.domain.AccessLogWorkItemResult;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.domain.AccessLogWorkItemStatusWrapper;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.AccessLogDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemStatus;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.communicationservice.exception.CommunicationServiceException;
|
||||||
|
import io.gec.raw.connector.exception.entity.SftpException;
|
||||||
|
import io.gec.raw.connector.ftp.control.FtpController;
|
||||||
|
import io.gec.raw.connector.job.domain.JobResult;
|
||||||
|
import io.gec.raw.connector.job.domain.WorkItemWrapper;
|
||||||
|
import io.gec.raw.connector.job.dto.JobAction;
|
||||||
|
import io.gec.raw.connector.job.dto.JobStatus;
|
||||||
|
import io.gec.raw.connector.job.dto.JobType;
|
||||||
|
import io.gec.raw.connector.job.handler.WorkItemHandler;
|
||||||
|
import io.gec.raw.connector.device.control.DeviceController;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.enterprise.context.control.ActivateRequestContext;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AccessLogJobHandler extends WorkItemHandler<LogWorkItemDTO, AccessLogWorkItemResult> {
|
||||||
|
@Inject
|
||||||
|
FtpController ftpController;
|
||||||
|
@Inject
|
||||||
|
DeviceController deviceController;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Optional<LogWorkItemDTO> getWorkItem(UUID workItemId) {
|
||||||
|
return communicationServiceController.fetchAccessLogWorkItem(workItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void startProcessing(WorkItemWrapper<LogWorkItemDTO> workItemWrapper) {
|
||||||
|
var accessLogWorkItemStatus = new AccessLogWorkItemStatusWrapper(workItemWrapper.workItemId(), LogWorkItemStatus.IN_PROGRESS);
|
||||||
|
updateLogWorkItemStatus(accessLogWorkItemStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ActivateRequestContext
|
||||||
|
@Override
|
||||||
|
protected AccessLogWorkItemResult processWorkItem(WorkItemWrapper<LogWorkItemDTO> workItemWrapper) {
|
||||||
|
logger.infof("Processing AccessLogWorkItem (ID:'%s') ...", workItemWrapper.workItemId());
|
||||||
|
UUID workItemId = workItemWrapper.workItemId();
|
||||||
|
LogWorkItemDTO workItem = workItemWrapper.workItem();
|
||||||
|
|
||||||
|
try {
|
||||||
|
Device rootDevice = deviceController.getDeviceByCommSvcId(workItem.getConnectionWorkItem().getDeviceId());
|
||||||
|
List<Integer> deviceNumbers = deviceController.getAccessDeviceIndexesByRootDeviceId(rootDevice.getId());
|
||||||
|
|
||||||
|
var sftpData = ftpController.createSftpData(workItem.getConnectionWorkItem().getConnectionPropertyValues(), rootDevice.getDeviceURL());
|
||||||
|
AccessLogDTO accessLogDTO = ftpController.getLoggingFile(sftpData, workItem.getDateFrom(), rootDevice.getId(), deviceNumbers);
|
||||||
|
accessLogDTO.setWorkItemId(workItemId);
|
||||||
|
communicationServiceController.createAccessLogNotifications(accessLogDTO);
|
||||||
|
|
||||||
|
return new AccessLogWorkItemResult(LogWorkItemStatus.DONE, getAccessLogResultMessage(accessLogDTO));
|
||||||
|
} catch (IllegalArgumentException | SftpException e) {
|
||||||
|
logger.errorf(e, "Processing AccessLogWorkItem (ID:'%s') - FAILED", workItemId);
|
||||||
|
return new AccessLogWorkItemResult(LogWorkItemStatus.LOG_FETCH_FAILURE, e.getMessage());
|
||||||
|
} catch (CommunicationServiceException | IOException e) {
|
||||||
|
logger.errorf(e, "Processing AccessLogWorkItem (ID:'%s') - FAILED", workItemId);
|
||||||
|
return new AccessLogWorkItemResult(LogWorkItemStatus.LOG_PARSE_FAILURE, e.getMessage());
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.errorf(e, "Processing AccessLogWorkItem (ID:'%s') - FAILED", workItemId);
|
||||||
|
return new AccessLogWorkItemResult(LogWorkItemStatus.DEVICE_ACCESS_FAILURE, e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getAccessLogResultMessage(AccessLogDTO accessLogDTO) {
|
||||||
|
//INFO: DO NOT CHANGE the format of message! It is used by frontend and this must be agreed upon before changing it.
|
||||||
|
return String.format("Access log items found: '%s'", accessLogDTO.getAccessLogItems().size());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void finishProcessing(WorkItemWrapper<LogWorkItemDTO> workItemWrapper, AccessLogWorkItemResult workItemResult) {
|
||||||
|
var accessLogWorkItemStatus = new AccessLogWorkItemStatusWrapper(
|
||||||
|
workItemWrapper.workItemId(),
|
||||||
|
workItemResult.getStatus(),
|
||||||
|
workItemResult.getMessage());
|
||||||
|
updateLogWorkItemStatus(accessLogWorkItemStatus);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected JobResult mapToJobResult(AccessLogWorkItemResult workItemResult) {
|
||||||
|
var workItemStatus = workItemResult.getStatus();
|
||||||
|
|
||||||
|
var jobStatus = switch (workItemStatus) {
|
||||||
|
case DONE -> JobStatus.DONE;
|
||||||
|
case LOG_PARSE_FAILURE, LOG_FETCH_FAILURE, DEVICE_ACCESS_FAILURE -> JobStatus.FAILED;
|
||||||
|
default -> throw new IllegalStateException("Mapping to job result failed, unexpected value: " + workItemStatus);
|
||||||
|
};
|
||||||
|
|
||||||
|
return new JobResult(jobStatus, workItemResult.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobType getJobType() {
|
||||||
|
return JobType.ACCESS_LOG;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public JobAction getJobAction() {
|
||||||
|
return JobAction.GET;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateLogWorkItemStatus(AccessLogWorkItemStatusWrapper logWorkItemStatus) {
|
||||||
|
var logWorkItemUpdateDTO = new LogWorkItemUpdateDTO();
|
||||||
|
logWorkItemUpdateDTO.setStatus(logWorkItemStatus.status());
|
||||||
|
logWorkItemUpdateDTO.setMessage(logWorkItemStatus.message());
|
||||||
|
|
||||||
|
communicationServiceController.updateAccessLogWorkItem(logWorkItemStatus.workItemId(), logWorkItemUpdateDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
38
src/main/java/io/gec/raw/connector/access/utils/ParserHelper.java
Executable file
38
src/main/java/io/gec/raw/connector/access/utils/ParserHelper.java
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
package io.gec.raw.connector.access.utils;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.time.ZoneOffset;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ParserHelper {
|
||||||
|
|
||||||
|
public static final String DATETIME_YEAR_MONTH_DAY_WITH_HYPHENS = "yyyy-MM-dd/HH:mm:ss";
|
||||||
|
public static final String DATETIME_DAY_MONTH_YEAR_WITH_DOTS = "dd.MM.yyyy/HH:mm:ss";
|
||||||
|
|
||||||
|
public boolean toBoolean(String str) {
|
||||||
|
if (str == null) {
|
||||||
|
return false;
|
||||||
|
} else if (str.equalsIgnoreCase("true") || str.equals("1")) {
|
||||||
|
return true;
|
||||||
|
} else if (str.equalsIgnoreCase("false") || str.equals("0")) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException("The String did not match either specified value");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime getOffsetDateTimeFromString(String dateTime) {
|
||||||
|
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME;
|
||||||
|
return OffsetDateTime.parse(dateTime, dateTimeFormatter);
|
||||||
|
}
|
||||||
|
|
||||||
|
public OffsetDateTime parseDateTime(String dateTime, String dateTimeFormat) {
|
||||||
|
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(dateTimeFormat);
|
||||||
|
LocalDateTime localDateTime = LocalDateTime.parse(dateTime, dateTimeFormatter);
|
||||||
|
return localDateTime.atOffset(ZoneOffset.UTC);
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/main/java/io/gec/raw/connector/base/entity/BaseEntity.java
Executable file
41
src/main/java/io/gec/raw/connector/base/entity/BaseEntity.java
Executable file
@@ -0,0 +1,41 @@
|
|||||||
|
package io.gec.raw.connector.base.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Column;
|
||||||
|
import jakarta.persistence.MappedSuperclass;
|
||||||
|
import jakarta.persistence.PrePersist;
|
||||||
|
import jakarta.persistence.PreUpdate;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@MappedSuperclass
|
||||||
|
public abstract class BaseEntity implements Serializable {
|
||||||
|
|
||||||
|
@Column(
|
||||||
|
nullable = false,
|
||||||
|
updatable = false
|
||||||
|
)
|
||||||
|
protected OffsetDateTime created;
|
||||||
|
@Column(
|
||||||
|
nullable = false
|
||||||
|
)
|
||||||
|
protected OffsetDateTime stamp;
|
||||||
|
|
||||||
|
protected BaseEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@PrePersist
|
||||||
|
protected void onCreate() {
|
||||||
|
this.created = OffsetDateTime.now();
|
||||||
|
this.stamp = OffsetDateTime.now();
|
||||||
|
}
|
||||||
|
|
||||||
|
@PreUpdate
|
||||||
|
protected void onUpdate() {
|
||||||
|
this.stamp = OffsetDateTime.now();
|
||||||
|
}
|
||||||
|
}
|
||||||
19
src/main/java/io/gec/raw/connector/base/entity/SimpleBaseEntity.java
Executable file
19
src/main/java/io/gec/raw/connector/base/entity/SimpleBaseEntity.java
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
package io.gec.raw.connector.base.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.MappedSuperclass;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.hibernate.annotations.UuidGenerator;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@MappedSuperclass
|
||||||
|
public abstract class SimpleBaseEntity extends BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
@UuidGenerator
|
||||||
|
protected UUID id;
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package io.gec.raw.connector.base.entity;
|
||||||
|
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.MappedSuperclass;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@Getter
|
||||||
|
@MappedSuperclass
|
||||||
|
public abstract class SimpleBaseEntityWithPredefinedId extends BaseEntity {
|
||||||
|
|
||||||
|
@Id
|
||||||
|
protected UUID id;
|
||||||
|
}
|
||||||
25
src/main/java/io/gec/raw/connector/base/entity/SubscribableEntity.java
Executable file
25
src/main/java/io/gec/raw/connector/base/entity/SubscribableEntity.java
Executable file
@@ -0,0 +1,25 @@
|
|||||||
|
package io.gec.raw.connector.base.entity;
|
||||||
|
|
||||||
|
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
public interface SubscribableEntity {
|
||||||
|
|
||||||
|
UUID getId();
|
||||||
|
|
||||||
|
int getSubscriptionInterval();
|
||||||
|
|
||||||
|
ComponentMode getMode();
|
||||||
|
|
||||||
|
boolean isInitialValueFetched();
|
||||||
|
|
||||||
|
default boolean isNotInitialValueFetched() {
|
||||||
|
return !isInitialValueFetched();
|
||||||
|
}
|
||||||
|
|
||||||
|
default boolean isSubscribed() {
|
||||||
|
return ComponentMode.OPERATION.equals(getMode()) && getSubscriptionInterval() > 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,205 @@
|
|||||||
|
package io.gec.raw.connector.communicationservice.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.AccessLogDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.communicationservice.exception.CommunicationServiceResponseExceptionMapper;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ChangeModeRequestDTO;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.connector.dto.ConnectorRequestDTO;
|
||||||
|
import io.gec.raw.connector.connector.dto.ConnectorResponseDTO;
|
||||||
|
import io.gec.raw.connector.device.dto.DeviceDTO;
|
||||||
|
import io.gec.raw.connector.device.dto.DeviceResponseDTO;
|
||||||
|
import io.gec.raw.connector.deviceproperty.dto.PropertyValueRequestDTO;
|
||||||
|
import io.gec.raw.connector.discovery.dto.DiscoveryWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.discovery.dto.DiscoveryWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.driver.dto.DriverWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.driver.dto.DriverWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.firmware.dto.FirmwareFileMetadataDTO;
|
||||||
|
import io.gec.raw.connector.firmware.dto.FirmwareWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.firmware.dto.FirmwareWorkItemUpdateRequestDTO;
|
||||||
|
import io.gec.raw.connector.job.dto.JobDTO;
|
||||||
|
import io.gec.raw.connector.job.dto.JobStateDTO;
|
||||||
|
import io.gec.raw.connector.pauseworkitem.dto.PauseWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.pauseworkitem.dto.PauseWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.setworkitem.dto.SetWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.setworkitem.dto.SetWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.variable.dto.UpdateVariableRequestDTO;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.ws.rs.GET;
|
||||||
|
import jakarta.ws.rs.PATCH;
|
||||||
|
import jakarta.ws.rs.POST;
|
||||||
|
import jakarta.ws.rs.PUT;
|
||||||
|
import jakarta.ws.rs.Path;
|
||||||
|
import jakarta.ws.rs.PathParam;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
import jakarta.ws.rs.QueryParam;
|
||||||
|
import jakarta.ws.rs.core.MediaType;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import org.eclipse.microprofile.rest.client.annotation.RegisterProvider;
|
||||||
|
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
@RegisterRestClient(configKey = "communication-service")
|
||||||
|
@RegisterProvider(CommunicationServiceResponseExceptionMapper.class)
|
||||||
|
public interface CommunicationService {
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/api/resources/jobs")
|
||||||
|
List<JobDTO> getJobs(
|
||||||
|
@QueryParam("connectorId") UUID connectorId,
|
||||||
|
@QueryParam("sinceDateTime") String sinceDateTime
|
||||||
|
);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("api/resources/discoveryWorkItems/{discoveryWorkItemId}")
|
||||||
|
DiscoveryWorkItemDTO getDiscoveryWorkItemById(@PathParam("discoveryWorkItemId") UUID discoveryWorkItemId);
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/api/resources/discoveryWorkItems/{id}")
|
||||||
|
DiscoveryWorkItemDTO updateDiscoveryWorkItem(
|
||||||
|
@PathParam("id") UUID discoveryWorkItemId,
|
||||||
|
DiscoveryWorkItemUpdateDTO discoveryWorkItemUpdateDTO
|
||||||
|
);
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/api/resources/discoveryWorkItems/deviceDiscovery/{id}")
|
||||||
|
Boolean addLatestDeviceDiscoveryAndArchiveOldDeviceDiscovery(
|
||||||
|
@PathParam("id") UUID discoveryWorkItemId,
|
||||||
|
UUID deviceId
|
||||||
|
);
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/api/resources/variables/values")
|
||||||
|
Boolean updateSubscribedVariable(
|
||||||
|
UpdateVariableRequestDTO updateVariableRequestDTO
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/api/resources/variables/values/collection")
|
||||||
|
Boolean updateSubscribedVariables(
|
||||||
|
List<UpdateVariableRequestDTO> updateVariableRequestDTOs
|
||||||
|
);
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("/api/resources/deviceProperties/values")
|
||||||
|
Boolean updateDeviceProperty(
|
||||||
|
PropertyValueRequestDTO propertyValueRequestDTO
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("api/resources/connectors/{connectorId}/status")
|
||||||
|
Boolean updateConnectorStatus(
|
||||||
|
@PathParam("connectorId") UUID connectorId
|
||||||
|
);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("api/resources/devices")
|
||||||
|
DeviceResponseDTO createOrUpdateDevicesWithSubDevices(DeviceDTO deviceDTO);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("/api/resources/connectors")
|
||||||
|
ConnectorResponseDTO registerConnector(ConnectorRequestDTO dto);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("api/resources/accessLogs")
|
||||||
|
void createAccessLogNotifications(AccessLogDTO accessLogDTO);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("api/resources/connectionWorkItems/{id}")
|
||||||
|
ConnectionWorkItemDTO getAccessConnectionWorkItem(@PathParam("id") UUID connectionWorkItemId);
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("api/resources/connectionWorkItems/{id}")
|
||||||
|
ConnectionWorkItemDTO updateAccessConnectionWorkItem(@PathParam("id") UUID connectionWorkItemId,
|
||||||
|
ConnectionWorkItemUpdateDTO connectionWorkItemUpdateDTO);
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("api/resources/logWorkItems/{id}")
|
||||||
|
LogWorkItemDTO updateAccessLogWorkItem(@PathParam("id") UUID logWorkItemId,
|
||||||
|
LogWorkItemUpdateDTO logWorkItemUpdateDTO);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/api/resources/logWorkItems/{id}")
|
||||||
|
LogWorkItemDTO getAccessLogWorkItem(@PathParam("id") UUID logWorkItemId);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/api/resources/accessConfigWorkItems/{id}")
|
||||||
|
AccessConfigWorkItemDTO getAccessConfigWorkItem(@PathParam("id") UUID accessConfigWorkItemId);
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("api/resources/accessConfigWorkItems/{id}")
|
||||||
|
AccessConfigWorkItemDTO updateAccessConfigWorkItem(@PathParam("id") UUID accessConfigWorkItemId,
|
||||||
|
AccessConfigWorkItemUpdateDTO accessConfigWorkItemUpdateDTO);
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("api/resources/pauseWorkItems/{id}")
|
||||||
|
PauseWorkItemDTO updatePauseWorkItem(@PathParam("id") UUID pauseWorkItemId,
|
||||||
|
PauseWorkItemUpdateDTO pauseWorkItemUpdateDTO);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/api/resources/pauseWorkItems/{id}")
|
||||||
|
PauseWorkItemDTO getPauseWorkItem(
|
||||||
|
@PathParam("id") UUID pauseWorkItemId
|
||||||
|
);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/api/resources/driverWorkItems/{id}")
|
||||||
|
DriverWorkItemDTO getDriverWorkItem(
|
||||||
|
@PathParam("id") UUID driverWorkItemId
|
||||||
|
);
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("api/resources/driverWorkItems/{id}")
|
||||||
|
DriverWorkItemDTO updateDriverWorkItem(@PathParam("id") UUID driverWorkItemId,
|
||||||
|
DriverWorkItemUpdateDTO driverWorkItemUpdateDTO);
|
||||||
|
|
||||||
|
@POST
|
||||||
|
@Path("api/resources/jobs/{jobId}/states")
|
||||||
|
JobStateDTO createJobState(@PathParam("jobId") UUID jobId,
|
||||||
|
JobStateDTO jobStateDTO);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("/api/resources/setWorkItems/{id}")
|
||||||
|
SetWorkItemDTO getSetWorkItem(@PathParam("id") UUID setWorkItemId);
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("api/resources/setWorkItems/{id}")
|
||||||
|
void updateSetWorkItem(@PathParam("id") UUID setWorkItemId,
|
||||||
|
SetWorkItemUpdateDTO setWorkItemUpdateDTO);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("api/resources/firmwareWorkItems/{id}")
|
||||||
|
FirmwareWorkItemDTO getFirmwareWorkItem(@PathParam("id") UUID firmwareWorkItemId);
|
||||||
|
|
||||||
|
@PATCH
|
||||||
|
@Path("api/resources/firmwareWorkItems/{id}")
|
||||||
|
void updateFirmwareWorkItem(@PathParam("id") UUID firmwareWorkItemId,
|
||||||
|
FirmwareWorkItemUpdateRequestDTO firmwareWorkItemUpdateRequestDTO);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("api/resources/firmwareWorkItems/{workItemId}/files/{firmwareId}/metadata")
|
||||||
|
FirmwareFileMetadataDTO getFirmwareFileMetadata(@PathParam("firmwareId") UUID firmwareId,
|
||||||
|
@PathParam("workItemId") UUID workItemId);
|
||||||
|
|
||||||
|
@GET
|
||||||
|
@Path("api/resources/firmwareWorkItems/{workItemId}/files/{firmwareId}")
|
||||||
|
@Produces(MediaType.APPLICATION_OCTET_STREAM)
|
||||||
|
Response getFirmwareFileStream(@PathParam("firmwareId") UUID firmwareId,
|
||||||
|
@PathParam("workItemId") UUID workItemId);
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("api/resources/componentModes/")
|
||||||
|
void changeComponentMode(ChangeModeRequestDTO changeModeRequestDTO);
|
||||||
|
|
||||||
|
@PUT
|
||||||
|
@Path("api/resources/componentModes/{id}")
|
||||||
|
JobStateDTO changeComponentModeForDeviceTree(@PathParam("id") UUID deviceId, ComponentMode componentMode);
|
||||||
|
}
|
||||||
@@ -0,0 +1,356 @@
|
|||||||
|
package io.gec.raw.connector.communicationservice.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.configworkitem.dto.AccessConfigWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.connectionworkitem.dto.ConnectionWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.AccessLogDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.access.logworkitem.dto.LogWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.communicationservice.exception.CommunicationServiceException;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ChangeModeRequestDTO;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.config.entity.ConnectorConfig;
|
||||||
|
import io.gec.raw.connector.connector.dto.ConnectorRequestDTO;
|
||||||
|
import io.gec.raw.connector.connector.dto.ConnectorResponseDTO;
|
||||||
|
import io.gec.raw.connector.deviceproperty.dto.PropertyValueRequestDTO;
|
||||||
|
import io.gec.raw.connector.discovery.dto.DiscoveryWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.discovery.dto.DiscoveryWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.driver.dto.DriverWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.driver.dto.DriverWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.firmware.dto.FirmwareFileMetadataDTO;
|
||||||
|
import io.gec.raw.connector.firmware.dto.FirmwareWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.firmware.dto.FirmwareWorkItemUpdateRequestDTO;
|
||||||
|
import io.gec.raw.connector.job.dto.JobDTO;
|
||||||
|
import io.gec.raw.connector.job.dto.JobStateDTO;
|
||||||
|
import io.gec.raw.connector.pauseworkitem.dto.PauseWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.pauseworkitem.dto.PauseWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.setworkitem.dto.SetWorkItemDTO;
|
||||||
|
import io.gec.raw.connector.setworkitem.dto.SetWorkItemUpdateDTO;
|
||||||
|
import io.gec.raw.connector.variable.dto.UpdateVariableRequestDTO;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class CommunicationServiceController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
@Inject
|
||||||
|
ConnectorConfig connectorConfig;
|
||||||
|
@Inject
|
||||||
|
CommunicationServiceRequestErrorHandler communicationServiceRequestErrorHandler;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
@RestClient
|
||||||
|
CommunicationService communicationService;
|
||||||
|
|
||||||
|
public Optional<ConnectorResponseDTO> registerConnector(ConnectorRequestDTO dto) {
|
||||||
|
try {
|
||||||
|
ConnectorResponseDTO result = communicationService.registerConnector(dto);
|
||||||
|
logger.infof("Comm.Svc. - Connector registered");
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - register Connector (ID:'%s') - FAILED", connectorConfig.getConnectorId());
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateConnectorStatus() {
|
||||||
|
try {
|
||||||
|
communicationService.updateConnectorStatus(connectorConfig.getConnectorId());
|
||||||
|
logger.infof("Comm.Svc. - Connector status updated");
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update Connector status - FAILED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<JobDTO> fetchJobs(String sinceDateTime) {
|
||||||
|
try {
|
||||||
|
//INFO: log concerning fetched jobs done in JobController
|
||||||
|
return communicationService.getJobs(connectorConfig.getConnectorId(), sinceDateTime);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch Jobs since '%s' - FAILED", sinceDateTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void createJobState(UUID jobId, JobStateDTO jobStateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.createJobState(jobId, jobStateDTO);
|
||||||
|
logger.infof("Comm.Svc. - Job (ID:'%s') status updated to: '%s'", jobId, jobStateDTO.getStatus());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update Job (ID:'%s') status to: '%s' - FAILED", jobId, jobStateDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<ConnectionWorkItemDTO> fetchAccessConnectionWorkItem(UUID connectionWorkItemId) {
|
||||||
|
try {
|
||||||
|
ConnectionWorkItemDTO result = communicationService.getAccessConnectionWorkItem(connectionWorkItemId);
|
||||||
|
logger.infof("Comm.Svc. - ConnectionWorkItem (ID:'%s') fetched", connectionWorkItemId);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch ConnectionWorkItem (ID:'%s') - FAILED", connectionWorkItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<LogWorkItemDTO> fetchAccessLogWorkItem(UUID logWorkItemId) {
|
||||||
|
try {
|
||||||
|
LogWorkItemDTO result = communicationService.getAccessLogWorkItem(logWorkItemId);
|
||||||
|
logger.infof("Comm.Svc. - LogWorkItem (ID:'%s') fetched", logWorkItemId);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch LogWorkItem (ID:'%s') - FAILED", logWorkItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<AccessConfigWorkItemDTO> fetchAccessConfigWorkItem(UUID accessConfigWorkItemId) {
|
||||||
|
try {
|
||||||
|
AccessConfigWorkItemDTO result = communicationService.getAccessConfigWorkItem(accessConfigWorkItemId);
|
||||||
|
logger.infof("Comm.Svc. - AccessConfigWorkItem (ID:'%s') fetched", accessConfigWorkItemId);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch AccessConfigWorkItem (ID:'%s') - FAILED", accessConfigWorkItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<PauseWorkItemDTO> fetchPauseWorkItem(UUID pauseWorkItemId) {
|
||||||
|
try {
|
||||||
|
PauseWorkItemDTO result = communicationService.getPauseWorkItem(pauseWorkItemId);
|
||||||
|
logger.infof("Comm.Svc. - PauseWorkItem (ID:'%s') fetched", pauseWorkItemId);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch PauseWorkItem (ID:'%s') - FAILED", pauseWorkItemId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<DiscoveryWorkItemDTO> fetchDiscoveryWorkItem(UUID id) {
|
||||||
|
try {
|
||||||
|
DiscoveryWorkItemDTO result = communicationService.getDiscoveryWorkItemById(id);
|
||||||
|
logger.infof("Comm.Svc. - DiscoveryWorkItem (ID:'%s') fetched", id);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch DiscoveryWorkItem (ID:'%s') - FAILED", id);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<DriverWorkItemDTO> fetchDriverWorkItem(UUID id) {
|
||||||
|
try {
|
||||||
|
DriverWorkItemDTO result = communicationService.getDriverWorkItem(id);
|
||||||
|
logger.infof("Comm.Svc. - DriverWorkItem (ID:'%s') fetched", id);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch DriverWorkItem (ID:'%s') - FAILED", id);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<FirmwareWorkItemDTO> fetchFirmwareWorkItem(UUID id) {
|
||||||
|
try {
|
||||||
|
FirmwareWorkItemDTO result = communicationService.getFirmwareWorkItem(id);
|
||||||
|
logger.infof("Comm.Svc. - FirmwareWorkItem (ID:'%s') fetched", id);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch FirmwareWorkItem (ID:'%s') - FAILED", id);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public FirmwareFileMetadataDTO fetchFirmwareFileMetadata(UUID firmwareId, UUID workItemId) {
|
||||||
|
try {
|
||||||
|
FirmwareFileMetadataDTO result = communicationService.getFirmwareFileMetadata(firmwareId, workItemId);
|
||||||
|
logger.infof("Comm.Svc. - FirmwareFileMetadata (ID:'%s') fetched", firmwareId);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch FirmwareFileMetadata (ID:'%s') - FAILED", firmwareId);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public InputStream fetchFirmwareFileStream(UUID firmwareId, UUID workItemId) {
|
||||||
|
try {
|
||||||
|
Response response = communicationService.getFirmwareFileStream(firmwareId, workItemId);
|
||||||
|
InputStream inputStream = response.readEntity(InputStream.class);
|
||||||
|
logger.infof("Comm.Svc. - firmware file input stream (ID:'%s') fetched", firmwareId);
|
||||||
|
|
||||||
|
return inputStream;
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - fetch firmware file input stream (ID:'%s') - FAILED", firmwareId);
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAccessConnectionWorkItem(UUID connectionWorkItemId, ConnectionWorkItemUpdateDTO connectionWorkItemUpdateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateAccessConnectionWorkItem(connectionWorkItemId, connectionWorkItemUpdateDTO);
|
||||||
|
logger.infof("Comm.Svc. - ConnectionWorkItem (ID:'%s') updated to status: '%s'", connectionWorkItemId, connectionWorkItemUpdateDTO.getStatus());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update ConnectionWorkItem (ID:'%s') status to '%s' - FAILED", connectionWorkItemId, connectionWorkItemUpdateDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAccessLogWorkItem(UUID logWorkItemId, LogWorkItemUpdateDTO logWorkItemUpdateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateAccessLogWorkItem(logWorkItemId, logWorkItemUpdateDTO);
|
||||||
|
logger.infof("Comm.Svc. - LogWorkItem (ID:'%s') updated to status: '%s'", logWorkItemId, logWorkItemUpdateDTO.getStatus());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update LogWorkItem (ID:'%s') status to '%s' - FAILED", logWorkItemId, logWorkItemUpdateDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateAccessConfigWorkItem(UUID accessConfigWorkItemId, AccessConfigWorkItemUpdateDTO accessConfigWorkItemUpdateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateAccessConfigWorkItem(accessConfigWorkItemId, accessConfigWorkItemUpdateDTO);
|
||||||
|
logger.infof("Comm.Svc. - AccessConfigWorkItem (ID:'%s') updated to status: '%s'", accessConfigWorkItemId, accessConfigWorkItemUpdateDTO.getStatus());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update AccessConfigWorkItem (ID:'%s') status to '%s' - FAILED", accessConfigWorkItemId, accessConfigWorkItemUpdateDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updatePauseWorkItem(UUID pauseWorkItemId, PauseWorkItemUpdateDTO pauseWorkItemUpdateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updatePauseWorkItem(pauseWorkItemId, pauseWorkItemUpdateDTO);
|
||||||
|
logger.infof("Comm.Svc. - PauseWorkItem (ID:'%s') updated to status: '%s'", pauseWorkItemId, pauseWorkItemUpdateDTO.getStatus());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update PauseWorkItem (ID:'%s') status to '%s' - FAILED", pauseWorkItemId, pauseWorkItemUpdateDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDiscoveryWorkItem(UUID discoveryWorkItemId, DiscoveryWorkItemUpdateDTO discoveryWorkItemUpdateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateDiscoveryWorkItem(discoveryWorkItemId, discoveryWorkItemUpdateDTO);
|
||||||
|
logger.infof("Comm.Svc. - DiscoveryWorkItem (ID:'%s') updated to status: '%s'", discoveryWorkItemId, discoveryWorkItemUpdateDTO.getDiscoveryStatusEnum());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update DiscoveryWorkItem (ID:'%s') status to '%s' - FAILED", discoveryWorkItemId, discoveryWorkItemUpdateDTO.getDiscoveryStatusEnum());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDriverWorkItem(UUID driverWorkItemId, DriverWorkItemUpdateDTO driverWorkItemUpdateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateDriverWorkItem(driverWorkItemId, driverWorkItemUpdateDTO);
|
||||||
|
logger.infof("Comm.Svc. - DriverWorkItem (ID:'%s') updated to status: '%s'", driverWorkItemId, driverWorkItemUpdateDTO.getStatus());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update DriverWorkItem (ID:'%s') to status '%s' - FAILED", driverWorkItemId, driverWorkItemUpdateDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateFirmwareWorkItem(UUID firmwareWorkItemId, FirmwareWorkItemUpdateRequestDTO firmwareWorkItemUpdateRequestDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateFirmwareWorkItem(firmwareWorkItemId, firmwareWorkItemUpdateRequestDTO);
|
||||||
|
logger.infof("Comm.Svc. - FirmwareWorkItem (ID:'%s') updated to status: '%s'", firmwareWorkItemId, firmwareWorkItemUpdateRequestDTO.getStatus());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - update FirmwareWorkItem (ID:'%s') to status '%s' - FAILED", firmwareWorkItemId, firmwareWorkItemUpdateRequestDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createAccessLogNotifications(AccessLogDTO accessLogDTO) throws CommunicationServiceException {
|
||||||
|
try {
|
||||||
|
communicationService.createAccessLogNotifications(accessLogDTO);
|
||||||
|
logger.infof("Comm.Svc. - AccessLog entries for AccessLogWorkItem (ID:'%s') sent (total: %d)", accessLogDTO.getWorkItemId(), accessLogDTO.getAccessLogItems().size());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - sending AccessLog entries (total: %d) for AccessLogWorkItem (ID:'%s') - FAILED", accessLogDTO.getAccessLogItems().size(),
|
||||||
|
accessLogDTO.getWorkItemId());
|
||||||
|
throw ex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateVariableValue(UpdateVariableRequestDTO updateVariableRequestDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateSubscribedVariable(updateVariableRequestDTO);
|
||||||
|
logger.debugf("Comm.Svc. - VariableValue (ID:'%s') updated to:'%s', quality:'%s'", updateVariableRequestDTO.getVariableId(), updateVariableRequestDTO.getValue(),
|
||||||
|
updateVariableRequestDTO.getQualityType());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - Update VariableValue (ID:'%s') to:'%s', quality:'%s' - FAILED", updateVariableRequestDTO.getVariableId(),
|
||||||
|
updateVariableRequestDTO.getValue(), updateVariableRequestDTO.getQualityType());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateVariableValues(List<UpdateVariableRequestDTO> variableValuesDTOs) {
|
||||||
|
try {
|
||||||
|
logger.debugf("Comm.Svc. - Sending Variable Values: %s)", variableValuesDTOs);
|
||||||
|
communicationService.updateSubscribedVariables(variableValuesDTOs);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - Sending Variable Values - FAILED");
|
||||||
|
logger.errorf("Values sent in failed request: %s", variableValuesDTOs);
|
||||||
|
communicationServiceRequestErrorHandler.handleErrorOfUpdateSubscribedVariables(variableValuesDTOs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDeviceProperty(PropertyValueRequestDTO propertyValueRequestDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateDeviceProperty(propertyValueRequestDTO);
|
||||||
|
logger.debugf("Comm.Svc. - PropertyValue (ID:'%s') updated to:'%s'", propertyValueRequestDTO.getPropertyId(), propertyValueRequestDTO.getValueAsString());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - Update PropertyValue (ID:'%s') to:'%s' - FAILED", propertyValueRequestDTO.getPropertyId(),
|
||||||
|
propertyValueRequestDTO.getValueAsString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<SetWorkItemDTO> fetchSetWorkItem(UUID setWorkItemId) {
|
||||||
|
try {
|
||||||
|
SetWorkItemDTO result = communicationService.getSetWorkItem(setWorkItemId);
|
||||||
|
logger.infof("Comm.Svc. - SetWorkItem (ID:'%s') fetched", setWorkItemId);
|
||||||
|
|
||||||
|
return Optional.of(result);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - Fetch SetWorkItem (ID:'%s') - FAILED", setWorkItemId);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateSetWorkItem(UUID setWorkItemId, SetWorkItemUpdateDTO setWorkItemUpdateDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.updateSetWorkItem(setWorkItemId, setWorkItemUpdateDTO);
|
||||||
|
logger.infof("Comm.Svc. - SetWorkItem (ID:'%s') updated to status: '%s'", setWorkItemId, setWorkItemUpdateDTO.getStatus());
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - Update SetWorkItem (ID:'%s') to status: '%s' - FAILED", setWorkItemId, setWorkItemUpdateDTO.getStatus());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeComponentMode(ChangeModeRequestDTO changeModeRequestDTO) {
|
||||||
|
try {
|
||||||
|
communicationService.changeComponentMode(changeModeRequestDTO);
|
||||||
|
logger.infof("Comm.Svc. - Updating ComponentMode");
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - Update ComponentMode - FAILED");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeComponentModeForDeviceTree(UUID deviceId, ComponentMode mode) {
|
||||||
|
try {
|
||||||
|
communicationService.changeComponentModeForDeviceTree(deviceId, mode);
|
||||||
|
logger.infof("Comm.Svc. - Updating ComponentMode for device (ID: '%s') to: '%s')", deviceId, mode);
|
||||||
|
} catch (CommunicationServiceException ex) {
|
||||||
|
logger.errorf(ex, "Comm.Svc. - Update ComponentMode for device (ID: '%s') to: '%s - FAILED')", deviceId, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package io.gec.raw.connector.communicationservice.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.variable.control.VariableValueCacheHandler;
|
||||||
|
import io.gec.raw.connector.variable.dto.UpdateVariableRequestDTO;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class CommunicationServiceRequestErrorHandler {
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
@Inject
|
||||||
|
VariableValueCacheHandler variableValueCacheHandler;
|
||||||
|
|
||||||
|
public void handleErrorOfUpdateSubscribedVariables(List<UpdateVariableRequestDTO> variableValuesDTOs) {
|
||||||
|
List<UUID> variableIds = variableValuesDTOs.stream().map(UpdateVariableRequestDTO::getVariableId).toList();
|
||||||
|
logger.infof("Removing from Cache Variable Values which were sent in failed request IDs: %s", variableIds);
|
||||||
|
variableValueCacheHandler.removeFromCache(variableIds);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package io.gec.raw.connector.communicationservice.exception;
|
||||||
|
|
||||||
|
public class CommunicationServiceException extends RuntimeException {
|
||||||
|
|
||||||
|
private final ModelType model;
|
||||||
|
private final FailureType failure;
|
||||||
|
|
||||||
|
public CommunicationServiceException(ModelType modelType, FailureType failureType, String message) {
|
||||||
|
super(message);
|
||||||
|
model = modelType;
|
||||||
|
failure = failureType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CommunicationServiceException(FailureType failureType, String message) {
|
||||||
|
super(message);
|
||||||
|
model = new ModelType("unknown");
|
||||||
|
failure = failureType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "CommunicationServiceException{model=%s, failure=%s, msg:%s}".formatted(model, failure, getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
package io.gec.raw.connector.communicationservice.exception;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
import org.eclipse.microprofile.rest.client.ext.ResponseExceptionMapper;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class CommunicationServiceResponseExceptionMapper implements ResponseExceptionMapper<CommunicationServiceException> {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommunicationServiceException toThrowable(Response response) {
|
||||||
|
return extractCommSvcExceptionFromResponse(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
private CommunicationServiceException extractCommSvcExceptionFromResponse(Response response) {
|
||||||
|
try {
|
||||||
|
Map<String, String> body = readResponseBody(response);
|
||||||
|
var model = body.get("object");
|
||||||
|
var failure = body.get("failure");
|
||||||
|
var message = body.get("message");
|
||||||
|
if (message == null) {
|
||||||
|
message = body.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
var modelType = new ModelType(model);
|
||||||
|
var failureType = new FailureType(response.getStatusInfo().toEnum(), failure);
|
||||||
|
|
||||||
|
return new CommunicationServiceException(modelType, failureType, message);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
var message = "Unable to extract CommunicationService response body as CommunicationServiceException";
|
||||||
|
logger.warn(message, ex);
|
||||||
|
return new CommunicationServiceException(new FailureType(response.getStatusInfo().toEnum(), "unknown"),
|
||||||
|
message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> readResponseBody(Response response) throws IOException {
|
||||||
|
String json = response.readEntity(String.class);
|
||||||
|
return new ObjectMapper().readValue(json, new TypeReference<>() {
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package io.gec.raw.connector.communicationservice.exception;
|
||||||
|
|
||||||
|
import jakarta.ws.rs.core.Response;
|
||||||
|
|
||||||
|
public record FailureType(Response.Status status, String name) {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "FailureType{status=%s, name=%s}".formatted(status, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package io.gec.raw.connector.communicationservice.exception;
|
||||||
|
|
||||||
|
public record ModelType(String name) {
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ModelType{name=%s}".formatted(name);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,70 @@
|
|||||||
|
package io.gec.raw.connector.componentmode.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.device.control.DeviceController;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import io.gec.raw.connector.deviceproperty.control.DevicePropertyController;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ChangeModeRequestDTO;
|
||||||
|
import io.gec.raw.connector.variable.control.VariableController;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ComponentModeController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
DeviceController deviceController;
|
||||||
|
@Inject
|
||||||
|
VariableController variableController;
|
||||||
|
@Inject
|
||||||
|
DevicePropertyController devicePropertyController;
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
|
||||||
|
public ChangeModeRequestDTO createChangeModeRequestDTO(UUID commDeviceId) {
|
||||||
|
ChangeModeRequestDTO changeModeRequestDTO = new ChangeModeRequestDTO();
|
||||||
|
|
||||||
|
Device rootDevice = deviceController.getDeviceByCommSvcId(commDeviceId);
|
||||||
|
|
||||||
|
logger.infof("Creating ChangeModeRequestDTO for Device ID: '%s'", rootDevice.getId());
|
||||||
|
createDeviceModeMap(rootDevice, changeModeRequestDTO);
|
||||||
|
|
||||||
|
return changeModeRequestDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
void createDeviceModeMap(Device device, ChangeModeRequestDTO changeModeRequestDTO) {
|
||||||
|
Objects.requireNonNull(device, "Device is null, cannot create DeviceModeMap.");
|
||||||
|
|
||||||
|
logger.debugf("Processing Device (ID:'%s')", device.getId());
|
||||||
|
|
||||||
|
createVariableModeMap(device.getId(), changeModeRequestDTO.getVariableModes());
|
||||||
|
createPropertyModeMap(device.getId(), changeModeRequestDTO.getPropertyModes());
|
||||||
|
|
||||||
|
changeModeRequestDTO.getDeviceModes().put(device.getCommServiceId(), device.getMode());
|
||||||
|
|
||||||
|
deviceController.getSubDevices(device.getId()).forEach(subDevice -> createDeviceModeMap(subDevice, changeModeRequestDTO));
|
||||||
|
}
|
||||||
|
|
||||||
|
void createVariableModeMap(UUID deviceId, Map<UUID, ComponentMode> variableModesMap) {
|
||||||
|
var variables = variableController.getVariablesByDeviceId(deviceId);
|
||||||
|
|
||||||
|
variables.forEach(variable -> {
|
||||||
|
variableModesMap.put(variable.getCommServiceId(), variable.getMode());
|
||||||
|
logger.debugf("Added Variable (ID:'%s') with mode '%s' to VariableModeMap for Device ID: '%s'", variable.getCommServiceId(), variable.getMode(), deviceId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void createPropertyModeMap(UUID deviceId, Map<UUID, ComponentMode> propertyModesMap) {
|
||||||
|
var properties = devicePropertyController.findByDeviceId(deviceId);
|
||||||
|
|
||||||
|
properties.forEach(property -> {
|
||||||
|
propertyModesMap.put(property.getCommServiceId(), property.getMode());
|
||||||
|
logger.debugf("Added Property (ID:'%s') with mode '%s' to PropertyModeMap for Device ID: '%s'", property.getCommServiceId(), property.getMode(), deviceId);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
package io.gec.raw.connector.componentmode.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.communicationservice.control.CommunicationServiceController;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ChangeModeRequestDTO;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.device.control.DeviceController;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ComponentModeHandler {
|
||||||
|
@Inject
|
||||||
|
ComponentModeController componentModeController;
|
||||||
|
@Inject
|
||||||
|
DeviceController deviceController;
|
||||||
|
@Inject
|
||||||
|
CommunicationServiceController communicationServiceController;
|
||||||
|
|
||||||
|
public void changeComponentModeForDeviceTree(UUID commDeviceId, ComponentMode componentMode) {
|
||||||
|
deviceController.updateModeByCommSvcId(commDeviceId, componentMode);
|
||||||
|
communicationServiceController.changeComponentModeForDeviceTree(commDeviceId, componentMode);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void changeComponentMode(UUID commDeviceId, ComponentMode componentMode) {
|
||||||
|
deviceController.updateModeByCommSvcId(commDeviceId, componentMode);
|
||||||
|
|
||||||
|
ChangeModeRequestDTO changeModeRequestDTO = componentModeController.createChangeModeRequestDTO(commDeviceId);
|
||||||
|
communicationServiceController.changeComponentMode(changeModeRequestDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void restoreComponentMode(UUID commDeviceId) {
|
||||||
|
deviceController.restoreModeByCommSvcId(commDeviceId);
|
||||||
|
|
||||||
|
ChangeModeRequestDTO changeModeRequestDTO = componentModeController.createChangeModeRequestDTO(commDeviceId);
|
||||||
|
communicationServiceController.changeComponentMode(changeModeRequestDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package io.gec.raw.connector.componentmode.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class ChangeModeRequestDTO {
|
||||||
|
private Map<UUID, ComponentMode> deviceModes = new HashMap<>();
|
||||||
|
private Map<UUID, ComponentMode> variableModes = new HashMap<>();
|
||||||
|
private Map<UUID, ComponentMode> propertyModes = new HashMap<>();
|
||||||
|
}
|
||||||
14
src/main/java/io/gec/raw/connector/componentmode/dto/ComponentMode.java
Executable file
14
src/main/java/io/gec/raw/connector/componentmode/dto/ComponentMode.java
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
package io.gec.raw.connector.componentmode.dto;
|
||||||
|
|
||||||
|
public enum ComponentMode {
|
||||||
|
|
||||||
|
OPERATION,
|
||||||
|
PAUSE,
|
||||||
|
SERVICE,
|
||||||
|
FIRMWARE_UPDATE,
|
||||||
|
OFFLINE;
|
||||||
|
|
||||||
|
public boolean isRestorable() {
|
||||||
|
return this.equals(OPERATION) || this.equals(PAUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/java/io/gec/raw/connector/config/control/AppConfig.java
Executable file
15
src/main/java/io/gec/raw/connector/config/control/AppConfig.java
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
package io.gec.raw.connector.config.control;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.ws.rs.Produces;
|
||||||
|
|
||||||
|
import java.time.Clock;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class AppConfig {
|
||||||
|
@Produces
|
||||||
|
@ApplicationScoped
|
||||||
|
public Clock createClockBean() {
|
||||||
|
return Clock.systemUTC();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
package io.gec.raw.connector.config.control;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.text.MessageFormat;
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ConnectorConfigController {
|
||||||
|
|
||||||
|
private static final String VERSION_PROPERTY = "version";
|
||||||
|
private static final String VERSION_PROPERTY_FORMAT = "yyyyMMddHHmm";
|
||||||
|
private static final String TIMESTAMP_FORMAT = "{0,date,dd.MM.yyyy} {0,time,HH:mm}";
|
||||||
|
|
||||||
|
@ConfigProperty(name = "quarkus.application.version")
|
||||||
|
String version;
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
@Inject
|
||||||
|
PropertyFileHandler propertyFileHandler;
|
||||||
|
|
||||||
|
public String getConnectorVersion() {
|
||||||
|
return String.format("%s (%s)", version, getTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
|
String getTimestamp() throws RuntimeException {
|
||||||
|
return propertyFileHandler.getProperty(VERSION_PROPERTY)
|
||||||
|
.filter(property -> !property.isBlank())
|
||||||
|
.map(this::formatTimestamp)
|
||||||
|
.orElseThrow(() -> new RuntimeException("Version property in version.properties file does not exist or is empty"));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String formatTimestamp(String timestamp) {
|
||||||
|
try {
|
||||||
|
SimpleDateFormat inputFormat = new SimpleDateFormat(VERSION_PROPERTY_FORMAT);
|
||||||
|
inputFormat.setLenient(false);
|
||||||
|
Date date = inputFormat.parse(timestamp);
|
||||||
|
return MessageFormat.format(TIMESTAMP_FORMAT, date);
|
||||||
|
} catch (ParseException e) {
|
||||||
|
logger.error("There was an error while parsing version from version.properties file, raw version property will be used");
|
||||||
|
return timestamp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/main/java/io/gec/raw/connector/config/control/PropertyFileHandler.java
Executable file
26
src/main/java/io/gec/raw/connector/config/control/PropertyFileHandler.java
Executable file
@@ -0,0 +1,26 @@
|
|||||||
|
package io.gec.raw.connector.config.control;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class PropertyFileHandler {
|
||||||
|
|
||||||
|
public static final String PROPERTY_FILE_NAME = "version.properties";
|
||||||
|
private final Properties properties = new Properties();
|
||||||
|
|
||||||
|
public PropertyFileHandler() {
|
||||||
|
try (InputStream inputStream = getClass().getClassLoader().getResourceAsStream(PROPERTY_FILE_NAME)) {
|
||||||
|
properties.load(inputStream);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException("There was a problem while loading property file", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<String> getProperty(String name) {
|
||||||
|
return Optional.ofNullable(properties.getProperty(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
package io.gec.raw.connector.config.control;
|
||||||
|
|
||||||
|
import io.smallrye.config.ConfigMapping;
|
||||||
|
import java.time.Duration;
|
||||||
|
|
||||||
|
@ConfigMapping(prefix = "connector.variable.bulk-value-sending")
|
||||||
|
public interface VariableBulkValueSendingConfig {
|
||||||
|
int maxQueueSize();
|
||||||
|
Duration maxDelayForFirstValue();
|
||||||
|
Duration maxWaitTimeForNextValue();
|
||||||
|
}
|
||||||
18
src/main/java/io/gec/raw/connector/config/entity/ConnectorConfig.java
Executable file
18
src/main/java/io/gec/raw/connector/config/entity/ConnectorConfig.java
Executable file
@@ -0,0 +1,18 @@
|
|||||||
|
package io.gec.raw.connector.config.entity;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
@Getter
|
||||||
|
public class ConnectorConfig {
|
||||||
|
@ConfigProperty(name = "connector.id")
|
||||||
|
UUID connectorId;
|
||||||
|
@ConfigProperty(name = "connector.name")
|
||||||
|
String connectorName;
|
||||||
|
@ConfigProperty(name = "connector.description")
|
||||||
|
String connectorDescription;
|
||||||
|
}
|
||||||
50
src/main/java/io/gec/raw/connector/config/entity/SnmpConfig.java
Executable file
50
src/main/java/io/gec/raw/connector/config/entity/SnmpConfig.java
Executable file
@@ -0,0 +1,50 @@
|
|||||||
|
package io.gec.raw.connector.config.entity;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import lombok.Getter;
|
||||||
|
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
@Getter
|
||||||
|
public class SnmpConfig {
|
||||||
|
@Inject
|
||||||
|
SnmpConnectionTypesConfig snmpConnectionTypesConfig;
|
||||||
|
|
||||||
|
@ConfigProperty(name = "snmp.message-dispatcher-pool-size")
|
||||||
|
int messageDispatcherPoolSize;
|
||||||
|
|
||||||
|
@ConfigProperty(name = "snmp.scheduled-tasks.pool-size")
|
||||||
|
int scheduledTasksPoolSize;
|
||||||
|
|
||||||
|
@ConfigProperty(name = "snmp.dynamic-table.pool-size")
|
||||||
|
int dynamicTablePoolSize;
|
||||||
|
@ConfigProperty(name = "snmp.dynamic-table.default-pooling-interval")
|
||||||
|
int dynamicTableDefaultPoolingInterval;
|
||||||
|
|
||||||
|
@ConfigProperty(name = "snmp.discovery.deprecated-protocols")
|
||||||
|
Optional<List<String>> discoveryDeprecatedProtocols;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.root-oid")
|
||||||
|
String discoveryRootOid;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.pool-size")
|
||||||
|
int discoveryPoolSize;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.initial-get-retries")
|
||||||
|
int discoveryInitialGetRetries;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.initial-get-timeout")
|
||||||
|
Long discoveryInitialGetTimeout;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.bulk-get-retries")
|
||||||
|
int discoveryBulkGetRetries;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.bulk-get-timeout")
|
||||||
|
Long discoveryBulkGetTimeout;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.get-retries")
|
||||||
|
int discoveryGetRetries;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.get-timeout")
|
||||||
|
Long discoveryGetTimeout;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.set-retries")
|
||||||
|
int discoverySetRetries;
|
||||||
|
@ConfigProperty(name = "snmp.discovery.set-timeout")
|
||||||
|
Long discoverySetTimeout;
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
package io.gec.raw.connector.config.entity;
|
||||||
|
|
||||||
|
import io.smallrye.config.ConfigMapping;
|
||||||
|
import io.smallrye.config.WithParentName;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ConfigMapping(prefix = "snmp.connection-types")
|
||||||
|
public interface SnmpConnectionTypesConfig {
|
||||||
|
@WithParentName
|
||||||
|
Map<String, Connection> connectionTypes();
|
||||||
|
|
||||||
|
interface Connection {
|
||||||
|
int port();
|
||||||
|
String protocol();
|
||||||
|
String hostname();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
package io.gec.raw.connector.connector.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.driver.control.DeviceDriverController;
|
||||||
|
import io.gec.raw.connector.protocol.domain.CommunicationProtocolEnum;
|
||||||
|
import io.gec.raw.connector.protocol.domain.SnmpVersionEnum;
|
||||||
|
import io.gec.raw.connector.communicationservice.control.CommunicationServiceController;
|
||||||
|
import io.gec.raw.connector.config.control.ConnectorConfigController;
|
||||||
|
import io.gec.raw.connector.config.entity.ConnectorConfig;
|
||||||
|
import io.gec.raw.connector.connector.dto.ConnectorRequestDTO;
|
||||||
|
import io.gec.raw.connector.connector.dto.ConnectorRequestDTO.ConnectorRequestDTOBuilder;
|
||||||
|
import io.gec.raw.connector.connector.dto.ConnectorResponseDTO;
|
||||||
|
import io.gec.raw.connector.protocol.control.ProtocolMapper;
|
||||||
|
import io.gec.raw.connector.protocol.control.ProtocolService;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ConnectorController {
|
||||||
|
private final ConnectorConfig connectorConfig;
|
||||||
|
private final ConnectorConfigController connectorConfigController;
|
||||||
|
private final CommunicationServiceController communicationServiceController;
|
||||||
|
private final DeviceDriverController deviceDriverController;
|
||||||
|
private final ProtocolService protocolService;
|
||||||
|
private final ConnectorUtils connectorUtils;
|
||||||
|
private final ProtocolMapper protocolMapper;
|
||||||
|
private final Logger logger;
|
||||||
|
|
||||||
|
public ConnectorController(ConnectorConfig connectorConfig,
|
||||||
|
ConnectorConfigController connectorConfigController,
|
||||||
|
CommunicationServiceController communicationServiceController,
|
||||||
|
DeviceDriverController deviceDriverController,
|
||||||
|
ProtocolService protocolService,
|
||||||
|
ConnectorUtils connectorUtils,
|
||||||
|
ProtocolMapper protocolMapper,
|
||||||
|
Logger logger) {
|
||||||
|
this.connectorConfig = connectorConfig;
|
||||||
|
this.connectorConfigController = connectorConfigController;
|
||||||
|
this.communicationServiceController = communicationServiceController;
|
||||||
|
this.deviceDriverController = deviceDriverController;
|
||||||
|
this.protocolService = protocolService;
|
||||||
|
this.connectorUtils = connectorUtils;
|
||||||
|
this.protocolMapper = protocolMapper;
|
||||||
|
this.logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<ConnectorResponseDTO> registerOnServer() {
|
||||||
|
ConnectorRequestDTO connectorRequestDTO = buildConnector();
|
||||||
|
|
||||||
|
var connectorRegisterResult = communicationServiceController.registerConnector(connectorRequestDTO);
|
||||||
|
if (connectorRegisterResult.isPresent()) {
|
||||||
|
protocolService.createOrUpdateProtocols(connectorRegisterResult.get().getProtocols());
|
||||||
|
deviceDriverController.synchronizeDrivers();
|
||||||
|
return connectorRegisterResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
ConnectorRequestDTO buildConnector() {
|
||||||
|
ConnectorRequestDTOBuilder connectorRequestDTOBuilder = ConnectorRequestDTO.builder();
|
||||||
|
String version = connectorConfigController.getConnectorVersion();
|
||||||
|
|
||||||
|
try {
|
||||||
|
connectorRequestDTOBuilder
|
||||||
|
.id(connectorConfig.getConnectorId())
|
||||||
|
.name(getConnectorName())
|
||||||
|
.description(connectorConfig.getConnectorDescription())
|
||||||
|
.ipAddress(InetAddress.getLocalHost().getHostAddress())
|
||||||
|
.userId(UUID.randomUUID())
|
||||||
|
.version(version)
|
||||||
|
.connectorProtocols(protocolMapper.getProtocols(List.of(
|
||||||
|
SnmpVersionEnum.SNMP_V1,
|
||||||
|
SnmpVersionEnum.SNMP_V2C,
|
||||||
|
SnmpVersionEnum.SNMP_V3,
|
||||||
|
CommunicationProtocolEnum.SFTP)));
|
||||||
|
} catch (Exception ex) {
|
||||||
|
logger.error("Error building the connector: " + ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
return connectorRequestDTOBuilder.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getConnectorName() throws SocketException, UnknownHostException {
|
||||||
|
return connectorConfig.getConnectorName().isEmpty()
|
||||||
|
? connectorUtils.getMacAddress()
|
||||||
|
: connectorConfig.getConnectorName();
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/main/java/io/gec/raw/connector/connector/control/ConnectorUtils.java
Executable file
22
src/main/java/io/gec/raw/connector/connector/control/ConnectorUtils.java
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
package io.gec.raw.connector.connector.control;
|
||||||
|
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
|
||||||
|
import java.net.InetAddress;
|
||||||
|
import java.net.NetworkInterface;
|
||||||
|
import java.net.SocketException;
|
||||||
|
import java.net.UnknownHostException;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ConnectorUtils {
|
||||||
|
|
||||||
|
public String getMacAddress() throws SocketException, UnknownHostException {
|
||||||
|
NetworkInterface network = NetworkInterface.getByInetAddress(InetAddress.getLocalHost());
|
||||||
|
byte[] mac = network.getHardwareAddress();
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (int i = 0; i < mac.length; i++) {
|
||||||
|
sb.append(String.format("%02X%s", mac[i], (i < mac.length - 1) ? "-" : ""));
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
27
src/main/java/io/gec/raw/connector/connector/dto/ConnectorRequestDTO.java
Executable file
27
src/main/java/io/gec/raw/connector/connector/dto/ConnectorRequestDTO.java
Executable file
@@ -0,0 +1,27 @@
|
|||||||
|
/*
|
||||||
|
* (c) 2023 German Edge Cloud GmbH & Co. KG
|
||||||
|
*/
|
||||||
|
package io.gec.raw.connector.connector.dto;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.protocol.dto.ProtocolDTO;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Value
|
||||||
|
@Builder
|
||||||
|
public class ConnectorRequestDTO {
|
||||||
|
|
||||||
|
UUID id;
|
||||||
|
String name;
|
||||||
|
String description;
|
||||||
|
String ipAddress;
|
||||||
|
UUID userId;
|
||||||
|
String version;
|
||||||
|
|
||||||
|
@Builder.Default
|
||||||
|
List<ProtocolDTO> connectorProtocols = new ArrayList<>();
|
||||||
|
}
|
||||||
19
src/main/java/io/gec/raw/connector/connector/dto/ConnectorResponseDTO.java
Executable file
19
src/main/java/io/gec/raw/connector/connector/dto/ConnectorResponseDTO.java
Executable file
@@ -0,0 +1,19 @@
|
|||||||
|
package io.gec.raw.connector.connector.dto;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.protocol.dto.ProtocolDTO;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Value;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Builder
|
||||||
|
@Value
|
||||||
|
public class ConnectorResponseDTO {
|
||||||
|
|
||||||
|
UUID id;
|
||||||
|
String name;
|
||||||
|
String description;
|
||||||
|
String ipAddress;
|
||||||
|
List<ProtocolDTO> protocols;
|
||||||
|
}
|
||||||
7
src/main/java/io/gec/raw/connector/connector/dto/DataTypeEnum.java
Executable file
7
src/main/java/io/gec/raw/connector/connector/dto/DataTypeEnum.java
Executable file
@@ -0,0 +1,7 @@
|
|||||||
|
package io.gec.raw.connector.connector.dto;
|
||||||
|
|
||||||
|
public enum DataTypeEnum {
|
||||||
|
|
||||||
|
STRING,
|
||||||
|
INTEGER;
|
||||||
|
}
|
||||||
10
src/main/java/io/gec/raw/connector/connector/dto/RepresentationEnum.java
Executable file
10
src/main/java/io/gec/raw/connector/connector/dto/RepresentationEnum.java
Executable file
@@ -0,0 +1,10 @@
|
|||||||
|
package io.gec.raw.connector.connector.dto;
|
||||||
|
|
||||||
|
public enum RepresentationEnum {
|
||||||
|
|
||||||
|
TEXT,
|
||||||
|
PASSWORD,
|
||||||
|
DATE,
|
||||||
|
NUMBER,
|
||||||
|
IPV4;
|
||||||
|
}
|
||||||
598
src/main/java/io/gec/raw/connector/device/control/DeviceController.java
Executable file
598
src/main/java/io/gec/raw/connector/device/control/DeviceController.java
Executable file
@@ -0,0 +1,598 @@
|
|||||||
|
package io.gec.raw.connector.device.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.communicationservice.control.CommunicationService;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.device.domain.DeviceMapping;
|
||||||
|
import io.gec.raw.connector.device.dto.DeviceDTO;
|
||||||
|
import io.gec.raw.connector.device.dto.DeviceResponseDTO;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import io.gec.raw.connector.device.enums.RittalDevicePropertyNameEnum;
|
||||||
|
import io.gec.raw.connector.deviceproperty.control.DevicePropertyController;
|
||||||
|
import io.gec.raw.connector.deviceproperty.control.DevicePropertyExtractor;
|
||||||
|
import io.gec.raw.connector.deviceproperty.control.DevicePropertyRepository;
|
||||||
|
import io.gec.raw.connector.deviceproperty.dto.DevicePropertyDTO;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DeviceProperty;
|
||||||
|
import io.gec.raw.connector.variable.control.VariableController;
|
||||||
|
import io.gec.raw.connector.variable.control.VariableMapper;
|
||||||
|
import io.gec.raw.connector.variable.dto.VariableDTO;
|
||||||
|
import io.gec.raw.connector.variable.entity.Variable;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import org.eclipse.microprofile.rest.client.inject.RestClient;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class DeviceController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
EntityManager em;
|
||||||
|
@Inject
|
||||||
|
VariableMapper variableMapper;
|
||||||
|
@Inject
|
||||||
|
VariableController variableController;
|
||||||
|
@Inject
|
||||||
|
DevicePropertyController devicePropertyController;
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
@Inject
|
||||||
|
DevicePropertyRepository devicePropertyRepository;
|
||||||
|
@Inject
|
||||||
|
@RestClient
|
||||||
|
CommunicationService communicationService;
|
||||||
|
@Inject
|
||||||
|
DeviceRepository deviceRepository;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Device storeDevice(DeviceMapping deviceMapping, UUID plantId, UUID parentId) throws Exception {
|
||||||
|
assert deviceMapping != null : "Device mapping is null";
|
||||||
|
assert plantId != null : "PlantId is null";
|
||||||
|
|
||||||
|
logger.infof("Processing Device (index:'%s', name:'%s', description:'%s') for DiscoveryWorkItem (ID:'%s') ...", deviceMapping.getDeviceIndex(), deviceMapping.getName(),
|
||||||
|
deviceMapping.getDescription(), deviceMapping.getDiscoveryWorkItemId());
|
||||||
|
|
||||||
|
Device device;
|
||||||
|
Optional<String> deviceSerialNumber = findPropertyValueByName(deviceMapping.getProperties(),
|
||||||
|
RittalDevicePropertyNameEnum.SERIAL_NUMBER.getLabel());
|
||||||
|
|
||||||
|
if (deviceSerialNumber.isPresent()) {
|
||||||
|
device = handleDeviceWithSerialNumber(deviceMapping, plantId, parentId, deviceSerialNumber.get());
|
||||||
|
} else {
|
||||||
|
device = handleDeviceWithoutSerialNumber(deviceMapping, plantId, parentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
processSubDevices(deviceMapping, plantId, device.getId());
|
||||||
|
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void processSubDevices(DeviceMapping device, UUID plantId, UUID parentId) throws Exception {
|
||||||
|
logger.infof("Processing sub-devices for Device (ID:'%s') - total: %d ", device.getId(), device.getSubDevices().size());
|
||||||
|
for (DeviceMapping subDevice : device.getSubDevices()) {
|
||||||
|
storeDevice(subDevice, plantId, parentId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Device getDeviceByCommSvcId(UUID commSvcId) {
|
||||||
|
return deviceRepository.getDeviceByCommSvcId(commSvcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Integer> getAccessDeviceIndexesByRootDeviceId(UUID rootDeviceId) {
|
||||||
|
return deviceRepository.getAccessDeviceIndexes(rootDeviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Device handleDeviceWithSerialNumber(DeviceMapping deviceMapping,
|
||||||
|
UUID plantId,
|
||||||
|
UUID parentId,
|
||||||
|
String serialNumber) {
|
||||||
|
var optionalDevice = findUniqueDeviceBySerialNumber(serialNumber, deviceMapping.isRoot(), plantId);
|
||||||
|
|
||||||
|
return optionalDevice.map(device -> updateDeviceFromDiscovery(device, deviceMapping))
|
||||||
|
.orElseGet(() -> createDeviceFromDiscovery(deviceMapping, plantId, parentId));
|
||||||
|
}
|
||||||
|
|
||||||
|
Device handleDeviceWithoutSerialNumber(DeviceMapping deviceData,
|
||||||
|
UUID plantId,
|
||||||
|
UUID parentId) {
|
||||||
|
assert parentId != null : "Parent ID is null but expected for devices without serial number.";
|
||||||
|
logger.infof("Processing device without Serial Number (name:'%s')", deviceData.getName());
|
||||||
|
|
||||||
|
Device parentDevice = getDeviceById(parentId);
|
||||||
|
assert parentDevice != null : "Parent device not found for device without serial number. parentId: " + parentId;
|
||||||
|
|
||||||
|
List<Device> subDevices = getDevicesByParentId(parentDevice.getId());
|
||||||
|
|
||||||
|
return subDevices.stream()
|
||||||
|
.filter(device -> device.getDescription().equals(deviceData.getDescription()))
|
||||||
|
.findFirst()
|
||||||
|
.filter(device -> device.getPlantId().equals(plantId))
|
||||||
|
.map(device -> updateDeviceFromDiscovery(device, deviceData))
|
||||||
|
.orElseGet(() -> createDeviceFromDiscovery(deviceData, plantId, parentDevice.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Device createDeviceFromDiscovery(DeviceMapping deviceMapping, UUID plantId, UUID parentId) {
|
||||||
|
assert deviceMapping != null : "Device is null";
|
||||||
|
assert plantId != null : "PlantId is null";
|
||||||
|
|
||||||
|
Device device = toDevice(deviceMapping, plantId, parentId);
|
||||||
|
em.persist(device);
|
||||||
|
logger.debugf("Device (ID:'%s', name: '%s') created", device.getId(), deviceMapping.getName());
|
||||||
|
|
||||||
|
variableController.createVariables(deviceMapping.getVariables(), device.getId());
|
||||||
|
devicePropertyController.createProperties(deviceMapping.getProperties(), device.getId());
|
||||||
|
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<String> findPropertyValueByName(List<? extends DevicePropertyExtractor> properties, String propertyName) {
|
||||||
|
if (properties == null || properties.isEmpty()) {
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
return properties.stream()
|
||||||
|
.filter(property -> propertyName.equals(property.getName()))
|
||||||
|
.findFirst()
|
||||||
|
.map(DevicePropertyExtractor::getValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Device updateDeviceFromDiscovery(Device device, DeviceMapping deviceData) {
|
||||||
|
assert device != null : "Device is null";
|
||||||
|
assert deviceData != null : "DeviceData is null";
|
||||||
|
|
||||||
|
device = updateDeviceData(device, deviceData);
|
||||||
|
|
||||||
|
communicationService.addLatestDeviceDiscoveryAndArchiveOldDeviceDiscovery(
|
||||||
|
deviceData.getDiscoveryWorkItemId(), device.getId());
|
||||||
|
logger.debugf("Updated discovery work item ID for device: %s", device.getId());
|
||||||
|
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Device updateDeviceData(Device device, DeviceMapping deviceData) {
|
||||||
|
assert device != null : "Device is null";
|
||||||
|
assert deviceData != null : "DeviceData is null";
|
||||||
|
|
||||||
|
logger.debugf("Device (ID:'%s', name:'%s') updated", device.getId(), device.getName());
|
||||||
|
|
||||||
|
device.setDiscoveryWorkItemId(deviceData.getDiscoveryWorkItemId());
|
||||||
|
device.setName(deviceData.getName());
|
||||||
|
device.setDescription(deviceData.getDescription());
|
||||||
|
device.setDeviceURL(deviceData.getDeviceURL());
|
||||||
|
device.setType(deviceData.getType());
|
||||||
|
device.setDeviceIndex(deviceData.getDeviceIndex());
|
||||||
|
device.setMode(deviceData.getMode());
|
||||||
|
|
||||||
|
variableController.createVariablesIfNotExistByName(deviceData.getVariables(), device.getId());
|
||||||
|
devicePropertyController.createPropertiesIfNotExistByName(deviceData.getProperties(), device.getId());
|
||||||
|
|
||||||
|
return em.merge(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Device> findUniqueDeviceBySerialNumber(String serialNumber, boolean isRootDevice, UUID plantId) {
|
||||||
|
var devicesWithSerialNumber = deviceRepository.findBySerialNumber(serialNumber, isRootDevice, plantId);
|
||||||
|
|
||||||
|
if (devicesWithSerialNumber.size() > 1) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
String.format("More than one device found for Serial Number:'%s', isRootDevice:'%s'", serialNumber, isRootDevice));
|
||||||
|
}
|
||||||
|
|
||||||
|
return devicesWithSerialNumber.stream().findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public Device toDevice(DeviceMapping deviceMapping, UUID plantId, UUID parentId) {
|
||||||
|
assert deviceMapping != null : "DeviceMapping is null";
|
||||||
|
assert plantId != null : "PlantId is null";
|
||||||
|
Device device = new Device();
|
||||||
|
device.setName(deviceMapping.getName());
|
||||||
|
device.setDescription(deviceMapping.getDescription() != null ? deviceMapping.getDescription() : "");
|
||||||
|
device.setDiscoveryWorkItemId(deviceMapping.getDiscoveryWorkItemId());
|
||||||
|
device.setConnectorId(deviceMapping.getConnectorId());
|
||||||
|
device.setPlantId(plantId);
|
||||||
|
device.setDeviceURL(deviceMapping.getDeviceURL());
|
||||||
|
device.setType(deviceMapping.getType());
|
||||||
|
device.setParentId(parentId);
|
||||||
|
device.setMode(ComponentMode.PAUSE);
|
||||||
|
device.setRestoreMode(ComponentMode.PAUSE);
|
||||||
|
device.setDriverHeaderId(deviceMapping.getDriverHeaderId());
|
||||||
|
device.setDeviceIndex(deviceMapping.getDeviceIndex());
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<UUID> findDeviceIdByDeviceUrl(String deviceURL) {
|
||||||
|
return deviceRepository.findDeviceIdByDeviceUrl(deviceURL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a {@link Device} object from the database based on its unique identifier.
|
||||||
|
* <p>
|
||||||
|
* This method fetches the device details corresponding to the provided {@code deviceId}. It performs a null check on the input parameter and logs appropriate messages based on
|
||||||
|
* whether the device is found or not.
|
||||||
|
*
|
||||||
|
* @param deviceId The unique identifier of the device to be retrieved. It must not be null.
|
||||||
|
* @return The {@link Device} object associated with the given {@code deviceId}, or {@code null} if no such device is found or if {@code deviceId} is null.
|
||||||
|
*/
|
||||||
|
public Device getDeviceById(UUID deviceId) {
|
||||||
|
|
||||||
|
if (deviceId == null) {
|
||||||
|
logger.error("Device ID is null.");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Start getting Device by ID: " + deviceId);
|
||||||
|
|
||||||
|
Optional<Device> device = deviceRepository.findByIdOptional(deviceId);
|
||||||
|
|
||||||
|
if (device.isEmpty()) {
|
||||||
|
logger.debug("No device found for ID: " + deviceId);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("Device found for ID: " + deviceId);
|
||||||
|
return device.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the root device in the hierarchy starting from the specified device.
|
||||||
|
* <p>
|
||||||
|
* This method iteratively traverses up the device hierarchy starting from the given device until it finds the root device. A root device is identified as a device that does
|
||||||
|
* not have a parent. If the input device or its ID is {@code null}, an {@link IllegalArgumentException} is thrown.
|
||||||
|
* <p>
|
||||||
|
* Note: This method operates recursively and may perform multiple database queries to find the root device.
|
||||||
|
*
|
||||||
|
* @param device The starting device from which to find the root device. Must not be {@code null}.
|
||||||
|
* @return The root {@link Device} of the provided device hierarchy.
|
||||||
|
* @throws IllegalArgumentException if the provided device or its ID is {@code null}.
|
||||||
|
*/
|
||||||
|
public Device getRootDevice(Device device) {
|
||||||
|
if (device == null || device.getId() == null) {
|
||||||
|
logger.error("#getRootDevice device is empty or Null: ");
|
||||||
|
throw new IllegalArgumentException("device is empty or Null");
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("1/2 #getRootDevice Start getting root Device for IP ofDevice with Id: " + device.getId());
|
||||||
|
while (device.getParentId() != null) {
|
||||||
|
device = deviceRepository.findById(device.getParentId());
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("2/2 #getRootDevice Finished getting root Device for IP ofDevice with Id: " + device.getId() + "Root Device Id: " + device.getId());
|
||||||
|
return device;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructs a device tree for a communication service starting from a specified device ID.
|
||||||
|
* <p>
|
||||||
|
* This method retrieves a device from the database using the given {@code deviceId} and then recursively builds a tree structure of all its sub-devices. Each device in the
|
||||||
|
* tree is converted to a {@code Device} object suitable for communication services. The tree includes the root device and all its hierarchical sub-devices.
|
||||||
|
*
|
||||||
|
* @param deviceId The unique identifier of the root device from which to start building the tree. Must not be {@code null}.
|
||||||
|
* @return A {@code Device} object representing the root of the device tree, including all its sub-devices.
|
||||||
|
* @throws IllegalArgumentException if the {@code deviceId} is {@code null} or if no device is found with the given ID.
|
||||||
|
*/
|
||||||
|
public DeviceDTO getDeviceTreeForCommSvc(UUID deviceId) {
|
||||||
|
if (deviceId == null) {
|
||||||
|
throw new IllegalArgumentException("Device ID is required but null was provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
Device deviceFromDB = em.find(Device.class, deviceId);
|
||||||
|
if (deviceFromDB == null) {
|
||||||
|
throw new IllegalArgumentException("Device (ID:'%s') not found".formatted(deviceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Device> subDevices = deviceRepository.getSubDevices(deviceFromDB.getId());
|
||||||
|
|
||||||
|
DeviceDTO tempDeviceDTO = createCommSvcDeviceDTO(deviceFromDB.getId());
|
||||||
|
|
||||||
|
ArrayList<DeviceDTO> subDeviceDTOs = subDevices.stream()
|
||||||
|
.map(subDevice -> getDeviceTreeForCommSvc(subDevice.getId()))
|
||||||
|
.collect(Collectors.toCollection(ArrayList::new));
|
||||||
|
|
||||||
|
tempDeviceDTO.setSubDevices(subDeviceDTOs);
|
||||||
|
return tempDeviceDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link DeviceDTO} object for communication services based on a specified root device ID.
|
||||||
|
* <p>
|
||||||
|
* This method retrieves an {@link Device} from the database using the provided {@code rootDeviceId} and converts it into a {@link DeviceDTO} object. It also fetches and sets
|
||||||
|
* the associated variables and properties for the device. Additionally, it retrieves and sets all direct sub-devices of the root device, along with their own sub-devices,
|
||||||
|
* effectively building a partial device tree.
|
||||||
|
*
|
||||||
|
* @param rootDeviceId The unique identifier of the root device to be converted. Must not be {@code null}.
|
||||||
|
* @return A {@link DeviceDTO} object representing the root device with its variables, properties, and sub-devices.
|
||||||
|
* @throws IllegalArgumentException if the {@code rootDeviceId} is {@code null} or if no device is found with the given ID.
|
||||||
|
*/
|
||||||
|
public DeviceDTO createCommSvcDeviceDTO(UUID rootDeviceId) {
|
||||||
|
if (rootDeviceId == null) {
|
||||||
|
throw new IllegalArgumentException("Root device ID must not be null");
|
||||||
|
}
|
||||||
|
|
||||||
|
Device rootDevice = em.find(Device.class, rootDeviceId);
|
||||||
|
if (rootDevice == null) {
|
||||||
|
throw new IllegalArgumentException("Root Device (ID:'%s') not found".formatted(rootDeviceId));
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceDTO rootDeviceDTO = DeviceDTO.from(rootDevice);
|
||||||
|
|
||||||
|
List<Variable> variables = variableController.getVariablesByDeviceId(rootDeviceId);
|
||||||
|
List<DeviceProperty> deviceProperties = devicePropertyRepository.findByDeviceId(rootDeviceId);
|
||||||
|
|
||||||
|
List<VariableDTO> variableDTOs = variableMapper.toVariableDTOs(variables);
|
||||||
|
List<DevicePropertyDTO> devicePropertyDTOs = toDevicePropertyDTOs(deviceProperties);
|
||||||
|
|
||||||
|
rootDeviceDTO.setVariables(variableDTOs);
|
||||||
|
rootDeviceDTO.setProperties(devicePropertyDTOs);
|
||||||
|
|
||||||
|
List<DeviceDTO> subDeviceDTOs = getCommSvcDevicesByParentId(rootDeviceId);
|
||||||
|
rootDeviceDTO.setSubDevices(subDeviceDTOs);
|
||||||
|
|
||||||
|
setCommSvcParentIdAndSubDevices(rootDeviceDTO.getSubDevices(), rootDeviceDTO.getId()); // Recursive call for sub-devices
|
||||||
|
|
||||||
|
return rootDeviceDTO;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Device getDeviceByDeviceIndex(UUID rootDeviceId, Integer deviceIndex) {
|
||||||
|
if (deviceIndex == null) {
|
||||||
|
throw new IllegalArgumentException("Device index required but null was provided");
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<Device> rootDevice = deviceRepository.findByIdOptional(rootDeviceId);
|
||||||
|
return rootDevice.map(device -> traverseDeviceTree(device, deviceIndex))
|
||||||
|
.orElse(null);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private Device traverseDeviceTree(Device device, Integer deviceIndex) {
|
||||||
|
List<Device> subDevices = deviceRepository.getSubDevices(device.getId());
|
||||||
|
|
||||||
|
for (Device subDevice : subDevices) {
|
||||||
|
if (deviceIndex.equals(subDevice.getDeviceIndex())) {
|
||||||
|
return subDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
Device result = traverseDeviceTree(subDevice, deviceIndex);
|
||||||
|
if (Objects.nonNull(result)) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCommSvcParentIdAndSubDevices(List<DeviceDTO> subDeviceDTOs, UUID commSvcParentId) {
|
||||||
|
for (DeviceDTO subDeviceDTO : subDeviceDTOs) {
|
||||||
|
subDeviceDTO.setParentId(commSvcParentId);
|
||||||
|
|
||||||
|
List<DeviceDTO> subSubDeviceDTOs = getCommSvcDevicesByParentId(subDeviceDTO.getConnectorDeviceId());
|
||||||
|
subDeviceDTO.setSubDevices(subSubDeviceDTOs);
|
||||||
|
|
||||||
|
setCommSvcParentIdAndSubDevices(subDeviceDTO.getSubDevices(), subDeviceDTO.getId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateModeByCommSvcId(UUID commSvcId, ComponentMode mode) {
|
||||||
|
var device = deviceRepository.getDeviceByCommSvcId(commSvcId);
|
||||||
|
if (device == null) {
|
||||||
|
throw new EntityNotFoundException("Device (CommSvcID:'%s') not found.".formatted(commSvcId));
|
||||||
|
}
|
||||||
|
updateMode(device, mode);
|
||||||
|
logger.infof("Device (CommSvcID:'%s') mode set to:'%s'", commSvcId, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateMode(Device device, ComponentMode mode) {
|
||||||
|
if (device.getMode().isRestorable()) {
|
||||||
|
device.setRestoreMode(device.getMode());
|
||||||
|
}
|
||||||
|
device.setMode(mode);
|
||||||
|
em.merge(device);
|
||||||
|
switch (mode) {
|
||||||
|
case PAUSE -> {
|
||||||
|
unsubscribeDeviceProperties(device.getId());
|
||||||
|
unsubscribeVariables(device.getId());
|
||||||
|
}
|
||||||
|
case OPERATION -> {
|
||||||
|
subscribeDeviceProperties(device.getId());
|
||||||
|
subscribeVariables(device.getId());
|
||||||
|
}
|
||||||
|
case FIRMWARE_UPDATE, OFFLINE -> {
|
||||||
|
updateModeRecursive(device, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void restoreModeByCommSvcId(UUID commSvcId) {
|
||||||
|
var device = deviceRepository.getDeviceByCommSvcId(commSvcId);
|
||||||
|
|
||||||
|
restoreModeRecursive(device);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreModeRecursive(Device device) {
|
||||||
|
restoreMode(device);
|
||||||
|
|
||||||
|
deviceRepository.getSubDevices(device.getId())
|
||||||
|
.forEach(this::restoreModeRecursive);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateModeRecursive(Device device, ComponentMode mode) {
|
||||||
|
updatePropertyMode(device.getId(), mode);
|
||||||
|
updateVariableMode(device.getId(), mode);
|
||||||
|
|
||||||
|
deviceRepository.getSubDevices(device.getId())
|
||||||
|
.forEach(subDevice -> updateMode(subDevice, mode));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Device> getSubDevices(UUID deviceId) {
|
||||||
|
if (deviceId == null) {
|
||||||
|
throw new IllegalArgumentException("Device id required but null was provided");
|
||||||
|
}
|
||||||
|
return deviceRepository.getSubDevices(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void restoreMode(Device device) {
|
||||||
|
Objects.requireNonNull(device, "Device required to restore mode");
|
||||||
|
restoreDeviceMode(device);
|
||||||
|
restoreVariableMode(device.getId());
|
||||||
|
restorePropertyMode(device.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void restoreDeviceMode(Device device) {
|
||||||
|
Objects.requireNonNull(device, "Device required to restore mode");
|
||||||
|
updateModeWithRestoreMode(device);
|
||||||
|
|
||||||
|
logger.debugf("Device (ID:'%s') mode restored to:'%s'", device.getId(), device.getMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateModeWithRestoreMode(Device device) {
|
||||||
|
if (device != null) {
|
||||||
|
ComponentMode restoreMode = device.getRestoreMode();
|
||||||
|
device.setMode(restoreMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restoreVariableMode(UUID deviceId) {
|
||||||
|
for (Variable variable : variableController.getVariablesByDeviceId(deviceId)) {
|
||||||
|
variableController.restoreMode(variable);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void restorePropertyMode(UUID deviceId) {
|
||||||
|
for (DeviceProperty property : devicePropertyController.findByDeviceId(deviceId)) {
|
||||||
|
devicePropertyController.restoreMode(property);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unsubscribeVariables(UUID deviceId) {
|
||||||
|
for (Variable variable : variableController.getVariablesByDeviceId(deviceId)) {
|
||||||
|
variableController.updateMode(variable, ComponentMode.PAUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void unsubscribeDeviceProperties(UUID deviceId) {
|
||||||
|
for (DeviceProperty property : devicePropertyController.findByDeviceId(deviceId)) {
|
||||||
|
devicePropertyController.updateMode(property, ComponentMode.PAUSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateVariableMode(UUID deviceId, ComponentMode mode) {
|
||||||
|
for (Variable variable : variableController.getVariablesByDeviceId(deviceId)) {
|
||||||
|
variableController.updateMode(variable, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePropertyMode(UUID deviceId, ComponentMode mode) {
|
||||||
|
for (DeviceProperty property : devicePropertyController.findByDeviceId(deviceId)) {
|
||||||
|
devicePropertyController.updateMode(property, mode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void subscribeVariables(UUID deviceId) {
|
||||||
|
for (Variable variable : variableController.getVariablesByDeviceId(deviceId)) {
|
||||||
|
variableController.updateMode(variable, ComponentMode.OPERATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void subscribeDeviceProperties(UUID deviceId) {
|
||||||
|
for (DeviceProperty property : devicePropertyController.findByDeviceId(deviceId)) {
|
||||||
|
devicePropertyController.updateMode(property, ComponentMode.OPERATION);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DevicePropertyDTO> toDevicePropertyDTOs(List<DeviceProperty> properties) {
|
||||||
|
return properties.stream()
|
||||||
|
.map(DevicePropertyDTO::from)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Device> getDevicesByParentId(UUID parentId) {
|
||||||
|
if (parentId == null) {
|
||||||
|
return new ArrayList<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
return deviceRepository.findByParentId(parentId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves a list of {@link DeviceDTO} objects that are direct sub-devices of a specified parent device.
|
||||||
|
* <p>
|
||||||
|
* This method fetches all {@link Device} entities that have the specified {@code parentId} from the database. Each of these Device entities is then converted into a Device
|
||||||
|
* object. Additionally, for each Device object, associated variables and properties are fetched and set. The method effectively maps a list of Device entities to a list of
|
||||||
|
* Device objects, ready for use in various services or business logic.
|
||||||
|
*
|
||||||
|
* @param parentId The unique identifier of the parent device whose sub-devices are to be retrieved. Can be {@code null}, in which case an empty list is returned.
|
||||||
|
* @return A list of {@link DeviceDTO} objects, each representing a sub-device of the specified parent. Returns an empty list if no sub-devices are found or if the
|
||||||
|
* {@code parentId} is {@code null}.
|
||||||
|
*/
|
||||||
|
private List<DeviceDTO> getCommSvcDevicesByParentId(UUID parentId) {
|
||||||
|
List<Device> subDevices = getDevicesByParentId(parentId);
|
||||||
|
|
||||||
|
ArrayList<DeviceDTO> mappedSubdevices = new ArrayList<>();
|
||||||
|
subDevices.forEach(deviceEntity -> {
|
||||||
|
DeviceDTO deviceDTO = DeviceDTO.from(deviceEntity);
|
||||||
|
|
||||||
|
List<Variable> variables = variableController.getVariablesByDeviceId(deviceEntity.getId());
|
||||||
|
List<DeviceProperty> properties = devicePropertyRepository.findByDeviceId(deviceEntity.getId());
|
||||||
|
|
||||||
|
List<VariableDTO> variableDTOs = variableMapper.toVariableDTOs(variables);
|
||||||
|
List<DevicePropertyDTO> devicePropertyDTOs = toDevicePropertyDTOs(properties);
|
||||||
|
|
||||||
|
deviceDTO.setVariables(variableDTOs);
|
||||||
|
deviceDTO.setProperties(devicePropertyDTOs);
|
||||||
|
mappedSubdevices.add(deviceDTO);
|
||||||
|
});
|
||||||
|
|
||||||
|
return mappedSubdevices;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateCommSvcId(DeviceResponseDTO deviceResponseDTO) {
|
||||||
|
updateCommSvcIdHelper(deviceResponseDTO);
|
||||||
|
deviceResponseDTO.getSubdevices().forEach(this::updateCommSvcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the communication service ID of a device and associated variables and properties based on the provided device response.
|
||||||
|
* <p>
|
||||||
|
* This method updates the 'commServiceId' field of a device in the database using the ID provided in the {@link DeviceResponseDTO}. It also updates the communication service
|
||||||
|
* IDs for the device's variables and properties. If no device is updated in the database (indicating no matching device was found), a warning is logged. The method delegates
|
||||||
|
* the updating of variables and properties to their respective controllers.
|
||||||
|
*
|
||||||
|
* @param deviceResponseDTO The {@link DeviceResponseDTO} containing the new communication service ID and identifiers for the device and its variables and properties.
|
||||||
|
*/
|
||||||
|
private void updateCommSvcIdHelper(DeviceResponseDTO deviceResponseDTO) {
|
||||||
|
if (deviceResponseDTO == null) {
|
||||||
|
logger.error("DeviceResponseDTO is null.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int result = em.createQuery("UPDATE device SET commServiceId = :CommSvcId WHERE id = :ConnectorDeviceId")
|
||||||
|
.setParameter("CommSvcId", deviceResponseDTO.getId())
|
||||||
|
.setParameter("ConnectorDeviceId", deviceResponseDTO.getConnectorDeviceId())
|
||||||
|
.executeUpdate();
|
||||||
|
|
||||||
|
if (result == 0) {
|
||||||
|
logger.warn(
|
||||||
|
"Update of Device (ID:'%s') to set CommSvcId:'%s' - without success, no row updated".formatted(deviceResponseDTO.getConnectorDeviceId(),
|
||||||
|
deviceResponseDTO.getId()));
|
||||||
|
}
|
||||||
|
|
||||||
|
variableController.updateCommSvcId(deviceResponseDTO.getVariables());
|
||||||
|
devicePropertyController.updateCommSvcId(deviceResponseDTO.getProperties());
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Device> findAllRootDevices() {
|
||||||
|
return deviceRepository.findAllRootDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
136
src/main/java/io/gec/raw/connector/device/control/DeviceRepository.java
Executable file
136
src/main/java/io/gec/raw/connector/device/control/DeviceRepository.java
Executable file
@@ -0,0 +1,136 @@
|
|||||||
|
package io.gec.raw.connector.device.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import io.gec.raw.connector.device.enums.RittalDeviceConstants;
|
||||||
|
import io.gec.raw.connector.device.enums.RittalDevicePropertyNameEnum;
|
||||||
|
import io.gec.raw.connector.device.projection.DeviceParentIdProjection;
|
||||||
|
import io.gec.raw.connector.device.projection.DeviceURLProjection;
|
||||||
|
import io.gec.raw.connector.utils.control.IPAddressHelper;
|
||||||
|
import io.quarkus.hibernate.orm.panache.PanacheRepositoryBase;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.persistence.EntityManager;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class DeviceRepository implements PanacheRepositoryBase<Device, UUID> {
|
||||||
|
|
||||||
|
private static final String DEVICE_ID = "deviceId";
|
||||||
|
@Inject
|
||||||
|
EntityManager em;
|
||||||
|
@Inject
|
||||||
|
IPAddressHelper ipAddressHelper;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Optional<DeviceURLProjection> findDeviceURLProjection(UUID id) {
|
||||||
|
return find("id", id)
|
||||||
|
.project(DeviceURLProjection.class)
|
||||||
|
.firstResultOptional();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Optional<DeviceParentIdProjection> findDeviceParentIdProjection(UUID id) {
|
||||||
|
return find("id", id)
|
||||||
|
.project(DeviceParentIdProjection.class)
|
||||||
|
.firstResultOptional();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<UUID> findDeviceIdsByParentId(UUID parentId) {
|
||||||
|
return Optional.ofNullable(parentId).map(id -> stream("parentId", id)
|
||||||
|
.map(Device::getId)
|
||||||
|
.toList())
|
||||||
|
.orElse(List.of());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Optional<UUID> findDeviceIdByDeviceUrl(String deviceUrl) {
|
||||||
|
return this.findByDeviceUrl(deviceUrl)
|
||||||
|
.map(Device::getId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void subscribe(UUID id) {
|
||||||
|
setSubscribed(id, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void unsubscribe(UUID id) {
|
||||||
|
setSubscribed(id, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubscribed(UUID id, boolean subscribed) {
|
||||||
|
update("subscribed = ?1 where id = ?2", subscribed, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<Integer> getAccessDeviceIndexes(UUID deviceId) {
|
||||||
|
return em.createQuery("SELECT d.deviceIndex FROM device d WHERE d.parentId =: deviceId AND d.type =:accessDevOid", Integer.class)
|
||||||
|
.setParameter("deviceId", deviceId)
|
||||||
|
.setParameter("accessDevOid", RittalDeviceConstants.ACCESS_DEVICE_TYPE_OID)
|
||||||
|
.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Device getDeviceByCommSvcId(UUID commDeviceId) {
|
||||||
|
return em.createQuery("SELECT d FROM device d WHERE d.commServiceId =: commDeviceId", Device.class)
|
||||||
|
.setParameter("commDeviceId", commDeviceId)
|
||||||
|
.getSingleResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Optional<Device> findByDeviceUrl(String deviceUrl) {
|
||||||
|
return Optional.ofNullable(deviceUrl).flatMap(url -> stream("deviceURL is not null")
|
||||||
|
.filter(device -> ipAddressHelper.removeHttpFromIpAddress(device.getDeviceURL()).equals(url))
|
||||||
|
.findFirst());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<Device> getSubDevices(UUID parentDeviceId) {
|
||||||
|
return em.createQuery("FROM device WHERE parentId = :deviceId", Device.class)
|
||||||
|
.setParameter(DEVICE_ID, parentDeviceId)
|
||||||
|
.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Device> findBySerialNumber(String serialNumber, boolean isRootDevice, UUID plantId) {
|
||||||
|
String queryString = """
|
||||||
|
SELECT d FROM device d
|
||||||
|
JOIN deviceproperty property ON property.deviceId = d.id
|
||||||
|
WHERE
|
||||||
|
property.name = :propertyName AND
|
||||||
|
property.valueAsString = :propertyStringValue AND
|
||||||
|
d.plantId = :plantId
|
||||||
|
""";
|
||||||
|
|
||||||
|
if (isRootDevice) {
|
||||||
|
queryString += " AND d.parentId IS NULL";
|
||||||
|
} else {
|
||||||
|
queryString += " AND d.parentId IS NOT NULL";
|
||||||
|
}
|
||||||
|
|
||||||
|
return em.createQuery(queryString, Device.class)
|
||||||
|
.setParameter("propertyName", RittalDevicePropertyNameEnum.SERIAL_NUMBER.getLabel())
|
||||||
|
.setParameter("propertyStringValue", serialNumber)
|
||||||
|
.setParameter("plantId", plantId)
|
||||||
|
.getResultList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateMode(UUID id, ComponentMode mode) {
|
||||||
|
update("mode = ?1 where id = ?2", mode, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Device> findAllRootDevices() {
|
||||||
|
return stream("parentId is null")
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Device> findByParentId(UUID parentId) {
|
||||||
|
return find("parentId", parentId)
|
||||||
|
.list();
|
||||||
|
}
|
||||||
|
}
|
||||||
153
src/main/java/io/gec/raw/connector/device/control/DeviceStructureService.java
Executable file
153
src/main/java/io/gec/raw/connector/device/control/DeviceStructureService.java
Executable file
@@ -0,0 +1,153 @@
|
|||||||
|
package io.gec.raw.connector.device.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.device.domain.DeviceMapping;
|
||||||
|
import io.gec.raw.connector.device.domain.DeviceOidValueMap;
|
||||||
|
import io.gec.raw.connector.device.enums.AccessDeviceTypeEnum;
|
||||||
|
import io.gec.raw.connector.device.enums.RittalDeviceConstants;
|
||||||
|
import io.gec.raw.connector.device.enums.RittalDevicePropertyNameEnum;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DevicePropertyMapping;
|
||||||
|
import io.gec.raw.connector.variable.entity.Variable;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static io.gec.raw.connector.device.enums.AccessDeviceTypeEnum.ACCESS_HANDLE;
|
||||||
|
import static io.gec.raw.connector.device.enums.AccessDeviceTypeEnum.ACCESS_KEYPAD;
|
||||||
|
import static java.util.stream.Collectors.groupingBy;
|
||||||
|
import static java.util.stream.Collectors.partitioningBy;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class DeviceStructureService {
|
||||||
|
|
||||||
|
private static final String VARIABLE_DOT_SEPARATOR = ".";
|
||||||
|
private static final Map<String, AccessDeviceTypeEnum> DESCRIPTION_TO_TYPE_MAP = Map.of(
|
||||||
|
RittalDeviceConstants.ACCESS_HANDLE_DEVICE_NAME, ACCESS_HANDLE,
|
||||||
|
RittalDeviceConstants.ACCESS_KEYPAD_DEVICE_NAME, ACCESS_KEYPAD
|
||||||
|
);
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ExternalDeviceBuilder externalDeviceBuilder;
|
||||||
|
@Inject
|
||||||
|
RittalDeviceBuilder rittalDeviceBuilder;
|
||||||
|
|
||||||
|
public DeviceMapping createRittalDeviceStructure(DeviceOidValueMap oidValueMap,
|
||||||
|
UUID connectorId,
|
||||||
|
UUID discoveryWorkItemId,
|
||||||
|
String hostname) throws NumberFormatException {
|
||||||
|
DeviceMapping rootDeviceTree = rittalDeviceBuilder.buildDeviceTree(oidValueMap, connectorId, discoveryWorkItemId, hostname);
|
||||||
|
|
||||||
|
rootDeviceTree.getSubDevices().forEach(rootSubDevice -> {
|
||||||
|
List<DeviceMapping> subDevices = rootSubDevice.getSubDevices();
|
||||||
|
|
||||||
|
var variablesPartitionedByDot = rootSubDevice.getVariables().stream()
|
||||||
|
.collect(partitioningBy(this::variableNameContainsDot));
|
||||||
|
|
||||||
|
var variablesWithDotInName = variablesPartitionedByDot.get(true);
|
||||||
|
|
||||||
|
Map<String, List<Variable>> variablesByDeviceName = groupByDeviceName(variablesWithDotInName);
|
||||||
|
List<String> deviceNames = List.copyOf(variablesByDeviceName.keySet());
|
||||||
|
|
||||||
|
variablesByDeviceName.forEach((deviceName, variables) -> {
|
||||||
|
int devicePosition = deviceNames.indexOf(deviceName) + 1;
|
||||||
|
DeviceMapping deviceMapping = createDeviceMappingFromVariables(deviceName, devicePosition, variables, rootSubDevice, oidValueMap);
|
||||||
|
subDevices.add(deviceMapping);
|
||||||
|
});
|
||||||
|
|
||||||
|
var variablesWithoutDotInName = variablesPartitionedByDot.get(false);
|
||||||
|
rootSubDevice.setVariables(variablesWithoutDotInName);
|
||||||
|
});
|
||||||
|
|
||||||
|
return rootDeviceTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceMapping createExternalDeviceStructure(DeviceOidValueMap oidValueMap,
|
||||||
|
UUID connectorId,
|
||||||
|
UUID dwiId,
|
||||||
|
UUID driverHeaderId,
|
||||||
|
String key) throws NumberFormatException {
|
||||||
|
return externalDeviceBuilder.buildDeviceTree(oidValueMap, connectorId, dwiId, driverHeaderId, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean variableNameContainsDot(Variable variable) {
|
||||||
|
return variable.getName().contains(VARIABLE_DOT_SEPARATOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LinkedHashMap<String, List<Variable>> groupByDeviceName(List<Variable> variablesWithDotInName) {
|
||||||
|
return variablesWithDotInName.stream()
|
||||||
|
.collect(groupingBy(this::getVariableNamePartBeforeDot, LinkedHashMap::new, Collectors.toList()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private String getVariableNamePartBeforeDot(Variable variable) {
|
||||||
|
return variable.getName().substring(0, variable.getName().indexOf(VARIABLE_DOT_SEPARATOR));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DeviceMapping createDeviceMappingFromVariables(String deviceName, int devicePosition,
|
||||||
|
List<Variable> variables,
|
||||||
|
DeviceMapping rootSubDevice,
|
||||||
|
DeviceOidValueMap oidValueMap) {
|
||||||
|
List<DevicePropertyMapping> devicePropertyMappings = createSubDeviceProperties(deviceName, devicePosition, variables, rootSubDevice, oidValueMap);
|
||||||
|
String deviceAlias = toDeviceAlias(devicePropertyMappings, deviceName);
|
||||||
|
|
||||||
|
return DeviceMapping.builder()
|
||||||
|
.name(deviceAlias)
|
||||||
|
.description(deviceName)
|
||||||
|
.connectorId(rootSubDevice.getConnectorId())
|
||||||
|
.discoveryWorkItemId(rootSubDevice.getDiscoveryWorkItemId())
|
||||||
|
.variables(variables)
|
||||||
|
.properties(devicePropertyMappings)
|
||||||
|
.isRoot(false)
|
||||||
|
.deviceIndex(rootSubDevice.getDeviceIndex()) // INFO: HAVE TO BE SAME AS FOR PARENT DEVICE - used in access log area
|
||||||
|
.mode(rootSubDevice.getMode())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DevicePropertyMapping> createSubDeviceProperties(String deviceName, int devicePosition,
|
||||||
|
List<Variable> variables,
|
||||||
|
DeviceMapping rootSubDevice,
|
||||||
|
DeviceOidValueMap oidValueMap) {
|
||||||
|
Optional<DevicePropertyMapping> sensorDeviceAlias = rittalDeviceBuilder.getDeviceAliasPropertyByVariables(variables, oidValueMap);
|
||||||
|
Optional<DevicePropertyMapping> accessDeviceType = Optional.ofNullable(toAccessDeviceTypeProperty(deviceName, rootSubDevice, oidValueMap));
|
||||||
|
Optional<DevicePropertyMapping> bus = findPropertyMapping(rootSubDevice.getProperties(), RittalDevicePropertyNameEnum.BUS);
|
||||||
|
Optional<DevicePropertyMapping> position = createPositionProperty(devicePosition);
|
||||||
|
|
||||||
|
return Stream.of(sensorDeviceAlias, accessDeviceType, bus, position)
|
||||||
|
.flatMap(Optional::stream)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private DevicePropertyMapping toAccessDeviceTypeProperty(String deviceName, DeviceMapping rootSubDevice, DeviceOidValueMap oidValueMap) {
|
||||||
|
if (rootSubDevice != null
|
||||||
|
&& RittalDeviceConstants.ACCESS_DEVICE_TYPE_OID.equals(rootSubDevice.getType())
|
||||||
|
&& DESCRIPTION_TO_TYPE_MAP.containsKey(deviceName)) {
|
||||||
|
return rittalDeviceBuilder.createAccessDeviceTypeProperty(oidValueMap, DESCRIPTION_TO_TYPE_MAP.get(deviceName));
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<DevicePropertyMapping> findPropertyMapping(List<DevicePropertyMapping> devicePropertyMappings, RittalDevicePropertyNameEnum name) {
|
||||||
|
return devicePropertyMappings.stream()
|
||||||
|
.filter(propertyMapping -> name.getLabel().equals(propertyMapping.getName()))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Optional<DevicePropertyMapping> createPositionProperty(int devicePosition) {
|
||||||
|
return Optional.of(DevicePropertyMapping.builder()
|
||||||
|
.name(RittalDevicePropertyNameEnum.POSITION.getLabel())
|
||||||
|
.value(String.valueOf(devicePosition))
|
||||||
|
.valueDatatype(RittalDevicePropertyNameEnum.POSITION.getDataType().name())
|
||||||
|
.readOnly(true)
|
||||||
|
.mode(ComponentMode.PAUSE)
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toDeviceAlias(List<DevicePropertyMapping> devicePropertyMappings, String deviceName) {
|
||||||
|
return findPropertyMapping(devicePropertyMappings, RittalDevicePropertyNameEnum.DEVICE_ALIAS)
|
||||||
|
.map(DevicePropertyMapping::getValue)
|
||||||
|
.orElse(deviceName);
|
||||||
|
}
|
||||||
|
}
|
||||||
112
src/main/java/io/gec/raw/connector/device/control/ExternalDeviceBuilder.java
Executable file
112
src/main/java/io/gec/raw/connector/device/control/ExternalDeviceBuilder.java
Executable file
@@ -0,0 +1,112 @@
|
|||||||
|
package io.gec.raw.connector.device.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.driver.entity.DriverVariable;
|
||||||
|
import io.gec.raw.connector.driver.control.DriverVariableRepository;
|
||||||
|
import io.gec.raw.connector.variable.entity.Variable;
|
||||||
|
import io.gec.raw.connector.device.domain.DeviceOidValueMap;
|
||||||
|
import io.gec.raw.connector.device.entity.AccessTypeEnum;
|
||||||
|
import io.gec.raw.connector.device.entity.DataTypeEnum;
|
||||||
|
import io.gec.raw.connector.device.domain.DeviceMapping;
|
||||||
|
import io.gec.raw.connector.variable.entity.VarTypeEnum;
|
||||||
|
import io.gec.raw.connector.device.enums.ExternalDevicePropertyEnum;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DevicePropertyMapping;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
import static io.gec.raw.connector.deviceproperty.entity.DevicePropertyMapping.createPropertyMapping;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class ExternalDeviceBuilder {
|
||||||
|
|
||||||
|
public static final String NO_QUALITY_OID = "NO_QUALITY_OID";
|
||||||
|
private static final String HTTPS_PREFIX = "https://";
|
||||||
|
@Inject
|
||||||
|
DriverVariableRepository driverVariableRepository;
|
||||||
|
|
||||||
|
public DeviceMapping buildDeviceTree(DeviceOidValueMap oidValueMap, UUID connectorId, UUID discoveryWorkItemId, UUID driverHeaderId, String key)
|
||||||
|
throws NumberFormatException {
|
||||||
|
return DeviceMapping.builder()
|
||||||
|
.name(oidValueMap.getSysName())
|
||||||
|
.description(oidValueMap.getSysDescr())
|
||||||
|
.connectorId(connectorId)
|
||||||
|
.deviceURL(HTTPS_PREFIX + key)
|
||||||
|
.discoveryWorkItemId(discoveryWorkItemId)
|
||||||
|
.variables(createVariables(driverHeaderId))
|
||||||
|
.properties(createProperties(oidValueMap))
|
||||||
|
.driverHeaderId(driverHeaderId)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<Variable> createVariables(UUID driverHeaderId) {
|
||||||
|
List<DriverVariable> driverVariableList = driverVariableRepository.findByDriverHeaderId(driverHeaderId);
|
||||||
|
|
||||||
|
return driverVariableList.stream()
|
||||||
|
.map(this::toVariable)
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<DevicePropertyMapping> createProperties(DeviceOidValueMap oidValueMap) {
|
||||||
|
return List.of(
|
||||||
|
createPropertyMapping(ExternalDevicePropertyEnum.DESCRIPTION, oidValueMap.getSysDescr()),
|
||||||
|
createPropertyMapping(ExternalDevicePropertyEnum.NAME, oidValueMap.getSysName()),
|
||||||
|
createPropertyMapping(ExternalDevicePropertyEnum.LOCATION, oidValueMap.getSysLocation()),
|
||||||
|
createPropertyMapping(ExternalDevicePropertyEnum.CONTACT, oidValueMap.getSysContact()),
|
||||||
|
createPropertyMapping(ExternalDevicePropertyEnum.SERIAL_NUMBER, oidValueMap.getSysDescr())
|
||||||
|
//TODO add hardcoded properties
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Variable toVariable(DriverVariable driverVariable) {
|
||||||
|
return Variable.builder()
|
||||||
|
.name(driverVariable.getName())
|
||||||
|
.description(driverVariable.getDescription())
|
||||||
|
.min(Integer.valueOf(driverVariable.getMin()))
|
||||||
|
.max(Integer.valueOf(driverVariable.getMax()))
|
||||||
|
.varType(VarTypeEnum.VALUE)
|
||||||
|
.varDataType(driverVariable.getDataType())
|
||||||
|
.snmpSetVarDataType(driverVariable.getDataType())
|
||||||
|
.scale(Integer.parseInt(driverVariable.getScale()))
|
||||||
|
.step(Integer.parseInt(driverVariable.getStep()))
|
||||||
|
.varAccessType(toVarAccessType(driverVariable))
|
||||||
|
.varQualityOid(NO_QUALITY_OID)
|
||||||
|
.valueAsIntegerOid(toValueAsIntegerOid(driverVariable))
|
||||||
|
.valueAsStringOid(toValueAsStringOid(driverVariable))
|
||||||
|
.subscriptionInterval(Integer.parseInt(driverVariable.getIntervalFactor()))
|
||||||
|
.driverVariableId(driverVariable.getId())
|
||||||
|
.functionType(driverVariable.getFunctionType())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private AccessTypeEnum toVarAccessType(DriverVariable driverVariable) {
|
||||||
|
return driverVariable.getIsReadOnly()
|
||||||
|
? AccessTypeEnum.READONLY
|
||||||
|
: AccessTypeEnum.READWRITE;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toValueAsIntegerOid(DriverVariable driverVariable) {
|
||||||
|
if (isRepresentedByNumber(driverVariable)) {
|
||||||
|
return driverVariable.getOid();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private String toValueAsStringOid(DriverVariable driverVariable) {
|
||||||
|
if (!isRepresentedByNumber(driverVariable)) {
|
||||||
|
return driverVariable.getOid();
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isRepresentedByNumber(DriverVariable driverVariable) {
|
||||||
|
return driverVariable.getDataType().equals(DataTypeEnum.INTEGER)
|
||||||
|
|| driverVariable.getDataType().equals(DataTypeEnum.FLOAT)
|
||||||
|
|| driverVariable.getDataType().equals(DataTypeEnum.NUMERIC)
|
||||||
|
|| driverVariable.getDataType().equals(DataTypeEnum.STATUSINT)
|
||||||
|
|| driverVariable.getDataType().equals(DataTypeEnum.ANALOGINT);
|
||||||
|
}
|
||||||
|
}
|
||||||
354
src/main/java/io/gec/raw/connector/device/control/RittalDeviceBuilder.java
Executable file
354
src/main/java/io/gec/raw/connector/device/control/RittalDeviceBuilder.java
Executable file
@@ -0,0 +1,354 @@
|
|||||||
|
package io.gec.raw.connector.device.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.device.domain.DeviceMapping;
|
||||||
|
import io.gec.raw.connector.device.domain.DeviceOidValueMap;
|
||||||
|
import io.gec.raw.connector.device.entity.AccessTypeEnum;
|
||||||
|
import io.gec.raw.connector.device.entity.DataTypeEnum;
|
||||||
|
import io.gec.raw.connector.device.enums.*;
|
||||||
|
import io.gec.raw.connector.deviceproperty.control.DeviceTypeProvider;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DevicePropertyMapping;
|
||||||
|
import io.gec.raw.connector.utils.control.RittalVariableConfigList;
|
||||||
|
import io.gec.raw.connector.utils.control.ValueScalingHelper;
|
||||||
|
import io.gec.raw.connector.variable.control.VariableConstraintParser;
|
||||||
|
import io.gec.raw.connector.variable.entity.VarTypeEnum;
|
||||||
|
import io.gec.raw.connector.variable.entity.Variable;
|
||||||
|
import jakarta.annotation.Nullable;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
|
||||||
|
import java.util.*;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import static io.gec.raw.connector.device.enums.VariableFieldName.*;
|
||||||
|
import static io.gec.raw.connector.utils.control.RittalVariableConfigList.excludedVariableNameList;
|
||||||
|
import static java.lang.Integer.parseInt;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class RittalDeviceBuilder {
|
||||||
|
@Inject
|
||||||
|
VariableConstraintParser constraintParser;
|
||||||
|
@Inject
|
||||||
|
ValueScalingHelper scalingHelper;
|
||||||
|
@Inject
|
||||||
|
DeviceTypeProvider deviceTypeProvider;
|
||||||
|
|
||||||
|
public DeviceMapping buildDeviceTree(DeviceOidValueMap oidValueMap, UUID connectorId, UUID discoveryWorkItemId, String hostname)
|
||||||
|
throws NumberFormatException {
|
||||||
|
DeviceMapping rootDevice = DeviceMapping.builder()
|
||||||
|
.deviceURL(RittalDeviceConstants.HTTPS_PREFIX + hostname)
|
||||||
|
.name(oidValueMap.getSysName())
|
||||||
|
.description(oidValueMap.getSysDescr())
|
||||||
|
.connectorId(connectorId)
|
||||||
|
.discoveryWorkItemId(discoveryWorkItemId)
|
||||||
|
.properties(buildRootDeviceProperties(oidValueMap, hostname))
|
||||||
|
.mode(ComponentMode.PAUSE)
|
||||||
|
.isRoot(true)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
int numberOfDevices = parseInt((oidValueMap.get(".1.3.6.1.4.1.2606.7.4.1.1.2.0").toString()));
|
||||||
|
var deviceIndexes = getDeviceIndexes(oidValueMap, numberOfDevices);
|
||||||
|
|
||||||
|
for (int subDevNumber = 0; subDevNumber < numberOfDevices; subDevNumber++) {
|
||||||
|
rootDevice.getSubDevices().add(buildSubDevice(oidValueMap, deviceIndexes[subDevNumber], connectorId, discoveryWorkItemId));
|
||||||
|
}
|
||||||
|
|
||||||
|
return rootDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] getDeviceIndexes(DeviceOidValueMap oidValueMap, int numberOfDevices) {
|
||||||
|
int deviceCounter = 1;
|
||||||
|
int deviceResultCounter = 0;
|
||||||
|
int[] result = new int[numberOfDevices];
|
||||||
|
|
||||||
|
while (deviceResultCounter < numberOfDevices && deviceCounter <= numberOfDevices) {
|
||||||
|
var searchString = oidValueMap.get(String.format(".1.3.6.1.4.1.2606.7.4.1.2.1.2.%s", deviceCounter));
|
||||||
|
if (searchString != null) {
|
||||||
|
result[deviceResultCounter++] = deviceCounter;
|
||||||
|
}
|
||||||
|
deviceCounter++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
DeviceMapping buildSubDevice(DeviceOidValueMap oidValueMap, int subDevNumber, UUID connectorId, UUID discoveryWorkItemId) {
|
||||||
|
var deviceName = oidValueMap.get(RittalDevicePropertyNameEnum.NAME.getIndexedOid(subDevNumber)).toString();
|
||||||
|
var deviceAlias = oidValueMap.get(RittalDevicePropertyNameEnum.DEVICE_ALIAS.getIndexedOid(subDevNumber)).toString();
|
||||||
|
|
||||||
|
DeviceMapping subDevice = DeviceMapping.builder()
|
||||||
|
.description(deviceName)
|
||||||
|
.type(oidValueMap.get(RittalDevicePropertyNameEnum.TYPE.getIndexedOid(subDevNumber)).toString())
|
||||||
|
.name(deviceAlias.isEmpty() ? deviceName : deviceAlias)
|
||||||
|
.properties(buildSubDeviceProperties(subDevNumber, oidValueMap))
|
||||||
|
.connectorId(connectorId)
|
||||||
|
.discoveryWorkItemId(discoveryWorkItemId)
|
||||||
|
.isRoot(false)
|
||||||
|
.mode(ComponentMode.PAUSE)
|
||||||
|
.deviceIndex(subDevNumber)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
int numberSnmpVars = parseInt(oidValueMap.get(RittalDevicePropertyNameEnum.NUMBER_OF_VARIABLES.getIndexedOid(subDevNumber)).toString());
|
||||||
|
if (numberSnmpVars > 0) {
|
||||||
|
subDevice.setVariables(buildVariables(numberSnmpVars, subDevNumber, oidValueMap));
|
||||||
|
}
|
||||||
|
|
||||||
|
return subDevice;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DevicePropertyMapping> buildRootDeviceProperties(DeviceOidValueMap oidValueMap, String hostname) {
|
||||||
|
List<DevicePropertyMapping> properties = Stream.of(
|
||||||
|
RittalDevicePropertyNameEnum.ROOT_SERIAL_NUMBER,
|
||||||
|
RittalDevicePropertyNameEnum.ROOT_HARDWARE_VERSION,
|
||||||
|
RittalDevicePropertyNameEnum.ROOT_SOFTWARE_VERSION,
|
||||||
|
RittalDevicePropertyNameEnum.ROOT_PRODUCTION_CODE,
|
||||||
|
RittalDevicePropertyNameEnum.ROOT_UNIT_TYPE
|
||||||
|
).map(property -> createPropertyMapping(property, oidValueMap, null))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
properties.add(createAccessDeviceTypeProperty(oidValueMap, AccessDeviceTypeEnum.ACCESS_MANAGEMENT_DEVICE));
|
||||||
|
properties.add(createIpAddressProperty(hostname));
|
||||||
|
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Variable> buildVariables(int numberSnmpVars, int subDeviceIndex, DeviceOidValueMap oidValueMap) {
|
||||||
|
return IntStream.rangeClosed(1, numberSnmpVars)
|
||||||
|
.mapToObj(varIndex -> buildVariableFromSnmpVar(varIndex, subDeviceIndex, oidValueMap))
|
||||||
|
.filter(variable -> !isVariableExcluded(variable.getName()))
|
||||||
|
.toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<DevicePropertyMapping> buildSubDeviceProperties(int subDevNumber, DeviceOidValueMap oidValueMap) {
|
||||||
|
List<DevicePropertyMapping> properties = Stream.of(
|
||||||
|
RittalDevicePropertyNameEnum.DEVICE_ALIAS,
|
||||||
|
RittalDevicePropertyNameEnum.NAME,
|
||||||
|
RittalDevicePropertyNameEnum.TYPE,
|
||||||
|
RittalDevicePropertyNameEnum.NODE_ID,
|
||||||
|
RittalDevicePropertyNameEnum.STATUS,
|
||||||
|
RittalDevicePropertyNameEnum.MODEL_NUMBER,
|
||||||
|
RittalDevicePropertyNameEnum.LOCATION,
|
||||||
|
RittalDevicePropertyNameEnum.BUS,
|
||||||
|
RittalDevicePropertyNameEnum.POSITION,
|
||||||
|
RittalDevicePropertyNameEnum.SOFTWARE_VERSION,
|
||||||
|
RittalDevicePropertyNameEnum.HARDWARE_VERSION,
|
||||||
|
RittalDevicePropertyNameEnum.SERIAL_NUMBER,
|
||||||
|
RittalDevicePropertyNameEnum.NUMBER_OF_VARIABLES,
|
||||||
|
RittalDevicePropertyNameEnum.STATUS_TEXT)
|
||||||
|
.map(property -> createPropertyMapping(property, oidValueMap, subDevNumber))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
getAccessDeviceTypeProperty(oidValueMap, subDevNumber).ifPresent(properties::add);
|
||||||
|
return properties;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<DevicePropertyMapping> getAccessDeviceTypeProperty(DeviceOidValueMap oidValueMap, Integer deviceIndex) {
|
||||||
|
var typeValue = oidValueMap.get(RittalDevicePropertyNameEnum.TYPE.getIndexedOid(deviceIndex)).toString();
|
||||||
|
if (RittalDeviceConstants.ACCESS_DEVICE_TYPE_OID.equals(typeValue)) {
|
||||||
|
var accessDeviceTypeProperty = createAccessDeviceTypeProperty(oidValueMap, AccessDeviceTypeEnum.ACCESS_DEVICE);
|
||||||
|
return Optional.of(accessDeviceTypeProperty);
|
||||||
|
}
|
||||||
|
return Optional.empty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DevicePropertyMapping createAccessDeviceTypeProperty(DeviceOidValueMap oidValueMap, AccessDeviceTypeEnum accessDeviceType) {
|
||||||
|
var accessDeviceTypeProperty = createPropertyMapping(RittalDevicePropertyNameEnum.ACCESS_DEVICE_TYPE, oidValueMap, null);
|
||||||
|
accessDeviceTypeProperty.setValue(accessDeviceType.name());
|
||||||
|
|
||||||
|
return accessDeviceTypeProperty;
|
||||||
|
}
|
||||||
|
|
||||||
|
DevicePropertyMapping createIpAddressProperty(String hostname) {
|
||||||
|
return createPropertyMapping(RittalDevicePropertyNameEnum.ROOT_IP_ADDRESS, hostname);
|
||||||
|
}
|
||||||
|
|
||||||
|
DevicePropertyMapping createPropertyMapping(RittalDevicePropertyNameEnum rittalDevicePropertyNameEnum, String value) {
|
||||||
|
return createPropertyMapping(
|
||||||
|
rittalDevicePropertyNameEnum.getLabel(),
|
||||||
|
null,
|
||||||
|
value,
|
||||||
|
rittalDevicePropertyNameEnum.getDataType().name(),
|
||||||
|
rittalDevicePropertyNameEnum.isReadOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
DevicePropertyMapping createPropertyMapping(RittalDevicePropertyNameEnum rittalDevicePropertyEnum, DeviceOidValueMap oidValueMap, @Nullable Integer deviceIndex) {
|
||||||
|
var oid = deviceIndex == null ? rittalDevicePropertyEnum.getBaseOid() : rittalDevicePropertyEnum.getIndexedOid(deviceIndex);
|
||||||
|
var value = Optional.ofNullable(oidValueMap.get(oid))
|
||||||
|
.orElse(RittalDeviceConstants.PROPERTY_NO_VALUE)
|
||||||
|
.toString();
|
||||||
|
|
||||||
|
if (rittalDevicePropertyEnum == RittalDevicePropertyNameEnum.TYPE) {
|
||||||
|
value = deviceTypeProvider.findByOid(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
return createPropertyMapping(rittalDevicePropertyEnum.getLabel(), oid, value, rittalDevicePropertyEnum.getDataType().name(), rittalDevicePropertyEnum.isReadOnly());
|
||||||
|
}
|
||||||
|
|
||||||
|
private DevicePropertyMapping createPropertyMapping(String name, String oid, String value, String valueDataType, boolean readOnly) {
|
||||||
|
return DevicePropertyMapping.builder()
|
||||||
|
.oid(oid)
|
||||||
|
.name(name)
|
||||||
|
.value(value)
|
||||||
|
.valueDatatype(valueDataType)
|
||||||
|
.readOnly(readOnly)
|
||||||
|
.mode(ComponentMode.PAUSE)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<DevicePropertyMapping> getDeviceAliasPropertyByVariables(List<Variable> sensorVariables,
|
||||||
|
DeviceOidValueMap oidValueMap) {
|
||||||
|
return sensorVariables.stream()
|
||||||
|
.filter(variable -> variable.getName().toLowerCase().endsWith(RittalDeviceConstants.VARIABLE_DESC_NAME))
|
||||||
|
.findFirst()
|
||||||
|
.map(descNameVariable -> toDeviceAliasProperty(oidValueMap, descNameVariable));
|
||||||
|
}
|
||||||
|
|
||||||
|
private DevicePropertyMapping toDeviceAliasProperty(DeviceOidValueMap oidValueMap, Variable v) {
|
||||||
|
return DevicePropertyMapping.builder()
|
||||||
|
.oid(v.getValueAsStringOid())
|
||||||
|
.name(RittalDevicePropertyNameEnum.DEVICE_ALIAS.getLabel())
|
||||||
|
.value(String.valueOf(oidValueMap.getOrDefault(v.getValueAsStringOid(), RittalDeviceConstants.PROPERTY_NO_VALUE)))
|
||||||
|
.valueDatatype(PropertyClassType.STRING.name())
|
||||||
|
.mode(ComponentMode.PAUSE)
|
||||||
|
.readOnly(false)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean isVariableExcluded(String variableName) {
|
||||||
|
return excludedVariableNameList.stream()
|
||||||
|
.anyMatch(excludedVariableName ->
|
||||||
|
variableName.toLowerCase().endsWith(excludedVariableName)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Variable buildVariableFromSnmpVar(int varStartIndex, int subDeviceIndex, DeviceOidValueMap oidValueMap) {
|
||||||
|
VarTypeEnum varType = VarTypeEnum.findByNumber(parseInt(getOidValue(oidValueMap, VARTYPE, subDeviceIndex, varStartIndex)[1]));
|
||||||
|
DataTypeEnum varDataType = DataTypeEnum.findByNumber(parseInt(getOidValue(oidValueMap, DATATYPE, subDeviceIndex, varStartIndex)[1]));
|
||||||
|
AccessTypeEnum varAccessType = AccessTypeEnum.findByNumber(parseInt(getOidValue(oidValueMap, ACCESS, subDeviceIndex, varStartIndex)[1]));
|
||||||
|
Variable variable = new Variable();
|
||||||
|
variable.setName(getOidValue(oidValueMap, NAME, subDeviceIndex, varStartIndex)[1]);
|
||||||
|
variable.setVarType(varType);
|
||||||
|
variable.setUnit(getOidValue(oidValueMap, UNIT, subDeviceIndex, varStartIndex)[1]);
|
||||||
|
variable.setVarDataType(varDataType);
|
||||||
|
variable.setSnmpSetVarDataType(varDataType);
|
||||||
|
variable.setScale(getOidValue(oidValueMap, SCALE, subDeviceIndex, varStartIndex)[1]);
|
||||||
|
variable.setConstraints(constraintParser.parseConstraints(getOidValue(oidValueMap, CONSTRAINTS, subDeviceIndex, varStartIndex)[1]));
|
||||||
|
variable.setStep(getOidValue(oidValueMap, STEPS, subDeviceIndex, varStartIndex)[1]);
|
||||||
|
variable.setMode(ComponentMode.PAUSE);
|
||||||
|
variable.setVarAccessType(varAccessType);
|
||||||
|
|
||||||
|
//INFO: String and Int Values
|
||||||
|
String[] stringResult = getOidValue(oidValueMap, VALUESTRING, subDeviceIndex, varStartIndex);
|
||||||
|
String[] integerResult = getOidValue(oidValueMap, VALUEINT, subDeviceIndex, varStartIndex);
|
||||||
|
variable.setValueAsStringOid(stringResult[0]);
|
||||||
|
variable.setValueAsIntegerOid(integerResult[0]);
|
||||||
|
|
||||||
|
//INFO: Quality
|
||||||
|
var qualityResult = getOidValue(oidValueMap, QUALITY, subDeviceIndex, varStartIndex);
|
||||||
|
variable.setVarQualityOid(qualityResult[0]);
|
||||||
|
|
||||||
|
variable.setSubscriptionInterval(getInterval(variable));
|
||||||
|
variable.setVarDataType(getType(variable));
|
||||||
|
variable.setFunctionType(getFunctionType(variable));
|
||||||
|
|
||||||
|
if (variable.getSnmpSetVarDataType() == DataTypeEnum.INTEGER) {
|
||||||
|
var minMaxMap = constraintParser.parseMinMaxConstraint(variable.getConstraints());
|
||||||
|
if (minMaxMap.get("min") != null) {
|
||||||
|
variable.setMin(scalingHelper.scaleNumericValueFromDevice(minMaxMap.get("min"), variable.getScale()));
|
||||||
|
}
|
||||||
|
if (minMaxMap.get("max") != null) {
|
||||||
|
variable.setMax(scalingHelper.scaleNumericValueFromDevice(minMaxMap.get("max"), variable.getScale()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//INFO: If min max Null Ignore
|
||||||
|
return variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Intervals
|
||||||
|
/*
|
||||||
|
* 5 minutes for SetPtHigh and SetPtLow for Alarm and Warnings.
|
||||||
|
5 minutes for DescName, Hysteresis, Category, Offset
|
||||||
|
5 minutes for Circuit, Socket Type, Grouping
|
||||||
|
10 secs for Values, Usage, Signal, Position
|
||||||
|
30 secs for Status, Relay
|
||||||
|
once : Size
|
||||||
|
*/
|
||||||
|
int getInterval(Variable variable) {
|
||||||
|
var tempName = variable.getName();
|
||||||
|
if (tempName.contains("Value") || tempName.contains("Usage") ||
|
||||||
|
tempName.contains("Signal") || tempName.contains("Position")) {
|
||||||
|
return 10;
|
||||||
|
} else if (tempName.contains("Status") || tempName.contains("Relay")) {
|
||||||
|
return 30;
|
||||||
|
} else if (tempName.contains("Size")) {
|
||||||
|
return 1800;
|
||||||
|
}
|
||||||
|
return 300;
|
||||||
|
}
|
||||||
|
|
||||||
|
FunctionTypeEnum getFunctionType(Variable variable) {
|
||||||
|
String variableName = variable.getName().toLowerCase();
|
||||||
|
|
||||||
|
if (variableName.endsWith(RittalDeviceConstants.VARIABLE_STATUS)) {
|
||||||
|
return FunctionTypeEnum.STATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<FunctionTypeEnum> trapFunctionType = RittalVariableConfigList.contains_FunctionTypeMap.entrySet().stream()
|
||||||
|
.filter(entry -> entry.getKey().stream().anyMatch(variableName::contains))
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (trapFunctionType.isPresent()) {
|
||||||
|
return trapFunctionType.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<FunctionTypeEnum> specificFunctionType = RittalVariableConfigList.endsWith_specificFunctionTypeMap.entrySet().stream()
|
||||||
|
.filter(entry -> entry.getKey().stream().anyMatch(variableName::endsWith))
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (specificFunctionType.isPresent()) {
|
||||||
|
return specificFunctionType.get();
|
||||||
|
}
|
||||||
|
Optional<FunctionTypeEnum> generalFunctionType = RittalVariableConfigList.endsWith_generalFunctionTypeMap.entrySet().stream()
|
||||||
|
.filter(entry -> entry.getKey().stream().anyMatch(variableName::endsWith))
|
||||||
|
.map(Map.Entry::getValue)
|
||||||
|
.findFirst();
|
||||||
|
|
||||||
|
if (generalFunctionType.isPresent()) {
|
||||||
|
return generalFunctionType.get();
|
||||||
|
}
|
||||||
|
return FunctionTypeEnum.VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
DataTypeEnum getType(Variable variable) {
|
||||||
|
if (variable.getName().toLowerCase().endsWith(RittalDeviceConstants.VARIABLE_STATUS)) {
|
||||||
|
return DataTypeEnum.STATUSINT;
|
||||||
|
} else if (variable.getVarDataType() == DataTypeEnum.INTEGER && (variable.getScale() > 1 || variable.getScale() < 0)) {
|
||||||
|
return DataTypeEnum.FLOAT;
|
||||||
|
} else if (variable.getVarDataType() == DataTypeEnum.INTEGER) {
|
||||||
|
return DataTypeEnum.NUMERIC;
|
||||||
|
} else if (variable.getVarDataType() == DataTypeEnum.ENUM) {
|
||||||
|
//TODO mabe Change to dedicated type
|
||||||
|
return DataTypeEnum.STATUSINT; //INFO: Cant be Numeric because of scaling
|
||||||
|
} else {
|
||||||
|
return DataTypeEnum.STRING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
String[] getOidValue(DeviceOidValueMap oidValueMap, VariableFieldName variableFieldName, int subDeviceIndex, int varStartIndex) {
|
||||||
|
String oid = String.format(".1.3.6.1.4.1.2606.7.4.2.2.1.%s.%s.%s", variableFieldName.getValue(), subDeviceIndex, varStartIndex);
|
||||||
|
Object value = oidValueMap.get(oid);
|
||||||
|
|
||||||
|
if (value == null) {
|
||||||
|
throw new NoSuchElementException("Can't find value in oidValueMap for OID: " + oid);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new String[] {oid, value.toString()};
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
40
src/main/java/io/gec/raw/connector/device/domain/DeviceMapping.java
Executable file
40
src/main/java/io/gec/raw/connector/device/domain/DeviceMapping.java
Executable file
@@ -0,0 +1,40 @@
|
|||||||
|
package io.gec.raw.connector.device.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DevicePropertyMapping;
|
||||||
|
import io.gec.raw.connector.variable.entity.Variable;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@NoArgsConstructor
|
||||||
|
@AllArgsConstructor
|
||||||
|
public class DeviceMapping {
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
private String name;
|
||||||
|
private String type;
|
||||||
|
private String parentId;
|
||||||
|
private String id;
|
||||||
|
private String deviceURL;
|
||||||
|
private UUID connectorId;
|
||||||
|
private UUID discoveryWorkItemId;
|
||||||
|
private boolean isRoot;
|
||||||
|
private UUID driverHeaderId;
|
||||||
|
private ComponentMode mode;
|
||||||
|
@Builder.Default
|
||||||
|
private Integer deviceIndex = 0;
|
||||||
|
@Builder.Default
|
||||||
|
private List<DeviceMapping> subDevices = new ArrayList<>();
|
||||||
|
@Builder.Default
|
||||||
|
private List<Variable> variables = new ArrayList<>();
|
||||||
|
@Builder.Default
|
||||||
|
private List<DevicePropertyMapping> properties = new ArrayList<>();
|
||||||
|
}
|
||||||
103
src/main/java/io/gec/raw/connector/device/domain/DeviceOidValueMap.java
Executable file
103
src/main/java/io/gec/raw/connector/device/domain/DeviceOidValueMap.java
Executable file
@@ -0,0 +1,103 @@
|
|||||||
|
package io.gec.raw.connector.device.domain;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.device.enums.ExternalDeviceConstants;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Frank.Pruefer
|
||||||
|
*/
|
||||||
|
public class DeviceOidValueMap extends HashMap<String, Object> {
|
||||||
|
|
||||||
|
private String sysDescr;
|
||||||
|
private String sysObjectId;
|
||||||
|
private String sysUpTime;
|
||||||
|
private String sysContact;
|
||||||
|
private String sysName;
|
||||||
|
private String sysLocation;
|
||||||
|
private String sysServices;
|
||||||
|
private String enterprise;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set an oid as a string and the corresponding variable value
|
||||||
|
*
|
||||||
|
* @param oid the oid
|
||||||
|
* @param value the value
|
||||||
|
*/
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object put(String oid, Object value) {
|
||||||
|
switch (oid) {
|
||||||
|
case ExternalDeviceConstants.OID_DESCRIPTION:
|
||||||
|
sysDescr = value.toString();
|
||||||
|
break;
|
||||||
|
case ExternalDeviceConstants.OID_SYS_OBJECT_ID:
|
||||||
|
sysObjectId = value.toString();
|
||||||
|
break;
|
||||||
|
case ExternalDeviceConstants.OID_SYS_UP_TIME:
|
||||||
|
sysUpTime = value.toString();
|
||||||
|
break;
|
||||||
|
case ExternalDeviceConstants.OID_SYS_CONTACT:
|
||||||
|
sysContact = value.toString();
|
||||||
|
break;
|
||||||
|
case ExternalDeviceConstants.OID_SYS_NAME:
|
||||||
|
sysName = value.toString();
|
||||||
|
break;
|
||||||
|
case ExternalDeviceConstants.OID_SYS_LOCATION:
|
||||||
|
sysLocation = value.toString();
|
||||||
|
break;
|
||||||
|
case ExternalDeviceConstants.OID_SYS_SERVICES:
|
||||||
|
sysServices = value.toString();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!oid.startsWith(ExternalDeviceConstants.OID_MIB_2_PREFIX)) {
|
||||||
|
try {
|
||||||
|
if (getEnterprise().isEmpty()) {
|
||||||
|
enterprise = oid.split("\\.")[7];
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
// ignore this exception when enterprise can't be determined from oid string
|
||||||
|
}
|
||||||
|
return super.put(oid, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return true, if all oids for a default device are set (from sysDesc to sysServices)
|
||||||
|
*/
|
||||||
|
public boolean isComplete() {
|
||||||
|
return sysDescr != null && sysObjectId != null && sysContact != null && sysName != null
|
||||||
|
&& sysLocation != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getEnterprise() {
|
||||||
|
return enterprise == null ? "" : enterprise;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSysDescr() {
|
||||||
|
return sysDescr == null ? "" : sysDescr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSysObjectId() {
|
||||||
|
return sysObjectId == null ? "" : sysObjectId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSysUpTime() {
|
||||||
|
return sysUpTime == null ? "" : sysUpTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSysContact() {
|
||||||
|
return sysContact == null ? "" : sysContact;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSysName() {
|
||||||
|
return sysName == null ? "" : sysName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getSysLocation() {
|
||||||
|
return sysLocation == null ? "" : sysLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
59
src/main/java/io/gec/raw/connector/device/dto/DeviceDTO.java
Executable file
59
src/main/java/io/gec/raw/connector/device/dto/DeviceDTO.java
Executable file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* (c) 2023 German Edge Cloud GmbH & Co. KG
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.gec.raw.connector.device.dto;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.variable.dto.VariableDTO;
|
||||||
|
import io.gec.raw.connector.device.entity.Device;
|
||||||
|
import io.gec.raw.connector.deviceproperty.dto.DevicePropertyDTO;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class DeviceDTO {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
private UUID connectorId;
|
||||||
|
private UUID connectorDeviceId;
|
||||||
|
private UUID discoveryWorkitemId;
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private String type;
|
||||||
|
private UUID parentId;
|
||||||
|
private String deviceUrl;
|
||||||
|
private UUID plantId;
|
||||||
|
private String assignedToProject;
|
||||||
|
private UUID commSvcId;
|
||||||
|
private UUID driverHeaderId;
|
||||||
|
private ComponentMode mode;
|
||||||
|
private List<VariableDTO> variables;
|
||||||
|
private List<DevicePropertyDTO> properties;
|
||||||
|
private List<UUID> communicationProtocolIds;
|
||||||
|
private List<DeviceDTO> subDevices;
|
||||||
|
|
||||||
|
public static DeviceDTO from(Device entity) {
|
||||||
|
return DeviceDTO.builder()
|
||||||
|
.id(entity.getCommServiceId())
|
||||||
|
.connectorId(entity.getConnectorId())
|
||||||
|
.connectorDeviceId(entity.getId())
|
||||||
|
.discoveryWorkitemId(entity.getDiscoveryWorkItemId())
|
||||||
|
.name(entity.getName())
|
||||||
|
.description(entity.getDescription())
|
||||||
|
.type(entity.getType())
|
||||||
|
.parentId(entity.getParentId())
|
||||||
|
.deviceUrl(entity.getDeviceURL())
|
||||||
|
.plantId(entity.getPlantId())
|
||||||
|
.mode(entity.getMode())
|
||||||
|
.driverHeaderId(entity.getDriverHeaderId())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/main/java/io/gec/raw/connector/device/dto/DevicePropertyResponseDTO.java
Executable file
15
src/main/java/io/gec/raw/connector/device/dto/DevicePropertyResponseDTO.java
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
package io.gec.raw.connector.device.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DevicePropertyResponseDTO {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
private UUID deviceId;
|
||||||
|
private UUID connectorPropertyId;
|
||||||
|
}
|
||||||
20
src/main/java/io/gec/raw/connector/device/dto/DeviceResponseDTO.java
Executable file
20
src/main/java/io/gec/raw/connector/device/dto/DeviceResponseDTO.java
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
package io.gec.raw.connector.device.dto;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class DeviceResponseDTO {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
private UUID connectorId;
|
||||||
|
private UUID connectorDeviceId;
|
||||||
|
private UUID parentId;
|
||||||
|
private List<DeviceResponseDTO> subdevices;
|
||||||
|
private List<VariableResponseDTO> variables;
|
||||||
|
private List<DevicePropertyResponseDTO> properties;
|
||||||
|
}
|
||||||
17
src/main/java/io/gec/raw/connector/device/dto/VariableResponseDTO.java
Executable file
17
src/main/java/io/gec/raw/connector/device/dto/VariableResponseDTO.java
Executable file
@@ -0,0 +1,17 @@
|
|||||||
|
package io.gec.raw.connector.device.dto;
|
||||||
|
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Builder
|
||||||
|
public class VariableResponseDTO {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
private UUID deviceId;
|
||||||
|
private UUID connectorVariableId;
|
||||||
|
}
|
||||||
31
src/main/java/io/gec/raw/connector/device/entity/AccessTypeEnum.java
Executable file
31
src/main/java/io/gec/raw/connector/device/entity/AccessTypeEnum.java
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
package io.gec.raw.connector.device.entity;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum AccessTypeEnum {
|
||||||
|
// CMC3 - Variable access types
|
||||||
|
NONE("NONE", 1),
|
||||||
|
READONLY("READONLY", 2),
|
||||||
|
READWRITE("READWRITE", 3),
|
||||||
|
READWRITESWITCH("READWRITESWITCH", 4),
|
||||||
|
READWRITEEXTENDED("READWRITEEXTENDED", 5);
|
||||||
|
|
||||||
|
private final String ordinal;
|
||||||
|
private final Integer number;
|
||||||
|
|
||||||
|
AccessTypeEnum(String ordinal, Integer number) {
|
||||||
|
this.ordinal = ordinal;
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AccessTypeEnum findByNumber(Integer number) {
|
||||||
|
for (AccessTypeEnum accessType : AccessTypeEnum.values()) {
|
||||||
|
if (accessType.getNumber().equals(number)) {
|
||||||
|
return accessType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
31
src/main/java/io/gec/raw/connector/device/entity/DataTypeEnum.java
Executable file
31
src/main/java/io/gec/raw/connector/device/entity/DataTypeEnum.java
Executable file
@@ -0,0 +1,31 @@
|
|||||||
|
package io.gec.raw.connector.device.entity;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum DataTypeEnum {
|
||||||
|
// CMC3 - Variables Datatype enum
|
||||||
|
INTEGER(2),
|
||||||
|
STRING(3),
|
||||||
|
ENUM(4),
|
||||||
|
ANALOGINT(5),
|
||||||
|
STATUSINT(6),
|
||||||
|
NUMERIC(7),
|
||||||
|
FLOAT(8);
|
||||||
|
|
||||||
|
private final Integer number;
|
||||||
|
|
||||||
|
DataTypeEnum(Integer number) {
|
||||||
|
this.number = number;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DataTypeEnum findByNumber(Integer number) {
|
||||||
|
for (DataTypeEnum dataType : DataTypeEnum.values()) {
|
||||||
|
if (dataType.getNumber().equals(number)) {
|
||||||
|
return dataType;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
52
src/main/java/io/gec/raw/connector/device/entity/Device.java
Executable file
52
src/main/java/io/gec/raw/connector/device/entity/Device.java
Executable file
@@ -0,0 +1,52 @@
|
|||||||
|
package io.gec.raw.connector.device.entity;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.base.entity.SimpleBaseEntity;
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import jakarta.enterprise.context.Dependent;
|
||||||
|
import jakarta.persistence.*;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@Dependent
|
||||||
|
@Entity(name = "device")
|
||||||
|
@Table(name = "device", schema = "connector_svc")
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
public class Device extends SimpleBaseEntity {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
private String description;
|
||||||
|
private String type;
|
||||||
|
|
||||||
|
@Column(name = "parent_id")
|
||||||
|
private UUID parentId;
|
||||||
|
private String deviceURL;
|
||||||
|
|
||||||
|
@Column(name = "plant_id")
|
||||||
|
private UUID plantId;
|
||||||
|
|
||||||
|
@Column(name = "connector_id")
|
||||||
|
private UUID connectorId;
|
||||||
|
|
||||||
|
@Column(name = "comm_svc_id")
|
||||||
|
private UUID commServiceId;
|
||||||
|
|
||||||
|
@Column(name = "discoveryWorkitem_id")
|
||||||
|
private UUID discoveryWorkItemId;
|
||||||
|
|
||||||
|
@Column(name = "driver_header_id")
|
||||||
|
private UUID driverHeaderId;
|
||||||
|
|
||||||
|
@Column(name = "device_index", nullable = false)
|
||||||
|
private Integer deviceIndex;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(nullable = false)
|
||||||
|
private ComponentMode mode;
|
||||||
|
|
||||||
|
@Enumerated(EnumType.STRING)
|
||||||
|
@Column(name = "restore_mode", nullable = false)
|
||||||
|
private ComponentMode restoreMode;
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
public enum AccessDeviceTypeEnum {
|
||||||
|
ACCESS_DEVICE,
|
||||||
|
ACCESS_MANAGEMENT_DEVICE,
|
||||||
|
ACCESS_HANDLE,
|
||||||
|
ACCESS_KEYPAD,
|
||||||
|
}
|
||||||
15
src/main/java/io/gec/raw/connector/device/enums/ExternalDeviceConstants.java
Executable file
15
src/main/java/io/gec/raw/connector/device/enums/ExternalDeviceConstants.java
Executable file
@@ -0,0 +1,15 @@
|
|||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
public class ExternalDeviceConstants {
|
||||||
|
|
||||||
|
private ExternalDeviceConstants() {}
|
||||||
|
|
||||||
|
public static final String OID_MIB_2_PREFIX = ".1.3.6.1.2.1.";
|
||||||
|
public static final String OID_DESCRIPTION = ".1.3.6.1.2.1.1.1.0";
|
||||||
|
public static final String OID_SYS_OBJECT_ID = ".1.3.6.1.2.1.1.2.0";
|
||||||
|
public static final String OID_SYS_UP_TIME = ".1.3.6.1.2.1.1.3.0";
|
||||||
|
public static final String OID_SYS_CONTACT = ".1.3.6.1.2.1.1.4.0";
|
||||||
|
public static final String OID_SYS_NAME = ".1.3.6.1.2.1.1.5.0";
|
||||||
|
public static final String OID_SYS_LOCATION = ".1.3.6.1.2.1.1.6.0";
|
||||||
|
public static final String OID_SYS_SERVICES = ".1.3.6.1.2.1.1.7.0";
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.device.entity.DataTypeEnum;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum ExternalDevicePropertyEnum {
|
||||||
|
|
||||||
|
DESCRIPTION("Description", ExternalDeviceConstants.OID_DESCRIPTION, DataTypeEnum.STRING, true),
|
||||||
|
NAME("Name", ExternalDeviceConstants.OID_SYS_NAME, DataTypeEnum.STRING, true),
|
||||||
|
LOCATION("Location", ExternalDeviceConstants.OID_SYS_LOCATION, DataTypeEnum.STRING, true),
|
||||||
|
CONTACT("Contact", ExternalDeviceConstants.OID_SYS_CONTACT, DataTypeEnum.STRING, true),
|
||||||
|
SERIAL_NUMBER("Serial number", ExternalDeviceConstants.OID_DESCRIPTION, DataTypeEnum.STRING, true);
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
private final String oid;
|
||||||
|
private final DataTypeEnum dataType;
|
||||||
|
private boolean readOnly;
|
||||||
|
}
|
||||||
12
src/main/java/io/gec/raw/connector/device/enums/FunctionTypeEnum.java
Executable file
12
src/main/java/io/gec/raw/connector/device/enums/FunctionTypeEnum.java
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
public enum FunctionTypeEnum {
|
||||||
|
|
||||||
|
UNDEFINED,
|
||||||
|
STATE,
|
||||||
|
VALUE,
|
||||||
|
SETTING,
|
||||||
|
CONFIGURATION,
|
||||||
|
SERVICE,
|
||||||
|
EXECUTE
|
||||||
|
}
|
||||||
5
src/main/java/io/gec/raw/connector/device/enums/PropertyClassType.java
Executable file
5
src/main/java/io/gec/raw/connector/device/enums/PropertyClassType.java
Executable file
@@ -0,0 +1,5 @@
|
|||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
public enum PropertyClassType {
|
||||||
|
GROUP, INT, FLOAT, BOOL, STRING, URL, ENUM, IP_V4, IP_V6
|
||||||
|
}
|
||||||
98
src/main/java/io/gec/raw/connector/device/enums/RittalDeviceConstants.java
Executable file
98
src/main/java/io/gec/raw/connector/device/enums/RittalDeviceConstants.java
Executable file
@@ -0,0 +1,98 @@
|
|||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
public class RittalDeviceConstants {
|
||||||
|
|
||||||
|
public static final String VARIABLE_DESC_NAME = ".descname";
|
||||||
|
|
||||||
|
//Excluded VariableNames
|
||||||
|
public static final String VARIABLE_KEY_CODE = ".keycode";
|
||||||
|
public static final String VARIABLE_KEY_COMMAND = ".keycommand";
|
||||||
|
public static final String VARIABLE_CATEGORY = ".category";
|
||||||
|
|
||||||
|
//Status functionType
|
||||||
|
public static final String VARIABLE_STATUS = ".status";
|
||||||
|
|
||||||
|
//setting functionType
|
||||||
|
public static final String VARIABLE_SETPT = ".setpt";
|
||||||
|
public static final String VARIABLE_OFFSET = ".offset";
|
||||||
|
public static final String VARIABLE_SENSITIVITY = ".sensitivity";
|
||||||
|
public static final String VARIABLE_GROUPING = ".grouping";
|
||||||
|
public static final String VARIABLE_HYSTERESIS = ".hysteresis";
|
||||||
|
public static final String VARIABLE_SETPOINT = ".setpoint";
|
||||||
|
public static final String VARIABLE_AVERAGE = ".average";
|
||||||
|
public static final String VARIABLE_LOGIC = ".logic";
|
||||||
|
public static final String VARIABLE_START = ".start";
|
||||||
|
public static final String VARIABLE_END = ".end";
|
||||||
|
public static final String VARIABLE_UNIT = ".unit";
|
||||||
|
public static final String VARIABLE_FACTOR = "factor";
|
||||||
|
public static final String VARIABLE_POWER_ON_DELAY = ".power on delay";
|
||||||
|
public static final String VARIABLE_MIN_VALUE = ".min.value";
|
||||||
|
public static final String VARIABLE_MAX_VALUE = ".max.value";
|
||||||
|
public static final String VARIABLE_MANUAL_VALUE = ".manual.value";
|
||||||
|
public static final String VARIABLE_CONFIG = ".config";
|
||||||
|
public static final String VARIABLE_GENERAL_ON_DELAY = ".general.on delay";
|
||||||
|
public static final String VARIABLE_GENERAL_ERROR_DELAY = ".general.error delay";
|
||||||
|
public static final String VARIABLE_ACTIVE_CUSTOM_ENERGY_VALUE = ".activecustomenergy.value";
|
||||||
|
|
||||||
|
|
||||||
|
//Execute functionType
|
||||||
|
public static final String VARIABLE_DELAY = ".delay";
|
||||||
|
public static final String VARIABLE_LOGIN_DELAY = "login.delay";
|
||||||
|
public static final String VARIABLE_RELAY = ".relay";
|
||||||
|
public static final String VARIABLE_COMMAND = ".command";
|
||||||
|
public static final String VARIABLE_ATTEMPTS = ".attempts";
|
||||||
|
public static final String VARIABLE_RED = ".red";
|
||||||
|
public static final String VARIABLE_GREEN = ".green";
|
||||||
|
public static final String VARIABLE_BLUE = ".blue";
|
||||||
|
public static final String VARIABLE_USER_COUNT = ".user count";
|
||||||
|
public static final String VARIABLE_GENERAL_GROUPING = ".general.grouping";
|
||||||
|
|
||||||
|
//Configuration functionType
|
||||||
|
public static final String VARIABLE_DESCNAME = ".descname";
|
||||||
|
public static final String VARIABLE_TYPE = ".type";
|
||||||
|
public static final String VARIABLE_CIRCUIT = ".circuit";
|
||||||
|
public static final String VARIABLE_SOCKET_TYPE = ".socket type";
|
||||||
|
public static final String VARIABLE_MODE = ".mode";
|
||||||
|
public static final String VARIABLE_LED_COMMAND = "led.command";
|
||||||
|
public static final String VARIABLE_SEQUENCE_MODE = ".sequence mode";
|
||||||
|
public static final String VARIABLE_CUSTOM_VALUE = "custom.value";
|
||||||
|
public static final String VARIABLE_ERROR_INFO = ".error info";
|
||||||
|
public static final String VARIABLE_POSITION = "position";
|
||||||
|
public static final String VARIABLE_CUSTOM_RUNTIME_VALUE = "custom.runtime.value";
|
||||||
|
public static final String VARIABLE_MESSAGE = "message";
|
||||||
|
public static final String VARIABLE_GENERAL_SEQUENCE_MODE = ".general.sequence mode";
|
||||||
|
|
||||||
|
|
||||||
|
//Service functionType
|
||||||
|
public static final String VARIABLE_SERVICE = "service";
|
||||||
|
public static final String VARIABLE_TRAP_RECEIVER = "trapreceiver";
|
||||||
|
public static final String VARIABLE_TRAP_ENABLE = "trapenable";
|
||||||
|
|
||||||
|
//other Constrains
|
||||||
|
public static final String PROPERTY_NO_VALUE = "No value";
|
||||||
|
public static final String HTTPS_PREFIX = "https://";
|
||||||
|
public static final String ACCESS_DEVICE_TYPE_OID = "1.3.6.1.4.1.2606.7.7.4.6144";
|
||||||
|
public static final String ACCESS_HANDLE_DEVICE_NAME = "Handle";
|
||||||
|
public static final String ACCESS_KEYPAD_DEVICE_NAME = "KeyPad";
|
||||||
|
|
||||||
|
|
||||||
|
public static final String OID_DEVICE_ALIAS = ".1.3.6.1.4.1.2606.7.4.1.2.1.3";
|
||||||
|
public static final String OID_NAME = ".1.3.6.1.4.1.2606.7.4.1.2.1.2";
|
||||||
|
public static final String OID_TYPE = ".1.3.6.1.4.1.2606.7.4.1.2.1.4";
|
||||||
|
public static final String OID_NODE_ID = ".1.3.6.1.4.1.2606.7.4.1.2.1.5";
|
||||||
|
public static final String OID_STATUS = ".1.3.6.1.4.1.2606.7.4.1.2.1.6";
|
||||||
|
public static final String OID_ORDER_NUMBER = ".1.3.6.1.4.1.2606.7.4.1.2.1.7";
|
||||||
|
public static final String OID_LOCATION = ".1.3.6.1.4.1.2606.7.4.1.2.1.8";
|
||||||
|
public static final String OID_BUS = ".1.3.6.1.4.1.2606.7.4.1.2.1.9";
|
||||||
|
public static final String OID_POSITION = ".1.3.6.1.4.1.2606.7.4.1.2.1.10";
|
||||||
|
public static final String OID_SOFTWARE_VERSION = ".1.3.6.1.4.1.2606.7.4.1.2.1.11";
|
||||||
|
public static final String OID_HARDWARE_VERSION = ".1.3.6.1.4.1.2606.7.4.1.2.1.12";
|
||||||
|
public static final String OID_SERIAL_NUMBER = ".1.3.6.1.4.1.2606.7.4.1.2.1.13";
|
||||||
|
public static final String OID_NUMBER_OF_VARIABLES = ".1.3.6.1.4.1.2606.7.4.1.2.1.17";
|
||||||
|
public static final String OID_STATUS_TEXT = ".1.3.6.1.4.1.2606.7.4.1.2.1.19";
|
||||||
|
public static final String OID_ROOT_SERIAL_NUMBER = ".1.3.6.1.4.1.2606.7.2.6.0";
|
||||||
|
public static final String OID_ROOT_HARDWARE_VERSION = ".1.3.6.1.4.1.2606.7.2.3.0";
|
||||||
|
public static final String OID_ROOT_SOFTWARE_VERSION = ".1.3.6.1.4.1.2606.7.2.4.0";
|
||||||
|
public static final String OID_ROOT_PRODUCTION_CODE = ".1.3.6.1.4.1.2606.7.2.7.0";
|
||||||
|
public static final String OID_ROOT_UNIT_TYPE = ".1.3.6.1.4.1.2606.7.2.8.0";
|
||||||
|
}
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.device.entity.DataTypeEnum;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum RittalDevicePropertyNameEnum {
|
||||||
|
|
||||||
|
DEVICE_ALIAS("Device alias", RittalDeviceConstants.OID_DEVICE_ALIAS, DataTypeEnum.STRING, false), //INFO: DO NOT CHANGE -> Property is used as DisplayName in the UI
|
||||||
|
ACCESS_DEVICE_TYPE("Access device type", null, DataTypeEnum.ENUM, true), //INFO: DO NOT CHANGE -> Property is used in Core.Svc
|
||||||
|
NAME("Name", RittalDeviceConstants.OID_NAME, DataTypeEnum.STRING, true),
|
||||||
|
TYPE("Type", RittalDeviceConstants.OID_TYPE, DataTypeEnum.STRING, true),
|
||||||
|
NODE_ID("Node Id", RittalDeviceConstants.OID_NODE_ID, DataTypeEnum.INTEGER, true),
|
||||||
|
STATUS("Status", RittalDeviceConstants.OID_STATUS, DataTypeEnum.STRING, true),
|
||||||
|
MODEL_NUMBER("Model number", RittalDeviceConstants.OID_ORDER_NUMBER, DataTypeEnum.STRING, true),
|
||||||
|
LOCATION("Location", RittalDeviceConstants.OID_LOCATION, DataTypeEnum.STRING, false),
|
||||||
|
BUS("BUS", RittalDeviceConstants.OID_BUS, DataTypeEnum.STRING, true),
|
||||||
|
POSITION("Position", RittalDeviceConstants.OID_POSITION, DataTypeEnum.INTEGER, true),
|
||||||
|
SOFTWARE_VERSION("Software version", RittalDeviceConstants.OID_SOFTWARE_VERSION, DataTypeEnum.STRING, true),
|
||||||
|
HARDWARE_VERSION("Hardware version", RittalDeviceConstants.OID_HARDWARE_VERSION, DataTypeEnum.STRING, true),
|
||||||
|
SERIAL_NUMBER("Serial number", RittalDeviceConstants.OID_SERIAL_NUMBER, DataTypeEnum.STRING, true),
|
||||||
|
NUMBER_OF_VARIABLES("Number of Variables", RittalDeviceConstants.OID_NUMBER_OF_VARIABLES, DataTypeEnum.INTEGER, true),
|
||||||
|
STATUS_TEXT("Statustext", RittalDeviceConstants.OID_STATUS_TEXT, DataTypeEnum.STRING, true),
|
||||||
|
// ROOT_DEVICE
|
||||||
|
ROOT_SERIAL_NUMBER("Serial number", RittalDeviceConstants.OID_ROOT_SERIAL_NUMBER, DataTypeEnum.STRING, true),
|
||||||
|
ROOT_HARDWARE_VERSION("Hardware version", RittalDeviceConstants.OID_ROOT_HARDWARE_VERSION, DataTypeEnum.STRING, true),
|
||||||
|
ROOT_SOFTWARE_VERSION("Software version", RittalDeviceConstants.OID_ROOT_SOFTWARE_VERSION, DataTypeEnum.STRING, true),
|
||||||
|
ROOT_PRODUCTION_CODE("Production Code", RittalDeviceConstants.OID_ROOT_PRODUCTION_CODE, DataTypeEnum.STRING, true),
|
||||||
|
ROOT_UNIT_TYPE("UnitType", RittalDeviceConstants.OID_ROOT_UNIT_TYPE, DataTypeEnum.STRING, true),
|
||||||
|
ROOT_IP_ADDRESS("IP address", null, DataTypeEnum.STRING, true);
|
||||||
|
|
||||||
|
private final String label;
|
||||||
|
private final String baseOid;
|
||||||
|
private final DataTypeEnum dataType;
|
||||||
|
private final boolean readOnly;
|
||||||
|
|
||||||
|
RittalDevicePropertyNameEnum(String label, String baseOid, DataTypeEnum dataType, boolean readOnly) {
|
||||||
|
this.label = label;
|
||||||
|
this.baseOid = baseOid;
|
||||||
|
this.dataType = dataType;
|
||||||
|
this.readOnly = readOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIndexedOid(int index) {
|
||||||
|
return this.baseOid + "." + index;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
src/main/java/io/gec/raw/connector/device/enums/VariableFieldName.java
Executable file
36
src/main/java/io/gec/raw/connector/device/enums/VariableFieldName.java
Executable file
@@ -0,0 +1,36 @@
|
|||||||
|
/*
|
||||||
|
*
|
||||||
|
* * (c) 2022 German Edge Cloud GmbH & Co. KG
|
||||||
|
* *
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.gec.raw.connector.device.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum VariableFieldName {
|
||||||
|
|
||||||
|
NAME("Name", 3),
|
||||||
|
VARTYPE("VarType", 4),
|
||||||
|
UNIT("Unit", 5),
|
||||||
|
DATATYPE("Datatype", 6),
|
||||||
|
SCALE("Scale", 7),
|
||||||
|
CONSTRAINTS("Constraints", 8),
|
||||||
|
STEPS("Steps", 9),
|
||||||
|
VALUESTRING("ValueString", 10),
|
||||||
|
VALUEINT("ValueInt", 11),
|
||||||
|
LASTCHANGE("LastChange", 12),
|
||||||
|
ACCESS("Access", 13),
|
||||||
|
QUALITY("Quality", 14),
|
||||||
|
ENTPHYSICALINDEX("EntPhysicalIndex", 15);
|
||||||
|
|
||||||
|
private final String text;
|
||||||
|
private final int value;
|
||||||
|
|
||||||
|
VariableFieldName(String text, int value) {
|
||||||
|
this.text = text;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
package io.gec.raw.connector.device.projection;
|
||||||
|
|
||||||
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@RegisterForReflection
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class DeviceParentIdProjection {
|
||||||
|
|
||||||
|
private UUID id;
|
||||||
|
private UUID parentId;
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
package io.gec.raw.connector.device.projection;
|
||||||
|
|
||||||
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@RegisterForReflection
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public class DeviceURLProjection {
|
||||||
|
|
||||||
|
private String deviceURL;
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
package io.gec.raw.connector.deviceproperty.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.communicationservice.control.CommunicationServiceController;
|
||||||
|
import io.gec.raw.connector.deviceproperty.dto.PropertyValueRequestDTO;
|
||||||
|
import io.gec.raw.connector.statistic.control.StatisticCollectorController;
|
||||||
|
import io.gec.raw.connector.statistic.domain.StatisticCategory;
|
||||||
|
import io.quarkus.cache.Cache;
|
||||||
|
import io.quarkus.cache.CacheKey;
|
||||||
|
import io.quarkus.cache.CacheName;
|
||||||
|
import io.quarkus.cache.CacheResult;
|
||||||
|
import io.quarkus.cache.CaffeineCache;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.concurrent.CompletableFuture;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class DevicePropertyCachedService {
|
||||||
|
|
||||||
|
@CacheName("device-properties")
|
||||||
|
Cache cache;
|
||||||
|
@Inject
|
||||||
|
CommunicationServiceController communicationServiceController;
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
@Inject
|
||||||
|
StatisticCollectorController statisticCollectorController;
|
||||||
|
|
||||||
|
@CacheResult(cacheName = "device-properties")
|
||||||
|
public Object getCachedValue(@CacheKey UUID key) {
|
||||||
|
Object value = cache.as(CaffeineCache.class).getIfPresent(key).getNow(null);
|
||||||
|
logger.debugv("Getting variable from cache, key: {0}, value: {1}", key, value);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDeviceProperty(@CacheKey UUID key, PropertyValueRequestDTO propertyValueRequestDTO) {
|
||||||
|
PropertyValueRequestDTO cachedPropertyValueRequestDTO = (PropertyValueRequestDTO) getCachedValue(key);
|
||||||
|
if (cachedPropertyValueRequestDTO == null || !cachedPropertyValueRequestDTO.equals(propertyValueRequestDTO)) {
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
communicationServiceController.updateDeviceProperty(propertyValueRequestDTO);
|
||||||
|
long end = System.currentTimeMillis();
|
||||||
|
|
||||||
|
StatisticCategory statisticCategory = StatisticCategory.of(this.getClass().getSimpleName(),
|
||||||
|
"PropertyValueRequestDTO");
|
||||||
|
statisticCollectorController.add(statisticCategory, start, end, end);
|
||||||
|
cache.as(CaffeineCache.class).put(key, CompletableFuture.completedFuture(propertyValueRequestDTO));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//INFO: Cache update always because Items could be removed automatically after expiration
|
||||||
|
cache.as(CaffeineCache.class).put(key, CompletableFuture.completedFuture(propertyValueRequestDTO));
|
||||||
|
logger.debugv("{0} added to cache: key: {1}, value: {2}", propertyValueRequestDTO.getClass().getSimpleName(), key, propertyValueRequestDTO);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
package io.gec.raw.connector.deviceproperty.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.componentmode.dto.ComponentMode;
|
||||||
|
import io.gec.raw.connector.device.dto.DevicePropertyResponseDTO;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DeviceProperty;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DevicePropertyMapping;
|
||||||
|
import io.gec.raw.connector.deviceproperty.exception.DevicePropertyNotFoundException;
|
||||||
|
import io.gec.raw.connector.deviceproperty.projection.DevicePropertyNameProjection;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.persistence.EntityNotFoundException;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.time.OffsetDateTime;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class DevicePropertyController {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
@Inject
|
||||||
|
DevicePropertyRepository devicePropertyRepository;
|
||||||
|
@Inject
|
||||||
|
DevicePropertyMapper devicePropertyMapper;
|
||||||
|
@Inject
|
||||||
|
DevicePropertyTaskScheduler devicePropertyTaskScheduler;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void createProperties(List<DevicePropertyMapping> properties, UUID deviceId) {
|
||||||
|
if (properties != null) {
|
||||||
|
for (DevicePropertyMapping property : properties) {
|
||||||
|
DeviceProperty tempProperty = devicePropertyMapper.toDeviceProperty(deviceId, property);
|
||||||
|
devicePropertyRepository.persist(tempProperty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void createPropertiesIfNotExistByName(List<DevicePropertyMapping> properties, UUID deviceId) {
|
||||||
|
var devicePropertyNames = devicePropertyRepository.findNamesByDeviceId(deviceId).stream()
|
||||||
|
.map(DevicePropertyNameProjection::getName)
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
var newDeviceProperties = properties.stream()
|
||||||
|
.filter(property -> !devicePropertyNames.contains(property.getName()))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
createProperties(newDeviceProperties, deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceProperty findById(UUID id) {
|
||||||
|
return devicePropertyRepository.findByIdOptional(id)
|
||||||
|
.orElseThrow(() -> new DevicePropertyNotFoundException(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public List<DeviceProperty> findByDeviceId(UUID deviceId) throws EntityNotFoundException {
|
||||||
|
return devicePropertyRepository.findByDeviceId(deviceId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Optional<DeviceProperty> findByName(List<DeviceProperty> properties, String name) {
|
||||||
|
return properties.stream()
|
||||||
|
.filter(property -> property.getName().equalsIgnoreCase(name))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
|
|
||||||
|
public DeviceProperty findPropertyByCommSvcId(UUID commSvcId) {
|
||||||
|
return devicePropertyRepository.findByCommSvcId(commSvcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeviceProperty> findSubscribedDeviceProperties() {
|
||||||
|
return devicePropertyRepository.findWithNonNullValueOidByMode(ComponentMode.OPERATION);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<DeviceProperty> findSubscribableDevicePropertiesUpdatedAfter(OffsetDateTime stamp) {
|
||||||
|
return devicePropertyRepository.findWithNonNullValueOidAfterStamp(stamp);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updatePropertyInterval(UUID propertyId, String intervalValue) {
|
||||||
|
validateSubmittedId(propertyId);
|
||||||
|
DeviceProperty deviceProperty = devicePropertyRepository.findById(propertyId);
|
||||||
|
var interval = parseIntervalStringToIntValue(deviceProperty, intervalValue);
|
||||||
|
deviceProperty.setSubscriptionInterval(interval);
|
||||||
|
logger.debugf("DeviceProperty (ID:'%s') interval changed to '%s'", propertyId, intervalValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateMode(DeviceProperty deviceProperty, ComponentMode mode) {
|
||||||
|
ComponentMode oldMode = deviceProperty.getMode();
|
||||||
|
if (ComponentMode.PAUSE.equals(mode) && deviceProperty.isNotInitialValueFetched() && Objects.nonNull(deviceProperty.getValueChangeOid())) {
|
||||||
|
devicePropertyTaskScheduler.executeTask(deviceProperty);
|
||||||
|
deviceProperty.setInitialValueFetched(true);
|
||||||
|
}
|
||||||
|
if (deviceProperty.getMode().isRestorable()) {
|
||||||
|
deviceProperty.setRestoreMode(oldMode);
|
||||||
|
}
|
||||||
|
deviceProperty.setMode(mode);
|
||||||
|
logger.debugf("Property (ID:'%s') mode set to:'%s'", deviceProperty.getId(), mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateCommSvcId(List<DevicePropertyResponseDTO> properties) {
|
||||||
|
properties.forEach(this::updatePropertyCommSvcId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updatePropertyCommSvcId(DevicePropertyResponseDTO property) {
|
||||||
|
Optional<DeviceProperty> toUpdate = devicePropertyRepository.findByIdOptional(property.getConnectorPropertyId());
|
||||||
|
toUpdate.ifPresentOrElse(deviceProperty -> deviceProperty.setCommServiceId(property.getId()),
|
||||||
|
() -> logger.warn("Could not store com_svc_id for " + property.getConnectorPropertyId()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void restoreMode(DeviceProperty property) {
|
||||||
|
Objects.requireNonNull(property, "Property required to restore mode");
|
||||||
|
updateModeWithRestoreMode(property);
|
||||||
|
|
||||||
|
logger.debugf("Property (ID:'%s') mode restored to:'%s'", property.getId(), property.getMode());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateModeWithRestoreMode(DeviceProperty DeviceProperty) {
|
||||||
|
if (DeviceProperty != null) {
|
||||||
|
ComponentMode restoreMode = DeviceProperty.getRestoreMode();
|
||||||
|
DeviceProperty.setMode(restoreMode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateSubmittedId(UUID propertyId) {
|
||||||
|
if (propertyId == null) {
|
||||||
|
throw new IllegalStateException("Update Interval Failed, Property ID is missing");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void updateDeviceProperty(DeviceProperty deviceProperty) {
|
||||||
|
devicePropertyRepository.update(deviceProperty);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Integer parseIntervalStringToIntValue(DeviceProperty deviceProperty, String value) {
|
||||||
|
try {
|
||||||
|
return Integer.parseInt(value);
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
throw new NumberFormatException("Invalid interval provided Property (ID:'%s'), interval:'%s'".formatted(deviceProperty.getId(), value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
package io.gec.raw.connector.deviceproperty.control;
|
||||||
|
|
||||||
|
public interface DevicePropertyExtractor {
|
||||||
|
String getName();
|
||||||
|
|
||||||
|
String getValue();
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
package io.gec.raw.connector.deviceproperty.control;
|
||||||
|
|
||||||
|
import io.gec.raw.connector.deviceproperty.dto.PropertyValueRequestDTO;
|
||||||
|
import io.gec.raw.connector.deviceproperty.entity.DeviceProperty;
|
||||||
|
import io.gec.raw.connector.variable.dto.VarQuality;
|
||||||
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
|
import jakarta.inject.Inject;
|
||||||
|
import jakarta.transaction.Transactional;
|
||||||
|
import org.jboss.logging.Logger;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
|
@ApplicationScoped
|
||||||
|
public class DevicePropertyHandler {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
DevicePropertyCachedService cachedService;
|
||||||
|
@Inject
|
||||||
|
Logger logger;
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void handleDevicePropertyValue(DeviceProperty deviceProperty, String devicePropertyValue) {
|
||||||
|
validateDeviceProperty(deviceProperty);
|
||||||
|
logUpdate("START", deviceProperty, "handle value");
|
||||||
|
updateDeviceProperty(deviceProperty, devicePropertyValue);
|
||||||
|
deviceProperty.setInitialValueFetched(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void validateDeviceProperty(DeviceProperty deviceProperty) {
|
||||||
|
if (Objects.isNull(deviceProperty)) {
|
||||||
|
String message = "DeviceProperty is required but not provided";
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
if (Objects.isNull(deviceProperty.getId())) {
|
||||||
|
String message = "id is required but not provided";
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
if (deviceProperty.getSubscriptionInterval() == 0) {
|
||||||
|
String message = "subscriptionInterval is required to be other than 0";
|
||||||
|
throw new IllegalArgumentException(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateDeviceProperty(DeviceProperty deviceProperty, String value) {
|
||||||
|
PropertyValueRequestDTO propertyValueRequestDTO = PropertyValueRequestDTO.builder()
|
||||||
|
.propertyId(deviceProperty.getId())
|
||||||
|
.commSvcId(deviceProperty.getCommServiceId())
|
||||||
|
.varQuality(value.isEmpty() ? VarQuality.WARNINGNOVALUE : VarQuality.OK)
|
||||||
|
.valueAsString(value)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
logUpdate("RESULT", deviceProperty, "value=%s. quality=%s".formatted(value, propertyValueRequestDTO.getVarQuality()));
|
||||||
|
cachedService.updateDeviceProperty(deviceProperty.getId(), propertyValueRequestDTO);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void logUpdate(String action, DeviceProperty deviceProperty, String message) {
|
||||||
|
logger.debugf("[%s] DeviceProperty(ID=%s, mode=%s, initialValueFetched=%s, interval=%s) - %s",
|
||||||
|
action,
|
||||||
|
deviceProperty.getId(),
|
||||||
|
deviceProperty.getMode(),
|
||||||
|
deviceProperty.isInitialValueFetched(),
|
||||||
|
deviceProperty.getSubscriptionInterval(),
|
||||||
|
message
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user