Compare commits

...

3 Commits

  1. 5
      zc-business/src/main/java/com/zc/business/constant/RedisKeyConstants.java
  2. 1
      zc-business/src/main/java/com/zc/business/controller/DcDeviceController.java
  3. 192
      zc-business/src/main/java/com/zc/business/controller/DcMetricsController.java
  4. 4
      zc-business/src/main/java/com/zc/business/controller/DcTrafficStatisticsController.java
  5. 5
      zc-business/src/main/java/com/zc/business/domain/DcDevice.java
  6. 2
      zc-business/src/main/java/com/zc/business/message/device/handler/DeviceMessageHandler.java
  7. 58
      zc-business/src/main/java/com/zc/business/request/DcMessageAccessCountRequest.java
  8. 32
      zc-business/src/main/java/com/zc/business/service/IDcMetricsService.java
  9. 6
      zc-business/src/main/java/com/zc/business/service/IDcTrafficStatisticsService.java
  10. 2
      zc-business/src/main/java/com/zc/business/service/IDcTrafficVolumeForecastService.java
  11. 55
      zc-business/src/main/java/com/zc/business/service/impl/DcMetricsServiceImpl.java
  12. 4
      zc-business/src/main/java/com/zc/business/service/impl/DcTrafficStatisticsServiceImpl.java
  13. 4
      zc-business/src/main/java/com/zc/business/service/impl/DcTrafficVolumeForecastServiceImpl.java
  14. 4
      zc-business/src/main/java/com/zc/business/statistics/handler/TrafficAnalysis.java

5
zc-business/src/main/java/com/zc/business/constant/RedisKeyConstants.java

@ -29,4 +29,9 @@ public class RedisKeyConstants
public static String getDcDevicesTrafficStatisticsKey(Byte direction) {
return DC_DEVICES_TRAFFIC_STATISTICS + ":" + direction;
}
/**
* 监控物联服务器
*/
public static final String MONITOR_IOT_SERVER = "monitor:iotServer:";
}

1
zc-business/src/main/java/com/zc/business/controller/DcDeviceController.java

@ -367,7 +367,6 @@ public class DcDeviceController extends BaseController {
OkHttp okHttp = new OkHttp();
String string = JSON.toJSONString(props);
JSONObject jsonObject = JSON.parseObject(string);
RequestParams requestParams = new RequestParams(jsonObject);

192
zc-business/src/main/java/com/zc/business/controller/DcMetricsController.java

@ -0,0 +1,192 @@
package com.zc.business.controller;
import cn.hutool.core.date.DateUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.redis.RedisCache;
import com.zc.business.request.DcMessageAccessCountRequest;
import com.zc.business.service.IDcMetricsService;
import com.zc.common.core.httpclient.OkHttp;
import com.zc.common.core.httpclient.exception.HttpException;
import com.zc.common.core.httpclient.request.RequestParams;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import okhttp3.Response;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static com.zc.business.constant.RedisKeyConstants.MONITOR_IOT_SERVER;
/**
* 指标数据
* @author xiepufeng
*/
@Api(tags = "指标数据")
@RestController
@RequestMapping("/business/metrics")
public class DcMetricsController {
protected final Logger logger = LoggerFactory.getLogger(this.getClass());
@Resource
private IDcMetricsService dcMetricsService;
@Value("${iot.address}")
private String iotAddress;
@Resource
private RedisCache redisCache;
/**
* 设备总数
*/
@ApiOperation("设备总数")
@GetMapping("/device/count")
public AjaxResult deviceCount(){
return AjaxResult.success(dcMetricsService.deviceCount());
}
/**
* 产品总数
*/
@ApiOperation("产品总数")
@GetMapping("/product/count")
public AjaxResult productCount(){
return AjaxResult.success(dcMetricsService.productCount());
}
/**
* 异常设备总数
*/
@ApiOperation("异常设备总数")
@GetMapping("/device-abnormal/count")
public AjaxResult deviceAbnormalCount(){
return AjaxResult.success(dcMetricsService.deviceAbnormalCount());
}
/**
* 获取消息接入总数
*
* @param request 请求参数对象包含消息接入的相关条件
* @return 返回AjaxResult对象其中包含消息接入总数
* @throws HttpException 当HTTP请求发生错误时抛出
* @throws IOException 当进行网络读写操作发生错误时抛出
*/
@ApiOperation("接入数据总数")
@GetMapping("/message-access/count")
public AjaxResult messageAccessCount(@Validated DcMessageAccessCountRequest request) throws HttpException, IOException {
// 初始化OkHttp客户端
OkHttp okHttp = new OkHttp();
// 将请求对象转换为JSON字符串
String string = JSON.toJSONString(request);
JSONObject jsonObject = JSON.parseObject(string);
jsonObject.put("direction", "received_message");
// 将JSON对象转换为请求参数
RequestParams requestParams = new RequestParams(jsonObject);
// 默认请求URL
String url = iotAddress + "/api/iot/metrics/device-gateway/message/count";
// 如果请求中包含产品ID,则修改请求URL
if (request.getProductId() != null) {
url = iotAddress + "/api/iot/metrics/device/message/count";
}
// 发起HTTP GET请求并获取响应
Response response // 请求响应
= okHttp
.url(url) // 设置请求地址
.data(requestParams) // 设置请求参数
.get(); // 执行GET请求
// 将响应内容解析为AjaxResult对象并返回
return JSON.parseObject(response.body().string(), AjaxResult.class);
}
@ApiOperation("物联系统监控")
@GetMapping("/iot-server/monitor")
public AjaxResult iotServerMonitor() throws HttpException, IOException {
OkHttp okHttp = new OkHttp();
String url = iotAddress + "/monitor/server";
Response response // 请求响应
= okHttp
.url(url) // 请求地址
.get(); // 请求方法
return JSON.parseObject(response.body().string(), AjaxResult.class);
}
/**
* 物联系统监控指标前天昨天数据查询
* 该接口不接受任何参数返回前天和昨天的物联系统监控指标数据
*
* @return AjaxResult 返回一个包含前天和昨天监控指标数据的列表如果数据不存在则返回错误信息
*/
@ApiOperation("物联系统监控指标前天昨天数据")
@GetMapping("/iot-server/monitor-previous")
public AjaxResult iotServerChain() {
// 从Redis缓存中获取昨天和前天的监控数据
JSONObject yesterdayData = redisCache.getCacheObject(MONITOR_IOT_SERVER + DateUtil.formatDate(DateUtil.yesterday()));
JSONObject beforeYesterdayData = redisCache.getCacheObject(MONITOR_IOT_SERVER + DateUtil.formatDate(DateUtil.offsetDay(DateUtil.date(), -2)));
// 如果昨天或前天的数据为空,则返回错误信息
if (yesterdayData == null || beforeYesterdayData == null) {
return AjaxResult.error("暂无数据");
}
// 将数据放入列表并返回
List<JSONObject> dataList = new ArrayList<>();
dataList.add(beforeYesterdayData);
dataList.add(yesterdayData);
return AjaxResult.success(dataList);
}
/**
* 定时缓存物联系统监控数据
* 该方法使用CRON表达式0 0 0 * * ?定时在每天的0点执行
* 方法不接受参数也不返回任何值
* 主要步骤包括
* 1. 构造缓存键值基于监控数据和前一天的日期
* 2. 获取物联系统监控的详细数据
* 3. 设定缓存过期时间为3天
* 4. 将监控数据缓存起来
* 如果在执行过程中遇到HttpException或IOException会记录错误日志
*/
@Scheduled(cron = "0 0 0 * * ?")
public void cacheIotServerMonitor() {
try {
// 构造缓存键,使用MONITOR_IOT_SERVER常量和前一天的日期
String cacheKey = MONITOR_IOT_SERVER + DateUtil.formatDate(DateUtil.yesterday());
// 获取监控数据中的"data"部分
Object cacheValue = this.iotServerMonitor().get("data");
// 设定缓存过期时间为3天
Integer expireTime = 3;
// 将监控数据缓存到Redis中,设定过期时间
redisCache.setCacheObject(cacheKey, cacheValue, expireTime, TimeUnit.DAYS);
} catch (HttpException | IOException e) {
// 记录缓存失败的错误日志
logger.error("缓存物联系统监控数据失败", e);
}
}
}

4
zc-business/src/main/java/com/zc/business/controller/DcTrafficStatisticsController.java

@ -6,7 +6,7 @@ import com.zc.business.domain.DcTrafficMetricsData;
import com.zc.business.domain.DcTrafficSectionData;
import com.zc.business.request.DcTrafficMetricsDataRequest;
import com.zc.business.request.DcTrafficSectionDataRequest;
import com.zc.business.service.DcTrafficStatisticsService;
import com.zc.business.service.IDcTrafficStatisticsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@ -25,7 +25,7 @@ import java.util.List;
public class DcTrafficStatisticsController {
@Autowired
private DcTrafficStatisticsService dcTrafficStatisticsService;
private IDcTrafficStatisticsService dcTrafficStatisticsService;
/**

5
zc-business/src/main/java/com/zc/business/domain/DcDevice.java

@ -17,6 +17,11 @@ public class DcDevice {
public static final Integer UNUSEDSTATE = 0;
public static final Integer USEOFSTATE = 1;
// 异常的
public static final String ABNORMAL = "0";
// 正常的
public static final String NORMAL = "1";
// 离线状态
public static final String OFFLINE = "0";
// 在线状态

2
zc-business/src/main/java/com/zc/business/message/device/handler/DeviceMessageHandler.java

@ -53,7 +53,7 @@ public class DeviceMessageHandler {
private RedisCache redisCache;
@Resource
private DcTrafficStatisticsService dcTrafficSectionDataService;
private IDcTrafficStatisticsService dcTrafficSectionDataService;
@Autowired
private IDcMeteorologicalDetectorDataService meteorologicalDetectorDataService;

58
zc-business/src/main/java/com/zc/business/request/DcMessageAccessCountRequest.java

@ -0,0 +1,58 @@
package com.zc.business.request;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import javax.validation.constraints.NotNull;
import java.util.Date;
@Data
public class DcMessageAccessCountRequest {
// 年、月、日、小时,用于定义时间周期类型
public static final String YEAR = "year";
public static final String MONTH = "month";
public static final String DAY = "day";
public static final String HOUR = "hour";
@NotNull(message = "开始时间不能为空")
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
private String startTime;
// 查询结束时间
@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
@NotNull(message = "结束时间不能为空")
private String endTime;
// 时间周期类型(年、月、日、小时)
private String periodType;
private String productId;
/**
* 根据给定的周期类型字符串将其转换为简写的字符串表示
* @return 对应的简写字符串比如"1y""1m"
* @throws IllegalArgumentException 如果传入的periodType不是预期的值或为null
*/
public String convertPeriodType() throws IllegalArgumentException {
// 检查输入参数是否为null或空字符串
if (periodType == null || periodType.isEmpty()) {
throw new IllegalArgumentException("periodType不能为null或空");
}
// 使用switch语句处理不同的周期类型
switch (periodType) {
case YEAR:
return "1y";
case MONTH:
return "1M";
case DAY:
return "1d";
case HOUR:
return "1h";
default:
// 对于未预期的输入值,抛出异常
throw new IllegalArgumentException("不受支持的 periodType: " + periodType);
}
}
}

32
zc-business/src/main/java/com/zc/business/service/IDcMetricsService.java

@ -0,0 +1,32 @@
package com.zc.business.service;
/**
* DcMetricsService 接口定义了与指标相关的服务操作
*/
public interface IDcMetricsService {
/**
* 获取设备数量
*
* @return 设备数量返回类型为整数
*/
int deviceCount();
/**
* 获取产品数量
* 该方法用于统计当前系统中的产品总数不需要传入任何参数
*
* @return 产品数量返回类型为整数
*/
int productCount();
/**
* 获取设备异常数量
* 该方法用于统计当前系统中的异常设备总数不需要传入任何参数
*
* @return 返回设备异常数量类型为int
*/
int deviceAbnormalCount();
}

6
zc-business/src/main/java/com/zc/business/service/DcTrafficStatisticsService.java → zc-business/src/main/java/com/zc/business/service/IDcTrafficStatisticsService.java

@ -10,7 +10,11 @@ import com.zc.business.request.DcTrafficSectionDataRequest;
import java.util.List;
public interface DcTrafficStatisticsService extends IService<DcTrafficSectionData> {
/**
* 交通统计服务接口提供处理交通数据的相关方法
* @author xiepufeng
*/
public interface IDcTrafficStatisticsService extends IService<DcTrafficSectionData> {
/**
* 处理实时接收到的一类交流站设备消息并将其转换为交通断面统计数据对象并缓存

2
zc-business/src/main/java/com/zc/business/service/DcTrafficVolumeForecastService.java → zc-business/src/main/java/com/zc/business/service/IDcTrafficVolumeForecastService.java

@ -3,5 +3,5 @@ package com.zc.business.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.zc.business.domain.DcTrafficVolumeForecast;
public interface DcTrafficVolumeForecastService extends IService<DcTrafficVolumeForecast> {
public interface IDcTrafficVolumeForecastService extends IService<DcTrafficVolumeForecast> {
}

55
zc-business/src/main/java/com/zc/business/service/impl/DcMetricsServiceImpl.java

@ -0,0 +1,55 @@
package com.zc.business.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.zc.business.domain.DcDevice;
import com.zc.business.service.IDcMetricsService;
import com.zc.business.service.IDcDeviceService;
import com.zc.business.service.IDcProductService;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@Service
public class DcMetricsServiceImpl implements IDcMetricsService {
@Resource
private IDcDeviceService dcDeviceService;
@Resource
private IDcProductService dcProductService;
/**
* 获取设备数量
*
* @return 设备数量返回类型为整数
*/
@Override
public int deviceCount() {
return dcDeviceService.count();
}
/**
* 获取产品数量
* 该方法用于统计当前系统中的产品总数不需要传入任何参数
*
* @return 产品数量返回类型为整数
*/
@Override
public int productCount() {
return dcProductService.count();
}
/**
* 获取设备异常数量
* 该方法用于统计当前系统中的异常设备总数不需要传入任何参数
*
* @return 返回设备异常数量类型为int
*/
@Override
public int deviceAbnormalCount() {
LambdaQueryWrapper<DcDevice> queryWrapper = new LambdaQueryWrapper<>();
queryWrapper.eq(DcDevice::getDeviceState, DcDevice.ABNORMAL);
return dcDeviceService.count(queryWrapper);
}
}

4
zc-business/src/main/java/com/zc/business/service/impl/DcTrafficStatisticsServiceImpl.java

@ -19,7 +19,7 @@ import com.zc.business.request.DcTrafficMetricsDataRequest;
import com.zc.business.request.DcTrafficSectionDataRequest;
import com.zc.business.statistics.cache.*;
import com.zc.business.mapper.DcTrafficSectionDataMapper;
import com.zc.business.service.DcTrafficStatisticsService;
import com.zc.business.service.IDcTrafficStatisticsService;
import com.zc.business.statistics.handler.TrafficAnalysis;
import com.zc.business.statistics.handler.TrafficStatistics;
import com.zc.business.utils.StakeMarkUtils;
@ -44,7 +44,7 @@ import java.util.stream.Collectors;
@Service
public class DcTrafficStatisticsServiceImpl
extends ServiceImpl<DcTrafficSectionDataMapper, DcTrafficSectionData>
implements DcTrafficStatisticsService {
implements IDcTrafficStatisticsService {
// 日志记录器
protected final Logger logger = LoggerFactory.getLogger(this.getClass());

4
zc-business/src/main/java/com/zc/business/service/impl/DcTrafficVolumeForecastServiceImpl.java

@ -3,7 +3,7 @@ package com.zc.business.service.impl;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zc.business.domain.DcTrafficVolumeForecast;
import com.zc.business.mapper.DcTrafficVolumeForecastMapper;
import com.zc.business.service.DcTrafficVolumeForecastService;
import com.zc.business.service.IDcTrafficVolumeForecastService;
import org.springframework.stereotype.Service;
/**
@ -14,6 +14,6 @@ import org.springframework.stereotype.Service;
@Service
public class DcTrafficVolumeForecastServiceImpl
extends ServiceImpl<DcTrafficVolumeForecastMapper, DcTrafficVolumeForecast>
implements DcTrafficVolumeForecastService {
implements IDcTrafficVolumeForecastService {
}

4
zc-business/src/main/java/com/zc/business/statistics/handler/TrafficAnalysis.java

@ -8,7 +8,7 @@ import com.zc.business.constant.StakeMarkConstant;
import com.zc.business.domain.*;
import com.zc.business.enums.*;
import com.zc.business.request.DcTrafficMetricsDataRequest;
import com.zc.business.service.DcTrafficVolumeForecastService;
import com.zc.business.service.IDcTrafficVolumeForecastService;
import com.zc.business.utils.AlgorithmUtils;
import com.zc.business.utils.StakeMarkUtils;
import org.springframework.stereotype.Component;
@ -32,7 +32,7 @@ public class TrafficAnalysis {
private RedisCache redisCache;
@Resource
private DcTrafficVolumeForecastService dcTrafficVolumeForecastService;
private IDcTrafficVolumeForecastService dcTrafficVolumeForecastService;
// 使用ConcurrentHashMap来缓存路段ID和设计交通量,以提高并发性能和减少数据库访问
private static final Map<Long, HashMap<Integer, Integer>> designTrafficVolumeCache = new HashMap<>();

Loading…
Cancel
Save