Compare commits
15 Commits
2d3d3aa676
...
6609c2eb4d
| Author | SHA1 | Date | |
|---|---|---|---|
| 6609c2eb4d | |||
| c2bf0b3040 | |||
| c9106a2b94 | |||
| b315a4b2df | |||
| 4f1a67f622 | |||
| 96ccb45a7f | |||
| bac5cf2ff9 | |||
| 7d4ee71add | |||
| b86f94e1dd | |||
| 5fc60a0335 | |||
| 79e1784eed | |||
| 3ac2599f0a | |||
| b06943d6c9 | |||
| de8653e1a3 | |||
| 1d865e72ad |
@@ -35,3 +35,25 @@ CREATE TABLE api_setting(
|
|||||||
INSERT INTO api_setting(id,phone_number,access_token,msgtype,touser,agentid,enable_duplicate_check,duplicate_check_interval)
|
INSERT INTO api_setting(id,phone_number,access_token,msgtype,touser,agentid,enable_duplicate_check,duplicate_check_interval)
|
||||||
VALUES (1,'18281561650','gKGCDSgWV82XbU0H','textcard','@all',1000002,1,1800);
|
VALUES (1,'18281561650','gKGCDSgWV82XbU0H','textcard','@all',1000002,1,1800);
|
||||||
|
|
||||||
|
|
||||||
|
CREATE TABLE device_info (
|
||||||
|
id INT PRIMARY KEY AUTO_INCREMENT,
|
||||||
|
time_out_period BIGINT,
|
||||||
|
android_id VARCHAR(255),
|
||||||
|
serial_number VARCHAR(255),
|
||||||
|
device_model VARCHAR(255),
|
||||||
|
last_online_time BIGINT,
|
||||||
|
status INT
|
||||||
|
);
|
||||||
|
|
||||||
|
INSERT INTO device_info (time_out_period,android_id,serial_number,device_model,last_online_time,status) VALUES
|
||||||
|
(3600, 'android_id_1', 'SN1234567890', 'Model A', UNIX_TIMESTAMP(), 1),
|
||||||
|
(3600, 'android_id_2', 'SN1234567891', 'Model B', UNIX_TIMESTAMP(), 1),
|
||||||
|
(3600, 'android_id_3', 'SN1234567892', 'Model C', UNIX_TIMESTAMP(), 0),
|
||||||
|
(3600, 'android_id_4', 'SN1234567893', 'Model D', UNIX_TIMESTAMP(), 1),
|
||||||
|
(3600, 'android_id_5', 'SN1234567894', 'Model E', UNIX_TIMESTAMP(), 0),
|
||||||
|
(3600, 'android_id_6', 'SN1234567895', 'Model F', UNIX_TIMESTAMP(), 1),
|
||||||
|
(3600, 'android_id_7', 'SN1234567896', 'Model G', UNIX_TIMESTAMP(), 0),
|
||||||
|
(3600, 'android_id_8', 'SN1234567897', 'Model H', UNIX_TIMESTAMP(), 1),
|
||||||
|
(3600, 'android_id_9', 'SN1234567898', 'Model I', UNIX_TIMESTAMP(), 0),
|
||||||
|
(3600, 'android_id_10', 'SN1234567899', 'Model J', UNIX_TIMESTAMP(), 1);
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
package com.kimgo.wepush.controller;
|
||||||
|
|
||||||
|
import com.kimgo.wepush.model.CallInfo;
|
||||||
|
import com.kimgo.wepush.model.DeviceInfo;
|
||||||
|
import com.kimgo.wepush.response.ServerResponseEntity;
|
||||||
|
import com.kimgo.wepush.service.HeartBeatService;
|
||||||
|
import jakarta.validation.Valid;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestHeader;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
public class HeartbeatController {
|
||||||
|
@Autowired
|
||||||
|
private HeartBeatService heartBeatService;
|
||||||
|
|
||||||
|
@PostMapping("/heartbeat")
|
||||||
|
public ServerResponseEntity receiveHeartbeat(@RequestHeader("accessToken") String accessToken,
|
||||||
|
@RequestBody @Valid DeviceInfo deviceInfo) {
|
||||||
|
// 处理心跳请求
|
||||||
|
// 更新客户端的“最后活跃时间”
|
||||||
|
if(accessToken == null){
|
||||||
|
return ServerResponseEntity.fail("accessToken cannot be empty.");
|
||||||
|
}
|
||||||
|
if (deviceInfo == null || deviceInfo.hasInvalidFields()){
|
||||||
|
return ServerResponseEntity.fail("json body value error.");
|
||||||
|
}
|
||||||
|
return heartBeatService.handleHeartbeatSignal(accessToken,deviceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,6 +2,7 @@ package com.kimgo.wepush.mapper;
|
|||||||
|
|
||||||
import com.kimgo.wepush.model.ApiSetting;
|
import com.kimgo.wepush.model.ApiSetting;
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author wangsiyuan
|
* @author wangsiyuan
|
||||||
@@ -9,6 +10,7 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
* @createDate 2023-12-05 01:25:35
|
* @createDate 2023-12-05 01:25:35
|
||||||
* @Entity com.kimgo.wepush.model.ApiSetting
|
* @Entity com.kimgo.wepush.model.ApiSetting
|
||||||
*/
|
*/
|
||||||
|
@Mapper
|
||||||
public interface ApiSettingMapper extends BaseMapper<ApiSetting> {
|
public interface ApiSettingMapper extends BaseMapper<ApiSetting> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
package com.kimgo.wepush.mapper;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.kimgo.wepush.model.ApiSetting;
|
||||||
|
import com.kimgo.wepush.model.DeviceInfoDAO;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface DeviceInfoDAOMapper extends BaseMapper<DeviceInfoDAO> {
|
||||||
|
}
|
||||||
@@ -2,6 +2,8 @@ package com.kimgo.wepush.mapper;
|
|||||||
|
|
||||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
import com.kimgo.wepush.model.QyWeChatAppInfo;
|
import com.kimgo.wepush.model.QyWeChatAppInfo;
|
||||||
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
public interface QyWeChatAppInfoMapper extends BaseMapper<QyWeChatAppInfo> {
|
public interface QyWeChatAppInfoMapper extends BaseMapper<QyWeChatAppInfo> {
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,5 +4,6 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
|||||||
import com.kimgo.wepush.model.QyWeChatURL;
|
import com.kimgo.wepush.model.QyWeChatURL;
|
||||||
import org.apache.ibatis.annotations.Mapper;
|
import org.apache.ibatis.annotations.Mapper;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
public interface QyWeChatURLMapper extends BaseMapper<QyWeChatURL> {
|
public interface QyWeChatURLMapper extends BaseMapper<QyWeChatURL> {
|
||||||
}
|
}
|
||||||
|
|||||||
23
src/main/java/com/kimgo/wepush/model/DeviceInfo.java
Normal file
23
src/main/java/com/kimgo/wepush/model/DeviceInfo.java
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package com.kimgo.wepush.model;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DeviceInfo {
|
||||||
|
private String androidId;
|
||||||
|
private String serialNumber;
|
||||||
|
private String deviceModel;
|
||||||
|
public boolean hasInvalidFields() {
|
||||||
|
return isNullOrInvalid(androidId) || isNullOrInvalid(serialNumber) || isNullOrInvalid(deviceModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 检查给定的字符串是否为 null、"null" 或空字符串。
|
||||||
|
*
|
||||||
|
* @param value 要检查的字符串。
|
||||||
|
* @return 如果字符串为 null、"null" 或空字符串,则返回 true;否则返回 false。
|
||||||
|
*/
|
||||||
|
private boolean isNullOrInvalid(String value) {
|
||||||
|
return value == null || value.equals("null") || value.isEmpty();
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/main/java/com/kimgo/wepush/model/DeviceInfoDAO.java
Normal file
16
src/main/java/com/kimgo/wepush/model/DeviceInfoDAO.java
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package com.kimgo.wepush.model;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
@TableName("device_info")
|
||||||
|
public class DeviceInfoDAO {
|
||||||
|
private Integer id;
|
||||||
|
private long timeOutPeriod;
|
||||||
|
private String androidId;
|
||||||
|
private String serialNumber;
|
||||||
|
private String deviceModel;
|
||||||
|
private long lastOnlineTime;
|
||||||
|
private int status;
|
||||||
|
}
|
||||||
60
src/main/java/com/kimgo/wepush/request/Request.java
Normal file
60
src/main/java/com/kimgo/wepush/request/Request.java
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package com.kimgo.wepush.request;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||||
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
|
import com.kimgo.wepush.model.TextCardMessage;
|
||||||
|
import com.kimgo.wepush.response.QyWeChatSendMessageApiResponse;
|
||||||
|
import com.kimgo.wepush.service.QyWeChatURLService;
|
||||||
|
import com.kimgo.wepush.service.TokenService;
|
||||||
|
import okhttp3.MediaType;
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
|
import okhttp3.RequestBody;
|
||||||
|
import okhttp3.Response;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
public class Request {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(Request.class);
|
||||||
|
|
||||||
|
public <T> QyWeChatSendMessageApiResponse okhttpRequest(String url,String accessToken,T object){
|
||||||
|
OkHttpClient client = new OkHttpClient();
|
||||||
|
|
||||||
|
// 使用Jackson进行序列化
|
||||||
|
ObjectMapper objectMapper = new ObjectMapper();
|
||||||
|
String jsonBody = null;
|
||||||
|
try {
|
||||||
|
jsonBody = objectMapper.writeValueAsString(object);
|
||||||
|
logger.info("jsonBody: {}",jsonBody);
|
||||||
|
} catch (JsonProcessingException e) {
|
||||||
|
logger.error("JSON processing error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// 构建请求体
|
||||||
|
RequestBody body = RequestBody.create(MediaType.parse("application/json; charset=utf-8"), jsonBody);
|
||||||
|
okhttp3.Request request = new okhttp3.Request.Builder().url(url).post(body).build();
|
||||||
|
try (Response response = client.newCall(request).execute()) {
|
||||||
|
String responseBody = response.body().string();
|
||||||
|
logger.info("request sendMessage api ResponseBody: {}", responseBody);
|
||||||
|
|
||||||
|
ObjectMapper objectMapper1 = new ObjectMapper();
|
||||||
|
QyWeChatSendMessageApiResponse apiResponse = objectMapper1.readValue(responseBody, QyWeChatSendMessageApiResponse.class);
|
||||||
|
|
||||||
|
if (apiResponse.getErrcode() == 0) {
|
||||||
|
logger.debug("Request qyWeChat Success.");
|
||||||
|
return apiResponse;
|
||||||
|
} else if (apiResponse.getErrcode() == 42001 || apiResponse.getErrcode() == 40014) {
|
||||||
|
logger.info("Access token expired. Refreshing token...");
|
||||||
|
// 一个方法来刷新accessToken
|
||||||
|
return apiResponse;
|
||||||
|
} else {
|
||||||
|
// 处理其他错误情况
|
||||||
|
logger.error("Error: {}", apiResponse.getErrmsg());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("OkHttp request error", e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,8 +62,9 @@ public class ServerResponseEntity <T> implements Serializable {
|
|||||||
public static <T> ServerResponseEntity<T> success(){
|
public static <T> ServerResponseEntity<T> success(){
|
||||||
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
|
ServerResponseEntity<T> serverResponseEntity = new ServerResponseEntity<>();
|
||||||
serverResponseEntity.setCode(ResponseEnum.OK.value());
|
serverResponseEntity.setCode(ResponseEnum.OK.value());
|
||||||
serverResponseEntity.getMsg();
|
serverResponseEntity.setMsg(ResponseEnum.OK.getMsg());
|
||||||
serverResponseEntity.setTimestamp(Instant.now().getEpochSecond());
|
serverResponseEntity.setTimestamp(Instant.now().getEpochSecond());
|
||||||
|
serverResponseEntity.setData(null);
|
||||||
return serverResponseEntity;
|
return serverResponseEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
115
src/main/java/com/kimgo/wepush/service/HeartBeatService.java
Normal file
115
src/main/java/com/kimgo/wepush/service/HeartBeatService.java
Normal file
@@ -0,0 +1,115 @@
|
|||||||
|
package com.kimgo.wepush.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
|
||||||
|
import com.kimgo.wepush.mapper.DeviceInfoDAOMapper;
|
||||||
|
import com.kimgo.wepush.model.DeviceInfo;
|
||||||
|
import com.kimgo.wepush.model.DeviceInfoDAO;
|
||||||
|
import com.kimgo.wepush.model.QyWeChatAppInfo;
|
||||||
|
import com.kimgo.wepush.model.QyWeChatURL;
|
||||||
|
import com.kimgo.wepush.response.ServerResponseEntity;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.sql.Time;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class HeartBeatService {
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(HeartBeatService.class);
|
||||||
|
private final long TIME_OUT_PERIOD = 600;
|
||||||
|
@Autowired
|
||||||
|
TokenService tokenService;
|
||||||
|
@Autowired
|
||||||
|
private DeviceInfoDAOMapper deviceInfoDAOMapper;
|
||||||
|
public ServerResponseEntity handleHeartbeatSignal(String accessToken,DeviceInfo deviceInfo) {
|
||||||
|
String correctAccessToken = tokenService.getApiAccessToken();
|
||||||
|
logger.info("accessToken: {} correctAccessToken: {}",accessToken,correctAccessToken);
|
||||||
|
if (!correctAccessToken.equals(accessToken)){
|
||||||
|
return ServerResponseEntity.fail("Invalid accessToken");
|
||||||
|
}
|
||||||
|
DeviceInfoDAO deviceInfoDAO = getDeviceInfoByAndroidId(deviceInfo.getAndroidId());
|
||||||
|
if (deviceInfoDAO == null) {
|
||||||
|
// 设备信息不存在,可能是无效的设备
|
||||||
|
addDeviceInfo(deviceInfo);
|
||||||
|
return ServerResponseEntity.success();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
updateClientStatus(deviceInfo);
|
||||||
|
return ServerResponseEntity.success();
|
||||||
|
} catch (Exception e) {
|
||||||
|
// 处理更新状态时的异常
|
||||||
|
return ServerResponseEntity.fail("Error updating client status");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void updateClientStatus(DeviceInfo deviceInfo) {
|
||||||
|
long currentTimeMillis = System.currentTimeMillis();
|
||||||
|
// 更新该客户端的最后活跃时间
|
||||||
|
|
||||||
|
UpdateWrapper<DeviceInfoDAO> updateWrapper = new UpdateWrapper<>();
|
||||||
|
updateWrapper.eq("android_id", deviceInfo.getAndroidId());
|
||||||
|
updateWrapper.set("last_online_time", currentTimeMillis); // 设置新的 accessToken
|
||||||
|
|
||||||
|
int result = deviceInfoDAOMapper.update(null, updateWrapper);
|
||||||
|
if (result > 0) {
|
||||||
|
logger.debug("Update successful");
|
||||||
|
} else {
|
||||||
|
logger.warn("Update failed: No rows affected");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public boolean addDeviceInfo(DeviceInfo deviceInfo) {
|
||||||
|
try {
|
||||||
|
DeviceInfoDAO deviceInfoDAO = convertToDeviceInfoDAO(deviceInfo);
|
||||||
|
int result = deviceInfoDAOMapper.insert(deviceInfoDAO);
|
||||||
|
logger.info("result: {}",result);
|
||||||
|
return result > 0;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error adding device info", e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据 androidId 查询 DeviceInfo。
|
||||||
|
*
|
||||||
|
* @param androidId 要查询的 Android ID。
|
||||||
|
* @return 与 androidId 对应的 DeviceInfoDAO 对象,如果没有找到,则返回 null。
|
||||||
|
*/
|
||||||
|
public DeviceInfoDAO getDeviceInfoByAndroidId(String androidId) {
|
||||||
|
QueryWrapper<DeviceInfoDAO> queryWrapper = new QueryWrapper<>();
|
||||||
|
queryWrapper.eq("android_id", androidId);
|
||||||
|
try {
|
||||||
|
DeviceInfoDAO deviceInfoDAO = deviceInfoDAOMapper.selectOne(queryWrapper);
|
||||||
|
if (deviceInfoDAO != null) {
|
||||||
|
logger.info("Data is queried in the database based on the device id");
|
||||||
|
return deviceInfoDAO;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error querying device info by android ID", e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将 DeviceInfo 转换为 DeviceInfoDAO。
|
||||||
|
*
|
||||||
|
* @param deviceInfo 要转换的 DeviceInfo 对象。
|
||||||
|
* @return 转换后的 DeviceInfoDAO 对象。
|
||||||
|
*/
|
||||||
|
private DeviceInfoDAO convertToDeviceInfoDAO(DeviceInfo deviceInfo) {
|
||||||
|
// 这里需要实现将 DeviceInfo 转换为 DeviceInfoDAO 的逻辑
|
||||||
|
// 示例代码(根据实际字段调整):
|
||||||
|
DeviceInfoDAO deviceInfoDAO = new DeviceInfoDAO();
|
||||||
|
deviceInfoDAO.setAndroidId(deviceInfo.getAndroidId());
|
||||||
|
deviceInfoDAO.setSerialNumber(deviceInfo.getSerialNumber());
|
||||||
|
deviceInfoDAO.setDeviceModel(deviceInfo.getDeviceModel());
|
||||||
|
deviceInfoDAO.setTimeOutPeriod(TIME_OUT_PERIOD);
|
||||||
|
deviceInfoDAO.setLastOnlineTime(System.currentTimeMillis());
|
||||||
|
deviceInfoDAO.setStatus(1);
|
||||||
|
return deviceInfoDAO;
|
||||||
|
}
|
||||||
|
}
|
||||||
104
src/main/java/com/kimgo/wepush/service/MonitorService.java
Normal file
104
src/main/java/com/kimgo/wepush/service/MonitorService.java
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
package com.kimgo.wepush.service;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||||
|
import com.kimgo.wepush.mapper.DeviceInfoDAOMapper;
|
||||||
|
import com.kimgo.wepush.model.DeviceInfoDAO;
|
||||||
|
import com.kimgo.wepush.model.TextCardMessage;
|
||||||
|
import com.kimgo.wepush.request.Request;
|
||||||
|
import com.kimgo.wepush.response.QyWeChatSendMessageApiResponse;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.time.LocalDateTime;
|
||||||
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class MonitorService {
|
||||||
|
@Autowired
|
||||||
|
private ApiSettingService apiSettingService;
|
||||||
|
@Autowired
|
||||||
|
private QyWeChatURLService qyWeChatURLService;
|
||||||
|
@Autowired
|
||||||
|
private TokenService tokenService;
|
||||||
|
private final Logger logger = LoggerFactory.getLogger(MonitorService.class);
|
||||||
|
@Autowired
|
||||||
|
private DeviceInfoDAOMapper deviceInfoDAOMapper;
|
||||||
|
public void monitorOnlineDevices(){
|
||||||
|
List<DeviceInfoDAO> devices = getAllDeviceIds();
|
||||||
|
for (int i = 0; i < devices.size(); i++) {
|
||||||
|
long currentTimeMillis = System.currentTimeMillis();
|
||||||
|
if (currentTimeMillis - devices.get(i).getLastOnlineTime() > devices.get(i).getTimeOutPeriod()){
|
||||||
|
sendNotification(devices.get(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 获取数据库中所有DeviceInfoDAO对象的id。
|
||||||
|
*
|
||||||
|
* @return 包含所有id的列表。
|
||||||
|
*/
|
||||||
|
private List<DeviceInfoDAO> getAllDeviceIds() {
|
||||||
|
try {
|
||||||
|
// 查询所有DeviceInfoDAO对象
|
||||||
|
List<DeviceInfoDAO> deviceInfoDAOs = deviceInfoDAOMapper.selectList(new QueryWrapper<>());
|
||||||
|
// 提取并返回所有对象的id
|
||||||
|
return deviceInfoDAOs;
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Error querying all device info IDs", e);
|
||||||
|
}
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendNotification(DeviceInfoDAO deviceInfoDAO){
|
||||||
|
Request request = new Request();
|
||||||
|
String accessToken = tokenService.getAccessToken();
|
||||||
|
String url = qyWeChatURLService.getSendTextCardMessageUrl() + "?access_token=" + accessToken;
|
||||||
|
QyWeChatSendMessageApiResponse qyWeChatSendMessageApiResponse = request.okhttpRequest(url,accessToken,setTextCardMessage(deviceInfoDAO));
|
||||||
|
if (qyWeChatSendMessageApiResponse ==null){
|
||||||
|
logger.info("Send Notification Fail");
|
||||||
|
}
|
||||||
|
if (qyWeChatSendMessageApiResponse.getErrcode() == 0){
|
||||||
|
logger.info("Send Notification Success");
|
||||||
|
} else if (qyWeChatSendMessageApiResponse.getErrcode() == 42001 || qyWeChatSendMessageApiResponse.getErrcode() == 40014){
|
||||||
|
tokenService.setAccessToken();
|
||||||
|
accessToken = tokenService.getAccessToken();
|
||||||
|
QyWeChatSendMessageApiResponse qyApiResponse = request.okhttpRequest(url,accessToken,deviceInfoDAO);
|
||||||
|
if (qyApiResponse.getErrcode() == 0){
|
||||||
|
logger.info("Send Notification Success");
|
||||||
|
} else {
|
||||||
|
logger.error("Send Notification Fail");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logger.error("Send Notification Fail");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public TextCardMessage setTextCardMessage(DeviceInfoDAO deviceInfoDAO) {
|
||||||
|
TextCardMessage textCardMessage = new TextCardMessage();
|
||||||
|
|
||||||
|
textCardMessage.setTouser(apiSettingService.getApiSetting().getTouser());
|
||||||
|
textCardMessage.setMsgtype(apiSettingService.getApiSetting().getMsgtype());
|
||||||
|
textCardMessage.setAgentid(apiSettingService.getApiSetting().getAgentid());
|
||||||
|
textCardMessage.setEnable_duplicate_check(0);
|
||||||
|
|
||||||
|
TextCardMessage.TextCard textCard = new TextCardMessage.TextCard();
|
||||||
|
textCard.setTitle("设备掉线通知");
|
||||||
|
String formattedCurrentTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
|
||||||
|
textCard.setDescription("<div class='gray'>设备信息</div>" +
|
||||||
|
"<div class='highlight'>设备id: " + deviceInfoDAO.getAndroidId() + "</div>" +
|
||||||
|
"<div class='highlight'>设备型号: " + deviceInfoDAO.getDeviceModel() + "</div>" +
|
||||||
|
"<div class='highlight'>检测到掉线时间: " + formattedCurrentTime + "</div>"+
|
||||||
|
"检测到设备已掉线,请及时查看设备状态.");
|
||||||
|
textCard.setUrl("https://kimgo.cn");
|
||||||
|
// 将TextCard对象设置到TextCardMessage中
|
||||||
|
textCardMessage.setTextcard(textCard);
|
||||||
|
|
||||||
|
logger.info("TextCardMessage: {}", textCardMessage.toString());
|
||||||
|
|
||||||
|
return textCardMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -18,7 +18,6 @@ public class QyWeChatURLService {
|
|||||||
private QyWeChatURLMapper qyWeChatURLMapper;
|
private QyWeChatURLMapper qyWeChatURLMapper;
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserConfig userConfig;
|
private UserConfig userConfig;
|
||||||
private String urlName;
|
|
||||||
private String sendTextCardMessageUrl;
|
private String sendTextCardMessageUrl;
|
||||||
private String qyWechatGetTokenUrl;
|
private String qyWechatGetTokenUrl;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package com.kimgo.wepush.service;
|
||||||
|
|
||||||
|
import com.kimgo.wepush.model.DeviceInfo;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class HeartBeatServiceTest {
|
||||||
|
@Autowired
|
||||||
|
HeartBeatService heartBeatService;
|
||||||
|
@Test
|
||||||
|
void updateClientStatus() {
|
||||||
|
DeviceInfo deviceInfo = new DeviceInfo();
|
||||||
|
deviceInfo.setDeviceModel("Model B");
|
||||||
|
deviceInfo.setSerialNumber("SN1234567891");
|
||||||
|
deviceInfo.setAndroidId("android_id_2");
|
||||||
|
heartBeatService.updateClientStatus(deviceInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void addDeviceInfo() {
|
||||||
|
DeviceInfo deviceInfo = new DeviceInfo();
|
||||||
|
deviceInfo.setDeviceModel("Model C");
|
||||||
|
deviceInfo.setSerialNumber("SN1234567899");
|
||||||
|
deviceInfo.setAndroidId("dadwdwfcev");
|
||||||
|
heartBeatService.addDeviceInfo(deviceInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package com.kimgo.wepush.service;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
|
||||||
|
@SpringBootTest
|
||||||
|
class MonitorServiceTest {
|
||||||
|
@Autowired
|
||||||
|
private MonitorService monitorService;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void monitorOnlineDevices() {
|
||||||
|
|
||||||
|
monitorService.monitorOnlineDevices();
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user