learshaw před 4 měsíci
rodič
revize
77ba353823
59 změnil soubory, kde provedl 2007 přidání a 581 odebrání
  1. 1 10
      ems/ems-application/ems-admin/src/main/java/com/ruoyi/web/controller/ems/EmsObjAttrValueController.java
  2. 0 112
      ems/ems-application/ems-collect/pom.xml
  3. 0 32
      ems/ems-application/ems-collect/src/main/java/com/ruoyi/SpingMqttApplication.java
  4. 0 77
      ems/ems-application/ems-collect/src/main/java/com/ruoyi/controller/TestController.java
  5. 0 59
      ems/ems-application/ems-collect/src/main/java/com/ruoyi/model/MqttRequest.java
  6. 0 66
      ems/ems-application/ems-collect/src/main/resources/application-locale.yml
  7. 0 9
      ems/ems-application/ems-collect/src/main/resources/application.yml
  8. 0 8
      ems/ems-application/ems-collect/src/main/resources/banner.txt
  9. 0 1
      ems/ems-application/pom.xml
  10. 120 0
      ems/ems-cloud/ems-dev-adapter/pom.xml
  11. 4 4
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/ClientInit.java
  12. 32 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/EmsDevAdpApplication.java
  13. 3 3
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/MqttConfig.java
  14. 3 3
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/MqttServerProperty.java
  15. 69 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/ThreadConfig.java
  16. 82 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/controller/CircuitBreakerController.java
  17. 64 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/MessageCache.java
  18. 1 1
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/MqttMessageHandler.java
  19. 1 1
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/MqttTemplate.java
  20. 252 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/GeekOpenCbHandler.java
  21. 64 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/MqttBaseHandler.java
  22. 19 6
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/RootMsgHandler.java
  23. 86 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/MqttCacheMsg.java
  24. 68 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/util/DataSourceUtils.java
  25. 41 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/util/IdUtils.java
  26. 68 0
      ems/ems-cloud/ems-dev-adapter/src/main/resources/application-local.yml
  27. 10 0
      ems/ems-cloud/ems-dev-adapter/src/main/resources/banner.txt
  28. 35 0
      ems/ems-cloud/ems-dev-adapter/src/main/resources/bootstrap.yml
  29. 17 36
      ems/ems-cloud/ems-dev-adapter/src/main/resources/logback.xml
  30. 28 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAbilityController.java
  31. 4 13
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAttrValueController.java
  32. 0 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/task/BaseTask.java
  33. 0 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/task/taskiml/FacTask.java
  34. 1 0
      ems/ems-cloud/pom.xml
  35. 7 0
      ems/ems-core/pom.xml
  36. 3 3
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsDevice.java
  37. 12 0
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAbility.java
  38. 157 0
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAbilityCallLog.java
  39. 66 53
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAttrValue.java
  40. 24 0
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjModel.java
  41. 2 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsDeviceMapper.java
  42. 45 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsObjAbilityCallLogMapper.java
  43. 1 9
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsObjAttrValueMapper.java
  44. 87 0
      ems/ems-core/src/main/java/com/ruoyi/ems/model/AbilityPayload.java
  45. 60 0
      ems/ems-core/src/main/java/com/ruoyi/ems/model/CallResponse.java
  46. 24 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IAbilityCallService.java
  47. 45 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsObjAbilityCallLogService.java
  48. 1 9
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsObjAttrValueService.java
  49. 161 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/AbilityCallServiceImpl.java
  50. 42 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAbilityCallLogServiceImpl.java
  51. 3 14
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAttrValueServiceImpl.java
  52. 0 1
      ems/ems-core/src/main/resources/mapper/ems/EmsDeviceMapper.xml
  53. 88 0
      ems/ems-core/src/main/resources/mapper/ems/EmsObjAbilityCallLogMapper.xml
  54. 8 3
      ems/ems-core/src/main/resources/mapper/ems/EmsObjAbilityMapper.xml
  55. 9 24
      ems/ems-core/src/main/resources/mapper/ems/EmsObjAttrValueMapper.xml
  56. 9 1
      ems/ems-core/src/main/resources/mapper/ems/EmsObjModelMapper.xml
  57. 12 13
      ems/sql/ems_init_data.sql
  58. 33 10
      ems/sql/ems_server.sql
  59. 35 0
      prod-common/src/main/java/com/huashe/common/utils/ThreadUtils.java

+ 1 - 10
ems/ems-application/ems-admin/src/main/java/com/ruoyi/web/controller/ems/EmsObjAttrValueController.java

@@ -54,15 +54,6 @@ public class EmsObjAttrValueController extends BaseController {
      * 新增能源对象属性值
      */
     @Log(title = "能源对象属性值", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody EmsObjAttrValue EmsObjAttrValue) {
-        return toAjax(objAttrValueService.insertObjAttrValue(EmsObjAttrValue));
-    }
-
-    /**
-     * 新增能源对象属性值
-     */
-    @Log(title = "能源对象属性值", businessType = BusinessType.INSERT)
     @PostMapping("/batch")
     public AjaxResult addBatch(@RequestBody List<EmsObjAttrValue> list) {
         return toAjax(objAttrValueService.insertBatch(list));
@@ -74,7 +65,7 @@ public class EmsObjAttrValueController extends BaseController {
     @Log(title = "能源对象属性值", businessType = BusinessType.UPDATE)
     @PutMapping
     public AjaxResult edit(@RequestBody EmsObjAttrValue EmsObjAttrValue) {
-        return toAjax(objAttrValueService.updateObjAttrValue(EmsObjAttrValue));
+        return toAjax(objAttrValueService.mergeObjAttrValue(EmsObjAttrValue));
     }
 
     /**

+ 0 - 112
ems/ems-application/ems-collect/pom.xml

@@ -1,112 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<project xmlns="http://maven.apache.org/POM/4.0.0"
-         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-    <parent>
-        <groupId>com.huashe.application</groupId>
-        <artifactId>ems-application</artifactId>
-        <version>1.0-SNAPSHOT</version>
-    </parent>
-    <modelVersion>4.0.0</modelVersion>
-    <packaging>jar</packaging>
-    <artifactId>ems-collect</artifactId>
-
-    <description>
-        采集服务
-    </description>
-
-    <dependencies>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-test</artifactId>
-            <scope>test</scope>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-web</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-configuration-processor</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <!-- https://mvnrepository.com/artifact/com.alibaba/fastjson -->
-        <dependency>
-            <groupId>com.alibaba.fastjson2</groupId>
-            <artifactId>fastjson2</artifactId>
-        </dependency>
-
-        <!-- mqtt -->
-        <dependency>
-            <groupId>org.springframework.integration</groupId>
-            <artifactId>spring-integration-mqtt</artifactId>
-        </dependency>
-
-        <!-- Swagger依赖 -->
-        <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger2</artifactId>
-            <version>2.6.1</version>
-        </dependency>
-        <dependency>
-            <groupId>io.springfox</groupId>
-            <artifactId>springfox-swagger-ui</artifactId>
-            <version>2.6.1</version>
-        </dependency>
-
-        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-lang3 -->
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-lang3</artifactId>
-        </dependency>
-
-        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
-        <dependency>
-            <groupId>org.apache.commons</groupId>
-            <artifactId>commons-collections4</artifactId>
-        </dependency>
-
-        <!-- https://mvnrepository.com/artifact/commons-io/commons-io -->
-        <dependency>
-            <groupId>commons-io</groupId>
-            <artifactId>commons-io</artifactId>
-        </dependency>
-
-    </dependencies>
-
-    <build>
-        <plugins>
-            <plugin>
-                <groupId>org.springframework.boot</groupId>
-                <artifactId>spring-boot-maven-plugin</artifactId>
-                <version>2.5.15</version>
-                <configuration>
-                    <fork>true</fork> <!-- 如果没有该配置,devtools不会生效 -->
-                </configuration>
-                <executions>
-                    <execution>
-                        <goals>
-                            <goal>repackage</goal>
-                        </goals>
-                    </execution>
-                </executions>
-            </plugin>
-            <plugin>   
-                <groupId>org.apache.maven.plugins</groupId>   
-                <artifactId>maven-war-plugin</artifactId>   
-                <version>3.1.0</version>   
-                <configuration>
-                    <failOnMissingWebXml>false</failOnMissingWebXml>
-                    <warName>${project.artifactId}</warName>
-                </configuration>   
-           </plugin>   
-        </plugins>
-        <finalName>${project.artifactId}</finalName>
-    </build>
-
-</project>

+ 0 - 32
ems/ems-application/ems-collect/src/main/java/com/ruoyi/SpingMqttApplication.java

@@ -1,32 +0,0 @@
-/*
- * 文 件 名:  ConfigServerApplication
- * 版    权:
- * 描    述:  <描述>
- * 修 改 人:  learshaw
- * 修改时间:  2018/12/18
- */
-package com.ruoyi;
-
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
-import org.springframework.boot.builder.SpringApplicationBuilder;
-import org.springframework.scheduling.annotation.EnableScheduling;
-
-/**
- * Mqtt启动入口
- * <功能详细描述>
- *
- * @author learshaw
- * @version [版本号, 2021/04/26]
- * @see [相关类/方法]
- * @since [产品/模块版本]
- */
-@EnableScheduling
-@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
-public class SpingMqttApplication {
-    public static void main(String[] args) {
-        SpringApplicationBuilder builder = new SpringApplicationBuilder(SpingMqttApplication.class);
-//        builder.web(WebApplicationType.NONE);
-        builder.run(args);
-    }
-}

+ 0 - 77
ems/ems-application/ems-collect/src/main/java/com/ruoyi/controller/TestController.java

@@ -1,77 +0,0 @@
-/*
- * 文 件 名:  AnalyseSourceController
- * 版    权:
- * 描    述:  <描述>
- * 修 改 人:  learshaw
- * 修改时间:  2019/8/1
- * 跟踪单号:  <跟踪单号>
- * 修改单号:  <修改单号>
- * 修改内容:  <修改内容>
- */
-package com.ruoyi.controller;
-
-import com.ruoyi.core.MqttTemplate;
-import com.ruoyi.model.MqttRequest;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Qualifier;
-import org.springframework.http.MediaType;
-import org.springframework.web.bind.annotation.CrossOrigin;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.RestController;
-
-import javax.annotation.Resource;
-
-/**
- * Test访问服务
- * <功能详细描述>
- *
- * @author learshaw
- * @version [版本号, 2019/8/1]
- * @see [相关类/方法]
- * @since [产品/模块版本]
- */
-@RestController
-@CrossOrigin(allowedHeaders = "*", allowCredentials = "false")
-@Api(value = "TestController", description = "Test访问接口")
-@RequestMapping(path = "/mqtt", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
-public class TestController {
-    /**
-     * 日志
-     */
-    private static final Logger log = LoggerFactory.getLogger(TestController.class);
-
-    @Resource
-    @Qualifier("mqttTemplate")
-    private MqttTemplate mqttTemplate;
-
-    /**
-     * 发送
-     *
-     * @return 数据列表
-     */
-    @RequestMapping(value = "/send", method = RequestMethod.POST)
-    @ApiOperation(value = "send", notes = "发送")
-    @ApiResponses({ @ApiResponse(code = 200, message = "success"),
-        @ApiResponse(code = 400, message = "{code:****,message:'fail'}")
-    })
-    public String send(@RequestBody MqttRequest req) {
-        String ret = "success";
-
-        try {
-            mqttTemplate.send(req.getTopic(), req.getPayload(), req.getQos(), req.isRetained());
-        }
-        catch (Exception e) {
-            log.error("send fail!", e);
-            ret = "fail!";
-        }
-
-        return ret;
-    }
-}

+ 0 - 59
ems/ems-application/ems-collect/src/main/java/com/ruoyi/model/MqttRequest.java

@@ -1,59 +0,0 @@
-/*
- * 文 件 名:  MqttRequest
- * 版    权:  浩鲸云计算科技股份有限公司
- * 描    述:  <描述>
- * 修 改 人:  lvwenbin
- * 修改时间:  2024/5/6
- * 跟踪单号:  <跟踪单号>
- * 修改单号:  <修改单号>
- * 修改内容:  <修改内容>
- */
-package com.ruoyi.model;
-
-/**
- * 发送请求
- * <功能详细描述>
- *
- * @author lvwenbin
- * @version [版本号, 2024/5/6]
- * @see [相关类/方法]
- * @since [产品/模块版本]
- */
-public class MqttRequest {
-    private String topic;
-    private String payload;
-    private int qos;
-    private boolean retained;
-
-    public String getTopic() {
-        return topic;
-    }
-
-    public void setTopic(String topic) {
-        this.topic = topic;
-    }
-
-    public String getPayload() {
-        return payload;
-    }
-
-    public void setPayload(String payload) {
-        this.payload = payload;
-    }
-
-    public int getQos() {
-        return qos;
-    }
-
-    public void setQos(int qos) {
-        this.qos = qos;
-    }
-
-    public boolean isRetained() {
-        return retained;
-    }
-
-    public void setRetained(boolean retained) {
-        this.retained = retained;
-    }
-}

+ 0 - 66
ems/ems-application/ems-collect/src/main/resources/application-locale.yml

@@ -1,66 +0,0 @@
-## MQTT##
-mqtt:
-  host: tcp://xt.wenhq.top:8581
-  client_id: ems-collect
-
-# 数据源配置
-spring:
-  datasource:
-    type: com.alibaba.druid.pool.DruidDataSource
-    driverClassName: com.mysql.cj.jdbc.Driver
-    druid:
-      # 主库数据源
-      master:
-        url: jdbc:mysql://172.192.10.105:30002/ems_ct?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
-        username: root
-        password: root
-      # 从库数据源
-      slave:
-        # 从数据源开关/默认关闭
-        enabled: false
-        url:
-        username:
-        password:
-      # 初始连接数
-      initialSize: 5
-      # 最小连接池数量
-      minIdle: 10
-      # 最大连接池数量
-      maxActive: 20
-      # 配置获取连接等待超时的时间
-      maxWait: 60000
-      # 配置连接超时时间
-      connectTimeout: 30000
-      # 配置网络超时时间
-      socketTimeout: 60000
-      # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
-      timeBetweenEvictionRunsMillis: 60000
-      # 配置一个连接在池中最小生存的时间,单位是毫秒
-      minEvictableIdleTimeMillis: 300000
-      # 配置一个连接在池中最大生存的时间,单位是毫秒
-      maxEvictableIdleTimeMillis: 900000
-      # 配置检测连接是否有效
-      validationQuery: SELECT 1 FROM DUAL
-      testWhileIdle: true
-      testOnBorrow: false
-      testOnReturn: false
-      webStatFilter:
-        enabled: true
-      statViewServlet:
-        enabled: true
-        # 设置白名单,不填则允许所有访问
-        allow:
-        url-pattern: /druid/*
-        # 控制台管理用户名和密码
-        login-username: ruoyi
-        login-password: 123456
-      filter:
-        stat:
-          enabled: true
-          # 慢SQL记录
-          log-slow-sql: true
-          slow-sql-millis: 1000
-          merge-sql: true
-        wall:
-          config:
-            multi-statement-allow: true

+ 0 - 9
ems/ems-application/ems-collect/src/main/resources/application.yml

@@ -1,9 +0,0 @@
-spring:
-  application:
-    name: ems-collect
-  profiles:
-    active: locale
-server:
-  port: 9203
-  servlet:
-    context-path: /ems-collect

+ 0 - 8
ems/ems-application/ems-collect/src/main/resources/banner.txt

@@ -1,8 +0,0 @@
-Spring Boot Version: ${spring-boot.version}
-Spring Application Name: ${spring.application.name}
- _____                         _____       _ _           _
-|  ___|                       /  __ \     | | |         | |
-| |__ _ __ ___  ___   ______  | /  \/ ___ | | | ___  ___| |_
-|  __| '_ ` _ \/ __| |______| | |    / _ \| | |/ _ \/ __| __|
-| |__| | | | | \__ \          | \__/\ (_) | | |  __/ (__| |_
-\____/_| |_| |_|___/           \____/\___/|_|_|\___|\___|\__|

+ 0 - 1
ems/ems-application/pom.xml

@@ -13,7 +13,6 @@
 
     <modules>
         <module>ems-admin</module>
-        <module>ems-collect</module>
     </modules>
     <packaging>pom</packaging>
 

+ 120 - 0
ems/ems-cloud/ems-dev-adapter/pom.xml

@@ -0,0 +1,120 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xmlns="http://maven.apache.org/POM/4.0.0"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>com.huashe.cloud.ems</groupId>
+        <artifactId>ems-cloud</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>ems-dev-adapter</artifactId>
+
+    <description>
+        能源设备适配器
+    </description>
+
+    <dependencies>
+
+    	<!-- SpringCloud Alibaba Nacos -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
+        </dependency>
+
+        <!-- SpringCloud Alibaba Nacos Config -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.alibaba.nacos</groupId>
+            <artifactId>nacos-common</artifactId>
+            <version>2.2.0</version>
+            <scope>compile</scope>
+            <optional>true</optional>
+        </dependency>
+
+    	<!-- SpringCloud Alibaba Sentinel -->
+        <dependency>
+            <groupId>com.alibaba.cloud</groupId>
+            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
+        </dependency>
+
+    	<!-- SpringBoot Actuator -->
+        <dependency>
+            <groupId>org.springframework.boot</groupId>
+            <artifactId>spring-boot-starter-actuator</artifactId>
+        </dependency>
+
+        <!-- Swagger UI -->
+        <dependency>
+            <groupId>io.springfox</groupId>
+            <artifactId>springfox-swagger-ui</artifactId>
+            <version>${swagger.fox.version}</version>
+        </dependency>
+
+        <!-- Mysql Connector -->
+        <dependency>
+            <groupId>com.mysql</groupId>
+            <artifactId>mysql-connector-j</artifactId>
+        </dependency>
+
+        <!-- RuoYi Common DataSource -->
+        <dependency>
+            <groupId>com.huashe.cloud</groupId>
+            <artifactId>ruoyi-common-datasource</artifactId>
+        </dependency>
+
+        <!-- RuoYi Common DataScope -->
+        <dependency>
+            <groupId>com.huashe.cloud</groupId>
+            <artifactId>ruoyi-common-datascope</artifactId>
+        </dependency>
+
+        <!-- RuoYi Common Swagger -->
+        <dependency>
+            <groupId>com.huashe.cloud</groupId>
+            <artifactId>ruoyi-common-swagger</artifactId>
+        </dependency>
+
+        <!-- mqtt -->
+        <dependency>
+            <groupId>org.springframework.integration</groupId>
+            <artifactId>spring-integration-mqtt</artifactId>
+            <version>5.1.2.RELEASE</version>
+        </dependency>
+
+        <dependency>
+            <groupId>com.huashe.ems</groupId>
+            <artifactId>ems-core</artifactId>
+            <version>1.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>ruoyi-common-quartz</artifactId>
+                    <groupId>com.huashe.cloud</groupId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <finalName>${project.artifactId}</finalName>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>repackage</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>

+ 4 - 4
ems/ems-application/ems-collect/src/main/java/com/ruoyi/ClientInit.java → ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/ClientInit.java

@@ -8,10 +8,10 @@
  * 修改单号:  <修改单号>
  * 修改内容:  <修改内容>
  */
-package com.ruoyi;
+package com.ruoyi.ems;
 
-import com.ruoyi.core.MqttTemplate;
-import com.ruoyi.handle.RootMsgHandler;
+import com.ruoyi.ems.core.MqttTemplate;
+import com.ruoyi.ems.handle.RootMsgHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Qualifier;
@@ -43,7 +43,7 @@ public class ClientInit implements CommandLineRunner {
     @Override
     public void run(String... args) {
         try {
-            template.subscribe("testtopic/#", 0, rootMsgHandler);
+            template.subscribe("/server/dlq/#", 0, rootMsgHandler);
         }
         catch (Exception e) {
             log.error("init fail!", e);

+ 32 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/EmsDevAdpApplication.java

@@ -0,0 +1,32 @@
+package com.ruoyi.ems;
+
+import com.ruoyi.common.security.annotation.EnableCustomConfig;
+import com.ruoyi.common.security.annotation.EnableRyFeignClients;
+import com.ruoyi.common.swagger.annotation.EnableCustomSwagger2;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
+import org.springframework.scheduling.annotation.EnableAsync;
+
+/**
+ * 能源设备适配器
+ *
+ * @author ruoyi
+ */
+@EnableCustomConfig
+@EnableCustomSwagger2
+@EnableAsync
+@SpringBootApplication(scanBasePackages = { "com.ruoyi.ems","com.ruoyi.system" })
+public class EmsDevAdpApplication {
+    public static void main(String[] args) {
+        // System.setProperty(GrpcConstants.NACOS_SERVER_GRPC_PORT_OFFSET_KEY,"1");
+        SpringApplication.run(EmsDevAdpApplication.class, args);
+        System.out.println("(♥◠‿◠)ノ゙  能源设备适配服务启动成功   ლ(´ڡ`ლ)゙  \n"
+            + "  _    _                   _          \n"
+            + " | |  | |                 | |         \n"
+            + " | |__| |_   _  __ _   ___| |__   ___ \n"
+            + " |  __  | | | |/ _` | / __| '_ \\ / _ \\\n"
+            + " | |  | | |_| | (_| | \\__ \\ | | |  __/\n"
+            + " |_|  |_|\\__,_|\\__,_| |___/_| |_|\\___|\n");
+    }
+}

+ 3 - 3
ems/ems-application/ems-collect/src/main/java/com/ruoyi/config/MqttConfig.java → ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/MqttConfig.java

@@ -8,10 +8,10 @@
  * 修改单号:  <修改单号>
  * 修改内容:  <修改内容>
  */
-package com.ruoyi.config;
+package com.ruoyi.ems.config;
 
 
-import com.ruoyi.core.MqttTemplate;
+import com.ruoyi.ems.core.MqttTemplate;
 import org.eclipse.paho.client.mqttv3.MqttException;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
@@ -30,7 +30,7 @@ import javax.annotation.Resource;
 @Configuration
 public class MqttConfig {
     @Resource
-    private MqttProperty mqttProperty;
+    private MqttServerProperty mqttProperty;
 
     @Bean(name = "mqttTemplate")
     public MqttTemplate getMqttTemplate() throws MqttException {

+ 3 - 3
ems/ems-application/ems-collect/src/main/java/com/ruoyi/config/MqttProperty.java → ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/MqttServerProperty.java

@@ -8,7 +8,7 @@
  * 修改单号:  <修改单号>
  * 修改内容:  <修改内容>
  */
-package com.ruoyi.config;
+package com.ruoyi.ems.config;
 
 import org.springframework.boot.context.properties.ConfigurationProperties;
 import org.springframework.context.annotation.Configuration;
@@ -23,8 +23,8 @@ import org.springframework.context.annotation.Configuration;
  * @since [产品/模块版本]
  */
 @Configuration
-@ConfigurationProperties(prefix = "mqtt")
-public class MqttProperty {
+@ConfigurationProperties(prefix = "mqtt.server")
+public class MqttServerProperty {
     private String host;
 
     private String clientId;

+ 69 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/ThreadConfig.java

@@ -0,0 +1,69 @@
+/*
+ * 文 件 名:  Socket
+ * 版    权:  浩鲸云计算科技股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  learshaw
+ * 修改时间:  2020/5/25
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
+
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadPoolExecutor;
+
+/**
+ * Scats socket 链路配置
+ * <功能详细描述>
+ *
+ * @author learshaw
+ * @version [版本号, 2021/04/07]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Configuration
+public class ThreadConfig {
+    private static final Logger log = LoggerFactory.getLogger(ThreadConfig.class);
+
+    @Bean(name = "msgHandleExecutor")
+    public ThreadPoolTaskExecutor msgHandleExecutor(@Value("${mqtt.executor.msgHandle.corePoolSize}") int corePoolSize,
+        @Value("${mqtt.executor.msgHandle.maxPoolSize}") int maxPoolSize,
+        @Value("${mqtt.executor.msgHandle.queueCapacity}") int queueCapacity,
+        @Value("${mqtt.executor.msgHandle.namePrefix}") String namePrefix) {
+        log.info("start msgHandleExecutor");
+        return buildExecutor(corePoolSize, maxPoolSize, queueCapacity, namePrefix,
+            new ThreadPoolExecutor.DiscardOldestPolicy());
+    }
+
+    private ThreadPoolTaskExecutor buildExecutor(int corePoolSize, int maxPoolSize, int queueCapacity,
+        String namePrefix, RejectedExecutionHandler rejectedExecutionHandler) {
+        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
+        //配置核心线程数
+        executor.setCorePoolSize(corePoolSize);
+        //配置最大线程数
+        executor.setMaxPoolSize(maxPoolSize);
+        //配置队列大小
+        executor.setQueueCapacity(queueCapacity);
+        //配置线程池中的线程的名称前缀
+        executor.setThreadNamePrefix(namePrefix);
+
+        // 线程池对拒绝任务(无限程可用)的处理策略
+        // ThreadPoolExecutor.AbortPolicy:丢弃任务并抛出RejectedExecutionException异常。
+        // ThreadPoolExecutor.DiscardPolicy:也是丢弃任务,但是不抛出异常。
+        // ThreadPoolExecutor.DiscardOldestPolicy:丢弃队列最前面的任务,然后重新尝试执行任务(重复此过程)
+        // ThreadPoolExecutor.CallerRunsPolicy:由调用线程处理该任务,如果执行器已关闭,则丢弃.
+        executor.setRejectedExecutionHandler(rejectedExecutionHandler);
+        //执行初始化
+        executor.initialize();
+
+        return executor;
+    }
+}

+ 82 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/controller/CircuitBreakerController.java

@@ -0,0 +1,82 @@
+/*
+ * 文 件 名:  GeekOpenCbController
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.controller;
+
+import com.huashe.common.exception.BusinessException;
+import com.ruoyi.ems.handle.MqttBaseHandler;
+import com.ruoyi.ems.model.AbilityPayload;
+import com.ruoyi.ems.model.CallResponse;
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.annotation.Resource;
+
+/**
+ * GeekOpen 断路器接口
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@RestController
+@CrossOrigin(allowedHeaders = "*", allowCredentials = "false")
+@RequestMapping("/circuit-breaker")
+@Api(value = "CircuitBreakerController", description = "断路器控制Api")
+public class CircuitBreakerController {
+    /**
+     * 日志
+     */
+    private static final Logger log = LoggerFactory.getLogger(CircuitBreakerController.class);
+
+    @Qualifier("geekOpenCbHandler")
+    @Resource
+    private MqttBaseHandler devAdapterService;
+
+    /**
+     * GeekOpen 断路器能力调用
+     *
+     * @return 数据列表
+     */
+    @RequestMapping(value = "/GeekOpen/abilityCall", method = RequestMethod.POST)
+    @ApiOperation(value = "/GeekOpen/call", notes = "GeekOpen 断路器能力调用")
+    @ApiResponses({ @ApiResponse(code = 200, message = "success"),
+        @ApiResponse(code = 400, message = "{code:****,message:'fail'}")
+    })
+    public CallResponse<Void> geekOpenCbAbilityCall(@RequestBody AbilityPayload abilityPayload) {
+        CallResponse<Void> res = null;
+
+        try {
+            String ret = devAdapterService.call(abilityPayload);
+            res = new CallResponse<>(0, ret);
+        }
+        catch (BusinessException e) {
+            res = new CallResponse<>(500, e.getMessage());
+        }
+        catch (Exception e) {
+            log.error("geekOpenCbAbilityCall fail!", e);
+            res = new CallResponse<>(501, "内部错误:" + e.getMessage());
+        }
+
+        return res;
+    }
+}

+ 64 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/MessageCache.java

@@ -0,0 +1,64 @@
+/*
+ * 文 件 名:  MessageCache
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.core;
+
+import com.ruoyi.ems.model.MqttCacheMsg;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Service;
+
+import java.util.Date;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * 消息缓存
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Service
+public class MessageCache {
+    /**
+     * 消息缓存队列
+     */
+    private final static Map<String, MqttCacheMsg> mqttMessageMap = new ConcurrentHashMap<>();
+
+    /**
+     * 定时清理过期的消息
+     */
+    @Scheduled(fixedRate = 3600000)
+    public void cleanUpOldMessages() {
+        long currentTime = new Date().getTime();
+        long threshold = 60 * 60 * 1000; // 1小时
+
+        Iterator<Map.Entry<String, MqttCacheMsg>> iterator = mqttMessageMap.entrySet().iterator();
+        while (iterator.hasNext()) {
+            Map.Entry<String, MqttCacheMsg> entry = iterator.next();
+            MqttCacheMsg msg = entry.getValue();
+            if ((currentTime - msg.getReceiveTime().getTime()) > threshold) {
+                // 删除缓存中的消息
+                iterator.remove();
+            }
+        }
+    }
+
+    public void addMqttMessage(String messageId, MqttCacheMsg mqttMessage) {
+        mqttMessageMap.put(messageId, mqttMessage);
+    }
+
+    public MqttCacheMsg getAndRemoveMqttMessage(String messageId) {
+        return mqttMessageMap.remove(messageId);
+    }
+}

+ 1 - 1
ems/ems-application/ems-collect/src/main/java/com/ruoyi/core/MqttMessageHandler.java → ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/MqttMessageHandler.java

@@ -8,7 +8,7 @@
  * 修改单号:  <修改单号>
  * 修改内容:  <修改内容>
  */
-package com.ruoyi.core;
+package com.ruoyi.ems.core;
 
 /**
  * Mqtt消息处理

+ 1 - 1
ems/ems-application/ems-collect/src/main/java/com/ruoyi/core/MqttTemplate.java → ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/MqttTemplate.java

@@ -8,7 +8,7 @@
  * 修改单号:  <修改单号>
  * 修改内容:  <修改内容>
  */
-package com.ruoyi.core;
+package com.ruoyi.ems.core;
 
 import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
 import org.eclipse.paho.client.mqttv3.MqttCallback;

+ 252 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/GeekOpenCbHandler.java

@@ -0,0 +1,252 @@
+/*
+ * 文 件 名:  GeekOpenService
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.handle;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.huashe.common.exception.Assert;
+import com.huashe.common.exception.BusinessException;
+import com.huashe.common.utils.ThreadUtils;
+import com.ruoyi.ems.core.MessageCache;
+import com.ruoyi.ems.core.MqttTemplate;
+import com.ruoyi.ems.domain.EmsDevice;
+import com.ruoyi.ems.domain.EmsObjAbilityCallLog;
+import com.ruoyi.ems.domain.EmsObjAttrValue;
+import com.ruoyi.ems.model.AbilityPayload;
+import com.ruoyi.ems.model.MqttCacheMsg;
+import com.ruoyi.ems.service.IEmsDeviceService;
+import com.ruoyi.ems.service.IEmsObjAbilityCallLogService;
+import com.ruoyi.ems.service.IEmsObjAttrValueService;
+import com.ruoyi.ems.util.IdUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Qualifier;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.Date;
+
+/**
+ * GeekOpen 断路器服务层
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Service
+public class GeekOpenCbHandler extends MqttBaseHandler {
+    private static final Logger log = LoggerFactory.getLogger(GeekOpenCbHandler.class);
+
+    @Resource
+    @Qualifier("mqttTemplate")
+    private MqttTemplate mqttTemplate;
+
+    @Autowired
+    private MessageCache messageCache;
+
+    @Autowired
+    private IEmsDeviceService deviceService;
+
+    @Autowired
+    private IEmsObjAttrValueService objAttrValueService;
+
+    @Autowired
+    private IEmsObjAbilityCallLogService objAbilityCallLogService;
+
+    private static final String TOPIC_PREFIX = "/device/dlq/";
+
+    /**
+     * 能力执行
+     *
+     * @param abilityParam 执行参数
+     * @return 响应
+     */
+    @Override
+    public String call(AbilityPayload abilityParam) {
+        String retStr = null;
+
+        String messageId = IdUtils.generateMessageId();
+        String deviceCode = abilityParam.getObjCode();
+        String msgBody = addMsgId(abilityParam.getAbilityParam(), "messageId", messageId);
+
+        // 发送消息到MQTT服务器
+        long sendTime = System.currentTimeMillis();
+        String topic = TOPIC_PREFIX + deviceCode;
+        mqttTemplate.send(topic, msgBody, 2, false);
+
+        // 写入日志
+        EmsObjAbilityCallLog logItem = saveLog(abilityParam, sendTime, 1);
+
+        while (true) {
+            MqttCacheMsg cacheMsg = messageCache.getAndRemoveMqttMessage(messageId);
+
+            if (null != cacheMsg) {
+                if (checkResult(abilityParam, cacheMsg)) {
+                    retStr = "执行成功!";
+                    updateLog(logItem, cacheMsg, 1);
+                }
+                else {
+                    retStr = "执行失败!";
+                    updateLog(logItem, cacheMsg, 2);
+                }
+                break;
+            }
+
+            ThreadUtils.sleep(100);
+
+            if (System.currentTimeMillis() - sendTime > 60000) {
+                retStr = "响应超时!";
+                break;
+            }
+        }
+
+        return retStr;
+    }
+
+    @Async("msgHandleExecutor")
+    @Override
+    public void msgHandle(String deviceCode, String payload) {
+        try {
+            EmsDevice device = deviceService.selectByCode(deviceCode);
+
+            if (null != device) {
+                JSONObject msgBody = JSONObject.parseObject(payload);
+                refreshStatus(device);
+
+                String messageId = msgBody.getString("messageId");
+
+                if (StringUtils.equals("auto", messageId)) {
+                    updateAttr(device, 2, msgBody);
+                }
+                else if (StringUtils.isNotEmpty(messageId)) {
+                    MqttCacheMsg mqttCacheMsg = new MqttCacheMsg(messageId, deviceCode, new Date(), payload);
+                    messageCache.addMqttMessage(messageId, mqttCacheMsg);
+                }
+            }
+            else {
+                log.warn("接收消息,设备未注册, deviceCode:{}\nmessageBody:{}", deviceCode, payload);
+            }
+        }
+        catch (Exception e) {
+            log.error(e.getMessage(), e);
+        }
+    }
+
+    /**
+     * 刷新设备状态
+     * @param device 设备信息
+     */
+    private void refreshStatus(EmsDevice device) {
+        device.setDeviceStatus(1);
+        deviceService.updateEmsDevice(device);
+    }
+
+    private void updateAttr(EmsDevice device, Integer objType, JSONObject jsonBody) {
+        if (jsonBody.containsKey("voltage")) {
+            EmsObjAttrValue attrValue = new EmsObjAttrValue(device.getDeviceCode(), objType, device.getDeviceModel(),
+                "voltage", jsonBody.getString("voltage"));
+            objAttrValueService.mergeObjAttrValue(attrValue);
+        }
+
+        if (jsonBody.containsKey("current")) {
+            EmsObjAttrValue attrValue = new EmsObjAttrValue(device.getDeviceCode(), objType, device.getDeviceModel(),
+                "current", jsonBody.getString("current"));
+            objAttrValueService.mergeObjAttrValue(attrValue);
+        }
+
+        if (jsonBody.containsKey("power")) {
+            EmsObjAttrValue attrValue = new EmsObjAttrValue(device.getDeviceCode(), objType, device.getDeviceModel(),
+                "power", jsonBody.getString("power"));
+            objAttrValueService.mergeObjAttrValue(attrValue);
+        }
+
+        if (jsonBody.containsKey("energy")) {
+            EmsObjAttrValue attrValue = new EmsObjAttrValue(device.getDeviceCode(), objType, device.getDeviceModel(),
+                "energy", jsonBody.getString("energy"));
+            objAttrValueService.mergeObjAttrValue(attrValue);
+        }
+    }
+
+    private boolean checkResult(AbilityPayload abilityParam, MqttCacheMsg cacheMsg) {
+        boolean flag = true;
+
+        try {
+            String sendParam = abilityParam.getAbilityParam();
+            String receiveParam = cacheMsg.getPayload();
+
+            JSONObject sendObject = JSONObject.parseObject(sendParam);
+            JSONObject receiveObject = JSONObject.parseObject(receiveParam);
+
+            String type = sendObject.getString("type");
+
+            if (StringUtils.equals(type, "event")) {
+                int sendKeyValue = sendObject.getIntValue("key");
+                int receiveKeyValue = receiveObject.getIntValue("key");
+                Assert.isTrue(sendKeyValue == receiveKeyValue, -1, "响应参数key校验失败!");
+            }
+            else if (StringUtils.equals(type, "setting")) {
+                if (sendObject.containsKey("keyLock")) {
+                    int sendKeyLockValue = sendObject.getIntValue("keyLock");
+                    int receiveKeyLockValue = receiveObject.getIntValue("keyLock");
+                    Assert.isTrue(sendKeyLockValue == receiveKeyLockValue, -1, "响应参数keyLock校验失败!");
+                }
+                else if (sendObject.containsKey("timerEnable") && sendObject.containsKey("timerInterval")) {
+                    int sendTimerEnableValue = sendObject.getIntValue("timerEnable");
+                    int receiveTimerEnableValue = receiveObject.getIntValue("timerEnable");
+                    Assert.isTrue(sendTimerEnableValue == receiveTimerEnableValue, -1, "响应参数timerEnable校验失败!");
+                    int sendTimerIntervalValue = sendObject.getIntValue("keyLock");
+                    int receiveTimerIntervalValue = receiveObject.getIntValue("timerInterval");
+                    Assert.isTrue(sendTimerIntervalValue == receiveTimerIntervalValue, -1,
+                        "响应参数timerInterval校验失败!");
+                }
+                else if (sendObject.containsKey("onState")) {
+                    int sendOnStateValue = sendObject.getIntValue("onState");
+                    int receiveOnStateValue = receiveObject.getIntValue("onState");
+                    Assert.isTrue(sendOnStateValue == receiveOnStateValue, -1, "响应参数onState校验失败!");
+                }
+            }
+        }
+        catch (BusinessException e) {
+            log.info(e.getMessage());
+            flag = false;
+        }
+        catch (Exception e) {
+            log.error(e.getMessage(), e);
+            flag = false;
+        }
+
+        return flag;
+    }
+
+    private EmsObjAbilityCallLog saveLog(AbilityPayload abilityParam, long sendTime, int callStatus) {
+        EmsObjAbilityCallLog objAbilityCallLog = new EmsObjAbilityCallLog();
+        objAbilityCallLog.setObjCode(abilityParam.getObjCode());
+        objAbilityCallLog.setObjType(abilityParam.getObjType());
+        objAbilityCallLog.setModelCode(abilityParam.getModeCode());
+        objAbilityCallLog.setAbilityKey(abilityParam.getAbilityKey());
+        objAbilityCallLog.setCallTime(new Date(sendTime));
+        objAbilityCallLog.setCallParam(abilityParam.getAbilityParam());
+        objAbilityCallLog.setCallStatus(callStatus);
+        objAbilityCallLogService.addLog(objAbilityCallLog);
+        return objAbilityCallLog;
+    }
+
+    private void updateLog(EmsObjAbilityCallLog objAbilityCallLog, MqttCacheMsg cacheMsg, int callStatus) {
+        objAbilityCallLog.setResTime(cacheMsg.getReceiveTime());
+        objAbilityCallLog.setResParam(cacheMsg.getPayload());
+        objAbilityCallLog.setCallStatus(callStatus);
+        objAbilityCallLogService.updateLog(objAbilityCallLog);
+    }
+}

+ 64 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/MqttBaseHandler.java

@@ -0,0 +1,64 @@
+/*
+ * 文 件 名:  BaseSendHandler
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/3/3
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.handle;
+
+import com.alibaba.fastjson2.JSONObject;
+import com.ruoyi.ems.model.AbilityPayload;
+import com.ruoyi.ems.util.IdUtils;
+
+/**
+ * Mqtt基类
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/3/3]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public abstract class MqttBaseHandler {
+    /**
+     * 抽象方法,用于能力调用
+     *
+     * @param abilityParam 能力参数
+     * @return 处理结果字符串
+     */
+    public abstract String call(AbilityPayload abilityParam);
+
+    /**
+     * 抽象方法,用于消息处理
+     *
+     * @param deviceCode 设备编码
+     * @param payload    负载数据
+     * @return 处理结果字符串
+     */
+    public abstract void msgHandle(String deviceCode, String payload);
+
+    /**
+     * 默认-生成消息ID
+     *
+     * @return String 消息ID
+     */
+    public String newMsgId() {
+        return IdUtils.generateMessageId();
+    }
+
+    /**
+     * 添加消息ID到消息中
+     *
+     * @param msg
+     * @return
+     */
+    public String addMsgId(String msg, String msgIdKey, String msgIdValue) {
+        JSONObject json = JSONObject.parseObject(msg);
+        json.put(msgIdKey, msgIdValue);
+        return json.toString();
+    }
+}

+ 19 - 6
ems/ems-application/ems-collect/src/main/java/com/ruoyi/handle/RootMsgHandler.java → ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/RootMsgHandler.java

@@ -8,11 +8,14 @@
  * 修改单号:  <修改单号>
  * 修改内容:  <修改内容>
  */
-package com.ruoyi.handle;
+package com.ruoyi.ems.handle;
 
-import com.ruoyi.core.MqttMessageHandler;
+import com.ruoyi.ems.core.MqttMessageHandler;
+import com.ruoyi.ems.core.MessageCache;
+import org.apache.commons.lang3.StringUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -28,11 +31,21 @@ import org.springframework.stereotype.Service;
 public class RootMsgHandler implements MqttMessageHandler {
     private static final Logger log = LoggerFactory.getLogger(RootMsgHandler.class);
 
+    @Autowired
+    private GeekOpenCbHandler geekOpenCbHandler;
+
     @Override
     public void handle(String topic, String payload) {
-        log.info("[Receive]Topic:{}, message:{}", topic, payload);
-        //TODO
-        //业务逻辑处理
-        //从线程池取一个线程执行处理
+        try {
+            log.info("[Receive]Topic:{}, message:{}", topic, payload);
+
+            if (StringUtils.startsWith(topic, "/server/dlq/")) {
+                String deviceCode = StringUtils.substringAfter(topic, "/server/dlq/");
+                geekOpenCbHandler.msgHandle(deviceCode, payload);
+            }
+        }
+        catch (Exception e) {
+            log.error("[Handle]Topic:{}, message:{}", topic, payload, e);
+        }
     }
 }

+ 86 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/MqttCacheMsg.java

@@ -0,0 +1,86 @@
+/*
+ * 文 件 名:  BaseMsg
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model;
+
+import java.util.Date;
+
+/**
+ * Mqtt交互消息
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class MqttCacheMsg {
+    /**
+     * 消息ID
+     */
+    private String messageId;
+
+    /**
+     * 设备代码
+     */
+    private String deviceCode;
+
+    /**
+     * 接收内容
+     */
+    private String payload;
+
+    /**
+     * 接收时间
+     */
+    private Date receiveTime;
+
+    public MqttCacheMsg() {
+    }
+
+    public MqttCacheMsg(String messageId, String deviceCode, Date date, String receivePayload) {
+        this.messageId = messageId;
+        this.deviceCode = deviceCode;
+        this.receiveTime = date;
+        this.payload = receivePayload;
+    }
+
+    public String getMessageId() {
+        return messageId;
+    }
+
+    public void setMessageId(String messageId) {
+        this.messageId = messageId;
+    }
+
+    public String getDeviceCode() {
+        return deviceCode;
+    }
+
+    public void setDeviceCode(String deviceCode) {
+        this.deviceCode = deviceCode;
+    }
+
+    public String getPayload() {
+        return payload;
+    }
+
+    public void setPayload(String payload) {
+        this.payload = payload;
+    }
+
+    public Date getReceiveTime() {
+        return receiveTime;
+    }
+
+    public void setReceiveTime(Date receiveTime) {
+        this.receiveTime = receiveTime;
+    }
+}

+ 68 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/util/DataSourceUtils.java

@@ -0,0 +1,68 @@
+/*
+ * 文 件 名:  DataSourceUtils
+ * 版    权:  浩鲸云计算科技股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  learshaw
+ * 修改时间:  2019/7/16
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.util;
+
+import com.alibaba.druid.pool.DruidDataSource;
+import org.apache.ibatis.session.SqlSessionFactory;
+import org.mybatis.spring.SqlSessionFactoryBean;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
+
+import javax.sql.DataSource;
+
+/**
+ * DataSource工具类 <功能详细描述>
+ *
+ * @author learshaw
+ * @version [版本号, 2019/7/16]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public abstract class DataSourceUtils {
+    private static final Logger log = LoggerFactory.getLogger(DataSourceUtils.class);
+
+    /**
+     * 数据源配置
+     *
+     * @param driverClass 驱动
+     * @param url         地址
+     * @param user        用户名
+     * @param password    密码
+     * @return 数据源
+     */
+    public static DruidDataSource buildDataSource(String driverClass, String url, String user, String password) {
+        DruidDataSource dataSource = new DruidDataSource();
+        dataSource.setDriverClassName(driverClass);
+        dataSource.setUrl(url);
+        dataSource.setUsername(user);
+        dataSource.setPassword(password);
+
+        return dataSource;
+    }
+
+    public static SqlSessionFactory buildSqlSessionFactory(DataSource dataSource, String mapperLocation,
+        String mybatisConfig) {
+        SqlSessionFactory factory = null;
+        try {
+            SqlSessionFactoryBean sessionFactory = new SqlSessionFactoryBean();
+            sessionFactory.setDataSource(dataSource);
+            sessionFactory.setMapperLocations(new PathMatchingResourcePatternResolver().getResources(mapperLocation));
+            sessionFactory.setConfigLocation(new PathMatchingResourcePatternResolver().getResource(mybatisConfig));
+            factory = sessionFactory.getObject();
+        }
+        catch (Exception e) {
+            log.error("buildSqlSessionFactory fail!", e);
+        }
+
+        return factory;
+    }
+}

+ 41 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/util/IdUtils.java

@@ -0,0 +1,41 @@
+/*
+ * 文 件 名:  MessageIdGenerator
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.util;
+
+import java.util.concurrent.ThreadLocalRandom;
+
+/**
+ * 消息ID生成器
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public abstract class IdUtils {
+    // 包含数字、大小写字母的字符池
+    private static final String CHAR_POOL = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+    // 生成消息ID
+    public static String generateMessageId() {
+        ThreadLocalRandom random = ThreadLocalRandom.current();
+        // 生成8-16位随机长度
+        int length = random.nextInt(8, 17);
+        StringBuilder sb = new StringBuilder(length);
+
+        for (int i = 0; i < length; i++) {
+            int index = random.nextInt(CHAR_POOL.length());
+            sb.append(CHAR_POOL.charAt(index));
+        }
+        return sb.toString();
+    }
+}

+ 68 - 0
ems/ems-cloud/ems-dev-adapter/src/main/resources/application-local.yml

@@ -0,0 +1,68 @@
+# spring配置
+spring:
+  mvc:
+    pathmatch:
+      matching-strategy: ant_path_matcher
+  redis:
+    host: 172.192.10.105
+    port: 30013
+    password:
+  datasource:
+    druid:
+      stat-view-servlet:
+        enabled: true
+        loginUsername: admin
+        loginPassword: 123456
+    dynamic:
+      druid:
+        initial-size: 5
+        min-idle: 5
+        maxActive: 20
+        maxWait: 60000
+        timeBetweenEvictionRunsMillis: 60000
+        minEvictableIdleTimeMillis: 300000
+        validationQuery: SELECT 1 FROM DUAL
+        testWhileIdle: true
+        testOnBorrow: false
+        testOnReturn: false
+        poolPreparedStatements: true
+        maxPoolPreparedStatementPerConnectionSize: 20
+        filters: stat,slf4j
+        connectionProperties: druid.stat.mergeSql\=true;druid.stat.slowSqlMillis\=5000
+      datasource:
+        # 主库数据源
+        master:
+          driver-class-name: com.mysql.cj.jdbc.Driver
+          url: jdbc:mysql://172.192.10.105:30002/ems_ct?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8
+          username: root
+          password: root
+          # 从库数据源
+          # slave:
+          # username:
+          # password:
+          # url:
+          # driver-class-name:
+
+mqtt:
+  server:
+    host: tcp://xt.wenhq.top:8581
+    client_id: ems-dev-adapter
+  executor:
+    msgHandle:
+      corePoolSize: 20
+      maxPoolSize: 50
+      queueCapacity: 2000
+      namePrefix: 'mqttHandle-'
+
+# mybatis配置
+mybatis:
+  # 搜索指定包别名
+  typeAliasesPackage: com.ruoyi.ems.**.domain;
+  # 配置mapper的扫描,找到所有的mapper.xml映射文件
+  mapperLocations: classpath*:mapper/**/*.xml
+  configuration:
+    map-underscore-to-camel-case: true
+# swagger配置
+swagger:
+  title: 能源模块接口文档
+  enabled: true

+ 10 - 0
ems/ems-cloud/ems-dev-adapter/src/main/resources/banner.txt

@@ -0,0 +1,10 @@
+Spring Boot Version: ${spring-boot.version}
+Spring Application Name: ${spring.application.name}
+ _____               ______              ___      _             _
+|  ___|              |  _  \            / _ \    | |           | |
+| |__ _ __ ___  ___  | | | |_____   __ / /_\ \ __| | __ _ _ __ | |_ ___ _ __
+|  __| '_ ` _ \/ __| | | | / _ \ \ / / |  _  |/ _` |/ _` | '_ \| __/ _ \ '__|
+| |__| | | | | \__ \ | |/ /  __/\ V /  | | | | (_| | (_| | |_) | ||  __/ |
+\____/_| |_| |_|___/ |___/ \___| \_/   \_| |_/\__,_|\__,_| .__/ \__\___|_|
+                                                         | |
+                                                         |_|

+ 35 - 0
ems/ems-cloud/ems-dev-adapter/src/main/resources/bootstrap.yml

@@ -0,0 +1,35 @@
+# Tomcat
+server:
+  port: 9203
+  servlet:
+    context-path: /ems-dev-adapter
+# Spring
+spring:
+  application:
+    # 应用名称
+    name: ems-dev-adapter
+  profiles:
+    # 环境配置
+    active: local
+  cloud:
+    nacos:
+      discovery:
+        # 服务注册地址
+        server-addr: 172.192.10.105:30003
+        group: ems
+        #server-addr: 172.10.0.71:8848
+        #group: public
+      config:
+        # 配置中心地址
+        server-addr: 172.192.10.105:30003
+        group: ems
+        #server-addr: 172.10.0.71:8848
+        #group: public
+        # 配置文件格式
+        file-extension: yml
+        # 共享配置
+        shared-configs:
+          - application-${spring.profiles.active}.${spring.cloud.nacos.config.file-extension}
+logging:
+  level:
+    com.ruoyi.ems: debug

+ 17 - 36
ems/ems-application/ems-collect/src/main/resources/logback.xml → ems/ems-cloud/ems-dev-adapter/src/main/resources/logback.xml

@@ -1,24 +1,24 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<configuration>
+<configuration scan="true" scanPeriod="60 seconds" debug="false">
     <!-- 日志存放路径 -->
-	<property name="log.path" value="./ruoyi/logs" />
-    <!-- 日志输出格式 -->
+	<property name="log.path" value="logs/ems-server" />
+   <!-- 日志输出格式 -->
 	<property name="log.pattern" value="%d{HH:mm:ss.SSS} [%thread] %-5level %logger{20} - [%method,%line] - %msg%n" />
 
-	<!-- 控制台输出 -->
+    <!-- 控制台输出 -->
 	<appender name="console" class="ch.qos.logback.core.ConsoleAppender">
 		<encoder>
 			<pattern>${log.pattern}</pattern>
 		</encoder>
 	</appender>
-	
-	<!-- 系统日志输出 -->
+
+    <!-- 系统日志输出 -->
 	<appender name="file_info" class="ch.qos.logback.core.rolling.RollingFileAppender">
-	    <file>${log.path}/sys-info.log</file>
+	    <file>${log.path}/info.log</file>
         <!-- 循环政策:基于时间创建日志文件 -->
 		<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
             <!-- 日志文件名格式 -->
-			<fileNamePattern>${log.path}/sys-info.%d{yyyy-MM-dd}.log</fileNamePattern>
+			<fileNamePattern>${log.path}/info.%d{yyyy-MM-dd}.log</fileNamePattern>
 			<!-- 日志最大的历史 60天 -->
 			<maxHistory>60</maxHistory>
 		</rollingPolicy>
@@ -34,13 +34,13 @@
             <onMismatch>DENY</onMismatch>
         </filter>
 	</appender>
-	
-	<appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
-	    <file>${log.path}/sys-error.log</file>
+
+    <appender name="file_error" class="ch.qos.logback.core.rolling.RollingFileAppender">
+	    <file>${log.path}/error.log</file>
         <!-- 循环政策:基于时间创建日志文件 -->
         <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
             <!-- 日志文件名格式 -->
-            <fileNamePattern>${log.path}/sys-error.%d{yyyy-MM-dd}.log</fileNamePattern>
+            <fileNamePattern>${log.path}/error.%d{yyyy-MM-dd}.log</fileNamePattern>
 			<!-- 日志最大的历史 60天 -->
 			<maxHistory>60</maxHistory>
         </rollingPolicy>
@@ -56,22 +56,8 @@
             <onMismatch>DENY</onMismatch>
         </filter>
     </appender>
-	
-	<!-- 用户访问日志输出  -->
-    <appender name="sys-user" class="ch.qos.logback.core.rolling.RollingFileAppender">
-		<file>${log.path}/sys-user.log</file>
-        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
-            <!-- 按天回滚 daily -->
-            <fileNamePattern>${log.path}/sys-user.%d{yyyy-MM-dd}.log</fileNamePattern>
-            <!-- 日志最大的历史 60天 -->
-            <maxHistory>60</maxHistory>
-        </rollingPolicy>
-        <encoder>
-            <pattern>${log.pattern}</pattern>
-        </encoder>
-    </appender>
-	
-	<!-- 系统模块日志级别控制  -->
+
+    <!-- 系统模块日志级别控制  -->
 	<logger name="com.ruoyi" level="info" />
 	<!-- Spring日志级别控制  -->
 	<logger name="org.springframework" level="warn" />
@@ -79,15 +65,10 @@
 	<root level="info">
 		<appender-ref ref="console" />
 	</root>
-	
+
 	<!--系统操作日志-->
-    <root level="info">
+    <root level="INFO">
         <appender-ref ref="file_info" />
         <appender-ref ref="file_error" />
     </root>
-	
-	<!--系统用户操作日志-->
-    <logger name="sys-user" level="info">
-        <appender-ref ref="sys-user"/>
-    </logger>
-</configuration> 
+</configuration>

+ 28 - 0
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAbilityController.java

@@ -1,12 +1,15 @@
 package com.ruoyi.ems.controller;
 
 import com.huashe.common.domain.AjaxResult;
+import com.huashe.common.exception.BusinessException;
 import com.ruoyi.common.core.utils.poi.ExcelUtil;
 import com.ruoyi.common.core.web.controller.BaseController;
 import com.ruoyi.common.core.web.page.TableDataInfo;
 import com.ruoyi.common.log.annotation.Log;
 import com.ruoyi.common.log.enums.BusinessType;
 import com.ruoyi.ems.domain.EmsObjAbility;
+import com.ruoyi.ems.model.AbilityPayload;
+import com.ruoyi.ems.service.IAbilityCallService;
 import com.ruoyi.ems.service.IEmsObjAbilityService;
 import io.swagger.annotations.Api;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,6 +38,31 @@ public class EmsObjAbilityController extends BaseController {
     @Autowired
     private IEmsObjAbilityService abilityService;
 
+    @Autowired
+    private IAbilityCallService abilityCallService;
+
+    /**
+     * 查询能源对象能力列表
+     */
+    @PostMapping("/call")
+    public AjaxResult callAbility(@RequestBody AbilityPayload abilityPayload) {
+        AjaxResult ajaxResult = null;
+
+        try {
+            String ret = abilityCallService.abilityCall(abilityPayload.getObjCode(), abilityPayload.getObjType(),
+                abilityPayload.getAbilityKey(), abilityPayload.getAbilityParam());
+            ajaxResult = success(ret);
+        }
+        catch (BusinessException e) {
+            ajaxResult = error(e.getMessage());
+        }
+        catch (Exception e) {
+            ajaxResult = error("内部错误!");
+        }
+
+        return ajaxResult;
+    }
+
     /**
      * 查询能源对象能力列表
      */

+ 4 - 13
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAttrValueController.java

@@ -53,10 +53,10 @@ public class EmsObjAttrValueController extends BaseController {
     /**
      * 新增能源对象属性值
      */
-    @Log(title = "能源对象属性值", businessType = BusinessType.INSERT)
-    @PostMapping
-    public AjaxResult add(@RequestBody EmsObjAttrValue EmsObjAttrValue) {
-        return toAjax(objAttrValueService.insertObjAttrValue(EmsObjAttrValue));
+    @Log(title = "能源对象属性值", businessType = BusinessType.UPDATE)
+    @PutMapping
+    public AjaxResult merge(@RequestBody EmsObjAttrValue EmsObjAttrValue) {
+        return toAjax(objAttrValueService.mergeObjAttrValue(EmsObjAttrValue));
     }
 
     /**
@@ -69,15 +69,6 @@ public class EmsObjAttrValueController extends BaseController {
     }
 
     /**
-     * 修改能源对象属性值
-     */
-    @Log(title = "能源对象属性值", businessType = BusinessType.UPDATE)
-    @PutMapping
-    public AjaxResult edit(@RequestBody EmsObjAttrValue EmsObjAttrValue) {
-        return toAjax(objAttrValueService.updateObjAttrValue(EmsObjAttrValue));
-    }
-
-    /**
      * 删除能源对象属性值
      */
     @Log(title = "能源对象属性值", businessType = BusinessType.DELETE)

+ 0 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/task/BaseTask.java → ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/task/BaseTask.java


+ 0 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/task/taskiml/FacTask.java → ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/task/taskiml/FacTask.java


+ 1 - 0
ems/ems-cloud/pom.xml

@@ -13,6 +13,7 @@
 
     <modules>
         <module>ems-server</module>
+        <module>ems-dev-adapter</module>
     </modules>
 
     <packaging>pom</packaging>

+ 7 - 0
ems/ems-core/pom.xml

@@ -25,6 +25,7 @@
         <lombook.version>1.18.28</lombook.version>
         <prod-commons.version>1.0-SNAPSHOT</prod-commons.version>
         <mybatis.version>3.5.13</mybatis.version>
+        <httpclient.version>4.5.13</httpclient.version>
     </properties>
 
     <dependencies>
@@ -87,6 +88,12 @@
             <artifactId>ruoyi-common-quartz</artifactId>
             <version>${ruoyi-cloud.version}</version>
         </dependency>
+
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>${httpclient.version}</version>
+        </dependency>
     </dependencies>
 
     <build>

+ 3 - 3
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsDevice.java

@@ -58,7 +58,7 @@ public class EmsDevice extends BaseEntity {
      * 设备状态
      */
     @Excel(name = "设备状态")
-    private Long deviceStatus;
+    private Integer deviceStatus;
 
     /**
      * 安装位置
@@ -191,11 +191,11 @@ public class EmsDevice extends BaseEntity {
         this.deviceSpec = deviceSpec;
     }
 
-    public Long getDeviceStatus() {
+    public Integer getDeviceStatus() {
         return deviceStatus;
     }
 
-    public void setDeviceStatus(Long deviceStatus) {
+    public void setDeviceStatus(Integer deviceStatus) {
         this.deviceStatus = deviceStatus;
     }
 

+ 12 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAbility.java

@@ -32,6 +32,9 @@ public class EmsObjAbility extends BaseEntity
     /** 能力参数 */
     private String abilityParam;
 
+    /** 隐藏标记 */
+    private Integer hiddenFlag;
+
     public void setId(Long id) 
     {
         this.id = id;
@@ -87,6 +90,14 @@ public class EmsObjAbility extends BaseEntity
         return abilityParam;
     }
 
+    public Integer getHiddenFlag() {
+        return hiddenFlag;
+    }
+
+    public void setHiddenFlag(Integer hiddenFlag) {
+        this.hiddenFlag = hiddenFlag;
+    }
+
     @Override
     public String toString() {
         return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
@@ -96,6 +107,7 @@ public class EmsObjAbility extends BaseEntity
             .append("abilityName", getAbilityName())
             .append("abilityDesc", getAbilityDesc())
             .append("abilityParam", getAbilityParam())
+            .append("hiddenFlag", getHiddenFlag())
             .toString();
     }
 }

+ 157 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAbilityCallLog.java

@@ -0,0 +1,157 @@
+package com.ruoyi.ems.domain;
+
+import java.util.Date;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.huashe.common.domain.BaseEntity;
+import org.apache.commons.lang3.builder.ToStringBuilder;
+import org.apache.commons.lang3.builder.ToStringStyle;
+
+
+/**
+ * 能源对象能力调用日志对象 adm_ems_obj_ability_call_log
+ * 
+ * @author ruoyi
+ * @date 2025-02-27
+ */
+public class EmsObjAbilityCallLog extends BaseEntity
+{
+    private static final long serialVersionUID = 1L;
+
+    /** 序号 */
+    private Long id;
+
+    /** 对象代码 */
+    private String objCode;
+
+    /** 对象类型 */
+    private Integer objType;
+
+    private String modelCode;
+
+    /** 能力键 */
+    private String abilityKey;
+
+    /** 调用时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date callTime;
+
+    /** 调用参数 */
+    private String callParam;
+
+    /** 调用状态 */
+    private Integer callStatus;
+
+    /** 响应时间 */
+    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
+    private Date resTime;
+
+    /** 响应内容 */
+    private String resParam;
+
+    public void setId(Long id) 
+    {
+        this.id = id;
+    }
+
+    public Long getId() 
+    {
+        return id;
+    }
+    public void setObjCode(String objCode) 
+    {
+        this.objCode = objCode;
+    }
+
+    public String getObjCode() 
+    {
+        return objCode;
+    }
+    public void setObjType(Integer objType)
+    {
+        this.objType = objType;
+    }
+
+    public Integer getObjType()
+    {
+        return objType;
+    }
+    public void setModelCode(String modelCode) 
+    {
+        this.modelCode = modelCode;
+    }
+
+    public String getModelCode() 
+    {
+        return modelCode;
+    }
+    public void setAbilityKey(String abilityKey) 
+    {
+        this.abilityKey = abilityKey;
+    }
+
+    public String getAbilityKey() 
+    {
+        return abilityKey;
+    }
+    public void setCallTime(Date callTime) 
+    {
+        this.callTime = callTime;
+    }
+
+    public Date getCallTime() 
+    {
+        return callTime;
+    }
+    public void setCallParam(String callParam) 
+    {
+        this.callParam = callParam;
+    }
+
+    public String getCallParam() 
+    {
+        return callParam;
+    }
+    public void setCallStatus(Integer callStatus)
+    {
+        this.callStatus = callStatus;
+    }
+
+    public Integer getCallStatus()
+    {
+        return callStatus;
+    }
+    public void setResTime(Date resTime) 
+    {
+        this.resTime = resTime;
+    }
+
+    public Date getResTime() 
+    {
+        return resTime;
+    }
+    public void setResParam(String resParam) 
+    {
+        this.resParam = resParam;
+    }
+
+    public String getResParam() 
+    {
+        return resParam;
+    }
+
+    @Override
+    public String toString() {
+        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
+            .append("id", getId())
+            .append("objCode", getObjCode())
+            .append("objType", getObjType())
+            .append("modelCode", getModelCode())
+            .append("abilityKey", getAbilityKey())
+            .append("callTime", getCallTime())
+            .append("callParam", getCallParam())
+            .append("callStatus", getCallStatus())
+            .append("resTime", getResTime())
+            .append("resParam", getResParam())
+            .toString();
+    }
+}

+ 66 - 53
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAttrValue.java

@@ -3,109 +3,122 @@ package com.ruoyi.ems.domain;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
 
+import java.util.Date;
+
 /**
  * 能源对象属性值对象 adm_ems_obj_attr_value
- * 
+ *
  * @author ruoyi
  * @date 2024-09-25
  */
-public class EmsObjAttrValue
-{
-    /** 序号 */
+public class EmsObjAttrValue {
+    /**
+     * 序号
+     */
     private Long id;
 
-    /** 对象代码 */
+    /**
+     * 对象代码
+     */
     private String objCode;
 
-    /** 对象类型 */
+    /**
+     * 对象类型
+     */
     private Integer objType;
 
-    /** 属性标识 */
+    /**
+     * 属性标识
+     */
     private String attrKey;
 
-    /** 属性名称 */
-    private String attrName;
-
-    /** 属性值 */
+    /**
+     * 属性值
+     */
     private String attrValue;
 
-    /** 模型code */
+    /**
+     * 模型code
+     */
     private String modelCode;
 
-    public void setId(Long id) 
-    {
+    /**
+     * 更新时间
+     */
+    private Date updateTime;
+
+    public EmsObjAttrValue() {
+    }
+
+    public EmsObjAttrValue(String objCode, Integer objType, String modelCode, String attrKey, String attrValue) {
+        this.objCode = objCode;
+        this.objType = objType;
+        this.modelCode = modelCode;
+        this.attrKey = attrKey;
+        this.attrValue = attrValue;
+    }
+
+    public void setId(Long id) {
         this.id = id;
     }
 
-    public Long getId() 
-    {
+    public Long getId() {
         return id;
     }
-    public void setObjCode(String objCode) 
-    {
+
+    public void setObjCode(String objCode) {
         this.objCode = objCode;
     }
 
-    public String getObjCode() 
-    {
+    public String getObjCode() {
         return objCode;
     }
-    public void setObjType(Integer objType)
-    {
+
+    public void setObjType(Integer objType) {
         this.objType = objType;
     }
 
-    public Integer getObjType()
-    {
+    public Integer getObjType() {
         return objType;
     }
-    public void setAttrKey(String attrKey) 
-    {
+
+    public void setAttrKey(String attrKey) {
         this.attrKey = attrKey;
     }
 
-    public String getAttrKey() 
-    {
+    public String getAttrKey() {
         return attrKey;
     }
 
-    public String getAttrName() {
-        return attrName;
-    }
-
-    public void setAttrName(String attrName) {
-        this.attrName = attrName;
-    }
-
-    public void setAttrValue(String attrValue)
-    {
+    public void setAttrValue(String attrValue) {
         this.attrValue = attrValue;
     }
 
-    public String getAttrValue() 
-    {
+    public String getAttrValue() {
         return attrValue;
     }
-    public void setModelCode(String modelCode) 
-    {
+
+    public void setModelCode(String modelCode) {
         this.modelCode = modelCode;
     }
 
-    public String getModelCode() 
-    {
+    public String getModelCode() {
         return modelCode;
     }
 
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
     @Override
     public String toString() {
-        return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE)
-            .append("id", getId())
-            .append("objCode", getObjCode())
-            .append("objType", getObjType())
-            .append("attrKey", getAttrKey())
-            .append("attrName", getAttrName())
-            .append("attrValue", getAttrValue())
-            .append("modelCode", getModelCode())
-            .toString();
+        return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE).append("id", getId())
+            .append("objCode", getObjCode()).append("objType", getObjType()).append("attrKey", getAttrKey())
+            .append("attrValue", getAttrValue()).append("modelCode", getModelCode())
+            .append("updateTime", getUpdateTime()).toString();
     }
 }

+ 24 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjModel.java

@@ -28,6 +28,12 @@ public class EmsObjModel extends BaseEntity
     /** 对象类型 */
     private Long objType;
 
+    /** 对象能力处理 */
+    private String abilityHandler;
+
+    /** 对象事件处理 */
+    private String eventHandler;
+
     private List<EmsObjAttr> attrList;
 
     private List<EmsObjAbility> abilityList;
@@ -71,6 +77,22 @@ public class EmsObjModel extends BaseEntity
         return objType;
     }
 
+    public String getAbilityHandler() {
+        return abilityHandler;
+    }
+
+    public void setAbilityHandler(String abilityHandler) {
+        this.abilityHandler = abilityHandler;
+    }
+
+    public String getEventHandler() {
+        return eventHandler;
+    }
+
+    public void setEventHandler(String eventHandler) {
+        this.eventHandler = eventHandler;
+    }
+
     public List<EmsObjAttr> getAttrList() {
         return attrList;
     }
@@ -102,6 +124,8 @@ public class EmsObjModel extends BaseEntity
             .append("modelCode", getModelCode())
             .append("modelName", getModelName())
             .append("objType", getObjType())
+            .append("abilityHandler", getAbilityHandler())
+            .append("eventHandler", getEventHandler())
             .toString();
     }
 }

+ 2 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsDeviceMapper.java

@@ -2,6 +2,7 @@ package com.ruoyi.ems.mapper;
 
 import com.ruoyi.ems.domain.EmsDevice;
 import com.ruoyi.ems.model.QueryDevice;
+import org.apache.ibatis.annotations.Mapper;
 import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
@@ -13,6 +14,7 @@ import java.util.Map;
  * @author ruoyi
  * @date 2024-07-10
  */
+@Mapper
 public interface EmsDeviceMapper {
     /**
      * 查询能源设备

+ 45 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsObjAbilityCallLogMapper.java

@@ -0,0 +1,45 @@
+package com.ruoyi.ems.mapper;
+
+import com.ruoyi.ems.domain.EmsObjAbilityCallLog;
+
+import java.util.List;
+
+/**
+ * 能源对象能力调用日志Mapper接口
+ *
+ * @author ruoyi
+ * @date 2025-02-27
+ */
+public interface EmsObjAbilityCallLogMapper {
+    /**
+     * 查询能源对象能力调用日志
+     *
+     * @param id 能源对象能力调用日志主键
+     * @return 能源对象能力调用日志
+     */
+    EmsObjAbilityCallLog selectObjAbilityCallLogById(Long id);
+
+    /**
+     * 查询能源对象能力调用日志列表
+     *
+     * @param objAbilityCallLog 能源对象能力调用日志
+     * @return 能源对象能力调用日志集合
+     */
+    List<EmsObjAbilityCallLog> selectObjAbilityCallLog(EmsObjAbilityCallLog objAbilityCallLog);
+
+    /**
+     * 新增能源对象能力调用日志
+     *
+     * @param objAbilityCallLog 能源对象能力调用日志
+     * @return 结果
+     */
+    int insertObjAbilityCallLog(EmsObjAbilityCallLog objAbilityCallLog);
+
+    /**
+     * 修改能源对象能力调用日志
+     *
+     * @param objAbilityCallLog 能源对象能力调用日志
+     * @return 结果
+     */
+    int updateObjAbilityCallLog(EmsObjAbilityCallLog objAbilityCallLog);
+}

+ 1 - 9
ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsObjAttrValueMapper.java

@@ -43,7 +43,7 @@ public interface EmsObjAttrValueMapper {
      * @param objAttrValue 能源对象属性值
      * @return 结果
      */
-    int insertObjAttrValue(EmsObjAttrValue objAttrValue);
+    int replaceObjAttrValue(EmsObjAttrValue objAttrValue);
 
     /**
      * 批量新增能源对象属性值
@@ -54,14 +54,6 @@ public interface EmsObjAttrValueMapper {
     int insertBatch(List<EmsObjAttrValue> list);
 
     /**
-     * 修改能源对象属性值
-     *
-     * @param objAttrValue 能源对象属性值
-     * @return 结果
-     */
-    int updateObjAttrValue(EmsObjAttrValue objAttrValue);
-
-    /**
      * 删除能源对象属性值
      *
      * @param objType 对象类型

+ 87 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/model/AbilityPayload.java

@@ -0,0 +1,87 @@
+/*
+ * 文 件 名:  AbilityPayload
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model;
+
+/**
+ * 能力调用
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class AbilityPayload {
+    /**
+     * 对象代码
+     */
+    private String objCode;
+
+    /**
+     * 对象类型
+     */
+    private Integer objType;
+
+    /**
+     * 模型代码
+     */
+    private String modeCode;
+
+    /**
+     * 能力标识
+     */
+    private String abilityKey;
+
+    /**
+     * 能力参数
+     */
+    private String abilityParam;
+
+    public String getObjCode() {
+        return objCode;
+    }
+
+    public void setObjCode(String objCode) {
+        this.objCode = objCode;
+    }
+
+    public Integer getObjType() {
+        return objType;
+    }
+
+    public void setObjType(Integer objType) {
+        this.objType = objType;
+    }
+
+    public String getModeCode() {
+        return modeCode;
+    }
+
+    public void setModeCode(String modeCode) {
+        this.modeCode = modeCode;
+    }
+
+    public String getAbilityKey() {
+        return abilityKey;
+    }
+
+    public void setAbilityKey(String abilityKey) {
+        this.abilityKey = abilityKey;
+    }
+
+    public String getAbilityParam() {
+        return abilityParam;
+    }
+
+    public void setAbilityParam(String abilityParam) {
+        this.abilityParam = abilityParam;
+    }
+}

+ 60 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/model/CallResponse.java

@@ -0,0 +1,60 @@
+/*
+ * 文 件 名:  CallResponse
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model;
+
+/**
+ * 调用响应
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class CallResponse<T> {
+    private int code;
+
+    private String message;
+
+    private T payload;
+
+    public CallResponse() {
+    }
+
+    public CallResponse(int code, String message) {
+        this.code = code;
+        this.message = message;
+    }
+
+    public int getCode() {
+        return code;
+    }
+
+    public void setCode(int code) {
+        this.code = code;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    public void setMessage(String message) {
+        this.message = message;
+    }
+
+    public T getPayload() {
+        return payload;
+    }
+
+    public void setPayload(T payload) {
+        this.payload = payload;
+    }
+}

+ 24 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/IAbilityCallService.java

@@ -0,0 +1,24 @@
+/*
+ * 文 件 名:  IDeviceCallService
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/26
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.service;
+
+/**
+ * 设备调用服务
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/26]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public interface IAbilityCallService {
+    String abilityCall(String objCode, int objType, String abilityKey, String param);
+}

+ 45 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsObjAbilityCallLogService.java

@@ -0,0 +1,45 @@
+package com.ruoyi.ems.service;
+
+import java.util.List;
+
+import com.ruoyi.ems.domain.EmsObjAbilityCallLog;
+
+/**
+ * 能源对象能力调用日志Service接口
+ *
+ * @author ruoyi
+ * @date 2025-02-27
+ */
+public interface IEmsObjAbilityCallLogService {
+    /**
+     * 查询能源对象能力调用日志
+     *
+     * @param id 能源对象能力调用日志主键
+     * @return 能源对象能力调用日志
+     */
+    EmsObjAbilityCallLog selectLogById(Long id);
+
+    /**
+     * 查询能源对象能力调用日志列表
+     *
+     * @param param 能源对象能力调用日志
+     * @return 能源对象能力调用日志集合
+     */
+    List<EmsObjAbilityCallLog> selectLogList(EmsObjAbilityCallLog param);
+
+    /**
+     * 新增能源对象能力调用日志
+     *
+     * @param objAbilityCallLog 能源对象能力调用日志
+     * @return 结果
+     */
+    int addLog(EmsObjAbilityCallLog objAbilityCallLog);
+
+    /**
+     * 修改能源对象能力调用日志
+     *
+     * @param objAbilityCallLog 能源对象能力调用日志
+     * @return 结果
+     */
+    int updateLog(EmsObjAbilityCallLog objAbilityCallLog);
+}

+ 1 - 9
ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsObjAttrValueService.java

@@ -42,7 +42,7 @@ public interface IEmsObjAttrValueService {
      * @param objAttrValue 能源对象属性值
      * @return 结果
      */
-    int insertObjAttrValue(EmsObjAttrValue objAttrValue);
+    int mergeObjAttrValue(EmsObjAttrValue objAttrValue);
 
     /**
      * 批量新增能源对象属性值
@@ -53,14 +53,6 @@ public interface IEmsObjAttrValueService {
     int insertBatch(List<EmsObjAttrValue> list);
 
     /**
-     * 修改能源对象属性值
-     *
-     * @param objAttrValue 能源对象属性值
-     * @return 结果
-     */
-    int updateObjAttrValue(EmsObjAttrValue objAttrValue);
-
-    /**
      * 批量删除能源对象属性值
      *
      * @param ids 需要删除的能源对象属性值主键集合

+ 161 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/AbilityCallServiceImpl.java

@@ -0,0 +1,161 @@
+/*
+ * 文 件 名:  DeviceCallServiceImpl
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/26
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.service.impl;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.huashe.common.exception.Assert;
+import com.huashe.common.exception.BusinessException;
+import com.ruoyi.ems.domain.EmsDevice;
+import com.ruoyi.ems.domain.EmsObjAbility;
+import com.ruoyi.ems.domain.EmsObjModel;
+import com.ruoyi.ems.model.AbilityPayload;
+import com.ruoyi.ems.model.CallResponse;
+import com.ruoyi.ems.service.IAbilityCallService;
+import com.ruoyi.ems.service.IEmsDeviceService;
+import com.ruoyi.ems.service.IEmsObjModelService;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+/**
+ * 设备调用服务
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/26]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Service
+public class AbilityCallServiceImpl implements IAbilityCallService {
+    private static final Logger log = LoggerFactory.getLogger(AbilityCallServiceImpl.class);
+
+    @Autowired
+    private IEmsDeviceService deviceService;
+
+    @Autowired
+    private IEmsObjModelService objModelService;
+
+    @Override
+    public String abilityCall(String objCode, int objType, String abilityKey, String param) {
+        String ret = null;
+
+        try {
+            Assert.notNull(objCode, -1, "对象代码code不能为空");
+            Assert.notNull(abilityKey, -1, "设备模型能力key不能为空");
+
+            String modeCode = getModeCode(objCode, objType);
+
+            EmsObjModel objModel = objModelService.selectByModelCode(modeCode);
+            Assert.notNull(objModel, -1, "设备模型(" + modeCode + ")不存在");
+            Assert.notNull(objModel.getAbilityHandler(), -1, "设备模型处理Handler未配置");
+
+            List<EmsObjAbility> objAbilitys = objModel.getAbilityList();
+            Assert.isTrue(checkExist(abilityKey, objAbilitys), -1,
+                "设备模型(" + modeCode + ")能力(" + abilityKey + ")不存在");
+
+            AbilityPayload payload = new AbilityPayload();
+            payload.setObjCode(objCode);
+            payload.setModeCode(modeCode);
+            payload.setObjType(objType);
+            payload.setAbilityKey(abilityKey);
+            payload.setAbilityParam(param);
+            String jsonBody = JSON.toJSONString(payload);
+
+            String res = execPost(objModel.getAbilityHandler(), jsonBody);
+            CallResponse<?> callResponse = JSONObject.parseObject(res, CallResponse.class);
+            Assert.isTrue(callResponse.getCode() == 0, -1, callResponse.getMessage());
+            ret = callResponse.getMessage();
+        }
+        catch (BusinessException e) {
+            log.info("调用设备模型能力执行失败! {}", e.getMessage());
+            throw e;
+        }
+        catch (Exception e) {
+            log.info("调用设备模型能力执行失败!", e);
+            throw new BusinessException(e.getMessage(), e);
+        }
+
+        return ret;
+    }
+
+    private String getModeCode(String objCode, int objType) {
+        String modeCode = null;
+
+        if (objType == 2) {
+            // 设备验证
+            EmsDevice device = deviceService.selectByCode(objCode);
+            Assert.notNull(device, -1, "设备不存在");
+            Assert.isTrue(null != device.getDeviceStatus() && device.getDeviceStatus() == 1, -1, "设备不在线");
+
+            // 设备模型匹配
+            Assert.notNull(device.getDeviceModel(), -1, "设备未关联模型能力");
+
+            modeCode = device.getDeviceModel();
+        }
+
+        return modeCode;
+    }
+
+    private String execPost(String url, String jsonBody) {
+        log.info("execPost [request] url:{} \njsonBody:\n{}", url, jsonBody);
+
+        String responseBody = null;
+
+        // 使用try-with-resources自动关闭HttpClient和Response
+        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
+            // 创建POST请求并设置URL
+            HttpPost httpPost = new HttpPost(url);
+
+            // 构造JSON请求体
+            StringEntity requestEntity = new StringEntity(jsonBody, ContentType.APPLICATION_JSON);
+            httpPost.setEntity(requestEntity);
+
+            // 执行请求并处理响应
+            try (CloseableHttpResponse response = httpClient.execute(httpPost)) {
+                // 获取状态码
+                int statusCode = response.getStatusLine().getStatusCode();
+                System.out.println("Status Code: " + statusCode);
+
+                // 获取响应内容
+                responseBody = EntityUtils.toString(response.getEntity());
+                log.info("execPost [response] statusCode:{} \nresponseBody:\n{}", statusCode, responseBody);
+            }
+        }
+        catch (Exception e) {
+            throw new BusinessException(e.getMessage(), e);
+        }
+
+        return responseBody;
+    }
+
+    private boolean checkExist(String abilityKey, List<EmsObjAbility> objAbilitys) {
+        for (EmsObjAbility objAbility : objAbilitys) {
+            if (StringUtils.equals(abilityKey, objAbility.getAbilityKey())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}

+ 42 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAbilityCallLogServiceImpl.java

@@ -0,0 +1,42 @@
+package com.ruoyi.ems.service.impl;
+
+import com.ruoyi.ems.domain.EmsObjAbilityCallLog;
+import com.ruoyi.ems.mapper.EmsObjAbilityCallLogMapper;
+import com.ruoyi.ems.service.IEmsObjAbilityCallLogService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.util.List;
+
+/**
+ * 能源对象能力调用日志Service业务层处理
+ *
+ * @author ruoyi
+ * @date 2025-02-27
+ */
+@Service
+public class EmsObjAbilityCallLogServiceImpl implements IEmsObjAbilityCallLogService {
+    @Resource
+    private EmsObjAbilityCallLogMapper objAbilityCallLogMapper;
+
+    @Override
+    public EmsObjAbilityCallLog selectLogById(Long id) {
+        return objAbilityCallLogMapper.selectObjAbilityCallLogById(id);
+    }
+
+    @Override
+    public List<EmsObjAbilityCallLog> selectLogList(EmsObjAbilityCallLog param) {
+        return objAbilityCallLogMapper.selectObjAbilityCallLog(param);
+    }
+
+    @Override
+    public int addLog(EmsObjAbilityCallLog objAbilityCallLog) {
+        return objAbilityCallLogMapper.insertObjAbilityCallLog(objAbilityCallLog);
+    }
+
+    @Override
+    public int updateLog(EmsObjAbilityCallLog objAbilityCallLog) {
+        return objAbilityCallLogMapper.updateObjAbilityCallLog(objAbilityCallLog);
+    }
+}

+ 3 - 14
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAttrValueServiceImpl.java

@@ -47,14 +47,14 @@ public class EmsObjAttrValueServiceImpl implements IEmsObjAttrValueService {
     }
 
     /**
-     * 新增能源对象属性值
+     * 新增/更新能源对象属性值
      *
      * @param objAttrValue 能源对象属性值
      * @return 结果
      */
     @Override
-    public int insertObjAttrValue(EmsObjAttrValue objAttrValue) {
-        return objAttrValueMapper.insertObjAttrValue(objAttrValue);
+    public int mergeObjAttrValue(EmsObjAttrValue objAttrValue) {
+        return objAttrValueMapper.replaceObjAttrValue(objAttrValue);
     }
 
     @Override
@@ -65,17 +65,6 @@ public class EmsObjAttrValueServiceImpl implements IEmsObjAttrValueService {
     }
 
     /**
-     * 修改能源对象属性值
-     *
-     * @param objAttrValue 能源对象属性值
-     * @return 结果
-     */
-    @Override
-    public int updateObjAttrValue(EmsObjAttrValue objAttrValue) {
-        return objAttrValueMapper.updateObjAttrValue(objAttrValue);
-    }
-
-    /**
      * 批量删除能源对象属性值
      *
      * @param ids 需要删除的能源对象属性值主键

+ 0 - 1
ems/ems-core/src/main/resources/mapper/ems/EmsDeviceMapper.xml

@@ -165,7 +165,6 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="locationType != null">#{locationType},</if>
             <if test="locationRef != null">#{locationRef},</if>
             <if test="areaCode != null">#{areaCode},</if>
-            <if test="areaAncestors !=null">#{areaAncestors},</if>
             <if test="deviceModel !=null">#{deviceModel},</if>
             <if test="refFacs != null">#{refFacs},</if>
             <if test="psCode != null">#{psCode},</if>

+ 88 - 0
ems/ems-core/src/main/resources/mapper/ems/EmsObjAbilityCallLogMapper.xml

@@ -0,0 +1,88 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper
+PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
+"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ruoyi.ems.mapper.EmsObjAbilityCallLogMapper">
+    
+    <resultMap type="com.ruoyi.ems.domain.EmsObjAbilityCallLog" id="objAbilityCallLogResult">
+        <result property="id"    column="id"    />
+        <result property="objCode"    column="obj_code"    />
+        <result property="objType"    column="obj_type"    />
+        <result property="modelCode"    column="model_code"    />
+        <result property="abilityKey"    column="ability_key"    />
+        <result property="callTime"    column="call_time"    />
+        <result property="callParam"    column="call_param"    />
+        <result property="callStatus"    column="call_status"    />
+        <result property="resTime"    column="res_time"    />
+        <result property="resParam"    column="res_param"    />
+    </resultMap>
+
+    <sql id="selectList">
+        select id, obj_code, obj_type, model_code, ability_key, call_time, call_status, res_time from adm_ems_obj_ability_call_log
+    </sql>
+
+    <sql id="selectDetail">
+        select id, obj_code, obj_type, model_code, ability_key, call_time, call_param, call_status, res_time, res_param from adm_ems_obj_ability_call_log
+    </sql>
+
+    <select id="selectObjAbilityCallLogById" parameterType="java.lang.Long" resultMap="objAbilityCallLogResult">
+        <include refid="selectDetail"/>
+        where id = #{id}
+    </select>
+
+    <select id="selectObjAbilityCallLog" parameterType="com.ruoyi.ems.domain.EmsObjAbilityCallLog" resultMap="objAbilityCallLogResult">
+        <include refid="selectList"/>
+        <where>  
+            <if test="objCode != null  and objCode != ''"> and obj_code = #{objCode}</if>
+            <if test="objType != null "> and obj_type = #{objType}</if>
+            <if test="modelCode != null  and modelCode != ''"> and model_code = #{modelCode}</if>
+            <if test="abilityKey != null  and abilityKey != ''"> and ability_key = #{abilityKey}</if>
+            <if test="callStatus != null "> and call_status = #{callStatus}</if>
+            <if test="startRecTime != null  and startRecTime != '' and endRecTime != null and endRecTime !=''">
+                and call_time between #{startRecTime} and #{endRecTime}
+            </if>
+        </where>
+    </select>
+
+    <insert id="insertObjAbilityCallLog" parameterType="com.ruoyi.ems.domain.EmsObjAbilityCallLog" useGeneratedKeys="true" keyProperty="id">
+        insert into adm_ems_obj_ability_call_log
+        <trim prefix="(" suffix=")" suffixOverrides=",">
+            <if test="objCode != null and objCode != ''">obj_code,</if>
+            <if test="objType != null">obj_type,</if>
+            <if test="modelCode != null and modelCode != ''">model_code,</if>
+            <if test="abilityKey != null and abilityKey != ''">ability_key,</if>
+            <if test="callTime != null">call_time,</if>
+            <if test="callParam != null">call_param,</if>
+            <if test="callStatus != null">call_status,</if>
+            <if test="resTime != null">res_time,</if>
+            <if test="resParam != null">res_param,</if>
+         </trim>
+        <trim prefix="values (" suffix=")" suffixOverrides=",">
+            <if test="objCode != null and objCode != ''">#{objCode},</if>
+            <if test="objType != null">#{objType},</if>
+            <if test="modelCode != null and modelCode != ''">#{modelCode},</if>
+            <if test="abilityKey != null and abilityKey != ''">#{abilityKey},</if>
+            <if test="callTime != null">#{callTime},</if>
+            <if test="callParam != null">#{callParam},</if>
+            <if test="callStatus != null">#{callStatus},</if>
+            <if test="resTime != null">#{resTime},</if>
+            <if test="resParam != null">#{resParam},</if>
+         </trim>
+    </insert>
+
+    <update id="updateObjAbilityCallLog" parameterType="EmsObjAbilityCallLog">
+        update adm_ems_obj_ability_call_log
+        <trim prefix="SET" suffixOverrides=",">
+            <if test="objCode != null and objCode != ''">obj_code = #{objCode},</if>
+            <if test="objType != null">obj_type = #{objType},</if>
+            <if test="modelCode != null and modelCode != ''">model_code = #{modelCode},</if>
+            <if test="abilityKey != null and abilityKey != ''">ability_key = #{abilityKey},</if>
+            <if test="callTime != null">call_time = #{callTime},</if>
+            <if test="callParam != null">call_param = #{callParam},</if>
+            <if test="callStatus != null">call_status = #{callStatus},</if>
+            <if test="resTime != null">res_time = #{resTime},</if>
+            <if test="resParam != null">res_param = #{resParam},</if>
+        </trim>
+        where id = #{id}
+    </update>
+</mapper>

+ 8 - 3
ems/ems-core/src/main/resources/mapper/ems/EmsObjAbilityMapper.xml

@@ -11,10 +11,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="abilityName"    column="ability_name"    />
         <result property="abilityDesc"    column="ability_desc"    />
         <result property="abilityParam"    column="ability_param"    />
+        <result property="hiddenFlag"    column="hidden_flag"    />
     </resultMap>
 
     <sql id="selectObjAbilityVo">
-        select id, model_code, ability_key, ability_name, ability_desc, ability_param from adm_ems_obj_ability
+        select id, model_code, ability_key, ability_name, ability_desc, ability_param, hidden_flag from adm_ems_obj_ability
     </sql>
 
     <select id="selectObjAbilityList" parameterType="com.ruoyi.ems.domain.EmsObjAbility" resultMap="ObjAbilityResult">
@@ -22,6 +23,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <where>  
             <if test="modelCode != null  and modelCode != ''"> and model_code = #{modelCode}</if>
             <if test="abilityKey != null  and abilityKey != ''"> and ability_key = #{abilityKey}</if>
+            <if test="hiddenFlag != null  and hiddenFlag != ''"> and hidden_flag = #{hiddenFlag}</if>
             <if test="abilityName != null  and abilityName != ''"> and ability_name like concat('%', #{abilityName}, '%')</if>
         </where>
     </select>
@@ -44,6 +46,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="abilityName != null and abilityName != ''">ability_name,</if>
             <if test="abilityDesc != null">ability_desc,</if>
             <if test="abilityParam != null">ability_param,</if>
+            <if test="hiddenFlag != null">hidden_flag,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="modelCode != null and modelCode != ''">#{modelCode},</if>
@@ -51,14 +54,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="abilityName != null and abilityName != ''">#{abilityName},</if>
             <if test="abilityDesc != null">#{abilityDesc},</if>
             <if test="abilityParam != null">#{abilityParam},</if>
+            <if test="hiddenFlag != null">#{hiddenFlag},</if>
          </trim>
     </insert>
 
     <insert id="insertBatch" parameterType="java.util.List">
-        insert into adm_ems_obj_ability (model_code, ability_key, ability_name, ability_desc, ability_param)
+        insert into adm_ems_obj_ability (model_code, ability_key, ability_name, ability_desc, ability_param, hidden_flag)
         values
         <foreach collection="list" item="item" index="index" separator=",">
-            (#{item.modelCode}, #{item.abilityKey}, #{item.abilityName}, #{item.abilityDesc}, #{item.abilityParam})
+            (#{item.modelCode}, #{item.abilityKey}, #{item.abilityName}, #{item.abilityDesc}, #{item.abilityParam}, #{item.hiddenFlag})
         </foreach>
     </insert>
 
@@ -70,6 +74,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="abilityName != null and abilityName != ''">ability_name = #{abilityName},</if>
             <if test="abilityDesc != null">ability_desc = #{abilityDesc},</if>
             <if test="abilityParam != null">ability_param = #{abilityParam},</if>
+            <if test="hiddenFlag != null">hidden_flag = #{hiddenFlag},</if>
         </trim>
         where id = #{id}
     </update>

+ 9 - 24
ems/ems-core/src/main/resources/mapper/ems/EmsObjAttrValueMapper.xml

@@ -9,13 +9,13 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="objCode"    column="obj_code"    />
         <result property="objType"    column="obj_type"    />
         <result property="attrKey"    column="attr_key"    />
-        <result property="attrName"    column="attr_name"    />
         <result property="attrValue"    column="attr_value"    />
         <result property="modelCode"    column="model_code"    />
+        <result property="updateTime"    column="update_time"    />
     </resultMap>
 
     <sql id="selectObjAttrValueVo">
-        select id, obj_code, obj_type, attr_key, attr_name, attr_value, model_code from adm_ems_obj_attr_value
+        select id, obj_code, obj_type, attr_key, attr_value, model_code, update_time from adm_ems_obj_attr_value
     </sql>
 
     <select id="selectObjAttrValueList" parameterType="com.ruoyi.ems.domain.EmsObjAttrValue" resultMap="objAttrValueResult">
@@ -38,47 +38,32 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         where id = #{id}
     </select>
         
-    <insert id="insertObjAttrValue" parameterType="com.ruoyi.ems.domain.EmsObjAttrValue" useGeneratedKeys="true" keyProperty="id">
-        insert into adm_ems_obj_attr_value
+    <update id="replaceObjAttrValue" parameterType="com.ruoyi.ems.domain.EmsObjAttrValue">
+        replace into adm_ems_obj_attr_value
         <trim prefix="(" suffix=")" suffixOverrides=",">
             <if test="objCode != null and objCode != ''">obj_code,</if>
             <if test="objType != null">obj_type,</if>
+            <if test="modelCode != null">model_code,</if>
             <if test="attrKey != null and attrKey != ''">attr_key,</if>
-            <if test="attrName != null and attrName != ''">attr_name,</if>
             <if test="attrValue != null">attr_value,</if>
-            <if test="modelCode != null">model_code,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="objCode != null and objCode != ''">#{objCode},</if>
             <if test="objType != null">#{objType},</if>
+            <if test="modelCode != null">#{modelCode},</if>
             <if test="attrKey != null and attrKey != ''">#{attrKey},</if>
-            <if test="attrName != null and attrName != ''">#{attrName},</if>
             <if test="attrValue != null">#{attrValue},</if>
-            <if test="modelCode != null">#{modelCode},</if>
          </trim>
-    </insert>
+    </update>
 
     <insert id="insertBatch" parameterType="java.util.List" >
-        insert into adm_ems_obj_attr_value (obj_code, obj_type, attr_key, attr_name, attr_value, model_code)
+        insert into adm_ems_obj_attr_value (obj_code, obj_type, model_code, attr_key, attr_value)
         values
         <foreach collection="list" item="item" index="index" separator=",">
-            (#{item.objCode}, #{item.objType}, #{item.attrKey}, #{item.attrName}, #{item.attrValue}, #{item.modelCode})
+            (#{item.objCode}, #{item.objType},  #{item.modelCode}, #{item.attrKey}, #{item.attrValue})
         </foreach>
     </insert>
 
-    <update id="updateObjAttrValue" parameterType="com.ruoyi.ems.domain.EmsObjAttrValue">
-        update adm_ems_obj_attr_value
-        <trim prefix="SET" suffixOverrides=",">
-            <if test="objCode != null and objCode != ''">obj_code = #{objCode},</if>
-            <if test="objType != null">obj_type = #{objType},</if>
-            <if test="attrKey != null and attrKey != ''">attr_key = #{attrKey},</if>
-            <if test="attrName != null and attrName != ''">attr_name = #{attrName},</if>
-            <if test="attrValue != null">attr_value = #{attrValue},</if>
-            <if test="modelCode != null">model_code = #{modelCode},</if>
-        </trim>
-        where id = #{id}
-    </update>
-
     <delete id="deleteObjAttrValueById" parameterType="Long">
         delete from adm_ems_obj_attr_value where id = #{id}
     </delete>

+ 9 - 1
ems/ems-core/src/main/resources/mapper/ems/EmsObjModelMapper.xml

@@ -9,10 +9,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="modelCode"    column="model_code"    />
         <result property="modelName"    column="model_name"    />
         <result property="objType"    column="obj_type"    />
+        <result property="abilityHandler"    column="ability_handler"    />
+        <result property="eventHandler"    column="event_handler"    />
     </resultMap>
 
     <sql id="selectObjModelVo">
-        select id, model_code, model_name, obj_type from adm_ems_obj_model
+        select id, model_code, model_name, obj_type, ability_handler, event_handler from adm_ems_obj_model
     </sql>
 
     <select id="selectObjModelList" parameterType="com.ruoyi.ems.domain.EmsObjModel" resultMap="objModelResult">
@@ -40,11 +42,15 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="modelCode != null and modelCode != ''">model_code,</if>
             <if test="modelName != null and modelName != ''">model_name,</if>
             <if test="objType != null">obj_type,</if>
+            <if test="abilityHandler != null and abilityHandler !=''">ability_handler,</if>
+            <if test="eventHandler != null and eventHandler !=''">event_handler,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
             <if test="modelCode != null and modelCode != ''">#{modelCode},</if>
             <if test="modelName != null and modelName != ''">#{modelName},</if>
             <if test="objType != null">#{objType},</if>
+            <if test="abilityHandler != null and abilityHandler !=''">#{abilityHandler},</if>
+            <if test="eventHandler != null and eventHandler !=''">#{eventHandler},</if>
          </trim>
     </insert>
 
@@ -54,6 +60,8 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="modelCode != null and modelCode != ''">model_code = #{modelCode},</if>
             <if test="modelName != null and modelName != ''">model_name = #{modelName},</if>
             <if test="objType != null">obj_type = #{objType},</if>
+            <if test="abilityHandler != null and abilityHandler !=''">ability_handler = #{abilityHandler},</if>
+            <if test="eventHandler != null and eventHandler !=''">event_handler = #{eventHandler},</if>
         </trim>
         where id = #{id}
     </update>

+ 12 - 13
ems/sql/ems_init_data.sql

@@ -267,19 +267,18 @@ INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES
 INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_type`, `attr_key`, `attr_name`, `attr_unit`) VALUES ('M_Z010', 0, 'power',   '功率', 'kW-h');
 
 -- 对象属性DEMO数据
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-B-1001-QR_00', 3, 'onOffState', '开关状态', 'on', 'M_W2_QR');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-B-1001-QF_01', 3, 'onOffState', '开关状态', 'off', 'M_W2_QF');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-B-1001-QF_02', 3, 'onOffState', '开关状态', 'on', 'M_W2_QF');
-
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-B-T-1001', 2, 'ratedCapacity', '额定容量', '1000', 'M_W2_T');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-B-T-1001', 2, 'ratedVoltage', '额定电压', '10', 'M_W2_T');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-B-T-1001', 2, 'ratedFrequency', '额定频率', '50', 'M_W2_T');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-B-T-1001', 2, 'phaseNumber', '相数', '3', 'M_W2_T');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-N-T-1002', 2, 'ratedCapacity', '额定容量', '1000', 'M_W2_T');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-N-T-1002', 2, 'ratedVoltage', '额定电压', '10', 'M_W2_T');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-N-T-1002', 2, 'ratedFrequency', '额定频率', '50', 'M_W2_T');
-INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `attr_key`, `attr_name`, `attr_value`, `model_code`) VALUES ('D-N-T-1002', 2, 'phaseNumber', '3', '相数', 'M_W2_T');
-
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-B-1001-QR_00', 3, 'M_W2_QR', 'onOffState', 'on');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-B-1001-QF_01', 3, 'M_W2_QF', 'onOffState', 'off');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-B-1001-QF_02', 3, 'M_W2_QF', 'onOffState', 'on');
+
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-B-T-1001', 2, 'M_W2_T', 'ratedCapacity', '1000');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-B-T-1001', 2, 'M_W2_T', 'ratedVoltage', '10');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-B-T-1001', 2, 'M_W2_T', 'ratedFrequency', '50');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-B-T-1001', 2, 'M_W2_T', 'phaseNumber', '3');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-N-T-1002', 2, 'M_W2_T', 'ratedCapacity', '1000');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-N-T-1002', 2, 'M_W2_T', 'ratedVoltage', '10');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-N-T-1002', 2, 'M_W2_T', 'ratedFrequency', '50');
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `obj_type`, `model_code`, `attr_key`, `attr_value`) VALUES ('D-N-T-1002', 2, 'M_W2_T', 'phaseNumber', '3');
 
 -- 对象能力DEMO数据
 INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `ability_param`) VALUES ('M_W2', 'checkLine', '线路检测', '执行xx方法进行测试', '{\"enable\":\"1\"}');

+ 33 - 10
ems/sql/ems_server.sql

@@ -547,19 +547,21 @@ create table adm_ems_obj_model  (
   `model_code`      varchar(64)     not null                     comment '模型code',
   `model_name`      varchar(128)    not null                     comment '模型名称',
   `obj_type`        int             not null                     comment '对象类型',
+  `ability_handler` varchar(2048)   default null                 comment '能力处理handler',
+  `event_handler`   varchar(2048)   default null                 comment '事件处理handler',
   primary key (`id`),
   unique key ux_ems_obj_attr(`model_code`)
 ) engine=innodb auto_increment=1 comment = '能源对象模型表';
 
 
 -- 对象模型初始数据
-INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES ('M_W2', '国网供电模型', 1);
-INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES ('M_E5', '光伏设施模型', 1);
-INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES ('M_C1', '储能模型', 1);
-INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES ('M_W2_T', '变压器设备模型', 2);
-INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES ('M_W2_AP', '配电柜模型', 2);
-INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES ('M_W2_QR', '漏电保护器模型', 2);
-INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`) VALUES ('M_W2_QF', '断路器模型', 2);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `ability_handler`) VALUES ('M_W2', '国网供电模型', 1, null, null);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `ability_handler`) VALUES ('M_E5', '光伏设施模型', 1, null, null);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `ability_handler`) VALUES ('M_C1', '储能模型', 1, null, null);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `ability_handler`) VALUES ('M_W2_T', '变压器设备模型', 2, null, null);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `ability_handler`) VALUES ('M_W2_AP', '配电柜模型', 2, null, null);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `ability_handler`) VALUES ('M_W2_QR', '漏电保护器模型', 2, null, null);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `ability_handler`) VALUES ('M_W2_QF', '断路器模型', 2, null, null);
 
 
 -- ----------------------------
@@ -623,12 +625,12 @@ create table adm_ems_obj_attr_value  (
   `id`              bigint(20)      not null auto_increment      comment '序号',
   `obj_code`        varchar(64)     not null                     comment '对象代码',
   `obj_type`        int             not null                     comment '对象类型',
+  `model_code`      varchar(64)     not null                     comment '模型code',
   `attr_key`        varchar(128)    not null                     comment '属性标识',
-  `attr_name`       varchar(256)    default null                 comment '属性名称',
   `attr_value`      varchar(32)     default null                 comment '属性值',
-  `model_code`      varchar(64)     default null                 comment '模型code',
+  `update_time`     datetime        default CURRENT_TIMESTAMP    ON UPDATE CURRENT_TIMESTAMP comment '更新时间',
   primary key (`id`),
-  unique key ux_ems_obj_attr_value(`obj_code`, `obj_type`, `attr_key`)
+  unique key ux_ems_obj_attr_value(`obj_code`, `obj_type`, `model_code`, `attr_key`)
 ) engine=innodb auto_increment=1 comment = '能源对象属性值表';
 
 
@@ -643,12 +645,33 @@ create table adm_ems_obj_ability  (
   `ability_name`    varchar(256)    default null                 comment '能力名称',
   `ability_desc`    varchar(1024)   default null                 comment '能力描述',
   `ability_param`   varchar(2048)   default null                 comment '能力参数',
+  `hidden_flag`     int             default 0                    comment '隐藏标记',
   primary key (`id`),
   unique key ux_ems_obj_ability(`model_code`, `ability_key`)
 ) engine=innodb auto_increment=1 comment = '能源对象能力表';
 
 
 -- ----------------------------
+-- 能源对象能力调用日志表
+-- ----------------------------
+drop table if exists adm_ems_obj_ability_call_log;
+create table adm_ems_obj_ability_call_log  (
+  `id`              bigint(20)      not null auto_increment      comment '序号',
+  `obj_code`        varchar(64)     not null                     comment '对象代码',
+  `obj_type`        int             not null                     comment '对象类型',
+  `model_code`      varchar(64)     not null                     comment '模型code',
+  `ability_key`     varchar(128)    not null                     comment '能力键',
+  `call_time`       datetime        not null                     comment '调用时间',
+  `call_param`      text            default null                 comment '调用参数',
+  `call_status`     int             not null                     comment '调用状态',
+  `res_time`        datetime        default null                 comment '响应时间',
+  `res_param`       text            default null                 comment '响应内容',
+  primary key (`id`),
+  key i_ability_call_log(`obj_code`, `obj_type`, `ability_key`, `call_time`)
+) engine=innodb auto_increment=1 comment = '能源对象能力调用日志表';
+
+
+-- ----------------------------
 -- 能源设施事件表
 -- ----------------------------
 drop table if exists adm_ems_obj_event;

+ 35 - 0
prod-common/src/main/java/com/huashe/common/utils/ThreadUtils.java

@@ -0,0 +1,35 @@
+/*
+ * 文 件 名:  ThreadUtils
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/2/27
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.huashe.common.utils;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 线程工具
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/2/27]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public abstract class ThreadUtils {
+    private static final Logger logger = LoggerFactory.getLogger(ThreadUtils.class);
+
+    public static void sleep(long millis) {
+        try {
+            Thread.sleep(millis);
+        } catch (InterruptedException e) {
+            logger.error("Thread sleep fail!", e);
+        }
+    }
+}