Răsfoiți Sursa

更新! 取消GateWay信息

TRX 1 an în urmă
părinte
comite
a42f97cebb
17 a modificat fișierele cu 312 adăugiri și 136 ștergeri
  1. 0 20
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/baseParam/SeriesModel.java
  2. 6 0
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/statistics/DeviceStatisticsModel.java
  3. 0 28
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/statistics/LineModel.java
  4. 11 6
      OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoSearchParam.java
  5. 13 6
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/devices/DeviceStatisticsController.java
  6. 0 63
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/devices/GateWayController.java
  7. 1 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/OperationMessageDao.java
  8. 5 1
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/extend/DeviceInfoDaoExtend.java
  9. 4 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/extend/OperationMessageDaoExtend.java
  10. 62 2
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/impl/DeviceInfoDaoImpl.java
  11. 50 2
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/impl/OperationMessageDaoImpl.java
  12. 38 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/device/OperationMessage.java
  13. 45 1
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/device/OperationMessageResult.java
  14. 1 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/artemis/OperationMessageService.java
  15. 7 3
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DeviceOnLineRecordService.java
  16. 60 0
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DeviceStatisticsService.java
  17. 9 4
      OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotSendMessageService.java

+ 0 - 20
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/baseParam/SeriesModel.java

@@ -1,20 +0,0 @@
-package com.zhongshu.iot.client.model.baseParam;
-
-import lombok.Data;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * @author TRX
- * @date 2025/2/27
- */
-@Data
-public class SeriesModel {
-
-    private List<Object> series = new ArrayList<Object>();
-
-    public void addSeries(Object series) {
-        this.series.add(series);
-    }
-}

+ 6 - 0
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/statistics/DeviceStatisticsModel.java

@@ -1,5 +1,6 @@
 package com.zhongshu.iot.client.model.iot.statistics;
 
+import com.github.microservice.models.statistics.PieModel;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
@@ -30,4 +31,9 @@ public class DeviceStatisticsModel {
     @Schema(description = "消息今日新增")
     private Long toDayMessageNumber = 0L;
 
+    @Schema(description = "设备分类统计图")
+    private PieModel devicePie = new PieModel();
+
+    @Schema(description = "设备状态统计图")
+    private PieModel deviceStatePie = new PieModel();
 }

+ 0 - 28
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/iot/statistics/LineModel.java

@@ -1,28 +0,0 @@
-package com.zhongshu.iot.client.model.iot.statistics;
-
-import com.zhongshu.iot.client.model.baseParam.SeriesModel;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * 折现图数据
- *
- * @author TRX
- * @date 2025/2/27
- */
-@Data
-public class LineModel {
-
-    @Schema(description = "X轴数据,横向方向")
-    private List<String> xAxis = new ArrayList<String>();
-
-    @Schema(description = "Y轴的数据")
-    private List<SeriesModel> series = new ArrayList<>();
-
-    public void addSeries(SeriesModel series) {
-        this.series.add(series);
-    }
-}

+ 11 - 6
OneCardIotClient/src/main/java/com/zhongshu/iot/client/model/mqtt/DeviceInfoSearchParam.java

@@ -1,13 +1,11 @@
 package com.zhongshu.iot.client.model.mqtt;
 
-import com.github.microservice.types.deviceUse.DeviceCategory;
-import com.github.microservice.types.deviceUse.DeviceSpecType;
-import com.github.microservice.types.deviceUse.DeviceType;
-import com.github.microservice.types.deviceUse.OnLineState;
+import com.github.microservice.types.deviceUse.*;
 import com.zhongshu.iot.client.model.baseParam.SuperSearchParam;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -26,8 +24,13 @@ public class DeviceInfoSearchParam extends SuperSearchParam {
     @Schema(description = "所属项目code")
     private String projectInfoCode;
 
+    @Schema(description = "设备code,产品code")
+    private String productCode;
+
     @Schema(description = "设备类型:消费机 闸机")
-    private DeviceType deviceType;
+    private List<DeviceType> deviceTypes = new ArrayList<>();
+
+    private List<DeviceType> ninDeviceTypes = new ArrayList<DeviceType>();
 
     @Schema(description = "设备型号")
     private DeviceSpecType specType;
@@ -36,5 +39,7 @@ public class DeviceInfoSearchParam extends SuperSearchParam {
     private OnLineState onLineState;
 
     @Schema(description = "区分是网关还是设备")
-    private List<DeviceCategory> deviceCategorys = List.of(DeviceCategory.DE);
+    private List<DeviceCategory> deviceCategorys;
+
+    private DeviceState state;
 }

+ 13 - 6
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/devices/DeviceStatisticsController.java

@@ -3,6 +3,7 @@ package com.zhongshu.iot.server.core.controller.devices;
 import com.github.microservice.auth.security.annotations.ResourceAuth;
 import com.github.microservice.auth.security.type.AuthType;
 import com.github.microservice.net.ResultContent;
+import com.zhongshu.iot.client.model.artemis.OperationMessageSearchParam;
 import com.zhongshu.iot.client.model.iot.ping.DeviceOnLineRecordSearch;
 import com.zhongshu.iot.server.core.service.device.DeviceOnLineRecordService;
 import com.zhongshu.iot.server.core.service.device.DeviceStatisticsService;
@@ -34,17 +35,23 @@ public class DeviceStatisticsController {
     private DeviceOnLineRecordService deviceOnLineRecordService;
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "设备在线状态统计")
+    @Operation(summary = "设备等统计数量")
+    @RequestMapping(value = "deviceStatistics", method = {RequestMethod.GET})
+    public ResultContent deviceStatistics() {
+        return deviceStatisticsService.deviceStatistics();
+    }
+
+    @ResourceAuth(value = "user", type = AuthType.User)
+    @Operation(summary = "设备在线折线图状态统计")
     @RequestMapping(value = "statisticsDeviceOnLine", method = {RequestMethod.POST})
     public ResultContent statisticsDeviceOnLine(@RequestBody DeviceOnLineRecordSearch param) {
         return deviceOnLineRecordService.statisticsDeviceOnLine(param);
     }
 
     @ResourceAuth(value = "user", type = AuthType.User)
-    @Operation(summary = "设备等统计数量")
-    @RequestMapping(value = "deviceStatistics", method = {RequestMethod.GET})
-    public ResultContent deviceStatistics() {
-        return deviceStatisticsService.deviceStatistics();
+    @Operation(summary = "实时消息上下行 TPS")
+    @RequestMapping(value = "statisticsMessageLine", method = {RequestMethod.POST})
+    public ResultContent statisticsMessageLine(@RequestBody OperationMessageSearchParam param) {
+        return deviceStatisticsService.statisticsMessageLine(param);
     }
-
 }

+ 0 - 63
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/controller/devices/GateWayController.java

@@ -1,63 +0,0 @@
-package com.zhongshu.iot.server.core.controller.devices;
-
-import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
-
-/**
- * 网关管理 服务
- *
- * @author TRX
- * @date 2024/3/21
- */
-@RequestMapping("/gateWay")
-@RestController
-@Validated
-@Tag(name = "网关管理")
-@Deprecated
-public class GateWayController {
-
-//    @Autowired
-//    GateWayInfoService gateWayInfoService;
-//
-//    @ResourceAuth(value = "user", type = AuthType.User)
-//    @Operation(summary = "添加网关")
-//    @RequestMapping(value = "addDeviceInfo", method = {RequestMethod.POST})
-//    public ResultContent addDeviceInfo(@RequestBody GateWayInfoAddParam param) {
-//        Assert.hasText(param.getGateWayId(), "网关ID不能为空");
-//        Assert.hasText(param.getGateWayName(), "网关名称不能为空");
-//        return gateWayInfoService.addGateWayInfo(param);
-//    }
-//
-//    @ResourceAuth(value = "user", type = AuthType.User)
-//    @Operation(summary = "网关列表-分页查询")
-//    @RequestMapping(value = {"pageGateWay"}, method = {RequestMethod.POST})
-//    public ResultContent<Page<GateWayInfoModel>> pageGateWay(@Parameter(hidden = true) @PageableDefault(page = 0, size = 10) Pageable pageable, GateWayInfoSearchParam param) {
-//        return gateWayInfoService.pageGateWay(pageable, param);
-//    }
-//
-//    @ResourceAuth(value = "user", type = AuthType.User)
-//    @Operation(summary = "删除网关")
-//    @RequestMapping(value = "deleteGateWayInfo", method = {RequestMethod.GET})
-//    public ResultContent deleteGateWayInfo(String gateWayId) {
-//        return gateWayInfoService.deleteGateWayInfo(gateWayId);
-//    }
-//
-//    @ResourceAuth(value = "user", type = AuthType.User)
-//    @Operation(summary = "查询网关")
-//    @RequestMapping(value = "getGateWayById", method = {RequestMethod.GET})
-//    public ResultContent<GateWayInfoModel> getGateWayById(String deviceId) {
-//        return gateWayInfoService.getById(deviceId);
-//    }
-//
-//    @ResourceAuth(value = "user", type = AuthType.User)
-//    @Operation(summary = "网关绑定设备、连接账号")
-//    @RequestMapping(value = "gateWayBindDevice", method = {RequestMethod.POST})
-//    public ResultContent gateWayBindDevice(@RequestBody GateWayBindDeviceParam param) {
-//        Assert.hasText(param.getGateWayId(), "网关ID不能为空");
-//        Assert.hasText(param.getUserName(), "连接账号不能为空");
-//        return gateWayInfoService.gateWayBindDevice(param);
-//    }
-
-}

+ 1 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/OperationMessageDao.java

@@ -17,4 +17,5 @@ public interface OperationMessageDao extends OperationMessageDaoExtend, org.spri
 
     // 业务数据是否存在
     boolean existsByDataId(String dataId);
+
 }

+ 5 - 1
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/extend/DeviceInfoDaoExtend.java

@@ -1,10 +1,12 @@
 package com.zhongshu.iot.server.core.dao.mqtt.extend;
 
-import com.zhongshu.iot.server.core.domain.iot.device.DeviceInfo;
 import com.zhongshu.iot.client.model.mqtt.DeviceInfoSearchParam;
+import com.zhongshu.iot.server.core.domain.iot.device.DeviceInfo;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 
+import java.util.Map;
+
 /**
  * @Author TRX
  * @CreateDate: 2023/7/7
@@ -16,4 +18,6 @@ public interface DeviceInfoDaoExtend {
 
     Long count(DeviceInfoSearchParam param);
 
+    Map<String, Long> deviceGroupStatistics(DeviceInfoSearchParam param, String fieldName);
+
 }

+ 4 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/extend/OperationMessageDaoExtend.java

@@ -1,10 +1,13 @@
 package com.zhongshu.iot.server.core.dao.mqtt.extend;
 
+import com.zhongshu.iot.client.model.iot.ping.DeviceOnLineRecordSearch;
 import com.zhongshu.iot.server.core.domain.iot.device.OperationMessage;
 import com.zhongshu.iot.client.model.artemis.OperationMessageSearchParam;
 import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 
+import java.util.Map;
+
 /**
  * @Author TRX
  * @CreateDate: 2023/7/7
@@ -22,4 +25,5 @@ public interface OperationMessageDaoExtend {
 
     Long count(OperationMessageSearchParam param);
 
+    Map<String, Long> statisticsMinuteNumber(OperationMessageSearchParam param);
 }

+ 62 - 2
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/impl/DeviceInfoDaoImpl.java

@@ -5,6 +5,7 @@ import com.zhongshu.iot.client.model.mqtt.DeviceInfoSearchParam;
 import com.zhongshu.iot.server.core.dao.base.BaseImpl;
 import com.zhongshu.iot.server.core.dao.mqtt.extend.DeviceInfoDaoExtend;
 import com.zhongshu.iot.server.core.domain.iot.device.DeviceInfo;
+import com.zhongshu.iot.server.core.util.CommonUtil;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -12,12 +13,16 @@ import org.springframework.data.domain.Page;
 import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.aggregation.Aggregation;
+import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.util.CollectionUtils;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Pattern;
 
 /**
@@ -49,9 +54,45 @@ public class DeviceInfoDaoImpl extends BaseImpl implements DeviceInfoDaoExtend {
         return mongoTemplate.count(query, DeviceInfo.class);
     }
 
+    @Override
+    public Map<String, Long> deviceGroupStatistics(DeviceInfoSearchParam param, String fieldName) {
+        Criteria criteria = buildFilterCriteria(param);
+
+        Map<String, Long> map = new HashMap<>();
+
+        List<AggregationOperation> operations = new ArrayList<>(3);
+        // 条件
+        AggregationOperation match = Aggregation.match(criteria);
+        operations.add(match);
+
+        // 分组
+        AggregationOperation group = Aggregation.group("$" + fieldName).count().as("count");
+        operations.add(group);
+
+        // 排序
+        AggregationOperation sort = Aggregation.sort(Sort.Direction.ASC, fieldName);
+        operations.add(sort);
+
+        Aggregation groupAggregation = Aggregation.newAggregation(operations);
+        List<Map> countObjs = mongoTemplate.aggregate(groupAggregation, DeviceInfo.class, Map.class).getMappedResults();
+        if (countObjs.size() > 0) {
+            countObjs.stream().forEach(it -> {
+                String name = (String) it.get(fieldName);
+                if (StringUtils.isEmpty(name)) {
+                    Object _id = it.get("_id");
+                    name = String.valueOf(_id);
+                }
+                Long number = CommonUtil.getLongByObj(it.get("count"));
+                map.put(name, number);
+            });
+        }
+        return map;
+    }
+
     public Criteria buildFilterCriteria(DeviceInfoSearchParam param) {
         Criteria criteria = buildCriteriaAboutTime(param);
 
+        // 设备品类
         if (ObjectUtils.isNotEmpty(param.getDeviceCategorys())) {
             criteria.and("deviceCategory").in(param.getDeviceCategorys());
         }
@@ -60,22 +101,41 @@ public class DeviceInfoDaoImpl extends BaseImpl implements DeviceInfoDaoExtend {
             criteria.and("deviceId").is(param.getDeviceId());
         }
 
+        // 分组
         if (StringUtils.isNotEmpty(param.getProjectInfoCode())) {
             criteria.and("projectInfoCode").is(param.getProjectInfoCode());
         }
 
+        // 所属产品
+        if (StringUtils.isNotEmpty(param.getProductCode())) {
+            criteria.and("productCode").is(param.getProductCode());
+        }
+
+        // 设备型号
         if (param.getSpecType() != null) {
             criteria.and("specType").is(param.getSpecType());
         }
 
-        if (param.getDeviceType() != null) {
-            criteria.and("deviceType").is(param.getDeviceType());
+        if (ObjectUtils.isNotEmpty(param.getDeviceTypes())) {
+            if (ObjectUtils.isNotEmpty(param.getNinDeviceTypes())) {
+                criteria.and("deviceType").in(param.getDeviceTypes()).nin(param.getNinDeviceTypes());
+            } else {
+                criteria.and("deviceType").in(param.getDeviceTypes());
+            }
+        } else {
+            if (ObjectUtils.isNotEmpty(param.getNinDeviceTypes())) {
+                criteria.and("deviceType").nin(param.getNinDeviceTypes());
+            }
         }
 
         if (param.getOnLineState() != null) {
             criteria.and("onLineState").is(param.getOnLineState());
         }
 
+        if (param.getState() != null) {
+            criteria.and("state").is(param.getState());
+        }
+
         // 模糊搜索
         List<Criteria> criterias = new ArrayList<>();
         if (StringUtils.isNotEmpty(param.getDeviceName())) {

+ 50 - 2
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/dao/mqtt/impl/OperationMessageDaoImpl.java

@@ -4,7 +4,9 @@ import com.github.microservice.components.data.mongo.mongo.helper.DBHelper;
 import com.zhongshu.iot.client.model.artemis.OperationMessageSearchParam;
 import com.zhongshu.iot.server.core.dao.base.BaseImpl;
 import com.zhongshu.iot.server.core.dao.mqtt.extend.OperationMessageDaoExtend;
+import com.zhongshu.iot.server.core.domain.iot.device.DeviceOnLineRecord;
 import com.zhongshu.iot.server.core.domain.iot.device.OperationMessage;
+import com.zhongshu.iot.server.core.util.CommonUtil;
 import com.zhongshu.iot.server.core.util.TokenUtil;
 import org.apache.commons.lang3.ObjectUtils;
 import org.apache.commons.lang3.StringUtils;
@@ -16,13 +18,17 @@ import org.springframework.data.domain.Pageable;
 import org.springframework.data.domain.Sort;
 import org.springframework.data.mongodb.core.FindAndModifyOptions;
 import org.springframework.data.mongodb.core.MongoTemplate;
+import org.springframework.data.mongodb.core.aggregation.Aggregation;
+import org.springframework.data.mongodb.core.aggregation.AggregationOperation;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Query;
 import org.springframework.data.mongodb.core.query.Update;
 import org.springframework.util.CollectionUtils;
 
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.regex.Pattern;
 
 /**
@@ -101,8 +107,50 @@ public class OperationMessageDaoImpl extends BaseImpl implements OperationMessag
         return StringUtils.isEmpty(flowDisposition.getToken());
     }
 
+    /**
+     * 统计
+     *
+     * @param param
+     * @return
+     */
+    @Override
+    public Map<String, Long> statisticsMinuteNumber(OperationMessageSearchParam param) {
+        Criteria criteria = buildFilterCriteria(param);
+
+        String fieldName = "minuteKey";
+        Map<String, Long> map = new HashMap<>();
+
+        List<AggregationOperation> operations = new ArrayList<>(3);
+        // 条件
+        AggregationOperation match = Aggregation.match(criteria);
+        operations.add(match);
+
+        // 分组
+        AggregationOperation group = Aggregation.group("$" + fieldName).count().as("count");
+        operations.add(group);
+
+        // 排序
+        AggregationOperation sort = Aggregation.sort(Sort.Direction.ASC, fieldName);
+        operations.add(sort);
+
+        Aggregation groupAggregation = Aggregation.newAggregation(operations);
+        List<Map> countObjs = mongoTemplate.aggregate(groupAggregation, OperationMessage.class, Map.class).getMappedResults();
+        if (countObjs.size() > 0) {
+            countObjs.stream().forEach(it -> {
+                String name = (String) it.get(fieldName);
+                if (StringUtils.isEmpty(name)) {
+                    Object _id = it.get("_id");
+                    name = String.valueOf(_id);
+                }
+                Long number = CommonUtil.getLongByObj(it.get("count"));
+                map.put(name, number);
+            });
+        }
+        return map;
+    }
+
     public Criteria buildFilterCriteria(OperationMessageSearchParam param) {
-        Criteria criteria = buildCriteria(param);
+        Criteria criteria = buildCriteriaAboutTime(param);
 
         if (StringUtils.isNotEmpty(param.getDeviceId())) {
             criteria.and("deviceId").is(param.getDeviceId());
@@ -130,7 +178,7 @@ public class OperationMessageDaoImpl extends BaseImpl implements OperationMessag
             criteria.and("event").nin(param.getNevents());
         }
 
-        // 消息业务类型
+        // 消息业务类型 设备上下行信息 平时的平等消息
         if (param.getOperationBusType() != null) {
             criteria.and("operationBusType").is(param.getOperationBusType());
         }

+ 38 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/device/OperationMessage.java

@@ -1,6 +1,7 @@
 package com.zhongshu.iot.server.core.domain.iot.device;
 
 import cn.hutool.json.JSONObject;
+import com.zhongshu.card.client.utils.DateUtils;
 import com.zhongshu.iot.client.type.OperationBusType;
 import com.zhongshu.iot.client.type.OperationType;
 import com.zhongshu.iot.server.core.domain.base.SuperEntity;
@@ -155,4 +156,41 @@ public class OperationMessage extends SuperEntity {
     @Schema(description = "是否响应成功")
     private Boolean reIsSuccess;
 
+    //------------------------------时间信息 start--------------------
+    @Schema(description = "年份,如:2024")
+    private Integer year;
+
+    @Schema(description = "月份,如:6")
+    private Integer month;
+
+    @Schema(description = "当前月的第几天")
+    private Integer dayOfMonth;
+
+    @Schema(description = "今年第几周,如:32")
+    private Integer week;
+
+    @Schema(description = "当前年的第几天")
+    private Integer dayOfYear;
+
+    @Schema(description = "当前的第几小时")
+    private Integer hourOfDay;
+
+    @Schema(description = "分钟key")
+    private String minuteKey;
+
+    @Schema(description = "小时key")
+    private String hourKey;
+
+    public void setTimes() {
+        this.year = DateUtils.getCurrentYear();
+        this.month = DateUtils.getCurrentMonthInYear();
+        this.dayOfMonth = DateUtils.getCurrentDayInMonth();
+        this.hourOfDay = DateUtils.getCurrentHourOfDay();
+
+        this.dayOfYear = DateUtils.getCurrentDayInYear();
+        this.week = DateUtils.getCurrentWeekInYear();
+        this.minuteKey = DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyyMMddHHmmKey);
+        this.hourKey = DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyyMMddHHKey);
+    }
+
 }

+ 45 - 1
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/domain/iot/device/OperationMessageResult.java

@@ -1,6 +1,7 @@
 package com.zhongshu.iot.server.core.domain.iot.device;
 
 import cn.hutool.json.JSONObject;
+import com.zhongshu.card.client.utils.DateUtils;
 import com.zhongshu.iot.client.type.OperationBusType;
 import com.zhongshu.iot.client.type.OperationType;
 import com.zhongshu.iot.server.core.domain.base.SuperEntity;
@@ -28,6 +29,12 @@ public class OperationMessageResult extends SuperEntity {
     @Schema(description = "关联的mqtt账号")
     private String mqttUserName;
 
+    @Schema(description = "所属物模型id")
+    private String iotThingId;
+
+    @Schema(description = "所属产品code")
+    private String productCode;
+
     @Schema(description = "消息内容")
     @DBRef(lazy = true)
     private OperationMessage operationMessage;
@@ -121,7 +128,7 @@ public class OperationMessageResult extends SuperEntity {
     @Schema(description = "是否响应成功")
     private Boolean reIsSuccess;
 
-    //-------------------------消息是否送达 start-------------------------
+    //-------------------------消息是否送达 start---------------------
 
     @Schema(description = "是否需要确定是否送达")
     private Boolean isNeedReceived = Boolean.FALSE;
@@ -132,4 +139,41 @@ public class OperationMessageResult extends SuperEntity {
     @Schema(description = "确定送达时间")
     private Long receivedTime;
 
+    //------------------------------时间信息 start--------------------
+    @Schema(description = "年份,如:2024")
+    private Integer year;
+
+    @Schema(description = "月份,如:6")
+    private Integer month;
+
+    @Schema(description = "当前月的第几天")
+    private Integer dayOfMonth;
+
+    @Schema(description = "今年第几周,如:32")
+    private Integer week;
+
+    @Schema(description = "当前年的第几天")
+    private Integer dayOfYear;
+
+    @Schema(description = "当前的第几小时")
+    private Integer hourOfDay;
+
+    @Schema(description = "分钟key")
+    private String minuteKey;
+
+    @Schema(description = "小时key")
+    private String hourKey;
+
+    public void setTimes() {
+        this.year = DateUtils.getCurrentYear();
+        this.month = DateUtils.getCurrentMonthInYear();
+        this.dayOfMonth = DateUtils.getCurrentDayInMonth();
+        this.hourOfDay = DateUtils.getCurrentHourOfDay();
+
+        this.dayOfYear = DateUtils.getCurrentDayInYear();
+        this.week = DateUtils.getCurrentWeekInYear();
+        this.minuteKey = DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyyMMddHHmmKey);
+        this.hourKey = DateUtils.paresTime(System.currentTimeMillis(), DateUtils.patternyyyyMMddHHKey);
+    }
+
 }

+ 1 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/artemis/OperationMessageService.java

@@ -283,6 +283,7 @@ public class OperationMessageService {
             if (ObjectUtils.isNotEmpty(temp) && temp.getToken().equals(token)) {
                 log.info("获取到执行锁,开始执行");
                 entity.setId(temp.getId());
+                entity.setTimes();
                 entity.setToken(temp.getToken());
                 entity.setCreateTime(System.currentTimeMillis());
                 addOperationMessage(entity);

+ 7 - 3
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DeviceOnLineRecordService.java

@@ -3,11 +3,12 @@ package com.zhongshu.iot.server.core.service.device;
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.deviceUse.OnLineState;
 import com.zhongshu.card.client.utils.DateUtils;
-import com.zhongshu.iot.client.model.baseParam.SeriesModel;
+import com.github.microservice.models.statistics.SeriesModel;
 import com.zhongshu.iot.client.model.iot.ping.DeviceOnLineRecordModel;
 import com.zhongshu.iot.client.model.iot.ping.DeviceOnLineRecordSearch;
-import com.zhongshu.iot.client.model.iot.statistics.LineModel;
+import com.github.microservice.models.statistics.LineModel;
 import com.zhongshu.iot.server.core.dao.iot.DeviceOnLineRecordDao;
+import com.zhongshu.iot.server.core.dao.mqtt.OperationMessageDao;
 import com.zhongshu.iot.server.core.dataConfig.CommonTTLTimeConfig;
 import com.zhongshu.iot.server.core.domain.iot.device.DeviceInfo;
 import com.zhongshu.iot.server.core.domain.iot.device.DeviceOnLineRecord;
@@ -41,6 +42,9 @@ public class DeviceOnLineRecordService extends SuperService {
     @Autowired
     private DeviceInfoService deviceInfoService;
 
+    @Autowired
+    private OperationMessageDao operationMessageDao;
+
     public void addOnLineRecord(DeviceInfo deviceInfo, OnLineState onLineState) {
         if (ObjectUtils.isEmpty(deviceInfo) || onLineState != OnLineState.OnLine) {
             return;
@@ -72,7 +76,7 @@ public class DeviceOnLineRecordService extends SuperService {
     }
 
     /**
-     * 统计
+     * 设备在线折线图统计
      *
      * @param search
      * @return

+ 60 - 0
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/device/DeviceStatisticsService.java

@@ -1,19 +1,27 @@
 package com.zhongshu.iot.server.core.service.device;
 
+import com.github.microservice.models.statistics.LineModel;
+import com.github.microservice.models.statistics.PieDataModel;
+import com.github.microservice.models.statistics.PieModel;
+import com.github.microservice.models.statistics.SeriesModel;
 import com.github.microservice.net.ResultContent;
 import com.github.microservice.types.deviceUse.DeviceCategory;
+import com.github.microservice.types.deviceUse.DeviceType;
 import com.zhongshu.iot.client.model.artemis.OperationMessageSearchParam;
 import com.zhongshu.iot.client.model.iot.statistics.DeviceStatisticsModel;
 import com.zhongshu.iot.client.model.mqtt.DeviceInfoSearchParam;
 import com.zhongshu.iot.client.type.OperationBusType;
 import com.zhongshu.iot.server.core.dao.mqtt.DeviceInfoDao;
 import com.zhongshu.iot.server.core.dao.mqtt.OperationMessageDao;
+import com.zhongshu.iot.server.core.util.CommonUtil;
 import com.zhongshu.iot.server.core.util.DateUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.ArrayList;
 import java.util.List;
+import java.util.Map;
 
 /**
  * 设备统计服务
@@ -63,7 +71,59 @@ public class DeviceStatisticsService {
         Long toDayMessageNumber = operationMessageDao.count(messageSearchParam);
         model.setToDayMessageNumber(toDayMessageNumber);
 
+        // 设备分类统计
+        model.setDevicePie(deviceGroupStatistics());
+
         return ResultContent.buildSuccess(model);
     }
 
+    /**
+     * 设备在线折线图统计
+     *
+     * @param search
+     * @return
+     */
+    public ResultContent<LineModel> statisticsMessageLine(OperationMessageSearchParam search) {
+        if (CommonUtil.longIsEmpty(search.getStartTime()) || CommonUtil.longIsEmpty(search.getEndTime())) {
+            return ResultContent.buildFail("搜索时间不能为空");
+        }
+        LineModel lineModel = new LineModel();
+        List<String> xAxis = new ArrayList<>();
+        SeriesModel seriesModel = new SeriesModel();
+
+        Map<String, Long> map = operationMessageDao.statisticsMinuteNumber(search);
+        Long startTime = search.getStartTime();
+        Long endTime = search.getEndTime();
+        // 已分钟一条数据
+        while (startTime <= endTime) {
+            String minuteKey = com.zhongshu.card.client.utils.DateUtils.paresTime(System.currentTimeMillis(), com.zhongshu.card.client.utils.DateUtils.patternyyyyMMddHHmmKey);
+            String xAxi = com.zhongshu.card.client.utils.DateUtils.paresTime(System.currentTimeMillis(), com.zhongshu.card.client.utils.DateUtils.patternHHmm);
+            xAxis.add(xAxi);
+            Long number = map.containsKey(minuteKey) ? map.get(minuteKey) : 0L;
+            seriesModel.addSeries(number);
+            startTime += 60 * 1000L;
+        }
+        lineModel.setXAxis(xAxis);
+        lineModel.addSeries(seriesModel);
+        return ResultContent.buildSuccess(lineModel);
+    }
+
+    /**
+     * 设备分类统计
+     */
+    public PieModel deviceGroupStatistics() {
+        PieModel pieModel = new PieModel();
+        DeviceInfoSearchParam param = new DeviceInfoSearchParam();
+        String fieldName = "deviceType";
+        Map<String, Long> map = deviceInfoDao.deviceGroupStatistics(param, fieldName);
+        for (DeviceType deviceType : DeviceType.values()) {
+            Long value = 0L;
+            if (map.containsKey(deviceType.name())) {
+                value = map.get(deviceType.name());
+            }
+            pieModel.addPieDataModel(PieDataModel.builder().value(value).name(deviceType.getRemark()).build());
+        }
+        return pieModel;
+    }
+
 }

+ 9 - 4
OneCardIotServer/src/main/java/com/zhongshu/iot/server/core/service/iot/IotSendMessageService.java

@@ -137,6 +137,7 @@ public class IotSendMessageService extends SuperService {
         if (ObjectUtils.isNotEmpty(entity)) {
             entity.setMessageId(CommonUtil.UUID()); // 消息ID
             entity.setOperationBusType(OperationBusType.IotThing);
+            entity.setTimes();
             entity.setClientId(""); // 终端ID
             entity.setTopic(""); // topic名称
             entity.setOperationType(OperationType.Push);
@@ -156,7 +157,7 @@ public class IotSendMessageService extends SuperService {
                 entity.setDeviceId(deviceInfo.getDeviceId());
                 entity.setDeviceInfo(deviceInfo);
             }
-
+            
             entity.setTtl(new Date(System.currentTimeMillis() + ttlMill));
             entity.setReceiveTime(System.currentTimeMillis());
             entity.setReceiveTimeStr(DateUtils.paresTime(System.currentTimeMillis(), DateUtils.FORMAT_LONG));
@@ -166,16 +167,20 @@ public class IotSendMessageService extends SuperService {
             for (IotMain iotMain : list) {
                 // %s/issued 下发数据 Topic
                 String topic = iotMain.getRealIotTopic();
-
                 String messageId = CommonUtil.UUID();
+                jsonObject.set("id", messageId);
+
                 OperationMessageResult messageResult = new OperationMessageResult();
+                messageResult.setTimes();
+                messageResult.setProductCode(iotMain.getProductCode());
+                messageResult.setIotThingId(iotMain.getIotThingId());
                 messageResult.setMessageId(messageId);
                 messageResult.setDataId(entity.getDataId());
                 messageResult.setOperationMessage(entity);
-                // 物模型信息
+
+                // 所属属性信息
                 messageResult.setIotMain(iotMain);
                 messageResult.setIotTemplate(iotMain.getIotTemplate());
-                jsonObject.set("id", messageId);
 
                 // 设备ID
                 messageResult.setDeviceId(iotMain.getDeviceId());