Initial commit
This commit is contained in:
commit
e2a4f08c0f
33
.gitignore
vendored
Normal file
33
.gitignore
vendored
Normal file
@ -0,0 +1,33 @@
|
||||
HELP.md
|
||||
target/
|
||||
!.mvn/wrapper/maven-wrapper.jar
|
||||
!**/src/main/**/target/
|
||||
!**/src/test/**/target/
|
||||
|
||||
### STS ###
|
||||
.apt_generated
|
||||
.classpath
|
||||
.factorypath
|
||||
.project
|
||||
.settings
|
||||
.springBeans
|
||||
.sts4-cache
|
||||
|
||||
### IntelliJ IDEA ###
|
||||
.idea
|
||||
*.iws
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
### NetBeans ###
|
||||
/nbproject/private/
|
||||
/nbbuild/
|
||||
/dist/
|
||||
/nbdist/
|
||||
/.nb-gradle/
|
||||
build/
|
||||
!**/src/main/**/build/
|
||||
!**/src/test/**/build/
|
||||
|
||||
### VS Code ###
|
||||
.vscode/
|
118
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
118
.mvn/wrapper/MavenWrapperDownloader.java
vendored
Normal file
@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2007-present the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import java.net.*;
|
||||
import java.io.*;
|
||||
import java.nio.channels.*;
|
||||
import java.util.Properties;
|
||||
|
||||
public class MavenWrapperDownloader {
|
||||
|
||||
private static final String WRAPPER_VERSION = "0.5.6";
|
||||
/**
|
||||
* Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
|
||||
*/
|
||||
private static final String DEFAULT_DOWNLOAD_URL = "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/"
|
||||
+ WRAPPER_VERSION + "/maven-wrapper-" + WRAPPER_VERSION + ".jar";
|
||||
|
||||
/**
|
||||
* Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
|
||||
* use instead of the default one.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
|
||||
".mvn/wrapper/maven-wrapper.properties";
|
||||
|
||||
/**
|
||||
* Path where the maven-wrapper.jar will be saved to.
|
||||
*/
|
||||
private static final String MAVEN_WRAPPER_JAR_PATH =
|
||||
".mvn/wrapper/maven-wrapper.jar";
|
||||
|
||||
/**
|
||||
* Name of the property which should be used to override the default download url for the wrapper.
|
||||
*/
|
||||
private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
|
||||
|
||||
public static void main(String args[]) {
|
||||
System.out.println("- Downloader started");
|
||||
File baseDirectory = new File(args[0]);
|
||||
System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
|
||||
|
||||
// If the maven-wrapper.properties exists, read it and check if it contains a custom
|
||||
// wrapperUrl parameter.
|
||||
File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
|
||||
String url = DEFAULT_DOWNLOAD_URL;
|
||||
if (mavenWrapperPropertyFile.exists()) {
|
||||
FileInputStream mavenWrapperPropertyFileInputStream = null;
|
||||
try {
|
||||
mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
|
||||
Properties mavenWrapperProperties = new Properties();
|
||||
mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
|
||||
url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
|
||||
} catch (IOException e) {
|
||||
System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
|
||||
} finally {
|
||||
try {
|
||||
if (mavenWrapperPropertyFileInputStream != null) {
|
||||
mavenWrapperPropertyFileInputStream.close();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// Ignore ...
|
||||
}
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading from: " + url);
|
||||
|
||||
File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
|
||||
if (!outputFile.getParentFile().exists()) {
|
||||
if (!outputFile.getParentFile().mkdirs()) {
|
||||
System.out.println(
|
||||
"- ERROR creating output directory '" + outputFile.getParentFile().getAbsolutePath() + "'");
|
||||
}
|
||||
}
|
||||
System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
|
||||
try {
|
||||
downloadFileFromURL(url, outputFile);
|
||||
System.out.println("Done");
|
||||
System.exit(0);
|
||||
} catch (Throwable e) {
|
||||
System.out.println("- Error downloading");
|
||||
e.printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
private static void downloadFileFromURL(String urlString, File destination) throws Exception {
|
||||
if (System.getenv("MVNW_USERNAME") != null && System.getenv("MVNW_PASSWORD") != null) {
|
||||
String username = System.getenv("MVNW_USERNAME");
|
||||
char[] password = System.getenv("MVNW_PASSWORD").toCharArray();
|
||||
Authenticator.setDefault(new Authenticator() {
|
||||
@Override
|
||||
protected PasswordAuthentication getPasswordAuthentication() {
|
||||
return new PasswordAuthentication(username, password);
|
||||
}
|
||||
});
|
||||
}
|
||||
URL website = new URL(urlString);
|
||||
ReadableByteChannel rbc;
|
||||
rbc = Channels.newChannel(website.openStream());
|
||||
FileOutputStream fos = new FileOutputStream(destination);
|
||||
fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
|
||||
fos.close();
|
||||
rbc.close();
|
||||
}
|
||||
|
||||
}
|
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
BIN
.mvn/wrapper/maven-wrapper.jar
vendored
Normal file
Binary file not shown.
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
2
.mvn/wrapper/maven-wrapper.properties
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.1/apache-maven-3.8.1-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar
|
310
mvnw
vendored
Normal file
310
mvnw
vendored
Normal file
@ -0,0 +1,310 @@
|
||||
#!/bin/sh
|
||||
# ----------------------------------------------------------------------------
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
# Maven Start Up Batch script
|
||||
#
|
||||
# Required ENV vars:
|
||||
# ------------------
|
||||
# JAVA_HOME - location of a JDK home dir
|
||||
#
|
||||
# Optional ENV vars
|
||||
# -----------------
|
||||
# M2_HOME - location of maven2's installed home dir
|
||||
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
# e.g. to debug Maven itself, use
|
||||
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
# ----------------------------------------------------------------------------
|
||||
|
||||
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||
|
||||
if [ -f /etc/mavenrc ] ; then
|
||||
. /etc/mavenrc
|
||||
fi
|
||||
|
||||
if [ -f "$HOME/.mavenrc" ] ; then
|
||||
. "$HOME/.mavenrc"
|
||||
fi
|
||||
|
||||
fi
|
||||
|
||||
# OS specific support. $var _must_ be set to either true or false.
|
||||
cygwin=false;
|
||||
darwin=false;
|
||||
mingw=false
|
||||
case "`uname`" in
|
||||
CYGWIN*) cygwin=true ;;
|
||||
MINGW*) mingw=true;;
|
||||
Darwin*) darwin=true
|
||||
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
if [ -x "/usr/libexec/java_home" ]; then
|
||||
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||
else
|
||||
export JAVA_HOME="/Library/Java/Home"
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
if [ -r /etc/gentoo-release ] ; then
|
||||
JAVA_HOME=`java-config --jre-home`
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$M2_HOME" ] ; then
|
||||
## resolve links - $0 may be a link to maven's home
|
||||
PRG="$0"
|
||||
|
||||
# need this for relative symlinks
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG="`dirname "$PRG"`/$link"
|
||||
fi
|
||||
done
|
||||
|
||||
saveddir=`pwd`
|
||||
|
||||
M2_HOME=`dirname "$PRG"`/..
|
||||
|
||||
# make it fully qualified
|
||||
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||
|
||||
cd "$saveddir"
|
||||
# echo Using m2 at $M2_HOME
|
||||
fi
|
||||
|
||||
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||
if $cygwin ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||
fi
|
||||
|
||||
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||
if $mingw ; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ]; then
|
||||
javaExecutable="`which javac`"
|
||||
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||
# readlink(1) is not available as standard on Solaris 10.
|
||||
readLink=`which readlink`
|
||||
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||
if $darwin ; then
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||
else
|
||||
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||
fi
|
||||
javaHome="`dirname \"$javaExecutable\"`"
|
||||
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||
JAVA_HOME="$javaHome"
|
||||
export JAVA_HOME
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$JAVACMD" ] ; then
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
fi
|
||||
else
|
||||
JAVACMD="`which java`"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||
echo " We cannot execute $JAVACMD" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$JAVA_HOME" ] ; then
|
||||
echo "Warning: JAVA_HOME environment variable is not set."
|
||||
fi
|
||||
|
||||
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||
|
||||
# traverses directory structure from process work directory to filesystem root
|
||||
# first directory with .mvn subdirectory is considered project base directory
|
||||
find_maven_basedir() {
|
||||
|
||||
if [ -z "$1" ]
|
||||
then
|
||||
echo "Path not specified to find_maven_basedir"
|
||||
return 1
|
||||
fi
|
||||
|
||||
basedir="$1"
|
||||
wdir="$1"
|
||||
while [ "$wdir" != '/' ] ; do
|
||||
if [ -d "$wdir"/.mvn ] ; then
|
||||
basedir=$wdir
|
||||
break
|
||||
fi
|
||||
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||
if [ -d "${wdir}" ]; then
|
||||
wdir=`cd "$wdir/.."; pwd`
|
||||
fi
|
||||
# end of workaround
|
||||
done
|
||||
echo "${basedir}"
|
||||
}
|
||||
|
||||
# concatenates all lines of a file
|
||||
concat_lines() {
|
||||
if [ -f "$1" ]; then
|
||||
echo "$(tr -s '\n' ' ' < "$1")"
|
||||
fi
|
||||
}
|
||||
|
||||
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||
if [ -z "$BASE_DIR" ]; then
|
||||
exit 1;
|
||||
fi
|
||||
|
||||
##########################################################################################
|
||||
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
##########################################################################################
|
||||
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||
fi
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||
fi
|
||||
if [ -n "$MVNW_REPOURL" ]; then
|
||||
jarUrl="$MVNW_REPOURL/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
else
|
||||
jarUrl="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
fi
|
||||
while IFS="=" read key value; do
|
||||
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||
esac
|
||||
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Downloading from: $jarUrl"
|
||||
fi
|
||||
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||
if $cygwin; then
|
||||
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||
fi
|
||||
|
||||
if command -v wget > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found wget ... using wget"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
wget "$jarUrl" -O "$wrapperJarPath"
|
||||
else
|
||||
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath"
|
||||
fi
|
||||
elif command -v curl > /dev/null; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Found curl ... using curl"
|
||||
fi
|
||||
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||
else
|
||||
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||
fi
|
||||
|
||||
else
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo "Falling back to using Java to download"
|
||||
fi
|
||||
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||
# For Cygwin, switch paths to Windows format before running javac
|
||||
if $cygwin; then
|
||||
javaClass=`cygpath --path --windows "$javaClass"`
|
||||
fi
|
||||
if [ -e "$javaClass" ]; then
|
||||
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
# Compiling the Java class
|
||||
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||
fi
|
||||
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||
# Running the downloader
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo " - Running MavenWrapperDownloader.java ..."
|
||||
fi
|
||||
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
##########################################################################################
|
||||
# End of extension
|
||||
##########################################################################################
|
||||
|
||||
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||
if [ "$MVNW_VERBOSE" = true ]; then
|
||||
echo $MAVEN_PROJECTBASEDIR
|
||||
fi
|
||||
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin; then
|
||||
[ -n "$M2_HOME" ] &&
|
||||
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||
[ -n "$JAVA_HOME" ] &&
|
||||
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||
[ -n "$CLASSPATH" ] &&
|
||||
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||
fi
|
||||
|
||||
# Provide a "standardized" way to retrieve the CLI args that will
|
||||
# work with both Windows and non-Windows executions.
|
||||
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||
export MAVEN_CMD_LINE_ARGS
|
||||
|
||||
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
exec "$JAVACMD" \
|
||||
$MAVEN_OPTS \
|
||||
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||
"-Dmaven.home=${M2_HOME}" "-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
182
mvnw.cmd
vendored
Normal file
182
mvnw.cmd
vendored
Normal file
@ -0,0 +1,182 @@
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||
@REM or more contributor license agreements. See the NOTICE file
|
||||
@REM distributed with this work for additional information
|
||||
@REM regarding copyright ownership. The ASF licenses this file
|
||||
@REM to you under the Apache License, Version 2.0 (the
|
||||
@REM "License"); you may not use this file except in compliance
|
||||
@REM with the License. You may obtain a copy of the License at
|
||||
@REM
|
||||
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||
@REM
|
||||
@REM Unless required by applicable law or agreed to in writing,
|
||||
@REM software distributed under the License is distributed on an
|
||||
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
@REM KIND, either express or implied. See the License for the
|
||||
@REM specific language governing permissions and limitations
|
||||
@REM under the License.
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM ----------------------------------------------------------------------------
|
||||
@REM Maven Start Up Batch script
|
||||
@REM
|
||||
@REM Required ENV vars:
|
||||
@REM JAVA_HOME - location of a JDK home dir
|
||||
@REM
|
||||
@REM Optional ENV vars
|
||||
@REM M2_HOME - location of maven2's installed home dir
|
||||
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||
@REM e.g. to debug Maven itself, use
|
||||
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||
@REM ----------------------------------------------------------------------------
|
||||
|
||||
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||
@echo off
|
||||
@REM set title of command window
|
||||
title %0
|
||||
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||
|
||||
@REM set %HOME% to equivalent of $HOME
|
||||
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||
|
||||
@REM Execute a user defined script before this one
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_pre.bat" call "%HOME%\mavenrc_pre.bat"
|
||||
if exist "%HOME%\mavenrc_pre.cmd" call "%HOME%\mavenrc_pre.cmd"
|
||||
:skipRcPre
|
||||
|
||||
@setlocal
|
||||
|
||||
set ERROR_CODE=0
|
||||
|
||||
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||
@setlocal
|
||||
|
||||
@REM ==== START VALIDATION ====
|
||||
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME not found in your environment. >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
:OkJHome
|
||||
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||
|
||||
echo.
|
||||
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||
echo location of your Java installation. >&2
|
||||
echo.
|
||||
goto error
|
||||
|
||||
@REM ==== END VALIDATION ====
|
||||
|
||||
:init
|
||||
|
||||
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||
@REM Fallback to current working directory if not found.
|
||||
|
||||
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||
|
||||
set EXEC_DIR=%CD%
|
||||
set WDIR=%EXEC_DIR%
|
||||
:findBaseDir
|
||||
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||
cd ..
|
||||
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||
set WDIR=%CD%
|
||||
goto findBaseDir
|
||||
|
||||
:baseDirFound
|
||||
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||
cd "%EXEC_DIR%"
|
||||
goto endDetectBaseDir
|
||||
|
||||
:baseDirNotFound
|
||||
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||
cd "%EXEC_DIR%"
|
||||
|
||||
:endDetectBaseDir
|
||||
|
||||
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||
|
||||
@setlocal EnableExtensions EnableDelayedExpansion
|
||||
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||
|
||||
:endReadAdditionalConfig
|
||||
|
||||
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||
|
||||
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
|
||||
FOR /F "tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||
)
|
||||
|
||||
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||
if exist %WRAPPER_JAR% (
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Found %WRAPPER_JAR%
|
||||
)
|
||||
) else (
|
||||
if not "%MVNW_REPOURL%" == "" (
|
||||
SET DOWNLOAD_URL="%MVNW_REPOURL%/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar"
|
||||
)
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||
echo Downloading from: %DOWNLOAD_URL%
|
||||
)
|
||||
|
||||
powershell -Command "&{"^
|
||||
"$webclient = new-object System.Net.WebClient;"^
|
||||
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||
"}"^
|
||||
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||
"}"
|
||||
if "%MVNW_VERBOSE%" == "true" (
|
||||
echo Finished downloading %WRAPPER_JAR%
|
||||
)
|
||||
)
|
||||
@REM End of extension
|
||||
|
||||
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||
@REM work with both Windows and non-Windows executions.
|
||||
set MAVEN_CMD_LINE_ARGS=%*
|
||||
|
||||
%MAVEN_JAVA_EXE% %JVM_CONFIG_MAVEN_PROPS% %MAVEN_OPTS% %MAVEN_DEBUG_OPTS% -classpath %WRAPPER_JAR% "-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" %WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||
if ERRORLEVEL 1 goto error
|
||||
goto end
|
||||
|
||||
:error
|
||||
set ERROR_CODE=1
|
||||
|
||||
:end
|
||||
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||
|
||||
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPost
|
||||
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||
if exist "%HOME%\mavenrc_post.bat" call "%HOME%\mavenrc_post.bat"
|
||||
if exist "%HOME%\mavenrc_post.cmd" call "%HOME%\mavenrc_post.cmd"
|
||||
:skipRcPost
|
||||
|
||||
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||
if "%MAVEN_BATCH_PAUSE%" == "on" pause
|
||||
|
||||
if "%MAVEN_TERMINATE_CMD%" == "on" exit %ERROR_CODE%
|
||||
|
||||
exit /B %ERROR_CODE%
|
173
pom.xml
Normal file
173
pom.xml
Normal file
@ -0,0 +1,173 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-parent</artifactId>
|
||||
<version>2.5.4</version>
|
||||
<relativePath/> <!-- lookup parent from repository -->
|
||||
</parent>
|
||||
<groupId>com.qgs</groupId>
|
||||
<artifactId>dc</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>dc</name>
|
||||
<description>data collection</description>
|
||||
<properties>
|
||||
<java.version>1.8</java.version>
|
||||
</properties>
|
||||
<dependencies>
|
||||
<!-- OPC UA 模块依赖 开始 -->
|
||||
<dependency>
|
||||
<groupId>org.eclipse.milo</groupId>
|
||||
<artifactId>sdk-client</artifactId>
|
||||
<version>0.6.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.milo</groupId>
|
||||
<artifactId>stack-client</artifactId>
|
||||
<version>0.6.3</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.eclipse.milo</groupId>
|
||||
<artifactId>stack-server</artifactId>
|
||||
<version>0.6.3</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.eclipse.milo</groupId>
|
||||
<artifactId>sdk-server</artifactId>
|
||||
<version>0.6.3</version>
|
||||
</dependency>
|
||||
<!-- OPC UA 模块依赖 结束 -->
|
||||
|
||||
<!-- 日志(logback+slf4j) 开始 -->
|
||||
<!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-api -->
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>1.7.32</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-core -->
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-core</artifactId>
|
||||
<version>1.2.5</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/ch.qos.logback/logback-classic -->
|
||||
<dependency>
|
||||
<groupId>ch.qos.logback</groupId>
|
||||
<artifactId>logback-classic</artifactId>
|
||||
<version>1.2.5</version>
|
||||
</dependency>
|
||||
|
||||
|
||||
|
||||
<!-- 日志 结束 -->
|
||||
|
||||
|
||||
<!-- websocket 开始 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-websocket</artifactId>
|
||||
</dependency>
|
||||
<!-- websocket 结束 -->
|
||||
|
||||
<!-- fastjson 开始 -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.78</version>
|
||||
</dependency>
|
||||
<!-- fastjson 结束 -->
|
||||
<!-- hutool 开始 -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-all</artifactId>
|
||||
<version>5.7.9</version>
|
||||
</dependency>
|
||||
<!-- hutool 结束 -->
|
||||
|
||||
<!-- rabbitmq 依赖 开始 -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||
</dependency>
|
||||
<!-- rabbitmq 依赖 结束 -->
|
||||
|
||||
<!-- fastjson 开始 -->
|
||||
<!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>fastjson</artifactId>
|
||||
<version>1.2.75</version>
|
||||
</dependency>
|
||||
<!-- fastjson 结束 -->
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson依赖 开始 -->
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>2.12.2</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>2.12.2</version>
|
||||
</dependency>
|
||||
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations -->
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>2.12.2</version>
|
||||
</dependency>
|
||||
|
||||
<!-- jackson依赖 结束 -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<version>2.5.4</version>
|
||||
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
13
src/main/java/com/qgs/dc/DcApplication.java
Normal file
13
src/main/java/com/qgs/dc/DcApplication.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.qgs.dc;
|
||||
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
|
||||
@SpringBootApplication
|
||||
public class DcApplication {
|
||||
|
||||
public static void main(String[] args) {
|
||||
SpringApplication.run(DcApplication.class, args);
|
||||
}
|
||||
|
||||
}
|
208
src/main/java/com/qgs/dc/common/utils/CommonFunction.java
Normal file
208
src/main/java/com/qgs/dc/common/utils/CommonFunction.java
Normal file
@ -0,0 +1,208 @@
|
||||
package com.qgs.dc.common.utils;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
import com.qgs.dc.opcua.constant.PLCTypeConstant;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.*;
|
||||
import org.springframework.messaging.Message;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Arrays;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* 1.在从OPC Server 中 读到变量,要把变量包装一下 传给前端
|
||||
* 2.如果有些 opc-server 变量类型并不是 ns-iden 而仅仅是 iden 那么需要调用initialNodeId 初始化节点
|
||||
*
|
||||
* */
|
||||
public class CommonFunction {
|
||||
public static boolean isLinux() {
|
||||
return System.getProperty("os.name").toLowerCase().contains("linux");
|
||||
}
|
||||
|
||||
public static boolean isWindows() {
|
||||
return System.getProperty("os.name").toLowerCase().contains("windows");
|
||||
}
|
||||
|
||||
public static String extractError(String as){
|
||||
String[] errMsgs = as.split(",");
|
||||
/*for(String i:errMsgs){
|
||||
System.err.println(i);
|
||||
}*/
|
||||
|
||||
String[] s = errMsgs[errMsgs.length-2].split(":");
|
||||
String errStatus = s[s.length-1];
|
||||
return errStatus.split("=")[1];
|
||||
}
|
||||
|
||||
//注意:下面类型 必须和 PLCType枚举类里面的 数据类型按顺序一一对应
|
||||
//含义 是什么数据类型 就返回什么数据类型,如果是数组的话也会返回数组里面的数据类型如 "QArray|Boolen"
|
||||
public static String judgeVarType(Object value){
|
||||
if(value instanceof UByte){
|
||||
return PLCTypeConstant.QUByte;
|
||||
}else if(value instanceof UInteger){
|
||||
return PLCTypeConstant.QUInteger;
|
||||
}else if(value instanceof UShort){
|
||||
return PLCTypeConstant.QUShort;
|
||||
}else if(value instanceof ULong){
|
||||
return PLCTypeConstant.QULong;
|
||||
}else if(value instanceof Boolean){
|
||||
return PLCTypeConstant.QBoolean;
|
||||
}else if(value instanceof String){
|
||||
return PLCTypeConstant.QString;
|
||||
}else if(value instanceof Double){
|
||||
return PLCTypeConstant.QDouble;
|
||||
}else if(value instanceof Float){
|
||||
return PLCTypeConstant.QFloat;
|
||||
}else if(value instanceof Long){
|
||||
return PLCTypeConstant.QLong;
|
||||
}else if(value instanceof Integer){
|
||||
return PLCTypeConstant.QInteger;
|
||||
}else if(value instanceof Short){
|
||||
return PLCTypeConstant.QShort;
|
||||
}else if(value.getClass().isArray()){
|
||||
Object[] newArray = (Object[]) value;
|
||||
if(newArray.length==0){
|
||||
return PLCTypeConstant.QArray+"|0";
|
||||
}
|
||||
Object o = newArray[0];
|
||||
Object o1 = judgeVarType(o);
|
||||
return PLCTypeConstant.QArray+"|"+o1;
|
||||
}else if(value instanceof Byte){
|
||||
return PLCTypeConstant.QByte;
|
||||
}else if(value instanceof ByteString){
|
||||
return PLCTypeConstant.QByteString;
|
||||
}else {
|
||||
//如果是20 那么是数组类型了,数组的话只要string返回回去就行了
|
||||
//还有 如 二维数组、日期变量 那么如果需要可以补充 ,,暂时没有
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public static void createDirIfNotExit(String url){
|
||||
File file =new File(url);
|
||||
//如果文件夹不存在则创建
|
||||
if (!file.exists() && !file.isDirectory())
|
||||
{
|
||||
System.out.println("//不存在");
|
||||
boolean mkdir = file.mkdir();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用处:在从OPC Server 中 读到变量,要把变量包装一下 传给前端
|
||||
* 含义: 包装变量
|
||||
* 如果传入的是数组,,那么把这个Object 包装成List,如果不是数组,就直接原路返回
|
||||
* //注意 传入的Objec,必须dataValue.getValue().getValue()
|
||||
* */
|
||||
public static Object var(Object object){
|
||||
if(object.getClass().isArray()){
|
||||
return Arrays.asList(object);
|
||||
}
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
|
||||
public static Object var2String(Object object){
|
||||
if(object.getClass().isArray()){
|
||||
Object[] o = (Object[])object;
|
||||
String res = "";
|
||||
if(o.length>0){
|
||||
for(int i=0;i<o.length;i++){
|
||||
if(i==o.length-1){
|
||||
res += o[i].toString();
|
||||
}else {
|
||||
res += o[i].toString() +",";
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
return object.toString();
|
||||
}
|
||||
|
||||
public static NodeId initialNodeId(Integer value){
|
||||
return new NodeId(Unsigned.ushort(0),Unsigned.uint(value));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 字节流数据 ==》java对象(MQMessage)
|
||||
* @param message MQ的message原始对象
|
||||
* @return
|
||||
*/
|
||||
public static MQMessage parse(Message<?> message){
|
||||
byte[] bytes =(byte[]) message.getPayload();
|
||||
MQMessage mqMessage = JSONObject.parseObject(bytes, MQMessage.class);
|
||||
return mqMessage;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 解析body
|
||||
* JSONObject对象 ==》java对象
|
||||
* @param body body
|
||||
* @param clazz ResponseBody、RequestBody 里面的body
|
||||
* @return
|
||||
*/
|
||||
public static Object parseBody(Object body,Class<?> clazz){
|
||||
JSONObject jsonObject = (JSONObject) body;
|
||||
Object o = JSON.toJavaObject(jsonObject, clazz);
|
||||
return o;
|
||||
}
|
||||
|
||||
/*
|
||||
type:
|
||||
1.返回的是这种格式:2021-08-16 15:00:05
|
||||
2.返回的是这种格式:20210816150021
|
||||
*/
|
||||
public static String getNowDate(Integer type){
|
||||
if(type==1){
|
||||
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||
}else {
|
||||
return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*32位默认长度的uuid
|
||||
* (获取32位uuid)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getUUID()
|
||||
{
|
||||
return UUID.randomUUID().toString().replace("-", "");
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取指定长度的随机数
|
||||
* (获取指定长度uuid)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static String getUUID(int len)
|
||||
{
|
||||
if(0 >= len)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
String uuid = getUUID();
|
||||
StringBuffer str = new StringBuffer();
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
str.append(uuid.charAt(i));
|
||||
}
|
||||
|
||||
return str.toString();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.qgs.dc.common.utils;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* Spring Context 工具类
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
@Component
|
||||
public class SpringContextUtils implements ApplicationContextAware {
|
||||
public static ApplicationContext applicationContext;
|
||||
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext)
|
||||
throws BeansException {
|
||||
applicationContext = applicationContext;
|
||||
}
|
||||
|
||||
public static Object getBean(String name) {
|
||||
return applicationContext.getBean(name);
|
||||
}
|
||||
|
||||
public static <T> T getBean(String name, Class<T> requiredType) {
|
||||
return applicationContext.getBean(name, requiredType);
|
||||
}
|
||||
|
||||
public static boolean containsBean(String name) {
|
||||
return applicationContext.containsBean(name);
|
||||
}
|
||||
|
||||
public static boolean isSingleton(String name) {
|
||||
return applicationContext.isSingleton(name);
|
||||
}
|
||||
|
||||
public static Class<? extends Object> getType(String name) {
|
||||
return applicationContext.getType(name);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package com.qgs.dc.common.websocket;
|
||||
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.web.socket.server.standard.ServerEndpointExporter;
|
||||
|
||||
@Configuration
|
||||
public class WebSocketConfig {
|
||||
@Bean
|
||||
public ServerEndpointExporter serverEndpointExporter() {
|
||||
return new ServerEndpointExporter();
|
||||
}
|
||||
|
||||
}
|
163
src/main/java/com/qgs/dc/common/websocket/WebSocketServer.java
Normal file
163
src/main/java/com/qgs/dc/common/websocket/WebSocketServer.java
Normal file
@ -0,0 +1,163 @@
|
||||
package com.qgs.dc.common.websocket;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.websocket.*;
|
||||
import javax.websocket.server.PathParam;
|
||||
import javax.websocket.server.ServerEndpoint;
|
||||
import java.io.IOException;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* 注意:
|
||||
* 1.如果多个客户端来 连接 websocket,,那么 不要相同id。。如果是相同id只能发送一个。所以前端连接的id 号要由后台给出 getUniqeId() 这个方法
|
||||
* */
|
||||
@Component
|
||||
//访问服务端的url地址
|
||||
@ServerEndpoint(value = "/opcua/websocket/{id}")
|
||||
public class WebSocketServer {
|
||||
private static int onlineCount = 0;
|
||||
private static ConcurrentHashMap<String, WebSocketServer> webSocketSet = new ConcurrentHashMap<>();
|
||||
|
||||
//前端的id 右后端给他
|
||||
public synchronized String getUniqeId(){
|
||||
return UUID.randomUUID().toString()+System.currentTimeMillis();
|
||||
}
|
||||
|
||||
//与某个客户端的连接会话,需要通过它来给客户端发送数据
|
||||
private Session session;
|
||||
private static Logger log = LogManager.getLogger(WebSocketServer.class);
|
||||
private String id = "";
|
||||
|
||||
public Integer getCurrentNum(){
|
||||
return webSocketSet.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接建立成功调用的方法*/
|
||||
@OnOpen
|
||||
public void onOpen(@PathParam(value = "id") String id, Session session) {
|
||||
this.session = session;
|
||||
this.id = id;//接收到发送消息的人员编号
|
||||
webSocketSet.put(id, this); //加入set中
|
||||
addOnlineCount(); //在线数加1
|
||||
log.info("用户"+id+"加入!当前在线人数为" + getOnlineCount());
|
||||
try {
|
||||
sendMessage("连接成功");
|
||||
} catch (IOException e) {
|
||||
log.error("websocket IO异常");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 连接关闭调用的方法
|
||||
*/
|
||||
/*@OnClose
|
||||
public void onClose() {
|
||||
|
||||
webSocketSet.remove(this); //从set中删除
|
||||
subOnlineCount(); //在线数减1
|
||||
log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
|
||||
}*/
|
||||
|
||||
// 关闭连接触发事件
|
||||
@OnClose
|
||||
public void onClose(Session session, CloseReason closeReason) {
|
||||
String[] uris = session.getRequestURI().toString().split("/");
|
||||
webSocketSet.remove(uris[uris.length-1]);
|
||||
subOnlineCount();
|
||||
log.info("有一连接关闭!当前在线人数为" + getOnlineCount());
|
||||
}
|
||||
|
||||
/**
|
||||
* 收到客户端消息后调用的方法
|
||||
*
|
||||
* @param message 客户端发送过来的消息
|
||||
* */
|
||||
@OnMessage
|
||||
public void onMessage(String message, Session session) {
|
||||
log.info("来自客户端的消息:" + message);
|
||||
//可以自己约定字符串内容,比如 内容|0 表示信息群发,内容|X 表示信息发给id为X的用户
|
||||
String sendMessage = message.split("[|]")[0];
|
||||
String sendUserId = message.split("[|]")[1];
|
||||
try {
|
||||
if(sendUserId.equals("0")){
|
||||
sendtoAll(sendMessage);
|
||||
}
|
||||
else{
|
||||
sendtoUser(sendMessage,sendUserId);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param session
|
||||
* @param error
|
||||
*/
|
||||
@OnError
|
||||
public void onError(Session session, Throwable error) {
|
||||
log.error("发生错误");
|
||||
error.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
public void sendMessage(String message) throws IOException {
|
||||
this.session.getBasicRemote().sendText(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送信息给指定ID用户,如果用户不在线则返回不在线信息给自己
|
||||
* @param message
|
||||
* @param sendUserId
|
||||
* @throws IOException
|
||||
*/
|
||||
public void sendtoUser(String message,String sendUserId) throws IOException {
|
||||
if (webSocketSet.get(sendUserId) != null) {
|
||||
if(!id.equals(sendUserId)){
|
||||
webSocketSet.get(sendUserId).sendMessage( "用户" + id + "发来消息:" + " <br/> " + message);
|
||||
}
|
||||
else{
|
||||
webSocketSet.get(sendUserId).sendMessage(message);
|
||||
}
|
||||
} else {
|
||||
//如果用户不在线则返回不在线信息给自己
|
||||
sendtoUser("当前用户不在线",id);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 发送信息给所有人
|
||||
* @param message
|
||||
* @throws IOException
|
||||
*/
|
||||
public void sendtoAll(String message) throws IOException {
|
||||
for (String key : webSocketSet.keySet()) {
|
||||
try {
|
||||
webSocketSet.get(key).sendMessage(message);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static synchronized int getOnlineCount() {
|
||||
return onlineCount;
|
||||
}
|
||||
|
||||
public static synchronized void addOnlineCount() {
|
||||
WebSocketServer.onlineCount++;
|
||||
}
|
||||
|
||||
public static synchronized void subOnlineCount() {
|
||||
WebSocketServer.onlineCount--;
|
||||
}
|
||||
}
|
||||
|
10
src/main/java/com/qgs/dc/mq/Constant/SecsGemTimeout.java
Normal file
10
src/main/java/com/qgs/dc/mq/Constant/SecsGemTimeout.java
Normal file
@ -0,0 +1,10 @@
|
||||
package com.qgs.dc.mq.Constant;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/27 15:43
|
||||
*/
|
||||
public class SecsGemTimeout {
|
||||
public static final Long T3_TIMEOUT = new Long(30000);
|
||||
}
|
96
src/main/java/com/qgs/dc/mq/configuration/ConfigOf00B.java
Normal file
96
src/main/java/com/qgs/dc/mq/configuration/ConfigOf00B.java
Normal file
@ -0,0 +1,96 @@
|
||||
package com.qgs.dc.mq.configuration;
|
||||
|
||||
|
||||
import org.springframework.amqp.core.Binding;
|
||||
import org.springframework.amqp.core.BindingBuilder;
|
||||
import org.springframework.amqp.core.DirectExchange;
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @Desc: "设备:00B 相关信息定义"
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/6/7 9:11
|
||||
*/
|
||||
@Configuration
|
||||
public class ConfigOf00B {
|
||||
|
||||
//水平扩展其他设备的时候 只要:control+R 然后 00B=>00C 然后replace all
|
||||
public static final String EQUIPMENT_NAME_00B = "00B";
|
||||
|
||||
public static final String EXCHANGE_NAME_00B = EQUIPMENT_NAME_00B +"_Exchange";
|
||||
public static final String EAP_REQUEST_QUEUE_00B = EQUIPMENT_NAME_00B +"_EAP_Request_Queue";
|
||||
public static final String EAP_RESPONSE_QUEUE_00B = EQUIPMENT_NAME_00B +"_EAP_Response_Queue";
|
||||
public static final String MES_REQUEST_QUEUE_00B = EQUIPMENT_NAME_00B +"_MES_Request_Queue";
|
||||
public static final String MES_RESPONSE_QUEUE_00B = EQUIPMENT_NAME_00B +"_MES_Response_Queue";
|
||||
public static final String EAP_REQUEST_QUEUE_ROUTINGKEY_00B = EQUIPMENT_NAME_00B +"_EAP_Request_Queue_RoutingKey";
|
||||
public static final String EAP_RESPONSE_QUEUE_ROUTINGKEY_00B = EQUIPMENT_NAME_00B +"_EAP_Response_Queue_RoutingKey";
|
||||
public static final String MES_REQUEST_QUEUE_ROUTINGKEY_00B = EQUIPMENT_NAME_00B +"_MES_Request_Queue_RoutingKey";
|
||||
public static final String MES_RESPONSE_QUEUE_ROUTINGKEY_00B = EQUIPMENT_NAME_00B +"_MES_Response_Queue_RoutingKey";
|
||||
|
||||
|
||||
@Bean
|
||||
public DirectExchange EXCHANGE_NAME_00B(){
|
||||
return new DirectExchange(EXCHANGE_NAME_00B);
|
||||
}
|
||||
|
||||
//todo
|
||||
@Bean
|
||||
public Queue MES_REQUEST_QUEUE_00B(){
|
||||
Queue queue = new Queue(MES_REQUEST_QUEUE_00B);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
}
|
||||
@Bean
|
||||
public Queue MES_RESPONSE_QUEUE_00B(){
|
||||
Queue queue = new Queue(MES_RESPONSE_QUEUE_00B);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
}
|
||||
@Bean
|
||||
public Queue EAP_REQUEST_QUEUE_00B(){
|
||||
Queue queue = new Queue(EAP_REQUEST_QUEUE_00B);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
|
||||
}
|
||||
@Bean
|
||||
public Queue EAP_RESPONSE_QUEUE_00B(){
|
||||
Queue queue = new Queue(EAP_RESPONSE_QUEUE_00B);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueA_00B(){
|
||||
return BindingBuilder.bind(EAP_REQUEST_QUEUE_00B()).to(EXCHANGE_NAME_00B())
|
||||
.with(EAP_REQUEST_QUEUE_ROUTINGKEY_00B);
|
||||
}
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueB_00B(){
|
||||
return BindingBuilder.bind(EAP_RESPONSE_QUEUE_00B()).to(EXCHANGE_NAME_00B())
|
||||
.with(EAP_RESPONSE_QUEUE_ROUTINGKEY_00B);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueC_00B(){
|
||||
return BindingBuilder.bind(MES_REQUEST_QUEUE_00B()).to(EXCHANGE_NAME_00B())
|
||||
.with(MES_REQUEST_QUEUE_ROUTINGKEY_00B);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueD_00B(){
|
||||
return BindingBuilder.bind(MES_RESPONSE_QUEUE_00B()).to(EXCHANGE_NAME_00B())
|
||||
.with(MES_RESPONSE_QUEUE_ROUTINGKEY_00B);
|
||||
}
|
||||
}
|
98
src/main/java/com/qgs/dc/mq/configuration/ConfigOf00C.java
Normal file
98
src/main/java/com/qgs/dc/mq/configuration/ConfigOf00C.java
Normal file
@ -0,0 +1,98 @@
|
||||
package com.qgs.dc.mq.configuration;
|
||||
|
||||
|
||||
import org.springframework.amqp.core.Binding;
|
||||
import org.springframework.amqp.core.BindingBuilder;
|
||||
import org.springframework.amqp.core.DirectExchange;
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @Desc: "设备:00C 相关信息定义"
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/6/7 9:11
|
||||
*/
|
||||
@Configuration
|
||||
public class ConfigOf00C {
|
||||
|
||||
//水平扩展其他设备的时候 只要改 EQUIPMENT_NAME 就行了
|
||||
//1.现在MQConstant 上新增 EQUIPMENT_***; 2.然后复制 本class,然后EQUIPMENT_NAME = MQConstant.EQUIPMENT_***;就行了。
|
||||
public static final String EQUIPMENT_NAME_00C = "00C";
|
||||
|
||||
public static final String EXCHANGE_NAME_00C = EQUIPMENT_NAME_00C +"_Exchange";
|
||||
public static final String EAP_REQUEST_QUEUE_00C = EQUIPMENT_NAME_00C +"_EAP_Request_Queue";
|
||||
public static final String EAP_RESPONSE_QUEUE_00C = EQUIPMENT_NAME_00C +"_EAP_Response_Queue";
|
||||
public static final String MES_REQUEST_QUEUE_00C = EQUIPMENT_NAME_00C +"_MES_Request_Queue";
|
||||
public static final String MES_RESPONSE_QUEUE_00C = EQUIPMENT_NAME_00C +"_MES_Response_Queue";
|
||||
public static final String EAP_REQUEST_QUEUE_ROUTINGKEY_00C = EQUIPMENT_NAME_00C +"_EAP_Request_Queue_RoutingKey";
|
||||
public static final String EAP_RESPONSE_QUEUE_ROUTINGKEY_00C = EQUIPMENT_NAME_00C +"_EAP_Response_Queue_RoutingKey";
|
||||
public static final String MES_REQUEST_QUEUE_ROUTINGKEY_00C = EQUIPMENT_NAME_00C +"_MES_Request_Queue_RoutingKey";
|
||||
public static final String MES_RESPONSE_QUEUE_ROUTINGKEY_00C = EQUIPMENT_NAME_00C +"_MES_Response_Queue_RoutingKey";
|
||||
|
||||
|
||||
@Bean
|
||||
public DirectExchange EXCHANGE_NAME_00C(){
|
||||
return new DirectExchange(EXCHANGE_NAME_00C);
|
||||
}
|
||||
|
||||
//todo
|
||||
@Bean
|
||||
public Queue MES_REQUEST_QUEUE_00C(){
|
||||
Queue queue = new Queue(MES_REQUEST_QUEUE_00C);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Queue MES_RESPONSE_QUEUE_00C(){
|
||||
Queue queue = new Queue(MES_RESPONSE_QUEUE_00C);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
}
|
||||
@Bean
|
||||
public Queue EAP_REQUEST_QUEUE_00C(){
|
||||
Queue queue = new Queue(EAP_REQUEST_QUEUE_00C);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
|
||||
}
|
||||
@Bean
|
||||
public Queue EAP_RESPONSE_QUEUE_00C(){
|
||||
Queue queue = new Queue(EAP_RESPONSE_QUEUE_00C);
|
||||
queue.addArgument("x-dead-letter-exchange",ConfigOfDeadLetterQueue.EXCHANGE_NAME_DLE);
|
||||
queue.addArgument("x-dead-letter-routing-key",ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
queue.addArgument("x-max-priority",ConfigOfDeadLetterQueue.MAX_PRIORITY);
|
||||
return queue;
|
||||
}
|
||||
|
||||
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueA_00C(){
|
||||
return BindingBuilder.bind(EAP_REQUEST_QUEUE_00C()).to(EXCHANGE_NAME_00C())
|
||||
.with(EAP_REQUEST_QUEUE_ROUTINGKEY_00C);
|
||||
}
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueB_00C(){
|
||||
return BindingBuilder.bind(EAP_RESPONSE_QUEUE_00C()).to(EXCHANGE_NAME_00C())
|
||||
.with(EAP_RESPONSE_QUEUE_ROUTINGKEY_00C);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueC_00C(){
|
||||
return BindingBuilder.bind(MES_REQUEST_QUEUE_00C()).to(EXCHANGE_NAME_00C())
|
||||
.with(MES_REQUEST_QUEUE_ROUTINGKEY_00C);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding bindExchangeAndQueueD_00C(){
|
||||
return BindingBuilder.bind(MES_RESPONSE_QUEUE_00C()).to(EXCHANGE_NAME_00C())
|
||||
.with(MES_RESPONSE_QUEUE_ROUTINGKEY_00C);
|
||||
}
|
||||
}
|
@ -0,0 +1,52 @@
|
||||
package com.qgs.dc.mq.configuration;
|
||||
|
||||
import org.springframework.amqp.core.Binding;
|
||||
import org.springframework.amqp.core.BindingBuilder;
|
||||
import org.springframework.amqp.core.DirectExchange;
|
||||
import org.springframework.amqp.core.Queue;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/14 10:45
|
||||
*/
|
||||
@Configuration
|
||||
public class ConfigOfDeadLetterQueue {
|
||||
/**
|
||||
* 队列默认参数:
|
||||
* durable: true
|
||||
* exclusive: false
|
||||
* autoDelete: false
|
||||
*/
|
||||
|
||||
/**
|
||||
* 死信队列 定义
|
||||
*
|
||||
* 所以 MES-Received 处理异常的 Message 都会被 投递到 Dead_Letter_Exchange => Dead_Letter_Queue(这个队列)
|
||||
*/
|
||||
public static final String EXCHANGE_NAME_DLE = "Dead_Letter_Exchange";
|
||||
public static final String EAP_REQUEST_QUEUE_DLE = "Dead_Letter_Queue";
|
||||
public static final String EAP_REQUEST_QUEUE_ROUTINGKEY_DLE = "DL_For_MESReceived_Rk";
|
||||
public static final Integer MAX_PRIORITY = 10;
|
||||
|
||||
@Bean
|
||||
public Queue EAP_REQUEST_QUEUE_DLE(){
|
||||
Queue queue = new Queue(EAP_REQUEST_QUEUE_DLE);
|
||||
queue.setIgnoreDeclarationExceptions(true);
|
||||
|
||||
return queue;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public DirectExchange EXCHANGE_NAME_DLE(){
|
||||
return new DirectExchange(EXCHANGE_NAME_DLE);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public Binding EAP_REQUEST_QUEUE_ROUTINGKEY_DLE(){
|
||||
return BindingBuilder.bind(EAP_REQUEST_QUEUE_DLE()).to(EXCHANGE_NAME_DLE())
|
||||
.with(EAP_REQUEST_QUEUE_ROUTINGKEY_DLE);
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
package com.qgs.dc.mq.consumer;
|
||||
|
||||
|
||||
import com.qgs.dc.mq.configuration.ConfigOfDeadLetterQueue;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.amqp.support.AmqpHeaders;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/6/22 15:36
|
||||
*/
|
||||
@Component
|
||||
public class DeadLetterQueueReceived {
|
||||
// @RabbitListener(
|
||||
// bindings = @QueueBinding(
|
||||
// value = @Queue(value="Dead_Letter_Queue_PID00B",durable = "true"),
|
||||
// exchange = @Exchange(name = "Dead_Letter_Exchange",durable = "true",type = ExchangeTypes.DIRECT,ignoreDeclarationExceptions = "true"),
|
||||
// key = "Dead_Letter_Queue_PID00B_RoutingKey"
|
||||
// )
|
||||
// )
|
||||
|
||||
|
||||
@RabbitListener(queues = ConfigOfDeadLetterQueue.EAP_REQUEST_QUEUE_DLE)
|
||||
@RabbitHandler
|
||||
public void dlForPID00B(Message<?> message, Channel channel)throws Exception{
|
||||
|
||||
System.out.println("线程名"+Thread.currentThread().hashCode()+"==============Dead_Letter_Exchange=================,"+",attr2"+message.getHeaders().get("attr2"));
|
||||
|
||||
Thread.sleep(500);
|
||||
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
|
||||
|
||||
//throw new Exception("12331");
|
||||
|
||||
//channel.basicNack(deliveryTag,false,true);
|
||||
channel.basicAck(deliveryTag,false);
|
||||
}
|
||||
}
|
144
src/main/java/com/qgs/dc/mq/consumer/PID00BReceived.java
Normal file
144
src/main/java/com/qgs/dc/mq/consumer/PID00BReceived.java
Normal file
@ -0,0 +1,144 @@
|
||||
package com.qgs.dc.mq.consumer;
|
||||
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
import com.qgs.dc.mq.configuration.ConfigOf00B;
|
||||
import com.qgs.dc.mq.consumer.commonHandler.MQMessageHandler;
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
import com.qgs.dc.mq.entity.common.Header;
|
||||
import com.qgs.dc.mq.entity.specificBody.QueryEQStatusBody;
|
||||
import com.qgs.dc.mq.secsgem.SendedList;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.amqp.support.AmqpHeaders;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Desc: "PID00B设备 接收MQ消息 监听类"
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/6/22 15:30
|
||||
*
|
||||
* Ctrl+R 替换设备名
|
||||
*/
|
||||
@Component
|
||||
public class PID00BReceived {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(PID00BReceived.class);
|
||||
|
||||
@Autowired
|
||||
MQMessageHandler mqMessageHandler;
|
||||
|
||||
@RabbitListener(queues = ConfigOf00B.EAP_REQUEST_QUEUE_00B)
|
||||
@RabbitHandler
|
||||
public void eapRequest(Message<?> message, Channel channel)throws Exception{
|
||||
|
||||
logger.info("==============received message-EAP_REQUEST_QUEUE_00B=================,priority:"+"equipmentName"+message.getHeaders().get("attr2"));
|
||||
|
||||
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
|
||||
//MQMessage 中的 transactionId
|
||||
String transactionId = (String)message.getHeaders().get("spring_returned_message_correlation");
|
||||
//logger.info("transactionId:"+transactionId);
|
||||
|
||||
try {
|
||||
|
||||
MQMessage mqMessage = CommonFunction.parse(message);
|
||||
|
||||
//1. 正常情况
|
||||
//Integer integer = mqMessageHandler.requestHandler(message);
|
||||
String integer= HttpUtil.post("localhost:8080/api/mq/mq-message-received/receivedFromEapRequest",JSONObject.toJSONString(mqMessage));
|
||||
Integer result = Integer.valueOf(integer);
|
||||
|
||||
//注意 这里特别注意 已经拒收的消息 再签收是要出错的,这里要特别注意。
|
||||
if(result == 1){
|
||||
logger.info("在 EAP_REQUEST_QUEUE_00B 队列中,transitionId"+transactionId+", 这条消息处理成功");
|
||||
channel.basicAck(deliveryTag,false);
|
||||
}else {
|
||||
logger.error("在 EAP_REQUEST_QUEUE_00B 队列中,transitionId"+transactionId+" 处理消息的时候 出现异常,然后 拒签消息 ,然后丢到死信队列");
|
||||
channel.basicNack(deliveryTag,false,false);
|
||||
}
|
||||
|
||||
|
||||
//2.模拟异常 ,然后 拒签消息 ,然后丢到死信队列
|
||||
|
||||
//throw new Exception("11111");
|
||||
}catch (Exception e){
|
||||
// 第一个false 是 不批量签收;第二个false 是 不重回队列
|
||||
channel.basicNack(deliveryTag,false,false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
//localhost:8001
|
||||
|
||||
|
||||
MQMessage mqMessage = new MQMessage();
|
||||
|
||||
Header header = new Header("Request","Execute","QUERYEQPStatus","12");
|
||||
QueryEQStatusBody queryEQStatusBody = new QueryEQStatusBody();
|
||||
queryEQStatusBody.setVidType("u4");
|
||||
List<String> vids = new ArrayList<>();
|
||||
vids.add("10000");
|
||||
vids.add("10001");
|
||||
vids.add("10002");
|
||||
queryEQStatusBody.setVidList(vids);
|
||||
mqMessage.setBody(JSONObject.toJSONBytes(queryEQStatusBody));
|
||||
mqMessage.setHeader(header);
|
||||
|
||||
|
||||
String s = JSONObject.toJSONString(mqMessage);
|
||||
|
||||
System.out.println(s);
|
||||
String result= HttpUtil.post("localhost:8001/receivedFromEapRequest",s);
|
||||
|
||||
System.out.println(result);
|
||||
}
|
||||
|
||||
@RabbitListener(queues = ConfigOf00B.MES_RESPONSE_QUEUE_00B)
|
||||
@RabbitHandler
|
||||
public void mesResponse(Message<?> message, Channel channel)throws Exception{
|
||||
logger.info("==============PID00B_Exchange-MES_Response_Queue=================,priority:"+message.getHeaders().get("priority")+",attr1"+message.getHeaders().get("attr1"));
|
||||
|
||||
|
||||
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
|
||||
|
||||
//模拟异常 ,然后 拒签消息 ,然后丢到死信队列
|
||||
try {
|
||||
MQMessage mqMessage = CommonFunction.parse(message);
|
||||
String transactionId = mqMessage.getHeader().getTransactionId();
|
||||
Integer result = mqMessageHandler.responseHandler(message);
|
||||
if(result == 1){
|
||||
logger.info("在 MES_RESPONSE_QUEUE_00B 队列中 , transitionId"+transactionId+" 这条消息处理成功");
|
||||
channel.basicAck(deliveryTag,false);
|
||||
}else {
|
||||
logger.error("在 MES_RESPONSE_QUEUE_00B 队列中 ,transitionId"+transactionId+" 处理消息的时候 出现异常,然后 拒签消息 ,然后丢到死信队列");
|
||||
channel.basicNack(deliveryTag,false,false);
|
||||
}
|
||||
|
||||
//throw new Exception("11111");
|
||||
}catch (Exception e){
|
||||
// 第一个false 是 不批量签收;第二个false 是 不重回队列
|
||||
channel.basicNack(deliveryTag,false,false);
|
||||
return;
|
||||
}
|
||||
|
||||
//注意 这里特别注意 已经拒收的消息 再签收是要出错的,这里要特别注意。
|
||||
//channel.basicAck(deliveryTag,false);
|
||||
|
||||
}
|
||||
|
||||
}
|
73
src/main/java/com/qgs/dc/mq/consumer/PID00CReceived.java
Normal file
73
src/main/java/com/qgs/dc/mq/consumer/PID00CReceived.java
Normal file
@ -0,0 +1,73 @@
|
||||
package com.qgs.dc.mq.consumer;
|
||||
|
||||
import com.qgs.dc.mq.configuration.ConfigOf00C;
|
||||
import com.rabbitmq.client.Channel;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||
import org.springframework.amqp.support.AmqpHeaders;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @Desc: "PID00B设备 接收MQ消息 监听类"
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/6/22 15:30
|
||||
*
|
||||
* Ctrl+R 替换设备名
|
||||
*/
|
||||
@Component
|
||||
public class PID00CReceived {
|
||||
|
||||
@RabbitListener(queues = ConfigOf00C.EAP_REQUEST_QUEUE_00C)
|
||||
@RabbitHandler
|
||||
public void eapRequest(Message<?> message, Channel channel)throws Exception{
|
||||
|
||||
System.out.println("==============received message-EAP_REQUEST_QUEUE_00C=================,priority:"+"equipmentName"+message.getHeaders().get("attr2"));
|
||||
Thread.sleep(100);
|
||||
|
||||
String correlationId = (String)message.getHeaders().get("spring_returned_message_correlation");
|
||||
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
|
||||
|
||||
|
||||
|
||||
|
||||
//模拟异常 ,然后 拒签消息 ,然后丢到死信队列
|
||||
try {
|
||||
System.err.println("处理消息的时候 出现异常,然后 拒签消息 ,然后丢到死信队列");
|
||||
throw new Exception("11111");
|
||||
}catch (Exception e){
|
||||
// 第一个false 是 不批量签收;第二个false 是 不重回队列
|
||||
channel.basicNack(deliveryTag,false,false);
|
||||
return;
|
||||
}
|
||||
|
||||
//注意 这里特别注意 已经拒收的消息 再签收是要出错的,这里要特别注意。
|
||||
//channel.basicAck(deliveryTag,false);
|
||||
|
||||
}
|
||||
|
||||
@RabbitListener(queues = ConfigOf00C.MES_RESPONSE_QUEUE_00C)
|
||||
@RabbitHandler
|
||||
public void mesResponse(Message<?> message, Channel channel)throws Exception{
|
||||
System.out.println("==============PID00B_Exchange-MES_Response_Queue=================,priority:"+message.getHeaders().get("priority")+",attr1"+message.getHeaders().get("attr1"));
|
||||
Thread.sleep(100);
|
||||
|
||||
Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG);
|
||||
|
||||
|
||||
//模拟异常 ,然后 拒签消息 ,然后丢到死信队列
|
||||
try {
|
||||
System.err.println("处理消息的时候 出现异常,然后 拒签消息 ,然后丢到死信队列");
|
||||
throw new Exception("11111");
|
||||
}catch (Exception e){
|
||||
// 第一个false 是 不批量签收;第二个false 是 不重回队列
|
||||
channel.basicNack(deliveryTag,false,false);
|
||||
return;
|
||||
}
|
||||
|
||||
//注意 这里特别注意 已经拒收的消息 再签收是要出错的,这里要特别注意。
|
||||
//channel.basicAck(deliveryTag,false);
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,96 @@
|
||||
package com.qgs.dc.mq.consumer.commonHandler;
|
||||
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
import com.qgs.dc.mq.consumer.PID00BReceived;
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
import com.qgs.dc.mq.entity.specificBody.QueryEQStatusBody;
|
||||
import com.qgs.dc.mq.producer.component.RabbitSender;
|
||||
import com.qgs.dc.mq.secsgem.SendedList;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/25 15:17
|
||||
*/
|
||||
@Component
|
||||
public class MQMessageHandler {
|
||||
|
||||
@Autowired
|
||||
RabbitSender rabbitSender;
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(MQMessageHandler.class);
|
||||
|
||||
/**
|
||||
* 执行 queryEquipmentStatus 业务逻辑
|
||||
* @param mqMessage
|
||||
* @return 结果依据requestHandler return来
|
||||
*/
|
||||
public Integer queryEquipmentStatus(MQMessage mqMessage){
|
||||
QueryEQStatusBody queryEqStatusBody = (QueryEQStatusBody)CommonFunction.parseBody(mqMessage.getBody(), QueryEQStatusBody.class);
|
||||
//开始
|
||||
//这里写 业务逻辑
|
||||
|
||||
//结束
|
||||
System.out.println(queryEqStatusBody.toString());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
String s = "";
|
||||
}
|
||||
|
||||
/**
|
||||
* reply消息 处理方法
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
public Integer responseHandler(Message<?> message){
|
||||
MQMessage mqMessage = CommonFunction.parse(message);
|
||||
String transactionId = mqMessage.getHeader().getTransactionId();
|
||||
SendedList.set(transactionId,mqMessage);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* 业务处理方法
|
||||
* @param message
|
||||
* @return
|
||||
* 1 = 代表成功 (外部可以 正常签收message (basicAck))
|
||||
* 2 = 代表业务处理异常 (外部 拒收 (basicNack))
|
||||
* 3 = 代表业务处理失败 (可以选择 签收 也可以拒收 依据自己业务决定 )
|
||||
*/
|
||||
public Integer requestHandler(Message<?> message){
|
||||
|
||||
MQMessage mqMessage = CommonFunction.parse(message);
|
||||
String messageName = mqMessage.getHeader().getMessageName();
|
||||
Integer result = -1;
|
||||
//业务逻辑
|
||||
switch (messageName) {
|
||||
case "QUERYEQPStatus":
|
||||
result = queryEquipmentStatus(mqMessage);
|
||||
break;
|
||||
case "b": //b分支
|
||||
System.out.println("匹配成功2");
|
||||
break;
|
||||
case "c": //c分支
|
||||
System.out.println("匹配成功3");
|
||||
break;
|
||||
case "d": //d分支
|
||||
System.out.println("匹配成功4");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
91
src/main/java/com/qgs/dc/mq/controller/MQController.java
Normal file
91
src/main/java/com/qgs/dc/mq/controller/MQController.java
Normal file
@ -0,0 +1,91 @@
|
||||
package com.qgs.dc.mq.controller;
|
||||
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.qgs.dc.mq.Constant.SecsGemTimeout;
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
import com.qgs.dc.mq.entity.CallbackMessageEntity;
|
||||
import com.qgs.dc.mq.entity.common.Header;
|
||||
import com.qgs.dc.mq.entity.specificBody.QueryEQStatusBody;
|
||||
import com.qgs.dc.mq.producer.component.RabbitSender;
|
||||
import com.qgs.dc.mq.secsgem.AsyncFuture;
|
||||
import com.qgs.dc.mq.secsgem.SendedList;
|
||||
import com.qgs.dc.opcua.controller.R;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Author: 蔡翔
|
||||
* @Date: 2019/10/12 15:15
|
||||
* @Version 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/mq")
|
||||
public class MQController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(MQController.class);
|
||||
|
||||
@Autowired
|
||||
RabbitSender rabbitSender;
|
||||
|
||||
@PostMapping("/eapResponse")
|
||||
/**
|
||||
* desc : 回复EAP的request 的回调接口(向rabbitmq中发送消息(direct模式))
|
||||
* MES => DC(数据采集中间件) => MQ => EAP
|
||||
*/
|
||||
public R eapResponse(@RequestBody CallbackMessageEntity callbackMessageEntity){
|
||||
try {
|
||||
logger.info("MES => EAP (EAP_Response), 状态:DC已收到 ,内容:"+ callbackMessageEntity.toString());
|
||||
//properties 这里的参数是写在MQ消息 header里面的,如果EAP端 需要某些参数 可以写在这里,eap去取更方便一些
|
||||
Map<String,Object> properties = new HashMap<>();
|
||||
properties.put("equipmentName","PID001");
|
||||
properties.put("transitionId", callbackMessageEntity.getMqMessage().getHeader().getTransactionId());
|
||||
rabbitSender.reply(callbackMessageEntity.getMqMessage(),properties, callbackMessageEntity.getExchangeName(), callbackMessageEntity.getRoutingKey(),"6000");
|
||||
logger.info("MES => EAP (EAP_Response) , 状态:DC已发送给MQ , 内容:"+ callbackMessageEntity.toString());
|
||||
return R.ok("回复成功");
|
||||
}catch (Exception e){
|
||||
logger.error("MES => EAP (EAP_Response) , 状态:DC处理异常 , 内容:"+ callbackMessageEntity.toString());
|
||||
return R.error().put("result",e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/mesRequest")
|
||||
/**
|
||||
* desc : MES给EAP发送远程指令(MES_Request)(向rabbitmq中发送消息(direct模式))
|
||||
* MES => DC(数据采集中间件) => MQ => EAP
|
||||
* return :返回 的就是这个指令的回复指令
|
||||
*/
|
||||
public R mesRequest(@RequestBody CallbackMessageEntity callbackMessageEntity){
|
||||
try {
|
||||
String transitionId = callbackMessageEntity.getMqMessage().getHeader().getTransactionId();
|
||||
MQMessage mqMessage = callbackMessageEntity.getMqMessage();
|
||||
String exchangeName = callbackMessageEntity.getExchangeName();
|
||||
String routingKey = callbackMessageEntity.getRoutingKey();
|
||||
|
||||
logger.info("MES => EAP (MES_Request), 状态:DC已收到 , 内容:"+ callbackMessageEntity.toString());
|
||||
//properties 这里的参数是写在MQ消息 header里面的,如果EAP端 需要某些参数 可以写在这里,eap去取更方便一些
|
||||
Map<String,Object> properties = new HashMap<>();
|
||||
properties.put("equipmentName","PID001");
|
||||
properties.put("transitionId",transitionId);
|
||||
|
||||
rabbitSender.reply(mqMessage,properties,exchangeName,routingKey,"6000");
|
||||
logger.info("MES => EAP (MES_Request) , 状态:DC已发送给MQ , 内容:"+ callbackMessageEntity.toString());
|
||||
|
||||
AsyncFuture<MQMessage> add = SendedList.add(transitionId,mqMessage);
|
||||
MQMessage mqMessageResponse = add.get(SecsGemTimeout.T3_TIMEOUT);
|
||||
return R.ok().put("responseMessage",mqMessageResponse);
|
||||
}catch (Exception e){
|
||||
logger.error("MES => EAP (MES_Request) , 状态:DC处理异常 , 内容:"+ callbackMessageEntity.toString());
|
||||
return R.error().put("result",e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
package com.qgs.dc.mq.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/27 10:17
|
||||
*/
|
||||
@Data
|
||||
@JSONType(orders={"exchangeName","routingKey","mqMessage"})
|
||||
public class CallbackMessageEntity {
|
||||
private String exchangeName;
|
||||
private String routingKey;
|
||||
private MQMessage mqMessage;
|
||||
}
|
19
src/main/java/com/qgs/dc/mq/entity/MQMessage.java
Normal file
19
src/main/java/com/qgs/dc/mq/entity/MQMessage.java
Normal file
@ -0,0 +1,19 @@
|
||||
package com.qgs.dc.mq.entity;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import com.qgs.dc.mq.entity.common.Header;
|
||||
import com.qgs.dc.mq.entity.common.Returns;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/12 15:38
|
||||
*/
|
||||
@Data
|
||||
@JSONType(orders={"header","body","returns"})
|
||||
public class MQMessage {
|
||||
private Header header;
|
||||
private byte[] body;
|
||||
private Returns returns;
|
||||
}
|
103
src/main/java/com/qgs/dc/mq/entity/common/Header.java
Normal file
103
src/main/java/com/qgs/dc/mq/entity/common/Header.java
Normal file
@ -0,0 +1,103 @@
|
||||
package com.qgs.dc.mq.entity.common;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/12 15:26
|
||||
*/
|
||||
@Data
|
||||
@JSONType(orders={"transactionId","messageType","messageCategory","messageName","equipmentId","sendTimestamp","from","to"})
|
||||
public class Header {
|
||||
private String transactionId;
|
||||
private String messageType;
|
||||
private String messageCategory;
|
||||
private String messageName;
|
||||
private String equipmentId;
|
||||
private String sendTimestamp;
|
||||
private String from;
|
||||
private String to;
|
||||
|
||||
//注意:一定要构造一个空的 构造函数,不然fastjson在序列化 和反序列化的时候会用下面的Header这样导致数据一致
|
||||
public Header() {
|
||||
|
||||
}
|
||||
public Header(String messageType, String messageCategory, String messageName, String equipmentId) {
|
||||
|
||||
this.transactionId = equipmentId+"_"+ CommonFunction.getNowDate(2)+"_"+CommonFunction.getUUID(5);
|
||||
this.messageType = messageType;
|
||||
this.messageCategory = messageCategory;
|
||||
this.messageName = messageName;
|
||||
this.equipmentId = equipmentId;
|
||||
this.sendTimestamp = CommonFunction.getNowDate(1);
|
||||
this.from = "mes";
|
||||
this.to = "eap";
|
||||
}
|
||||
|
||||
public String getTransactionId() {
|
||||
return transactionId;
|
||||
}
|
||||
|
||||
public void setTransactionId(String transactionId) {
|
||||
this.transactionId = transactionId;
|
||||
}
|
||||
|
||||
public String getMessageType() {
|
||||
return messageType;
|
||||
}
|
||||
|
||||
public void setMessageType(String messageType) {
|
||||
this.messageType = messageType;
|
||||
}
|
||||
|
||||
public String getMessageCategory() {
|
||||
return messageCategory;
|
||||
}
|
||||
|
||||
public void setMessageCategory(String messageCategory) {
|
||||
this.messageCategory = messageCategory;
|
||||
}
|
||||
|
||||
public String getMessageName() {
|
||||
return messageName;
|
||||
}
|
||||
|
||||
public void setMessageName(String messageName) {
|
||||
this.messageName = messageName;
|
||||
}
|
||||
|
||||
public String getEquipmentId() {
|
||||
return equipmentId;
|
||||
}
|
||||
|
||||
public void setEquipmentId(String equipmentId) {
|
||||
this.equipmentId = equipmentId;
|
||||
}
|
||||
|
||||
public String getSendTimestamp() {
|
||||
return sendTimestamp;
|
||||
}
|
||||
|
||||
public void setSendTimestamp(String sendTimestamp) {
|
||||
this.sendTimestamp = sendTimestamp;
|
||||
}
|
||||
|
||||
public String getFrom() {
|
||||
return from;
|
||||
}
|
||||
|
||||
public void setFrom(String from) {
|
||||
this.from = from;
|
||||
}
|
||||
|
||||
public String getTo() {
|
||||
return to;
|
||||
}
|
||||
|
||||
public void setTo(String to) {
|
||||
this.to = to;
|
||||
}
|
||||
}
|
37
src/main/java/com/qgs/dc/mq/entity/common/Returns.java
Normal file
37
src/main/java/com/qgs/dc/mq/entity/common/Returns.java
Normal file
@ -0,0 +1,37 @@
|
||||
package com.qgs.dc.mq.entity.common;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/12 15:35
|
||||
*/
|
||||
@Data
|
||||
@JSONType(orders={"returnCode","ReasonCode"})
|
||||
public class Returns {
|
||||
private String returnCode;
|
||||
private String ReasonCode;
|
||||
|
||||
public String getReturnCode() {
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
public void setReturnCode(String returnCode) {
|
||||
this.returnCode = returnCode;
|
||||
}
|
||||
|
||||
public String getReasonCode() {
|
||||
return ReasonCode;
|
||||
}
|
||||
|
||||
public void setReasonCode(String reasonCode) {
|
||||
ReasonCode = reasonCode;
|
||||
}
|
||||
|
||||
public Returns(String returnCode, String reasonCode) {
|
||||
this.returnCode = returnCode;
|
||||
ReasonCode = reasonCode;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.qgs.dc.mq.entity.specificBody;
|
||||
|
||||
import com.alibaba.fastjson.annotation.JSONType;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/12 15:43
|
||||
*/
|
||||
@Data
|
||||
@JSONType(orders={"VIDType","VIDList"})
|
||||
public class QueryEQStatusBody {
|
||||
private String vidType;
|
||||
private List<String> vidList;
|
||||
}
|
@ -0,0 +1,19 @@
|
||||
package com.qgs.dc.mq.exception;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/17 16:03
|
||||
*/
|
||||
public class T3TimeoutException extends Exception{
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
// 提供无参数的构造方法
|
||||
public T3TimeoutException() {
|
||||
}
|
||||
|
||||
// 提供一个有参数的构造方法,可自动生成
|
||||
public T3TimeoutException(String message) {
|
||||
super(message);// 把参数传递给Throwable的带String参数的构造方法
|
||||
}
|
||||
}
|
350
src/main/java/com/qgs/dc/mq/producer/component/RabbitSender.java
Normal file
350
src/main/java/com/qgs/dc/mq/producer/component/RabbitSender.java
Normal file
@ -0,0 +1,350 @@
|
||||
package com.qgs.dc.mq.producer.component;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import org.springframework.amqp.AmqpException;
|
||||
import org.springframework.amqp.core.MessagePostProcessor;
|
||||
import org.springframework.amqp.core.ReturnedMessage;
|
||||
import org.springframework.amqp.rabbit.connection.CorrelationData;
|
||||
import org.springframework.amqp.rabbit.core.RabbitTemplate;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.messaging.support.MessageBuilder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
@Component
|
||||
public class RabbitSender {
|
||||
@Autowired
|
||||
private RabbitTemplate rabbitTemplate;
|
||||
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(RabbitSender.class);
|
||||
|
||||
|
||||
final RabbitTemplate.ReturnsCallback returnsCallback = new RabbitTemplate.ReturnsCallback(){
|
||||
//rabbitTemplate.setReturnCallback 会调用这个接口
|
||||
//第二种publisher-returns模式,该模式会在消息没有被路由到queues时将消息返回
|
||||
@Override
|
||||
public void returnedMessage(ReturnedMessage returned) {
|
||||
org.springframework.amqp.core.Message message = returned.getMessage();
|
||||
logger.error("消息未能成功路由到指定queues : return--message:" + new String(message.getBody()) + ",replyCode:" + returned.getReplyCode()
|
||||
+ ",replyText:" + returned.getReplyText() + ",exchange:" + returned.getExchange() + ",routingKey:" + returned.getRoutingKey());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* rabbitTemplate.setConfirmCallback() 会调用这个接口。
|
||||
* 确认消息 的回调监听接口,,用于确认消息是否被broker所收到(也就是 是否投递到exchange(不能保证是否投递到queue))。
|
||||
* 当消息被broker 成功接收到 后 会调用这个方法
|
||||
* */
|
||||
/**
|
||||
* 参数:
|
||||
* CorrelationData 作为一个唯一标识( 生产者 消费者 消息确认的唯一标识 )
|
||||
* b broker是否落盘成功
|
||||
* s 失败的一些异常信息会送
|
||||
* */
|
||||
final RabbitTemplate.ConfirmCallback confirmCallback = new RabbitTemplate.ConfirmCallback() {
|
||||
/**
|
||||
* 参数:
|
||||
* CorrelationData 作为一个唯一标识( 生产者 消费者 消息确认的唯一标识 )
|
||||
* ack broker是否落盘成功
|
||||
* s 失败的一些异常信息会送
|
||||
* */
|
||||
@Override
|
||||
public void confirm(CorrelationData correlationData, boolean ack, String cause) {
|
||||
//如果RabbitMQ 因为自身内部错
|
||||
//误导致消息丢失,就会发送一条nack (Basic . Nack )命令,生产者应用程序同样可以在回调
|
||||
//方法中处理该nack 命令。
|
||||
if (ack) {
|
||||
logger.info("消息 transactionId: [" + correlationData.getId() + "] 成功发送到指定ExChange");
|
||||
} else {
|
||||
logger.info("消息 transactionId: [" + correlationData.getId() + "] 发送到ExChange失败,原因 : " + cause);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @Description 向rabbitmq中发送消息(topic模式)
|
||||
* @Param
|
||||
* message 具体的消息内容
|
||||
* properties 额外的附加属性
|
||||
* @Return void
|
||||
* @Author caixiang
|
||||
* @Date 2020/6/17
|
||||
**/
|
||||
public void sendTopic(Object message, Map<String,Object> properties, String routingKey) throws Exception{
|
||||
MessageHeaders messageHeaders = new MessageHeaders(properties);
|
||||
//message的Object 传进来的可能就是 泛型。。createMessage会自动生成 deliveryTag
|
||||
Message<?> msg = MessageBuilder.createMessage(message,messageHeaders);
|
||||
|
||||
//唯一标识
|
||||
CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());
|
||||
|
||||
//设置确认 confirm
|
||||
rabbitTemplate.setConfirmCallback(confirmCallback);
|
||||
|
||||
/**
|
||||
* 声明消息处理器 (这个消息处理器 是在 发给broker 之前执行的(就是对你要发送给mq 的消息 进行封装处理 和 上面的confirmCallback不同)。)
|
||||
* 这个对消息进行处理 可以设置一些参数 对消息进行一些定制化处理
|
||||
* 我们这里 来设置消息的编码 以及消息的过期时间
|
||||
* 因为在.net 以及其他版本过期时间不一致 这里的时间毫秒值 为字符串
|
||||
* */
|
||||
MessagePostProcessor mpp = new MessagePostProcessor(){
|
||||
//当发送消息到broker 成功 之后调用下面的方法。
|
||||
@Override
|
||||
public org.springframework.amqp.core.Message postProcessMessage(org.springframework.amqp.core.Message message) throws AmqpException {
|
||||
System.err.println("posted todo:"+message);
|
||||
//message.getMessageProperties() 下 可以进行各种 SET 属性
|
||||
return message;
|
||||
}
|
||||
};
|
||||
//发送端 要可以注重routingkey。。。因为exchange 要依据这个routingkey 把这条消息转发给队列。
|
||||
rabbitTemplate.convertAndSend("rc_exchange",
|
||||
routingKey,
|
||||
msg,
|
||||
mpp,
|
||||
cd
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @Description 向rabbitmq中发送消息(direct模式)
|
||||
* @Param
|
||||
* mqMessage 通用的消息格式
|
||||
* properties 额外的附加属性,放在Message Header里
|
||||
* exchange exchangeName
|
||||
* routingKey 路由键
|
||||
* expiration 设置这条消息的过期时间,如 6000 =》 6s ,6s后未被消费就过期
|
||||
* @Return void
|
||||
* @Author caixiang
|
||||
* @Date 2020/6/17
|
||||
**/
|
||||
public void sendDirect(MQMessage mqMessage, Map<String,Object> properties, String exchange, String routingKey, String expiration) throws Exception{
|
||||
byte[] message = JSONObject.toJSONBytes(mqMessage);
|
||||
|
||||
MessageHeaders messageHeaders = new MessageHeaders(properties);
|
||||
//message的Object 传进来的可能就是 泛型。。createMessage会自动生成 deliveryTag
|
||||
|
||||
//content_type 默认 就是application/octet-stream 不是json格式的
|
||||
Message<?> msg = MessageBuilder.createMessage(message,messageHeaders);
|
||||
|
||||
|
||||
//唯一标识
|
||||
String transitionId = mqMessage.getHeader().getEquipmentId()+"_"+ CommonFunction.getNowDate(2)+"_"+CommonFunction.getUUID(5);
|
||||
CorrelationData cd = new CorrelationData(transitionId);
|
||||
|
||||
|
||||
//设置确认 confirm(),投递到Exchange 成功的时候 会调用下面这个回调方法
|
||||
//rabbitTemplate.setConfirmCallback(confirmCallback); //ok
|
||||
|
||||
|
||||
//注意 有关rabbitTemplate 配置 的信息 不能写在这里,
|
||||
// 因为 每次外部REST接口过来(不同线程) 调用sendDirect方法的时候 都会setConfirmCallback(new ConfirmBackSender());
|
||||
//而rabbitmq只允许 设置 一次 ConfirmBack;这里new 了这么多 肯定不对
|
||||
//rabbitTemplate.setConfirmCallback(new ConfirmBackSender()); //这样不行
|
||||
rabbitTemplate.setConfirmCallback(confirmCallback); //这样可以,confirmBackSender就是把回调处理类 独立出去了 ,和写在本类中的returnCallback 做一个区别
|
||||
|
||||
//设置确认 returnedMessage(); 当未投递到queue的时候 会调用下面这个方法。
|
||||
//注意 :如果要设置setReturnCallback 那么 必须配置spring.rabbitmq.publisher-returns=true,spring.rabbitmq.template.mandatory=true
|
||||
rabbitTemplate.setReturnsCallback(returnsCallback);
|
||||
|
||||
/**
|
||||
* 声明消息处理器 (这个消息处理器 是在 发给broker 之前执行的(就是对你要发送给mq 的消息 进行封装处理 和 上面的confirmCallback不同)。)
|
||||
* 这个对消息进行处理 可以设置一些参数 对消息进行一些定制化处理
|
||||
* 我们这里 来设置消息的编码 以及消息的过期时间
|
||||
* 因为在.net 以及其他版本过期时间不一致 这里的时间毫秒值 为字符串
|
||||
* */
|
||||
MessagePostProcessor mpp = new MessagePostProcessor(){
|
||||
//当发送消息到broker 之前调用下面的方法,也就是对消息进行加工。
|
||||
@Override
|
||||
public org.springframework.amqp.core.Message postProcessMessage(org.springframework.amqp.core.Message message) throws AmqpException {
|
||||
// System.err.println("posted todo:"+message);
|
||||
// //message.getMessageProperties() 下 可以进行各种 SET 属性
|
||||
// Random random = new Random();
|
||||
// int i = random.nextInt(10);
|
||||
// message.getMessageProperties().setPriority(i);
|
||||
//过期时间: 单位毫秒 (注意:这些消息 只有在队列队首的 时候过期了才会移除,否则是不会被移除的)
|
||||
message.getMessageProperties().setExpiration(expiration);
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//发送端 要可以注重routingkey。。。因为exchange 要依据这个routingkey 把这条消息转发给队列。
|
||||
rabbitTemplate.convertAndSend(exchange,
|
||||
routingKey,
|
||||
msg,
|
||||
mpp,
|
||||
cd
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 回复EAP的request(向rabbitmq中发送消息(direct模式))
|
||||
* @Param
|
||||
* mqMessage 通用的消息格式
|
||||
* properties 额外的附加属性,放在Message Header里
|
||||
* exchange exchangeName
|
||||
* routingKey 路由键
|
||||
* expiration 设置这条消息的过期时间,如 6000 =》 6s ,6s后未被消费就过期
|
||||
* @Return void
|
||||
* @Author caixiang
|
||||
* @Date 2020/6/17
|
||||
**/
|
||||
public void reply(MQMessage mqMessage, Map<String,Object> properties, String exchange, String routingKey, String expiration) throws Exception{
|
||||
byte[] message = JSONObject.toJSONBytes(mqMessage);
|
||||
|
||||
MessageHeaders messageHeaders = new MessageHeaders(properties);
|
||||
//message的Object 传进来的可能就是 泛型。。createMessage会自动生成 deliveryTag
|
||||
|
||||
//content_type 默认 就是application/octet-stream 不是json格式的
|
||||
Message<?> msg = MessageBuilder.createMessage(message,messageHeaders);
|
||||
|
||||
|
||||
//唯一标识
|
||||
String transitionId = mqMessage.getHeader().getEquipmentId()+"_"+ CommonFunction.getNowDate(2)+"_"+CommonFunction.getUUID(5);
|
||||
CorrelationData cd = new CorrelationData(transitionId);
|
||||
|
||||
|
||||
//设置确认 confirm(),投递到Exchange 成功的时候 会调用下面这个回调方法
|
||||
//rabbitTemplate.setConfirmCallback(confirmCallback); //ok
|
||||
|
||||
|
||||
//注意 有关rabbitTemplate 配置 的信息 不能写在这里,
|
||||
// 因为 每次外部REST接口过来(不同线程) 调用sendDirect方法的时候 都会setConfirmCallback(new ConfirmBackSender());
|
||||
//而rabbitmq只允许 设置 一次 ConfirmBack;这里new 了这么多 肯定不对
|
||||
//rabbitTemplate.setConfirmCallback(new ConfirmBackSender()); //这样不行
|
||||
rabbitTemplate.setConfirmCallback(confirmCallback); //这样可以,confirmBackSender就是把回调处理类 独立出去了 ,和写在本类中的returnCallback 做一个区别
|
||||
|
||||
//设置确认 returnedMessage(); 当未投递到queue的时候 会调用下面这个方法。
|
||||
//注意 :如果要设置setReturnCallback 那么 必须配置spring.rabbitmq.publisher-returns=true,spring.rabbitmq.template.mandatory=true
|
||||
rabbitTemplate.setReturnsCallback(returnsCallback);
|
||||
|
||||
/**
|
||||
* 声明消息处理器 (这个消息处理器 是在 发给broker 之前执行的(就是对你要发送给mq 的消息 进行封装处理 和 上面的confirmCallback不同)。)
|
||||
* 这个对消息进行处理 可以设置一些参数 对消息进行一些定制化处理
|
||||
* 我们这里 来设置消息的编码 以及消息的过期时间
|
||||
* 因为在.net 以及其他版本过期时间不一致 这里的时间毫秒值 为字符串
|
||||
* */
|
||||
MessagePostProcessor mpp = new MessagePostProcessor(){
|
||||
//当发送消息到broker 之前调用下面的方法,也就是对消息进行加工。
|
||||
@Override
|
||||
public org.springframework.amqp.core.Message postProcessMessage(org.springframework.amqp.core.Message message) throws AmqpException {
|
||||
// System.err.println("posted todo:"+message);
|
||||
// //message.getMessageProperties() 下 可以进行各种 SET 属性
|
||||
// Random random = new Random();
|
||||
// int i = random.nextInt(10);
|
||||
// message.getMessageProperties().setPriority(i);
|
||||
//过期时间: 单位毫秒 (注意:这些消息 只有在队列队首的 时候过期了才会移除,否则是不会被移除的)
|
||||
message.getMessageProperties().setExpiration(expiration);
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//发送端 要可以注重routingkey。。。因为exchange 要依据这个routingkey 把这条消息转发给队列。
|
||||
rabbitTemplate.convertAndSend(exchange,
|
||||
routingKey,
|
||||
msg,
|
||||
mpp,
|
||||
cd
|
||||
);
|
||||
}
|
||||
//todo sendDirect应该改成 sendCommon(加上T3超时校验),还要加一个reply() 方法 专门用于 eapRequest 回复用
|
||||
|
||||
|
||||
|
||||
public void sendDirect(MQMessage mqMessage, Map<String,Object> properties, String exchange, String routingKey) throws Exception{
|
||||
byte[] message = JSONObject.toJSONBytes(mqMessage);
|
||||
MessageHeaders messageHeaders = new MessageHeaders(properties);
|
||||
Message<?> msg = MessageBuilder.createMessage(message,messageHeaders);
|
||||
//String transitionId = mqMessage.getHeader().getEquipmentId()+"_"+CommonFunction.getNowDate(2)+"_"+CommonFunction.getUUID(10);
|
||||
String transitionId = mqMessage.getHeader().getTransactionId();
|
||||
CorrelationData cd = new CorrelationData(transitionId);
|
||||
rabbitTemplate.setConfirmCallback(confirmCallback);
|
||||
rabbitTemplate.setReturnsCallback(returnsCallback);
|
||||
rabbitTemplate.convertAndSend(exchange,
|
||||
routingKey,
|
||||
msg,
|
||||
cd
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @Description 向rabbitmq中发送消息(direct模式)
|
||||
* @Param
|
||||
* message 具体的消息内容
|
||||
* properties 额外的附加属性
|
||||
* @Return void
|
||||
* @Author caixiang
|
||||
* @Date 2020/6/17
|
||||
**/
|
||||
public void sendDirect(Object message, Map<String,Object> properties,String routingKey,String exchange) throws Exception{
|
||||
MessageHeaders messageHeaders = new MessageHeaders(properties);
|
||||
//message的Object 传进来的可能就是 泛型。。createMessage会自动生成 deliveryTag
|
||||
|
||||
//content_type 默认 就是application/octet-stream 不是json格式的
|
||||
Message<?> msg = MessageBuilder.createMessage(message,messageHeaders);
|
||||
|
||||
|
||||
//唯一标识
|
||||
CorrelationData cd = new CorrelationData(UUID.randomUUID().toString());
|
||||
|
||||
|
||||
//设置确认 confirm(),投递到Exchange 成功的时候 会调用下面这个回调方法
|
||||
//rabbitTemplate.setConfirmCallback(confirmCallback); //ok
|
||||
|
||||
|
||||
//注意 有关rabbitTemplate 配置 的信息 不能写在这里,
|
||||
// 因为 每次外部REST接口过来(不同线程) 调用sendDirect方法的时候 都会setConfirmCallback(new ConfirmBackSender());
|
||||
//而rabbitmq只允许 设置 一次 ConfirmBack;这里new 了这么多 肯定不对
|
||||
//rabbitTemplate.setConfirmCallback(new ConfirmBackSender()); //这样不行
|
||||
rabbitTemplate.setConfirmCallback(confirmCallback); //这样可以,confirmBackSender就是把回调处理类 独立出去了 ,和写在本类中的returnCallback 做一个区别
|
||||
|
||||
//设置确认 returnedMessage(); 当未投递到queue的时候 会调用下面这个方法。
|
||||
//注意 :如果要设置setReturnCallback 那么 必须配置spring.rabbitmq.publisher-returns=true,spring.rabbitmq.template.mandatory=true
|
||||
rabbitTemplate.setReturnsCallback(returnsCallback);
|
||||
|
||||
/**
|
||||
* 声明消息处理器 (这个消息处理器 是在 发给broker 之前执行的(就是对你要发送给mq 的消息 进行封装处理 和 上面的confirmCallback不同)。)
|
||||
* 这个对消息进行处理 可以设置一些参数 对消息进行一些定制化处理
|
||||
* 我们这里 来设置消息的编码 以及消息的过期时间
|
||||
* 因为在.net 以及其他版本过期时间不一致 这里的时间毫秒值 为字符串
|
||||
* */
|
||||
MessagePostProcessor mpp = new MessagePostProcessor(){
|
||||
//当发送消息到broker 之前调用下面的方法,也就是对消息进行加工。
|
||||
@Override
|
||||
public org.springframework.amqp.core.Message postProcessMessage(org.springframework.amqp.core.Message message) throws AmqpException {
|
||||
System.err.println("posted todo:"+message);
|
||||
//message.getMessageProperties() 下 可以进行各种 SET 属性
|
||||
Random random = new Random();
|
||||
int i = random.nextInt(10);
|
||||
message.getMessageProperties().setPriority(i);
|
||||
//过期时间: 单位毫秒 (注意:这些消息 只有在队列队首的 时候过期了才会移除,否则是不会被移除的)
|
||||
message.getMessageProperties().setExpiration("6000");
|
||||
return message;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//发送端 要可以注重routingkey。。。因为exchange 要依据这个routingkey 把这条消息转发给队列。
|
||||
rabbitTemplate.convertAndSend(exchange,
|
||||
routingKey,
|
||||
msg,
|
||||
mpp,
|
||||
cd
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,130 @@
|
||||
package com.qgs.dc.mq.producer.controller;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
import com.qgs.dc.mq.producer.component.RabbitSender;
|
||||
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
import com.qgs.dc.mq.entity.common.Header;
|
||||
import com.qgs.dc.mq.entity.specificBody.QueryEQStatusBody;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/9/30 11:03
|
||||
*/
|
||||
@RestController
|
||||
public class TestController {
|
||||
@Autowired
|
||||
RabbitSender rabbitSender;
|
||||
|
||||
|
||||
|
||||
//For EAP SERVER1
|
||||
@GetMapping("/putMessageDirect")
|
||||
public String putMessageDirect() throws Exception {
|
||||
Map<String,Object> properties = new HashMap<>();
|
||||
properties.put("attr1",String.valueOf(1));
|
||||
properties.put("attr2","00B");
|
||||
//序列化
|
||||
MQMessage mqMessage = new MQMessage();
|
||||
|
||||
Header header = new Header("Request","Execute","QUERYEQPStatus","12");
|
||||
header.setTransactionId("abc123456");
|
||||
QueryEQStatusBody queryEQStatusBody = new QueryEQStatusBody();
|
||||
queryEQStatusBody.setVidType("u4");
|
||||
List<String> vids = new ArrayList<>();
|
||||
vids.add("10000");
|
||||
vids.add("10001");
|
||||
vids.add("10002");
|
||||
queryEQStatusBody.setVidList(vids);
|
||||
mqMessage.setBody(JSONObject.toJSONBytes(queryEQStatusBody));
|
||||
mqMessage.setHeader(header);
|
||||
|
||||
|
||||
|
||||
//rabbitSender.sendDirect(mqMessage,properties,"00B_Exchange","00B_EAP_Request_Queue_RoutingKey","6000");
|
||||
rabbitSender.sendDirect(mqMessage,properties,"00B_Exchange","00B_MES_Response_Queue_RoutingKey");
|
||||
|
||||
Thread.sleep(30);
|
||||
return null;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
Map<String,Object> properties = new HashMap<>();
|
||||
properties.put("attr1",String.valueOf(1));
|
||||
properties.put("attr2","00B");
|
||||
//序列化
|
||||
MQMessage mqMessage = new MQMessage();
|
||||
|
||||
Header header = new Header("Request","Execute","QUERYEQPStatus","12");
|
||||
header.setTransactionId("abc123456");
|
||||
QueryEQStatusBody queryEQStatusBody = new QueryEQStatusBody();
|
||||
queryEQStatusBody.setVidType("u4");
|
||||
List<String> vids = new ArrayList<>();
|
||||
vids.add("10000");
|
||||
vids.add("10001");
|
||||
vids.add("10002");
|
||||
queryEQStatusBody.setVidList(vids);
|
||||
mqMessage.setBody(JSONObject.toJSONBytes(queryEQStatusBody));
|
||||
mqMessage.setHeader(header);
|
||||
System.out.println(mqMessage);
|
||||
//序列化
|
||||
//1.jackson
|
||||
ObjectMapper objectMapper = new ObjectMapper();
|
||||
//byte[] byteJackson = objectMapper.writeValueAsBytes(mqMessage);
|
||||
//2.fastjson
|
||||
byte[] bytes = JSONObject.toJSONBytes(mqMessage);
|
||||
|
||||
//反序列化
|
||||
//1.jackson
|
||||
//MQMessage mqMessageJackson = objectMapper.readValue(byteJackson, MQMessage.class);
|
||||
//2.fastjson
|
||||
MQMessage mqMessageFastjson = JSONObject.parseObject(bytes, MQMessage.class);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
|
||||
// public static void main(String[] args) {
|
||||
// //序列化
|
||||
// MQMessage mesResponse = new MQMessage();
|
||||
//
|
||||
// Header header = new Header("Request","Execute","QUERYEQPStatus","12");
|
||||
// QueryEQStatusBody queryEQStatusBody = new QueryEQStatusBody();
|
||||
// queryEQStatusBody.setVidType("u4");
|
||||
// List<String> vids = new ArrayList<>();
|
||||
// vids.add("10000");
|
||||
// vids.add("10001");
|
||||
// vids.add("10002");
|
||||
// queryEQStatusBody.setVidList(vids);
|
||||
// mesResponse.setBody(JSONObject.toJSONBytes(queryEQStatusBody));
|
||||
// mesResponse.setHeader(header);
|
||||
//
|
||||
// byte[] bytes = JSONObject.toJSONBytes(mesResponse);
|
||||
//// String s = JSONObject.toJSONString(requestBody);
|
||||
//// RequestBody parsedRequestBody = JSONObject.parseObject(bytes, RequestBody.class);
|
||||
//// JSONObject jsonObject = (JSONObject)parsedRequestBody.getBody();
|
||||
//// QueryEQStatusBody queryEQStatusBody1 = JSON.toJavaObject(jsonObject, QueryEQStatusBody.class);
|
||||
//
|
||||
// //1.先解析成MesRequest/MesResponse ,拿到header里的messageName
|
||||
//// MQMessage message = CommonFunction.parse(bytes);
|
||||
//// String messageName = message.getHeader().getMessageName();
|
||||
////
|
||||
//// //拿到具体messageName 就可以拿到具体body
|
||||
//// QueryEQStatusBody queryEQStatusBody1 = (QueryEQStatusBody)CommonFunction.parseBody(message.getBody(), QueryEQStatusBody.class);
|
||||
//// System.out.println();
|
||||
// }
|
||||
|
||||
|
||||
}
|
63
src/main/java/com/qgs/dc/mq/secsgem/AsyncFuture.java
Normal file
63
src/main/java/com/qgs/dc/mq/secsgem/AsyncFuture.java
Normal file
@ -0,0 +1,63 @@
|
||||
package com.qgs.dc.mq.secsgem;
|
||||
|
||||
|
||||
import com.qgs.dc.mq.exception.T3TimeoutException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* @Author: 蔡翔
|
||||
* @Date: 2019/11/6 14:11
|
||||
* @Version 1.0
|
||||
*
|
||||
* (重点)
|
||||
* AsyncFuture 这个类就是票据, 刚拿到这个票据是没有信息的,当done == true 的时候,这个票据 上就自动有信息了
|
||||
* 这个结果类设计的比较神奇
|
||||
*/
|
||||
public class AsyncFuture<MQMessage> implements Future<MQMessage> {
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(AsyncFuture.class);
|
||||
|
||||
private volatile boolean done = false;
|
||||
private MQMessage oldRequest;
|
||||
private MQMessage result;
|
||||
|
||||
public AsyncFuture(MQMessage oldRequest) {
|
||||
this.oldRequest = oldRequest;
|
||||
}
|
||||
public AsyncFuture() {
|
||||
}
|
||||
|
||||
public void done(MQMessage result){
|
||||
synchronized (this){
|
||||
System.out.println("done");
|
||||
|
||||
this.result = result;
|
||||
this.done = true;
|
||||
//注意这里的notifyAll只能唤醒 本锁的所有 下的所有 wait(),这里的锁就是 AsyncFuture这个类
|
||||
notifyAll();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MQMessage get(Long timeout) throws Exception {
|
||||
synchronized (this){
|
||||
//其实有 synchronize就相当于有一个阻塞队列,当有线程执行了wait 方法,就会把执行wait的这个线程给加入wait<Thread> 队列,
|
||||
//当有线程执行notify方法的时候,就会往这个队列中取出一个或者多个Thread,取出来以后就能执行后续代码了
|
||||
System.out.println("get");
|
||||
|
||||
// 当线程执行wait()时,会把当前的锁释放,然后让出CPU,进入等待状态。 wait()会立刻释放synchronized(obj)中的obj锁,以便其他线程可以执行obj.notify()
|
||||
// * 当线程执行notify()/notifyAll()方法时,会唤醒一个处于等待状态该对象锁的线程,然后继续往下执行,直到执行完退出对象锁锁住的区域(synchronized修饰的代码块)后再释放锁
|
||||
this.wait(timeout);
|
||||
if(!done){
|
||||
logger.error("T3 timeout , request information: "+oldRequest.toString());
|
||||
throw new T3TimeoutException("T3 timeout , request information: "+oldRequest.toString());
|
||||
}
|
||||
|
||||
//因为上面的代码是加锁的,所以这里的代码也是加锁的。
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
14
src/main/java/com/qgs/dc/mq/secsgem/Future.java
Normal file
14
src/main/java/com/qgs/dc/mq/secsgem/Future.java
Normal file
@ -0,0 +1,14 @@
|
||||
package com.qgs.dc.mq.secsgem;
|
||||
|
||||
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
|
||||
/**
|
||||
* @Author: 蔡翔
|
||||
* @Date: 2019/11/6 13:49
|
||||
* @Version 1.0
|
||||
*/
|
||||
public interface Future<MQMessage> {
|
||||
//别人调用我的时候,我先给他们返回一个结果,
|
||||
MQMessage get(Long timeout) throws Exception;
|
||||
}
|
56
src/main/java/com/qgs/dc/mq/secsgem/Main.java
Normal file
56
src/main/java/com/qgs/dc/mq/secsgem/Main.java
Normal file
@ -0,0 +1,56 @@
|
||||
package com.qgs.dc.mq.secsgem;
|
||||
|
||||
|
||||
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
import com.qgs.dc.mq.entity.common.Header;
|
||||
import com.qgs.dc.mq.entity.common.Returns;
|
||||
import com.qgs.dc.mq.entity.specificBody.QueryEQStatusBody;
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/17 14:35
|
||||
*/
|
||||
public class Main {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
new Thread(()->{
|
||||
MQMessage mqMessage = new MQMessage();
|
||||
|
||||
Header header = new Header("Request","Execute","QUERYEQPStatus","12");
|
||||
QueryEQStatusBody queryEQStatusBody = new QueryEQStatusBody();
|
||||
queryEQStatusBody.setVidType("u4");
|
||||
List<String> vids = new ArrayList<>();
|
||||
vids.add("10000");
|
||||
vids.add("10001");
|
||||
vids.add("10002");
|
||||
queryEQStatusBody.setVidList(vids);
|
||||
mqMessage.setBody(JSONObject.toJSONBytes(queryEQStatusBody));
|
||||
mqMessage.setHeader(header);
|
||||
|
||||
AsyncFuture<MQMessage> add = SendedList.add(header.getTransactionId(),mqMessage);
|
||||
try {
|
||||
MQMessage mqMessageResponse = add.get(new Long(3000));
|
||||
System.out.println(mqMessageResponse.getReturns().getReturnCode());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
|
||||
Thread.sleep(1000);
|
||||
|
||||
new Thread(()->{
|
||||
MQMessage mqMessage = new MQMessage();
|
||||
mqMessage.setReturns(new Returns("233","2"));
|
||||
SendedList.set("11221",mqMessage);
|
||||
}).start();
|
||||
}
|
||||
}
|
42
src/main/java/com/qgs/dc/mq/secsgem/SendedList.java
Normal file
42
src/main/java/com/qgs/dc/mq/secsgem/SendedList.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.qgs.dc.mq.secsgem;
|
||||
|
||||
|
||||
|
||||
|
||||
import com.qgs.dc.mq.entity.MQMessage;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* @Desc: "MES端 发送远程指令列表"
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/17 14:14
|
||||
*/
|
||||
public class SendedList {
|
||||
private static HashMap<String, AsyncFuture<MQMessage>> list = new HashMap<>();
|
||||
|
||||
// public static synchronized AsyncFuture<MQMessage> get(String transitionId){
|
||||
// return list.get(transitionId);
|
||||
// }
|
||||
// public static synchronized void put(String transitionId,AsyncFuture<MQMessage> asyncFuture){
|
||||
// list.put(transitionId,asyncFuture);
|
||||
// }
|
||||
|
||||
public static synchronized AsyncFuture<MQMessage> add(String transitionId, MQMessage mqMessageRequest) {
|
||||
|
||||
AsyncFuture<MQMessage> objectAsyncFuture = new AsyncFuture<>(mqMessageRequest);
|
||||
list.put(transitionId,objectAsyncFuture);
|
||||
return objectAsyncFuture;
|
||||
}
|
||||
|
||||
public static synchronized Boolean set(String transitionId, MQMessage message) {
|
||||
AsyncFuture<MQMessage> mqMessageAsyncFuture = list.get(transitionId);
|
||||
if(mqMessageAsyncFuture == null){
|
||||
return false;
|
||||
}
|
||||
mqMessageAsyncFuture.done(message);
|
||||
//清除 ,防止这个hashMap过大。
|
||||
list.remove(transitionId);
|
||||
return true;
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package com.qgs.dc.opcua.Consumer;
|
||||
|
||||
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.Variant;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/18 14:32
|
||||
*/
|
||||
@Component
|
||||
public class EventReceivedCallBack implements UaMonitoredItem.EventConsumer,UaMonitoredItem.ValueConsumer {
|
||||
private static final Logger logger = LoggerFactory.getLogger(EventReceivedCallBack.class);
|
||||
|
||||
|
||||
@Override
|
||||
public void onEventArrived(UaMonitoredItem uaMonitoredItem, Variant[] variants) {
|
||||
logger.info("Server Event Received from {}", uaMonitoredItem.getReadValueId().getNodeId());
|
||||
//这里variants 就是 0,2253 这个事件的 变量
|
||||
for (int i = 0; i < variants.length; i++) {
|
||||
logger.info("\t variant[{}]: {}", i, variants[i].getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onValueArrived(UaMonitoredItem item, DataValue dataValue) {
|
||||
|
||||
}
|
||||
}
|
63
src/main/java/com/qgs/dc/opcua/arg/AddPLCArgEntity.java
Normal file
63
src/main/java/com/qgs/dc/opcua/arg/AddPLCArgEntity.java
Normal file
@ -0,0 +1,63 @@
|
||||
package com.qgs.dc.opcua.arg;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/30 11:05
|
||||
*/
|
||||
public class AddPLCArgEntity {
|
||||
private String plcName;
|
||||
private String urlConfig;
|
||||
private String policyConfig;
|
||||
private String userConfigs;
|
||||
private String ip;
|
||||
private Integer messageMode;
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
|
||||
public String getUrlConfig() {
|
||||
return urlConfig;
|
||||
}
|
||||
|
||||
public void setUrlConfig(String urlConfig) {
|
||||
this.urlConfig = urlConfig;
|
||||
}
|
||||
|
||||
public String getPolicyConfig() {
|
||||
return policyConfig;
|
||||
}
|
||||
|
||||
public void setPolicyConfig(String policyConfig) {
|
||||
this.policyConfig = policyConfig;
|
||||
}
|
||||
|
||||
public String getUserConfigs() {
|
||||
return userConfigs;
|
||||
}
|
||||
|
||||
public void setUserConfigs(String userConfigs) {
|
||||
this.userConfigs = userConfigs;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public Integer getMessageMode() {
|
||||
return messageMode;
|
||||
}
|
||||
|
||||
public void setMessageMode(Integer messageMode) {
|
||||
this.messageMode = messageMode;
|
||||
}
|
||||
}
|
39
src/main/java/com/qgs/dc/opcua/arg/BrowsArgEntity.java
Normal file
39
src/main/java/com/qgs/dc/opcua/arg/BrowsArgEntity.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.qgs.dc.opcua.arg;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/30 11:02
|
||||
*/
|
||||
public class BrowsArgEntity {
|
||||
private String plcName;
|
||||
//例子: ns=5;s=StaticVariables
|
||||
//rootNameSpace == ns
|
||||
private Integer rootNameSpace;
|
||||
//idenrifier == s
|
||||
private String idenrifier;
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
|
||||
public Integer getRootNameSpace() {
|
||||
return rootNameSpace;
|
||||
}
|
||||
|
||||
public void setRootNameSpace(Integer rootNameSpace) {
|
||||
this.rootNameSpace = rootNameSpace;
|
||||
}
|
||||
|
||||
public String getIdenrifier() {
|
||||
return idenrifier;
|
||||
}
|
||||
|
||||
public void setIdenrifier(String idenrifier) {
|
||||
this.idenrifier = idenrifier;
|
||||
}
|
||||
}
|
18
src/main/java/com/qgs/dc/opcua/arg/DelPlcArgEntity.java
Normal file
18
src/main/java/com/qgs/dc/opcua/arg/DelPlcArgEntity.java
Normal file
@ -0,0 +1,18 @@
|
||||
package com.qgs.dc.opcua.arg;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/19 15:49
|
||||
*/
|
||||
public class DelPlcArgEntity {
|
||||
private String plcName;
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
package com.qgs.dc.opcua.arg;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2021/8/20 9:52
|
||||
*/
|
||||
public class GetCurrentSubArgEntity {
|
||||
private String plcName;
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
36
src/main/java/com/qgs/dc/opcua/arg/ReadArgEntity.java
Normal file
36
src/main/java/com/qgs/dc/opcua/arg/ReadArgEntity.java
Normal file
@ -0,0 +1,36 @@
|
||||
package com.qgs.dc.opcua.arg;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/30 10:22
|
||||
*/
|
||||
public class ReadArgEntity {
|
||||
private Integer nameSpace;
|
||||
private String identifier;
|
||||
private String plcName;
|
||||
|
||||
public Integer getNameSpace() {
|
||||
return nameSpace;
|
||||
}
|
||||
|
||||
public void setNameSpace(Integer nameSpace) {
|
||||
this.nameSpace = nameSpace;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
54
src/main/java/com/qgs/dc/opcua/arg/WriteArgEntity.java
Normal file
54
src/main/java/com/qgs/dc/opcua/arg/WriteArgEntity.java
Normal file
@ -0,0 +1,54 @@
|
||||
package com.qgs.dc.opcua.arg;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/30 10:43
|
||||
*/
|
||||
public class WriteArgEntity {
|
||||
private Integer nameSpace;
|
||||
private String identifier;
|
||||
private String newValue;
|
||||
private String type;
|
||||
private String plcName;
|
||||
|
||||
public Integer getNameSpace() {
|
||||
return nameSpace;
|
||||
}
|
||||
|
||||
public void setNameSpace(Integer nameSpace) {
|
||||
this.nameSpace = nameSpace;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public String getNewValue() {
|
||||
return newValue;
|
||||
}
|
||||
|
||||
public void setNewValue(String newValue) {
|
||||
this.newValue = newValue;
|
||||
}
|
||||
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(String type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
80
src/main/java/com/qgs/dc/opcua/config/LocalMulPLCConfig.java
Normal file
80
src/main/java/com/qgs/dc/opcua/config/LocalMulPLCConfig.java
Normal file
@ -0,0 +1,80 @@
|
||||
package com.qgs.dc.opcua.config;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
import com.qgs.dc.opcua.constant.PLCConstant;
|
||||
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.HashMap;
|
||||
|
||||
|
||||
public class LocalMulPLCConfig {
|
||||
|
||||
//读取json文件
|
||||
public static String readJsonFile(String fileName) {
|
||||
String jsonStr = "";
|
||||
try {
|
||||
File jsonFile = new File(fileName);
|
||||
if (!jsonFile.exists()) {
|
||||
boolean b= jsonFile.createNewFile();
|
||||
JSONObject json = new JSONObject();
|
||||
json =JSON.parseObject("{\"config\": []}");
|
||||
FileWriter fw = new FileWriter(jsonFile.getAbsoluteFile());
|
||||
BufferedWriter bw = new BufferedWriter(fw);
|
||||
json.writeJSONString(bw);
|
||||
bw.close();
|
||||
}
|
||||
|
||||
FileReader fileReader = new FileReader(jsonFile);
|
||||
Reader reader = new InputStreamReader(new FileInputStream(jsonFile), StandardCharsets.UTF_8);
|
||||
int ch = 0;
|
||||
StringBuffer sb = new StringBuffer();
|
||||
while ((ch = reader.read()) != -1) {
|
||||
sb.append((char) ch);
|
||||
}
|
||||
fileReader.close();
|
||||
reader.close();
|
||||
jsonStr = sb.toString();
|
||||
return jsonStr;
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static HashMap<String,PLCConfig> getPLCConfig(){
|
||||
//String path = LocalMulPLCConfig.class.getClassLoader().getResource("mulPLCConfig.json").getPath();
|
||||
String s = "";
|
||||
if(CommonFunction.isLinux()){
|
||||
CommonFunction.createDirIfNotExit(PLCConstant.localURLDirForLinux);
|
||||
s = readJsonFile(PLCConstant.localURLForLinux);
|
||||
}else if(CommonFunction.isWindows()){
|
||||
CommonFunction.createDirIfNotExit(PLCConstant.localURLDirForWindows);
|
||||
s = readJsonFile(PLCConstant.localURLForWindows);
|
||||
}
|
||||
|
||||
JSONObject jobj = JSON.parseObject(s);
|
||||
|
||||
|
||||
|
||||
JSONArray movies = jobj.getJSONArray("config");//构建JSONArray数组
|
||||
|
||||
HashMap<String,PLCConfig> res = new HashMap<>();
|
||||
for (int i = 0 ; i < movies.size();i++){
|
||||
JSONObject key = (JSONObject)movies.get(i);
|
||||
String plcName = (String)key.get("plc_name");
|
||||
String url_config = (String)key.get("endpointUrl_config");
|
||||
String policy_config = (String)key.get("securityPolicy_config");
|
||||
String[] user_config =((String)key.get("identityProvider_config")).isEmpty()?null:((String)key.get("identityProvider_config")).split(",");
|
||||
String ip = (String)key.get("ip");
|
||||
Integer messageMode = (Integer)key.get("messageMode_config");
|
||||
res.put(plcName,new PLCConfig(plcName,url_config, SecurityPolicy.valueOf(policy_config),user_config,ip,messageMode));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
}
|
70
src/main/java/com/qgs/dc/opcua/config/PLCConfig.java
Normal file
70
src/main/java/com/qgs/dc/opcua/config/PLCConfig.java
Normal file
@ -0,0 +1,70 @@
|
||||
package com.qgs.dc.opcua.config;
|
||||
|
||||
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
|
||||
|
||||
public class PLCConfig {
|
||||
private String plcName;
|
||||
private String endpointUrlConfig;
|
||||
private SecurityPolicy securityPolicyConfig;
|
||||
private String[] identityProviderConfig;
|
||||
private String ip;
|
||||
//None Or SignAndEncrypt
|
||||
private Integer messageMode;
|
||||
|
||||
public PLCConfig(String plcName,String endpointUrlConfig, SecurityPolicy securityPolicyConfig, String[] identityProviderConfig,String ip,Integer messageMode) {
|
||||
this.plcName = plcName;
|
||||
this.endpointUrlConfig = endpointUrlConfig;
|
||||
this.securityPolicyConfig = securityPolicyConfig;
|
||||
this.identityProviderConfig = identityProviderConfig;
|
||||
this.ip = ip;
|
||||
this.messageMode = messageMode;
|
||||
}
|
||||
|
||||
public Integer getMessageMode() {
|
||||
return messageMode;
|
||||
}
|
||||
|
||||
public void setMessageMode(Integer messageMode) {
|
||||
this.messageMode = messageMode;
|
||||
}
|
||||
|
||||
public String getIp() {
|
||||
return ip;
|
||||
}
|
||||
|
||||
public void setIp(String ip) {
|
||||
this.ip = ip;
|
||||
}
|
||||
|
||||
public String getEndpointUrlConfig() {
|
||||
return endpointUrlConfig;
|
||||
}
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
|
||||
public void setEndpointUrlConfig(String endpointUrlConfig) {
|
||||
this.endpointUrlConfig = endpointUrlConfig;
|
||||
}
|
||||
|
||||
public SecurityPolicy getSecurityPolicyConfig() {
|
||||
return securityPolicyConfig;
|
||||
}
|
||||
|
||||
public void setSecurityPolicyConfig(SecurityPolicy securityPolicyConfig) {
|
||||
this.securityPolicyConfig = securityPolicyConfig;
|
||||
}
|
||||
|
||||
public String[] getIdentityProviderConfig() {
|
||||
return identityProviderConfig;
|
||||
}
|
||||
|
||||
public void setIdentityProviderConfig(String[] identityProviderConfig) {
|
||||
this.identityProviderConfig = identityProviderConfig;
|
||||
}
|
||||
}
|
38
src/main/java/com/qgs/dc/opcua/constant/PLCConstant.java
Normal file
38
src/main/java/com/qgs/dc/opcua/constant/PLCConstant.java
Normal file
@ -0,0 +1,38 @@
|
||||
package com.qgs.dc.opcua.constant;
|
||||
|
||||
public class PLCConstant {
|
||||
//配置多PLC 的 配置文件 ( 注意如果要在 新服务器上部署 没有文件结构要配置文件结构)
|
||||
public static final String localURLForWindows = "C:\\code\\study\\mulPLC\\mulPLCConfig.json";
|
||||
public static final String localURLDirForWindows = "C:\\code\\study\\mulPLC";
|
||||
public static final String localURLForLinux = "/usr/local/security/mulPLCConfig.json";
|
||||
public static final String localURLDirForLinux = "/usr/local/security";
|
||||
|
||||
|
||||
//连接OPC 的授权文件。
|
||||
public static final String securityURLForWindows = "C:\\code\\study\\mulPLC\\security";
|
||||
public static final String securityURLForLinux = "/usr/local/security";
|
||||
|
||||
|
||||
//常用线程
|
||||
public static Thread displayThread = new Thread();
|
||||
|
||||
|
||||
//错误常量
|
||||
|
||||
//opc server 未授权证书
|
||||
public static final String SECURITY_CHECKS_FAILED = "Bad_SecurityChecksFailed";
|
||||
//Bad_Timeout 是指断网了(或者是网络波荡太久) 然后造成 连接超时
|
||||
public static final String TIMEOUT = "Bad_Timeout";
|
||||
//Bad_ConnectionRejected 是指opc server 宕机了
|
||||
public static final String CONNECTION_REJECTED = "Bad_ConnectionRejected";
|
||||
// 无session 原因:是你部署 程序的的服务器上没有配置 opc-server 的host 要加192.168.0.228 WIN-92SDA5G5VE8
|
||||
public static final String SESSION_CLOSED = "Bad_SessionClosed";
|
||||
|
||||
|
||||
//订阅
|
||||
public static final Integer Subscription_Visited = 1;
|
||||
public static final Integer Subscription_Function_Var = 2;
|
||||
public static final Integer Subscription_Function_Event = 3;
|
||||
|
||||
|
||||
}
|
25
src/main/java/com/qgs/dc/opcua/constant/PLCTypeConstant.java
Normal file
25
src/main/java/com/qgs/dc/opcua/constant/PLCTypeConstant.java
Normal file
@ -0,0 +1,25 @@
|
||||
package com.qgs.dc.opcua.constant;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/22 11:31
|
||||
*/
|
||||
public class PLCTypeConstant {
|
||||
public static final String QUByte = "QUByte";
|
||||
public static final String QUInteger = "QUInteger";
|
||||
public static final String QUShort = "QUShort";
|
||||
public static final String QULong = "QULong";
|
||||
public static final String QBoolean = "QBoolean";
|
||||
public static final String QString = "QString";
|
||||
public static final String QDouble = "QDouble";
|
||||
public static final String QFloat = "QFloat";
|
||||
public static final String QLong = "QLong";
|
||||
public static final String QInteger = "QInteger";
|
||||
public static final String QShort = "QShort";
|
||||
public static final String QArray = "QArray";
|
||||
public static final String QByte = "QByte";
|
||||
public static final String QByteString = "QByteString";
|
||||
|
||||
|
||||
}
|
405
src/main/java/com/qgs/dc/opcua/controller/OperateController.java
Normal file
405
src/main/java/com/qgs/dc/opcua/controller/OperateController.java
Normal file
@ -0,0 +1,405 @@
|
||||
package com.qgs.dc.opcua.controller;
|
||||
|
||||
import com.qgs.dc.opcua.Consumer.EventReceivedCallBack;
|
||||
import com.qgs.dc.opcua.arg.*;
|
||||
import com.qgs.dc.common.utils.CommonFunction;
|
||||
import com.qgs.dc.opcua.constant.PLCConstant;
|
||||
import com.qgs.dc.opcua.selfunion.Enum.PLCType;
|
||||
import com.qgs.dc.opcua.selfunion.NodeIdKey;
|
||||
import com.qgs.dc.opcua.selfunion.UAService;
|
||||
import com.qgs.dc.opcua.selfunion.entity.CurrentSubEntity;
|
||||
import com.qgs.dc.opcua.selfunion.entity.DelSubscribeEntity;
|
||||
import com.qgs.dc.opcua.selfunion.entity.SubscribeEventArgEntity;
|
||||
import com.qgs.dc.opcua.selfunion.entity.SubscribeVarArgEntity;
|
||||
import com.qgs.dc.common.websocket.WebSocketServer;
|
||||
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaMonitoredItem;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.DataValue;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.NodeId;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UShort;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/opcua")
|
||||
public class OperateController {
|
||||
private static final Logger logger = LoggerFactory.getLogger(OperateController.class);
|
||||
|
||||
//todo controller 需要仔细编写,,重点关注 那些报错异常(断网、opc-server宕机)
|
||||
@Autowired
|
||||
UAService uaService;
|
||||
|
||||
@Autowired
|
||||
WebSocketServer webSocketServer;
|
||||
|
||||
@PostMapping("/addThisPlc")
|
||||
/**
|
||||
* @Description
|
||||
* @Param [
|
||||
* plcName, plc3
|
||||
* urlConfig, opc.tcp://WIN-92SDA5G5VE8:55101 //换成ip就行,如果这样要配置域名解析
|
||||
* policyConfig, None //None,Basic256,Basic128Rsa15
|
||||
* userConfigs, "" //如果无账号密码填空,如果有 账号密码逗号隔开 如 CXCX,123456789
|
||||
* ip, WIN-92SDA5G5VE8
|
||||
* messageMode 1 //None(1),Sign(2),SignAndEncrypt(3);
|
||||
* ]
|
||||
* @Return com.qgs.dc.opcua.opcuamilnow.controller.R
|
||||
* @Author caixiang
|
||||
* @Date 2020/7/28 11:15
|
||||
**/
|
||||
public R addThisPlc(@RequestBody AddPLCArgEntity addPLCArgEntity){
|
||||
try {
|
||||
Integer integer = uaService.dynamicAddPlc(addPLCArgEntity.getPlcName(), addPLCArgEntity.getUrlConfig(), addPLCArgEntity.getPolicyConfig(),addPLCArgEntity.getUserConfigs() , addPLCArgEntity.getIp(),addPLCArgEntity.getMessageMode());
|
||||
return R.ok().put("result",integer);
|
||||
}catch (Exception e){
|
||||
String s = uaService.extractError(e.getMessage());
|
||||
s = s+";详细:"+e.getMessage();
|
||||
return R.error().put("result",s);
|
||||
}
|
||||
}
|
||||
|
||||
public void unlinkSubscribeWhenRemovePlc(String plcName) throws Exception {
|
||||
//并且把 这个plc 已订阅的 变量 给删除 -- 开始
|
||||
List<CurrentSubEntity> currentSubscribeVarForVisited = uaService.getCurrentSubscribeVarForVisited(plcName);
|
||||
List<Integer> ns = new ArrayList<>();
|
||||
List<String> iden = new ArrayList<>();
|
||||
for(CurrentSubEntity currentSubEntity:currentSubscribeVarForVisited){
|
||||
ns.add(currentSubEntity.getNameSpace());
|
||||
iden.add(currentSubEntity.getIdentifier());
|
||||
}
|
||||
uaService.deSubscribeForVisit(ns, iden, plcName);
|
||||
//并且把 这个plc 已订阅的 变量 给删除 -- 结束
|
||||
}
|
||||
|
||||
@DeleteMapping("/removeThisPlc")
|
||||
public R removeThisPlc(@RequestBody DelPlcArgEntity delPlcArgEntity){
|
||||
//return R.ok().put("status",uaService.dynamicRemovePlc(plcName));
|
||||
try {
|
||||
Integer integer = uaService.dynamicRemovePlc(delPlcArgEntity.getPlcName());
|
||||
|
||||
unlinkSubscribeWhenRemovePlc(delPlcArgEntity.getPlcName());
|
||||
if(integer == null){
|
||||
return R.error().put("result",delPlcArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
return R.ok().put("result",integer);
|
||||
}catch (Exception e){
|
||||
String s = uaService.extractError(e.getMessage());
|
||||
return R.error().put("result",s);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/getBrows")
|
||||
public R getBrows(@RequestBody BrowsArgEntity browsArgEntity){
|
||||
NodeIdKey nodeIdKey = uaService.browseA(browsArgEntity.getPlcName(), browsArgEntity.getRootNameSpace(), browsArgEntity.getIdenrifier());
|
||||
if(nodeIdKey == null){
|
||||
return R.error().put("result",browsArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
return R.ok().put("result",nodeIdKey);
|
||||
}
|
||||
|
||||
//如果是数组类型 的那么 newValue 就是 一个字符串 并且用 逗号隔开,后面跟着 数据类型 如 "1,2,4|QUByte"
|
||||
/**
|
||||
* 参数
|
||||
* {
|
||||
* "nameSpace": 6,
|
||||
* "identifier": "S7-1200 station_1.PLC_1.TestDB80.Array[0..7] of DInt1",
|
||||
* "newValue": "1,2,3,4,5,6,7,8#QInteger",
|
||||
* "type": "QArray",
|
||||
* "plcName": "plc1"
|
||||
* }
|
||||
*
|
||||
* */
|
||||
@PostMapping("/write")
|
||||
//public R write(Integer nameSpace,String identifier,String newValue,String type,String plcName){
|
||||
public R write(@RequestBody WriteArgEntity writeArgEntity){
|
||||
try {
|
||||
//PLCType.valueOf(type).convertType(newValue); 意思是 把newValue 这个数据转成type 类型的变量
|
||||
Object var = PLCType.valueOf(writeArgEntity.getType()).convertType(writeArgEntity.getNewValue());
|
||||
Boolean aBoolean = uaService.setValue(writeArgEntity.getNameSpace(), writeArgEntity.getIdentifier(), var, writeArgEntity.getPlcName());
|
||||
if(aBoolean == null){
|
||||
return R.error().put("result",writeArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}else if(aBoolean){
|
||||
return R.ok();
|
||||
}else {
|
||||
return R.error();
|
||||
}
|
||||
}catch (Exception e){
|
||||
return R.error().put("result", e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/read")
|
||||
//public R read(Integer nameSpace,String identifier,String plcName) {
|
||||
public R read(@RequestBody ReadArgEntity readArgEntity) {
|
||||
try {
|
||||
DataValue dv = uaService.getValue(readArgEntity.getNameSpace(), readArgEntity.getIdentifier(), readArgEntity.getPlcName());
|
||||
if(dv == null){
|
||||
return R.error().put("result",readArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
Object value = dv.getValue().getValue();
|
||||
System.out.println(CommonFunction.judgeVarType(value));
|
||||
return R.ok().put("result", CommonFunction.var(value));
|
||||
}catch (Exception e){
|
||||
return R.error().put("result", e.getMessage());
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//todo 1.订阅变量数组...(并且把数据类型返还给前端)
|
||||
/**
|
||||
* 含义 : 可以同时订阅:变量、数组 ( 注意这个是功能型订阅 )
|
||||
* 参数 : SubscribeArgEntity
|
||||
* listNameSpace List<Integer>
|
||||
* listIdentifier List<String>
|
||||
* plcName String
|
||||
* 注意 : ns 和 identify 必须位置上相互对应,,判断是否数组依据就是看几组数据
|
||||
* 返回:
|
||||
* 这边是通过websocket 返回的 是一个字符串
|
||||
* 第一组 是变量名
|
||||
* 第二组 是变量值
|
||||
* 第三组 是变量值 的类型(如果是数组 那就是QArray)
|
||||
* 第四组 是变量值 的类型(如果是数组 那这组就存在,代表数组里面变量的数据类型)
|
||||
* 3,Byte|8,7,7,7,8|QArray|QShort
|
||||
* 3,Byte|0|QUByte
|
||||
* */
|
||||
@PostMapping("subscribeVarForFunction")
|
||||
public R subscribeVarForFunction(@RequestBody SubscribeVarArgEntity subscribeVarArgEntity) throws Exception {
|
||||
|
||||
Integer integer = uaService.subscribeValues(subscribeVarArgEntity.getListNameSpace(), subscribeVarArgEntity.getListIdentifier(), new Double(1000),
|
||||
(item, dataValue) -> {
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
"" + item.getReadValueId().getNodeId() + ", value :" + dataValue.getValue());
|
||||
System.out.println();
|
||||
NodeId currentNode = item.getReadValueId().getNodeId();
|
||||
UShort namespaceIndex = currentNode.getNamespaceIndex();
|
||||
Object identifier = currentNode.getIdentifier();
|
||||
|
||||
Object value = dataValue.getValue().getValue();
|
||||
String varType = CommonFunction.judgeVarType(value);
|
||||
|
||||
String res = namespaceIndex + "," + identifier + "|" + CommonFunction.var2String(value) + "|" + varType+ "|" +subscribeVarArgEntity.getPlcName();
|
||||
|
||||
try {
|
||||
webSocketServer.sendtoAll(res);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, subscribeVarArgEntity.getPlcName(),PLCConstant.Subscription_Function_Var);
|
||||
|
||||
if(integer == null){
|
||||
return R.error().put("result",subscribeVarArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
/**
|
||||
* 含义 : 订阅变量,界面展示用用
|
||||
* 参数 : SubscribeArgEntity
|
||||
* listNameSpace List<Integer>
|
||||
* listIdentifier List<String>
|
||||
* plcName String
|
||||
* 注意 : ns 和 identify 必须位置上相互对应,,判断是否数组依据就是看几组数据
|
||||
* 返回:
|
||||
* 1 <===> 你要订阅的这个Node 订阅成功(包括这个变量已存在 然后你再次去订阅)
|
||||
* -1 <===> 你要订阅的这个Node 订阅失败
|
||||
* 2 <===> 你要订阅的这个Node 已订阅,请勿重复订阅
|
||||
* websocket 传递格式:
|
||||
* 这边是通过websocket 返回的 是一个字符串
|
||||
* 第一组 是变量名
|
||||
* 第二组 是变量值
|
||||
* 第三组 是变量值 的类型(如果是数组 那就是QArray)
|
||||
* 第四组 是变量值 的类型(如果是数组 那这组就存在,代表数组里面变量的数据类型)
|
||||
* 第五组 是这个变量所属 的plc,,是哪个plc
|
||||
* 3,Byte|8,7,7,7,8|QArray|QShort|plcName
|
||||
* 3,Byte|0|QUByte|plcName
|
||||
* */
|
||||
@PostMapping("subscribeVarForVisit")
|
||||
public R subscribeVarForVisit(@RequestBody SubscribeVarArgEntity subscribeVarArgEntity){
|
||||
|
||||
try {
|
||||
Integer integer = uaService.subscribeForVisit(subscribeVarArgEntity.getListNameSpace(), subscribeVarArgEntity.getListIdentifier(), new Double(1000), (item, dataValue) -> {
|
||||
UInteger attributeId = item.getReadValueId().getAttributeId();
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
"" + item.getReadValueId().getNodeId() + ", value :" + dataValue.getValue()+",attributeId:"+attributeId);
|
||||
|
||||
NodeId currentNode = item.getReadValueId().getNodeId();
|
||||
UShort namespaceIndex = currentNode.getNamespaceIndex();
|
||||
Object identifier = currentNode.getIdentifier();
|
||||
Object value = dataValue.getValue().getValue();
|
||||
String varType = CommonFunction.judgeVarType(value);
|
||||
|
||||
String res = namespaceIndex + "," + identifier + "|" + CommonFunction.var2String(value) + "|" + varType+ "|" +subscribeVarArgEntity.getPlcName();
|
||||
|
||||
try {
|
||||
webSocketServer.sendtoAll(res);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}, subscribeVarArgEntity.getPlcName());
|
||||
if(integer == null){
|
||||
return R.error().put("result",subscribeVarArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
|
||||
if(integer == 1){
|
||||
return R.ok().put("result","成功");
|
||||
}else if(integer == 2) {
|
||||
return R.error().put("result","你要订阅的这个Node 已订阅,请勿重复订阅");
|
||||
}else {
|
||||
return R.error().put("result","你要订阅的这个Node 订阅失败");
|
||||
}
|
||||
}catch (Exception e){
|
||||
return R.error().put("result",e.getMessage());
|
||||
}
|
||||
}
|
||||
/**
|
||||
* 含义 : 订阅一个或者多个事件
|
||||
* 参数 : SubscribeArgEntity
|
||||
* listNameSpace List<Integer>
|
||||
* listIdentifier List<String>
|
||||
* plcName String
|
||||
* 注意 : ns 和 identify 必须位置上相互对应,,判断是否数组依据就是看几组数据
|
||||
* 返回:
|
||||
* 把事件触发 时候的一些数据 拿过来(通过过滤器过滤过来) 然后传给前端。
|
||||
* status: 暂停(等待事件 验证好了之后 再做这些)
|
||||
* */
|
||||
@PostMapping("subscribeEventsForFunction")
|
||||
public R subscribeEventsForFunction(@RequestBody SubscribeEventArgEntity subscribeVarArgEntity) throws Exception {
|
||||
if(subscribeVarArgEntity.getListNameSpace().size()!=subscribeVarArgEntity.getListIdentifier().size()){
|
||||
return R.error("传入参数不正确");
|
||||
}
|
||||
List<UaMonitoredItem.EventConsumer> list = new ArrayList<>();
|
||||
int size = subscribeVarArgEntity.getListNameSpace().size();
|
||||
UaMonitoredItem.EventConsumer a1 =((uaMonitoredItem, variants) -> {
|
||||
logger.info("Server Event Received from {}", uaMonitoredItem.getReadValueId().getNodeId());
|
||||
//这里variants 就是 0,2253 这个事件的 变量
|
||||
for (int i = 0; i < variants.length; i++) {
|
||||
logger.info("\t variant[{}]: {}", i, variants[i].getValue());
|
||||
}
|
||||
});
|
||||
UaMonitoredItem.EventConsumer a2 =((uaMonitoredItem, variants) -> {
|
||||
logger.info("myDevice Event Received from {}", uaMonitoredItem.getReadValueId().getNodeId());
|
||||
//这里variants 就是 0,2253 这个事件的 变量
|
||||
for (int i = 0; i < variants.length; i++) {
|
||||
logger.info("\t variant[{}]: {}", i, variants[i].getValue());
|
||||
}
|
||||
});
|
||||
UaMonitoredItem.EventConsumer a3 = new EventReceivedCallBack();
|
||||
|
||||
for(int i=0;i<size;i++){
|
||||
list.add(a3);
|
||||
}
|
||||
Integer plc1 = uaService.subscribeEvents(subscribeVarArgEntity.getPlcName(), subscribeVarArgEntity.getListNameSpace(), subscribeVarArgEntity.getListIdentifier(),list);
|
||||
if(plc1 == null){
|
||||
return R.error().put("result",subscribeVarArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
return R.ok().put("result",plc1);
|
||||
}
|
||||
|
||||
/* *
|
||||
* 原因:订阅包含一个寿命计数器,保存了在没有发布请求时经历的循环次数,当达到阈值时,会删除这个订阅以及与订阅相关的监控项。在删除订阅时,会发送一条StateChangeNotification消息,并携带状态码Bad_Timeout
|
||||
* */
|
||||
|
||||
|
||||
/**
|
||||
* 含义:删除 某个订阅分类下 的 某个Node 或者 List<Node>(包括事件 和变量 )
|
||||
* 参数:
|
||||
* 1.plcName
|
||||
* 2.你要取消订阅 事件的 nameSpace 和 identifier
|
||||
* 3.可以选择你要过滤的条件(现在暂时无,,后续可以补充)
|
||||
* 4.设置回调函数(就是当有订阅 的事件发生的时候 就调用的函数 )
|
||||
* 5.注意type 是 你要删除的订阅是在哪个(1 == 代表 展示型订阅;;2 == 代表 功能型(变量) 订阅;;3 == 代表 功能型(事件) 订阅)
|
||||
* 返回:Integer
|
||||
* 1 <===> 代表 删除订阅的事件 成功
|
||||
* -2 <===> 代表 你要删除的订阅事件 不存在
|
||||
* -1 <===> 代表 删除订阅失败/参数错误
|
||||
* 如果有异常就直接抛出异常
|
||||
* null 代表选中的plc异常
|
||||
*
|
||||
* 注意:如果之前订阅是 批量订阅的额(也就是个List),在delSubscribe的时候可以分开取消订阅。
|
||||
*
|
||||
* */
|
||||
@PostMapping("delSubscribe")
|
||||
public R delSubscribe(@RequestBody DelSubscribeEntity delSubscribeEntity) throws Exception {
|
||||
Integer integer = uaService.deleteSubscribe(delSubscribeEntity.getPlcName(), delSubscribeEntity.getListNameSpace(), delSubscribeEntity.getListIdentifier(),delSubscribeEntity.getType());
|
||||
if(integer == null){
|
||||
return R.error().put("result",delSubscribeEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
return R.ok().put("result",integer);
|
||||
}
|
||||
|
||||
/**
|
||||
* 含义:删除某个已订阅的变量
|
||||
* 注意:
|
||||
* 1.
|
||||
* 参数:
|
||||
* 回调函数BiConsumer<UaMonitoredItem, DataValue>,是当你订阅的这个变量当变量发生 改变的时候 你执行的方法(刚开始 会执行一次)
|
||||
* 返回值:
|
||||
* 1 <===> 你要 取消订阅的这个Node 成功(包括这个变量已存在 然后你再次去订阅)
|
||||
* -1 <===> 你要 取消订阅的这个Node 失败
|
||||
* 2 <===> 你要 取消订阅的这个Node 不存在
|
||||
* 有异常直接抛出
|
||||
* null 代表选中的plc不存在
|
||||
*
|
||||
* tip:Subscription有两种模式,一种是Reporting,另一种是Sampling。
|
||||
* 如果定义为Sampling,则这个Subscription是一个Triggered Item,即被激发的订阅,需要一个定义为Reporting的Subscription(称为Triggering Item)
|
||||
* 与它连接。这样当Triggering Item更新时,会激发Triggered Item更新。
|
||||
*
|
||||
* */
|
||||
@PostMapping("deSubscribeVarForVisit")
|
||||
public R deSubscribeVarForVisit(@RequestBody SubscribeVarArgEntity subscribeVarArgEntity) {
|
||||
|
||||
try {
|
||||
Integer integer = uaService.deSubscribeForVisit(subscribeVarArgEntity.getListNameSpace() , subscribeVarArgEntity.getListIdentifier() , subscribeVarArgEntity.getPlcName());
|
||||
if(integer == null){
|
||||
return R.error().put("result",subscribeVarArgEntity.getPlcName()+" 这台plc不存在 / 或参数异常");
|
||||
}
|
||||
if(integer == 1){
|
||||
return R.ok().put("result","成功");
|
||||
}else if(integer == 2) {
|
||||
return R.error().put("result","取消订阅的这个Node 不存在");
|
||||
}else {
|
||||
return R.error().put("result","取消订阅的这个Node 失败");
|
||||
}
|
||||
}catch (Exception e){
|
||||
return R.error().put("result",e.getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@PostMapping("getCurrentSubscribeVarForVisited")
|
||||
public R getCurrentSubscribeVarForVisited(@RequestBody GetCurrentSubArgEntity currentSubArgEntity) {
|
||||
//todo 测试
|
||||
try {
|
||||
List<CurrentSubEntity> currentSubscribeVarForVisited = uaService.getCurrentSubscribeVarForVisited(currentSubArgEntity.getPlcName());
|
||||
if(currentSubscribeVarForVisited == null){
|
||||
return R.error().put("result",currentSubArgEntity.getPlcName()+"这台plc不存在 或是 订阅不存在");
|
||||
}
|
||||
return R.ok().put("result",currentSubscribeVarForVisited);
|
||||
}catch (Exception e){
|
||||
return R.ok().put("result",e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("getUniqueWebSocketId")
|
||||
public R getUniqueWebSocketId() throws Exception {
|
||||
String uniqeId = webSocketServer.getUniqeId();
|
||||
return R.ok().put("result",uniqeId);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("getConnectedPLC")
|
||||
public R getConnectedPLC() {
|
||||
return R.ok().put("result",uaService.getConnectedPLC());
|
||||
}
|
||||
|
||||
}
|
66
src/main/java/com/qgs/dc/opcua/controller/R.java
Normal file
66
src/main/java/com/qgs/dc/opcua/controller/R.java
Normal file
@ -0,0 +1,66 @@
|
||||
/**
|
||||
* Copyright (c) 2016-2019 人人开源 All rights reserved.
|
||||
*
|
||||
* https://www.renren.io
|
||||
*
|
||||
* 版权所有,侵权必究!
|
||||
*/
|
||||
|
||||
package com.qgs.dc.opcua.controller;
|
||||
|
||||
|
||||
import org.springframework.http.HttpStatus;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 返回数据
|
||||
*
|
||||
* @author Mark sunlightcs@gmail.com
|
||||
*/
|
||||
public class R extends HashMap<String, Object> {
|
||||
private static final long serialVersionUID = 1L;
|
||||
//默认成功 是1
|
||||
public R() {
|
||||
put("code", 1);
|
||||
put("msg", "success");
|
||||
}
|
||||
|
||||
public static R error() {
|
||||
return error(HttpStatus.INTERNAL_SERVER_ERROR.value(), "未知异常,请联系管理员");
|
||||
}
|
||||
|
||||
public static R error(String msg) {
|
||||
return error(HttpStatus.INTERNAL_SERVER_ERROR.value(), msg);
|
||||
}
|
||||
|
||||
public static R error(int code, String msg) {
|
||||
R r = new R();
|
||||
r.put("code", code);
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok(String msg) {
|
||||
R r = new R();
|
||||
r.put("msg", msg);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok(Map<String, Object> map) {
|
||||
R r = new R();
|
||||
r.putAll(map);
|
||||
return r;
|
||||
}
|
||||
|
||||
public static R ok() {
|
||||
return new R();
|
||||
}
|
||||
|
||||
@Override
|
||||
public R put(String key, Object value) {
|
||||
super.put(key, value);
|
||||
return this;
|
||||
}
|
||||
}
|
647
src/main/java/com/qgs/dc/opcua/controller/WmcController.java
Normal file
647
src/main/java/com/qgs/dc/opcua/controller/WmcController.java
Normal file
@ -0,0 +1,647 @@
|
||||
package com.qgs.dc.opcua.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* @Author: 蔡翔
|
||||
* @Date: 2019/10/12 15:15
|
||||
* @Version 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/testPLC1")
|
||||
public class WmcController {
|
||||
/*
|
||||
|
||||
|
||||
private static final Logger logger = LoggerFactory.getLogger(WmcController.class);
|
||||
@Autowired
|
||||
UAService uaService;
|
||||
|
||||
@Autowired
|
||||
WebSocketServer webSocketServer;
|
||||
|
||||
*/
|
||||
/**
|
||||
* 测试real 类型(get / set)
|
||||
**//*
|
||||
|
||||
@PostMapping("/noRR")
|
||||
public R noRr() throws Exception {
|
||||
return R.ok().put("OK",123);
|
||||
}
|
||||
|
||||
@GetMapping("/norr")
|
||||
public R removeThisPlc() throws Exception {
|
||||
uaService.dynamicRemovePlc("plc1");
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("testWriteOneVar")
|
||||
public R testWriteOneVar(Integer a) throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
Boolean aBoolean = null;
|
||||
try {
|
||||
aBoolean = uaService.setValue(PLCVar.INT32_3, a,"plc1");
|
||||
}catch (Exception e){
|
||||
String[] errMsgs = e.getMessage().split(",");
|
||||
for(String i : errMsgs){
|
||||
System.out.println("i = 》 " + i);
|
||||
}
|
||||
System.err.println("err msg: "+uaService.extractError(e.getMessage()));
|
||||
}
|
||||
|
||||
return R.ok().put("result",aBoolean);
|
||||
}
|
||||
@GetMapping("testWriteOneVarForByte")
|
||||
public R testWriteOneVarForByte(Integer a) throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
Boolean aBoolean = null;
|
||||
try {
|
||||
aBoolean = uaService.setValue(PLCVar.BYTE_3, Unsigned.ubyte(a),"plc1");
|
||||
}catch (Exception e){
|
||||
String[] errMsgs = e.getMessage().split(",");
|
||||
for(String i : errMsgs){
|
||||
System.out.println("i = 》 " + i);
|
||||
}
|
||||
System.err.println("err msg: "+uaService.extractError(e.getMessage()));
|
||||
}
|
||||
|
||||
return R.ok().put("result",aBoolean);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("testHistoryRead")
|
||||
public R testHistoryRead() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
DateTime start = new DateTime(new Date(System.currentTimeMillis()+10000));
|
||||
DateTime end = new DateTime(new Date());
|
||||
|
||||
DateTime start1 = DateTime.MIN_VALUE;
|
||||
DateTime end1 = DateTime.now();
|
||||
|
||||
List<DataValue> aBoolean = uaService.historyRead("plc1",start,end,5,"Counter1");
|
||||
return R.ok().put("result",aBoolean);
|
||||
}
|
||||
|
||||
@GetMapping("testReadStringArray")
|
||||
public R testReadStringArray() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
DataValue aBoolean = uaService.getValue(PLCVar.StringArray_3,"plc1");
|
||||
List<String> s = (List<String>)aBoolean.getValue().getValue();
|
||||
return R.ok().put("result",aBoolean.getValue().getValue());
|
||||
}
|
||||
|
||||
@GetMapping("testReadBooleanArray")
|
||||
public R testReadBooleanArray() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
DataValue aBoolean = null;
|
||||
try {
|
||||
aBoolean = uaService.getValue(PLCVar.BooleanArray_3,"plc1");
|
||||
}catch (Exception e){
|
||||
String[] errMsgs = e.getMessage().split(",");
|
||||
for(String i : errMsgs){
|
||||
System.out.println("i = 》 " + i);
|
||||
}
|
||||
|
||||
System.err.println("err msg: "+uaService.extractError(e.getMessage()));
|
||||
if("Bad_ConnectionRejected".equals(uaService.extractError(e.getMessage()))){
|
||||
System.err.println("OPC SERVER 已经宕机 请确认开启");
|
||||
}
|
||||
}
|
||||
System.out.println(aBoolean.getValue().getValue().getClass().isArray());
|
||||
return R.ok().put("result",aBoolean.getValue().getValue());
|
||||
}
|
||||
|
||||
@GetMapping("testWriteTwoVar")
|
||||
public R testWriteTwoVar(Boolean b,Integer a) throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
List<PLCVar> list = new ArrayList<>();
|
||||
list.add(PLCVar.INT32_3);
|
||||
list.add(PLCVar.Boolean_3);
|
||||
|
||||
List<Object> value = new ArrayList<>();
|
||||
value.add(a);
|
||||
value.add(b);
|
||||
|
||||
Boolean aBoolean = uaService.setValues(list, value,"plc1");
|
||||
return R.ok().put("result",aBoolean);
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("getUniqueId")
|
||||
public R getUniqueId(){
|
||||
return R.ok(webSocketServer.getUniqeId());
|
||||
}
|
||||
|
||||
@GetMapping("testReadOneVar")
|
||||
public R testReadOneVar() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
DataValue dataValue = uaService.getValue(PLCVar.INT32_3,"plc1");
|
||||
return R.ok().put("result",dataValue.getValue().getValue());
|
||||
}
|
||||
|
||||
@GetMapping("testReadTwoVar")
|
||||
public R testReadTwoVar() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
List<PLCVar> list = new ArrayList<>();
|
||||
list.add(PLCVar.Boolean_3);
|
||||
list.add(PLCVar.INT32_3);
|
||||
|
||||
List<DataValue> values = uaService.getValues(list ,"plc1");
|
||||
List<Object> res = new ArrayList<>();
|
||||
for(DataValue dv:values){
|
||||
res.add(dv.getValue().getValue());
|
||||
}
|
||||
return R.ok().put("result",res);
|
||||
}
|
||||
|
||||
@GetMapping("subscribeInt32")
|
||||
public R subscribeInt32() throws Exception {
|
||||
//只要这个线程还在执行 就会一直未true。
|
||||
boolean alive = PLCConstant.displayThread.isAlive();
|
||||
|
||||
uaService.subscribe(PLCVar.INT32_3,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
|
||||
Object value = dataValue.getValue().getValue();
|
||||
try {
|
||||
webSocketServer.sendtoAll(value.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(value.equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc2",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeByte")
|
||||
public R subscribeByte() throws Exception {
|
||||
//只要这个线程还在执行 就会一直未true。
|
||||
boolean alive = PLCConstant.displayThread.isAlive();
|
||||
|
||||
uaService.subscribe(PLCVar.BYTE_3,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
|
||||
Object value = dataValue.getValue().getValue();
|
||||
//CommonFunction.judgeVarType(value);
|
||||
//System.out.println(integer);
|
||||
|
||||
try {
|
||||
webSocketServer.sendtoAll(value.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(value.equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc1",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("suspendSubscribeInt32")
|
||||
public R suspendSubscribeInt32() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
List<Integer> namespace = new ArrayList<>();
|
||||
namespace.add(3);
|
||||
List<Object> identify = new ArrayList<>();
|
||||
identify.add("Int32");
|
||||
return R.ok().put("result",uaService.suspendSubscribe("plc2",namespace,identify));
|
||||
}
|
||||
|
||||
@GetMapping("delSubscribeInt32")
|
||||
public R delSubscribeInt32() throws Exception {
|
||||
//只要这个线程还在执行 就会一直未true。
|
||||
boolean alive = PLCConstant.displayThread.isAlive();
|
||||
List<Integer> ns = new ArrayList<>();
|
||||
ns.add(PLCVar.INT32_3.getNameSpace());
|
||||
|
||||
List<Object> id = new ArrayList<>();
|
||||
id.add(PLCVar.INT32_3.getIdentifier());
|
||||
uaService.deleteSubscribe("plc2",ns,id);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeCounter1")
|
||||
public R subscribeCounter1() throws Exception {
|
||||
|
||||
uaService.subscribe(PLCVar.Counter1_5,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
|
||||
Object value = dataValue.getValue().getValue();
|
||||
try {
|
||||
webSocketServer.sendtoAll(value.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(value.equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc1",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeBoolen")
|
||||
public R subscribeBoolen() throws Exception {
|
||||
uaService.subscribe(PLCVar.Boolean_3,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
Object value = dataValue.getValue().getValue();
|
||||
//Integer integer = CommonFunction.judgeVarType(value);
|
||||
//System.out.println(integer);
|
||||
|
||||
try {
|
||||
webSocketServer.sendtoAll(value.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(value.equals(false)){
|
||||
System.err.println("subscribeBoolen I am over");
|
||||
}
|
||||
},"plc1",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeMultiply")
|
||||
public R subscribeMultiply() throws Exception {
|
||||
List<PLCVar> list = new ArrayList<>();
|
||||
list.add(PLCVar.Boolean_3);
|
||||
list.add(PLCVar.INT32_3);
|
||||
|
||||
uaService.subscribeValues(list,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
Object value = dataValue.getValue().getValue();
|
||||
try {
|
||||
webSocketServer.sendtoAll(value.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(value.equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc1");
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeEvent")
|
||||
public R subscribeEvent() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
|
||||
Integer a = uaService.subscribeEvent("plc1",0,2253,((uaMonitoredItem, variants) -> {
|
||||
logger.info("Event Received from {}",uaMonitoredItem.getReadValueId().getNodeId());
|
||||
|
||||
//这里variants 就是 0,2253 这个事件的 变量
|
||||
for (int i = 0; i < variants.length; i++) {
|
||||
logger.info("\t variant[{}]: {}", i, variants[i].getValue());
|
||||
}
|
||||
|
||||
if (eventCount.incrementAndGet() == 3) {
|
||||
//如果收到这个事件 3次以后 就可以退出了。
|
||||
}
|
||||
}));
|
||||
return R.ok().put("result",a);
|
||||
}
|
||||
|
||||
@GetMapping("subscribeEvent2")
|
||||
public R subscribeEvent2() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
uaService.subscribeEvent("plc1",2,"MyDevice",((uaMonitoredItem, variants) -> {
|
||||
logger.info("Event Received from {}",uaMonitoredItem.getReadValueId().getNodeId());
|
||||
//这里variants 就是 0,2253 这个事件的 变量
|
||||
for (int i = 0; i < variants.length; i++) {
|
||||
logger.info("\t variant[{}]: {}", i, variants[i].getValue());
|
||||
}
|
||||
|
||||
if (eventCount.incrementAndGet() == 3) {
|
||||
//如果收到这个事件 3次以后 就可以退出了。
|
||||
}
|
||||
}));
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeEvents")
|
||||
public R subscribeEvents() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
List<Integer> nameSpace = new ArrayList<>();
|
||||
List<Object> identifier = new ArrayList<>();
|
||||
nameSpace.add(0);
|
||||
identifier.add(2253);
|
||||
nameSpace.add(2);
|
||||
identifier.add("MyDevice");
|
||||
|
||||
BiConsumer<UaMonitoredItem, Variant[]> a1 =((uaMonitoredItem, variants) -> {
|
||||
logger.info("Server Event Received from {}", uaMonitoredItem.getReadValueId().getNodeId());
|
||||
//这里variants 就是 0,2253 这个事件的 变量
|
||||
for (int i = 0; i < variants.length; i++) {
|
||||
logger.info("\t variant[{}]: {}", i, variants[i].getValue());
|
||||
}
|
||||
|
||||
if (eventCount.incrementAndGet() == 3) {
|
||||
//如果收到这个事件 3次以后 就可以退出了。
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
BiConsumer<UaMonitoredItem, Variant[]> a2 =((uaMonitoredItem, variants) -> {
|
||||
logger.info("myDevice Event Received from {}", uaMonitoredItem.getReadValueId().getNodeId());
|
||||
//这里variants 就是 0,2253 这个事件的 变量
|
||||
for (int i = 0; i < variants.length; i++) {
|
||||
logger.info("\t variant[{}]: {}", i, variants[i].getValue());
|
||||
}
|
||||
|
||||
if (eventCount.incrementAndGet() == 3) {
|
||||
//如果收到这个事件 3次以后 就可以退出了。
|
||||
}
|
||||
});
|
||||
List<BiConsumer<UaMonitoredItem, Variant[]>> list = new ArrayList<>();
|
||||
list.add(a1);
|
||||
list.add(a2);
|
||||
|
||||
Integer plc1 = uaService.subscribeEvents("plc1", nameSpace, identifier,list);
|
||||
return R.ok().put("result",plc1);
|
||||
}
|
||||
|
||||
@GetMapping("suspendSubscribeEvent")
|
||||
public R suspendSubscribeEvent() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
List<Integer> namespace = new ArrayList<>();
|
||||
namespace.add(0);
|
||||
List<Object> identify = new ArrayList<>();
|
||||
identify.add(2253);
|
||||
return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
|
||||
}
|
||||
|
||||
@GetMapping("suspendSubscribeEvent2")
|
||||
public R suspendSubscribeEvent2() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
List<Integer> namespace = new ArrayList<>();
|
||||
namespace.add(2);
|
||||
List<Object> identify = new ArrayList<>();
|
||||
identify.add("MyDevice");
|
||||
return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
|
||||
}
|
||||
|
||||
@GetMapping("suspendSubscribeEvents")
|
||||
public R suspendSubscribeEvents() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
List<Integer> namespace = new ArrayList<>();
|
||||
List<Object> identify = new ArrayList<>();
|
||||
namespace.add(0);
|
||||
identify.add(2253);
|
||||
namespace.add(2);
|
||||
identify.add("MyDevice");
|
||||
|
||||
return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@GetMapping("suspendSubscribeVar2")
|
||||
public R suspendSubscribeVar2() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
List<Integer> namespace = new ArrayList<>();
|
||||
namespace.add(3);
|
||||
List<Object> identify = new ArrayList<>();
|
||||
identify.add("Boolean");
|
||||
return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
|
||||
}
|
||||
|
||||
@GetMapping("suspendSubscribeVars")
|
||||
public R suspendSubscribeVars() throws Exception {
|
||||
final AtomicInteger eventCount = new AtomicInteger(0);
|
||||
List<Integer> namespace = new ArrayList<>();
|
||||
namespace.add(3);
|
||||
namespace.add(3);
|
||||
|
||||
List<Object> identify = new ArrayList<>();
|
||||
identify.add("Boolean");
|
||||
identify.add("Int32");
|
||||
|
||||
return R.ok().put("result",uaService.suspendSubscribe("plc1",namespace,identify));
|
||||
}
|
||||
|
||||
|
||||
//test Real PLC
|
||||
@GetMapping("testWriteREALPlc")
|
||||
public R testWriteREALPlc(Integer a) throws Exception {
|
||||
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
Boolean aBoolean = null;
|
||||
try {
|
||||
aBoolean = uaService.setValue(PLCVar.RealPLC, Unsigned.ubyte(a),"plc3");
|
||||
|
||||
}catch (Exception e){
|
||||
String[] errMsgs = e.getMessage().split(",");
|
||||
for(String i : errMsgs){
|
||||
System.out.println("i = 》 " + i);
|
||||
}
|
||||
System.err.println("err msg: "+uaService.extractError(e.getMessage()));
|
||||
}
|
||||
|
||||
return R.ok().put("result",aBoolean);
|
||||
}
|
||||
@GetMapping("testWriteREALPlc2")
|
||||
public R testWriteREALPlc2(Integer a) throws Exception {
|
||||
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
Boolean aBoolean = null;
|
||||
try {
|
||||
aBoolean = uaService.setValue(PLCVar.RealPLC, a,"plc3");
|
||||
}catch (Exception e){
|
||||
String[] errMsgs = e.getMessage().split(",");
|
||||
for(String i : errMsgs){
|
||||
System.out.println("i = 》 " + i);
|
||||
}
|
||||
System.err.println("err msg: "+uaService.extractError(e.getMessage()));
|
||||
}
|
||||
|
||||
return R.ok().put("result",aBoolean);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("testReadREALPlc")
|
||||
public R testReadREALPlc() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
DataValue dataValue = uaService.getValue(PLCVar.RealPLC,"plc3");
|
||||
return R.ok().put("result",CommonFunction.var(dataValue.getValue().getValue()));
|
||||
}
|
||||
|
||||
@GetMapping("testReadREALPlc3")
|
||||
public R testReadREALPlc3() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
DataValue dataValue = uaService.getInitialNode(2255,"plc3");
|
||||
Object b = dataValue.getValue().getValue();
|
||||
return R.ok().put("result",CommonFunction.var(b));
|
||||
}
|
||||
|
||||
@GetMapping("testReadREALPlc3Brow")
|
||||
public R testReadREALPlc3Brow() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
NodeIdKey nodeIdKey = uaService.browseA("plc3", 3, "@LOCALSERVER");
|
||||
return R.ok().put("result",nodeIdKey);
|
||||
}
|
||||
|
||||
//todo main
|
||||
@GetMapping("testWriteArray")
|
||||
public R testWriteArray() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
String newValue = "false,false,false,false,false#QBoolean";
|
||||
|
||||
Object[] objects = PLCType.QArray.convertArray(newValue);
|
||||
|
||||
//Boolean aBoolean = uaService.setValue(3, "BooleanArray", o, "plc1");
|
||||
|
||||
//todo
|
||||
//uaService.setValues()
|
||||
return R.ok().put("result",123);
|
||||
}
|
||||
@GetMapping("testWriteByteArray")
|
||||
public R testWriteByteArray() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
String newValue = "6.1,6.1,6.1,6.1,6.1#QFloat";
|
||||
|
||||
//注意 这种方式也可以得到数据类型但是无法new 出 对应类型 的变量数组 如Boolen[] 只能是 Object[] 这样无法通过Milo写入OPC-SERVER
|
||||
Object objectsaa = PLCType.QArray.convertType(newValue);
|
||||
Object[] z1 = (Object[])objectsaa;
|
||||
Object z2 = z1[0];
|
||||
String name = z2.getClass().getName();
|
||||
|
||||
Object[] objects = PLCType.QArray.convertArray(newValue);
|
||||
|
||||
//Boolean aBoolean = uaService.setValue(3, "BooleanArray", o, "plc1");
|
||||
//ns=3;s=ByteArray ns=3;s=FloatArray
|
||||
|
||||
DataValue aByte = uaService.getValue(3, "FloatArray","plc1");
|
||||
|
||||
//todo 可以通过下面这种方式取到对应的数据类型,并且 解析出 数据里面的数据类型(放到judgeVarType 函数中去)
|
||||
Object os = aByte.getValue().getValue();
|
||||
Object[] osa = (Object[])os;
|
||||
Object a = osa[0];
|
||||
Object o = CommonFunction.judgeVarType(aByte.getValue().getValue());
|
||||
Object o1 = CommonFunction.judgeVarType(a);
|
||||
|
||||
//todo
|
||||
//uaService.setValues()
|
||||
return R.ok().put("result",o+"|"+o1);
|
||||
}
|
||||
|
||||
@GetMapping("testWriteDoubleArray")
|
||||
public R testWriteDoubleArray() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
String newValue = "7.1,7.1,7.1,7.1,7.1#QDouble";
|
||||
|
||||
|
||||
Object[] objects = PLCType.QArray.convertArray(newValue);
|
||||
|
||||
//ns=3;s=DoubleArray
|
||||
|
||||
DataValue aByte = uaService.getValue(3, "DoubleArray","plc1");
|
||||
Object o = CommonFunction.judgeVarType(aByte.getValue().getValue());
|
||||
System.err.println("before:"+o);
|
||||
|
||||
Boolean aBoolean = uaService.setValue(3, "DoubleArray", objects, "plc1");
|
||||
System.err.println("是否写成功"+aBoolean);
|
||||
|
||||
DataValue aByte1 = uaService.getValue(3, "DoubleArray","plc1");
|
||||
Object o1 = CommonFunction.judgeVarType(aByte1.getValue().getValue());
|
||||
System.err.println("before:"+o1);
|
||||
|
||||
//todo
|
||||
//uaService.setValues()
|
||||
return R.ok().put("result",o+"|"+o1);
|
||||
}
|
||||
|
||||
@GetMapping("getByteArrayValue")
|
||||
public R getByteArrayValue() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
//ns=3;s=ByteArray
|
||||
DataValue value = uaService.getValue(3, "BooleanArray", "plc1");
|
||||
//todo
|
||||
return R.ok().put("result",value.getValue().getValue());
|
||||
}
|
||||
|
||||
@GetMapping("subscribeRealPLCVar")
|
||||
public R subscribeRealPLCVar() throws Exception {
|
||||
//只要这个线程还在执行 就会一直未true。
|
||||
boolean alive = PLCConstant.displayThread.isAlive();
|
||||
|
||||
uaService.subscribe(PLCVar.RealPLC,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
|
||||
Object value = dataValue.getValue().getValue();
|
||||
IdType types = dataValue.getValue().getDataType().get().getType();
|
||||
int typeValue = dataValue.getValue().getDataType().get().getType().getValue();
|
||||
//Integer integer = CommonFunction.judgeVarType(value);
|
||||
|
||||
try {
|
||||
webSocketServer.sendtoAll(value.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(value.equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc3",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeList")
|
||||
public R subscribeList() throws Exception {
|
||||
//只要这个线程还在执行 就会一直未true。
|
||||
boolean alive = PLCConstant.displayThread.isAlive();
|
||||
|
||||
uaService.subscribe(PLCVar.StringArray_3,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
|
||||
Object value = dataValue.getValue().getValue();
|
||||
|
||||
IdType types = dataValue.getValue().getDataType().get().getType();
|
||||
System.out.println("types:"+types);
|
||||
int typeValue = dataValue.getValue().getDataType().get().getType().getValue();
|
||||
System.out.println("typeValue:"+typeValue);
|
||||
//Integer integer = CommonFunction.judgeVarType(value);
|
||||
//System.out.println("integer:"+integer);
|
||||
|
||||
try {
|
||||
webSocketServer.sendtoAll(value.toString());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if(value.equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc1",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
@ -0,0 +1,142 @@
|
||||
package com.qgs.dc.opcua.controller;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
|
||||
/**
|
||||
* @Author: 蔡翔
|
||||
* @Date: 2019/10/12 15:15
|
||||
* @Version 1.0
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/testPLC2")
|
||||
public class WmcController2plc2 {
|
||||
/*
|
||||
private static final Logger logger = LoggerFactory.getLogger(WmcController2plc2.class);
|
||||
@Autowired
|
||||
UAService uaService;
|
||||
|
||||
*//**
|
||||
* 测试real 类型(get / set)
|
||||
**//*
|
||||
@PostMapping("/noRR")
|
||||
public R noRR() throws Exception {
|
||||
return R.ok().put("OK",123);
|
||||
}
|
||||
|
||||
@GetMapping("/removeThisPlc")
|
||||
public R removeThisPlc() throws Exception {
|
||||
return R.ok().put("result",uaService.dynamicRemovePlc("plc2"));
|
||||
}
|
||||
|
||||
@GetMapping("testWriteOneVar")
|
||||
public R testWriteOneVar(Integer a) throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
Boolean aBoolean = uaService.setValue(PLCVar.INT32_3, a,"plc2");
|
||||
return R.ok().put("result",aBoolean);
|
||||
}
|
||||
|
||||
@GetMapping("testWriteTwoVar")
|
||||
public R testWriteTwoVar(Boolean b,Integer a) throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
List<PLCVar> list = new ArrayList<>();
|
||||
list.add(PLCVar.INT32_3);
|
||||
list.add(PLCVar.Boolean_3);
|
||||
|
||||
List<Object> value = new ArrayList<>();
|
||||
value.add(a);
|
||||
value.add(b);
|
||||
|
||||
Boolean aBoolean = uaService.setValues(list, value,"plc2");
|
||||
return R.ok().put("result",aBoolean);
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("testReadOneVar")
|
||||
public R testReadOneVar() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
DataValue dataValue = uaService.getValue(PLCVar.INT32_3,"plc2");
|
||||
return R.ok().put("result",dataValue.getValue().getValue());
|
||||
}
|
||||
|
||||
@GetMapping("testReadTwoVar")
|
||||
public R testReadTwoVar() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
|
||||
List<PLCVar> list = new ArrayList<>();
|
||||
list.add(PLCVar.Boolean_3);
|
||||
list.add(PLCVar.INT32_3);
|
||||
|
||||
List<DataValue> values = uaService.getValues(list ,"plc2");
|
||||
List<Object> res = new ArrayList<>();
|
||||
for(DataValue dv:values){
|
||||
res.add(dv.getValue().getValue());
|
||||
}
|
||||
return R.ok().put("result",res);
|
||||
}
|
||||
|
||||
@GetMapping("testReadBooleanArray")
|
||||
public R testReadBooleanArray() throws Exception {
|
||||
System.out.println("uaService.hashCode(): "+uaService.hashCode());
|
||||
DataValue aBoolean = null;
|
||||
try {
|
||||
aBoolean = uaService.getValue(PLCVar.BooleanArray_3,"plc2");
|
||||
}catch (Exception e){
|
||||
|
||||
System.out.println("err status: "+uaService.extractError(e.getMessage()));
|
||||
}
|
||||
return R.ok().put("result",aBoolean.getValue().getValue());
|
||||
}
|
||||
|
||||
@GetMapping("subscribeInt32")
|
||||
public R subscribeInt32() throws Exception {
|
||||
uaService.subscribe(PLCVar.INT32_3,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
if(dataValue.getValue().getValue().equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc2",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeMultiply")
|
||||
public R subscribeMultiply() throws Exception {
|
||||
List<PLCVar> list = new ArrayList<>();
|
||||
list.add(PLCVar.Boolean_3);
|
||||
list.add(PLCVar.INT32_3);
|
||||
|
||||
uaService.subscribeValues(list,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
if(dataValue.getValue().getValue().equals(11)){
|
||||
System.err.println("subscribeInt32 I am over");
|
||||
}
|
||||
},"plc2");
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
|
||||
@GetMapping("subscribeBoolen")
|
||||
public R subscribeBoolen() throws Exception {
|
||||
uaService.subscribe(PLCVar.Boolean_3,new Double(1000),(item,dataValue)->{
|
||||
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
if(dataValue.getValue().getValue().equals(false)){
|
||||
System.err.println("subscribeBoolen I am over");
|
||||
}
|
||||
},"plc2",1);
|
||||
return R.ok().put("result","ok");
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
47
src/main/java/com/qgs/dc/opcua/selfunion/ClientExample.java
Normal file
47
src/main/java/com/qgs/dc/opcua/selfunion/ClientExample.java
Normal file
@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2019 the Eclipse Milo Authors
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
|
||||
package com.qgs.dc.opcua.selfunion;
|
||||
|
||||
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
|
||||
import org.eclipse.milo.opcua.sdk.client.api.identity.IdentityProvider;
|
||||
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
|
||||
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
|
||||
import org.eclipse.milo.opcua.stack.core.types.enumerated.MessageSecurityMode;
|
||||
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
|
||||
public interface ClientExample {
|
||||
|
||||
default String getEndpointUrl() {
|
||||
return "opc.tcp://LAPTOP-HU5V73OJ:53530/OPCUA/SimulationServer";
|
||||
}
|
||||
|
||||
default Predicate<EndpointDescription> endpointFilter() {
|
||||
//只要是 就全部放进来 (不过滤)
|
||||
return e -> e.getSecurityMode().equals(MessageSecurityMode.SignAndEncrypt);
|
||||
}
|
||||
|
||||
default SecurityPolicy getSecurityPolicy() {
|
||||
//return SecurityPolicy.None;
|
||||
return SecurityPolicy.Basic128Rsa15;
|
||||
}
|
||||
|
||||
default IdentityProvider getIdentityProvider() {
|
||||
//return new AnonymousProvider();
|
||||
return new UsernameProvider("CXCX","251128856");
|
||||
}
|
||||
|
||||
void run(OpcUaClient client, CompletableFuture<OpcUaClient> future) throws Exception;
|
||||
|
||||
}
|
195
src/main/java/com/qgs/dc/opcua/selfunion/Enum/PLCType.java
Normal file
195
src/main/java/com/qgs/dc/opcua/selfunion/Enum/PLCType.java
Normal file
@ -0,0 +1,195 @@
|
||||
package com.qgs.dc.opcua.selfunion.Enum;
|
||||
|
||||
import com.qgs.dc.opcua.constant.PLCTypeConstant;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.ByteString;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UByte;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UInteger;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.ULong;
|
||||
import org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.UShort;
|
||||
|
||||
|
||||
//展示支持数据
|
||||
//如果要添加新的变量 :
|
||||
// 1.①先在PLCTypeConstant中添加 变量常量;;
|
||||
// 2.②在枚举类PLCType.convertType() 方法中扩展 新的变量,,如果是数组的话PLCType.convertArray()也要扩展;;③枚举类里面也要扩展QUByte(1),
|
||||
// 3.④CommonFunction.judgeVarType() 里面也要扩展
|
||||
public enum PLCType implements PLCTypeEnum{
|
||||
//注意:下面类型 必须和 CommonFunction.judgeVarType() 方法里面的数据类型 按顺序一一对应
|
||||
|
||||
/**
|
||||
* 无符号 Byte
|
||||
* */
|
||||
QUByte(1),
|
||||
/**
|
||||
* 无符号 Integer
|
||||
* */
|
||||
QUInteger(2),
|
||||
/**
|
||||
* 无符号 Short
|
||||
* */
|
||||
QUShort(3),
|
||||
QULong(4),
|
||||
QBoolean(5),
|
||||
QString(6),
|
||||
QDouble(7),
|
||||
QFloat(8),
|
||||
QLong(9),
|
||||
QInteger(10),
|
||||
QShort(11),
|
||||
QArray(12), //如果是数组,那么数据长度要小于等于原数组长度
|
||||
QByte(13),
|
||||
QByteString(14)
|
||||
;
|
||||
private Integer plcVarType;
|
||||
PLCType(Integer type){
|
||||
this.plcVarType = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getVarType() {
|
||||
return this.plcVarType;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用处:在写变量到 OPC-Server的时候,需要先把变量 类型转换一下 ( 转换的是非数组变量 )
|
||||
* 注意:1. 如果是ByteString 类型 那么传进来newValue 就是 “1,2,3,4,5,1,1,1” type = ByteString;
|
||||
* 参数:传入旧的数据类型
|
||||
* 返回:返回新的数据类型
|
||||
* */
|
||||
@Override
|
||||
public Object convertType(Object oldType) {
|
||||
if(plcVarType == 1){
|
||||
return UByte.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 2){
|
||||
return UInteger.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 3){
|
||||
return UShort.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 4){
|
||||
return ULong.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 5){
|
||||
return Boolean.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 6){
|
||||
return String.valueOf(oldType);
|
||||
}else if(plcVarType == 7){
|
||||
return Double.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 8){
|
||||
return Float.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 9){
|
||||
return Long.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 10){
|
||||
return Integer.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 11){
|
||||
return Short.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 12){
|
||||
return convertArray(oldType);
|
||||
}else if(plcVarType == 13){
|
||||
return Byte.valueOf(String.valueOf(oldType));
|
||||
}else if(plcVarType == 14){
|
||||
// 如果知道是 ByteString 数据类型。那么传进来 是String 类型 用逗号隔开
|
||||
String s = (String)oldType;
|
||||
String[] split = s.split(",");
|
||||
byte[] u = new byte[split.length];
|
||||
for(int i=0;i<split.length;i++){
|
||||
u[i] = Byte.parseByte(split[i]);
|
||||
}
|
||||
ByteString b = ByteString.of(u);
|
||||
return b;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 用处:在写变量到 OPC-Server的时候,需要先把变量 类型转换一下 ( 转换的是数组变量 )
|
||||
* 参数:传入旧的数据类型 例如 "7.1,7.1,7.1,7.1,7.1#QDouble"
|
||||
* 返回:返回新的数据类型 例如 [....] 合适数据类型
|
||||
* */
|
||||
@Override
|
||||
public Object[] convertArray(Object oldType) {
|
||||
|
||||
//如果是数组 就先返回string。 注意:如果是数组 传入的是String 类型并且格式 是 “1,2,3|QUByte” 这样的。 注意后面QUByte 跟着的是数组里面变量的类型
|
||||
String s = (String)oldType;
|
||||
String[] all = s.split("#");
|
||||
String[] content = all[0].split(",");
|
||||
|
||||
String type = all[1];
|
||||
Integer length = content.length;
|
||||
|
||||
if(PLCTypeConstant.QUByte.equals(type)){
|
||||
UByte[] res = new UByte[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = UByte.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QUInteger.equals(type)){
|
||||
UInteger[] res = new UInteger[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = UInteger.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QUShort.equals(type)){
|
||||
UShort[] res = new UShort[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = UShort.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QULong.equals(type)){
|
||||
ULong[] res = new ULong[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = ULong.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QBoolean.equals(type)){
|
||||
Boolean[] res = new Boolean[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = Boolean.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QString.equals(type)){
|
||||
String[] res = new String[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = String.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QDouble.equals(type)){
|
||||
Double[] res = new Double[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = Double.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QFloat.equals(type)){
|
||||
Float[] res = new Float[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = Float.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QLong.equals(type)){
|
||||
Long[] res = new Long[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = Long.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QInteger.equals(type)){
|
||||
Integer[] res = new Integer[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = Integer.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QShort.equals(type)){
|
||||
Short[] res = new Short[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = Short.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else if(PLCTypeConstant.QByte.equals(type)) {
|
||||
Byte[] res = new Byte[length];
|
||||
for(int i=0;i<content.length;i++){
|
||||
res[i] = Byte.valueOf(content[i]);
|
||||
}
|
||||
return res;
|
||||
}else {
|
||||
return null;
|
||||
}
|
||||
|
||||
//return content;
|
||||
}
|
||||
}
|
@ -0,0 +1,7 @@
|
||||
package com.qgs.dc.opcua.selfunion.Enum;
|
||||
|
||||
public interface PLCTypeEnum {
|
||||
Integer getVarType();
|
||||
Object convertType(Object oldType);
|
||||
Object[] convertArray(Object oldType);
|
||||
}
|
42
src/main/java/com/qgs/dc/opcua/selfunion/Enum/PLCVar.java
Normal file
42
src/main/java/com/qgs/dc/opcua/selfunion/Enum/PLCVar.java
Normal file
@ -0,0 +1,42 @@
|
||||
package com.qgs.dc.opcua.selfunion.Enum;
|
||||
|
||||
public enum PLCVar implements PLCVarEnum {
|
||||
/**
|
||||
* 命名空间为3 identify:Int32 的变量
|
||||
* */
|
||||
INT32_3(3,"Int32"),
|
||||
BYTE_3(3,"Byte"),
|
||||
Boolean_3(3,"Boolean"),
|
||||
BooleanArray_3(3,"BooleanArray"),
|
||||
ByteArray_3(3,"ByteArray"),
|
||||
StringArray_3(3,"StringArray"),
|
||||
Counter1_5(5,"Counter1"),
|
||||
Double_5(3,"Double"),
|
||||
Float_5(3,"Float"),
|
||||
String_5(3,"String"),
|
||||
UInteger_5(3,"UInteger"),
|
||||
UInt16_5(3,"UInt16"),
|
||||
Int64_5(3,"Int64"),
|
||||
Int32_5(3,"Int32"),
|
||||
Int16_5(3,"Int16"),
|
||||
|
||||
RealPLC(3,"@LOCALSERVER.db1.0,b"),
|
||||
|
||||
;
|
||||
private Integer namespace;
|
||||
private String identifier;
|
||||
PLCVar(Integer namespace,String identifier){
|
||||
this.namespace = namespace;
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Integer getNameSpace() {
|
||||
return this.namespace;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getIdentifier() {
|
||||
return this.identifier;
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
package com.qgs.dc.opcua.selfunion.Enum;
|
||||
|
||||
public interface PLCVarEnum {
|
||||
Integer getNameSpace();
|
||||
String getIdentifier();
|
||||
}
|
111
src/main/java/com/qgs/dc/opcua/selfunion/KeyStoreLoader.java
Normal file
111
src/main/java/com/qgs/dc/opcua/selfunion/KeyStoreLoader.java
Normal file
@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2019 the Eclipse Milo Authors
|
||||
*
|
||||
* This program and the accompanying materials are made
|
||||
* available under the terms of the Eclipse Public License 2.0
|
||||
* which is available at https://www.eclipse.org/legal/epl-2.0/
|
||||
*
|
||||
* SPDX-License-Identifier: EPL-2.0
|
||||
*/
|
||||
|
||||
package com.qgs.dc.opcua.selfunion;
|
||||
|
||||
import org.eclipse.milo.opcua.sdk.server.util.HostnameUtil;
|
||||
import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateBuilder;
|
||||
import org.eclipse.milo.opcua.stack.core.util.SelfSignedCertificateGenerator;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.*;
|
||||
import java.security.cert.X509Certificate;
|
||||
import java.time.Period;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
class KeyStoreLoader {
|
||||
|
||||
private static final Pattern IP_ADDR_PATTERN = Pattern.compile(
|
||||
"^(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])$");
|
||||
|
||||
private static final String CLIENT_ALIAS = "client-ai";
|
||||
private static final char[] PASSWORD = "password".toCharArray();
|
||||
|
||||
private final Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private X509Certificate clientCertificate;
|
||||
private KeyPair clientKeyPair;
|
||||
|
||||
//DESKTOP-5CTK5AA
|
||||
KeyStoreLoader load(Path baseDir,String ip) throws Exception {
|
||||
KeyStore keyStore = KeyStore.getInstance("PKCS12");
|
||||
|
||||
//注意不同 plc 要不同的 证书。。 如果要更换证书 配置那么要把之间的证书信息给删除了。不然回去读之前的证书信息 然后去匹配新的config信息这样就冲突了
|
||||
String myCer = ip+"-local-client-Cer.pfx";
|
||||
Path serverKeyStore = baseDir.resolve(myCer);
|
||||
|
||||
logger.info("Loading KeyStore at {}", serverKeyStore);
|
||||
|
||||
if (!Files.exists(serverKeyStore)) {
|
||||
keyStore.load(null, PASSWORD);
|
||||
|
||||
KeyPair keyPair = SelfSignedCertificateGenerator.generateRsaKeyPair(2048);
|
||||
|
||||
//注意证书的uri 中必须是OPC服务器 的ip,,并且生成的证书uri 和 初始化客户端上的uri 必须相同。
|
||||
String uri = "urn:"+ip+":SimulationServer:clientBaseMilo";
|
||||
|
||||
SelfSignedCertificateBuilder builder = new SelfSignedCertificateBuilder(keyPair)
|
||||
.setCommonName("QGS_OpcUaClient")
|
||||
.setOrganization("digitalpetri")
|
||||
.setOrganizationalUnit("dev")
|
||||
.setLocalityName("Folsom")
|
||||
.setStateName("CA")
|
||||
.setCountryCode("CN")
|
||||
//opc.tcp://DESKTOP-5CTK5AA:53530/OPCUA/SimulationServer
|
||||
.setApplicationUri(uri)
|
||||
.addDnsName("localhost")
|
||||
.addIpAddress("127.0.0.1")
|
||||
.setValidityPeriod(Period.ofYears(99));
|
||||
|
||||
// Get as many hostnames and IP addresses as we can listed in the certificate.
|
||||
for (String hostname : HostnameUtil.getHostnames("0.0.0.0")) {
|
||||
if (IP_ADDR_PATTERN.matcher(hostname).matches()) {
|
||||
builder.addIpAddress(hostname);
|
||||
} else {
|
||||
builder.addDnsName(hostname);
|
||||
}
|
||||
}
|
||||
|
||||
X509Certificate certificate = builder.build();
|
||||
|
||||
keyStore.setKeyEntry(CLIENT_ALIAS, keyPair.getPrivate(), PASSWORD, new X509Certificate[]{certificate});
|
||||
try (OutputStream out = Files.newOutputStream(serverKeyStore)) {
|
||||
keyStore.store(out, PASSWORD);
|
||||
}
|
||||
} else {
|
||||
try (InputStream in = Files.newInputStream(serverKeyStore)) {
|
||||
keyStore.load(in, PASSWORD);
|
||||
}
|
||||
}
|
||||
|
||||
Key serverPrivateKey = keyStore.getKey(CLIENT_ALIAS, PASSWORD);
|
||||
if (serverPrivateKey instanceof PrivateKey) {
|
||||
clientCertificate = (X509Certificate) keyStore.getCertificate(CLIENT_ALIAS);
|
||||
PublicKey serverPublicKey = clientCertificate.getPublicKey();
|
||||
clientKeyPair = new KeyPair(serverPublicKey, (PrivateKey) serverPrivateKey);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
X509Certificate getClientCertificate() {
|
||||
return clientCertificate;
|
||||
}
|
||||
|
||||
KeyPair getClientKeyPair() {
|
||||
return clientKeyPair;
|
||||
}
|
||||
|
||||
}
|
98
src/main/java/com/qgs/dc/opcua/selfunion/NodeIdKey.java
Normal file
98
src/main/java/com/qgs/dc/opcua/selfunion/NodeIdKey.java
Normal file
@ -0,0 +1,98 @@
|
||||
package com.qgs.dc.opcua.selfunion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class NodeIdKey {
|
||||
private String nodeName;
|
||||
private Integer namespace;
|
||||
private String identifier;
|
||||
private List<NodeIdKey> child;
|
||||
|
||||
/**
|
||||
* type 类型 (就是Node)
|
||||
* Unspecified(0),
|
||||
*
|
||||
* Object(1), //一般代表文件夹
|
||||
*
|
||||
* Variable(2), //一般代表变量
|
||||
*
|
||||
* Method(4), //一般代表方法
|
||||
*
|
||||
* ObjectType(8),
|
||||
*
|
||||
* VariableType(16),
|
||||
*
|
||||
* ReferenceType(32),
|
||||
*
|
||||
* DataType(64),
|
||||
*
|
||||
* View(128); //一般代表视图
|
||||
*
|
||||
* */
|
||||
private Integer nodeType;
|
||||
|
||||
/**
|
||||
* 这个代表 Node节点里面存着的变量 的类型
|
||||
* */
|
||||
private String varType;
|
||||
|
||||
public NodeIdKey(String nodeName,Integer nodeType,Integer namespace, String identifier,String varType) {
|
||||
this.nodeName = nodeName;
|
||||
this.nodeType = nodeType;
|
||||
this.namespace = namespace;
|
||||
this.identifier = identifier;
|
||||
this.varType = varType;
|
||||
this.child = new ArrayList<>();
|
||||
}
|
||||
|
||||
public Integer getNodeType() {
|
||||
return nodeType;
|
||||
}
|
||||
|
||||
public void setNodeType(Integer nodeType) {
|
||||
this.nodeType = nodeType;
|
||||
}
|
||||
|
||||
public String getVarType() {
|
||||
return varType;
|
||||
}
|
||||
|
||||
public void setVarType(String varType) {
|
||||
this.varType = varType;
|
||||
}
|
||||
|
||||
public List<NodeIdKey> getChild() {
|
||||
return child;
|
||||
}
|
||||
|
||||
public void setChild(List<NodeIdKey> child) {
|
||||
this.child = child;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public String getNodeName() {
|
||||
return nodeName;
|
||||
}
|
||||
|
||||
public void setNodeName(String nodeName) {
|
||||
this.nodeName = nodeName;
|
||||
}
|
||||
|
||||
public Integer getNamespace() {
|
||||
return namespace;
|
||||
}
|
||||
|
||||
public void setNamespace(Integer namespace) {
|
||||
this.namespace = namespace;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
}
|
69
src/main/java/com/qgs/dc/opcua/selfunion/Test.java
Normal file
69
src/main/java/com/qgs/dc/opcua/selfunion/Test.java
Normal file
@ -0,0 +1,69 @@
|
||||
package com.qgs.dc.opcua.selfunion;
|
||||
|
||||
|
||||
public class Test {
|
||||
public static void main(String[] args) throws Exception {
|
||||
/*
|
||||
//1.测试读且 单个变量
|
||||
UAService uaService = new UAService();
|
||||
DataValue valueByName = uaService.getValueByName(PLCVar.INT32_3);
|
||||
System.out.println(valueByName.getValue().getValue());
|
||||
*/
|
||||
|
||||
/*
|
||||
//2.测试读且 多个变量
|
||||
UAService uaService = new UAService();
|
||||
List<DataValue> values = uaService.getValues(PLCVar.Boolean_3,PLCVar.INT32_3);
|
||||
for(DataValue i:values){
|
||||
System.out.println(i.getValue().getValue());
|
||||
}*/
|
||||
/*
|
||||
|
||||
//3.write 一次性 写一个变量
|
||||
UAService uaService = new UAService();
|
||||
boolean valueByName = uaService.setValue(PLCVar.INT32_3,11);
|
||||
System.out.println(valueByName);
|
||||
*/
|
||||
/*
|
||||
//4.write 一次性 写多个变量
|
||||
UAService uaService = new UAService();
|
||||
List<PLCVar> vars = new ArrayList<>();
|
||||
vars.add(PLCVar.INT32_3);
|
||||
vars.add(PLCVar.Boolean_3);
|
||||
List<Object> values = new ArrayList<>();
|
||||
values.add(20);
|
||||
values.add(false);
|
||||
|
||||
boolean valueByName = uaService.setValues(vars,values);
|
||||
System.out.println(valueByName);*/
|
||||
|
||||
//5.订阅变量
|
||||
/*
|
||||
UAService uaService = new UAService();
|
||||
uaService.subscribe(PLCVar.INT32_3,new Double(1000.0),(item, dataValue)->{
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
if(dataValue.getValue().getValue().equals(11)){
|
||||
System.out.println("I AM DONE");
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
uaService.subscribe(PLCVar.Boolean_3,new Double(1000.0),(item,dataValue)->{
|
||||
System.err.println("(测试是否 每隔intervel 都会执行这个回调方法) subscription value received: item:NodeId : " +
|
||||
""+item.getReadValueId().getNodeId()+", value :"+ dataValue.getValue());
|
||||
System.out.println();
|
||||
if(dataValue.getValue().getValue().equals(false)){
|
||||
System.out.println("I AM DONE");
|
||||
}
|
||||
|
||||
});
|
||||
System.out.println("测试subscribe 是否异步");*/
|
||||
|
||||
String a = "a|b";
|
||||
String[] split = a.split("\\|");
|
||||
System.out.println(split[0]);
|
||||
System.out.println(split[1]);
|
||||
}
|
||||
}
|
39
src/main/java/com/qgs/dc/opcua/selfunion/Test2.java
Normal file
39
src/main/java/com/qgs/dc/opcua/selfunion/Test2.java
Normal file
@ -0,0 +1,39 @@
|
||||
package com.qgs.dc.opcua.selfunion;
|
||||
|
||||
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public class Test2 {
|
||||
public static void main(String[] args) throws Exception {/*
|
||||
UAService uaService = new UAService();
|
||||
*//*boolean valueByName = uaService.setValue(PLCVar.INT32_3,11);
|
||||
System.out.println("before:"+valueByName);*//*
|
||||
long start = System.currentTimeMillis();
|
||||
uaService.setValue(PLCVar.Boolean_3,true);
|
||||
long end = System.currentTimeMillis();
|
||||
System.out.println("after:need time :"+(end-start));*/
|
||||
|
||||
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {
|
||||
try {
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return "101";
|
||||
});
|
||||
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 100);
|
||||
|
||||
//s 参数是主体,,i 是future的结果。 并且会等 future1、future2 都完成了。
|
||||
CompletableFuture<Double> future = future1.thenCombine(future2, (s, i) -> Double.parseDouble(s + i));
|
||||
|
||||
try {
|
||||
System.out.println(future.get());
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
57
src/main/java/com/qgs/dc/opcua/selfunion/Test3.java
Normal file
57
src/main/java/com/qgs/dc/opcua/selfunion/Test3.java
Normal file
@ -0,0 +1,57 @@
|
||||
package com.qgs.dc.opcua.selfunion;
|
||||
|
||||
|
||||
import com.qgs.dc.opcua.selfunion.Enum.PLCVar;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/20 8:52
|
||||
*/
|
||||
public class Test3 {
|
||||
public static void main(String[] args) {
|
||||
List<String> as = new ArrayList<>();
|
||||
as.add("1");
|
||||
as.add("2");
|
||||
as.add("3");
|
||||
|
||||
HashMap<String,String> asas = new HashMap<>();
|
||||
asas.put("1","a");
|
||||
asas.put("2","b");
|
||||
asas.put("3","c");
|
||||
|
||||
String[] ss = new String[3];
|
||||
ss[0] = "a";
|
||||
ss[1] = "b";
|
||||
ss[2] = "c";
|
||||
|
||||
System.out.println("as:"+asas.getClass().isArray());
|
||||
System.out.println("asas:"+asas.getClass().isArray());
|
||||
System.out.println("ss:"+ Arrays.asList(ss));
|
||||
List<Object> list = new ArrayList<>();
|
||||
list = Arrays.asList(ss);
|
||||
System.out.println("list"+list);
|
||||
|
||||
System.out.println("INT32_3:"+ PLCVar.valueOf("INT32_3").getIdentifier());
|
||||
|
||||
String newValue = "6,7,8,9,10#QUByte";
|
||||
String[] split = newValue.split("#");
|
||||
System.out.println(split);
|
||||
|
||||
Object[] b = te();
|
||||
System.out.println(b);
|
||||
}
|
||||
|
||||
public static Object[] te(){
|
||||
Object[] as = new Object[3];
|
||||
as[0] = true;
|
||||
as[1] = true;
|
||||
as[2] = true;
|
||||
return as;
|
||||
}
|
||||
}
|
1823
src/main/java/com/qgs/dc/opcua/selfunion/UAService.java
Normal file
1823
src/main/java/com/qgs/dc/opcua/selfunion/UAService.java
Normal file
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,72 @@
|
||||
package com.qgs.dc.opcua.selfunion.entity;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/8/6 8:48
|
||||
*/
|
||||
public class CurrentSubEntity {
|
||||
private Integer nameSpace;
|
||||
private String identifier;
|
||||
private Object value;
|
||||
private String valueType;
|
||||
private Boolean isArray;
|
||||
private String plcName;
|
||||
|
||||
public CurrentSubEntity(Integer nameSpace, String identifier, Object value, String valueType, Boolean isArray, String plcName) {
|
||||
this.nameSpace = nameSpace;
|
||||
this.identifier = identifier;
|
||||
this.value = value;
|
||||
this.valueType = valueType;
|
||||
this.isArray = isArray;
|
||||
this.plcName = plcName;
|
||||
}
|
||||
|
||||
public Boolean getArray() {
|
||||
return isArray;
|
||||
}
|
||||
|
||||
public void setArray(Boolean array) {
|
||||
isArray = array;
|
||||
}
|
||||
|
||||
public Integer getNameSpace() {
|
||||
return nameSpace;
|
||||
}
|
||||
|
||||
public void setNameSpace(Integer nameSpace) {
|
||||
this.nameSpace = nameSpace;
|
||||
}
|
||||
|
||||
public String getIdentifier() {
|
||||
return identifier;
|
||||
}
|
||||
|
||||
public void setIdentifier(String identifier) {
|
||||
this.identifier = identifier;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public void setValue(Object value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValueType() {
|
||||
return valueType;
|
||||
}
|
||||
|
||||
public void setValueType(String valueType) {
|
||||
this.valueType = valueType;
|
||||
}
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
@ -0,0 +1,47 @@
|
||||
package com.qgs.dc.opcua.selfunion.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/8/7 9:57
|
||||
*/
|
||||
public class DelSubscribeEntity {
|
||||
List<Integer> listNameSpace;
|
||||
List<Object> listIdentifier;
|
||||
String plcName;
|
||||
Integer type;
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Integer type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public List<Integer> getListNameSpace() {
|
||||
return listNameSpace;
|
||||
}
|
||||
|
||||
public void setListNameSpace(List<Integer> listNameSpace) {
|
||||
this.listNameSpace = listNameSpace;
|
||||
}
|
||||
|
||||
public List<Object> getListIdentifier() {
|
||||
return listIdentifier;
|
||||
}
|
||||
|
||||
public void setListIdentifier(List<Object> listIdentifier) {
|
||||
this.listIdentifier = listIdentifier;
|
||||
}
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
@ -0,0 +1,61 @@
|
||||
package com.qgs.dc.opcua.selfunion.entity;
|
||||
|
||||
import org.eclipse.milo.opcua.sdk.client.api.subscriptions.UaSubscription;
|
||||
|
||||
import java.util.HashMap;
|
||||
|
||||
public class SubscribeEntity {
|
||||
private UaSubscription uaSubscription;
|
||||
// 1 代表已经订阅成功 ;;; 2 代表 这个订阅以被取消
|
||||
private Integer status;
|
||||
|
||||
//1 == 代表 展示型订阅;;2 == 代表 功能型(变量) 订阅;;3 == 代表 功能型(事件) 订阅
|
||||
private Integer type;
|
||||
|
||||
/**
|
||||
* type == 1 的时候
|
||||
* content 中包含所有的 节点信息(key:"ns,identifier" value:"",,value 是空值,,只有当type==2 的时候才有意义)
|
||||
* type == 2 的时候
|
||||
* content 就包含(key:"ns,identifier" value:"后调函数的接口")
|
||||
* */
|
||||
private HashMap<String,String> content;
|
||||
|
||||
public SubscribeEntity(UaSubscription uaSubscription, Integer status,Integer type) {
|
||||
this.uaSubscription = uaSubscription;
|
||||
this.status = status;
|
||||
this.type = type;
|
||||
content = new HashMap<>();
|
||||
}
|
||||
|
||||
public Integer getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void setType(Integer type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
public HashMap<String, String> getContent() {
|
||||
return content;
|
||||
}
|
||||
|
||||
public void setContent(HashMap<String, String> content) {
|
||||
this.content = content;
|
||||
}
|
||||
|
||||
public UaSubscription getUaSubscription() {
|
||||
return uaSubscription;
|
||||
}
|
||||
|
||||
public void setUaSubscription(UaSubscription uaSubscription) {
|
||||
this.uaSubscription = uaSubscription;
|
||||
}
|
||||
|
||||
public Integer getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Integer status) {
|
||||
this.status = status;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.qgs.dc.opcua.selfunion.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/23 14:51
|
||||
*/
|
||||
public class SubscribeEventArgEntity {
|
||||
List<Integer> listNameSpace;
|
||||
List<Object> listIdentifier;
|
||||
String plcName;
|
||||
|
||||
public List<Integer> getListNameSpace() {
|
||||
return listNameSpace;
|
||||
}
|
||||
|
||||
public void setListNameSpace(List<Integer> listNameSpace) {
|
||||
this.listNameSpace = listNameSpace;
|
||||
}
|
||||
|
||||
public List<Object> getListIdentifier() {
|
||||
return listIdentifier;
|
||||
}
|
||||
|
||||
public void setListIdentifier(List<Object> listIdentifier) {
|
||||
this.listIdentifier = listIdentifier;
|
||||
}
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
package com.qgs.dc.opcua.selfunion.entity;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @Desc: ""
|
||||
* @Author: caixiang
|
||||
* @DATE: 2020/7/23 14:51
|
||||
*/
|
||||
public class SubscribeVarArgEntity {
|
||||
List<Integer> listNameSpace;
|
||||
List<String> listIdentifier;
|
||||
String plcName;
|
||||
|
||||
public List<Integer> getListNameSpace() {
|
||||
return listNameSpace;
|
||||
}
|
||||
|
||||
public void setListNameSpace(List<Integer> listNameSpace) {
|
||||
this.listNameSpace = listNameSpace;
|
||||
}
|
||||
|
||||
public List<String> getListIdentifier() {
|
||||
return listIdentifier;
|
||||
}
|
||||
|
||||
public void setListIdentifier(List<String> listIdentifier) {
|
||||
this.listIdentifier = listIdentifier;
|
||||
}
|
||||
|
||||
public String getPlcName() {
|
||||
return plcName;
|
||||
}
|
||||
|
||||
public void setPlcName(String plcName) {
|
||||
this.plcName = plcName;
|
||||
}
|
||||
}
|
29
src/main/resources/application.yml
Normal file
29
src/main/resources/application.yml
Normal file
@ -0,0 +1,29 @@
|
||||
server:
|
||||
port: 8009
|
||||
spring:
|
||||
rabbitmq:
|
||||
# 如果是rabbitmq+haproxy+keepalived集群 ,,那么192.168.0.176是haproxy代理的地址(严格来说是keepalived的vip)
|
||||
addresses: 192.168.0.176:5672
|
||||
username: cdte
|
||||
password: cdte
|
||||
virtual-host: cdte
|
||||
connection-timeout: 15000
|
||||
publisher-confirm-type: correlated
|
||||
publisher-returns: true
|
||||
template:
|
||||
mandatory: true
|
||||
listener:
|
||||
simple:
|
||||
acknowledge-mode: manual
|
||||
concurrency: 1
|
||||
max-concurrency: 10
|
||||
prefetch: 5
|
||||
|
||||
#================重试机制 开始
|
||||
#retry:
|
||||
#max-attempts: 3 #最大重试次数
|
||||
#enabled: true #是否开启消费者重试(为false时关闭消费者重试,这时消费端代码异常会一直重复收到消息)
|
||||
#initial-interval: 2000 #重试间隔时间(单位毫秒)
|
||||
#max-interval: 10000 # 重试最大间隔时间
|
||||
#multiplier: 2 # 间隔时间乘子,间隔时间*乘子=下一次的间隔时间,最大不能超过设置的最大间隔时间
|
||||
#================重试机制 结束
|
512
src/main/resources/logback.xml
Normal file
512
src/main/resources/logback.xml
Normal file
@ -0,0 +1,512 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- 日志级别从低到高分为TRACE < DEBUG < INFO < WARN < ERROR < FATAL,如果设置为WARN,则低于WARN的信息都不会输出 -->
|
||||
<!-- scan:当此属性设置为true时,配置文档如果发生改变,将会被重新加载,默认值为true -->
|
||||
<!-- scanPeriod:设置监测配置文档是否有修改的时间间隔,如果没有给出时间单位,默认单位是毫秒。
|
||||
当scan为true时,此属性生效。默认的时间间隔为1分钟。 -->
|
||||
<!-- debug:当此属性设置为true时,将打印出logback内部日志信息,实时查看logback运行状态。默认值为false。 -->
|
||||
<configuration scan="true" scanPeriod="10 seconds">
|
||||
<contextName>logback-spring</contextName>
|
||||
|
||||
<!-- name的值是变量的名称,value的值时变量定义的值。通过定义的值会被插入到logger上下文中。定义后,可以使“${}”来使用变量。 -->
|
||||
|
||||
<property name="logging.pathwork" value="C:/qgs_logger/work" />
|
||||
<property name="logging.pathopc" value="C:/qgs_logger/opc" />
|
||||
<property name="logging.pathmq" value="C:/qgs_logger/mq" />
|
||||
|
||||
|
||||
<!--0. 日志格式和颜色渲染 -->
|
||||
<!-- 彩色日志依赖的渲染类 -->
|
||||
<conversionRule conversionWord="clr" converterClass="org.springframework.boot.logging.logback.ColorConverter" />
|
||||
<conversionRule conversionWord="wex" converterClass="org.springframework.boot.logging.logback.WhitespaceThrowableProxyConverter" />
|
||||
<conversionRule conversionWord="wEx" converterClass="org.springframework.boot.logging.logback.ExtendedWhitespaceThrowableProxyConverter" />
|
||||
<!-- 彩色日志格式 -->
|
||||
<property name="CONSOLE_LOG_PATTERN" value="${CONSOLE_LOG_PATTERN:-%clr(%d{yyyy-MM-dd HH:mm:ss.SSS}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}"/>
|
||||
|
||||
<!--1. 输出到控制台-->
|
||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||
<!--此日志appender是为开发使用,只配置最底级别,控制台输出的日志级别是大于或等于此级别的日志信息-->
|
||||
<filter class="ch.qos.logback.classic.filter.ThresholdFilter">
|
||||
<level>debug</level>
|
||||
</filter>
|
||||
<encoder>
|
||||
<Pattern>${CONSOLE_LOG_PATTERN}</Pattern>
|
||||
<!-- 设置字符集 -->
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
</appender>
|
||||
|
||||
<!--2. 输出到文档-->
|
||||
<!-- 2.1 level为 DEBUG 日志,时间滚动输出 -->
|
||||
<appender name="DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathwork}/work-log-debug.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <!– 日志归档 –>-->
|
||||
<!-- <fileNamePattern>${logging.pathwork}/work-log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!--<!– <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">–>-->
|
||||
<!--<!– <maxFileSize>100MB</maxFileSize>–>-->
|
||||
<!--<!– </timeBasedFileNamingAndTriggeringPolicy>–>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathwork}/work-log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
|
||||
|
||||
|
||||
<!-- 此日志文档只记录debug级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>debug</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="OPCUA_DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathopc}/opcua-log-debug.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||
</encoder>
|
||||
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathopc}/opcua-log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
|
||||
<!-- 此日志文档只记录debug级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>debug</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="MQ_DEBUG_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathmq}/mq-log-debug.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <!– 日志归档 –>-->
|
||||
<!-- <fileNamePattern>${logging.pathmq}/mq-log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathmq}/mq-log-debug-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文档只记录debug级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>debug</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 2.2 level为 INFO 日志,时间滚动输出 -->
|
||||
<appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathwork}/work-log-info.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <!– 每天日志归档路径以及格式 –>-->
|
||||
<!-- <fileNamePattern>${logging.pathwork}/work-log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathwork}/work-log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文档只记录info级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>info</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="OPCUA_INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathopc}/opcua-log-info.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <!– 每天日志归档路径以及格式 –>-->
|
||||
<!-- <fileNamePattern>${logging.pathopc}/opcua-log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathopc}/opcua-log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文档只记录info级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>info</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
<appender name="MQ_INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathmq}/mq-log-info.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset>
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <!– 每天日志归档路径以及格式 –>-->
|
||||
<!-- <fileNamePattern>${logging.pathmq}/mq-log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathmq}/mq-log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文档只记录info级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>info</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 2.3 level为 WARN 日志,时间滚动输出 -->
|
||||
<appender name="WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathwork}/work-log-warn.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <fileNamePattern>${logging.pathwork}/work-log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathwork}/work-log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文档只记录warn级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>warn</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="OPCUA_WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathopc}/opcua-log-warn.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <fileNamePattern>${logging.pathopc}/opcua-log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathopc}/opcua-log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文档只记录warn级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>warn</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
<appender name="MQ_WARN_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathmq}/mq-log-warn.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <fileNamePattern>${logging.pathmq}/mq-log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathmq}/mq-log-warn-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
<!-- 此日志文档只记录warn级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>warn</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<!-- 2.4 level为 ERROR 日志,时间滚动输出 -->
|
||||
<appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathwork}/work-log-error.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <fileNamePattern>${logging.pathwork}/work-log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathwork}/work-log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
|
||||
<!-- 此日志文档只记录ERROR级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
|
||||
<appender name="OPCUA_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathopc}/opcua-log-error.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <fileNamePattern>${logging.pathopc}/opcua-log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathopc}/opcua-log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
|
||||
<!-- 此日志文档只记录ERROR级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
<appender name="MQ_ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
|
||||
<!-- 正在记录的日志文档的路径及文档名 -->
|
||||
<file>${logging.pathmq}/mq-log-error.log</file>
|
||||
<!--日志文档输出格式-->
|
||||
<encoder>
|
||||
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{50} - %msg%n</pattern>
|
||||
<charset>UTF-8</charset> <!-- 此处设置字符集 -->
|
||||
</encoder>
|
||||
<!-- 日志记录器的滚动策略,按日期,按大小记录 -->
|
||||
<!-- <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">-->
|
||||
<!-- <fileNamePattern>${logging.pathmq}/mq-log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>-->
|
||||
<!-- <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">-->
|
||||
<!-- <maxFileSize>100MB</maxFileSize>-->
|
||||
<!-- </timeBasedFileNamingAndTriggeringPolicy>-->
|
||||
<!-- <!–日志文档保留天数–>-->
|
||||
<!-- <maxHistory>999</maxHistory>-->
|
||||
<!-- </rollingPolicy>-->
|
||||
|
||||
<rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
|
||||
<!-- rollover daily -->
|
||||
<fileNamePattern>${logging.pathmq}/mq-log-error-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
|
||||
<!-- each file should be at most 100MB, keep 60 days worth of history, but at most 20GB -->
|
||||
<maxFileSize>100MB</maxFileSize>
|
||||
<maxHistory>999</maxHistory>
|
||||
<totalSizeCap>200GB</totalSizeCap>
|
||||
</rollingPolicy>
|
||||
|
||||
<!-- 此日志文档只记录ERROR级别的 -->
|
||||
<filter class="ch.qos.logback.classic.filter.LevelFilter">
|
||||
<level>ERROR</level>
|
||||
<onMatch>ACCEPT</onMatch>
|
||||
<onMismatch>DENY</onMismatch>
|
||||
</filter>
|
||||
</appender>
|
||||
<!--
|
||||
<logger>用来设置某一个包或者具体的某一个类的日志打印级别、
|
||||
以及指定<appender>。<logger>仅有一个name属性,
|
||||
一个可选的level和一个可选的addtivity属性。
|
||||
name:用来指定受此logger约束的某一个包或者具体的某一个类。
|
||||
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
|
||||
还有一个特俗值INHERITED或者同义词NULL,代表强制执行上级的级别。
|
||||
如果未设置此属性,那么当前logger将会继承上级的级别。
|
||||
addtivity:是否向上级logger传递打印信息。默认是true。
|
||||
<logger name="org.springframework.web" level="info"/>
|
||||
<logger name="org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor" level="INFO"/>
|
||||
-->
|
||||
|
||||
<!--
|
||||
使用mybatis的时候,sql语句是debug下才会打印,而这里我们只配置了info,所以想要查看sql语句的话,有以下两种操作:
|
||||
第一种把<root level="info">改成<root level="DEBUG">这样就会打印sql,不过这样日志那边会出现很多其他消息
|
||||
第二种就是单独给dao下目录配置debug模式,代码如下,这样配置sql语句会打印,其他还是正常info级别:
|
||||
【logging.level.org.mybatis=debug logging.level.dao=debug】
|
||||
-->
|
||||
|
||||
<!--
|
||||
root节点是必选节点,用来指定最基础的日志输出级别,只有一个level属性
|
||||
level:用来设置打印级别,大小写无关:TRACE, DEBUG, INFO, WARN, ERROR, ALL 和 OFF,
|
||||
不能设置为INHERITED或者同义词NULL。默认是DEBUG
|
||||
可以包含零个或多个元素,标识这个appender将会添加到这个logger。
|
||||
-->
|
||||
|
||||
<!-- name就是包名,这个包下的 所有logger 输出就以下配置 -->
|
||||
<logger name="com.qgs.dc.opcua" additivity="false">
|
||||
<!--使用哪一个Appender-->
|
||||
<appender-ref ref="OPCUA_DEBUG_FILE" />
|
||||
<appender-ref ref="OPCUA_INFO_FILE" />
|
||||
<appender-ref ref="OPCUA_WARN_FILE" />
|
||||
<appender-ref ref="OPCUA_ERROR_FILE" />
|
||||
</logger>
|
||||
|
||||
<logger name="com.qgs.dc.mq" additivity="false">
|
||||
<appender-ref ref="MQ_DEBUG_FILE" />
|
||||
<appender-ref ref="MQ_INFO_FILE" />
|
||||
<appender-ref ref="MQ_WARN_FILE" />
|
||||
<appender-ref ref="MQ_ERROR_FILE" />
|
||||
</logger>
|
||||
|
||||
<root level="info">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="DEBUG_FILE" />
|
||||
<appender-ref ref="INFO_FILE" />
|
||||
<appender-ref ref="WARN_FILE" />
|
||||
<appender-ref ref="ERROR_FILE" />
|
||||
</root>
|
||||
|
||||
<!-- 4.2 生产环境:输出到文档
|
||||
<springProfile name="pro">
|
||||
<root level="info">
|
||||
<appender-ref ref="CONSOLE" />
|
||||
<appender-ref ref="DEBUG_FILE" />
|
||||
<appender-ref ref="INFO_FILE" />
|
||||
<appender-ref ref="ERROR_FILE" />
|
||||
<appender-ref ref="WARN_FILE" />
|
||||
</root>
|
||||
</springProfile> -->
|
||||
</configuration>
|
13
src/test/java/com/qgs/dc/DcApplicationTests.java
Normal file
13
src/test/java/com/qgs/dc/DcApplicationTests.java
Normal file
@ -0,0 +1,13 @@
|
||||
package com.qgs.dc;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
|
||||
@SpringBootTest
|
||||
class DcApplicationTests {
|
||||
|
||||
@Test
|
||||
void contextLoads() {
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user