提交 699b8516 authored 作者: wangqiang's avatar wangqiang

集成mqtt客户端

上级 f5d7b383
HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
*/target/
*/.settings/
.settings
target
### STS ###
.apt_generated
# built application files
*.apk
*.ap_
# Eclipse project files
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
.DS_Store
### IntelliJ IDEA ###
# idea files
.idea
*.iws
*.iml
*.ipr
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
out
bin
# Built application files and Maven
target/
pom.xml.tag
pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
dependency-reduced-pom.xml
buildNumber.properties
.mvn/timing.properties
.pdb
# Compiled class files
*.class
# Log Files
*.log
# About IntelliJ
*.iml
/.idea/
/out/
# BlueJ files
*.ctxt
# Mobile Tools for Java (J2ME)
.mtj.tmp/
# macOS
.DS_Store
# Package Files
#*.jar
#*.war
#*.ear
#*.zip
#*.tar.gz
#*.rar
# CMake
cmake-build-debug/
# File-based project format
*.iws
# mpeltonen/sbt-idea plugin
.idea_modules/
# JIRA plugin
atlassian-ide-plugin.xml
# Crashlytics plugin (for Android Studio and IntelliJ)
com_crashlytics_export_strings.xml
crashlytics.properties
crashlytics-build.properties
fabric.properties
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
#PowderDesigner
*.pdb
*.pjb
*.prj
#IDEA http-client 环境文件
*.env.json
/qz-services/qz-admin/.gitignore
/qz-services/qz-admin/mvnw
/qz-services/qz-admin/mvnw.cmd
/qz-services/qz-admin/.mvn/
/qz-services/qz-pond/.gitignore
/qz-services/qz-pond/mvnw
/qz-services/qz-pond/mvnw.cmd
/qz-services/qz-pond/qz-pond.iml
/qz-services/qz-pond/.mvn/
/qz-services/qz-report/.gitignore
/qz-services/qz-report/mvnw
/qz-services/qz-report/.mvn/
/qz-services/qz-report/mvnw.cmd
/qz-services/qz-report/qz-report.iml
# apq-pc-client
客户端API-SERVER + IOT-CLIENT
# apq-pc-control
客户端硬件监控
# apq-pc-info
客户端PC信息采集器(cpu, memory。。。)
# apq-pc-register
客户端PC软件检测控制器(qq。。。)
<?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.4.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.priusis</groupId>
<artifactId>apq-pc-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>apq-pc-client</name>
<description>apq-pc-client</description>
<properties>
<java.version>1.8</java.version>
<commons-lang3.version>3.4</commons-lang3.version>
<!-- Eclipse Paho 1.1.0 contains major issue with persistence of buffered messages. Using 1.1.1-SNAPSHOT for now. Need to remove this after Paho 1.1.1 release -->
<paho.client.version>1.2.0</paho.client.version>
<json-path.version>2.2.0</json-path.version>
<jsonassert.version>1.5.0</jsonassert.version>
<milo.client.version>0.1.0</milo.client.version>
<moquette.version>0.10</moquette.version>
<netty.version>4.1.22.Final</netty.version>
<jackson.version>2.10.2</jackson.version>
<spring.version>4.3.4.RELEASE</spring.version>
<winsw.version>2.0.1</winsw.version>
<bouncycastle.version>1.52</bouncycastle.version>
<slf4j.version>1.7.7</slf4j.version>
<pkg.name>pi-gateway</pkg.name>
<pkg.user>priusis-iot</pkg.user>
<pkg.unixLogFolder>/var/log/${pkg.name}</pkg.unixLogFolder>
<pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
<pkg.win.dist>${project.build.directory}/windows</pkg.win.dist>
<priusis-iot.version>1.0.0-SNAPSHOT</priusis-iot.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</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>
<dependency>
<groupId>com.priusis</groupId>
<artifactId>netty-mqtt</artifactId>
<version>${priusis-iot.version}</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>${paho.client.version}</version>
</dependency>
<dependency>
<groupId>com.sun.winsw</groupId>
<artifactId>winsw</artifactId>
<version>${winsw.version}</version>
<classifier>bin</classifier>
<type>exe</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>io.moquette</groupId>
<artifactId>moquette-broker</artifactId>
<version>${moquette.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.11</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>${pkg.name}-${project.version}</finalName>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.fortasoft</groupId>
<artifactId>gradle-maven-plugin</artifactId>
<version>1.0.8</version>
</plugin>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>3.0</version>
<configuration>
<header>license-header-template.txt</header>
<properties>
<owner>The PriusisIot Authors</owner>
</properties>
<excludes>
<exclude>**/.env</exclude>
<exclude>**/README</exclude>
<exclude>**/LICENSE</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/banner.txt</exclude>
<exclude>src/test/resources/**</exclude>
<exclude>src/sh/**</exclude>
<exclude>src/main/scripts/control/**</exclude>
<exclude>src/main/scripts/windows/**</exclude>
</excludes>
<mapping>
<conf>SCRIPT_STYLE</conf>
<gradle>JAVADOC_STYLE</gradle>
</mapping>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.sun.winsw</groupId>
<artifactId>winsw</artifactId>
<classifier>bin</classifier>
<type>exe</type>
<destFileName>service.exe</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${pkg.win.dist}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-service-conf</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/conf</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>logback.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/conf</directory>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/unix.properties</filter>
</filters>
</configuration>
</execution>
<execution>
<id>copy-win-conf</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${pkg.win.dist}/conf</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>logback.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/conf</directory>
<excludes>
<exclude>pi-gateway.conf</exclude>
</excludes>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/windows.properties</filter>
</filters>
</configuration>
</execution>
<execution>
<id>copy-control</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/control</outputDirectory>
<resources>
<resource>
<directory>src/main/scripts/control</directory>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/unix.properties</filter>
</filters>
</configuration>
</execution>
<execution>
<id>copy-windows-control</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${pkg.win.dist}</outputDirectory>
<resources>
<resource>
<directory>src/main/scripts/windows</directory>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/windows.properties</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Implementation-Title>PriusisIot Gateway</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>boot</classifier>
<layout>ZIP</layout>
<executable>true</executable>
<excludeDevtools>true</excludeDevtools>
<embeddedLaunchScriptProperties>
<confFolder>${pkg.installFolder}/conf</confFolder>
<logFolder>${pkg.unixLogFolder}</logFolder>
<logFilename>${pkg.name}.out</logFilename>
<initInfoProvides>${pkg.name}</initInfoProvides>
</embeddedLaunchScriptProperties>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.fortasoft</groupId>
<artifactId>gradle-maven-plugin</artifactId>
<configuration>
<tasks>
<task>build</task>
<task>buildDeb</task>
<task>buildRpm</task>
</tasks>
<args>
<arg>-PprojectBuildDir=${project.build.directory}</arg>
<arg>-PprojectVersion=${project.version}</arg>
<arg>-PmainJar=${project.build.directory}/${project.build.finalName}-boot.${project.packaging}
</arg>
<arg>-PpkgName=${pkg.name}</arg>
<arg>-PpkgUser=${pkg.user}</arg>
<arg>-PpkgInstallFolder=${pkg.installFolder}</arg>
<arg>-PpkgLogFolder=${pkg.unixLogFolder}</arg>
</args>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>invoke</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>${pkg.name}</finalName>
<descriptors>
<descriptor>src/main/assembly/windows.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
package com.priusis.client.service;
import com.google.common.collect.Lists;
import com.priusis.client.service.conf.PcConnectionConfiguration;
import com.priusis.client.service.conf.PcPersistenceConfiguration;
import com.priusis.monitor.mqtt.MqttClient;
import com.priusis.monitor.mqtt.MqttConnectResult;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.mqtt.MqttQoS;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.util.Iterator;
import java.util.List;
import java.util.Queue;
import java.util.concurrent.*;
@Slf4j
public class MqttMessageSender implements Runnable {
private MqttClient tbClient;
private PersistentFileService persistentFileService;
private PcPersistenceConfiguration persistence;
private final PcConnectionConfiguration connection;
private BlockingQueue<MessageFuturePair> incomingQueue;
private Queue<Future<Void>> outgoingQueue;
public MqttMessageSender(PcPersistenceConfiguration persistence,
PcConnectionConfiguration connection,
MqttClient tbClient,
PersistentFileService persistentFileService,
BlockingQueue<MessageFuturePair> incomingQueue) {
this.persistence = persistence;
this.connection = connection;
this.tbClient = tbClient;
this.persistentFileService = persistentFileService;
this.incomingQueue = incomingQueue;
outgoingQueue = new ConcurrentLinkedQueue();
}
@Override
public void run() {
while (!Thread.interrupted()) {
try {
checkClientConnected();
List<MqttPersistentMessage> storedMessages = getMessages();
if (!storedMessages.isEmpty()) {
Iterator<MqttPersistentMessage> iter = storedMessages.iterator();
while (iter.hasNext()) {
if (!checkClientConnected()) {
persistentFileService.saveForResend(Lists.newArrayList(iter));
break;
}
MqttPersistentMessage message = iter.next();
log.debug("Sending message [{}]", message);
publishMqttMessage(message);
}
} else {
Thread.sleep(persistence.getPollingInterval());
}
} catch (InterruptedException e) {
log.trace(e.getMessage());
Thread.currentThread().interrupt();
} catch (Throwable e) {
log.error(e.getMessage(), e);
}
}
}
private Future<Void> publishMqttMessage(MqttPersistentMessage message) {
return tbClient.publish(message.getTopic(), Unpooled.wrappedBuffer(message.getPayload()), MqttQoS.AT_MOST_ONCE).addListener(
future -> incomingQueue.put(new MessageFuturePair(future, message))
);
}
private boolean checkClientConnected() {
if (!tbClient.isConnected()) {
try {
clearOutgoingQueue();
log.info("Priusisiot MQTT connection failed. Reconnecting in [{}] milliseconds", connection.getRetryInterval());
Thread.sleep(connection.getRetryInterval());
log.info("Attempting to reconnect to Priusisiot.");
MqttConnectResult result = tbClient.reconnect().get(connection.getConnectionTimeout(), TimeUnit.MILLISECONDS);
if (result.isSuccess()) {
log.info("Successfully reconnected to Priusisiot.");
}
} catch (TimeoutException e) {
log.trace(e.getMessage(), e);
} catch (Exception e) {
log.error(e.getMessage(), e);
}
return false;
}
return true;
}
private void clearOutgoingQueue() {
outgoingQueue.forEach(future -> {
try {
future.cancel(true);
} catch (CancellationException e) {
log.warn("Failed to cancel outgoing message on disconnected client. Reason: " + e.getMessage(), e);
}
});
outgoingQueue.clear();
}
private List<MqttPersistentMessage> getMessages() {
try {
List<MqttPersistentMessage> resendMessages = persistentFileService.getResendMessages();
if (!resendMessages.isEmpty()) {
return resendMessages;
} else {
return persistentFileService.getPersistentMessages();
}
} catch (IOException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
}
package com.priusis.client.service.core;
import com.priusis.client.data.kv.KvEntry;
import com.priusis.client.service.MqttDeliveryFuture;
import com.priusis.client.service.MqttRpcDataMessage;
import com.priusis.client.service.conf.PcExtensionConfiguration;
import com.priusis.client.service.data.AttributeRequest;
import com.priusis.client.service.data.AttributeResponse;
import com.priusis.client.service.data.AttributesUpdateSubscription;
import com.priusis.client.service.data.RpcCommandResponse;
import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.function.Consumer;
/**
* Created by priusis on 16.01.17.
*/
public interface MqttService {
void init() throws Exception;
void destroy() throws Exception;
String getTenantLabel();
/**
* Report device attributes change to Priusisiot
*
* @param attributes - the attribute values list
*/
MqttDeliveryFuture onDeviceAttributesUpdate(List<KvEntry> attributes);
/**
* Report attributes request to Priusisiot
*
* @param attributeRequest - attributes request
* @param listener - attributes response
*/
void onDeviceAttributeRequest(AttributeRequest attributeRequest, Consumer<AttributeResponse> listener);
/**
* Report response from device to the server-side RPC call from Priusisiot
*
* @param response - the device response to RPC call
*/
void onDeviceRpcResponse(RpcCommandResponse response);
/**
* Subscribe to attribute updates from Priusisiot
*
* @param subscription - the subscription
* @return true if successful, false if already subscribed
*/
boolean subscribe(AttributesUpdateSubscription subscription);
/**
* Unsubscribe to attribute updates from Priusisiot
*
* @param subscription - the subscription
* @return true if successful, false if already unsubscribed
*/
boolean unsubscribe(AttributesUpdateSubscription subscription);
/**
* Report generic error from one of gateway components
*
* @param e - the error
*/
void onError(Exception e);
/**
* Report error related to device
*
* @param deviceName - the device name
* @param e - the error
*/
void onError(String deviceName, Exception e);
/**
* Report applied configuration
*
* @param configuration - extension configuration
*/
void onAppliedConfiguration(String configuration);
/**
* Report extension configuration error
*
* @param e - the error
* @param configuration - extension configuration
*/
void onConfigurationError(Exception e, PcExtensionConfiguration configuration);
/**
* Report extension configuration status
*
* @param id - extension id
* @param status - extension status
*/
void onConfigurationStatus(String id, String status);
/**
* rpc请求落文件
*
* @param mqttRpcDataMessage
* @return
* @throws IOException
*/
File flushRpcDataToFile(MqttRpcDataMessage mqttRpcDataMessage) throws IOException;
/**
* 读取
*
* @param method
* @return
* @throws IOException
*/
MqttRpcDataMessage readFromFile(String method) throws IOException;
}
package com.priusis.client.service.core;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ObjectNode;
import com.google.common.io.Resources;
import com.priusis.client.data.kv.*;
import com.priusis.client.service.*;
import com.priusis.client.service.conf.*;
import com.priusis.client.service.data.*;
import com.priusis.client.util.JsonTools;
import com.priusis.monitor.mqtt.*;
import io.netty.buffer.ByteBuf;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
import io.netty.util.concurrent.Promise;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.PostConstruct;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManagerFactory;
import java.io.*;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.security.KeyStore;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.stream.Collectors;
import static com.priusis.client.util.JsonTools.*;
/**
* Created by priusis on 16.01.17.
*/
@Slf4j
public class MqttServiceImpl implements MqttService, MqttHandler, MqttClientCallback {
//private static final String GATEWAY_RPC_TOPIC = "gateway/rpc";
//private static final String GATEWAY_ATTRIBUTES_TOPIC = "gateway/attrs";
//private static final String GATEWAY_TELEMETRY_TOPIC = "gateway/telemetry";
//private static final String GATEWAY_REQUESTS_ATTRIBUTES_TOPIC = "gateway/attrs/req";
//private static final String GATEWAY_RESPONSES_ATTRIBUTES_TOPIC = "gateway/attrs/res";
//private static final String GATEWAY_CONNECT_TOPIC = "gateway/connect";
//private static final String GATEWAY_DISCONNECT_TOPIC = "gateway/disconnect";
//private static final String GATEWAY = "GATEWAY";
private static final String DEVICE_TELEMETRY_TOPIC = "devices/telemetry";
private static final String DEVICE_ATTRIBUTES_TOPIC = "devices/attrs";
private static final String DEVICE_RPC_TOPIC = "devices/rpc";
private static final String DEVICE_GET_ATTRIBUTES_REQUEST_TOPIC = "devices/attrs/req/1";
private static final String DEVICE_GET_ATTRIBUTES_RESPONSE_PLUS_TOPIC = "devices/attrs/res/+";
private static final String DEVICE_GET_ATTRIBUTES_RESPONSE_TOPIC = "devices/attrs/res/1";
private static final String JKS = "JKS";
private static final long DEFAULT_CONNECTION_TIMEOUT = 10000;
private static final long DEFAULT_POLLING_INTERVAL = 1000;
private final ConcurrentMap<String, DeviceInfo> devices = new ConcurrentHashMap<>();
private final AtomicLong attributesCount = new AtomicLong();
private final AtomicLong telemetryCount = new AtomicLong();
private final AtomicInteger msgIdSeq = new AtomicInteger();
private final Set<AttributesUpdateSubscription> attributeUpdateSubs = ConcurrentHashMap.newKeySet();
private final Map<AttributeRequestKey, AttributeRequestListener> pendingAttrRequestsMap = new ConcurrentHashMap<>();
private String tenantLabel;
private PersistentFileService persistentFileService;
private Consumer<String> extensionsConfigListener;
private PcCoreConfiguration configuration;
private PcConnectionConfiguration connection;
private PcReportingConfiguration reporting;
private PcPersistenceConfiguration persistence;
private volatile ObjectNode error;
private MqttClient tbClient;
private ScheduledExecutorService scheduler;
private ExecutorService mqttSenderExecutor;
private ExecutorService mqttReceiverExecutor;
private ExecutorService callbackExecutor = Executors.newCachedThreadPool();
@Autowired
private NioEventLoopGroup nioEventLoopGroup;
public MqttServiceImpl(PcCoreConfiguration configuration, Consumer<String> extensionsConfigListener) {
this.configuration = configuration;
this.extensionsConfigListener = extensionsConfigListener;
}
@Override
@PostConstruct
public void init() {
BlockingQueue<MessageFuturePair> incomingQueue = new LinkedBlockingQueue<>();
this.tenantLabel = configuration.getLabel();
this.connection = configuration.getConnection();
this.reporting = configuration.getReporting();
this.persistence = configuration.getPersistence();
this.tenantLabel = configuration.getLabel();
initTimeouts();
initMqttClient();
initMqttSender(incomingQueue);
initMqttReceiver(incomingQueue);
scheduler = Executors.newSingleThreadScheduledExecutor();
scheduler.scheduleAtFixedRate(this::reportStats, 0, reporting.getInterval(), TimeUnit.MILLISECONDS);
}
private void initTimeouts() {
// Backwards compatibility with old config file
if (connection.getConnectionTimeout() == 0) {
connection.setConnectionTimeout(DEFAULT_CONNECTION_TIMEOUT);
}
if (persistence.getPollingInterval() == 0) {
persistence.setPollingInterval(DEFAULT_POLLING_INTERVAL);
}
}
@Override
public void destroy() throws Exception {
scheduler.shutdownNow();
callbackExecutor.shutdownNow();
mqttSenderExecutor.shutdownNow();
mqttReceiverExecutor.shutdownNow();
tbClient.disconnect();
}
@Override
public String getTenantLabel() {
return tenantLabel;
}
@Override
public MqttDeliveryFuture onDeviceAttributesUpdate(List<KvEntry> attributes) {
final int msgId = msgIdSeq.incrementAndGet();
log.trace("[{}] Updating device attributes: {}", msgId, attributes);
ObjectNode node = newNode();
//ObjectNode deviceNode = node.putObject(deviceName);
attributes.forEach(kv -> putToNode(node, kv));
final int packSize = attributes.size();
return persistMessage(DEVICE_ATTRIBUTES_TOPIC, msgId, toNodeBytes(node),
message -> {
log.debug("[{}] Device attributes were delivered!", msgId);
attributesCount.addAndGet(packSize);
},
error -> log.warn("[{}] Failed to report device attributes!", msgId, error));
}
private MqttDeliveryFuture persistMessage(String topic,
int msgId,
byte[] payload,
Consumer<Void> onSuccess,
Consumer<Throwable> onFailure) {
try {
return persistentFileService.persistMessage(topic, msgId, payload, onSuccess, onFailure);
} catch (Throwable e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
@Override
public void onDeviceAttributeRequest(AttributeRequest request, Consumer<AttributeResponse> listener) {
final int msgId = msgIdSeq.incrementAndGet();
String deviceName = request.getDeviceName();
AttributeRequestKey requestKey = new AttributeRequestKey(request.getRequestId(), request.getDeviceName());
log.trace("[{}][{}] Requesting {} attribute: {}", deviceName, msgId, request.isClientScope() ? "client" : "shared", request.getAttributeKey());
ObjectNode node = newNode();
node.put("id", request.getRequestId());
node.put("client", request.isClientScope());
node.put("device", request.getDeviceName());
node.put("key", request.getAttributeKey());
MqttMessage msg = new MqttMessage(toBytes(node));
msg.setId(msgId);
pendingAttrRequestsMap.put(requestKey, new AttributeRequestListener(request, listener));
persistMessage(DEVICE_GET_ATTRIBUTES_REQUEST_TOPIC, msgId, toBytes(node),
message -> {
log.debug("[{}] Device attributes request was delivered!", msgId);
},
error -> {
log.warn("[{}] Failed to report device attributes!", msgId, error);
pendingAttrRequestsMap.remove(requestKey);
});
}
@Override
public void onDeviceRpcResponse(RpcCommandResponse response) {
final int msgId = msgIdSeq.incrementAndGet();
int requestId = response.getRequestId();
String data = response.getData();
ObjectNode node = newNode();
node.put("id", requestId);
node.put("data", data);
persistMessage(DEVICE_RPC_TOPIC, msgId, toBytes(node),
token -> {
log.debug("[{}] RPC response from device was delivered!", requestId);
},
error -> {
log.warn("[{}] Failed to report RPC response from device!", requestId, error);
});
}
@Override
public boolean subscribe(AttributesUpdateSubscription subscription) {
return subscribe(attributeUpdateSubs::add, subscription);
}
@Override
public boolean unsubscribe(AttributesUpdateSubscription subscription) {
return unsubscribe(attributeUpdateSubs::remove, subscription);
}
@Override
public void onError(Exception e) {
onError(null, e);
}
@Override
public void onError(String deviceName, Exception e) {
ObjectNode node = newNode();
node.put("ts", System.currentTimeMillis());
if (deviceName != null) {
node.put("device", deviceName);
}
node.put("error", toString(e));
error = node;
}
private void reportStats() {
try {
ObjectNode node = newNode();
node.put("ts", System.currentTimeMillis());
ObjectNode valuesNode = node.putObject("values");
valuesNode.put("devicesOnline", devices.size());
valuesNode.put("attributesUploaded", attributesCount.getAndSet(0));
valuesNode.put("telemetryUploaded", telemetryCount.getAndSet(0));
if (error != null) {
valuesNode.put("latestError", JsonTools.toString(error));
error = null;
}
persistMessage(DEVICE_TELEMETRY_TOPIC, msgIdSeq.incrementAndGet(), toBytes(node),
token -> log.info("Gateway statistics {} reported!", node),
error -> log.warn("Failed to report gateway statistics!", error));
} catch (Throwable e) {
log.error("Failed to persist statistics message!", e);
}
}
@Override
public void onMessage(String topic, ByteBuf payload) {
String message = payload.toString(StandardCharsets.UTF_8);
log.trace("Message arrived [{}] {}", topic, message);
callbackExecutor.submit(() -> {
try {
if (topic.equals(DEVICE_ATTRIBUTES_TOPIC)) {
onAttributesUpdate(message);
} else if (topic.equals(DEVICE_GET_ATTRIBUTES_RESPONSE_PLUS_TOPIC)) {
onDeviceAttributesResponse(message);
} else if (topic.equals(DEVICE_RPC_TOPIC)) {
onRpcCommand(message);
} else if (topic.equals(DEVICE_ATTRIBUTES_TOPIC)) {
onGatewayAttributesUpdate(message);
} else if (topic.equals(DEVICE_GET_ATTRIBUTES_RESPONSE_TOPIC)) {
onGatewayAttributesGet(message);
}
} catch (Exception e) {
log.warn("Failed to process arrived message!", message);
}
});
}
@Override
public void connectionLost(Throwable throwable) {
log.warn("Lost connection to Priusisiot.");
pendingAttrRequestsMap.clear();
devices.clear();
}
@Override
public void onSuccessfulReconnect() {
}
private void onAttributesUpdate(String message) {
JsonNode payload = fromString(message);
String deviceName = payload.get("device").asText();
Set<AttributesUpdateListener> listeners = attributeUpdateSubs.stream()
.filter(sub -> sub.matches(deviceName)).map(sub -> sub.getListener())
.collect(Collectors.toSet());
if (!listeners.isEmpty()) {
JsonNode data = payload.get("data");
List<KvEntry> attributes = getKvEntries(data);
listeners.forEach(listener -> callbackExecutor.submit(() -> {
try {
listener.onAttributesUpdated(deviceName, attributes);
} catch (Exception e) {
log.error("[{}] Failed to process attributes update", deviceName, e);
}
}));
}
}
private void onRpcCommand(String message) {
JsonNode payload = fromString(message);
MqttRpcDataMessage mqttRpcDataMessage = MqttRpcDataMessage.builder().requestId(payload.get("id").asInt())
.method(payload.get("method").asText()).params(payload.get("params").asText()).build();
// 存储rpc下发的数据
try {
persistentFileService.flushRpcDataToFile(mqttRpcDataMessage);
} catch (IOException e) {
log.error("Failed to process rpc command persistent : {}", message);
}
}
private void onGatewayAttributesGet(String message) {
log.info("Configuration arrived! {}", message);
JsonNode payload = fromString(message);
if (payload.get("shared").get("configuration") != null) {
String configuration = payload.get("shared").get("configuration").asText();
if (!StringUtils.isEmpty(configuration)) {
updateConfiguration(configuration);
}
}
}
private void onGatewayAttributesUpdate(String message) {
log.info("Configuration updates arrived! {}", message);
JsonNode payload = fromString(message);
if (payload.has("configuration")) {
String configuration = payload.get("configuration").asText();
if (!StringUtils.isEmpty(configuration)) {
updateConfiguration(configuration);
}
}
}
private void updateConfiguration(String configuration) {
try {
if (extensionsConfigListener != null) {
extensionsConfigListener.accept(configuration);
}
onAppliedConfiguration(configuration);
} catch (Exception e) {
log.warn("Failed to update extension configurations [[]]", e.getMessage(), e);
}
}
@Override
public void onAppliedConfiguration(String configuration) {
byte[] msgData = toBytes(newNode().put("appliedConfiguration", configuration));
persistMessage(DEVICE_ATTRIBUTES_TOPIC, msgIdSeq.incrementAndGet(), msgData, null,
error ->
log.warn("Could not publish applied configuration", error));
}
@Override
public void onConfigurationError(Exception e, PcExtensionConfiguration configuration) {
String id = configuration.getId();
byte[] msgDataError = toBytes(newNode().put(id + "ExtensionError", toString(e)));
persistMessage(DEVICE_TELEMETRY_TOPIC, msgIdSeq.incrementAndGet(), msgDataError, null,
error -> log.warn("Could not report extension error", error));
byte[] msgDataStatus = toBytes(newNode().put(id + "ExtensionStatus", "Failure"));
persistMessage(DEVICE_TELEMETRY_TOPIC, msgIdSeq.incrementAndGet(), msgDataStatus, null,
error -> log.warn("Could not report extension error status", error));
}
@Override
public void onConfigurationStatus(String id, String status) {
byte[] extentionStatusData = toBytes(newNode().put(id + "ExtensionStatus", status));
persistMessage(DEVICE_TELEMETRY_TOPIC, msgIdSeq.incrementAndGet(), extentionStatusData,
message -> log.info("Reported status [{}] of extension [{}]", status, id),
error -> log.warn("Extension status reporting failed", error));
byte[] extentionErrorData = toBytes(newNode().put(id + "ExtensionError", ""));
persistMessage(DEVICE_TELEMETRY_TOPIC, msgIdSeq.incrementAndGet(), extentionErrorData,
null, error ->
log.warn("Extension error clearing failed", error));
}
@Override
public File flushRpcDataToFile(MqttRpcDataMessage mqttRpcDataMessage) throws IOException {
return persistentFileService.flushRpcDataToFile(mqttRpcDataMessage);
}
@Override
public MqttRpcDataMessage readFromFile(String method) throws IOException {
return persistentFileService.readFromFile(method);
}
private void onDeviceAttributesResponse(String message) {
JsonNode payload = fromString(message);
AttributeRequestKey requestKey = new AttributeRequestKey(payload.get("id").asInt(), payload.get("device").asText());
AttributeRequestListener listener = pendingAttrRequestsMap.get(requestKey);
if (listener == null) {
log.warn("[{}][{}] Can't find listener for request", requestKey.getDeviceName(), requestKey.getRequestId());
return;
}
AttributeRequest request = listener.getRequest();
AttributeResponse.AttributeResponseBuilder response = AttributeResponse.builder();
response.requestId(request.getRequestId());
response.deviceName(request.getDeviceName());
response.key(request.getAttributeKey());
response.clientScope(request.isClientScope());
response.topicExpression(request.getTopicExpression());
response.valueExpression(request.getValueExpression());
String key = listener.getRequest().getAttributeKey();
JsonNode value = payload.get("value");
if (value == null) {
response.data(Optional.empty());
} else if (value.isBoolean()) {
response.data(Optional.of(new BooleanDataEntry(key, value.asBoolean())));
} else if (value.canConvertToLong()) {
response.data(Optional.of(new LongDataEntry(key, value.asLong())));
} else if (value.isDouble()) {
response.data(Optional.of(new DoubleDataEntry(key, value.asDouble())));
} else {
response.data(Optional.of(new StringDataEntry(key, value.asText())));
}
callbackExecutor.submit(() -> {
try {
listener.getListener().accept(response.build());
} catch (Exception e) {
log.error("[{}][{}] Failed to process attributes response", requestKey.getDeviceName(), requestKey.getRequestId(), e);
}
});
}
private void initMqttSender(BlockingQueue<MessageFuturePair> incomingQueue) {
mqttSenderExecutor = Executors.newSingleThreadExecutor();
mqttSenderExecutor.submit(new MqttMessageSender(persistence, connection, tbClient, persistentFileService, incomingQueue));
}
private void initMqttReceiver(BlockingQueue<MessageFuturePair> incomingQueue) {
mqttReceiverExecutor = Executors.newSingleThreadExecutor();
mqttReceiverExecutor.submit(new MqttMessageReceiver(persistentFileService, incomingQueue, connection.getIncomingQueueWarningThreshold()));
}
private static String toString(Exception e) {
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
return sw.toString();
}
private <T> boolean subscribe(Function<T, Boolean> f, T sub) {
if (f.apply(sub)) {
log.info("Subscription added: {}", sub);
return true;
} else {
log.warn("Subscription was already added: {}", sub);
return false;
}
}
private <T> boolean unsubscribe(Function<T, Boolean> f, T sub) {
if (f.apply(sub)) {
log.info("Subscription removed: {}", sub);
return true;
} else {
log.warn("Subscription was already removed: {}", sub);
return false;
}
}
private MqttClient initMqttClient() {
try {
MqttClientConfig mqttClientConfig = getMqttClientConfig();
mqttClientConfig.setUsername(connection.getSecurity().getAccessToken());
tbClient = MqttClient.create(mqttClientConfig, this);
tbClient.setCallback(this);
tbClient.setEventLoop(nioEventLoopGroup);
connectTbClient();
tbClient.on(DEVICE_ATTRIBUTES_TOPIC, this).await(connection.getConnectionTimeout(), TimeUnit.MILLISECONDS);
tbClient.on(DEVICE_GET_ATTRIBUTES_RESPONSE_PLUS_TOPIC, this).await(connection.getConnectionTimeout(), TimeUnit.MILLISECONDS);
tbClient.on(DEVICE_GET_ATTRIBUTES_RESPONSE_TOPIC, this).await(connection.getConnectionTimeout(), TimeUnit.MILLISECONDS);
tbClient.on(DEVICE_RPC_TOPIC, this).await(connection.getConnectionTimeout(), TimeUnit.MILLISECONDS);
byte[] msgData = toBytes(newNode().put("sharedKeys", "configuration"));
persistMessage(DEVICE_GET_ATTRIBUTES_REQUEST_TOPIC, msgIdSeq.incrementAndGet(), msgData,
null,
error -> log.warn("Error getiing attributes", error));
return tbClient;
} catch (InterruptedException e) {
log.error(e.getMessage(), e);
Thread.currentThread().interrupt();
return null;
} catch (ExecutionException e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
private void connectTbClient() throws InterruptedException, ExecutionException {
Promise<MqttConnectResult> connectResult = (Promise<MqttConnectResult>) tbClient.connect(connection.getHost(), connection.getPort());
connectResult.addListener(future -> {
if (future.isSuccess()) {
MqttConnectResult result = (MqttConnectResult) future.getNow();
log.debug("Gateway connect result code: [{}]", result.getReturnCode());
} else {
log.error("Unable to connect to mqtt server!");
if (future.cause() != null) {
log.error(future.cause().getMessage(), future.cause());
}
}
});
try {
connectResult.get(connection.getConnectionTimeout(), TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
log.error("Unable to connect to mqtt server try again!");
String message = "Unable to connect to Priusisiot. Connection timed out after [" + connection.getConnectionTimeout() + "] milliseconds";
log.error(message, e);
Thread.sleep(connection.getRetryInterval());
connectTbClient();
}
}
private MqttClientConfig getMqttClientConfig() {
MqttClientConfig mqttClientConfig;
if (!StringUtils.isEmpty(connection.getSecurity().getAccessToken())) {
if (StringUtils.isEmpty(connection.getSecurity().getTruststore())) {
mqttClientConfig = new MqttClientConfig();
mqttClientConfig.setUsername(connection.getSecurity().getAccessToken());
} else {
try {
SslContext sslCtx = initOneWaySslContext(connection.getSecurity());
mqttClientConfig = new MqttClientConfig(sslCtx);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
} else {
try {
SslContext sslCtx = initTwoWaySslContext(connection.getSecurity());
mqttClientConfig = new MqttClientConfig(sslCtx);
} catch (Exception e) {
log.error(e.getMessage(), e);
throw new RuntimeException(e);
}
}
return mqttClientConfig;
}
private SslContext initOneWaySslContext(MqttClientSecurityConfiguration configuration) throws Exception {
URL tsUrl = Resources.getResource(configuration.getTruststore());
File tsFile = new File(tsUrl.toURI());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore trustStore = KeyStore.getInstance(JKS);
try (InputStream tsFileInputStream = new FileInputStream(tsFile)) {
trustStore.load(tsFileInputStream, configuration.getTruststorePassword().toCharArray());
}
tmf.init(trustStore);
return SslContextBuilder.forClient().trustManager(tmf).build();
}
private SslContext initTwoWaySslContext(MqttClientSecurityConfiguration configuration) throws Exception {
URL ksUrl = Resources.getResource(configuration.getKeystore());
File ksFile = new File(ksUrl.toURI());
URL tsUrl = Resources.getResource(configuration.getTruststore());
File tsFile = new File(tsUrl.toURI());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
KeyStore trustStore = KeyStore.getInstance(JKS);
try (InputStream tsFileInputStream = new FileInputStream(tsFile)) {
trustStore.load(tsFileInputStream, configuration.getTruststorePassword().toCharArray());
}
tmf.init(trustStore);
KeyStore keyStore = KeyStore.getInstance(JKS);
try (InputStream ksFileInputStream = new FileInputStream(ksFile)) {
keyStore.load(ksFileInputStream, configuration.getKeystorePassword().toCharArray());
}
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(keyStore, configuration.getKeystorePassword().toCharArray());
return SslContextBuilder.forClient().keyManager(kmf).trustManager(tmf).build();
}
public void setPersistentFileService(PersistentFileService persistentFileService) {
this.persistentFileService = persistentFileService;
}
}
package com.priusis.client.service.data;
import com.priusis.client.data.kv.KvEntry;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import java.util.List;
/**
* Created by priusis on 23.01.17.
*/
@Data
@AllArgsConstructor
@RequiredArgsConstructor
public class DeviceData {
private final List<KvEntry> attributes;
private int timeout;
}
package com.priusis.client.util.converter;
import com.fasterxml.jackson.databind.JsonNode;
import com.priusis.client.data.kv.KvEntry;
import com.priusis.client.service.data.DeviceData;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.List;
import java.util.concurrent.ConcurrentHashMap;
import static com.priusis.client.util.JsonTools.fromString;
import static com.priusis.client.util.JsonTools.getKvEntries;
/**
* Created by priusis on 15.05.17.
*/
@Data
@Slf4j
public class BasicJsonConverter{
protected String filterExpression;
protected String deviceNameJsonExpression;
protected String deviceTypeJsonExpression;
private ConcurrentHashMap<String, SimpleDateFormat> formatters = new ConcurrentHashMap<>();
public DeviceData parseBody(String body) {
try {
JsonNode payload = fromString(body);
return parseDeviceData(payload);
} catch (Exception e) {
log.error("Exception occurred while parsing json request body [{}]", body, e);
throw new RuntimeException(e);
}
}
protected DeviceData parseDeviceData(JsonNode payload) throws ParseException {
//long ts = System.currentTimeMillis();
List<KvEntry> attrData = getKvEntries(payload);
return new DeviceData(attrData);
}
}
<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.priusis</groupId>
<artifactId>apq-pc-control</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<junit.version>4.12</junit.version>
<lombok.version>1.16.18</lombok.version>
<jna.version>3.0.9</jna.version>
</properties>
<dependencies>
<!-- web组件 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.0.RELEASE</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>${lombok.version}</version>
</dependency>
<dependency>
<groupId>com.sun.jna</groupId>
<artifactId>jna</artifactId>
<version>${jna.version}</version>
</dependency>
</dependencies>
</project>
\ No newline at end of file
package com;
import com.priusis.utils.ICQrDecode;
import com.priusis.utils.IHwPortController;
import com.zy.QrDecode.CQrDecode;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class TestDemo {
//static String qrString = "0000000D920A7111688CEDA9D7E27F2AE7C98D2E";
static String qrString = "0000000D9BBC6C567944AF514A1AD0A252491B99";
public static void main2(String[] args) {
String path = CQrDecode.parseAbsolutePath("/qr/dat/", "smart-property/0000000d.dat");
int[] result = new int[4];
CQrDecode qrInstance = new CQrDecode();
int ret = qrInstance.ZOOYAPI_GetCodeII(path + "0000000d.dat", qrString, result);
log.info("ret:{}", ret);
log.info("卡号 " + Integer.toHexString(result[0]));
log.info("校验码 " + Integer.toString(result[1]));
log.info("*********************************");
}
public static void main(String[] args) {
/*String path = CQrDecode.parseAbsolutePath("/qr/dat/", "smart-property/0000000d.dat");
int[] result = new int[4];
int ret2 = ICQrDecode.instanceDll.hello(path + "0000000d.dat");
log.info("ret:{}", ret2);
int ret = ICQrDecode.instanceDll.ZOOYAPI_GetCodeII(path + "0000000d.dat", qrString, result);
log.info("ret:{}", ret);
log.info("卡号 " + Integer.toHexString(result[0]));
log.info("校验码 " + Integer.toString(result[1]));
log.info("*********************************");*/
// 初始化硬件接口管理模块
int result = IHwPortController.instanceDll.APQ_HWPORT_Initialize();
log.info("APQ_HWPORT_Initialize ret:{}", result);
// 获取普通设备权限
int result31 = IHwPortController.instanceDll.APQ_HWPORT_get_normal_device_permit(4);
log.info("APQ_HWPORT_get_normal_device_permit ret:{}", result31);
// 设置普通设备权限
int result32 = IHwPortController.instanceDll.APQ_HWPORT_set_normal_device_permit(4, 1, null);
log.info("APQ_HWPORT_set_normal_device_permit ret:{}", result32);
// 应用硬件接口管理模块的配置内容
int result5 = IHwPortController.instanceDll.APQ_HWPORT_Apply();
log.info("APQ_HWPORT_Apply ret:{}", result5);
// 再次获取普通设备权限,验证
int result33 = IHwPortController.instanceDll.APQ_HWPORT_get_normal_device_permit(4);
log.info("Check APQ_HWPORT_get_normal_device_permit ret:{}", result33);
// 获取网络设备权限
//int speed = 0;
//int result4 = IHwPortController.instanceDll.APQ_HWPORT_get_net_device_permit(0, speed);
//log.info("APQ_HWPORT_get_net_device_permit ret:{}, speed:{}", result4, speed);
// 清理硬件接口管理模块
int result2 = IHwPortController.instanceDll.APQ_HWPORT_Uninitialize();
log.info("APQ_HWPORT_Uninitialize ret:{}", result2);
}
}
package com.priusis.exception;
import lombok.Getter;
/**
* @author yangli
* @since 20/10/16
*/
@Getter
public class ServiceException extends RuntimeException {
private final int code;
public ServiceException(String msg) {
this(500, msg);
}
public ServiceException(int code, String msg) {
super(msg);
this.code = code;
}
}
package com.priusis.utils;
import com.sun.jna.Library;
import com.sun.jna.Native;
import com.sun.jna.Platform;
public interface ICQrDecode extends Library {
ICQrDecode INSTANCE = (ICQrDecode) Native.loadLibrary((Platform.isWindows() ? "msvcrt" : "c"), ICQrDecode.class);
void printf(String format, Object... args);
ICQrDecode instanceDll = (ICQrDecode) Native.loadLibrary("D:\\work\\priusis\\priusis-iot\\apq-iot\\apq-client\\apq-pc-control\\src\\main\\resources\\QrDecode.dll", ICQrDecode.class);
public int hello(String str);
public int ZOOYAPI_GetCode(String path, String qrString, int[] result);
public int ZOOYAPI_GetCodeII(String path, String qrString, int[] result);
}
package com.priusis.utils;
import com.sun.jna.Library;
import com.sun.jna.Native;
/******************************************************************************************************************************
* 调用流程举例:
*
* // 定义回调函数
* void device_change_cb_fn(int changeType, char *devInfoBuf)
* {
* printf("=== get cb type=%d, data=[%s]\r\n", changeType, devInfoBuf);
* }
*
*
* // --- 1. 初始化 ---
* // 初始化接口
* APQ_HWPORT_Initialize()
*
* // 注册设备热插拔通知后,接收热插拔事件
* APQ_HWPORT_Register_Device_Notification(device_change_cb_fn)
*
* // --- 2. 权限操作 ---
* // 可选:获取某个硬件接口权限
* APQ_HWPORT_get_normal_device_permit()
*
* // 设置某硬件接口权限
* APQ_HWPORT_set_normal_device_permit()
* APQ_HWPORT_set_storage_device_permit()
* // 设置网络限速,将启动限速线程
* APQ_HWPORT_set_net_device_permit(APQ_HWPORT_NET_DEVID_ETH_CARD, APQ_HWPORT_NET_PERM_LIMIT, 0, NULL);
* // 应用配置
* APQ_HWPORT_Apply()
*
* // 解除网络限速,清理限速线程
* APQ_HWPORT_set_net_device_permit(APQ_HWPORT_NET_DEVID_ETH_CARD, APQ_HWPORT_NET_PERM_NO_LIMIT, 0, NULL);
* // 应用配置
* APQ_HWPORT_Apply()
*
* // --- 3. 清理资源 ---
* // 停止监听并释放资源
* APQ_HWPORT_Unregister_Device_Notification()
*
* // 清理资源
* APQ_HWPORT_Uninitialize()
*
******************************************************************************************************************************/
public interface IHwPortController extends Library {
IHwPortController instanceDll = (IHwPortController) Native.loadLibrary("D:\\work\\priusis\\priusis-iot\\apq-iot\\apq-client\\apq-pc-control\\src\\main\\resources\\x64\\Release\\HwPortController.dll", IHwPortController.class);
/**
* 初始化硬件接口管理模块
* 备 注:调用其他接口前必须调用一次此接口初始化资源
*
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
int APQ_HWPORT_Initialize();
/**
* 应用硬件接口管理模块的配置内容
* 备 注:调用完成此接口后,设置才会生效
*
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
int APQ_HWPORT_Apply();
/**
* 清理硬件接口管理模块
* 备 注:最后必须调用此函数清理资源
*
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
int APQ_HWPORT_Uninitialize();
/**
* 获取普通设备权限
*
* @param device_id 指定普通设备硬件接口类型 {@link HwportNormalDevidEnum}
* @return 返回 {@link HwportNormalPermEnum} 权限类型
*/
int APQ_HWPORT_get_normal_device_permit(int device_id);
/**
* 设置普通设备权限
*
* @param device_id 枚举类型设备ID号 {@link HwportNormalDevidEnum}
* @param perm 普通类权限 {@link HwportNormalPermEnum}
* @param data 预留参数字串,未明确的传NULL
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
int APQ_HWPORT_set_normal_device_permit(int device_id, int perm, char[] data);
/**
* 获取可移动存储设备权限
*
* @param device_id 指定可移动存储设备硬件接口类型 {@link HwportStorageDevidEnum}
* @return 返回 {@link HwportStoragePermEnum} 权限类型
*/
int APQ_HWPORT_get_storage_device_permit(int device_id);
/**
* 设置可移动存储设备权限
*
* @param device_id 枚举类型设备ID号 {@link HwportStorageDevidEnum}
* @param perm 存储类权限 {@link HwportStoragePermEnum}
* @param data 预留参数字串,未明确的传NULL
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
int APQ_HWPORT_set_storage_device_permit(int device_id, int perm, char[] data);
/**
* 获取网络设备权限
*
* @param device_id 指定网络设备硬件接口类型 {@link HwportNetDevidEnum}
* @return 返回存放配置内的带宽限速值 {@link HwportNetPermEnum} 权限类型
*/
int APQ_HWPORT_get_net_device_permit(int device_id, int speed);
/**
* 设置网络设备权限
* 设置限速选项会启动限速线程,退出程序时需要调用APQ_HWPORT_NET_PERM_NO_LIMIT或者其他不限速的权限清理限速线程
*
* @param device_id 枚举类型设备ID号 {@link HwportNetDevidEnum}
* @param perm 存储类权限 {@link HwportNetPermEnum}
* @param speed 带宽限制值,单位KB/s
* @param data 预留参数字串,未明确的传NULL
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
int APQ_HWPORT_set_net_device_permit(int device_id, int perm, int speed, char[] data);
/**
* 注册设备热插拔通知(如USB设备)
* 备 注:不使用时,需要调用 APQ_HWPORT_Unregister_Device_Notification 停止监听并释放资源
*
* @param P_DEVICE_CHANGE_CB callback_fn: 指定事件发生时的回调函数
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
//int APQ_HWPORT_Register_Device_Notification(IN P_DEVICE_CHANGE_CB callback_fn)
/**
* 停止监听并释放设备热插拔通知相关资源
*
* @return 成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值 {@link HwportResultEnum}
*/
int APQ_HWPORT_Unregister_Device_Notification();
/**
* 根据设备类型和所属设备的权限类型获取权限字符名,用于打印结果
*
* @param device_type {@link HwportDeviceTypeEnum}
* @param devid_type {@link HwportStorageDevidEnum} {@link HwportNetDevidEnum} {@link HwportNormalDevidEnum}
* @return 返回值:0成功,-1失败
*/
int APQ_HWPORT_get_dev_str_by_id(int device_type, int devid_type);
/**
* 根据设备类型和所属设备的权限类型获取权限字符名,用于打印结果
*
* @param device_type {@link HwportDeviceTypeEnum}
* @param perm_type {@link HwportStoragePermEnum} {@link HwportNetPermEnum} {@link HwportNormalPermEnum}
* @return 返回值:0成功,-1失败
*/
int APQ_HWPORT_get_perm_str_by_id(int device_type, int perm_type);
/**
* 定义可配置权限的设备类型枚举类型
*/
enum HwportDeviceTypeEnum {
APQ_HWPORT_DEVICE_TYPE_NORMAL(0), // 普通类设备
APQ_HWPORT_DEVICE_TYPE_STORAGE(1), // 存储类设备
APQ_HWPORT_DEVICE_TYPE_NET(2), // 网络类设备
APQ_HWPORT_DEVICE_TYPE_MAX(-1), /* 不使用 */;
private int code;
HwportDeviceTypeEnum(int code) {
this.code = code;
}
}
enum HwportResultEnum {
APQ_HWPORT_RESULT_OK(0), // 调用成功
APQ_HWPORT_RESULT_ERROR_UNKNOWN(1), // 调用失败,未知原因
APQ_HWPORT_RESULT_ERROR_INTERNAL(2), // 调用失败,内部错误
APQ_HWPORT_RESULT_ERROR_PARAM(3), // 调用失败,参数错误
APQ_HWPORT_RESULT_ERROR_RIGHTS(4), // 调用失败,需要管理员权限
;
private int code;
HwportResultEnum(int code) {
this.code = code;
}
}
/**
* 定义普通类设备ID(如USB设备)枚举类型
*/
enum HwportNormalDevidEnum {
APQ_HWPORT_NORMAL_DEVID_SERIAL(0), // 串口
APQ_HWPORT_NORMAL_DEVID_GPIO(1), // GPIO
APQ_HWPORT_NORMAL_DEVID_DONGLE(2), // 加密狗
APQ_HWPORT_NORMAL_DEVID_MOUSE(3), // 鼠标
APQ_HWPORT_NORMAL_DEVID_KEYBOARD(4), // 键盘
APQ_HWPORT_NORMAL_DEVID_CAMERA(5), // 摄像头
APQ_HWPORT_NORMAL_DEVID_USB_CONVERSION(6), // USB转换
APQ_HWPORT_NORMAL_DEVID_BT(7) // 蓝牙
;
private int code;
HwportNormalDevidEnum(int code) {
this.code = code;
}
}
/**
* 定义普通类权限(如USB设备)枚举类型
*/
enum HwportNormalPermEnum {
APQ_HWPORT_NORMAL_PERM_UNKNOWN(0), // 未知权限,一般是未配置
APQ_HWPORT_NORMAL_PERM_DENY(1), // 拒绝连接/使用此硬件接口
APQ_HWPORT_NORMAL_PERM_ALLOW(2), // 允许连接/使用此硬件接口
APQ_HWPORT_NORMAL_PERM_MAX(-1); /* 不使用 */
private int code;
HwportNormalPermEnum(int code) {
this.code = code;
}
}
/**
* 定义存储类设备ID(存储设备)枚举类型
*/
enum HwportStorageDevidEnum {
APQ_HWPORT_STORAGE_DEVID_CDROM(0), // 光驱
APQ_HWPORT_STORAGE_DEVID_UDISK(1), // U盘, removable disk
//APQ_HWPORT_STORAGE_DEVID_HDD_DISK(2), // 移动硬盘, <==> APQ_HWPORT_STORAGE_DEVID_UDISK
//APQ_HWPORT_STORAGE_DEVID_USB_TYPEC(3), // Type-C, <==> APQ_HWPORT_STORAGE_DEVID_UDISK
APQ_HWPORT_STORAGE_DEVID_MAX(-1), /* 不使用 */;
private int code;
HwportStorageDevidEnum(int code) {
this.code = code;
}
}
/**
* 定义存储类权限(存储设备)枚举类型
*/
enum HwportStoragePermEnum {
APQ_HWPORT_STORAGE_PERM_UNKNOWN(0), // 未知权限,一般是未配置
APQ_HWPORT_STORAGE_PERM_DENY(1), // 拒绝连接/使用此硬件接口
APQ_HWPORT_STORAGE_PERM_ALLOW(2), // 允许连接/使用此硬件接口
APQ_HWPORT_STORAGE_PERM_READ_WRITE(3), // 允许连接/使用此硬件接口,接口读写数据权限都有, <==> APQ_HWPORT_STORAGE_PERM_ALLOW
APQ_HWPORT_STORAGE_PERM_READ_ONLY(4), // 允许连接/使用此硬件接口,接口只有读数据权限 r
APQ_HWPORT_STORAGE_PERM_WRITE_IN_ONLY(5), // (等价于只读),允许连接/使用此硬件接口,接口只有拷入:支持读取数据以及向电脑拷入数据,不能从电脑拷出
APQ_HWPORT_STORAGE_PERM_WRITE_OUT_ONLY(6), // (此项无效,无法禁止向电脑拷入,等价于拒绝),允许连接/使用此硬件接口,接口只有拷出:支持读取数据以及从电脑拷出数据,不能向电脑拷入
APQ_HWPORT_STORAGE_PERM_MAX(-1) /* 不使用 */;
private int code;
HwportStoragePermEnum(int code) {
this.code = code;
}
}
/**
* 定义网速类设备ID(网络设备)枚举类型
*/
enum HwportNetDevidEnum {
APQ_HWPORT_NET_DEVID_ETH_CARD(0), // 网口
//APQ_HWPORT_NET_DEVID_WIFI(1), // WiFi <==> 网口
//APQ_HWPORT_NET_DEVID_CELLULAR(2), // 4G + 5G <==> 网口
APQ_HWPORT_NET_DEVID_MAX(-1) /* 不使用 */;
private int code;
HwportNetDevidEnum(int code) {
this.code = code;
}
}
/**
* 定义网速类权限(网络设备)枚举类型
*/
enum HwportNetPermEnum {
APQ_HWPORT_NET_PERM_UNKNOWN(0), // 未知权限,一般是未配置
APQ_HWPORT_NET_PERM_DENY(1), // 拒绝连接/使用此硬件接口
APQ_HWPORT_NET_PERM_ALLOW(2), // 允许连接/使用此硬件接口
APQ_HWPORT_NET_PERM_NO_LIMIT(3), // 不限制网络带宽, APQ_HWPORT_NET_PERM_ALLOW
APQ_HWPORT_NET_PERM_LIMIT(4), // 限制网络带宽,速度值由参数speed指定
APQ_HWPORT_NET_PERM_MAX(-1) /* 不使用 */;
private int code;
HwportNetPermEnum(int code) {
this.code = code;
}
}
}
package com.priusis.utils;
import lombok.Data;
/**
* @author yanghan
* @date 2020/11/27 16:15
*/
@Data
public class QrCode {
/**设备卡号*/
private String card;
/**校验码*/
private String checkCode;
@Override
public String toString() {
return "QrCode{" +
"card='" + card + '\'' +
", checkCode='" + checkCode + '\'' +
'}';
}
}
package com.priusis.utils;
import com.priusis.exception.ServiceException;
import com.zy.QrDecode.CQrDecode;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class QrCodeUtils {
static int[] result = new int[4];
public static QrCode qrCodeUt(String qrString) {
String path = CQrDecode.parseAbsolutePath("/qr/dat/0000000d.dat", "smart-property/0000000d.dat");
CQrDecode cQrDecode = new CQrDecode();
int i = cQrDecode.ZOOYAPI_GetCodeII(path, qrString, result);
log.info("二维码解码状态:{}, datPath:{}", i, path);
switch (i) {
case 0:
QrCode qrCode = new QrCode();
qrCode.setCard(Integer.toHexString(result[0]));
qrCode.setCheckCode(Integer.toString(result[1]));
return qrCode;
case 4001:
throw new ServiceException("key file path error or not exist");
case 4003:
throw new ServiceException("key file open fail");
case 4005:
throw new ServiceException("qr-code is not match current key file");
default:
return null;
}
}
}
package com.zy.QrDecode;
import com.sun.jna.Platform;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.system.ApplicationHome;
import java.io.File;
import java.io.UnsupportedEncodingException;
@Slf4j
public class CQrDecode {
static {
/*
dll 问题
IDEA中通过load加载
或者配置loadLibrary,都是要配置 -Djava.library.path=D:\work\priusis\projects\ower\QrDecode
*/
try {
String path = parseAbsolutePath("/qr/dll", "/qr/dll");
log.debug("load加载path:{}", path);
if (Platform.isWindows()) {
System.load(path + "/QrDecode.dll");
} else if (Platform.isLinux()) {
String lib = System.getProperty("java.library.path");
lib = path + ":" + lib;
log.debug("load加载 java.library.path:{}", lib);
System.setProperty("java.library.path", lib);
System.loadLibrary("QrDecode");
}
} catch (Exception e) {
log.error("loadLibrary Exception");
}
}
public native int hello(String str);
public native int ZOOYAPI_GetCode(String path, String qrString, int[] result);
public native int ZOOYAPI_GetCodeII(String path, String qrString, int[] result);
/**
* @param relatePath 相对路径 /qr/dat/
* @return
*/
public static String parseAbsolutePath(String relatePath, String defaultPath) {
String path = defaultPath;
if (Platform.isWindows()) {
path = CQrDecode.class.getResource(relatePath).getPath();
path = path.replaceFirst("/", "");//排除中文空格
path = path.replaceAll("%20", " ");//排除中文空格
path = path.replaceAll("/", "\\\\");//排除中文空格
try {
path = java.net.URLDecoder.decode(path, "utf-8"); //解决路径包含中文的情况
} catch (UnsupportedEncodingException e) {
log.error("巡检二维码异常", e);
}
}
if (Platform.isLinux()) {
try {
ApplicationHome h = new ApplicationHome(CQrDecode.class);
File jarF = h.getSource();
log.debug("load加载jarF:{}", jarF);
log.debug("load加载jarF:{}", jarF.getPath());
path = jarF.getParentFile().toString() + relatePath;
} catch (Exception e) {
log.error("巡检二维码获取path异常:{}", e);
path = "/app/smart-property/qr/dll";
}
}
return path;
}
}
#pragma once
// 下列 ifdef 块是创建使从 DLL 导出更简单的
// 宏的标准方法。此 DLL 中的所有文件都是用命令行上定义的 HWPORTCONTROLLERDLL_EXPORTS
// 符号编译的。在使用此 DLL 的
// 任何项目上不应定义此符号。这样,源文件中包含此文件的任何其他项目都会将
// HWPORTCONTROLLERDLL_API 函数视为是从 DLL 导入的,而此 DLL 则将用此宏定义的
// 符号视为是被导出的。
#ifdef HWPORTCONTROLLERDLL_EXPORTS
#define HWPORTCONTROLLERDLL_API __declspec(dllexport)
#else
#define HWPORTCONTROLLERDLL_API __declspec(dllimport)
#endif
/*#ifdef __cplusplus
extern "C"
{
#endif*/
/* NOTE: 此库内所有函数必须使用管理员权限运行 */
/*------- Macro -------*/
#define MAX_RESTRICT_NET_BAND_SPEED 1000000000 // 1000 Mbps
/*------- Enum -------*/
/* 定义可配置权限的设备类型枚举类型 */
typedef enum
{
APQ_HWPORT_DEVICE_TYPE_NORMAL = 0, // 普通类设备
APQ_HWPORT_DEVICE_TYPE_STORAGE = 1, // 存储类设备
APQ_HWPORT_DEVICE_TYPE_NET = 2, // 网络类设备
APQ_HWPORT_DEVICE_TYPE_MAX, /* 不使用 */
} APQ_HWPORT_DEVICE_TYPE_E;
/* 定义普通类设备ID(如USB设备)枚举类型 */
typedef enum
{
APQ_HWPORT_NORMAL_DEVID_SERIAL = 0, // 串口
APQ_HWPORT_NORMAL_DEVID_GPIO = 1, // GPIO
APQ_HWPORT_NORMAL_DEVID_DONGLE = 2, // 加密狗
APQ_HWPORT_NORMAL_DEVID_MOUSE = 3, // 鼠标
APQ_HWPORT_NORMAL_DEVID_KEYBOARD = 4, // 键盘
APQ_HWPORT_NORMAL_DEVID_CAMERA = 5, // 摄像头
APQ_HWPORT_NORMAL_DEVID_USB_CONVERSION = 6, // USB转换
APQ_HWPORT_NORMAL_DEVID_BT = 7, // 蓝牙
//APQ_HWPORT_NORMAL_DEVID_OTHER = 8, // 其他(此项不支持,必须指定要禁用类型)
APQ_HWPORT_NORMAL_DEVID_MAX, /* 不使用 */
} APQ_HWPORT_NORMAL_DEVID_E;
/* 定义普通类权限(如USB设备)枚举类型 */
typedef enum
{
APQ_HWPORT_NORMAL_PERM_UNKNOWN = 0, // 未知权限,一般是未配置
APQ_HWPORT_NORMAL_PERM_DENY = 1, // 拒绝连接/使用此硬件接口
APQ_HWPORT_NORMAL_PERM_ALLOW = 2, // 允许连接/使用此硬件接口
APQ_HWPORT_NORMAL_PERM_MAX, /* 不使用 */
} APQ_HWPORT_NORMAL_PERM_E;
/* 定义存储类设备ID(存储设备)枚举类型 */
typedef enum
{
APQ_HWPORT_STORAGE_DEVID_CDROM = 0, // 光驱
APQ_HWPORT_STORAGE_DEVID_UDISK = 1, // U盘, removable disk
//APQ_HWPORT_STORAGE_DEVID_HDD_DISK = 2, // 移动硬盘, <==> APQ_HWPORT_STORAGE_DEVID_UDISK
//APQ_HWPORT_STORAGE_DEVID_USB_TYPEC = 3, // Type-C, <==> APQ_HWPORT_STORAGE_DEVID_UDISK
APQ_HWPORT_STORAGE_DEVID_MAX, /* 不使用 */
} APQ_HWPORT_STORAGE_DEVID_E;
/* 定义存储类权限(存储设备)枚举类型 */
typedef enum
{
APQ_HWPORT_STORAGE_PERM_UNKNOWN = 0, // 未知权限,一般是未配置
APQ_HWPORT_STORAGE_PERM_DENY = 1, // 拒绝连接/使用此硬件接口
APQ_HWPORT_STORAGE_PERM_ALLOW = 2, // 允许连接/使用此硬件接口
APQ_HWPORT_STORAGE_PERM_READ_WRITE = 3, // 允许连接/使用此硬件接口,接口读写数据权限都有, <==> APQ_HWPORT_STORAGE_PERM_ALLOW
APQ_HWPORT_STORAGE_PERM_READ_ONLY = 4, // 允许连接/使用此硬件接口,接口只有读数据权限 r
APQ_HWPORT_STORAGE_PERM_WRITE_IN_ONLY = 5, // (等价于只读),允许连接/使用此硬件接口,接口只有拷入:支持读取数据以及向电脑拷入数据,不能从电脑拷出
APQ_HWPORT_STORAGE_PERM_WRITE_OUT_ONLY = 6, // (此项无效,无法禁止向电脑拷入,等价于拒绝),允许连接/使用此硬件接口,接口只有拷出:支持读取数据以及从电脑拷出数据,不能向电脑拷入
APQ_HWPORT_STORAGE_PERM_MAX, /* 不使用 */
} APQ_HWPORT_STORAGE_PERM_E;
/*定义网速类设备ID(网络设备)枚举类型 */
typedef enum
{
APQ_HWPORT_NET_DEVID_ETH_CARD = 0, // 网口
//APQ_HWPORT_NET_DEVID_WIFI = 1, // WiFi <==> 网口
//APQ_HWPORT_NET_DEVID_CELLULAR = 2, // 4G + 5G <==> 网口
APQ_HWPORT_NET_DEVID_MAX, /* 不使用 */
} APQ_HWPORT_NET_DEVID_E;
/*定义网速类权限(网络设备)枚举类型 */
typedef enum
{
APQ_HWPORT_NET_PERM_UNKNOWN = 0, // 未知权限,一般是未配置
APQ_HWPORT_NET_PERM_DENY = 1, // 拒绝连接/使用此硬件接口
APQ_HWPORT_NET_PERM_ALLOW = 2, // 允许连接/使用此硬件接口
APQ_HWPORT_NET_PERM_NO_LIMIT = 3, // 不限制网络带宽, APQ_HWPORT_NET_PERM_ALLOW
APQ_HWPORT_NET_PERM_LIMIT = 4, // 限制网络带宽,速度值由参数speed指定
APQ_HWPORT_NET_PERM_MAX, /* 不使用 */
} APQ_HWPORT_NET_PERM_E;
/*定义返回结果枚举类型 */
typedef enum
{
APQ_HWPORT_RESULT_OK = 0, // 调用成功
APQ_HWPORT_RESULT_ERROR_UNKNOWN = 1, // 调用失败,未知原因
APQ_HWPORT_RESULT_ERROR_INTERNAL = 2, // 调用失败,内部错误
APQ_HWPORT_RESULT_ERROR_PARAM = 3, // 调用失败,参数错误
APQ_HWPORT_RESULT_ERROR_RIGHTS = 4, // 调用失败,需要管理员权限
// ...
} APQ_HWPORT_RESULT_E;
/******************************************************************************************************************************
* 调用流程举例:
*
* // 定义回调函数
* void device_change_cb_fn(int changeType, char *devInfoBuf)
* {
* printf("=== get cb type=%d, data=[%s]\r\n", changeType, devInfoBuf);
* }
*
*
* // --- 1. 初始化 ---
* // 初始化接口
* APQ_HWPORT_Initialize()
*
* // 注册设备热插拔通知后,接收热插拔事件
* APQ_HWPORT_Register_Device_Notification(device_change_cb_fn)
*
* // --- 2. 权限操作 ---
* // 可选:获取某个硬件接口权限
* APQ_HWPORT_get_normal_device_permit()
*
* // 设置某硬件接口权限
* APQ_HWPORT_set_normal_device_permit()
* APQ_HWPORT_set_storage_device_permit()
* // 设置网络限速,将启动限速线程
* APQ_HWPORT_set_net_device_permit(APQ_HWPORT_NET_DEVID_ETH_CARD, APQ_HWPORT_NET_PERM_LIMIT, 0, NULL);
* // 应用配置
* APQ_HWPORT_Apply()
*
* // 解除网络限速,清理限速线程
* APQ_HWPORT_set_net_device_permit(APQ_HWPORT_NET_DEVID_ETH_CARD, APQ_HWPORT_NET_PERM_NO_LIMIT, 0, NULL);
* // 应用配置
* APQ_HWPORT_Apply()
*
* // --- 3. 清理资源 ---
* // 停止监听并释放资源
* APQ_HWPORT_Unregister_Device_Notification()
*
* // 清理资源
* APQ_HWPORT_Uninitialize()
*
******************************************************************************************************************************/
/*------- Function -------*/
/******************************************************************************************************************************
*函数名:APQ_HWPORT_Initialize
*功 能:初始化硬件接口管理模块
*参 数:
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注:调用其他接口前必须调用一次此接口初始化资源
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_Initialize(); 1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_Apply
*功 能:应用硬件接口管理模块的配置内容
*参 数:
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注:调用完成此接口后,设置才会生效
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_Apply(); 1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_Uninitialize
*功 能:清理硬件接口管理模块
*参 数:
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注:最后必须调用此函数清理资源
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_Uninitialize(); 1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_set_normal_device_permit
*功 能:设置普通设备权限
*参 数:
IN APQ_HWPORT_NORMAL_DEVID_E device_id: 枚举类型设备ID号
IN APQ_HWPORT_NORMAL_PERM_E perm: 普通类权限
IN char *data: 预留参数字串,未明确的传NULL
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注:
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_set_normal_device_permit(IN APQ_HWPORT_NORMAL_DEVID_E device_id, IN APQ_HWPORT_NORMAL_PERM_E perm, IN char *data);
1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_get_normal_device_permit
*功 能:获取普通设备权限
*参 数:
IN APQ_HWPORT_NORMAL_DEVID_E device_id: 指定普通设备硬件接口类型
*返回值:返回 APQ_HWPORT_NORMAL_PERM_E 权限类型
*备 注:
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_NORMAL_PERM_E APQ_HWPORT_get_normal_device_permit(IN APQ_HWPORT_NORMAL_DEVID_E device_id);
1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_set_storage_device_permit
*功 能:设置可移动存储设备权限
*参 数:
IN APQ_HWPORT_STORAGE_DEVID_E device_id: 枚举类型设备ID号
IN APQ_HWPORT_STORAGE_PERM_E perm: 存储类权限
IN char *data: 预留参数字串,未明确的传NULL
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注:
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_set_storage_device_permit(IN APQ_HWPORT_STORAGE_DEVID_E device_id, IN APQ_HWPORT_STORAGE_PERM_E perm, IN char *data);
1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_get_storage_device_permit
*功 能:获取可移动存储设备权限
*参 数:
IN APQ_HWPORT_NORMAL_DEVID_E device_id: 指定可移动存储设备硬件接口类型
*返回值:返回 APQ_HWPORT_NORMAL_PERM_E 权限类型
*备 注:
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_STORAGE_PERM_E APQ_HWPORT_get_storage_device_permit(IN APQ_HWPORT_STORAGE_DEVID_E device_id);
1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_set_net_device_permit
*功 能:设置网络设备权限
*参 数:
IN APQ_HWPORT_NET_DEVID_E device_id: 枚举类型设备ID号
IN APQ_HWPORT_NET_PERM_E perm: 网络类权限
IN int speed: 带宽限制值,单位KB/s
IN char *data: 预留参数字串,未明确的传NULL
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注: 设置限速选项会启动限速线程,退出程序时需要调用APQ_HWPORT_NET_PERM_NO_LIMIT或者其他不限速的权限清理限速线程
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_set_net_device_permit(IN APQ_HWPORT_NET_DEVID_E device_id, IN APQ_HWPORT_NET_PERM_E perm, IN int speed, IN char *data);
1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_get_net_device_permit
*功 能:获取网络设备权限
*参 数:
IN APQ_HWPORT_NORMAL_DEVID_E device_id: 指定网络设备硬件接口类型
OUT int *pSpeed: 返回存放配置内的带宽限速值,单位KB/s
*返回值:返回 APQ_HWPORT_NORMAL_PERM_E 权限类型
*备 注:
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_NET_PERM_E APQ_HWPORT_get_net_device_permit(IN APQ_HWPORT_NET_DEVID_E device_id, OUT int *pSpeed);
1
/******************************************************************************************************************************
*功 能:注册设备热插拔通知后,接收热插拔事件
*参 数:
int changeType: 代表该设备状态,1代表插入,2代表拔出
char *devInfoBuf: 存放识别到的设备信息(易读信息文本,用逗号区分:"设备描述","友好名称","总线已报告设备描述","提供商")
******************************************************************************************************************************/
typedef void(*P_DEVICE_CHANGE_CB)(int changeType, char *devInfoBuf);
/******************************************************************************************************************************
*函数名:APQ_HWPORT_Register_Device_Notification
*功 能:注册设备热插拔通知(如USB设备)
*参 数:
IN P_DEVICE_CHANGE_CB callback_fn: 指定事件发生时的回调函数
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注:不使用时,需要调用 APQ_HWPORT_Unregister_Device_Notification 停止监听并释放资源
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_Register_Device_Notification(IN P_DEVICE_CHANGE_CB callback_fn); 0
/******************************************************************************************************************************
*函数名:APQ_HWPORT_Register_Device_Notification
*功 能:停止监听并释放设备热插拔通知相关资源
*参 数:
*返回值:成功返回 APQ_HWPORT_RESULT_OK,失败返回 APQ_HWPORT_RESULT_ERROR_开头的值
*备 注:
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API APQ_HWPORT_RESULT_E APQ_HWPORT_Unregister_Device_Notification(void); 1
/******************************************************************************************************************************
*函数名:APQ_HWPORT_get_dev_str_by_id
*功 能:根据设备类型和所属设备的权限类型获取权限字符名,用于打印结果
*参 数:
IN APQ_HWPORT_DEVICE_TYPE_E device_type: 指定设备类型
IN int perm_type: 指定所属设备的设备ID类型,强制转成int,如(int)APQ_HWPORT_STORAGE_DEVID_UDISK
*返回值:0成功,-1失败
*备 注:用于打印结果,非必要不使用
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API const char * APQ_HWPORT_get_dev_str_by_id(IN APQ_HWPORT_DEVICE_TYPE_E device_type, IN int devid_type);
/******************************************************************************************************************************
*函数名:APQ_HWPORT_get_perm_str_by_id
*功 能:根据设备类型和所属设备的权限类型获取权限字符名,用于打印结果
*参 数:
IN APQ_HWPORT_DEVICE_TYPE_E device_type: 指定设备类型
IN int perm_type: 指定所属设备的权限类型,强制转成int,如(int)APQ_HWPORT_STORAGE_PERM_DENY
*返回值:权限字符名
*备 注:用于打印结果,非必要不使用
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API const char *APQ_HWPORT_get_perm_str_by_id(IN APQ_HWPORT_DEVICE_TYPE_E device_type, IN int perm_type);
/******************************************************************************************************************************
*函数名:APQ_HWPORT_get_perm_id_by_str
*功 能:根据设备类型和所属设备的权限字符名获取权限类型,用于打印结果
*参 数:
IN APQ_HWPORT_DEVICE_TYPE_E device_type: 指定设备类型
IN const char* perm_str: 指定所属设备的权限字符名
*返回值:权限类型,需强制转换成对应enum类型
*备 注:用于打印结果,非必要不使用
******************************************************************************************************************************/
HWPORTCONTROLLERDLL_API const int APQ_HWPORT_get_perm_id_by_str(IN APQ_HWPORT_DEVICE_TYPE_E device_type, IN const char* perm_str);
/*#ifdef __cplusplus
}
#endif*/
}nsgm?!7G*X2pErfK0%XjStԮr{=^<Sa
\ No newline at end of file
APQ_HWPORT_NET_DEVID_ETH_CARD=APQ_HWPORT_NET_PERM_ALLOW
APQ_HWPORT_NET_DEVID_ETH_CARD_SPEED=1000000
APQ_HWPORT_NORMAL_DEVID_BT=APQ_HWPORT_NORMAL_PERM_ALLOW
APQ_HWPORT_NORMAL_DEVID_CAMERA=APQ_HWPORT_NORMAL_PERM_ALLOW
APQ_HWPORT_NORMAL_DEVID_DONGLE=APQ_HWPORT_NORMAL_PERM_UNKNOWN
APQ_HWPORT_NORMAL_DEVID_GPIO=APQ_HWPORT_NORMAL_PERM_UNKNOWN
APQ_HWPORT_NORMAL_DEVID_KEYBOARD=APQ_HWPORT_NORMAL_PERM_ALLOW
APQ_HWPORT_NORMAL_DEVID_MOUSE=APQ_HWPORT_NORMAL_PERM_ALLOW
APQ_HWPORT_NORMAL_DEVID_SERIAL=APQ_HWPORT_NORMAL_PERM_ALLOW
APQ_HWPORT_NORMAL_DEVID_USB_CONVERSION=APQ_HWPORT_NORMAL_PERM_ALLOW
APQ_HWPORT_STORAGE_DEVID_CDROM=APQ_HWPORT_STORAGE_PERM_UNKNOWN
APQ_HWPORT_STORAGE_DEVID_UDISK=APQ_HWPORT_STORAGE_PERM_UNKNOWN
KEY=value
apq-pc-info @ 83ec6432
Subproject commit 83ec6432dacc56bea307f0fa79fa05a87e21297f
apq-pc-register @ 83ec6432
Subproject commit 83ec6432dacc56bea307f0fa79fa05a87e21297f
<?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">
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://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.4.10</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.priusis</groupId>
<artifactId>haikang-client</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>haikang-client</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
<commons-lang3.version>3.4</commons-lang3.version>
<!-- Eclipse Paho 1.1.0 contains major issue with persistence of buffered messages. Using 1.1.1-SNAPSHOT for now. Need to remove this after Paho 1.1.1 release -->
<paho.client.version>1.2.0</paho.client.version>
<json-path.version>2.2.0</json-path.version>
<jsonassert.version>1.5.0</jsonassert.version>
<milo.client.version>0.1.0</milo.client.version>
<moquette.version>0.10</moquette.version>
<netty.version>4.1.22.Final</netty.version>
<jackson.version>2.10.2</jackson.version>
<spring.version>4.3.4.RELEASE</spring.version>
<winsw.version>2.0.1</winsw.version>
<bouncycastle.version>1.52</bouncycastle.version>
<slf4j.version>1.7.7</slf4j.version>
<pkg.name>pi-gateway</pkg.name>
<pkg.user>priusis-iot</pkg.user>
<pkg.unixLogFolder>/var/log/${pkg.name}</pkg.unixLogFolder>
<pkg.installFolder>/usr/share/${pkg.name}</pkg.installFolder>
<pkg.win.dist>${project.build.directory}/windows</pkg.win.dist>
<priusis-iot.version>1.0.0-SNAPSHOT</priusis-iot.version>
<groupId>com.priusis</groupId>
<artifactId>apq-client</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>pom</packaging>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.hibernate.validator</groupId>
<artifactId>hibernate-validator</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</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>
<dependency>
<groupId>com.priusis</groupId>
<artifactId>netty-mqtt</artifactId>
<version>${priusis-iot.version}</version>
<exclusions>
<exclusion>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.eclipse.paho</groupId>
<artifactId>org.eclipse.paho.client.mqttv3</artifactId>
<version>${paho.client.version}</version>
</dependency>
<dependency>
<groupId>com.sun.winsw</groupId>
<artifactId>winsw</artifactId>
<version>${winsw.version}</version>
<classifier>bin</classifier>
<type>exe</type>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>${commons-lang3.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-common</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-transport</artifactId>
<version>${netty.version}</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>io.moquette</groupId>
<artifactId>moquette-broker</artifactId>
<version>${moquette.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.3.2</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.7.11</version>
</dependency>
<dependency>
<groupId>com.github.oshi</groupId>
<artifactId>oshi-core</artifactId>
<version>3.5.0</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<name>apq-client</name>
<build>
<finalName>${pkg.name}-${project.version}</finalName>
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
</resource>
</resources>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${java.version}</source>
<target>${java.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>2.7</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.2.1</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.0.2</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>3.0.0</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>${spring-boot.version}</version>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
<plugin>
<groupId>org.fortasoft</groupId>
<artifactId>gradle-maven-plugin</artifactId>
<version>1.0.8</version>
</plugin>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
<version>3.0</version>
<configuration>
<header>license-header-template.txt</header>
<properties>
<owner>The PriusisIot Authors</owner>
</properties>
<excludes>
<exclude>**/.env</exclude>
<exclude>**/README</exclude>
<exclude>**/LICENSE</exclude>
<exclude>**/*.properties</exclude>
<exclude>**/banner.txt</exclude>
<exclude>src/test/resources/**</exclude>
<exclude>src/sh/**</exclude>
<exclude>src/main/scripts/control/**</exclude>
<exclude>src/main/scripts/windows/**</exclude>
</excludes>
<mapping>
<conf>SCRIPT_STYLE</conf>
<gradle>JAVADOC_STYLE</gradle>
</mapping>
</configuration>
<executions>
<execution>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<groupId>com.mycila</groupId>
<artifactId>license-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>com.sun.winsw</groupId>
<artifactId>winsw</artifactId>
<classifier>bin</classifier>
<type>exe</type>
<destFileName>service.exe</destFileName>
</artifactItem>
</artifactItems>
<outputDirectory>${pkg.win.dist}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<executions>
<execution>
<id>copy-service-conf</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/conf</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>logback.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/conf</directory>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/unix.properties</filter>
</filters>
</configuration>
</execution>
<execution>
<id>copy-win-conf</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${pkg.win.dist}/conf</outputDirectory>
<resources>
<resource>
<directory>src/main/resources</directory>
<excludes>
<exclude>logback.xml</exclude>
</excludes>
<filtering>false</filtering>
</resource>
<resource>
<directory>src/main/conf</directory>
<excludes>
<exclude>pi-gateway.conf</exclude>
</excludes>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/windows.properties</filter>
</filters>
</configuration>
</execution>
<execution>
<id>copy-control</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${project.build.directory}/control</outputDirectory>
<resources>
<resource>
<directory>src/main/scripts/control</directory>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/unix.properties</filter>
</filters>
</configuration>
</execution>
<execution>
<id>copy-windows-control</id>
<phase>process-resources</phase>
<goals>
<goal>copy-resources</goal>
</goals>
<configuration>
<outputDirectory>${pkg.win.dist}</outputDirectory>
<resources>
<resource>
<directory>src/main/scripts/windows</directory>
<filtering>true</filtering>
</resource>
</resources>
<filters>
<filter>src/main/filters/windows.properties</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifestEntries>
<Implementation-Title>PriusisIot Gateway</Implementation-Title>
<Implementation-Version>${project.version}</Implementation-Version>
</manifestEntries>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<classifier>boot</classifier>
<layout>ZIP</layout>
<executable>true</executable>
<excludeDevtools>true</excludeDevtools>
<embeddedLaunchScriptProperties>
<confFolder>${pkg.installFolder}/conf</confFolder>
<logFolder>${pkg.unixLogFolder}</logFolder>
<logFilename>${pkg.name}.out</logFilename>
<initInfoProvides>${pkg.name}</initInfoProvides>
</embeddedLaunchScriptProperties>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.fortasoft</groupId>
<artifactId>gradle-maven-plugin</artifactId>
<configuration>
<tasks>
<task>build</task>
<task>buildDeb</task>
<task>buildRpm</task>
</tasks>
<args>
<arg>-PprojectBuildDir=${project.build.directory}</arg>
<arg>-PprojectVersion=${project.version}</arg>
<arg>-PmainJar=${project.build.directory}/${project.build.finalName}-boot.${project.packaging}
</arg>
<arg>-PpkgName=${pkg.name}</arg>
<arg>-PpkgUser=${pkg.user}</arg>
<arg>-PpkgInstallFolder=${pkg.installFolder}</arg>
<arg>-PpkgLogFolder=${pkg.unixLogFolder}</arg>
</args>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>invoke</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<finalName>${pkg.name}</finalName>
<descriptors>
<descriptor>src/main/assembly/windows.xml</descriptor>
</descriptors>
</configuration>
<executions>
<execution>
<id>assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<modules>
<module>apq-pc-client</module>
<module>apq-pc-control</module>
<module>apq-pc-info</module>
<module>apq-pc-register</module>
</modules>
</project>
</project>
\ No newline at end of file
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论