feat(device): 新增设备状态管理集成服务

- 添加设备状态客户端接口,支持设备在线状态查询与设置
- 创建设备状态相关 DTO,包括设备状态、在线状态和状态动作枚举
- 实现设备状态集成服务,封装设备状态操作与异常处理逻辑
- 支持单个及批量设备在线状态检查与设置功能
- 提供
This commit is contained in:
2025-09-25 14:18:06 +08:00
parent 59baf8811b
commit 47c6b2ca67
5 changed files with 376 additions and 0 deletions

View File

@@ -0,0 +1,51 @@
package com.ycwl.basic.integration.device.client;
import com.ycwl.basic.integration.common.response.CommonResponse;
import com.ycwl.basic.integration.device.dto.status.DeviceStatusDTO;
import com.ycwl.basic.integration.device.dto.status.OnlineStatusResponseDTO;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import java.util.List;
@FeignClient(name = "zt-device", contextId = "deviceStatusClient", path = "/api/device/status")
public interface DeviceStatusClient {
/**
* 获取设备状态
*/
@GetMapping("/{deviceNo}")
CommonResponse<DeviceStatusDTO> getDeviceStatus(@PathVariable("deviceNo") String deviceNo);
/**
* 检查设备是否在线
*/
@GetMapping("/{deviceNo}/online")
CommonResponse<OnlineStatusResponseDTO> isDeviceOnline(@PathVariable("deviceNo") String deviceNo);
/**
* 获取所有在线设备
*/
@GetMapping("/online")
CommonResponse<List<DeviceStatusDTO>> getAllOnlineDevices();
/**
* 设置设备离线
*/
@PostMapping("/{deviceNo}/offline")
CommonResponse<String> setDeviceOffline(@PathVariable("deviceNo") String deviceNo);
/**
* 设置设备在线
*/
@PostMapping("/{deviceNo}/online")
CommonResponse<String> setDeviceOnline(@PathVariable("deviceNo") String deviceNo);
/**
* 清理过期设备状态
*/
@PostMapping("/clean")
CommonResponse<String> cleanExpiredDevices();
}

View File

@@ -0,0 +1,41 @@
package com.ycwl.basic.integration.device.dto.status;
/**
* 设备状态动作枚举
*/
public enum DeviceStatusActionEnum {
/**
* 设备注册
*/
REGISTER("register"),
/**
* 设备保活
*/
KEEPALIVE("keepalive"),
/**
* 设备注销
*/
UNREGISTER("unregister");
private final String action;
DeviceStatusActionEnum(String action) {
this.action = action;
}
public String getAction() {
return action;
}
public static DeviceStatusActionEnum fromString(String action) {
for (DeviceStatusActionEnum statusAction : values()) {
if (statusAction.action.equalsIgnoreCase(action)) {
return statusAction;
}
}
throw new IllegalArgumentException("Unknown device status action: " + action);
}
}

View File

@@ -0,0 +1,49 @@
package com.ycwl.basic.integration.device.dto.status;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.time.LocalDateTime;
/**
* 设备状态信息
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class DeviceStatusDTO {
/**
* 设备编号
*/
private String deviceNo;
/**
* 是否在线
*/
private Boolean isOnline;
/**
* 最后活动时间
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private LocalDateTime lastActiveTime;
/**
* 最后动作(register/keepalive/unregister)
*/
private String lastAction;
/**
* 客户端IP
*/
private String clientIP;
/**
* 状态更新时间
*/
@JsonFormat(pattern = "yyyy-MM-dd'T'HH:mm:ss'Z'")
private LocalDateTime updateTime;
}

View File

@@ -0,0 +1,24 @@
package com.ycwl.basic.integration.device.dto.status;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* 在线状态响应
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class OnlineStatusResponseDTO {
/**
* 设备编号
*/
private String deviceNo;
/**
* 是否在线
*/
private Boolean isOnline;
}

View File

@@ -0,0 +1,211 @@
package com.ycwl.basic.integration.device.service;
import com.ycwl.basic.integration.common.exception.IntegrationException;
import com.ycwl.basic.integration.common.response.CommonResponse;
import com.ycwl.basic.integration.common.service.IntegrationFallbackService;
import com.ycwl.basic.integration.device.client.DeviceStatusClient;
import com.ycwl.basic.integration.device.dto.status.DeviceStatusDTO;
import com.ycwl.basic.integration.device.dto.status.OnlineStatusResponseDTO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Slf4j
@Service
@RequiredArgsConstructor
public class DeviceStatusIntegrationService {
private final DeviceStatusClient deviceStatusClient;
private final IntegrationFallbackService fallbackService;
private static final String SERVICE_NAME = "zt-device";
public DeviceStatusDTO getDeviceStatus(String deviceNo) {
log.debug("获取设备状态, deviceNo: {}", deviceNo);
return fallbackService.executeWithFallback(
SERVICE_NAME,
"device:status:" + deviceNo,
() -> {
CommonResponse<DeviceStatusDTO> response = deviceStatusClient.getDeviceStatus(deviceNo);
return handleResponse(response, "获取设备状态失败");
},
DeviceStatusDTO.class
);
}
public OnlineStatusResponseDTO isDeviceOnline(String deviceNo) {
log.debug("检查设备是否在线, deviceNo: {}", deviceNo);
return fallbackService.executeWithFallback(
SERVICE_NAME,
"device:online:" + deviceNo,
() -> {
CommonResponse<OnlineStatusResponseDTO> response = deviceStatusClient.isDeviceOnline(deviceNo);
return handleResponse(response, "检查设备在线状态失败");
},
OnlineStatusResponseDTO.class
);
}
public List<DeviceStatusDTO> getAllOnlineDevices() {
log.debug("获取所有在线设备");
return fallbackService.executeWithFallback(
SERVICE_NAME,
"devices:online:all",
() -> {
CommonResponse<List<DeviceStatusDTO>> response = deviceStatusClient.getAllOnlineDevices();
return handleResponse(response, "获取所有在线设备失败");
},
List.class
);
}
public void setDeviceOffline(String deviceNo) {
log.debug("设置设备离线, deviceNo: {}", deviceNo);
CommonResponse<String> response = deviceStatusClient.setDeviceOffline(deviceNo);
handleResponse(response, "设置设备离线失败");
}
public void setDeviceOnline(String deviceNo) {
log.debug("设置设备在线, deviceNo: {}", deviceNo);
CommonResponse<String> response = deviceStatusClient.setDeviceOnline(deviceNo);
handleResponse(response, "设置设备在线失败");
}
public void cleanExpiredDevices() {
log.debug("清理过期设备状态");
CommonResponse<String> response = deviceStatusClient.cleanExpiredDevices();
handleResponse(response, "清理过期设备状态失败");
}
/**
* 安全地获取设备状态
*/
public Optional<DeviceStatusDTO> getDeviceStatusSafely(String deviceNo) {
try {
DeviceStatusDTO status = getDeviceStatus(deviceNo);
return Optional.ofNullable(status);
} catch (Exception e) {
log.warn("获取设备状态异常: deviceNo={}, error={}", deviceNo, e.getMessage());
return Optional.empty();
}
}
/**
* 安全地检查设备是否在线
*/
public boolean isDeviceOnlineSafely(String deviceNo) {
try {
OnlineStatusResponseDTO response = isDeviceOnline(deviceNo);
return response != null && Boolean.TRUE.equals(response.getIsOnline());
} catch (Exception e) {
log.warn("检查设备在线状态异常: deviceNo={}, error={}", deviceNo, e.getMessage());
return false;
}
}
/**
* 批量检查设备是否在线
*/
public boolean areAllDevicesOnline(List<String> deviceNos) {
if (deviceNos == null || deviceNos.isEmpty()) {
return true;
}
log.debug("批量检查设备在线状态, deviceNos: {}", deviceNos);
for (String deviceNo : deviceNos) {
if (!isDeviceOnlineSafely(deviceNo)) {
return false;
}
}
return true;
}
/**
* 批量设置设备离线
*/
public void setDevicesOffline(List<String> deviceNos) {
if (deviceNos == null || deviceNos.isEmpty()) {
return;
}
log.debug("批量设置设备离线, deviceNos: {}", deviceNos);
for (String deviceNo : deviceNos) {
try {
setDeviceOffline(deviceNo);
} catch (Exception e) {
log.error("设置设备离线失败: deviceNo={}, error={}", deviceNo, e.getMessage());
}
}
}
/**
* 批量设置设备在线
*/
public void setDevicesOnline(List<String> deviceNos) {
if (deviceNos == null || deviceNos.isEmpty()) {
return;
}
log.debug("批量设置设备在线, deviceNos: {}", deviceNos);
for (String deviceNo : deviceNos) {
try {
setDeviceOnline(deviceNo);
} catch (Exception e) {
log.error("设置设备在线失败: deviceNo={}, error={}", deviceNo, e.getMessage());
}
}
}
/**
* 获取在线设备数量
*/
public int getOnlineDeviceCount() {
try {
List<DeviceStatusDTO> onlineDevices = getAllOnlineDevices();
return onlineDevices != null ? onlineDevices.size() : 0;
} catch (Exception e) {
log.warn("获取在线设备数量失败: {}", e.getMessage());
return 0;
}
}
/**
* 获取指定设备编号列表中的在线设备
*/
public List<String> getOnlineDeviceNos(List<String> deviceNos) {
if (deviceNos == null || deviceNos.isEmpty()) {
return List.of();
}
return deviceNos.stream()
.filter(this::isDeviceOnlineSafely)
.toList();
}
/**
* 获取指定设备编号列表中的离线设备
*/
public List<String> getOfflineDeviceNos(List<String> deviceNos) {
if (deviceNos == null || deviceNos.isEmpty()) {
return List.of();
}
return deviceNos.stream()
.filter(deviceNo -> !isDeviceOnlineSafely(deviceNo))
.toList();
}
private <T> T handleResponse(CommonResponse<T> response, String errorMessage) {
if (response == null || !response.isSuccess()) {
String msg = response != null && response.getMessage() != null
? response.getMessage()
: errorMessage;
Integer code = response != null ? response.getCode() : 5000;
throw new IntegrationException(code, msg, SERVICE_NAME);
}
return response.getData();
}
}