门磁对接

master
Bbt 7 months ago
parent dc25aa9475
commit 1b75633bd6

38
.gitignore vendored

@ -0,0 +1,38 @@
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store

@ -0,0 +1,2 @@
编号 门磁设备IMEI 对应摄像头IP
1 866674056947364 192.168.0.68

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

@ -21,19 +21,105 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<version>2.0.5.RELEASE</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.18</version>
<version>5.8.15</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.80</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!-- https://mvnrepository.com/artifact/com.alibaba/easyexcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.3.3</version>
</dependency>
<!--caffeine本地缓存-->
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
<version>2.9.0</version>
</dependency>
<dependency>
<groupId>cglib</groupId>
<artifactId>cglib</artifactId>
<version>3.2.7</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.8.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
<version>2.11.1</version>
</dependency>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.49</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
<finalName>fileHandle</finalName>
</build>
</project>

@ -0,0 +1,33 @@
package com.doormagnet;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;
@Configuration
@EnableAsync
public class AsyncConfiguration {
@Bean("doorMagnetExecutor")
public Executor doSomethingExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
// 核心线程数:线程池创建时候初始化的线程数
executor.setCorePoolSize(4);
// 最大线程数:线程池最大的线程数,只有在缓冲队列满了之后才会申请超过核心线程数的线程
executor.setMaxPoolSize(8);
// 缓冲队列:用来缓冲执行任务的队列
executor.setQueueCapacity(16);
// 允许线程的空闲时间60秒当超过了核心线程之外的线程在空闲时间到达之后会被销毁
executor.setKeepAliveSeconds(30);
// 线程池名的前缀:设置好了之后可以方便我们定位处理任务所在的线程池
executor.setThreadNamePrefix("file-handle-");
// 缓冲队列满了之后的拒绝策略:由调用线程处理(一般是主线程)
executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());
executor.initialize();
return executor;
}
}

@ -1,17 +1,23 @@
package com.doormagnet;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
/*
* @User $USER
* @Time $DATE $TIME
*
*/
@Slf4j
@EnableAsync
@EnableScheduling
@SpringBootApplication
public class DoorMagnet {
public class DoorMagnetApplication {
public static void main(String[] args) {
SpringApplication.run(DoorMagnet.class);
SpringApplication.run(DoorMagnetApplication.class);
System.out.println("门磁对接程序");
}
}

@ -0,0 +1,23 @@
package com.doormagnet.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.stereotype.Component;
import java.util.concurrent.Executors;
/**
* @Author
* @Date 2023/12/22 17:46
* @Version 1.0
*/
@Configuration
@EnableScheduling
public class SchuedingConfig implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(Executors.newScheduledThreadPool(30));
}
}

@ -0,0 +1,37 @@
package com.doormagnet.controller;
import cn.hutool.json.JSONObject;
import cn.hutool.json.ObjectMapper;
import com.alibaba.fastjson.JSON;
import com.doormagnet.pojo.EventReport;
import com.doormagnet.service.DoorMagnetService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.support.BindingAwareModelMap;
import org.springframework.web.bind.annotation.*;
import java.io.File;
/**
* @Author
* @Date 2024/4/24 11:36
* @Version 1.0
*/
@RestController
@RequestMapping("/doormagnet")
public class DoorMagnetController {
@Autowired
private DoorMagnetService doorMagnetService;
@PostMapping("/test")
public void test(@RequestBody JSONObject jsonObject){
EventReport eventReport = JSON.parseObject(String.valueOf(jsonObject), EventReport.class);
if (eventReport.getEventContent().getOpenState()== 1 || eventReport.getEventContent().getOpenState()== 0){
Boolean flag = doorMagnetService.creatfile(eventReport);
System.out.println("eventReport = " + flag);
}
}
}

@ -0,0 +1,42 @@
package com.doormagnet.ftp.config;
import cn.hutool.core.util.CharsetUtil;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* ftp
*/
@Data
@Component
@ConfigurationProperties(prefix = "ftp.client")
public class FtpConfig {
//连接地址
private String ip;
//端口
private Integer port;
//用户名
private String username;
//密码
private String password;
//ftp连接模式主动模式和被动模式, 0主动1被动
private Integer model = 1;
//编码格式
private String charset = CharsetUtil.UTF_8;
//连接超时时长,单位毫秒
private Integer connectionTimeout = 3000;
//Socket连接超时时长单位毫秒
private long soTimeout = 3000;
private String srcPath;
private String destPath;
private boolean dirFilter;
private boolean enableTLS;
private List<String> typeList;
}

@ -0,0 +1,78 @@
package com.doormagnet.ftp.service;
import com.doormagnet.ftp.config.FtpConfig;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
/**
* @Author
* @Date 2024/4/30 17:48
* @Version 1.0
*/
@Service
public class FtpService {
@Autowired
private FtpConfig ftpProperties;
//
// public void uploadFile(String localFilePath, String remoteDirectory) throws IOException {
// FTPClient ftpClient = new FTPClient();
// try {
// ftpClient.connect(ftpProperties.getIp(), ftpProperties.getPort());
// ftpClient.login(ftpProperties.getUsername(), ftpProperties.getPassword());
// ftpClient.enterLocalPassiveMode();
// ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
//
// FileInputStream inputStream = new FileInputStream(localFilePath);
// boolean uploaded = ftpClient.storeFile(remoteDirectory, inputStream);
// inputStream.close();
//
// if (uploaded) {
// System.out.println("File uploaded successfully");
// } else {
// System.out.println("File upload failed");
// }
// } finally {
// if (ftpClient.isConnected()) {
// ftpClient.logout();
// ftpClient.disconnect();
// }
// }
// }
/**
* @description
* @author
* @param[1] null
* @throws
* @time 2024/4/30 18:00
* 使ftpftp
*/
public void downloadFile(String srcpath, String filename, File file) throws IOException {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(ftpProperties.getIp(), ftpProperties.getPort());
ftpClient.login(ftpProperties.getUsername(), ftpProperties.getPassword());
ftpClient.enterLocalPassiveMode();
ftpClient.setControlEncoding("UTF-8");
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
ftpClient.enterLocalPassiveMode();
ftpClient.changeWorkingDirectory(srcpath);
ftpClient.storeFile(filename, new FileInputStream(file));
} finally {
if (ftpClient.isConnected()) {
ftpClient.logout();
ftpClient.disconnect();
}
}
}
}

@ -0,0 +1,29 @@
package com.doormagnet.pojo;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author
* @Date 2024/4/24 11:33
* @Version 1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class EventContent {
@JsonProperty("open_state")
private Integer openState = 3;
@JsonProperty("battery_voltage")
private Double batteryVoltage;
@JsonProperty("battery_value")
private Integer batteryValue;
@JsonProperty("arming_state")
private Integer armingState;
@JsonProperty("alarm_type")
private Integer alarmType;
}

@ -0,0 +1,56 @@
package com.doormagnet.pojo;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @Author
* @Date 2024/4/28 11:24
* @Version 1.0
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonInclude(JsonInclude.Include.NON_NULL)
public class EventReport {
@JsonProperty("timestamp")
private long timestamp;
@JsonProperty("tenantId")
private String tenantId;
@JsonProperty("serviceId")
private Integer serviceId;
@JsonProperty("protocol")
private String protocol;
@JsonProperty("productId")
private String productId;
@JsonProperty("messageType")
private String messageType;
@JsonProperty("eventType")
private Integer eventType;
@JsonProperty("eventContent")
private EventContent eventContent;
@JsonProperty("deviceSn")
private String deviceSn;
@JsonProperty("deviceId")
private String deviceId;
@JsonProperty("IMSI")
private String IMSI;
@JsonProperty("IMEI")
private String IMEI;
}

@ -0,0 +1,82 @@
package com.doormagnet.service;
import cn.hutool.core.util.RandomUtil;
import com.doormagnet.ftp.config.FtpConfig;
import com.doormagnet.ftp.service.FtpService;
import com.doormagnet.pojo.EventReport;
import com.doormagnet.task.ExcelReader;
import com.doormagnet.until.StringKit;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.io.File;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @Author
* @Date 2024/4/24 11:35
* @Version 1.0
*/
@Slf4j
@Service
public class DoorMagnetService {
@Autowired
private FtpConfig properties;
@Autowired
private FtpService ftpService;
private static final SimpleDateFormat hmsSdf = new SimpleDateFormat("HHmmss");
/**
* @description
* @author
* @param[1] null
* @throws
* @time 2024/4/28 14:14
* bcp + ftp
* bcpDoorMagnet__HHmmss_.bcp
* bcpip
*/
public Boolean creatfile(EventReport eventReport) {
log.info("=============bcp开始创建================");
String path = properties.getSrcPath();
String destPath = properties.getDestPath();
String fileName = "";
String ip = ExcelReader.get(eventReport.getIMEI());
String hhmmss = hmsSdf.format(new Date());
if (StringKit.isEmpty(ip)) {
log.info("=============设备ip为空=");
return null;
}
fileName = "DoorMagnet_" + eventReport.getTimestamp() + "_" + eventReport.getIMEI()+"_" + hhmmss + "_" + RandomUtil.randomNumbers(4) + ".bcp";
//根据操作系统自动判断路径分隔符
path = path + File.separator + fileName;
PrintWriter writer = null;
try {
log.info("=============bcp文件路径" + path);
writer = new PrintWriter(path, "UTF-8");
StringBuffer sb = new StringBuffer();
sb.append(eventReport.getTimestamp()).append(",").append(eventReport.getEventContent().getOpenState()).append(",");
sb.append(eventReport.getIMEI()).append(",").append(ip);
writer.print(sb.toString());
writer.flush();
writer.close();
//将生成的bcp文件上传到ftp
File file = new File(path);
//ftp转发
ftpService.downloadFile(destPath,fileName, file);
} catch (Exception e) {
e.printStackTrace();
log.error("=============bcp创建失败================");
return false;
}
log.info("=============bcp创建成功================");
return true;
}
}

@ -0,0 +1,17 @@
package com.doormagnet.task;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@Data
public class ConfigData {
@ExcelProperty("编号")
private String id;
@ExcelProperty("门磁设备IMEI")
private String doorwayIMEI;
@ExcelProperty("对应摄像头IP")
private String cameraIP;
}

@ -0,0 +1,68 @@
package com.doormagnet.task;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@Component
public class ExcelReader {
private static final Cache<String, String> cache = Caffeine.newBuilder().build();
@PostConstruct
public static void readExcel() {
String filePath = "F:\\WT\\config.xlsx";
// 读取 Excel 文件并映射到对象
List<ConfigData> dataList = EasyExcel.read(filePath, ConfigData.class, new ExcelListener()).sheet().doReadSync();
Map map = new HashMap();
cache.putAll(map);
Map<String, String> dictMapCode = dataList.stream().collect(Collectors.toMap(
e -> e.getDoorwayIMEI(),
e -> e.getCameraIP(), (v1, v2) -> v2));
cache.putAll(dictMapCode);
}
public static class ExcelListener extends AnalysisEventListener<ConfigData> {
private final List<ConfigData> dataList = new ArrayList<>();
@Override
public void invoke(ConfigData data, AnalysisContext context) {
// 处理每一行的数据
dataList.add(data);
}
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 数据读取完成后的处理
// System.out.println("所有数据处理完毕");
}
public List<ConfigData> getDataList() {
return dataList;
}
}
public static String get(String key) {
return cache.get(key, s -> null);
}
public static void main(String[] args) {
readExcel();
}
}

@ -0,0 +1,106 @@
package com.doormagnet.until;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.regex.Pattern;
public class StringKit {
public StringKit() {
}
public static Boolean isEmpty(Object argObject) {
Boolean tbool = false;
String tString = toString(argObject);
if (tString.equals("")) {
tbool = true;
}
return tbool;
}
public static String toString(Object argObject) {
String tmpstr = "";
try {
if (argObject != null) {
tmpstr = argObject.toString();
tmpstr = tmpstr.replaceAll("\0", "");
if( "null".equals(tmpstr) || "underfind".equals(tmpstr) || "undefined".equals(tmpstr) ){
tmpstr="";
}
}
} catch (Exception var3) {
}
return tmpstr;
}
public static String toStringNull(Object argObject) {
String tmpstr = "";
try {
if (argObject != null) {
tmpstr = argObject.toString();
if( "null".equals(tmpstr) || "underfind".equals(tmpstr) || "undefined".equals(tmpstr) ){
tmpstr="null";
}
}
} catch (Exception var3) {
}
return tmpstr;
}
@Deprecated
public static String toDefaultString(Object argObject) {
String tmpstr = "无";
try {
if (argObject != null) {
tmpstr = argObject.toString();
if( "null".equals(tmpstr) || "underfind".equals(tmpstr) || "undefined".equals(tmpstr) ){
tmpstr="无";
}
}
} catch (Exception var3) {
}
return tmpstr;
}
@Deprecated
public static String toDefaultInt(Object argObject) {
String tmpstr = "0";
try {
if (argObject != null) {
tmpstr = argObject.toString();
if( "null".equals(tmpstr) || "underfind".equals(tmpstr) || "undefined".equals(tmpstr) ){
tmpstr="0";
}
}
} catch (Exception var3) {
}
return tmpstr;
}
public static boolean isNumeric(String str){
Pattern pattern = Pattern.compile("[0-9]*");
return pattern.matcher(str).matches();
}
public static boolean isEng(String str){
Pattern pattern = Pattern.compile("[a-zA-Z]");
return pattern.matcher(str).matches();
}
public static String getTrace(Throwable t){
StringWriter stringWriter = new StringWriter();
PrintWriter writer = new PrintWriter(stringWriter);
t.printStackTrace(writer);
StringBuffer buffer = stringWriter.getBuffer();
return buffer.toString();
}
}

@ -0,0 +1,31 @@
spring:
application:
name: doormagnetservice
profiles:
active: dev
server:
port: 9477
ftp:
client:
# 连接地址
ip: 192.168.0.38
# 端口
port: 21
# 用户名
username: watu2
# 密码
password: watu123
# ftp连接模式:主动模式和被动模式; 0主动1被动默认被动
model: 1
# Socket连接超时时长
soTimeout: 30000
# 源路径:配置需要搬运的目录
srcPath: D:\home
# 目标路径:配置目的地相对路径,需要注意实际目的地路径 = ftp服务器配置的用户根路径 + destPath
destPath: /home/doorbcp
# 文件过滤开关:默认关闭
dirFilter: false
# 是否启用FTPS加密传输默认关闭
enableTLS: false
typeList: bcp

@ -0,0 +1,71 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration scan="true" scanPeriod="60 seconds" debug="false">
<!--彩色日志解析-->
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<springProperty scope="context" name="LOG_PATH" source="logback.path" defaultValue="/home/project/fileTransfer/log"/>
<springProperty scope="context" name="MAX_HISTORY" source="logback.max-history" defaultValue="7"/>
<!--输出到控制台-->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>${CONSOLE_LOG_PATTERN}</pattern>
<!-- 设置字符集 -->
<charset>UTF-8</charset>
</encoder>
</appender>
<!--输出到文件-->
<appender name="FILE_INFO" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/info/info.%d{yyyy-MM-dd}.log</fileNamePattern>
<MaxHistory>${MAX_HISTORY}</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>INFO</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<appender name="FILE_ERROR" class="ch.qos.logback.core.rolling.RollingFileAppender">
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>${LOG_PATH}/error/error.%d{yyyy-MM-dd}.log</fileNamePattern>
<MaxHistory>${MAX_HISTORY}</MaxHistory>
</rollingPolicy>
<encoder>
<pattern>${FILE_LOG_PATTERN}</pattern>
<charset>UTF-8</charset>
</encoder>
<filter class="ch.qos.logback.classic.filter.LevelFilter">
<level>ERROR</level>
<onMatch>ACCEPT</onMatch>
<onMismatch>DENY</onMismatch>
</filter>
</appender>
<logger name="com.watu.filetransfer"/>
<logger name="org.springframework" level="warn"/>
<springProfile name="dev">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
</root>
</springProfile>
<springProfile name="test">
<root level="DEBUG">
<appender-ref ref="CONSOLE"/>
<appender-ref ref="FILE_INFO"/>
<appender-ref ref="FILE_ERROR"/>
</root>
</springProfile>
<springProfile name="prod">
<root level="INFO">
<appender-ref ref="FILE_INFO"/>
<appender-ref ref="FILE_ERROR"/>
</root>
</springProfile>
</configuration>
Loading…
Cancel
Save