From 640e7f5286426f4a1c305e04352884d83df61a44 Mon Sep 17 00:00:00 2001
From: zhuangtianxiang <2913129173@qq.com>
Date: Tue, 11 Mar 2025 20:36:47 +0800
Subject: [PATCH] =?UTF-8?q?feat(iot):=20=E6=B7=BB=E5=8A=A0=E6=B8=A9?=
 =?UTF-8?q?=E5=BA=A6=E5=BC=82=E5=B8=B8=E4=BA=8B=E4=BB=B6=E5=A4=84=E7=90=86?=
 =?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

- 在 RecordData 实体中添加处理记录数据的方法- 新增 TemperatureExceededEvent 类用于温度异常事件
- 在 DeviceController 中集成事件处理逻辑
- 更新数据库结构,增加参数对比类型和默认值字段
- 优化 Param 实体,添加 CompareType枚举
---
 .../framework/message/sse/SseConfig.java      |  4 +-
 .../device/controller/DeviceController.java   |  5 --
 .../entity/TemperatureExceededEvent.java      | 21 +++++
 .../service/impl/RecordDataServiceImpl.java   | 78 ++++++++++++++++++-
 .../gateway/modules/iot/tsl/entity/Param.java | 42 ++++++++++
 .../tsl/service/impl/EventServiceImpl.java    |  3 +
 src/main/resources/db/gateway.sql             |  5 ++
 .../resources/db/gateway/public/iot_param.sql | 32 ++++++--
 .../gateway/service/iot/ParamServiceTest.java |  4 +-
 9 files changed, 174 insertions(+), 20 deletions(-)
 create mode 100644 src/main/java/com/zsc/edu/gateway/modules/iot/record/entity/TemperatureExceededEvent.java

diff --git a/src/main/java/com/zsc/edu/gateway/framework/message/sse/SseConfig.java b/src/main/java/com/zsc/edu/gateway/framework/message/sse/SseConfig.java
index ef68322..5832ab0 100644
--- a/src/main/java/com/zsc/edu/gateway/framework/message/sse/SseConfig.java
+++ b/src/main/java/com/zsc/edu/gateway/framework/message/sse/SseConfig.java
@@ -1,8 +1,6 @@
 package com.zsc.edu.gateway.framework.message.sse;
 
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Bean;
-import org.springframework.http.MediaType;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Component;
 import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;
 
diff --git a/src/main/java/com/zsc/edu/gateway/modules/iot/device/controller/DeviceController.java b/src/main/java/com/zsc/edu/gateway/modules/iot/device/controller/DeviceController.java
index ec79b62..e1d590d 100644
--- a/src/main/java/com/zsc/edu/gateway/modules/iot/device/controller/DeviceController.java
+++ b/src/main/java/com/zsc/edu/gateway/modules/iot/device/controller/DeviceController.java
@@ -2,7 +2,6 @@ package com.zsc.edu.gateway.modules.iot.device.controller;
 
 import com.alibaba.fastjson2.JSONException;
 import com.alibaba.fastjson2.JSONObject;
-import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.zsc.edu.gateway.framework.message.sse.SseConfig;
@@ -13,15 +12,11 @@ import com.zsc.edu.gateway.modules.iot.device.dto.DeviceServeDto;
 import com.zsc.edu.gateway.modules.iot.device.entity.Device;
 import com.zsc.edu.gateway.modules.iot.device.query.DeviceQuery;
 import com.zsc.edu.gateway.modules.iot.device.service.DeviceService;
-import com.zsc.edu.gateway.modules.iot.device.vo.DeviceStatusVo;
 import com.zsc.edu.gateway.modules.iot.device.vo.DeviceVo;
-import com.zsc.edu.gateway.modules.iot.record.entity.DataWarningVo;
 import com.zsc.edu.gateway.modules.iot.record.entity.RecordData;
-import com.zsc.edu.gateway.modules.iot.record.entity.RecordDataStatusVo;
 import com.zsc.edu.gateway.modules.iot.record.service.RecordDataService;
 import jakarta.annotation.Resource;
 import lombok.AllArgsConstructor;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.http.HttpStatus;
 import org.springframework.http.MediaType;
 import org.springframework.http.ResponseEntity;
diff --git a/src/main/java/com/zsc/edu/gateway/modules/iot/record/entity/TemperatureExceededEvent.java b/src/main/java/com/zsc/edu/gateway/modules/iot/record/entity/TemperatureExceededEvent.java
new file mode 100644
index 0000000..458aabf
--- /dev/null
+++ b/src/main/java/com/zsc/edu/gateway/modules/iot/record/entity/TemperatureExceededEvent.java
@@ -0,0 +1,21 @@
+package com.zsc.edu.gateway.modules.iot.record.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+import org.springframework.context.ApplicationEvent;
+
+/**
+ * @author zhuang
+ */
+@Getter
+@Setter
+public class TemperatureExceededEvent extends ApplicationEvent {
+    private final RecordData recordData;
+    private final double reducedParameter;
+
+    public TemperatureExceededEvent(Object source, RecordData recordData, double reducedParameter) {
+        super(source);
+        this.recordData = recordData;
+        this.reducedParameter = reducedParameter;
+    }
+}
diff --git a/src/main/java/com/zsc/edu/gateway/modules/iot/record/service/impl/RecordDataServiceImpl.java b/src/main/java/com/zsc/edu/gateway/modules/iot/record/service/impl/RecordDataServiceImpl.java
index 98cb2fc..b7effd6 100644
--- a/src/main/java/com/zsc/edu/gateway/modules/iot/record/service/impl/RecordDataServiceImpl.java
+++ b/src/main/java/com/zsc/edu/gateway/modules/iot/record/service/impl/RecordDataServiceImpl.java
@@ -5,16 +5,25 @@ import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.zsc.edu.gateway.modules.iot.device.entity.Device;
+import com.zsc.edu.gateway.modules.iot.device.repo.DeviceRepository;
 import com.zsc.edu.gateway.modules.iot.record.entity.DataWarningVo;
 import com.zsc.edu.gateway.modules.iot.record.entity.RecordData;
 import com.zsc.edu.gateway.modules.iot.record.entity.RecordDataStatusVo;
+import com.zsc.edu.gateway.modules.iot.record.entity.TemperatureExceededEvent;
 import com.zsc.edu.gateway.modules.iot.record.repo.RecordDataRepository;
 import com.zsc.edu.gateway.modules.iot.record.service.RecordDataService;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Event;
+import com.zsc.edu.gateway.modules.iot.tsl.entity.Param;
+import com.zsc.edu.gateway.modules.iot.tsl.repo.EventRepository;
+import jakarta.annotation.Resource;
 import lombok.AllArgsConstructor;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.Map;
 
 /**
  * @author zhuang
@@ -23,8 +32,12 @@ import java.util.List;
 @Service
 public class RecordDataServiceImpl extends ServiceImpl<RecordDataRepository, RecordData> implements RecordDataService {
 
-    private final RecordDataRepository recordDataRepository;
-
+    @Resource
+    private final ApplicationEventPublisher eventPublisher;
+    @Resource
+    private final DeviceRepository deviceRepository;
+    @Resource
+    private final EventRepository eventRepository;
     @Override
     public RecordData recordData(String clientId, JSONObject data) {
         RecordData recordData = new RecordData();
@@ -32,6 +45,7 @@ public class RecordDataServiceImpl extends ServiceImpl<RecordDataRepository, Rec
         recordData.setContent(data);
         recordData.setRecordTime(LocalDateTime.now());
         baseMapper.insert(recordData);
+        processRecordData(recordData);
         return recordData;
     }
 
@@ -64,6 +78,64 @@ public class RecordDataServiceImpl extends ServiceImpl<RecordDataRepository, Rec
     public IPage<RecordData> query(Page<RecordData> page, String clientId) {
         LambdaQueryWrapper<RecordData> queryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(RecordData::getClientId, clientId);
-        return recordDataRepository.selectPage(page, queryWrapper);
+        return baseMapper.selectPage(page, queryWrapper);
     }
+
+    public void processRecordData(RecordData recordData) {
+        // 根据 clientId 查询设备信息
+        Device device = deviceRepository.selectOne(new LambdaQueryWrapper<Device>().eq(Device::getClientId, recordData.getClientId()));
+
+        // 获取产品下的所有事件
+        List<Event> events = eventRepository.selectList(new LambdaQueryWrapper<Event>().eq(Event::getProductId, device.getProductId()));
+
+        // 遍历每个事件
+        for (Event event : events) {
+            // 遍历事件的 outputs 列表中的每个参数
+            event.getOutputs().forEach(param -> {
+                processParam(recordData, param);
+            });
+        }
+    }
+
+    private void processParam(RecordData recordData, Param param) {
+        // 获取参数的默认值和比较类型
+        Double defaultValue = param.getDefaultValue();
+        Param.CompareType compareType = param.getCompareType();
+        String identifier = param.getIdentifier();
+
+        // 检查 recordData 的内容中是否包含该参数的标识符
+        if (recordData.getContent().get(identifier) != null) {
+            try {
+                // 获取参数的实际值
+                double value = Double.parseDouble(recordData.getContent().get(identifier).toString());
+
+                // 根据比较类型进行不同的处理
+                switch (compareType) {
+                    case GT:
+                        if (value > defaultValue) {
+                            eventPublisher.publishEvent(new TemperatureExceededEvent(this, recordData, value));
+                        }
+                        break;
+                    case LT:
+                        if (value < defaultValue) {
+                            eventPublisher.publishEvent(new TemperatureExceededEvent(this, recordData, value));
+                        }
+                        break;
+                    case EQ:
+                        if (value == defaultValue) {
+                            eventPublisher.publishEvent(new TemperatureExceededEvent(this, recordData, value));
+                        }
+                        break;
+                    default:
+                        // 处理未知的比较类型
+                        System.err.println("Unknown compare type: " + compareType);
+                        break;
+                }
+            } catch (NumberFormatException e) {
+                // 处理数值转换异常
+                System.err.println("Failed to parse value for identifier: " + identifier + ". Error: " + e.getMessage());
+            }
+        }
+    }
+
 }
diff --git a/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/entity/Param.java b/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/entity/Param.java
index 2dd4ce7..e01ea64 100644
--- a/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/entity/Param.java
+++ b/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/entity/Param.java
@@ -44,6 +44,16 @@ public class Param extends BaseParam {
      */
     private Long foreignId;
 
+    /**
+     * 对比类型
+     */
+    private CompareType compareType;
+
+    /**
+     * 默认数值
+     */
+    private Double defaultValue;
+
     public enum Type implements IEnum<String>, IState<Type> {
         /**
          * 物模型输入
@@ -109,4 +119,36 @@ public class Param extends BaseParam {
             return this.description;
         }
     }
+
+    public enum CompareType implements IEnum<Integer>, IState<CompareType> {
+        /**
+         * 大于
+         */
+        GT(1, ">"),
+        /**
+         * 小于
+         */
+        LT(2, "<"),
+        /**
+         * 等于
+         */
+        EQ(3, "=");
+        private final int value;
+        private final String description;
+
+        CompareType(int value, String description) {
+            this.value = value;
+            this.description = description;
+        }
+
+        @Override
+        public Integer getValue() {
+            return value;
+        }
+
+        @Override
+        public String toString() {
+            return this.description;
+        }
+    }
 }
diff --git a/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/EventServiceImpl.java b/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/EventServiceImpl.java
index e5c0d91..eea22eb 100644
--- a/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/EventServiceImpl.java
+++ b/src/main/java/com/zsc/edu/gateway/modules/iot/tsl/service/impl/EventServiceImpl.java
@@ -9,7 +9,10 @@ import com.zsc.edu.gateway.modules.iot.tsl.mapper.EventMapper;
 import com.zsc.edu.gateway.modules.iot.tsl.repo.EventRepository;
 import com.zsc.edu.gateway.modules.iot.tsl.service.EventService;
 import com.zsc.edu.gateway.modules.iot.tsl.service.ParamService;
+import jakarta.annotation.Resource;
 import lombok.AllArgsConstructor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.ApplicationEventPublisher;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
diff --git a/src/main/resources/db/gateway.sql b/src/main/resources/db/gateway.sql
index 9a7a3de..150d6c7 100644
--- a/src/main/resources/db/gateway.sql
+++ b/src/main/resources/db/gateway.sql
@@ -934,5 +934,10 @@ ALTER TABLE iot_device
     ALTER COLUMN longitude SET DEFAULT 113.39,
     ALTER COLUMN latitude SET DEFAULT 22.52;
 
+ALTER TABLE iot_param
+    ALTER COLUMN contrast_type SET DEFAULT NULL;
+
+ALTER TABLE iot_param
+    ALTER COLUMN "default_value " SET DEFAULT NULL;
 
 
diff --git a/src/main/resources/db/gateway/public/iot_param.sql b/src/main/resources/db/gateway/public/iot_param.sql
index 5f8ace1..bb94ae3 100644
--- a/src/main/resources/db/gateway/public/iot_param.sql
+++ b/src/main/resources/db/gateway/public/iot_param.sql
@@ -1,14 +1,20 @@
 create table iot_param
 (
-    id bigserial not null
+    id               bigint generated by default as identity
         constraint iot_param_name_pk
             primary key,
-    data_type  integer,
-    uint       varchar,
-    type       integer,
-    identifier varchar,
-    name       varchar,
-    remark     varchar
+    data_type        integer,
+    uint             varchar,
+    type             varchar,
+    identifier       varchar,
+    name             varchar,
+    remark           varchar,
+    foreign_id       bigint,
+    foreign_type     integer,
+    dept_id          bigint,
+    create_id        bigint,
+    contrast_type    integer,
+    "default_value " double precision
 );
 
 comment on table iot_param is '参数';
@@ -27,6 +33,18 @@ comment on column iot_param.name is '名称';
 
 comment on column iot_param.remark is '备注';
 
+comment on column iot_param.foreign_id is '联表id';
+
+comment on column iot_param.foreign_type is '关联类型';
+
+comment on column iot_param.dept_id is '部门权限id';
+
+comment on column iot_param.create_id is '创建人id';
+
+comment on column iot_param.contrast_type is '对比类型';
+
+comment on column iot_param."default_value " is '默认数值';
+
 alter table iot_param
     owner to gitea;
 
diff --git a/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java b/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java
index 6f78c52..2ddd16f 100644
--- a/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java
+++ b/src/test/java/com/zsc/edu/gateway/service/iot/ParamServiceTest.java
@@ -60,9 +60,9 @@ public class ParamServiceTest {
 
     @Test
     void createParams() {
-        ParamDto dto = new ParamDto("PARAM_NAME_3", "测试1", "备注", DataType.DATE, Param.Type.OUTPUT);
+//        ParamDto dto = new ParamDto("PARAM_NAME_3", "测试1", "备注", DataType.DATE, Param.Type.OUTPUT);
         List<ParamDto> params = new ArrayList<>();
-        params.add(dto);
+//        params.add(dto);
         Long foreignId = 1L;
         Boolean result = service.create(params, foreignId, null);
         assertTrue(result);