This commit is contained in:
liuzhenlei 2024-10-16 17:03:01 +08:00
parent 47fd938102
commit 25c843650e
15 changed files with 438 additions and 18 deletions

View File

@ -7,6 +7,7 @@ import com.hxl.puyang.config.netty.BootNettyClient;
import com.hxl.puyang.location.service.LocationAlarmHistoryService;
import com.hxl.puyang.location.service.LocationRealdataService;
import com.hxl.puyang.location.service.LocationUserService;
import com.hxl.puyang.utils.DataSecureUtil;
import com.xxl.job.core.handler.annotation.XxlJob;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@ -76,4 +77,40 @@ public class ActuatorFactory {
}
log.info("发送人员基础信息结束");
}
/**
* 人员实时位置数据上报
*/
@XxlJob("reportRealData")
public void reportRealData() {
log.info("发送人员实时位置数据开始");
try {
locationRealdataService.reportRealData();
} catch (Exception e) {
log.error("数据发送失败");
log.error(ExceptionUtil.stacktraceToString(e));
}
log.info("发送人员实时位置数据结束");
}
/**
* 报警数据上报
*/
@XxlJob("reportAlarm")
public void reportAlarm() {
log.info("发送报警数据开始");
try {
locationAlarmHistoryService.reportAlarm();
} catch (Exception e) {
log.error("数据发送失败");
log.error(ExceptionUtil.stacktraceToString(e));
}
log.info("发送报警数据结束");
}
public static void main(String[] args) {
String aa = "a8JUw/VInCWEpQWjJ1pQjtxnJVSeQCf5mRh+y1jNzhGTadVzL9g5Sj8ilUZFIsIfh1ATfeYtn8JPhbyBpgt0DTca4Jvysq1g9eNQC4To1qpgR4yR0+ekZWghsxum8Gx8VpM2F7MNCgFgWs9E5gBqutz7PENLULJCWyOqfWnVCD70V6use9vtSjp1ZeLAsu2e+siv6uxTD3sP0DLxUL2EStft7Nqb4y0dkh6FmFDSN43/oTchaeO7oF7X85M4/DD0RrlH26jTYNU6eC9zaus+gFVL8i+sBe386KJqUg9Z+9zMk81rYV+jrVo7Z8njSF5e0pxT4fGAknOj7/zjhwb4gk2oj4qfrT2SBudDfcpFjRxifOoj4SF2OZJ7UdDLurwbfCki7rLj5LHi/pp0EDxau6oM0v1S8qcAQ+5ZGKGHsDRTOVb67T9a2OMT7poS5z8rmYuGDoDoWzh+cOWTJle2aSBLP47g3H1wDDBNTJxYkd79vv8uZrae6DeGY2GDCp28p2As4WvXCY1OGsAbYqe4IqVoBJTaBhU3w4jwi5oP1qFAoT8sJSyUcoHEusmV6T1YIUhkDOYv9fhmw4t33Bl9yegi9E7+NEfS2FJawhM03Ro=";
System.out.println(DataSecureUtil.decryptBase64(aa));
}
}

View File

@ -1,6 +1,7 @@
package com.hxl.puyang.config.netty;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import lombok.extern.slf4j.Slf4j;
@ -52,4 +53,15 @@ public class BootNettyChannelInboundHandlerAdapter extends ChannelInboundHandler
cause.printStackTrace();
ctx.close();
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
super.channelRead(ctx, msg);
log.info(JSONUtil.toJsonStr(msg));
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
super.channelReadComplete(ctx);
}
}

View File

@ -3,7 +3,6 @@ package com.hxl.puyang.config.netty;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.extra.spring.SpringUtil;
import cn.hutool.json.JSONUtil;
import com.hxl.puyang.config.NettyConfig;
import com.hxl.puyang.enums.DataTypeEnum;
import com.hxl.puyang.location.entity.LocationAlarmHistory;
@ -38,8 +37,10 @@ public class BootNettyClient {
private EventLoopGroup group;
/**
* 配置客户端连接服务器
*/
public void connect() {
log.info("连接");
//客户端的NIO线程组
group = new NioEventLoopGroup();
@ -52,7 +53,7 @@ public class BootNettyClient {
bootstrap = bootstrap.channel(NioSocketChannel.class).option(ChannelOption.SO_KEEPALIVE, true);
//设置 I/O处理类,主要用于网络I/O事件记录日志编码解码消息
bootstrap = bootstrap.handler(new BootNettyChannelInitializer<SocketChannel>());
log.info("netty client start success!");
log.info("netty客户端启动成功!");
//连接服务端
ChannelFuture f = bootstrap.connect(nettyConfig.getIp(), nettyConfig.getPort()).sync();
channel = f.channel();
@ -79,6 +80,7 @@ public class BootNettyClient {
*/
public <T> void sendData(String data, List<T> list, DataTypeEnum dataTypeEnum) throws Exception {
checkChannel();
log.info("发送的数据:" + data);
ChannelFuture channelFuture = channel.writeAndFlush(data);
channelFuture.addListener((ChannelFutureListener) future1 -> {
if (future1.isSuccess()) {
@ -111,6 +113,11 @@ public class BootNettyClient {
});
}
/**
* 项目停止关闭连接
*
* @throws Exception
*/
@PreDestroy
public void stopClient() throws Exception {
if (channel != null) {

View File

@ -2,8 +2,11 @@ package com.hxl.puyang.location.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hxl.puyang.location.entity.LocationAlarmHistory;
import com.hxl.puyang.location.model.AlarmDataModel;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author lzl
* @description 针对表hxl_location_alarm_history(历史求救记录表)的数据库操作Mapper
@ -13,6 +16,12 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LocationAlarmHistoryMapper extends BaseMapper<LocationAlarmHistory> {
/**
* 获取需要上报的报警信息
*
* @return
*/
List<AlarmDataModel> getAlarmData();
}

View File

@ -2,8 +2,11 @@ package com.hxl.puyang.location.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.hxl.puyang.location.entity.LocationRealdata;
import com.hxl.puyang.location.model.RealDataModel;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
/**
* @author lzl
* @description 针对表hxl_location_realdata(实时定位表)的数据库操作Mapper
@ -13,6 +16,13 @@ import org.apache.ibatis.annotations.Mapper;
@Mapper
public interface LocationRealdataMapper extends BaseMapper<LocationRealdata> {
/**
* 获取人员定位实时数据
*
* @return
*/
List<RealDataModel> getRealData();
}

View File

@ -10,4 +10,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface LocationAlarmHistoryService extends IService<LocationAlarmHistory> {
/**
* 上报人员报警信息
*/
void reportAlarm();
}

View File

@ -9,5 +9,8 @@ import com.baomidou.mybatisplus.extension.service.IService;
* @createDate 2024-10-15 11:04:40
*/
public interface LocationRealdataService extends IService<LocationRealdata> {
/**
* 上报人员位置信息
*/
void reportRealData();
}

View File

@ -1,20 +1,98 @@
package com.hxl.puyang.location.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxl.puyang.config.ReportConfig;
import com.hxl.puyang.config.netty.BootNettyClient;
import com.hxl.puyang.enums.DataTypeEnum;
import com.hxl.puyang.location.entity.LocationAlarmHistory;
import com.hxl.puyang.location.service.LocationAlarmHistoryService;
import com.hxl.puyang.location.mapper.LocationAlarmHistoryMapper;
import com.hxl.puyang.location.model.AlarmDataModel;
import com.hxl.puyang.location.model.DataModel;
import com.hxl.puyang.location.model.DataSecureModel;
import com.hxl.puyang.location.service.LocationAlarmHistoryService;
import com.hxl.puyang.utils.DataSecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
/**
* @author lzl
* @description 针对表hxl_location_alarm_history(历史求救记录表)的数据库操作Service实现
* @createDate 2024-10-15 14:00:33
*/
@Service
@Slf4j
public class LocationAlarmHistoryServiceImpl extends ServiceImpl<LocationAlarmHistoryMapper, LocationAlarmHistory>
implements LocationAlarmHistoryService {
@Resource
private LocationAlarmHistoryMapper locationAlarmHistoryMapper;
@Resource
private ReportConfig reportConfig;
@Resource
private BootNettyClient bootNettyClient;
private final static String END_STR = "@@";
private final static int CODE = 200;
/**
* 上报人员报警信息
*/
@Override
public void reportAlarm() {
log.info("开始上报——上报人员报警信息");
try {
//验证ReportConfig数据完整性
if (reportConfig.checkParam()) {
//1收集信息
List<AlarmDataModel> alarmDataModels = locationAlarmHistoryMapper.getAlarmData();
List<LocationAlarmHistory> locationAlarmHistories = new ArrayList<>();
if (CollectionUtil.isNotEmpty(alarmDataModels)) {
for (AlarmDataModel a : alarmDataModels) {
if (ObjectUtil.isNull(a.getId())) {
String uuid = StrUtil.uuid();
a.setId(uuid);
a.setAlarmCode(uuid);
}
LocationAlarmHistory locationAlarmHistory = new LocationAlarmHistory();
locationAlarmHistory.setId(a.getOid());
locationAlarmHistory.setIsReportYq(1);
locationAlarmHistory.setRid(a.getId());
locationAlarmHistories.add(locationAlarmHistory);
}
//包装数据
DataSecureModel<AlarmDataModel> dataSecureModel = new DataSecureModel<>();
dataSecureModel.setCollectTime(DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN));
dataSecureModel.setDatas(alarmDataModels);
//加密数据
String secureStr = DataSecureUtil.encryptBase64(JSONUtil.toJsonStr(dataSecureModel));
DataModel dataModel = new DataModel();
dataModel.setCompanyCode(reportConfig.getCompanyCode());
dataModel.setServiceId(DataTypeEnum.PERSONNEL_WARN.getServiceId());
dataModel.setData(secureStr);
bootNettyClient.sendData(JSONUtil.toJsonStr(dataModel) + END_STR, locationAlarmHistories, DataTypeEnum.PERSONNEL_WARN);
} else {
log.info("上报人员报警信息,未收集到可上报的数据");
}
}
} catch (Exception e) {
log.error("上报人员报警信息出错");
log.error(ExceptionUtil.stacktraceToString(e));
}
log.info("结束上报——上报人员报警信息");
}
}

View File

@ -1,20 +1,86 @@
package com.hxl.puyang.location.service.impl;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hxl.puyang.config.ReportConfig;
import com.hxl.puyang.config.netty.BootNettyClient;
import com.hxl.puyang.enums.DataTypeEnum;
import com.hxl.puyang.location.entity.LocationRealdata;
import com.hxl.puyang.location.service.LocationRealdataService;
import com.hxl.puyang.location.mapper.LocationRealdataMapper;
import com.hxl.puyang.location.model.DataModel;
import com.hxl.puyang.location.model.DataSecureModel;
import com.hxl.puyang.location.model.RealDataModel;
import com.hxl.puyang.location.service.LocationRealdataService;
import com.hxl.puyang.utils.DataSecureUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.List;
/**
* @author lzl
* @description 针对表hxl_location_realdata(实时定位表)的数据库操作Service实现
* @createDate 2024-10-15 11:04:40
*/
@Service
@Slf4j
public class LocationRealdataServiceImpl extends ServiceImpl<LocationRealdataMapper, LocationRealdata>
implements LocationRealdataService {
@Resource
private LocationRealdataMapper locationRealdataMapper;
@Resource
private ReportConfig reportConfig;
@Resource
private BootNettyClient bootNettyClient;
private final static String END_STR = "@@";
private final static int CODE = 200;
/**
* 上报人员位置信息
*/
@Override
public void reportRealData() {
log.info("开始上报——上报人员位置信息");
try {
//验证ReportConfig数据完整性
if (reportConfig.checkParam()) {
//1收集信息
List<RealDataModel> realDataModels = locationRealdataMapper.getRealData();
if (CollectionUtil.isNotEmpty(realDataModels)) {
for (RealDataModel r : realDataModels) {
r.setId(StrUtil.uuid());
}
//包装数据
DataSecureModel<RealDataModel> dataSecureModel = new DataSecureModel<>();
dataSecureModel.setCollectTime(DateUtil.format(DateUtil.date(), DatePattern.PURE_DATETIME_PATTERN));
dataSecureModel.setDatas(realDataModels);
//加密数据
String secureStr = DataSecureUtil.encryptBase64(JSONUtil.toJsonStr(dataSecureModel));
DataModel dataModel = new DataModel();
dataModel.setCompanyCode(reportConfig.getCompanyCode());
dataModel.setServiceId(DataTypeEnum.PERSONNEL_REAL.getServiceId());
dataModel.setData(secureStr);
bootNettyClient.sendData(JSONUtil.toJsonStr(dataModel) + END_STR, null, DataTypeEnum.PERSONNEL_REAL);
} else {
log.info("上报人员位置信息,未收集到可上报的数据");
}
}
} catch (Exception e) {
log.error("上报人员位置信息出错");
log.error(ExceptionUtil.stacktraceToString(e));
}
log.info("结束上报——上报人员位置信息");
}
}

View File

@ -0,0 +1,145 @@
package com.hxl.puyang.utils;
import com.hxl.puyang.config.exception.MyException;
import javax.crypto.Cipher;
import javax.crypto.KeyGenerator;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Base64;
/**
* AES加密工具类
*
* @author liangKai
* @version 1.0
* @date 2020/6/1510:42
*/
public class AesUtil {
/**
* AES密码器
*/
private static Cipher cipher;
/**
* 字符串编码
*/
private static final String KEY_CHARSET = "UTF-8";
/**
* 算法方式
*/
private static final String KEY_ALGORITHM = "AES";
/**
* 算法/模式/填充
*/
private static final String CIPHER_ALGORITHM_CBC = "AES/CBC/PKCS5Padding";
/**
* 私钥大小128/192/256(bits) 16/24/32bytes暂时使用128如果扩大需要更换java/jre里面的jar包
*/
private static final Integer PRIVATE_KEY_SIZE_BIT = 128;
private static final Integer PRIVATE_KEY_SIZE_BYTE = 16;
/**
* 加密
*
* @param secretKey 秘钥
* @param plainText 明文字符串
* @return
*/
public static String encrypt(String secretKey, String plainText) {
byte[] bytes = secretKey.getBytes(StandardCharsets.UTF_8);
if (bytes.length != PRIVATE_KEY_SIZE_BYTE) {
throw new MyException("AESUtil:Invalid AES secretKey length (must be 16 bytes)");
}
// 密文字符串
String cipherText = "";
try {
// 加密模式初始化参数
initParam(bytes, Cipher.ENCRYPT_MODE);
// 获取加密内容的字节数组
byte[] bytePlainText = plainText.getBytes(KEY_CHARSET);
// 执行加密
byte[] byteCipherText = cipher.doFinal(bytePlainText);
cipherText = Base64.getEncoder().encodeToString(byteCipherText);
} catch (Exception e) {
throw new MyException("AESUtil:encrypt fail!", e);
}
return cipherText;
}
/**
* 解密
*
* @param secretKey 秘钥
* @param cipherText 密文字符串
* @return
*/
public static String decrypt(String secretKey, String cipherText) {
byte[] bytes = secretKey.getBytes(StandardCharsets.UTF_8);
if (bytes.length != PRIVATE_KEY_SIZE_BYTE) {
throw new MyException("AESUtil:Invalid AES secretKey length (must be 16 bytes)");
}
// 明文字符串
String plainText = "";
try {
initParam(bytes, Cipher.DECRYPT_MODE);
// 将加密并编码后的内容解码成字节数组
byte[] byteCipherText = Base64.getDecoder().decode(cipherText);
// 解密
byte[] bytePlainText = cipher.doFinal(byteCipherText);
plainText = new String(bytePlainText, KEY_CHARSET);
} catch (Exception e) {
throw new MyException("AESUtil:decrypt fail!", e);
}
return plainText;
}
/**
* 初始化参数
*
* @param keyBytes 密钥加密的规则 16位
* @param mode 加密模式加密or解密
*/
public static void initParam(byte[] keyBytes, int mode) {
try {
// 防止Linux下生成随机key
SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");
secureRandom.setSeed(keyBytes);
// 获取key生成器
KeyGenerator keygen = KeyGenerator.getInstance(KEY_ALGORITHM);
keygen.init(PRIVATE_KEY_SIZE_BIT, secureRandom);
// 获得原始对称密钥的字节数组
byte[] raw = keyBytes;
// 根据字节数组生成AES内部密钥
SecretKeySpec key = new SecretKeySpec(raw, KEY_ALGORITHM);
// 根据指定算法"AES/CBC/PKCS5Padding"实例化密码器
cipher = Cipher.getInstance(CIPHER_ALGORITHM_CBC);
IvParameterSpec iv = new IvParameterSpec(keyBytes);
cipher.init(mode, key, iv);
} catch (Exception e) {
throw new MyException("AESUtil:initParam fail!", e);
}
}
/**
* 秘钥
*/
public static final String SECRET_KEY = "f271379419e349ba";
}

View File

@ -1,9 +1,5 @@
package com.hxl.puyang.utils;
import cn.hutool.crypto.SecureUtil;
import java.nio.charset.StandardCharsets;
/**
* @author: 刘振雷
* @time: 2024/10/15
@ -22,7 +18,7 @@ public class DataSecureUtil {
* @return
*/
public static String encryptBase64(String dataStr) {
return SecureUtil.aes(KEY.getBytes()).encryptBase64(dataStr, StandardCharsets.UTF_8);
return AesUtil.encrypt(KEY, dataStr);
}
/**
@ -32,6 +28,6 @@ public class DataSecureUtil {
* @return
*/
public static String decryptBase64(String encryptBase64Str) {
return SecureUtil.aes(KEY.getBytes()).decryptStr(encryptBase64Str, StandardCharsets.UTF_8);
return AesUtil.decrypt(KEY, encryptBase64Str);
}
}

View File

@ -25,7 +25,7 @@ xxl:
executor:
appname: longdeyang
address:
ip: 10.8.33.15
ip: 127.0.0.1
port: 8901
logpath: /data/applogs/xxl-job/jobhandler
logretentiondays: 30

View File

@ -33,9 +33,9 @@ xxl:
report-config:
company-name: 濮阳龙德洋新材料有限公司 #企业名称
company-code: 123456789 #企业编码
company-code: PY45700000010 #企业编码
# netty 连接信息
netty-config:
ip: 10.8.33.15
port: 8866
ip: 218.29.42.147
port: 9008

View File

@ -39,4 +39,38 @@
is_report,dealing_with_people_id,is_report_yq,
rid
</sql>
<!--获取需要上报的报警信息-->
<select id="getAlarmData" resultType="com.hxl.puyang.location.model.AlarmDataModel">
SELECT h.rid as id,
h.card_id AS deviceCode,
'1' AS deviceType,
DATE_FORMAT(h.alarm_time, '%Y%m%d%H%i%s') AS alarmStartTime,
CASE h.police_type
WHEN 1 THEN 3
WHEN 2 THEN 1
ELSE 4
END AS alarmType,
CAST(s.longitude as DECIMAL(9, 6)) AS longitude,
CAST(s.latitude as DECIMAL(9, 6)) AS latitude,
1 AS alarmStatus,
DATE_FORMAT(h.processing_time, '%Y%m%d%H%i%s') AS alarmEndTime,
0 AS deleted,
DATE_FORMAT(h.alarm_time, '%Y%m%d%H%i%s') AS createDate,
u.USER_NAME AS createBy,
DATE_FORMAT(h.processing_time, '%Y%m%d%H%i%s') AS updateDate,
h.dealing_with_people AS updateBy,
h.id AS oid,
h.rid as alarmCode
FROM
hxl_location_alarm_history h
INNER JOIN hxl_location_user u ON u.CARD_NO = h.card_id
INNER JOIN hxl_location_station s ON s.station_no = h.beacon_id
WHERE
h.police_type IN ( 1, 2, 3 )
AND h.handle_status = 1
and h.alarm_time > '2024-10-01'
and h.is_report_yq in (0,3)
and ifnull(h.false_positives,0) = 0
</select>
</mapper>

View File

@ -25,4 +25,23 @@
distance,signal_time,pre_beacon_id,
pre_signal_time,create_time,update_time
</sql>
<!--获取人员定位实时数据-->
<select id="getRealData" resultType="com.hxl.puyang.location.model.RealDataModel">
SELECT CAST(s.longitude as DECIMAL(9, 6)) AS longitude,
CAST(s.latitude as DECIMAL(9, 6)) AS latitude,
d.card_id AS locaterCode,
u.rid AS staffCode,
0 AS deleted,
DATE_FORMAT(IF(d.update_time IS NOT NULL, d.update_time, d.create_time), '%Y%m%d%H%i%s') AS createDate,
u.USER_NAME AS createBy,
DATE_FORMAT(IF(d.update_time IS NOT NULL, d.update_time, d.create_time), '%Y%m%d%H%i%s') AS updateDate,
u.USER_NAME AS updateBy
FROM hxl_location_realdata d
INNER JOIN hxl_location_user u ON u.CARD_NO = d.card_id
INNER JOIN hxl_location_station s ON s.station_no = d.beacon_id
WHERE
u.rid IS NOT NULL
AND (d.create_time > DATE_ADD( now(), INTERVAL - 180 SECOND ) OR d.update_time > DATE_ADD( now(), INTERVAL - 180 SECOND ))
</select>
</mapper>