Przeglądaj źródła

智慧照明对接

learshaw 2 dni temu
rodzic
commit
918336b00b
40 zmienionych plików z 1924 dodań i 468 usunięć
  1. 7 1
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/TaskExecutor.java
  2. 0 5
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/SquareLightCtlConfig.java
  3. 78 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/controller/SquareLightCtlController.java
  4. 1 1
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/InDoorEnergyTemplate.java
  5. 171 42
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/SquareLightCtlTemplate.java
  6. 0 1
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/BaseMeterDevHandler.java
  7. 44 42
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/InDoorEnergyHandler.java
  8. 701 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/SquareLightCtlHandler.java
  9. 123 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/CallData.java
  10. 32 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/BaselineInfo.java
  11. 40 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/CcElecInfo.java
  12. 31 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/DeviceInfo.java
  13. 45 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/LightControlReq.java
  14. 5 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/SlcDevice.java
  15. 48 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/SlcDeviceLamp.java
  16. 38 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/StatusInfo.java
  17. 36 0
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/SyncStatusReq.java
  18. 55 11
      ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/retrofit/SquareLightCtlApi.java
  19. 0 1
      ems/ems-cloud/ems-dev-adapter/src/main/resources/application-local.yml
  20. 0 1
      ems/ems-cloud/ems-dev-adapter/src/main/resources/application-prod-ct.yml
  21. 56 11
      ems/ems-cloud/ems-dev-adapter/src/test/java/com/huashe/test/SquareLightCtlTest.java
  22. 84 12
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAttrController.java
  23. 2 0
      ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAttrValueController.java
  24. 0 14
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsDevice.java
  25. 8 9
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAbility.java
  26. 4 64
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAttrDto.java
  27. 1 1
      ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjEventLog.java
  28. 16 0
      ems/ems-core/src/main/java/com/ruoyi/ems/mapper/EmsDeviceMapper.java
  29. 0 104
      ems/ems-core/src/main/java/com/ruoyi/ems/service/EmsCommonCache.java
  30. 15 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsDeviceService.java
  31. 5 11
      ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsObjAttrService.java
  32. 15 0
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsDeviceServiceImpl.java
  33. 2 56
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAttrServiceImpl.java
  34. 0 2
      ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAttrValueServiceImpl.java
  35. 12 3
      ems/ems-core/src/main/resources/mapper/ems/EmsDeviceMapper.xml
  36. 7 7
      ems/ems-core/src/main/resources/mapper/ems/EmsObjAbilityMapper.xml
  37. 7 3
      ems/ems-core/src/main/resources/mapper/ems/EmsObjAttrMapper.xml
  38. 92 41
      ems/sql/ems_init_data.sql
  39. 9 25
      ems/sql/ems_server.sql
  40. 134 0
      prod-common/src/main/java/com/huashe/common/domain/JsonEntity.java

+ 7 - 1
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/TaskExecutor.java

@@ -13,6 +13,7 @@ package com.ruoyi.ems;
 import com.ruoyi.ems.core.ObjectCache;
 import com.ruoyi.ems.handle.GeekOpenCbHandler;
 import com.ruoyi.ems.handle.InDoorEnergyHandler;
+import com.ruoyi.ems.handle.SquareLightCtlHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -49,6 +50,10 @@ public class TaskExecutor {
     @Resource
     private InDoorEnergyHandler inDoorEnergyHandler;
 
+    @Qualifier("squareLightCtlHandler")
+    @Resource
+    private SquareLightCtlHandler squareLightCtlHandler;
+
     /**
      * 定时清理过期设备上报响应
      */
@@ -61,9 +66,10 @@ public class TaskExecutor {
     /**
      * 定时刷新设备在线状态
      */
-    @Scheduled(cron = "0 0/1 * * * ?")
+    @Scheduled(cron = "0 0/5 * * * ?")
     public void refreshOnline() {
         inDoorEnergyHandler.refreshOnline();
+        squareLightCtlHandler.refreshOnline();
     }
 
 //    /**

+ 0 - 5
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/config/SquareLightCtlConfig.java

@@ -38,11 +38,6 @@ public class SquareLightCtlConfig {
     private String clientId;
 
     /**
-     * 项目ID
-     */
-    private String projectId;
-
-    /**
      * 用户名
      */
     private String userName;

+ 78 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/controller/SquareLightCtlController.java

@@ -0,0 +1,78 @@
+/*
+ * 文 件 名:  SquareLightCtlController
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/19
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.controller;
+
+import com.ruoyi.ems.handle.InDoorEnergyHandler;
+import com.ruoyi.ems.handle.SquareLightCtlHandler;
+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;
+
+/**
+ * 广场灯控控制接口
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/19]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@RestController
+@CrossOrigin(allowedHeaders = "*", allowCredentials = "false")
+@RequestMapping("/square-light-ctl")
+@Api(value = "SquareLightCtlController", description = "广场灯控Api")
+public class SquareLightCtlController {
+    /**
+     * 日志
+     */
+    private static final Logger log = LoggerFactory.getLogger(InDoorEnergyController.class);
+
+    @Qualifier("squareLightCtlHandler")
+    @Resource
+    private SquareLightCtlHandler squareLightCtlHandler;
+
+    /**
+     * 常泰室内能耗能力调用
+     *
+     * @return 数据列表
+     */
+    @RequestMapping(value = "/ct/abilityCall", method = RequestMethod.POST)
+    @ApiOperation(value = "/ct/abilityCall", notes = "常泰室内能耗能力调用")
+    @ApiResponses({ @ApiResponse(code = 200, message = "success"),
+        @ApiResponse(code = 400, message = "{code:****,message:'fail'}")
+    })
+    public CallResponse<Void> ctSlAbilityCall(@RequestBody AbilityPayload abilityPayload) {
+        CallResponse<Void> res = null;
+
+        try {
+            res = squareLightCtlHandler.call(abilityPayload);
+        }
+        catch (Exception e) {
+            log.error("ctSlAbilityCall fail!", e);
+            res = new CallResponse<>(501, "内部错误:" + e.getMessage());
+        }
+
+        return res;
+    }
+}

+ 1 - 1
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/InDoorEnergyTemplate.java

@@ -89,7 +89,7 @@ public class InDoorEnergyTemplate extends BaseApiTemplate {
         return accessToken;
     }
 
-    public synchronized String getNewToken() {
+    public String getNewToken() {
         RedisService redisService = SpringUtils.getBean(RedisService.class);
 
         InDoorEnergyConfig config = SpringUtils.getBean(InDoorEnergyConfig.class);

+ 171 - 42
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/core/SquareLightCtlTemplate.java

@@ -12,12 +12,15 @@ package com.ruoyi.ems.core;
 
 import com.alibaba.fastjson.support.retrofit.Retrofit2ConverterFactory;
 import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONObject;
+import com.huashe.common.domain.JsonEntity;
 import com.huashe.common.exception.Assert;
 import com.ruoyi.common.core.utils.SpringUtils;
-import com.ruoyi.common.redis.service.RedisService;
 import com.ruoyi.ems.config.SquareLightCtlConfig;
+import com.ruoyi.ems.model.CallData;
 import com.ruoyi.ems.model.slightctl.AppLoginReq;
 import com.ruoyi.ems.model.slightctl.AppLoginRes;
+import com.ruoyi.ems.model.slightctl.DeviceInfo;
 import com.ruoyi.ems.model.slightctl.SlcDevice;
 import com.ruoyi.ems.model.slightctl.SlcProject;
 import com.ruoyi.ems.model.slightctl.SlcProjectSubset;
@@ -25,16 +28,12 @@ import com.ruoyi.ems.model.slightctl.SlcResponse;
 import com.ruoyi.ems.retrofit.SquareLightCtlApi;
 import lombok.extern.slf4j.Slf4j;
 import okhttp3.OkHttpClient;
-import org.apache.commons.lang3.StringUtils;
 import retrofit2.Call;
 import retrofit2.Response;
 import retrofit2.Retrofit;
 
-import java.math.BigDecimal;
-import java.math.BigInteger;
 import java.util.ArrayList;
 import java.util.List;
-import java.util.concurrent.TimeUnit;
 
 /**
  * 广场灯控接口模板
@@ -122,87 +121,89 @@ public class SquareLightCtlTemplate extends BaseApiTemplate {
     }
 
     public synchronized String getToken() {
-        RedisService redisService = SpringUtils.getBean(RedisService.class);
-        String accessToken = redisService.getCacheObject("SQUARE_LIGHT_CTL_TOKEN");
-
-        if (StringUtils.isEmpty(accessToken)) {
-            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
-            AppLoginRes res = appLogin(config);
-            redisService.setCacheObject("SQUARE_LIGHT_CTL_TOKEN", res.getAccessToken(), 5 * 60L, TimeUnit.SECONDS);
-            accessToken = res.getAccessToken();
-        }
-
-        return accessToken;
+        SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
+        AppLoginRes res = appLogin(config);
+        return res.accessToken;
     }
 
     /**
      * 获取项目列表
      *
-     * @param pageNum  页码
-     * @param pageSize 每页记录数
      * @return 登录响应
      */
-    public List<SlcProject> getProjectList(int pageNum, int pageSize) {
-        List<SlcProject> list = null;
+    public CallData<SlcProject> getProjectList() {
+        CallData<SlcProject> ret = null;
+        String token = null;
+        String resBody = null;
 
         try {
             SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
+            token = getToken();
 
-            String token = getToken();
             Assert.notEmpty(token, -1, "获取Token失败");
             token = "Bearer " + token;
 
             // 执行调用
-            Call<String> call = api.getProjectList(config.getClientId(), token, pageNum, pageSize);
+            Call<String> call = api.getProjectList(config.getClientId(), token);
             Response<String> response = call.execute();
-            String resBody = response.body();
+            resBody = response.body();
+
             log.debug("getProjectList response:{}", resBody);
             Assert.notEmpty(resBody, -1, "获取项目列表失败");
             SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
             Assert.notNull(slcRes, -1, "解析项目列表响应失败.");
-            Assert.isTrue(200 == slcRes.getCode(), -1, "登录失败:" + slcRes.getMsg());
-            list = JSON.parseArray(slcRes.getData(), SlcProject.class);
+            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
+            ret = CallData.<SlcProject>builder().addCallParam("ClientId", config.getClientId())
+                .addCallParam("token", token).setCallStatus(0).setResPayload(resBody)
+                .setList(JSON.parseArray(slcRes.getData(), SlcProject.class)).build();
         }
         catch (Exception e) {
             log.error("getProjectList fail!", e);
+            ret = CallData.<SlcProject>builder().addCallParam("token", token).setCallStatus(2).setResPayload(resBody)
+                .build();
         }
 
-        return list;
+        return ret;
     }
 
     /**
      * 获取项目分组列表
      *
-     * @param pageNum  页码
-     * @param pageSize 每页记录数
      * @return 登录响应
      */
-    public List<SlcProjectSubset> getProjectSubsetList(String projectId, int pageNum, int pageSize) {
-        List<SlcProjectSubset> list = null;
+    public CallData<SlcProjectSubset> getProjectSubsetList(String projectId) {
+        CallData<SlcProjectSubset> ret = null;
+        String token = null;
+        String resBody = null;
 
         try {
             SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
 
-            String token = getToken();
+            token = getToken();
             Assert.notEmpty(token, -1, "获取Token失败");
             token = "Bearer " + token;
 
-            // 执行调用
-            Call<String> call = api.getProjectSubsetList(config.getClientId(), token, projectId, pageNum, pageSize);
+            Call<String> call = api.getProjectSubsetList(config.getClientId(), token, projectId);
             Response<String> response = call.execute();
-            String resBody = response.body();
+            resBody = response.body();
             log.debug("getProjectSubsetList response:{}", resBody);
             Assert.notEmpty(resBody, -1, "获取项目分组列表失败");
             SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
             Assert.notNull(slcRes, -1, "解析项目分组列表响应失败.");
-            Assert.isTrue(200 == slcRes.getCode(), -1, "登录失败:" + slcRes.getMsg());
-            list = JSON.parseArray(slcRes.getData(), SlcProjectSubset.class);
+            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
+
+            ret = CallData.<SlcProjectSubset>builder().addCallParam("ClientId", config.getClientId())
+                .addCallParam("token", token).addCallParam("projectId", projectId).setCallStatus(0)
+                .setResPayload(resBody).setList(JSON.parseArray(slcRes.getData(), SlcProjectSubset.class)).build();
+
         }
         catch (Exception e) {
             log.error("getProjectSubsetList fail!", e);
+            ret = CallData.<SlcProjectSubset>builder().addCallParam("token", token).addCallParam("projectId", projectId)
+                .setCallStatus(2).setResPayload(resBody).build();
         }
 
-        return list;
+        return ret;
     }
 
     /**
@@ -210,8 +211,8 @@ public class SquareLightCtlTemplate extends BaseApiTemplate {
      *
      * @return 登录响应
      */
-    public List<SlcDevice> getDeviceList(String projectId) {
-        List<SlcDevice> list = new ArrayList<>();
+    public CallData<SlcDevice> getDeviceList(String projectId, String subsetId) {
+        CallData.Builder<SlcDevice> builder = CallData.builder();
 
         try {
             SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
@@ -224,26 +225,154 @@ public class SquareLightCtlTemplate extends BaseApiTemplate {
             int pageSize = 50;
             int total = 0;
 
+            List<SlcDevice> list = new ArrayList<>();
+            builder.addCallParam("projectId", projectId).addCallParam("token", token);
+
             do {
                 // 执行调用
-                Call<String> call = api.getDeviceList(config.getClientId(), projectId, token, pageNum, pageSize);
+                Call<String> call = api.getDeviceList(config.getClientId(), token, projectId, subsetId, pageNum,
+                    pageSize);
+
                 Response<String> response = call.execute();
                 String resBody = response.body();
                 log.debug("getDeviceList response:{}", resBody);
+                builder.appendResPayload(String.format("response(pageNum-%d): %s", pageNum, System.lineSeparator()))
+                    .appendResPayload(resBody).appendResPayload(System.lineSeparator());
                 Assert.notEmpty(resBody, -1, "获取设备列表失败");
                 SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
                 Assert.notNull(slcRes, -1, "解析设备列表响应失败.");
-                Assert.isTrue(200 == slcRes.getCode(), -1, "登录失败:" + slcRes.getMsg());
+                Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
                 total = slcRes.getTotal();
                 list.addAll(JSON.parseArray(slcRes.getRows(), SlcDevice.class));
                 pageNum++;
             }
             while (list.size() < total);
+
+            builder.setList(list).setCallStatus(0);
         }
         catch (Exception e) {
+            builder.setCallStatus(2);
             log.error("getDeviceList fail!", e);
         }
 
-        return list;
+        return builder.build();
+    }
+
+    /**
+     * 获取设备
+     *
+     * @return 登录响应
+     */
+    public CallData<DeviceInfo> getDeviceInfo(String projectId, String deviceId) {
+        CallData.Builder<DeviceInfo> builder = CallData.builder();
+
+        try {
+            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
+
+            String token = getToken();
+            Assert.notEmpty(token, -1, "获取Token失败");
+            token = "Bearer " + token;
+
+            JsonEntity<JSONObject> syncBody = JsonEntity.objBuilder().addKeyArray("idList", deviceId).build();
+
+            // 执行调用
+            builder.addCallParam("syncStatus req", syncBody.getJsonObj().toString());
+            Call<String> call = api.syncStatus(config.getClientId(), projectId, token, syncBody.getJsonObj());
+            Response<String> response = call.execute();
+            String resBody = response.body();
+            log.debug("syncStatus response:{}", resBody);
+            builder.appendResPayload(String.format("syncStatus response: %s%s", resBody, System.lineSeparator()));
+            Assert.notNull(resBody, -1, "同步状态响应失败.");
+
+            builder.addCallParam("projectId", projectId);
+            call = api.getDeviceInfo(config.getClientId(), projectId, token, deviceId);
+            response = call.execute();
+            resBody = response.body();
+            log.debug("getDeviceInfo response:{}", resBody);
+            builder.appendResPayload(String.format("getDeviceInfo response: %s%s", resBody, System.lineSeparator()));
+            Assert.notEmpty(resBody, -1, "获取同步状态响应失败");
+            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
+            Assert.notNull(slcRes, -1, "解析同步状态响应失败.");
+            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
+            String data = slcRes.getData();
+            DeviceInfo deviceInfo = JSON.parseObject(data, DeviceInfo.class);
+            builder.setData(deviceInfo).setCallStatus(0);
+        }
+        catch (Exception e) {
+            builder.setCallStatus(2);
+            log.error("getDeviceInfo fail!", e);
+        }
+
+        return builder.build();
+    }
+
+    /**
+     * 照明控制
+     *
+     * @return 登录响应
+     */
+    public CallData<Void> lightControl(String projectId, JSONObject req) {
+        CallData.Builder<Void> builder = CallData.builder();
+
+        try {
+            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
+
+            String token = getToken();
+            Assert.notEmpty(token, -1, "获取Token失败");
+            token = "Bearer " + token;
+
+            // 执行调用
+            builder.addCallParam("token", token).addCallParam("body", req.toString())
+                .addCallParam("projectId", projectId);
+            Call<String> call = api.lightControl(config.getClientId(), projectId, token, req);
+            Response<String> response = call.execute();
+            String resBody = response.body();
+            log.debug("lightControl response:{}", resBody);
+            builder.setResPayload(resBody).setCallStatus(0);
+            Assert.notEmpty(resBody, -1, "获取灯控响应失败");
+            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
+            Assert.notNull(slcRes, -1, "解析灯控响应失败.");
+            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
+        }
+        catch (Exception e) {
+            builder.setCallStatus(2);
+            log.error("lightControl fail!", e);
+        }
+
+        return builder.build();
+    }
+
+    /**
+     * 亮度调节
+     *
+     * @return 登录响应
+     */
+    public CallData<Void> controlBrightness(String projectId, JSONObject req) {
+        CallData.Builder<Void> builder = CallData.builder();
+
+        try {
+            SquareLightCtlConfig config = SpringUtils.getBean(SquareLightCtlConfig.class);
+
+            String token = getToken();
+            Assert.notEmpty(token, -1, "获取Token失败");
+            token = "Bearer " + token;
+
+            // 执行调用
+            builder.addCallParam("token", token).addCallParam("body", req.toString());
+            Call<String> call = api.controlBrightness(config.getClientId(), projectId, token, req);
+            Response<String> response = call.execute();
+            String resBody = response.body();
+            log.debug("controlBrightness response:{}", resBody);
+            builder.setResPayload(resBody).setCallStatus(0);
+            Assert.notEmpty(resBody, -1, "获取调光响应失败");
+            SlcResponse slcRes = JSON.parseObject(resBody, SlcResponse.class);
+            Assert.notNull(slcRes, -1, "解析调光响应失败.");
+            Assert.isTrue(200 == slcRes.getCode(), -1, slcRes.getMsg());
+        }
+        catch (Exception e) {
+            log.error("controlBrightness fail!", e);
+        }
+
+        return builder.build();
     }
 }

+ 0 - 1
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/BaseMeterDevHandler.java

@@ -52,7 +52,6 @@ public abstract class BaseMeterDevHandler extends BaseDevHandler {
 
     protected static final long MAX_CACHE_AGE_MILLIS = 2 * 60 * 60 * 1000;
 
-    protected static final long MAX_HOUR_INCREASE_RATE = 1000;
 
     /**
      * 获取计量设备列表

+ 44 - 42
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/InDoorEnergyHandler.java

@@ -63,6 +63,9 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
     // 设备模型代码
     private static final String DEV_MODE_CODE = "M_W4_SM_INDOOR_ENERGY";
 
+    // 设备子系统代码
+    private static final String SUBSYSTEM_CODE = "SYS_NHJC";
+
     // 单小时最大增长量(度)
     private static final double MAX_HOUR_INCREASE_RATE = 1000.0;
 
@@ -90,6 +93,13 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
     }
 
     @Override
+    public List<EmsDevice> getDeviceList() {
+        QueryDevice queryDevice = new QueryDevice();
+        queryDevice.setDeviceModel(DEV_MODE_CODE);
+        return deviceService.selectList(queryDevice);
+    }
+
+    @Override
     public CallResponse<Void> call(AbilityPayload abilityParam) {
         CallResponse<Void> callResponse = null;
 
@@ -124,44 +134,6 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
         return callResponse;
     }
 
-    private void meterReadingGw(String modeCode, String abilityKey, String objCode) {
-        // 查询当前设备的接口属性值
-        List<EmsObjAttrValue> attrValues = objAttrValueService.selectByObjCode(modeCode, objCode);
-        attrValues = attrValues.stream()
-            // 过滤条件:attrKey以"interface"开头
-            .filter(attr -> StringUtils.startsWith(attr.getAttrKey(), "interface"))
-            // 收集为新的List
-            .collect(Collectors.toList());
-
-        Set<String> pointIdSet = getPointIds(attrValues);
-        CodesValReq req = new CodesValReq(pointIdSet);
-
-        // 调用能耗数据接口获取实时数据
-        InDoorEnergyTemplate template = new InDoorEnergyTemplate(config.getUrl());
-        String callRes = template.getCodesVal(req);
-        JSONObject resJson = JSONObject.parseObject(callRes);
-
-        if (resJson.getInteger("code") == 200) {
-            saveCallLog(objCode, modeCode, abilityKey, 0, JSON.toJSONString(req), callRes);
-
-            String dataStr = resJson.getString("ResultPointObjArr");
-            List<CodesVal> retList = JSONObject.parseArray(dataStr, CodesVal.class);
-            // 更新设备属性
-            updateDeviceAttrList(attrValues, retList);
-        }
-        else {
-            saveCallLog(objCode, modeCode, abilityKey, 2, JSON.toJSONString(req), callRes);
-            throw new BusinessException(-1, resJson.getString("error"));
-        }
-    }
-
-    @Override
-    public List<EmsDevice> getDeviceList() {
-        QueryDevice queryDevice = new QueryDevice();
-        queryDevice.setDeviceModel(DEV_MODE_CODE);
-        return deviceService.selectList(queryDevice);
-    }
-
     @Override
     public void refreshOnline() {
         try {
@@ -182,11 +154,10 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
             boolean isOnline = PingUtils.pingHost(ipAddress, 3000); // 3秒超时
 
             // 3. 获取当前系统状态
-            String objCode = "SYS_NHJC"; // 能耗监测系统代码
             String statusKey = "interfaceStatus";
 
             // 查询当前状态
-            EmsObjAttrValue currentStatus = objAttrValueService.selectObjAttrValue(SYS_MODE_CODE, objCode, statusKey);
+            EmsObjAttrValue currentStatus = objAttrValueService.selectObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, statusKey);
 
             String newStatus = isOnline ? "1" : "0";
             String oldStatus = currentStatus != null ? currentStatus.getAttrValue() : null;
@@ -196,10 +167,10 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
                 log.info("能耗监测系统连接状态变化: {} -> {}, IP: {}", oldStatus, newStatus, ipAddress);
 
                 // 更新系统属性状态
-                objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, objCode, statusKey, newStatus);
+                objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, statusKey, newStatus);
 
                 String key = isOnline ? "connect" : "disconnect";
-                triggerEvent(SYS_MODE_CODE, objCode, key, null, new Date());
+                triggerEvent(SYS_MODE_CODE, SUBSYSTEM_CODE, key, null, new Date());
             }
 
             // 5. 记录心跳日志(可选,用于调试)
@@ -210,6 +181,37 @@ public class InDoorEnergyHandler extends BaseMeterDevHandler {
         }
     }
 
+    private void meterReadingGw(String modeCode, String abilityKey, String objCode) {
+        // 查询当前设备的接口属性值
+        List<EmsObjAttrValue> attrValues = objAttrValueService.selectByObjCode(modeCode, objCode);
+        attrValues = attrValues.stream()
+            // 过滤条件:attrKey以"interface"开头
+            .filter(attr -> StringUtils.startsWith(attr.getAttrKey(), "interface"))
+            // 收集为新的List
+            .collect(Collectors.toList());
+
+        Set<String> pointIdSet = getPointIds(attrValues);
+        CodesValReq req = new CodesValReq(pointIdSet);
+
+        // 调用能耗数据接口获取实时数据
+        InDoorEnergyTemplate template = new InDoorEnergyTemplate(config.getUrl());
+        String callRes = template.getCodesVal(req);
+        JSONObject resJson = JSONObject.parseObject(callRes);
+
+        if (resJson.getInteger("code") == 200) {
+            saveCallLog(objCode, modeCode, abilityKey, 0, JSON.toJSONString(req), callRes);
+
+            String dataStr = resJson.getString("ResultPointObjArr");
+            List<CodesVal> retList = JSONObject.parseArray(dataStr, CodesVal.class);
+            // 更新设备属性
+            updateDeviceAttrList(attrValues, retList);
+        }
+        else {
+            saveCallLog(objCode, modeCode, abilityKey, 2, JSON.toJSONString(req), callRes);
+            throw new BusinessException(-1, resJson.getString("error"));
+        }
+    }
+
     /**
      * 采集室内能耗计量数据
      *

+ 701 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/handle/SquareLightCtlHandler.java

@@ -0,0 +1,701 @@
+/*
+ * 文 件 名:  SquareLightCtlHandler
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/19
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.handle;
+
+import com.alibaba.fastjson2.JSON;
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+import com.huashe.common.domain.JsonEntity;
+import com.huashe.common.exception.Assert;
+import com.ruoyi.ems.config.SquareLightCtlConfig;
+import com.ruoyi.ems.core.SquareLightCtlTemplate;
+import com.ruoyi.ems.domain.EmsDevice;
+import com.ruoyi.ems.domain.EmsObjAttrValue;
+import com.ruoyi.ems.domain.MeterDevice;
+import com.ruoyi.ems.enums.DevObjType;
+import com.ruoyi.ems.model.AbilityPayload;
+import com.ruoyi.ems.model.CallData;
+import com.ruoyi.ems.model.CallResponse;
+import com.ruoyi.ems.model.QueryDevice;
+import com.ruoyi.ems.model.slightctl.BaselineInfo;
+import com.ruoyi.ems.model.slightctl.CcElecInfo;
+import com.ruoyi.ems.model.slightctl.DeviceInfo;
+import com.ruoyi.ems.model.slightctl.SlcDevice;
+import com.ruoyi.ems.model.slightctl.SlcDeviceLamp;
+import com.ruoyi.ems.model.slightctl.SlcProject;
+import com.ruoyi.ems.model.slightctl.SlcProjectSubset;
+import com.ruoyi.ems.model.slightctl.StatusInfo;
+import com.ruoyi.ems.util.PingUtils;
+import org.apache.commons.collections4.CollectionUtils;
+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;
+
+import java.util.ArrayList;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * 广场灯控
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/19]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Service
+public class SquareLightCtlHandler extends BaseMeterDevHandler {
+    private static final Logger log = LoggerFactory.getLogger(SquareLightCtlHandler.class);
+
+    // 对接系统
+    private static final String SYS_MODE_CODE = "M_Z010_SYS_SQUARE_LIGHT";
+
+    // 灯杆模型代码
+    private static final String LAMP_POST_MODE_CODE = "M_Z010_DEV_SQUARE_LAMP_POST";
+
+    // 照明灯组模型代码
+    private static final String DEV_MODE_CODE = "M_Z010_DEV_SQUARE_LIGHT";
+
+    // 集中器设备代码
+    private static final String CONCENTRATOR_MODE_CODE = "M_Z010_DEV_SQUARE_CONCENTRATOR";
+
+    // 设备子系统代码
+    private static final String SUBSYSTEM_CODE = "SYS_ZHZM";
+
+    @Autowired
+    private SquareLightCtlConfig config;
+
+    @Override
+    public List<MeterDevice> getMeterDeviceList() {
+        throw new UnsupportedOperationException("不支持的调用");
+    }
+
+    @Override
+    public List<EmsDevice> getDeviceList() {
+        QueryDevice queryDevice = new QueryDevice();
+        queryDevice.setDeviceModel(DEV_MODE_CODE);
+        return deviceService.selectList(queryDevice);
+    }
+
+    @Override
+    public void refreshOnline() {
+        try {
+            // 1. 从URL中提取IP地址
+            String url = config.getUrl();
+            if (StringUtils.isBlank(url)) {
+                log.warn("广场灯控系统URL配置为空,跳过心跳检测");
+                return;
+            }
+
+            String ipAddress = PingUtils.extractIpFromUrl(url);
+            if (StringUtils.isBlank(ipAddress)) {
+                log.warn("无法从URL中提取IP地址: {}", url);
+                return;
+            }
+
+            // 2. 执行ping检测
+            boolean isOnline = PingUtils.pingHost(ipAddress, 3000); // 3秒超时
+
+            // 3. 获取当前系统状态
+            String statusKey = "interfaceStatus";
+
+            // 查询当前状态
+            EmsObjAttrValue currentStatus = objAttrValueService.selectObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE,
+                statusKey);
+
+            String newStatus = isOnline ? "1" : "0";
+            String oldStatus = currentStatus != null ? currentStatus.getAttrValue() : null;
+
+            // 4. 状态发生变化时更新并记录
+            if (!StringUtils.equals(oldStatus, newStatus)) {
+                log.info("能耗监测系统连接状态变化: {} -> {}, IP: {}", oldStatus, newStatus, ipAddress);
+
+                // 更新系统属性状态
+                objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, statusKey, newStatus);
+
+                String key = isOnline ? "connect" : "disconnect";
+                triggerEvent(SYS_MODE_CODE, SUBSYSTEM_CODE, key, null, new Date());
+            }
+
+            // 5. 记录心跳日志(可选,用于调试)
+            log.debug("广场灯控系统心跳检测完成 - IP: {}, 状态: {}", ipAddress, isOnline ? "在线" : "离线");
+        }
+        catch (Exception e) {
+            log.error("广场灯控系统心跳检测异常", e);
+        }
+    }
+
+    @Override
+    public CallResponse<Void> call(AbilityPayload abilityParam) {
+        CallResponse<Void> callResponse = null;
+
+        try {
+            if (DevObjType.SYSTEM.getCode() == abilityParam.getObjType()) {
+                switch (abilityParam.getAbilityKey()) {
+                    case "GetProjectList":
+                        execGetProjectList();
+                        break;
+                    case "GetProjectSubsetList":
+                        execGetProjectSubsetList();
+                        break;
+                    case "GetDeviceList":
+                        execGetDeviceList();
+                        break;
+                    case "lightControlAll":
+                        lightControlAll(abilityParam.getAbilityParam());
+                        break;
+                    default:
+                        throw new UnsupportedOperationException("不支持的abilityKey");
+                }
+            }
+            else if (DevObjType.DEVC.getCode() == abilityParam.getObjType()) {
+                switch (abilityParam.getAbilityKey()) {
+                    case "lightControl":
+                        lightControl(abilityParam.getObjCode(), abilityParam.getAbilityParam());
+                        break;
+                    case "lightControlBrightness":
+                        lightControlBrightness(abilityParam.getObjCode(), abilityParam.getAbilityParam());
+                        break;
+                    default:
+                        throw new UnsupportedOperationException("不支持的abilityKey");
+                }
+            }
+
+            callResponse = new CallResponse<>(0, "成功");
+        }
+        catch (Exception e) {
+            callResponse = new CallResponse<>(-1, e.getMessage());
+            log.error("调用ability异常", e);
+        }
+
+        return callResponse;
+    }
+
+    public void execGetProjectList() {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+        CallData<SlcProject> callData = template.getProjectList();
+        List<SlcProject> projects = callData.getList();
+        saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "GetProjectList", callData.getCallStatus(),
+            callData.getCallPayload(), callData.getResPayload());
+        objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, "projectList",
+            JSON.toJSONString(projects));
+    }
+
+    public void execGetProjectSubsetList() {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+        CallData<SlcProject> projectCallData = template.getProjectList();
+        List<SlcProject> projects = projectCallData.getList();
+
+        if (CollectionUtils.isNotEmpty(projects)) {
+            List<SlcProjectSubset> subsets = new ArrayList<>();
+
+            for (SlcProject project : projects) {
+                CallData<SlcProjectSubset> callData = template.getProjectSubsetList(project.getProjectId());
+                List<SlcProjectSubset> slcProjectSubsets = callData.getList();
+                saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "GetProjectSubsetList", callData.getCallStatus(),
+                    callData.getCallPayload(), callData.getResPayload());
+                subsets.addAll(slcProjectSubsets);
+            }
+
+            objAttrValueService.updateObjAttrValue(SYS_MODE_CODE, SUBSYSTEM_CODE, "projectSubsetList",
+                JSON.toJSONString(subsets));
+        }
+    }
+
+    public void lightControlAll(String paramValue) {
+        QueryDevice queryDevice = new QueryDevice();
+        queryDevice.setDeviceModel(DEV_MODE_CODE);
+        queryDevice.setSubsystemCode(SUBSYSTEM_CODE);
+        queryDevice.setDeviceStatus(1);
+        List<EmsDevice> devices = deviceService.selectList(queryDevice);
+
+        if (CollectionUtils.isNotEmpty(devices)) {
+            JsonEntity.ObjBuilder json = JsonEntity.objBuilder();
+
+            for (EmsDevice device : devices) {
+                EmsObjAttrValue value = objAttrValueService.selectObjAttrValue(DEV_MODE_CODE, device.getDeviceCode(),
+                    "deviceId");
+                json.addKeyArray("deviceIds", value.getAttrValue());
+            }
+
+            EmsObjAttrValue projectIdAttr = objAttrValueService.selectObjAttrValue(DEV_MODE_CODE,
+                devices.get(0).getDeviceCode(), "projectId");
+
+            JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", "1")
+                .putKv("lampOnOff", paramValue).putKv("brightness", 0);
+            json.addKeyArray("lampList", lampListObj.build().getJsonObj());
+
+            lightControl(projectIdAttr.getAttrValue(), json.build().getJsonObj());
+        }
+    }
+
+    public void lightControl(String objCode, String paramValue) {
+        List<EmsObjAttrValue> attrValues = objAttrValueService.selectByObjCode(DEV_MODE_CODE, objCode);
+        Map<String, EmsObjAttrValue> attrValueMap = attrValues.stream()
+            .collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, v -> v));
+
+        EmsObjAttrValue projectIdAttr = attrValueMap.get("projectId");
+        Assert.notNull(projectIdAttr, -1, "lampList 属性未同步");
+        EmsObjAttrValue deviceIdAttr = attrValueMap.get("deviceId");
+        Assert.notNull(deviceIdAttr, -1, "deviceId 属性未同步");
+        EmsObjAttrValue lampListAttr = attrValueMap.get("lampList");
+        Assert.notNull(lampListAttr, -1, "lampList 属性未同步");
+
+        JsonEntity.ObjBuilder json = JsonEntity.objBuilder().addKeyArray("deviceIds", deviceIdAttr.getAttrValue());
+
+        List<SlcDeviceLamp> lampList = JSONArray.parseArray(lampListAttr.getAttrValue(), SlcDeviceLamp.class);
+        Assert.notEmpty(lampList, -1, "灯组列表为空");
+
+        for (SlcDeviceLamp lamp : lampList) {
+            JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", lamp.getLampNo())
+                .putKv("lampOnOff", paramValue).putKv("brightness", 0);
+
+            json.addKeyArray("lampList", lampListObj.build().getJsonObj());
+        }
+
+        lightControl(projectIdAttr.getAttrValue(), json.build().getJsonObj());
+    }
+
+    /**
+     * 灯组开关控制
+     */
+    public void lightControl(String projectId, JSONObject req) {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+        CallData<Void> callData = template.lightControl(projectId, req);
+        saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "lightControl", callData.getCallStatus(), callData.getCallPayload(),
+            callData.getResPayload());
+    }
+
+    public void lightControlBrightness(String objCode, String paramValue) {
+        List<EmsObjAttrValue> attrValues = objAttrValueService.selectByObjCode(DEV_MODE_CODE, objCode);
+        Map<String, EmsObjAttrValue> attrValueMap = attrValues.stream()
+            .collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, v -> v));
+
+        EmsObjAttrValue projectIdAttr = attrValueMap.get("projectId");
+        Assert.notNull(projectIdAttr, -1, "projectId 属性未同步");
+        EmsObjAttrValue deviceIdAttr = attrValueMap.get("deviceId");
+        Assert.notNull(deviceIdAttr, -1, "deviceId 属性未同步");
+        EmsObjAttrValue lampListAttr = attrValueMap.get("lampList");
+        Assert.notNull(lampListAttr, -1, "lampList 属性未同步");
+
+        JsonEntity.ObjBuilder json = JsonEntity.objBuilder().addKeyArray("deviceIds", deviceIdAttr.getAttrValue());
+
+        List<SlcDeviceLamp> lampList = JSONArray.parseArray(lampListAttr.getAttrValue(), SlcDeviceLamp.class);
+        Assert.notEmpty(lampList, -1, "灯组列表为空");
+
+        for (SlcDeviceLamp lamp : lampList) {
+            JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", lamp.getLampNo())
+                .putKv("brightness", paramValue);
+
+            json.addKeyArray("lampList", lampListObj.build().getJsonObj());
+        }
+
+        lightControlBrightness(projectIdAttr.getAttrValue(), json.build().getJsonObj());
+    }
+
+    /**
+     * 灯组亮度控制
+     */
+    public void lightControlBrightness(String projectId, JSONObject req) {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+        CallData<Void> callData = template.controlBrightness(projectId, req);
+        saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "lightControlBrightness", callData.getCallStatus(),
+            callData.getCallPayload(), callData.getResPayload());
+    }
+
+    public void execGetDeviceList() {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+        CallData<SlcProject> projecCallData = template.getProjectList();
+        List<SlcProject> projects = projecCallData.getList();
+
+        if (CollectionUtils.isNotEmpty(projects)) {
+            for (SlcProject project : projects) {
+                CallData<SlcDevice> callData = template.getDeviceList(project.getProjectId(), null);
+                saveCallLog(SUBSYSTEM_CODE, SYS_MODE_CODE, "GetDeviceList", callData.getCallStatus(),
+                    callData.getCallPayload(), callData.getResPayload());
+
+                // 灯组设备同步
+                List<SlcDevice> lightDevs = callData.getList().stream()
+                    .filter(dev -> StringUtils.equals(dev.getDeviceModelId(), "1945454135655632897"))
+                    .collect(Collectors.toList());
+                syncLightDeviceList(lightDevs);
+                mergeLightDevAttrValue(project.getProjectId(), lightDevs);
+
+                // 集中器设备同步
+                List<SlcDevice> centDevs = callData.getList().stream()
+                    .filter(dev -> StringUtils.equals(dev.getDeviceModelId(), "1943504597877362689"))
+                    .collect(Collectors.toList());
+                syncCentDeviceList(centDevs);
+                mergeCentDevAttrValue(project.getProjectId(), centDevs);
+            }
+        }
+    }
+
+    public void syncLightDeviceList(List<SlcDevice> slcDevices) {
+        // 查询数据库记录
+        QueryDevice param = new QueryDevice();
+        param.setDeviceModel(LAMP_POST_MODE_CODE);
+        param.setSubsystemCode(SUBSYSTEM_CODE);
+        List<EmsDevice> dbDevs = deviceService.selectList(param);
+
+        if (CollectionUtils.isNotEmpty(dbDevs)) {
+            for (EmsDevice emsDevice : dbDevs) {
+                deviceService.deleteDevice(LAMP_POST_MODE_CODE, emsDevice.getDeviceCode());
+                objAttrValueService.deleteByObjCode(LAMP_POST_MODE_CODE, emsDevice.getDeviceCode());
+            }
+        }
+
+        // 待新增的设备
+        if (CollectionUtils.isNotEmpty(slcDevices)) {
+            Map<String, SlcDevice> slcDevMap = slcDevices.stream()
+                .collect(Collectors.toMap(SlcDevice::getDeviceId, Function.identity()));
+
+            Map<String, List<String>> matchMap = mergeLightDev(slcDevices);
+
+            List<EmsDevice> addDevs = new ArrayList<>();
+            List<EmsObjAttrValue> attrValues = new ArrayList<>();
+
+            for (Map.Entry<String, List<String>> entry : matchMap.entrySet()) {
+                // 灯杆ID
+                String deviceCode = entry.getKey();
+                // 原始设备ID
+                List<String> deviceIds = entry.getValue();
+
+                SlcDevice slcDeviceTmp = slcDevMap.get(deviceIds.get(0));
+                addDevs.add(buildLampPostDevice(deviceCode, slcDeviceTmp));
+                attrValues.add(buildLampPostLights(deviceCode, deviceIds));
+            }
+
+            addDevs.sort(Comparator.comparing(EmsDevice::getDeviceName));
+            deviceService.insertBatch(addDevs);
+            objAttrValueService.insertBatch(attrValues);
+        }
+    }
+
+    private Map<String, List<String>> mergeLightDev(List<SlcDevice> slcDevices) {
+        Map<String, List<String>> ret = new HashMap<>();
+
+        for (SlcDevice device : slcDevices) {
+            // 获取deviceName的前缀(如"B1")
+            String prefix = "SL-Z-" + StringUtils.substringBefore(device.getDeviceName(), "-");
+
+            // 如果map中不存在该前缀,初始化一个空列表
+            ret.computeIfAbsent(prefix, k -> new ArrayList<>());
+
+            // 将当前deviceName添加到对应前缀的列表中
+            ret.get(prefix).add(device.getDeviceId());
+        }
+
+        return ret;
+    }
+
+    public void syncCentDeviceList(List<SlcDevice> slcDevices) {
+        // 查询数据库记录
+        QueryDevice param = new QueryDevice();
+        param.setDeviceModel(CONCENTRATOR_MODE_CODE);
+        param.setSubsystemCode(SUBSYSTEM_CODE);
+        List<EmsDevice> dbDevs = deviceService.selectList(param);
+        Set<String> dbDevCodeSet = dbDevs.stream().map(EmsDevice::getDeviceCode).collect(Collectors.toSet());
+
+        Map<String, SlcDevice> slcDevMap = slcDevices.stream()
+            .collect(Collectors.toMap(SlcDevice::getDeviceCode, Function.identity()));
+        Set<String> slcDevCodeSet = slcDevices.stream().map(SlcDevice::getDeviceCode).collect(Collectors.toSet());
+
+        // 待删除的设备
+        Set<String> delCodes = new HashSet<>(dbDevCodeSet);
+        delCodes.removeAll(slcDevCodeSet);
+
+        if (CollectionUtils.isNotEmpty(delCodes)) {
+            for (String code : delCodes) {
+                deviceService.deleteDevice(CONCENTRATOR_MODE_CODE, code);
+            }
+        }
+
+        // 待新增的设备
+        Set<String> addCodes = new HashSet<>(slcDevCodeSet);
+        addCodes.removeAll(dbDevCodeSet);
+
+        if (CollectionUtils.isNotEmpty(addCodes)) {
+            List<EmsDevice> addDevs = new ArrayList<>();
+
+            for (String code : addCodes) {
+                SlcDevice slcDevice = slcDevMap.get(code);
+                addDevs.add(buildCentDevice(slcDevice));
+            }
+
+            addDevs.sort(Comparator.comparing(EmsDevice::getDeviceName));
+            deviceService.insertBatch(addDevs);
+        }
+    }
+
+    private EmsDevice buildLampPostDevice(String deviceCode, SlcDevice slcDevice) {
+        EmsDevice device = new EmsDevice();
+        device.setDeviceCode(deviceCode);
+        device.setDeviceName(StringUtils.substringBefore(slcDevice.getDeviceName(), "-") + "灯杆");
+        device.setDeviceSpec("智慧灯杆");
+        device.setDeviceStatus(slcDevice.getStatus());
+        device.setDeviceModel(LAMP_POST_MODE_CODE);
+        device.setSubsystemCode(SUBSYSTEM_CODE);
+
+        if (StringUtils.startsWith(slcDevice.getDeviceName(), "B")) {
+            device.setLocation("北区广场");
+            device.setLocationRef("321283124S300104");
+            device.setAreaCode("321283124S3001");
+            device.setRefFacs("Z-ZM-01");
+        }
+        else if (StringUtils.startsWith(slcDevice.getDeviceName(), "N")) {
+            device.setLocation("南区广场");
+            device.setLocationRef("321283124S300204");
+            device.setAreaCode("321283124S3002");
+            device.setRefFacs("Z-ZM-02");
+        }
+
+        return device;
+    }
+
+    private EmsObjAttrValue buildLampPostLights(String deviceCode, List<String> lampList) {
+        EmsObjAttrValue attrValue = new EmsObjAttrValue();
+        attrValue.setObjCode(deviceCode);
+        attrValue.setModelCode(LAMP_POST_MODE_CODE);
+        attrValue.setAttrKey("subDev");
+        attrValue.setAttrValue(JSON.toJSONString(lampList));
+        return attrValue;
+    }
+
+    private EmsDevice buildCentDevice(SlcDevice slcDevice) {
+        EmsDevice device = new EmsDevice();
+        device.setDeviceCode(slcDevice.getDeviceCode());
+        device.setDeviceName(slcDevice.getDeviceName());
+        device.setDeviceBrand("佐通");
+        device.setDeviceSpec("单灯控制器");
+        device.setDeviceStatus(slcDevice.getStatus());
+        device.setDeviceModel(CONCENTRATOR_MODE_CODE);
+        device.setSubsystemCode(SUBSYSTEM_CODE);
+
+        if (StringUtils.startsWith(slcDevice.getDeviceName(), "北区")) {
+            device.setLocation("北区广场");
+            device.setLocationRef("321283124S300104");
+            device.setAreaCode("321283124S3001");
+            device.setRefFacs("DEV01");
+        }
+        else if (StringUtils.startsWith(slcDevice.getDeviceName(), "南区")) {
+            device.setLocation("南区广场");
+            device.setLocationRef("321283124S300204");
+            device.setAreaCode("321283124S3002");
+            device.setRefFacs("DEV02");
+        }
+
+        return device;
+    }
+
+    private void mergeLightDevAttrValue(String projectId, List<SlcDevice> slcDevices) {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+
+        for (SlcDevice slcDevice : slcDevices) {
+            CallData<DeviceInfo> callData = template.getDeviceInfo(projectId, slcDevice.getDeviceId());
+            DeviceInfo deviceInfo = callData.getData();
+
+            List<EmsObjAttrValue> oaValues = objAttrValueService.selectByObjCode(DEV_MODE_CODE,
+                slcDevice.getDeviceId());
+
+            if (CollectionUtils.isNotEmpty(oaValues)) {
+                Map<String, EmsObjAttrValue> vMap = oaValues.stream()
+                    .collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, Function.identity()));
+
+                checkAndUpdate(vMap, slcDevice.getDeviceId(), "abnormal", String.valueOf(slcDevice.getAbnormal()));
+                checkAndUpdate(vMap, slcDevice.getDeviceId(), "csq", slcDevice.getCsq());
+
+                if (null != deviceInfo.getBaselineInfo()) {
+                    BaselineInfo baselineInfo = deviceInfo.getBaselineInfo();
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "firmwareVer", baselineInfo.getFirmwareVer());
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "softwareVer", baselineInfo.getSoftwareVer());
+                }
+
+                if (null != deviceInfo.getStatusInfo()) {
+                    StatusInfo sInfo = deviceInfo.getStatusInfo();
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "current", String.valueOf(sInfo.getCurrent()));
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "power", String.valueOf(sInfo.getPower()));
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "factor", String.valueOf(sInfo.getFactor()));
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "voltage", String.valueOf(sInfo.getVoltage()));
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "energy", String.valueOf(sInfo.getEnergy()));
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "temperature",
+                        String.valueOf(sInfo.getTemperature()));
+                }
+
+                if (CollectionUtils.isNotEmpty(deviceInfo.getLampList())) {
+                    List<SlcDeviceLamp> lampList = deviceInfo.getLampList();
+                    SlcDeviceLamp lamp = lampList.get(0);
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "cct", String.valueOf(lamp.getCct()));
+                    checkAndUpdate(vMap, slcDevice.getDeviceId(), "lampOnOff", String.valueOf(lamp.getLampOnOff()));
+                }
+            }
+            else {
+                oaValues = new ArrayList<>();
+                oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "projectId", projectId));
+                oaValues.add(
+                    new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "deviceId", slcDevice.getDeviceId()));
+                oaValues.add(
+                    new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "deviceUid", slcDevice.getDeviceUid()));
+                oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "deviceModelId",
+                    slcDevice.getDeviceModelId()));
+                oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "minCct",
+                    String.valueOf(slcDevice.getMinCct())));
+                oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "maxCct",
+                    String.valueOf(slcDevice.getMaxCct())));
+                oaValues.add(
+                    new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "imageUrl", slcDevice.getImageUrl()));
+                oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "abnormal",
+                    String.valueOf(slcDevice.getAbnormal())));
+                oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "csq", slcDevice.getCsq()));
+
+                if (null != deviceInfo.getBaselineInfo()) {
+                    BaselineInfo bInfo = deviceInfo.getBaselineInfo();
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "firmwareVer",
+                        bInfo.getFirmwareVer()));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "softwareVer",
+                        bInfo.getSoftwareVer()));
+                }
+
+                if (null != deviceInfo.getStatusInfo()) {
+                    StatusInfo sInfo = deviceInfo.getStatusInfo();
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "current",
+                        String.valueOf(sInfo.getCurrent())));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "power",
+                        String.valueOf(sInfo.getPower())));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "factor",
+                        String.valueOf(sInfo.getFactor())));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "voltage",
+                        String.valueOf(sInfo.getVoltage())));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "energy",
+                        String.valueOf(sInfo.getEnergy())));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "frequency",
+                        String.valueOf(sInfo.getFrequency())));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "temperature",
+                        String.valueOf(sInfo.getTemperature())));
+                }
+
+                if (CollectionUtils.isNotEmpty(deviceInfo.getLampList())) {
+                    List<SlcDeviceLamp> lampList = deviceInfo.getLampList();
+                    SlcDeviceLamp lamp = lampList.get(0);
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "cct",
+                        String.valueOf(lamp.getCct())));
+                    oaValues.add(new EmsObjAttrValue(slcDevice.getDeviceId(), DEV_MODE_CODE, "lampOnOff",
+                        String.valueOf(lamp.getLampOnOff())));
+                }
+
+                objAttrValueService.insertBatch(oaValues);
+            }
+        }
+    }
+
+    private void mergeCentDevAttrValue(String projectId, List<SlcDevice> slcDevices) {
+        for (SlcDevice slcDevice : slcDevices) {
+            List<EmsObjAttrValue> objAttrValues = objAttrValueService.selectByObjCode(CONCENTRATOR_MODE_CODE,
+                slcDevice.getDeviceCode());
+            CcElecInfo info = slcDevice.getCcElecInfo();
+
+            if (CollectionUtils.isNotEmpty(objAttrValues)) {
+                Map<String, EmsObjAttrValue> objAttrValueMap = objAttrValues.stream()
+                    .collect(Collectors.toMap(EmsObjAttrValue::getAttrKey, Function.identity()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "abnormal",
+                    String.valueOf(slcDevice.getAbnormal()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "csq", String.valueOf(slcDevice.getCsq()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "kwh", String.valueOf(info.getKwh()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "kvarh", String.valueOf(info.getKvarh()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "ua", String.valueOf(info.getUa()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "ub", String.valueOf(info.getUb()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "uc", String.valueOf(info.getUc()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "ia", String.valueOf(info.getIa()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "ib", String.valueOf(info.getIb()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "ic", String.valueOf(info.getIc()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "pfa", String.valueOf(info.getPfa()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "pfb", String.valueOf(info.getPfb()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "pfc", String.valueOf(info.getPfc()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "hza", String.valueOf(info.getHza()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "hzb", String.valueOf(info.getHzb()));
+                checkAndUpdate(objAttrValueMap, slcDevice.getDeviceCode(), "hzc", String.valueOf(info.getHzc()));
+            }
+            else {
+                objAttrValues = new ArrayList<>();
+                objAttrValues.add(
+                    new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "projectId", projectId));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "deviceId",
+                    slcDevice.getDeviceId()));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "deviceUid",
+                    slcDevice.getDeviceUid()));
+                objAttrValues.add(
+                    new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "deviceModelId",
+                        slcDevice.getDeviceModelId()));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "imageUrl",
+                    slcDevice.getImageUrl()));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "abnormal",
+                    String.valueOf(slcDevice.getAbnormal())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "csq",
+                    String.valueOf(slcDevice.getCsq())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "kwh",
+                    String.valueOf(info.getKwh())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "kvarh",
+                    String.valueOf(info.getKvarh())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "ua",
+                    String.valueOf(info.getUa())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "ub",
+                    String.valueOf(info.getUb())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "uc",
+                    String.valueOf(info.getUc())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "ia",
+                    String.valueOf(info.getIa())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "ib",
+                    String.valueOf(info.getIb())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "ic",
+                    String.valueOf(info.getIc())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "pfa",
+                    String.valueOf(info.getPfa())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "pfb",
+                    String.valueOf(info.getPfb())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "pfc",
+                    String.valueOf(info.getPfc())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "hza",
+                    String.valueOf(info.getHza())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "hzb",
+                    String.valueOf(info.getHzb())));
+                objAttrValues.add(new EmsObjAttrValue(slcDevice.getDeviceCode(), CONCENTRATOR_MODE_CODE, "hzc",
+                    String.valueOf(info.getHzc())));
+
+                objAttrValueService.insertBatch(objAttrValues);
+            }
+        }
+    }
+
+    private void checkAndUpdate(Map<String, EmsObjAttrValue> objAttrValueMap, String objCode, String key,
+        String newValue) {
+        EmsObjAttrValue objAttrValue = objAttrValueMap.get(key);
+
+        if (null != objAttrValue) {
+            if (!StringUtils.equals(objAttrValue.getAttrValue(), newValue)) {
+                objAttrValueService.updateObjAttrValue(DEV_MODE_CODE, objCode, key, newValue);
+            }
+        }
+        else {
+            objAttrValue = new EmsObjAttrValue(objCode, DEV_MODE_CODE, key, newValue);
+            objAttrValueService.mergeObjAttrValue(objAttrValue);
+        }
+    }
+}

+ 123 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/CallData.java

@@ -0,0 +1,123 @@
+/*
+ * 文 件 名:  CommonCall
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/24
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model;
+
+import lombok.Getter;
+
+import java.util.List;
+
+/**
+ * CallData
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/24]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class CallData<T> {
+    @Getter
+    private final String callPayload;
+
+    @Getter
+    private final String resPayload;
+
+    @Getter
+    private final Integer callStatus;
+
+    @Getter
+    private final T data;
+
+    @Getter
+    private final List<T> list;
+
+    // 私有构造方法,只能通过Builder创建对象
+    private CallData(Builder<T> builder) {
+        this.callPayload = builder.callPayload.toString();
+        this.resPayload = builder.resPayload.toString();
+        this.callStatus = builder.callStatus;
+        this.data = builder.data;
+        this.list = builder.list;
+    }
+
+    // Builder类
+    public static class Builder<T> {
+        private StringBuilder callPayload = new StringBuilder();
+
+        private StringBuilder resPayload = new StringBuilder();
+
+        private Integer callStatus;
+
+        private T data;
+
+        private List<T> list;
+
+        public Builder() {
+        }
+
+        /**
+         * 链式添加callPayload键值对
+         */
+        public Builder<T> addCallParam(String key, Object value) {
+            this.callPayload.append(key).append(": ").append(value).append(System.lineSeparator());
+            return this;
+        }
+
+        /**
+         * 设置resPayload
+         */
+        public Builder<T> setResPayload(String resPayload) {
+            this.resPayload = new StringBuilder(resPayload);
+            return this;
+        }
+
+        public Builder<T> appendResPayload(String resPayload) {
+            this.resPayload.append(resPayload);
+            return this;
+        }
+
+        /**
+         * 设置resPayload
+         */
+        public Builder<T> setCallStatus(Integer callStatus) {
+            this.callStatus = callStatus;
+            return this;
+        }
+
+        /**
+         * 设置data
+         */
+        public Builder<T> setData(T data) {
+            this.data = data;
+            return this;
+        }
+
+        /**
+         * 设置data
+         */
+        public Builder<T> setList(List<T> list) {
+            this.list = list;
+            return this;
+        }
+
+        /**
+         * 构建CallData对象
+         */
+        public CallData<T> build() {
+            return new CallData<>(this);
+        }
+    }
+
+    // 用于获取Builder实例的静态方法
+    public static <T> Builder<T> builder() {
+        return new Builder<>();
+    }
+}

+ 32 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/BaselineInfo.java

@@ -0,0 +1,32 @@
+/*
+ * 文 件 名:  BaselineInfo
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/29
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model.slightctl;
+
+import lombok.Data;
+
+/**
+ * BaselineInfo
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/29]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Data
+public class BaselineInfo {
+    private String firmwareVer;
+    private String address;
+    private String createTime;
+    private String deviceModelName;
+    private String deviceModelId;
+    private String softwareVer;
+}

+ 40 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/CcElecInfo.java

@@ -0,0 +1,40 @@
+/*
+ * 文 件 名:  CcElecInfo
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/25
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model.slightctl;
+
+import lombok.Data;
+
+/**
+ * 电能参数
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/25]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Data
+public class CcElecInfo {
+    private Double kwh;
+    private Double kvarh;
+    private Double ua;
+    private Double ub;
+    private Double uc;
+    private Double ia;
+    private Double ib;
+    private Double ic;
+    private Double pfa;
+    private Double pfb;
+    private Double pfc;
+    private Double hza;
+    private Double hzb;
+    private Double hzc;
+}

+ 31 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/DeviceInfo.java

@@ -0,0 +1,31 @@
+/*
+ * 文 件 名:  DeviceInfoRes
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/29
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model.slightctl;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * DeviceInfoRes
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/29]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Data
+public class DeviceInfo {
+    public StatusInfo statusInfo;
+    private BaselineInfo baselineInfo;
+    private List<SlcDeviceLamp> lampList;
+}

+ 45 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/LightControlReq.java

@@ -0,0 +1,45 @@
+/*
+ * 文 件 名:  LightControlReq
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/19
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model.slightctl;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 灯控请求
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/19]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Data
+public class LightControlReq {
+    /**
+     * 设备ID列表
+     */
+    private List<String> deviceIds;
+
+    /**
+     * 灯列表
+     */
+    private List<SlcDeviceLamp> lampList;
+
+    public LightControlReq() {
+    }
+
+    public LightControlReq(List<String> deviceIds, List<SlcDeviceLamp> lampList) {
+        this.deviceIds = deviceIds;
+        this.lampList = lampList;
+    }
+}

+ 5 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/SlcDevice.java

@@ -46,5 +46,10 @@ public class SlcDevice {
     private Integer deviceCode;
     private Integer minCct;
     private Integer maxCct;
+    private CcElecInfo ccElecInfo;
     private List<SlcDeviceLamp> lampList;
+
+    public String getDeviceCode() {
+        return "SL-Z-" + this.deviceUid;
+    }
 }

+ 48 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/SlcDeviceLamp.java

@@ -37,4 +37,52 @@ public class SlcDeviceLamp {
 
     // 亮度百分比
     private Integer lampBright;
+
+    // 亮度值
+
+    private String brightness;
+
+    public SlcDeviceLamp() {
+    }
+
+    // 私有构造方法,只能通过Builder创建
+    private SlcDeviceLamp(Builder builder) {
+        this.lampNo = builder.lampNo;
+        this.lampOnOff = builder.lampOnOff;
+        this.brightness = builder.brightness;
+    }
+
+    // Builder静态内部类
+    public static class Builder {
+        private String lampNo;
+
+        private Integer lampOnOff;
+
+        private String brightness;
+
+        // 私有构造方法
+        private Builder() {
+        }
+
+        // 链式设值方法
+        public Builder lampNo(String lampNo) {
+            this.lampNo = lampNo;
+            return this;
+        }
+
+        public Builder lampOnOff(Integer lampOnOff) {
+            this.lampOnOff = lampOnOff;
+            return this;
+        }
+
+        public Builder brightness(String brightness) {
+            this.brightness = brightness;
+            return this;
+        }
+
+        // 构建实体对象
+        public SlcDeviceLamp build() {
+            return new SlcDeviceLamp(this);
+        }
+    }
 }

+ 38 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/StatusInfo.java

@@ -0,0 +1,38 @@
+/*
+ * 文 件 名:  StatusInfo
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/29
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model.slightctl;
+
+import io.swagger.models.auth.In;
+import lombok.Data;
+
+/**
+ * StatusInfo
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/29]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Data
+public class StatusInfo {
+    private Integer csq;
+    private Double current;
+    private Long runingTime;
+    private Long runingTimeCurrent;
+    private String temperature;
+    private String angle;
+    private Double power;
+    private Double factor;
+    private Double voltage;
+    private Double energy;
+    private Integer frequency;
+}

+ 36 - 0
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/model/slightctl/SyncStatusReq.java

@@ -0,0 +1,36 @@
+/*
+ * 文 件 名:  SyncStatusReq
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/19
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.ruoyi.ems.model.slightctl;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * 同步设备状态请求
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/19]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+@Data
+public class SyncStatusReq {
+    private List<String> idList;
+
+    public SyncStatusReq() {
+    }
+
+    public SyncStatusReq(List<String> idList) {
+        this.idList = idList;
+    }
+}

+ 55 - 11
ems/ems-cloud/ems-dev-adapter/src/main/java/com/ruoyi/ems/retrofit/SquareLightCtlApi.java

@@ -10,6 +10,7 @@
  */
 package com.ruoyi.ems.retrofit;
 
+import com.alibaba.fastjson2.JSONObject;
 import com.ruoyi.ems.model.slightctl.AppLoginReq;
 import retrofit2.Call;
 import retrofit2.http.Body;
@@ -17,6 +18,7 @@ import retrofit2.http.GET;
 import retrofit2.http.Header;
 import retrofit2.http.Headers;
 import retrofit2.http.POST;
+import retrofit2.http.Path;
 import retrofit2.http.Query;
 
 /**
@@ -44,14 +46,11 @@ public interface SquareLightCtlApi {
      *
      * @param clientId      客户端id
      * @param authorization 认证信息
-     * @param pageNum       页码
-     * @param pageSize      每页记录数
      * @return 项目列表
      */
     @Headers({ "tenantId: 1", "Content-Type: application/json" })
     @GET("/light-cloud/app/project/list")
-    Call<String> getProjectList(@Header("clientId") String clientId, @Header("Authorization") String authorization,
-        @Query("pageNum") int pageNum, @Query("pageSize") int pageSize);
+    Call<String> getProjectList(@Header("clientId") String clientId, @Header("Authorization") String authorization);
 
     /**
      * 获取项目分组列表
@@ -59,20 +58,16 @@ public interface SquareLightCtlApi {
      * @param clientId      客户端id
      * @param authorization 认证信息
      * @param projectId     项目ID
-     * @param pageNum       页码
-     * @param pageSize      每页记录数
      * @return 项目列表
      */
     @Headers({ "tenantId: 1", "Content-Type: application/json" })
     @GET("/light-cloud/app/projectSubset/list")
     Call<String> getProjectSubsetList(@Header("clientId") String clientId,
-        @Header("Authorization") String authorization, @Query("projectId") String projectId,
-        @Query("pageNum") int pageNum, @Query("pageSize") int pageSize);
+        @Header("Authorization") String authorization, @Query("projectId") String projectId);
 
     /**
      * 获取项目分组列表
      *
-     * @param clientId      客户端id
      * @param authorization 认证信息
      * @param projectId     项目ID
      * @param pageNum       页码
@@ -81,6 +76,55 @@ public interface SquareLightCtlApi {
      */
     @Headers({ "tenantId: 1", "Content-Type: application/json" })
     @GET("/light-cloud/app/device/list")
-    Call<String> getDeviceList(@Header("clientId") String clientId, @Header("projectId") String projectId,
-        @Header("Authorization") String authorization, @Query("pageNum") int pageNum, @Query("pageSize") int pageSize);
+    Call<String> getDeviceList(@Header("clientId") String clientId, @Header("Authorization") String authorization,
+        @Header("projectId") String projectId, @Header("subsetId") String subsetId, @Query("pageNum") int pageNum,
+        @Query("pageSize") int pageSize);
+
+    /**
+     * 同步设备状态
+     *
+     * @param clientId 客户端id
+     * @param req      灯控请求
+     * @return 灯控响应
+     */
+    @Headers({ "tenantId: 1", "Content-Type: application/json" })
+    @POST("/light-cloud/operate/device/syncStatus")
+    Call<String> syncStatus(@Header("clientId") String clientId, @Header("projectId") String projectId,
+        @Header("Authorization") String authorization, @Body JSONObject req);
+
+    /**
+     * 获取设备状态
+     *
+     * @param clientId 客户端id
+     * @param deviceId 设备编号
+     * @return 灯控响应
+     */
+    @Headers({ "tenantId: 1", "Content-Type: application/json" })
+    @GET("/light-cloud/operate/device/light/info/{deviceId}")
+    Call<String> getDeviceInfo(@Header("clientId") String clientId, @Header("projectId") String projectId,
+        @Header("Authorization") String authorization, @Path("deviceId") String deviceId);
+
+    /**
+     * 设备开关灯批量-普通照明
+     *
+     * @param clientId 客户端id
+     * @param req      灯控请求
+     * @return 灯控响应
+     */
+    @Headers({ "tenantId: 1", "Content-Type: application/json" })
+    @POST("/light-cloud/app/device/light/control")
+    Call<String> lightControl(@Header("clientId") String clientId, @Header("projectId") String projectId,
+        @Header("Authorization") String authorization, @Body JSONObject req);
+
+    /**
+     * 设备调光批量-普通照明
+     *
+     * @param clientId 客户端id
+     * @param req      灯控请求
+     * @return 灯控响应
+     */
+    @Headers({ "tenantId: 1", "Content-Type: application/json" })
+    @POST("/light-cloud/operate/device/light/controlBrightness")
+    Call<String> controlBrightness(@Header("clientId") String clientId, @Header("projectId") String projectId,
+        @Header("Authorization") String authorization, @Body JSONObject req);
 }

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

@@ -68,7 +68,6 @@ adapter:
   # 广场照明控制
   square-lighting-ctl:
     url: http://127.0.0.1:8686
-    project-id: 1948750398922747906
     client-id: 5fa30d0e6c8245d550df634eb0cbc326
     user-name: developer3
     password: dev@admin123

+ 0 - 1
ems/ems-cloud/ems-dev-adapter/src/main/resources/application-prod-ct.yml

@@ -68,7 +68,6 @@ adapter:
   # 广场照明控制
   square-lighting-ctl:
     url: http://172.17.60.30:8686
-    project-id: 1948750398922747906
     client-id: 5fa30d0e6c8245d550df634eb0cbc326
     user-name: developer3
     password: dev@admin123

+ 56 - 11
ems/ems-cloud/ems-dev-adapter/src/test/java/com/huashe/test/SquareLightCtlTest.java

@@ -11,10 +11,14 @@
 package com.huashe.test;
 
 import com.alibaba.fastjson2.JSONObject;
+import com.huashe.common.domain.JsonEntity;
 import com.ruoyi.ems.EmsDevAdpApplication;
 import com.ruoyi.ems.config.SquareLightCtlConfig;
 import com.ruoyi.ems.core.SquareLightCtlTemplate;
+import com.ruoyi.ems.handle.SquareLightCtlHandler;
+import com.ruoyi.ems.model.CallData;
 import com.ruoyi.ems.model.slightctl.AppLoginRes;
+import com.ruoyi.ems.model.slightctl.DeviceInfo;
 import com.ruoyi.ems.model.slightctl.SlcDevice;
 import com.ruoyi.ems.model.slightctl.SlcProject;
 import com.ruoyi.ems.model.slightctl.SlcProjectSubset;
@@ -26,8 +30,6 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.test.context.SpringBootTest;
 import org.springframework.test.context.junit4.SpringRunner;
 
-import java.util.List;
-
 /**
  * 广场灯控测试
  * <功能详细描述>
@@ -55,24 +57,67 @@ public class SquareLightCtlTest {
     @Test
     public void testGetProjectList() {
         SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
-        List<SlcProject> list = template.getProjectList(1, 10);
-        log.info("ProjectList: {}", JSONObject.toJSONString(list));
-        Assert.assertNotNull(list);
+        CallData<SlcProject> callData = template.getProjectList();
+        log.info("ResPayload: {}", callData.getResPayload());
+        Assert.assertNotNull(callData.getResPayload());
     }
 
     @Test
     public void testGetProjectSubsetList() {
         SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
-        List<SlcProjectSubset> list = template.getProjectSubsetList("1948750398922747906", 1, 10);
-        log.info("ProjectSubsetList: {}", JSONObject.toJSONString(list));
-        Assert.assertNotNull(list);
+        CallData<SlcProjectSubset> callData = template.getProjectSubsetList("1948750398922747906");
+        log.info("ProjectSubsetList: {}", callData.getCallPayload());
+        Assert.assertNotNull(callData.getResPayload());
     }
 
     @Test
     public void testGetDeviceList() {
         SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
-        List<SlcDevice> list = template.getDeviceList("1948750398922747906");
-        log.info("DeviceList: {}", JSONObject.toJSONString(list));
-        Assert.assertNotNull(list);
+        CallData<SlcDevice> callData = template.getDeviceList("1948750398922747906", "1948750399027605506");
+        log.info("DeviceList: {}", callData.getCallPayload());
+        Assert.assertNotNull(callData.getCallPayload());
+    }
+
+    @Test
+    public void testGetDeviceInfo() {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+        CallData<DeviceInfo> callData = template.getDeviceInfo("1948750398922747906", "1954717047404425217");
+        log.info("DeviceInfo: {}", JSONObject.toJSONString(callData.getData()));
+        Assert.assertNotNull(callData.getData());
+    }
+
+    @Test
+    public void testLightControl() {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+        JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", "1").putKv("lampOnOff", 1)
+            .putKv("brightness", 0);
+
+        JsonEntity.ObjBuilder json = JsonEntity.objBuilder().addKeyArray("deviceIds", "1954717047404425217")
+            .addKeyArray("lampList", lampListObj.build().getJsonObj());
+
+        CallData<Void> callData = template.lightControl("1948750398922747906", json.build().getJsonObj());
+        log.info("lightControl: {}", callData.getResPayload());
+        Assert.assertNotNull(callData.getResPayload());
+    }
+
+    @Test
+    public void testControlBrightness() {
+        SquareLightCtlTemplate template = new SquareLightCtlTemplate(config.getUrl());
+
+        JsonEntity.ObjBuilder lampListObj = JsonEntity.objBuilder().putKv("lampNo", "1").putKv("brightness", 25);
+        JsonEntity.ObjBuilder json = JsonEntity.objBuilder().addKeyArray("deviceIds", "1954717047404425217")
+            .addKeyArray("lampList", lampListObj.build().getJsonObj());
+
+        CallData<Void> callData = template.controlBrightness("1948750398922747906", json.build().getJsonObj());
+        log.info("controlBrightness: {}", callData.getResPayload());
+        Assert.assertNotNull(callData.getResPayload());
+    }
+
+    @Autowired
+    private SquareLightCtlHandler handler;
+
+    @Test
+    public void testSyncDeviceList() {
+        handler.execGetDeviceList();
     }
 }

+ 84 - 12
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAttrController.java

@@ -3,17 +3,24 @@ package com.ruoyi.ems.controller;
 import com.alibaba.fastjson2.JSONArray;
 import com.alibaba.fastjson2.JSONObject;
 import com.huashe.common.domain.AjaxResult;
+import com.huashe.common.domain.JsonEntity;
 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.EmsDevice;
 import com.ruoyi.ems.domain.EmsObjAttr;
 import com.ruoyi.ems.domain.EmsObjAttrDto;
 import com.ruoyi.ems.domain.EmsObjAttrEnum;
+import com.ruoyi.ems.domain.EmsSubsystem;
+import com.ruoyi.ems.enums.DevObjType;
+import com.ruoyi.ems.mapper.EmsDeviceMapper;
+import com.ruoyi.ems.mapper.EmsSubsystemMapper;
 import com.ruoyi.ems.service.IEmsObjAttrEnumService;
 import com.ruoyi.ems.service.IEmsObjAttrService;
 import io.swagger.annotations.Api;
 import org.apache.commons.collections4.CollectionUtils;
+import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
@@ -45,6 +52,12 @@ public class EmsObjAttrController extends BaseController {
     @Autowired
     private IEmsObjAttrEnumService enumService;
 
+    @Autowired
+    private EmsDeviceMapper deviceService;
+
+    @Autowired
+    private EmsSubsystemMapper subsystemService;
+
     /**
      * 查询能源对象属性列表
      */
@@ -59,7 +72,8 @@ public class EmsObjAttrController extends BaseController {
      * 查询能源对象属性列表
      */
     @GetMapping("/enum/list")
-    public AjaxResult list(@RequestParam(name="modelCode") String modelCode, @RequestParam(name = "attrKey")String attrKey) {
+    public AjaxResult list(@RequestParam(name = "modelCode") String modelCode,
+        @RequestParam(name = "attrKey") String attrKey) {
         List<EmsObjAttrEnum> list = enumService.getObjAttrEnumList(modelCode, attrKey);
         return AjaxResult.success(list);
     }
@@ -77,7 +91,8 @@ public class EmsObjAttrController extends BaseController {
      */
     @GetMapping("/getObjAttr")
     public AjaxResult list(@RequestParam(name = "objType") Integer objType,
-        @RequestParam(name = "objCode") String objCode) {
+        @RequestParam(name = "objCode") String objCode,
+        @RequestParam(name = "modelCode", required = false) String modelCode) {
         AjaxResult result = null;
 
         try {
@@ -85,22 +100,19 @@ public class EmsObjAttrController extends BaseController {
             json.put("objType", objType);
             json.put("objCode", objCode);
 
+            if (null == modelCode) {
+                modelCode = getModeCode(objType, objCode);
+                json.put("modelCode", modelCode);
+            }
+
             // 获取属性列表
-            List<EmsObjAttrDto> attrDtos = attrService.selectObjAttrItem(objType, objCode);
+            List<EmsObjAttrDto> attrDtos = attrService.selectObjAttrItem(modelCode, objType, objCode);
 
             if (CollectionUtils.isNotEmpty(attrDtos)) {
                 Map<String, List<EmsObjAttrDto>> attrMap = attrDtos.stream()
                     .collect(Collectors.groupingBy(EmsObjAttrDto::getAttrGroup, Collectors.toList()));
 
-                json.put("Base", attrMap.get("Base"));
-                json.put("Protocol", attrMap.get("Protocol"));
-                json.put("State", attrMap.get("State"));
-                json.put("Measure", attrMap.get("Measure"));
-            } else {
-                json.put("Base", new JSONArray());
-                json.put("Protocol",  new JSONArray());
-                json.put("State",  new JSONArray());
-                json.put("Measure",  new JSONArray());
+                json.putAll(attrMap);
             }
 
             result = success(json);
@@ -113,6 +125,51 @@ public class EmsObjAttrController extends BaseController {
     }
 
     /**
+     * 查询能源对象属性值列表
+     */
+    @GetMapping("/getObjAttrBatch")
+    public AjaxResult listAll(@RequestParam(name = "objType") Integer objType,
+        @RequestParam(name = "modelCode") String modelCode) {
+        AjaxResult result = null;
+
+        try {
+            // 获取属性列表
+            List<EmsObjAttrDto> attrDtos = attrService.selectObjAttrItem(modelCode, objType, null);
+            JsonEntity.ObjBuilder json = JsonEntity.objBuilder();
+
+            if (CollectionUtils.isNotEmpty(attrDtos)) {
+                attrDtos = attrDtos.stream()
+                    .filter(attr -> StringUtils.isNotEmpty(attr.getObjCode()))
+                    .collect(Collectors.toList());
+                Map<String, List<EmsObjAttrDto>> objAttrMap = attrDtos.stream()
+                    .collect(Collectors.groupingBy(EmsObjAttrDto::getObjCode, Collectors.toList()));
+
+                for (Map.Entry<String, List<EmsObjAttrDto>> entry : objAttrMap.entrySet()) {
+                    String objCode = entry.getKey();
+                    List<EmsObjAttrDto> subDtos = entry.getValue();
+
+                    JsonEntity.ObjBuilder nodeJson = JsonEntity.objBuilder().putKv("objType", objType)
+                        .putKv("objCode", objCode).putKv("modelCode", modelCode);
+
+                    Map<String, List<EmsObjAttrDto>> gpAttrMap = subDtos.stream()
+                        .collect(Collectors.groupingBy(EmsObjAttrDto::getAttrGroup, Collectors.toList()));
+
+                    nodeJson.putMap(gpAttrMap);
+
+                    json.putKv(objCode, nodeJson.build().getJsonObj());
+                }
+            }
+
+            result = success(json.build().getJsonObj());
+        }
+        catch (Exception e) {
+            result = error(e.getMessage());
+        }
+
+        return result;
+    }
+
+    /**
      * 新增能源对象属性
      */
     @Log(title = "能源对象属性", businessType = BusinessType.INSERT)
@@ -147,4 +204,19 @@ public class EmsObjAttrController extends BaseController {
     public AjaxResult remove(@PathVariable Long[] ids) {
         return toAjax(attrService.deleteObjAttrByIds(ids));
     }
+
+    private String getModeCode(Integer objType, String objCode) {
+        String modeCode = null;
+
+        if (objType == DevObjType.DEVC.getCode()) {
+            EmsDevice device = deviceService.selectDeviceByCode(objCode);
+            modeCode = null != device ? device.getDeviceModel() : null;
+        }
+        else if (objType == DevObjType.SYSTEM.getCode()) {
+            EmsSubsystem subsystem = subsystemService.selectEmsSubsystemByCode(objCode);
+            modeCode = null != subsystem ? subsystem.getModelCode() : null;
+        }
+
+        return modeCode;
+    }
 }

+ 2 - 0
ems/ems-cloud/ems-server/src/main/java/com/ruoyi/ems/controller/EmsObjAttrValueController.java

@@ -76,6 +76,8 @@ public class EmsObjAttrValueController extends BaseController {
     @Log(title = "能源对象属性值", businessType = BusinessType.INSERT)
     @PostMapping("/batch")
     public AjaxResult addBatch(@RequestBody List<EmsObjAttrValue> list) {
+        EmsObjAttrValue objAttrValue = list.get(0);
+        objAttrValueService.deleteByObjCode(objAttrValue.getModelCode(), objAttrValue.getObjCode());
         return toAjax(objAttrValueService.insertBatch(list));
     }
 

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

@@ -67,11 +67,6 @@ public class EmsDevice extends BaseEntity {
     private String location;
 
     /**
-     * 安装位置层级
-     */
-    private String locationType;
-
-    /**
      * 归属区域代码
      */
     private String locationRef;
@@ -207,14 +202,6 @@ public class EmsDevice extends BaseEntity {
         this.location = location;
     }
 
-    public String getLocationType() {
-        return locationType;
-    }
-
-    public void setLocationType(String locationType) {
-        this.locationType = locationType;
-    }
-
     public String getLocationRef() {
         return locationRef;
     }
@@ -323,7 +310,6 @@ public class EmsDevice extends BaseEntity {
             .append("deviceSpec", getDeviceSpec())
             .append("deviceStatus", getDeviceStatus())
             .append("location", getLocation())
-            .append("locationType", getLocationType())
             .append("locationRef", getLocationRef())
             .append("locationRefName", getLocationRefName())
             .append("areaCode", getAreaCode())

+ 8 - 9
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAbility.java

@@ -26,8 +26,8 @@ public class EmsObjAbility
     /** 能力描述 */
     private String abilityDesc;
 
-    /** 能力参数 */
-    private String abilityParam;
+    /** 参数定义 */
+    private String paramDefinition;
 
     /** 隐藏标记 */
     private Integer hiddenFlag;
@@ -77,14 +77,13 @@ public class EmsObjAbility
     {
         return abilityDesc;
     }
-    public void setAbilityParam(String abilityParam) 
-    {
-        this.abilityParam = abilityParam;
+
+    public String getParamDefinition() {
+        return paramDefinition;
     }
 
-    public String getAbilityParam() 
-    {
-        return abilityParam;
+    public void setParamDefinition(String paramDefinition) {
+        this.paramDefinition = paramDefinition;
     }
 
     public Integer getHiddenFlag() {
@@ -103,7 +102,7 @@ public class EmsObjAbility
             .append("abilityKey", getAbilityKey())
             .append("abilityName", getAbilityName())
             .append("abilityDesc", getAbilityDesc())
-            .append("abilityParam", getAbilityParam())
+            .append("paramDefinition", getParamDefinition())
             .append("hiddenFlag", getHiddenFlag())
             .toString();
     }

+ 4 - 64
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjAttrDto.java

@@ -11,6 +11,7 @@
 package com.ruoyi.ems.domain;
 
 import com.fasterxml.jackson.annotation.JsonFormat;
+import lombok.Data;
 
 import java.util.Date;
 
@@ -23,7 +24,10 @@ import java.util.Date;
  * @see [相关类/方法]
  * @since [产品/模块版本]
  */
+@Data
 public class EmsObjAttrDto {
+    private String objCode;
+
     private String attrGroup;
 
     /** 属性标识 */
@@ -46,68 +50,4 @@ public class EmsObjAttrDto {
 
     @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     private Date updateTime;
-
-    public String getAttrGroup() {
-        return attrGroup;
-    }
-
-    public void setAttrGroup(String attrGroup) {
-        this.attrGroup = attrGroup;
-    }
-
-    public String getAttrKey() {
-        return attrKey;
-    }
-
-    public void setAttrKey(String attrKey) {
-        this.attrKey = attrKey;
-    }
-
-    public String getAttrName() {
-        return attrName;
-    }
-
-    public void setAttrName(String attrName) {
-        this.attrName = attrName;
-    }
-
-    public String getAttrValue() {
-        return attrValue;
-    }
-
-    public void setAttrValue(String attrValue) {
-        this.attrValue = attrValue;
-    }
-
-    public String getAttrValueName() {
-        return attrValueName;
-    }
-
-    public void setAttrValueName(String attrValueName) {
-        this.attrValueName = attrValueName;
-    }
-
-    public String getAttrUnit() {
-        return attrUnit;
-    }
-
-    public void setAttrUnit(String attrUnit) {
-        this.attrUnit = attrUnit;
-    }
-
-    public Date getUpdateTime() {
-        return updateTime;
-    }
-
-    public void setUpdateTime(Date updateTime) {
-        this.updateTime = updateTime;
-    }
-
-    public String getAttrValueType() {
-        return attrValueType;
-    }
-
-    public void setAttrValueType(String attrValueType) {
-        this.attrValueType = attrValueType;
-    }
 }

+ 1 - 1
ems/ems-core/src/main/java/com/ruoyi/ems/domain/EmsObjEventLog.java

@@ -10,7 +10,7 @@ import java.util.Date;
 import java.util.List;
 
 /**
- * 能源对象上报日志表 adm_ems_obj_report_log
+ * 能源对象上报日志表 adm_ems_obj_event_log
  *
  * @author ruoyi
  * @date 2025-02-27

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

@@ -83,6 +83,14 @@ public interface EmsDeviceMapper {
     int insertEmsDevice(EmsDevice emsDevice);
 
     /**
+     * 新增能源设备
+     *
+     * @param list 能源设备
+     * @return 结果
+     */
+    int insertBatch(List<EmsDevice> list);
+
+    /**
      * 修改能源设备
      *
      * @param emsDevice 能源设备
@@ -106,6 +114,14 @@ public interface EmsDeviceMapper {
      */
     int deleteEmsDeviceByIds(Long[] ids);
 
+    /**
+     * 删除能源设备
+     *
+     * @param deviceCode 模型代码
+     * @return 结果
+     */
+    int deleteEmsDevice(@Param("modelCode") String modelCode, @Param("deviceCode") String deviceCode);
+
     List<Map<String, Object>> cntDeviceStatus(@Param("areaCode") String areaCode);
 
     List<Map<String, Object>> calcDeviceOnlineSummary(@Param("areaCode") String areaCode);

+ 0 - 104
ems/ems-core/src/main/java/com/ruoyi/ems/service/EmsCommonCache.java

@@ -1,104 +0,0 @@
-/*
- * 文 件 名:  EmsCommonCacheImpl
- * 版    权:  华设设计集团股份有限公司
- * 描    述:  <描述>
- * 修 改 人:  lvwenbin
- * 修改时间:  2025/2/13
- * 跟踪单号:  <跟踪单号>
- * 修改单号:  <修改单号>
- * 修改内容:  <修改内容>
- */
-package com.ruoyi.ems.service;
-
-import com.ruoyi.ems.core.BaseCache;
-import com.ruoyi.ems.domain.FacsCategory;
-import com.ruoyi.ems.domain.FacsSubCategory;
-import org.apache.commons.collections4.CollectionUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.ApplicationArguments;
-import org.springframework.boot.ApplicationRunner;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-/**
- * 公共缓存实现类
- * <功能详细描述>
- *
- * @author lvwenbin
- * @version [版本号, 2025/2/13]
- * @see [相关类/方法]
- * @since [产品/模块版本]
- */
-@Service("emsCommonCache")
-public class EmsCommonCache implements BaseCache, ApplicationRunner {
-    private static final Logger log = LoggerFactory.getLogger(EmsCommonCache.class);
-
-    @Autowired
-    private IFacsCategoryService facsCategoryService;
-
-    @Autowired
-    private IFacsSubCategoryService facsSubCategoryService;
-
-    /**
-     * 分类缓存
-     */
-    private Map<String, FacsCategory> facsCategoryCache = new ConcurrentHashMap<>();
-
-    /**
-     * 子分类缓存
-     */
-    private Map<String, FacsSubCategory> facsSubCategoryCache = new ConcurrentHashMap<>();
-
-    @Override
-    public FacsCategory getCategory(String code) {
-        return facsCategoryCache.get(code);
-    }
-
-    /**
-     * 根据编码获取子分类信息
-     *
-     * @param code 编码
-     * @return 子分类信息
-     */
-    @Override
-    public FacsSubCategory getSubCategory(String code) {
-        return facsSubCategoryCache.get(code);
-    }
-
-    @Override
-    public void run(ApplicationArguments args) throws Exception {
-        loadFacsCategory();
-        loadFacsSubCategory();
-    }
-
-    private void loadFacsCategory() {
-        List<FacsCategory> dbList = facsCategoryService.selectCategoryList();
-
-        if (CollectionUtils.isNotEmpty(dbList)) {
-            Map<String, FacsCategory> dbMap = dbList.stream()
-                .collect(Collectors.toMap(FacsCategory::getCode, Function.identity()));
-            facsCategoryCache.putAll(dbMap);
-        }
-
-        log.info("加载设施分类缓存完成,共{}条数据", dbList.size());
-    }
-
-    private void loadFacsSubCategory() {
-        List<FacsSubCategory> dbList = facsSubCategoryService.selectSubCategoryList();
-
-        if (CollectionUtils.isNotEmpty(dbList)) {
-            Map<String, FacsSubCategory> dbMap = dbList.stream()
-                .collect(Collectors.toMap(FacsSubCategory::getCode, Function.identity()));
-            facsSubCategoryCache.putAll(dbMap);
-        }
-
-        log.info("加载设施子分类缓存完成,共{}条数据", dbList.size());
-    }
-}

+ 15 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsDeviceService.java

@@ -79,6 +79,14 @@ public interface IEmsDeviceService {
     int insertEmsDevice(EmsDevice emsDevice);
 
     /**
+     * 新增能源设备
+     *
+     * @param list 能源设备
+     * @return 结果
+     */
+    int insertBatch(List<EmsDevice> list);
+
+    /**
      * 修改能源设备
      *
      * @param emsDevice 能源设备
@@ -102,6 +110,13 @@ public interface IEmsDeviceService {
      */
     int deleteEmsDeviceById(Long id);
 
+    /**
+     * 根据模型删除
+     * @param deviceCode 模型代码
+     * @return 删除数量
+     */
+    int deleteDevice(String modelCode, String deviceCode);
+
     List<Map<String, Object>> cntDeviceStatus(String areaCode);
 
     List<Map<String, Object>> calcDeviceOnlineSummary(String areaCode);

+ 5 - 11
ems/ems-core/src/main/java/com/ruoyi/ems/service/IEmsObjAttrService.java

@@ -38,11 +38,13 @@ public interface IEmsObjAttrService {
 
     /**
      * 查询能源对象属性
-     * @param objType 对象类型
-     * @param objCode 对象编号
+     *
+     * @param modelCode 对象模型
+     * @param objType   对象类型
+     * @param objCode   对象编号
      * @return 能源对象属性集合
      */
-    List<EmsObjAttrDto> selectObjAttrItem(Integer objType, String objCode);
+    List<EmsObjAttrDto> selectObjAttrItem(String modelCode, Integer objType, String objCode);
 
     /**
      * 新增能源对象属性
@@ -77,14 +79,6 @@ public interface IEmsObjAttrService {
     int deleteObjAttrByIds(Long[] ids);
 
     /**
-     * 删除能源对象属性信息
-     *
-     * @param id 能源对象属性主键
-     * @return 结果
-     */
-    int deleteObjAttrById(Long id);
-
-    /**
      * 根据模型编号删除
      *
      * @param modelCode 模型编号

+ 15 - 0
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsDeviceServiceImpl.java

@@ -5,6 +5,8 @@ import java.util.Map;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import com.ruoyi.ems.mapper.EmsObjAttrValueMapper;
+import com.ruoyi.ems.service.IEmsObjAttrService;
 import org.apache.commons.collections4.CollectionUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -30,6 +32,9 @@ public class EmsDeviceServiceImpl implements IEmsDeviceService {
     private EmsDeviceMapper emsDeviceMapper;
 
     @Autowired
+    private EmsObjAttrValueMapper attrValueMapper;
+
+    @Autowired
     private IAreaService areaService;
 
     /**
@@ -106,6 +111,11 @@ public class EmsDeviceServiceImpl implements IEmsDeviceService {
         return emsDeviceMapper.insertEmsDevice(emsDevice);
     }
 
+    @Override
+    public int insertBatch(List<EmsDevice> list) {
+        return emsDeviceMapper.insertBatch(list);
+    }
+
     /**
      * 修改能源设备
      *
@@ -140,6 +150,11 @@ public class EmsDeviceServiceImpl implements IEmsDeviceService {
     }
 
     @Override
+    public int deleteDevice(String modelCode, String deviceCode) {
+        return  emsDeviceMapper.deleteEmsDevice(modelCode,deviceCode);
+    }
+
+    @Override
     public List<Map<String, Object>> cntDeviceStatus(String areaCode) {
         return emsDeviceMapper.cntDeviceStatus(areaCode);
     }

+ 2 - 56
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAttrServiceImpl.java

@@ -1,16 +1,11 @@
 package com.ruoyi.ems.service.impl;
 
-import com.ruoyi.ems.domain.EmsDevice;
 import com.ruoyi.ems.domain.EmsObjAttr;
 import com.ruoyi.ems.domain.EmsObjAttrDto;
 import com.ruoyi.ems.domain.EmsObjAttrEnum;
-import com.ruoyi.ems.domain.EmsSubsystem;
-import com.ruoyi.ems.enums.DevObjType;
 import com.ruoyi.ems.mapper.EmsObjAttrMapper;
-import com.ruoyi.ems.service.IEmsDeviceService;
 import com.ruoyi.ems.service.IEmsObjAttrEnumService;
 import com.ruoyi.ems.service.IEmsObjAttrService;
-import com.ruoyi.ems.service.IEmsSubsystemService;
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -34,12 +29,6 @@ public class EmsObjAttrServiceImpl implements IEmsObjAttrService {
     @Autowired
     private IEmsObjAttrEnumService enumService;
 
-    @Autowired
-    private IEmsDeviceService deviceService;
-
-    @Autowired
-    private IEmsSubsystemService subsystemService;
-
     /**
      * 查询能源对象属性
      *
@@ -104,17 +93,8 @@ public class EmsObjAttrServiceImpl implements IEmsObjAttrService {
     }
 
     @Override
-    public List<EmsObjAttrDto> selectObjAttrItem(Integer objType, String objCode) {
-        List<EmsObjAttrDto> ret = null;
-
-        // 获取对象模型代码
-        String modeCode = getModeCode(objType, objCode);
-
-        if (StringUtils.isNotEmpty(modeCode)) {
-            ret = objAttrMapper.selectObjAttrDto(modeCode, objType, objCode);
-        }
-
-        return ret;
+    public List<EmsObjAttrDto> selectObjAttrItem(String modelCode, Integer objType, String objCode) {
+        return objAttrMapper.selectObjAttrDto(modelCode, objType, objCode);
     }
 
     /**
@@ -178,25 +158,6 @@ public class EmsObjAttrServiceImpl implements IEmsObjAttrService {
         return objAttrMapper.deleteObjAttrByIds(ids);
     }
 
-    /**
-     * 删除能源对象属性信息
-     *
-     * @param id 能源对象属性主键
-     * @return 结果
-     */
-    @Override
-    public int deleteObjAttrById(Long id) {
-        int cnt = 0;
-        EmsObjAttr objAttr = objAttrMapper.selectObjAttrById(id);
-
-        if (null != objAttr) {
-            cnt = objAttrMapper.deleteObjAttrById(id);
-            enumService.deleteByModelCode(objAttr.getModelCode());
-        }
-
-        return cnt;
-    }
-
     @Override
     public int deleteByModelCode(String modelCode) {
         int cnt = objAttrMapper.deleteByModelCode(modelCode);
@@ -213,19 +174,4 @@ public class EmsObjAttrServiceImpl implements IEmsObjAttrService {
             }
         }
     }
-
-    private String getModeCode(Integer objType, String objCode) {
-        String modeCode = null;
-
-        if (objType == DevObjType.DEVC.getCode()) {
-            EmsDevice device = deviceService.selectByCode(objCode);
-            modeCode = null != device ? device.getDeviceModel() : null;
-        }
-        else if (objType == DevObjType.SYSTEM.getCode()) {
-            EmsSubsystem subsystem = subsystemService.selectEmsSubsystemByCode(objCode);
-            modeCode = null != subsystem ? subsystem.getModelCode() : null;
-        }
-
-        return modeCode;
-    }
 }

+ 0 - 2
ems/ems-core/src/main/java/com/ruoyi/ems/service/impl/EmsObjAttrValueServiceImpl.java

@@ -69,8 +69,6 @@ public class EmsObjAttrValueServiceImpl implements IEmsObjAttrValueService {
 
     @Override
     public int insertBatch(List<EmsObjAttrValue> list) {
-        EmsObjAttrValue objAttrValue = list.get(0);
-        objAttrValueMapper.deleteByObjCode(objAttrValue.getModelCode(), objAttrValue.getObjCode());
         return objAttrValueMapper.insertBatch(list);
     }
 

+ 12 - 3
ems/ems-core/src/main/resources/mapper/ems/EmsDeviceMapper.xml

@@ -189,7 +189,6 @@
             <if test="deviceSpec != null">device_spec,</if>
             <if test="deviceStatus != null">device_status,</if>
             <if test="location != null">location,</if>
-            <if test="locationType != null">location_type,</if>
             <if test="locationRef != null">location_ref,</if>
             <if test="areaCode != null">area_code,</if>
             <if test="deviceModel !=null">device_model,</if>
@@ -204,7 +203,6 @@
             <if test="deviceSpec != null">#{deviceSpec},</if>
             <if test="deviceStatus != null">#{deviceStatus},</if>
             <if test="location != null">#{location},</if>
-            <if test="locationType != null">#{locationType},</if>
             <if test="locationRef != null">#{locationRef},</if>
             <if test="areaCode != null">#{areaCode},</if>
             <if test="deviceModel !=null">#{deviceModel},</if>
@@ -214,6 +212,14 @@
         </trim>
     </insert>
 
+    <insert id="insertBatch" parameterType="java.util.List">
+        insert into adm_ems_device (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`)
+        values
+        <foreach collection="list" item="item" index="index" separator=",">
+            (#{item.deviceCode},#{item.deviceName},#{item.deviceBrand},#{item.deviceSpec},#{item.deviceStatus},#{item.location},#{item.locationRef},#{item.areaCode},#{item.deviceModel},#{item.refFacs},#{item.psCode},#{item.subsystemCode})
+        </foreach>
+    </insert>
+
     <update id="updateEmsDevice" parameterType="com.ruoyi.ems.domain.EmsDevice">
         update adm_ems_device
         <trim prefix="SET" suffixOverrides=",">
@@ -223,7 +229,6 @@
             <if test="deviceSpec != null">device_spec = #{deviceSpec},</if>
             <if test="deviceStatus != null">device_status = #{deviceStatus},</if>
             <if test="location != null">location = #{location},</if>
-            <if test="locationType != null">location_type = #{locationType},</if>
             <if test="locationRef != null">location_ref = #{locationRef},</if>
             <if test="areaCode != null">area_code = #{areaCode},</if>
             <if test="deviceModel !=null">device_model = #{deviceModel},</if>
@@ -247,6 +252,10 @@
         </foreach>
     </delete>
 
+    <delete id="deleteEmsDevice" parameterType="String">
+        delete from adm_ems_device where device_code = #{deviceCode} and device_model = #{modelCode}
+    </delete>
+
     <select id="cntDeviceStatus">
         SELECT
         device_status deviceStatus,

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

@@ -10,12 +10,12 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="abilityKey"    column="ability_key"    />
         <result property="abilityName"    column="ability_name"    />
         <result property="abilityDesc"    column="ability_desc"    />
-        <result property="abilityParam"    column="ability_param"    />
+        <result property="paramDefinition"    column="param_definition"    />
         <result property="hiddenFlag"    column="hidden_flag"    />
     </resultMap>
 
     <sql id="selectObjAbilityVo">
-        select id, model_code, ability_key, ability_name, ability_desc, ability_param, hidden_flag from adm_ems_obj_ability
+        select id, model_code, ability_key, ability_name, ability_desc, param_definition, hidden_flag from adm_ems_obj_ability
     </sql>
 
     <select id="selectObjAbilityList" parameterType="com.ruoyi.ems.domain.EmsObjAbility" resultMap="ObjAbilityResult">
@@ -45,7 +45,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="abilityKey != null and abilityKey != ''">ability_key,</if>
             <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="paramDefinition != null">param_definition,</if>
             <if test="hiddenFlag != null">hidden_flag,</if>
          </trim>
         <trim prefix="values (" suffix=")" suffixOverrides=",">
@@ -53,16 +53,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="abilityKey != null and abilityKey != ''">#{abilityKey},</if>
             <if test="abilityName != null and abilityName != ''">#{abilityName},</if>
             <if test="abilityDesc != null">#{abilityDesc},</if>
-            <if test="abilityParam != null">#{abilityParam},</if>
+            <if test="paramDefinition != null">#{paramDefinition},</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, hidden_flag)
+        insert into adm_ems_obj_ability (model_code, ability_key, ability_name, ability_desc, param_definition, hidden_flag)
         values
         <foreach collection="list" item="item" index="index" separator=",">
-            (#{item.modelCode}, #{item.abilityKey}, #{item.abilityName}, #{item.abilityDesc}, #{item.abilityParam}, #{item.hiddenFlag})
+            (#{item.modelCode}, #{item.abilityKey}, #{item.abilityName}, #{item.abilityDesc}, #{item.paramDefinition}, #{item.hiddenFlag})
         </foreach>
     </insert>
 
@@ -73,7 +73,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
             <if test="abilityKey != null and abilityKey != ''">ability_key = #{abilityKey},</if>
             <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="paramDefinition != null">param_definition = #{paramDefinition},</if>
             <if test="hiddenFlag != null">hidden_flag = #{hiddenFlag},</if>
         </trim>
         where id = #{id}

+ 7 - 3
ems/ems-core/src/main/resources/mapper/ems/EmsObjAttrMapper.xml

@@ -15,6 +15,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
     </resultMap>
 
     <resultMap type="com.ruoyi.ems.domain.EmsObjAttrDto" id="ObjAttrDtoResult">
+        <result property="objCode"    column="obj_code"    />
         <result property="attrGroup"    column="attr_group"    />
         <result property="attrKey"    column="attr_key"    />
         <result property="attrName"    column="attr_name"    />
@@ -47,13 +48,16 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
 
     <select id="selectObjAttrDto"  resultMap="ObjAttrDtoResult">
         select
-            a.attr_group, a.attr_key, a.attr_name, v.attr_value, e.attr_value_name, a.attr_unit, a.attr_value_type, v.update_time from  adm_ems_obj_attr a
+            v.obj_code, a.attr_group, a.attr_key, a.attr_name, v.attr_value, e.attr_value_name, a.attr_unit, a.attr_value_type, v.update_time from  adm_ems_obj_attr a
         left join
             (
                select
-                  attr_key, attr_value, update_time
+                   obj_code, attr_key, attr_value, update_time
                from adm_ems_obj_attr_value
-               where model_code = #{modelCode} and obj_code = #{objCode}
+               <where>
+                   model_code = #{modelCode}
+                   <if test="objCode != null and objCode != ''"> and obj_code = #{objCode}</if>
+               </where>
             ) v on a.attr_key = v.attr_key
         join adm_ems_obj_model m on a.model_code = m.model_code and m.obj_type = #{objType}
         left join adm_ems_obj_attr_enum e on a.model_code = e.model_code and a.attr_key = e.attr_key and v.attr_value = e.attr_value

+ 92 - 41
ems/sql/ems_init_data.sql

@@ -165,8 +165,6 @@ INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_sub
 INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('GCC02', '南区-光储充监测', 'W', 'W4', 1, '321283124S3002');
 INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('Charge01', '北区-充电桩监测', 'W', 'W4', 1, '321283124S3001');
 INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('Charge02', '南区-充电桩监测', 'W', 'W4', 1, '321283124S3002');
-INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('ZHZM01', '北区-照明监测', 'W', 'W4', 1, '321283124S3001');
-INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('ZHZM02', '南区-照明监测', 'W', 'W4', 1, '321283124S3002');
 INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('ZHHM01', '北区-海绵监测', 'W', 'W4', 1, '321283124S3001');
 INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('ZHHM02', '南区-海绵监测', 'W', 'W4', 1, '321283124S3002');
 INSERT INTO `adm_ems_facs` (`facs_code`, `facs_name`, `facs_category`, `facs_subcategory`, `enable`, `ref_area`) VALUES ('LG01', '北区-垃圾厨余监测', 'W', 'W4', 1, '321283124S3001');
@@ -202,8 +200,6 @@ INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `dev
 INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('D-N-EVSE-20002', '2号充电桩',    '特来电', 'TCDZ-DCO.7', 1, '南区广场', '321283124S300204', '321283124S3002',  'test', 'Z-FW-02', 'DC-EVSE', 'SYS_CD');
 INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('D-N-EVSE-20003', '3号充电桩',    '特来电', 'TCDZ-DCO.7', 1, '南区广场', '321283124S300204', '321283124S3002',  'test', 'Z-FW-02', 'DC-EVSE', 'SYS_CD');
 INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('D-N-EVSE-20004', '4号充电桩',    '特来电', 'TCDZ-DCO.7', 1, '南区广场', '321283124S300204', '321283124S3002',  'test', 'Z-FW-02', 'DC-EVSE', 'SYS_CD');
-INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('ZHZM-01', '照明01',    'xxx', 'xxx', 1, '北区广场', '321283124S300104', '321283124S3001',  'test', 'Z-ZM-01', NULL, 'SYS_ZHZM');
-INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('ZHZM-02', '照明02',    'xxx', 'xxx', 1, '南区广场', '321283124S300204', '321283124S3002',  'test', 'Z-ZM-02', NULL, 'SYS_ZHZM');
 INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('ZHHM-01', '海绵设备1',    'xxx', 'xxx', 1, '北区广场', '321283124S300104', '321283124S3001',  'test', 'Z-QT-01', NULL, 'SYS_ZHHM');
 INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('ZHHM-02', '海绵设备2',    'xxx', 'xxx', 1, '南区广场', '321283124S300204', '321283124S3002',  'test', 'Z-QT-02', NULL, 'SYS_ZHHM');
 INSERT INTO `adm_ems_device` (`device_code`, `device_name`, `device_brand`, `device_spec`, `device_status`, `location`, `location_ref`, `area_code`, `device_model`, `ref_facs`, `ps_code`, `subsystem_code`) VALUES ('LGCY-01', '厨余垃圾设备1',    'xxx', 'xxx', 1, '北区广场', '321283124S300104', '321283124S3001',  'test', 'Z-QT-01', NULL, 'SYS_LG');
@@ -248,10 +244,18 @@ INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `abilit
 INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `event_handler`) VALUES ('M_TEST', '测试', 3, NULL, NULL);
 
 INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `event_handler`) VALUES ('M_W4_SM_INDOOR_ENERGY', '室内能耗计量终端', 2, 'http://172.17.60.27:9203/ems-dev-adapter/in-door-energy/ct/abilityCall', NULL);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `event_handler`) VALUES ('M_Z010_DEV_SQUARE_LAMP_POST', '智慧灯杆', 2, 'http://172.17.60.27:9203/ems-dev-adapter/square-light-ctl/ct/abilityCall', NULL);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `event_handler`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', '照明灯组', 2, 'http://172.17.60.27:9203/ems-dev-adapter/square-light-ctl/ct/abilityCall', NULL);
+INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `event_handler`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', '照明集中器', 2, 'http://172.17.60.27:9203/ems-dev-adapter/square-light-ctl/ct/abilityCall', NULL);
 INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `event_handler`) VALUES ('M_W2_QF_GEEKOPEN', 'GeekOpen断路器', 2, 'http://172.17.60.27:9203/ems-dev-adapter/circuit-breaker/GeekOpen/abilityCall', NULL);
 INSERT INTO `adm_ems_obj_model` (`model_code`, `model_name`, `obj_type`, `ability_handler`, `event_handler`) VALUES ('M_W2_QS_KEKA_86', 'KEKA开关(86型)', 2, 'http://172.17.60.27:9203/ems-dev-adapter/button-switch/keka/86ButtonSwitchCall', NULL);
 
 -- 对象属性数据
+-- 能耗监测属性
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'Protocol', 'interfaceType', '协议类型', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'Protocol', 'url', '服务地址', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'Protocol', 'appId', 'appId', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'State', 'interfaceStatus', '通道状态', NULL, 'Enum');
 INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SM_INDOOR_ENERGY', 'Base', 'ip', '网络地址', NULL, 'String');
 INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SM_INDOOR_ENERGY', 'Base', 'gateway', '网关地址', NULL, 'String');
 INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SM_INDOOR_ENERGY', 'Base', 'subnetMask', '子网掩码', NULL, 'String');
@@ -260,50 +264,79 @@ INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_na
 INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SM_INDOOR_ENERGY', 'Measure', 'interface3', 'D3口通道', NULL, 'Table');
 INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SM_INDOOR_ENERGY', 'Measure', 'interface4', 'D4口通道', NULL, 'Table');
 
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'Protocol', 'interfaceType', '协议类型', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'Protocol', 'url', '服务地址', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'Protocol', 'appId', 'appId', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W4_SYS_IN_DOOR', 'State', 'interfaceStatus', '通道状态', NULL, 'Enum');
+-- 广场灯控属性
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Protocol', 'interfaceType', '协议类型', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Protocol', 'url', '服务地址', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Protocol', 'clientId', '客户端编号', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Protocol', 'userName', '用户名', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Protocol', 'password', '密码', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'State', 'interfaceStatus', '通道状态', NULL, 'Enum');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Base', 'projectList', '项目列表', NULL, 'Table');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Base', 'projectSubsetList', '分组列表', NULL, 'Table');
+
+-- 灯杆属性
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LAMP_POST', 'Base', 'subDev', '灯组列表', NULL, 'String');
+
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'projectId', '项目ID', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'deviceId', '控制器ID', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'deviceUid', '控制器sn号', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'deviceModelId', '设备型号id', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'minCct', '最小色温', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'maxCct', '最大色温', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'imageUrl', '图片', NULL, 'WebPic');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'abnormal', '设备状态', NULL, 'Enum');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Base', 'csq', '信号强度', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Protocol', 'firmwareVer', '固件版本', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'Protocol', 'softwareVer', '软件版本', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'State', 'cct', '色温', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'State', 'lampOnOff', '开关', NULL, 'Enum');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Measure', 'current', '电流', 'A', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Measure', 'power', '功率', 'W', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Measure', 'factor', '功率因数', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Measure', 'voltage', '电压', 'V', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Measure', 'energy', '总电能', 'kW·h', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Measure', 'frequency', '频率', 'Hz', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'Measure', 'temperature', '设备温度', NULL, 'Value');
+
+
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'Base', 'deviceId', '设备ID', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'Base', 'deviceUid', '设备sn号', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'Base', 'deviceModelId', '设备型号id', NULL, 'String');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'Base', 'imageUrl', '图片', NULL, 'WebPic');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'Base', 'abnormal', '设备状态', NULL, 'Enum');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'Base', 'csq', '信号强度', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'kwh', '有功功率', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'kvarh', '无功功率', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'ua', 'A相电压', 'V', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'ub', 'B相电压', 'V', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'uc', 'C相电压', 'V', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'ia', 'A相电流', 'A', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'ib', 'B相电流', 'A', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'ic', 'C相电流', 'A', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'pfa', 'A相功率因素', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'pfb', 'B相功率因素', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'pfc', 'C相功率因素', NULL, 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'hza', 'A相频率', 'Hz', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'hzb', 'B相频率', 'Hz', 'Value');
+INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'State', 'hzc', 'C相频率', 'Hz', 'Value');
 
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Base', 'version', '固件版本号', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Base', 'iccid', '物联网卡ICCID号', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Base', 'imei', '设备imei', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'State', 'timerEnable', '上报定时开关', '', 'Enum');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'State', 'timerInterval', '上报时间间隔', '秒(S)', 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'State', 'signal', '信号强度', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'State', 'keyLock', '状态-按键锁定', NULL, 'Enum');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'State', 'key', '状态-通断', NULL, 'Enum');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'State', 'resetLock', '重置锁', NULL, 'Enum');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'State', 'onState', '设备上电的默认状态', '1', 'Enum');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Measure', 'power', '实时功率', '瓦(W)', 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Measure', 'voltage', '实时电压', '伏特(V)', 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Measure', 'current', '实时电流', '安培(A)', 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Measure', 'energy', '累计电量值', '千瓦时(kW·h)', 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Protocol', 'protocol', '协议', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Protocol', 'server', 'MQTT地址', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Protocol', 'port', 'MQTT端口', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Protocol', 'clientId', '设备ID', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Protocol', 'username', '用户名', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Protocol', 'subcribe', '订阅主题', NULL, 'Value');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QF_GEEKOPEN', 'Protocol', 'publish', '发布主题', NULL, 'Value');
-
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QS_KEKA_86', 'Base', 'gatewayId', '网关编号', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QS_KEKA_86', 'Protocol', 'protocol', '协议', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QS_KEKA_86', 'Protocol', 'server', 'MQTT地址', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QS_KEKA_86', 'Protocol', 'port', 'MQTT端口', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QS_KEKA_86', 'Protocol', 'publish', '发布主题', NULL, 'String');
-INSERT INTO `adm_ems_obj_attr` (`model_code`, `attr_group`, `attr_key`, `attr_name`, `attr_unit`, `attr_value_type`) VALUES ('M_W2_QS_KEKA_86', 'Protocol', 'subcribe', '订阅主题', NULL, 'String');
 
 INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_W4_SYS_IN_DOOR', 'interfaceStatus', '1', '正常');
 INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_W4_SYS_IN_DOOR', 'interfaceStatus', '0', '断开');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'interfaceStatus', '1', '正常');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'interfaceStatus', '0', '断开');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'abnormal', '0', '正常');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'abnormal', '1', '异常');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'lampOnOff', '0', '关闭');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'lampOnOff', '1', '开启');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'abnormal', '0', '正常');
+INSERT INTO `adm_ems_obj_attr_enum` (`model_code`, `attr_key`, `attr_value`, `attr_value_name`) VALUES ('M_Z010_DEV_SQUARE_CONCENTRATOR', 'abnormal', '1', '异常');
 
 -- 对象属性
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_NHJC', 'M_W4_SYS_IN_DOOR', 'interfaceType', 'http', NULL);
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_NHJC', 'M_W4_SYS_IN_DOOR', 'url', 'http://172.17.50.186:80', NULL);
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_NHJC', 'M_W4_SYS_IN_DOOR', 'appId', 'httpsjy', NULL);
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_NHJC', 'M_W4_SYS_IN_DOOR', 'interfaceStatus', '1', NULL);
-
-
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('ID-E-C-2003', 'M_W4_SM_INDOOR_ENERGY', 'ip', '172.17.50.175', NULL);
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('ID-E-C-2003', 'M_W4_SM_INDOOR_ENERGY', 'gateway', '172.17.50.254', NULL);
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('ID-E-C-2003', 'M_W4_SM_INDOOR_ENERGY', 'subnetMask', '255.255.255.0', NULL);
@@ -351,10 +384,28 @@ INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `att
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('ID-E-C-1007', 'M_W4_SM_INDOOR_ENERGY', 'interface1', '[{"name":"(电表)南区宿舍ALZ","key":"C_1007_AV_0000","value":null,"updateTime":null}]', NULL);
 INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('ID-E-C-1007', 'M_W4_SM_INDOOR_ENERGY', 'interface2', '[{"name":"(电表)南区宿舍ALE","key":"C_1007_AV_0200","value":null,"updateTime":null}]', NULL);
 
--- 对象能力DEMO数据
-INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `ability_param`, `hidden_flag`) VALUES ('M_W4_SYS_IN_DOOR', 'MeterReadingTotal', '全量抄报-网关', '网关-测点批量抄报', null, 1);
-INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `ability_param`, `hidden_flag`) VALUES ('M_W4_SM_INDOOR_ENERGY', 'MeterReadingGw', '实时抄报-网关', '网关-测点批量抄报', null, 1);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'interfaceType', 'http', NULL);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'url', 'http://172.17.60.30:8686', NULL);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'clientId', '5fa30d0e6c8245d550df634eb0cbc326', NULL);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'userName', 'developer3', NULL);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'password', 'dev@admin123', NULL);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'interfaceStatus', '1', NULL);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'projectList', '[{"createTime":"2025-07-25 22:21:16","projectAddress":"未知","projectDeviceNum":196,"projectId":"1948750398922747906","projectName":"智慧照明","projectSubsetNum":4,"remark":"","type":"0"}]', NULL);
+INSERT INTO `adm_ems_obj_attr_value` (`obj_code`, `model_code`, `attr_key`, `attr_value`, `update_time`) VALUES ('SYS_ZHZM', 'M_Z010_SYS_SQUARE_LIGHT', 'projectSubsetList', '[{"subsetDeviceNum":"196","subsetId":"1948750399027605506","subsetName":"分组1"},{"subsetDeviceNum":"0","subsetId":"1948750399090520065","subsetName":"分组2"},{"subsetDeviceNum":"0","subsetId":"1948750399140851713","subsetName":"分组3"},{"subsetDeviceNum":"0","subsetId":"1948750399186989058","subsetName":"分组4"}]', NULL);
+
+
+-- 对象能力数据
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_W4_SYS_IN_DOOR', 'MeterReadingTotal', '全量抄报-网关', '网关-测点批量抄报', null, 1);
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_W4_SM_INDOOR_ENERGY', 'MeterReadingGw', '实时抄报-网关', '网关-测点批量抄报', null, 1);
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'GetProjectList', '同步项目列表', '同步项目列表', null, 1);
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'GetProjectSubsetList', '同步项目分组列表', '同步项目分组列表', null, 1);
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'GetDeviceList', '同步设备列表', '同步设备列表', null, 1);
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_Z010_SYS_SQUARE_LIGHT', 'lightControlAll', '全量开关', '全量开关', '{"type":"Options", "list":[{"key":"全部开灯", "value":"1"},{"key":"全部关灯", "value":"0"}]}', 1);
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'lightControl', '照明开关', '照明开关', '{"type":"Options", "list":[{"key":"开灯", "value":"1"},{"key":"关灯", "value":"0"}]}', 1);
+INSERT INTO `adm_ems_obj_ability` (`model_code`, `ability_key`, `ability_name`, `ability_desc`, `param_definition`, `hidden_flag`) VALUES ('M_Z010_DEV_SQUARE_LIGHT', 'lightControlBrightness', '亮度设置', '亮度设置', '{"type":"Slider", "min":0, "max":100}', 1);
+
 
+-- 对象事件数据
 INSERT INTO `adm_ems_obj_event` (`model_code`, `event_key`, `event_type`, `event_name`, `event_desc`, `event_code`, `ext_event_code`) VALUES ('M_W4_SYS_IN_DOOR', 'connect', 1, '连接恢复', '连接正常', 'M_W4_SYS_IN_DOOR_00', NULL);
 INSERT INTO `adm_ems_obj_event` (`model_code`, `event_key`, `event_type`, `event_name`, `event_desc`, `event_code`, `ext_event_code`) VALUES ('M_W4_SYS_IN_DOOR', 'disconnect', 1, '连接断开', '连接断开', 'M_W4_SYS_IN_DOOR_01', NULL);
 

+ 9 - 25
ems/sql/ems_server.sql

@@ -693,7 +693,7 @@ create table adm_ems_obj_attr  (
   `attr_group`      varchar(128)    not null                     comment '属性分组',
   `attr_key`        varchar(128)    not null                     comment '属性标识',
   `attr_name`       varchar(256)    default null                 comment '属性名称',
-  `attr_unit`       varchar(32)     default null                 comment '属性单位',
+  `attr_unit`       text            default null                 comment '属性单位',
   `attr_value_type` varchar(32)     default null                 comment '属性单位值类型',
   primary key (`id`),
   unique key ux_ems_obj_attr(`model_code`, `attr_key`)
@@ -736,13 +736,13 @@ create table adm_ems_obj_attr_value  (
 -- ----------------------------
 drop table if exists adm_ems_obj_ability;
 create table adm_ems_obj_ability  (
-  `id`              bigint(20)      not null auto_increment      comment '序号',
-  `model_code`      varchar(64)     not null                     comment '模型code',
-  `ability_key`     varchar(128)    not null                     comment '能力键',
-  `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 '隐藏标记',
+  `id`                 bigint(20)      not null auto_increment      comment '序号',
+  `model_code`         varchar(64)     not null                     comment '模型code',
+  `ability_key`        varchar(128)    not null                     comment '能力键',
+  `ability_name`       varchar(256)    default null                 comment '能力名称',
+  `ability_desc`       varchar(1024)   default null                 comment '能力描述',
+  `param_definition`   text            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 = '能源对象能力表';
@@ -761,29 +761,13 @@ create table adm_ems_obj_ability_call_log  (
   `call_payload`    text            default null                 comment '调用参数',
   `call_status`     int             not null                     comment '调用状态',
   `res_time`        datetime        default null                 comment '响应时间',
-  `res_payload`       text            default null                 comment '响应内容',
+  `res_payload`     mediumtext      default null                 comment '响应内容',
   primary key (`id`),
   key i_ability_call_log(`obj_code`, `model_code`, `ability_key`, `call_time`)
 ) engine=innodb auto_increment=1 comment = '能源对象能力调用日志表';
 
 
 -- ----------------------------
--- 能源对象能力调用日志表
--- ----------------------------
-drop table if exists adm_ems_obj_report_log;
-create table adm_ems_obj_report_log  (
-  `id`              bigint(20)      not null auto_increment      comment '序号',
-  `obj_code`        varchar(64)     not null                     comment '对象代码',
-  `model_code`      varchar(64)     not null                     comment '模型code',
-  `msg_desc`        varchar(128)    default null                 comment '消息描述',
-  `report_time`     datetime        not null                     comment '上报时间',
-  `report_payload`  text            default null                 comment '上报参数',
-  primary key (`id`),
-  key i_obj_report_log(`obj_code`, `report_time`)
-) engine=innodb auto_increment=1 comment = '能源对象上报日志表';
-
-
--- ----------------------------
 -- 能源设施事件表
 -- ----------------------------
 drop table if exists adm_ems_obj_event;

+ 134 - 0
prod-common/src/main/java/com/huashe/common/domain/JsonEntity.java

@@ -0,0 +1,134 @@
+/*
+ * 文 件 名:  JsonObj
+ * 版    权:  华设设计集团股份有限公司
+ * 描    述:  <描述>
+ * 修 改 人:  lvwenbin
+ * 修改时间:  2025/9/28
+ * 跟踪单号:  <跟踪单号>
+ * 修改单号:  <修改单号>
+ * 修改内容:  <修改内容>
+ */
+package com.huashe.common.domain;
+
+import com.alibaba.fastjson2.JSONArray;
+import com.alibaba.fastjson2.JSONObject;
+
+import java.util.Map;
+
+/**
+ * JsonEntity
+ * <功能详细描述>
+ *
+ * @author lvwenbin
+ * @version [版本号, 2025/9/28]
+ * @see [相关类/方法]
+ * @since [产品/模块版本]
+ */
+public class JsonEntity<T> {
+
+    private final T jsonObj;
+
+    // 私有构造方法,只能通过Builder创建对象
+    private JsonEntity(JsonEntity.ObjBuilder builder) {
+        this.jsonObj = (T) builder.jsonObject;
+    }
+
+    private JsonEntity(JsonEntity.ArrayBuilder builder) {
+        this.jsonObj = (T) builder.jsonArray;
+    }
+
+    public T getJsonObj() {
+        return jsonObj;
+    }
+
+    // Builder类
+    public static class ObjBuilder {
+        private JSONObject jsonObject = new JSONObject();
+
+        public ObjBuilder() {
+        }
+
+        public JsonEntity.ObjBuilder putKv(String key, Object value) {
+            this.jsonObject.put(key, value);
+            return this;
+        }
+
+        public JsonEntity.ObjBuilder putSubKv(String key, String subKey, Object value) {
+            JSONObject tmpObj = this.jsonObject.getJSONObject(key);
+            tmpObj.put(subKey, value);
+            return this;
+        }
+
+        public JsonEntity.ObjBuilder putMap(Map<? extends String, ?> map) {
+            jsonObject.putAll(map);
+            return this;
+        }
+
+        public JsonEntity.ObjBuilder addKeyArray(String key, Object value) {
+            JSONArray tmpArr = this.jsonObject.getJSONArray(key);
+
+            if (tmpArr == null) {
+                tmpArr = new JSONArray();
+                this.jsonObject.put(key, tmpArr);
+            }
+
+            tmpArr.add(value);
+            return this;
+        }
+
+        /**
+         * 设置resPayload
+         */
+        public JsonEntity.ObjBuilder set(JSONObject jsonObject) {
+            this.jsonObject = jsonObject;
+            return this;
+        }
+
+        /**
+         * 构建CallData对象
+         */
+        public JsonEntity<JSONObject> build() {
+            return new JsonEntity<>(this);
+        }
+    }
+
+    // Builder类
+    public static class ArrayBuilder {
+        private JSONArray jsonArray = new JSONArray();
+
+        public ArrayBuilder() {
+        }
+
+        public JsonEntity.ArrayBuilder addKv(int index, String key, Object value) {
+            JSONObject jsonObject = this.jsonArray.getJSONObject(index);
+            jsonObject.put(key, value);
+            return this;
+        }
+
+        public JsonEntity.ArrayBuilder addKv(String matchKey, String matchVal, String setKey, Object setValue) {
+            jsonArray.forEach(obj -> {
+                JSONObject tmpObj = (JSONObject) obj;
+                if (tmpObj.getString(matchKey).equals(matchVal)) {
+                    tmpObj.put(setKey, setValue);
+                }
+            });
+            return this;
+        }
+
+        /**
+         * 构建CallData对象
+         */
+        public JsonEntity<JSONArray> build() {
+            return new JsonEntity<>(this);
+        }
+    }
+
+    // 用于获取Builder实例的静态方法
+    public static JsonEntity.ObjBuilder objBuilder() {
+        return new JsonEntity.ObjBuilder();
+    }
+
+    public static JsonEntity.ArrayBuilder arraybuilder() {
+        return new JsonEntity.ArrayBuilder();
+    }
+}