Przeglądaj źródła

实时大屏功能常规接口开发基本完成

wangxiaofei 2 miesięcy temu
rodzic
commit
866eccbdb1
23 zmienionych plików z 740 dodań i 535 usunięć
  1. 10 0
      taphole-admin/pom.xml
  2. 5 0
      taphole-admin/src/main/resources/log4j2-spring.xml
  3. 7 4
      taphole-camera/src/main/java/com.sckj.camera/util/LocalDateUtils.java
  4. 4 0
      taphole-common/src/main/java/com/sckj/common/util/TimeUtils.java
  5. 4 0
      taphole-iron/pom.xml
  6. 46 7
      taphole-iron/src/main/java/com/sckj/iron/controller/TIronParamController.java
  7. 53 25
      taphole-iron/src/main/java/com/sckj/iron/controller/TIronVisualScreenController.java
  8. 33 0
      taphole-iron/src/main/java/com/sckj/iron/dto/IronParamDTO.java
  9. 0 23
      taphole-iron/src/main/java/com/sckj/iron/dto/TrendData.java
  10. 10 16
      taphole-iron/src/main/java/com/sckj/iron/entity/TIronParam.java
  11. 15 1
      taphole-iron/src/main/java/com/sckj/iron/entity/TL2Data.java
  12. 59 21
      taphole-iron/src/main/java/com/sckj/iron/service/impl/TIronParamServiceImpl.java
  13. 0 11
      taphole-iron/src/main/java/com/sckj/iron/service/impl/TL2DataServiceImpl.java
  14. 309 284
      taphole-iron/src/main/java/com/sckj/iron/socketio/DeviceEventListener.java
  15. 0 56
      taphole-iron/src/main/java/com/sckj/iron/socketio/IronTrendListener.java
  16. 70 5
      taphole-iron/src/main/java/com/sckj/iron/socketio/PushData.java
  17. 0 15
      taphole-iron/src/main/java/com/sckj/iron/validate/TIronParamUpdateValidate.java
  18. 16 10
      taphole-iron/src/main/java/com/sckj/iron/vo/TIronParamDetailVo.java
  19. 16 10
      taphole-iron/src/main/java/com/sckj/iron/vo/TIronParamListedVo.java
  20. 7 0
      taphole-opc/src/main/java/com/sckj/opc/dto/L2Data.java
  21. 68 45
      taphole-opc/src/main/java/com/sckj/opc/opcua/OPCDAServiceImpl.java
  22. 4 1
      taphole-warn/src/main/java/com/sckj/warn/vo/TExceptionLogDetailVo.java
  23. 4 1
      taphole-warn/src/main/java/com/sckj/warn/vo/TExceptionLogListedVo.java

+ 10 - 0
taphole-admin/pom.xml

@@ -73,6 +73,16 @@
             <groupId>com.sckj</groupId>
             <artifactId>taphole-opc</artifactId>
         </dependency>
+<!--        <dependency>-->
+<!--            <groupId>org.springframework.boot</groupId>-->
+<!--            <artifactId>spring-boot-starter-actuator</artifactId>-->
+<!--            <exclusions>-->
+<!--                <exclusion>-->
+<!--                    <artifactId>log4j-to-slf4j</artifactId>-->
+<!--                    <groupId>org.apache.logging.log4j</groupId>-->
+<!--                </exclusion>-->
+<!--            </exclusions>-->
+<!--        </dependency>-->
 
         <!--<dependency>-->
             <!--<groupId>org.springframework.boot</groupId>-->

+ 5 - 0
taphole-admin/src/main/resources/log4j2-spring.xml

@@ -67,6 +67,11 @@
             <AppenderRef ref="Console"/>
         </Logger>
 
+        <!-- 监控系统信息 -->
+        <Logger name="org.jinterop" level="error" additivity="false">
+            <AppenderRef ref="Console"/>
+        </Logger>
+
         <!-- 初始化日志 -->
         <root level="info">
             <appender-ref ref="Console"/>

+ 7 - 4
taphole-camera/src/main/java/com.sckj.camera/util/LocalDateUtils.java

@@ -1,9 +1,6 @@
 package com.sckj.camera.util;
 
-import java.time.LocalDate;
-import java.time.LocalDateTime;
-import java.time.Period;
-import java.time.ZoneId;
+import java.time.*;
 import java.time.format.DateTimeFormatter;
 import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalUnit;
@@ -29,6 +26,12 @@ public class LocalDateUtils {
         return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
     }
 
+    public static String formatDate(Date date) {
+        Instant instant = date.toInstant();
+        LocalDateTime localDateTime = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
+        return localDateTime.format(DATE_TIME_FORMATTER);
+    }
+
     /**
      * Date 转 LocalDateTime
      *

+ 4 - 0
taphole-common/src/main/java/com/sckj/common/util/TimeUtils.java

@@ -5,8 +5,12 @@ import java.lang.management.ManagementFactory;
 import java.text.DateFormat;
 import java.text.ParsePosition;
 import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
 import java.util.*;
 import java.util.regex.Pattern;
+import java.time.format.DateTimeFormatter;
 
 public class TimeUtils {
 

+ 4 - 0
taphole-iron/pom.xml

@@ -34,6 +34,10 @@
             <groupId>com.sckj</groupId>
             <artifactId>taphole-camera</artifactId>
         </dependency>
+        <dependency>
+            <groupId>com.sckj</groupId>
+            <artifactId>taphole-warn</artifactId>
+        </dependency>
     </dependencies>
 
 </project>

+ 46 - 7
taphole-iron/src/main/java/com/sckj/iron/controller/TIronParamController.java

@@ -2,6 +2,7 @@ package com.sckj.iron.controller;
 
 import com.sckj.common.aop.Log;
 import com.sckj.common.validate.commons.IdValidate;
+import com.sckj.iron.entity.TIronParam;
 import com.sckj.iron.service.impl.TIronParamServiceImpl;
 import com.sckj.iron.validate.TIronParamCreateValidate;
 import com.sckj.iron.validate.TIronParamUpdateValidate;
@@ -14,6 +15,7 @@ import com.sckj.common.core.PageResult;
 import com.sckj.common.validator.annotation.IDMust;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
+import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
@@ -29,15 +31,15 @@ public class TIronParamController {
     TIronParamServiceImpl iTIronParamService;
 
     @GetMapping("/list")
-    @ApiOperation(value="参数设定列表")
+    @ApiOperation(value = "参数设定列表")
     public AjaxResult<PageResult<TIronParamListedVo>> list(@Validated PageValidate pageValidate,
-                                                     @Validated TIronParamSearchValidate searchValidate) {
+                                                           @Validated TIronParamSearchValidate searchValidate) {
         PageResult<TIronParamListedVo> list = iTIronParamService.list(pageValidate, searchValidate);
         return AjaxResult.success(list);
     }
 
     @GetMapping("/detail")
-    @ApiOperation(value="参数设定详情")
+    @ApiOperation(value = "参数设定详情")
     public AjaxResult<TIronParamDetailVo> detail(@Validated @IDMust() @RequestParam("id") Integer id) {
         TIronParamDetailVo detail = iTIronParamService.detail(id);
         return AjaxResult.success(detail);
@@ -45,7 +47,7 @@ public class TIronParamController {
 
     @Log(title = "参数设定新增")
     @PostMapping("/add")
-    @ApiOperation(value="参数设定新增")
+    @ApiOperation(value = "参数设定新增")
     public AjaxResult<Object> add(@Validated @RequestBody TIronParamCreateValidate createValidate) {
         iTIronParamService.add(createValidate);
         return AjaxResult.success();
@@ -53,7 +55,7 @@ public class TIronParamController {
 
     @Log(title = "参数设定编辑")
     @PostMapping("/edit")
-    @ApiOperation(value="参数设定编辑")
+    @ApiOperation(value = "参数设定编辑")
     public AjaxResult<Object> edit(@Validated @RequestBody TIronParamUpdateValidate updateValidate) {
         iTIronParamService.edit(updateValidate);
         return AjaxResult.success();
@@ -61,7 +63,7 @@ public class TIronParamController {
 
     @Log(title = "参数设定删除")
     @PostMapping("/del")
-    @ApiOperation(value="参数设定删除")
+    @ApiOperation(value = "参数设定删除")
     public AjaxResult<Object> del(@Validated @RequestBody IdValidate idValidate) {
         iTIronParamService.del(idValidate.getId());
         return AjaxResult.success();
@@ -69,9 +71,46 @@ public class TIronParamController {
 
     @Log(title = "参数设定批量删除")
     @PostMapping("/del_ex")
-    @ApiOperation(value="参数设定批量删除")
+    @ApiOperation(value = "参数设定批量删除")
     public AjaxResult<Object> del_ex(@RequestBody List<Long> ids) {
         return iTIronParamService.del_ex(ids);
     }
 
+
+    @PostMapping("/getByParamType")
+    @ApiOperation(value = "根据参数类型获取参数列表")
+    public AjaxResult getByParamType(String paramType) {
+        List<TIronParam> list = iTIronParamService.lambdaQuery().eq(TIronParam::getParamType, paramType).list();
+        return AjaxResult.success(list);
+    }
+
+    @GetMapping("/getByParamName")
+    @ApiOperation(value = "根据参数名获取参数列表")
+    public AjaxResult getByParamName(String paramName) {
+        TIronParam ironParam = iTIronParamService.lambdaQuery().eq(TIronParam::getParamName, paramName).one();
+        return AjaxResult.success(ironParam);
+    }
+
+    @PostMapping("/updateByParamName")
+    @ApiOperation(value = "根据参数名更新参数列表")
+    public AjaxResult setByParamName(String paramName, String paramValue) {
+        List<TIronParam> list1 = iTIronParamService.lambdaQuery().eq(TIronParam::getParamName, paramName).list();
+        if (ObjectUtils.isEmpty(list1)) {
+            return AjaxResult.failed("不存在该数据,请确认参数名");
+        }
+        iTIronParamService.lambdaUpdate().eq(TIronParam::getParamName, paramName).set(TIronParam::getParamValue, paramValue);
+        return AjaxResult.success();
+    }
+
+    @Log(title = "更新参数列表")
+    @PostMapping("/updateIronParam")
+    @ApiOperation(value = "更新参数列表")
+    public AjaxResult<Object> updateIronParam(@RequestBody List<TIronParam> ironParamList) {
+        if (ObjectUtils.isEmpty(ironParamList)) {
+            return AjaxResult.failed("传入数据为空!");
+        }
+        iTIronParamService.updateBatchData(ironParamList);
+        return AjaxResult.success();
+    }
+
 }

+ 53 - 25
taphole-iron/src/main/java/com/sckj/iron/controller/TIronVisualScreenController.java

@@ -1,17 +1,18 @@
 package com.sckj.iron.controller;
 
-import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.github.pagehelper.PageHelper;
 import com.sckj.camera.manager.CameraProperties;
 import com.sckj.camera.model.bo.CameraBO;
 import com.sckj.camera.model.entity.Camera;
 import com.sckj.camera.service.CameraServiceImpl;
+import com.sckj.common.aop.Log;
 import com.sckj.common.aop.NotLogin;
 import com.sckj.common.aop.NotPower;
 import com.sckj.common.core.AjaxResult;
 import com.sckj.common.util.RedisUtils;
 import com.sckj.common.validate.commons.PageValidate;
 import com.sckj.iron.dto.CameraDTO;
+import com.sckj.iron.dto.IronParamDTO;
 import com.sckj.iron.entity.TIronParam;
 import com.sckj.iron.entity.TL2Data;
 import com.sckj.iron.service.impl.IronLoginServiceImpl;
@@ -38,6 +39,8 @@ import java.io.IOException;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @Author feng
@@ -153,12 +156,12 @@ public class TIronVisualScreenController {
      *
      * @return
      */
-    @ApiOperation("获取摄像头列表")
-    @PostMapping("/getCameraInfo")
-    public AjaxResult list() {
-        List<Camera> normalCameras = cameraService.lambdaQuery().eq(Camera::getStatus, "1").orderByAsc(Camera::getSort).list();
-        List<Camera> bannerCameras = cameraService.lambdaQuery().eq(Camera::getStatus, "2").orderByAsc(Camera::getSort).list();
-        TIronParam tIronParam = iTIronParamService.lambdaQuery().eq(TIronParam::getParamType, "cameraParam").eq(TIronParam::getParamName, "cameraPlayDuration").one();
+    @ApiOperation("获取摄像头参数信息")
+    @PostMapping("/getCameraParamInfo")
+    public AjaxResult getCameraParamInfo() {
+        List<Camera> normalCameras = cameraService.lambdaQuery().eq(Camera::getType,"1").eq(Camera::getStatus, "1").orderByAsc(Camera::getSort).list();
+        List<Camera> bannerCameras = cameraService.lambdaQuery().eq(Camera::getType,"1").eq(Camera::getStatus, "2").orderByAsc(Camera::getSort).list();
+        TIronParam tIronParam = iTIronParamService.lambdaQuery().eq(TIronParam::getParamType, "camera_param").eq(TIronParam::getParamName, "camera_play_duration").one();
         Map<String, Object> map = new HashMap<>();
         map.put("normalList", normalCameras);
         map.put("bannerList", bannerCameras);
@@ -171,11 +174,11 @@ public class TIronVisualScreenController {
      *
      * @return
      */
-    @ApiOperation("设置摄像头是否轮播、顺序")
+    @ApiOperation("更新摄像头轮播状态、顺序")
     @PostMapping("/updateCamera")
     public AjaxResult updateCamera(@RequestBody List<CameraBO> cameraList) {
         if (ObjectUtils.isEmpty(cameraList)) {
-            return AjaxResult.failed("传入的摄像头列表数据为空");
+            return AjaxResult.failed("传入数据为空!");
         }
         cameraService.updateBatchs(cameraList);
         return AjaxResult.success();
@@ -188,12 +191,12 @@ public class TIronVisualScreenController {
      * @param cameraId 相机信息ID
      * @return ResultDTO
      */
-    @ApiOperation("摄像头播放")
+    @ApiOperation("播放摄像头")
     @PostMapping("/playCamera")
     public AjaxResult playCamera(Long cameraId) {
         Camera camera = cameraService.getById(cameraId);
         if (ObjectUtils.isEmpty(camera)) {
-            return AjaxResult.failed("该摄像头不存在");
+            return AjaxResult.failed("该摄像头不存在!");
         }
         String channelNumberStr = 1 + "02"; //新通道(2012年之后设备,02代表子码流)
         String rtspName = "rtsp://" + camera.getAccount() + ":" + camera.getPassword() + "@" + camera.getIp() + ":554/" + channelNumberStr + "?transportmode=unicast"; //新码流
@@ -204,21 +207,46 @@ public class TIronVisualScreenController {
         return AjaxResult.success(cameraDTO);
     }
 
-    /**
-     * 摄像头登录
-     *
-     * @return
-     */
-    @ApiOperation("设置摄像头轮播参数")
-    @PostMapping("/updateCameraParam")
-    public AjaxResult cameraParamUpdate(Integer cameraPlayDuration) {
-        try {
-            iTIronParamService.lambdaUpdate().eq(TIronParam::getParamType, "cameraParam").eq(TIronParam::getParamName, "cameraPlayDuration")
-                    .set(TIronParam::getParamValue, cameraPlayDuration).update();
-        } catch (Exception e) {
-            e.printStackTrace();
-            return AjaxResult.failed("失败");
+//    /**
+//     * 摄像头登录
+//     *
+//     * @return
+//     */
+//    @ApiOperation("更新摄像头轮播间隔")
+//    @PostMapping("/updateCameraParam")
+//    public AjaxResult updateCameraParam(Integer cameraPlayDuration) {
+//        try {
+//            iTIronParamService.lambdaUpdate().eq(TIronParam::getParamType, "camera_param").eq(TIronParam::getParamName, "camera_play_duration")
+//                    .set(TIronParam::getParamValue, cameraPlayDuration).update();
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//            return AjaxResult.failed("失败");
+//        }
+//        return AjaxResult.success();
+//    }
+
+    @PostMapping("/getIronParams")
+    @ApiOperation(value = "获取出铁参数设置(出铁诊断模型参数:iron_judge,摄像头轮播时长参数:camera_param,大屏趋势图轮播项:iron_trend)")
+    public AjaxResult getIronParam(String paramType) {
+        List<TIronParam> list = iTIronParamService.lambdaQuery().eq(TIronParam::getStatus, "1")
+                .eq(TIronParam::getParamType, paramType).orderByAsc(TIronParam::getSort).list();
+        List<IronParamDTO> collect = list.stream().flatMap((item) -> {
+            IronParamDTO dto = new IronParamDTO();
+            BeanUtils.copyProperties(item, dto);
+            return Stream.of(dto);
+        }).collect(Collectors.toList());
+        return AjaxResult.success(collect);
+    }
+
+
+    @Log(title = "更新出铁参数设置")
+    @PostMapping("/updateIronParams")
+    @ApiOperation(value = "更新出铁参数设置")
+    public AjaxResult<Object> updateIronParam(@RequestBody List<IronParamDTO> ironParamList) {
+        if (ObjectUtils.isEmpty(ironParamList)) {
+            return AjaxResult.failed("传入数据为空!");
         }
+        iTIronParamService.updateBatchs(ironParamList);
         return AjaxResult.success();
     }
 

+ 33 - 0
taphole-iron/src/main/java/com/sckj/iron/dto/IronParamDTO.java

@@ -0,0 +1,33 @@
+package com.sckj.iron.dto;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.io.Serializable;
+
+@Data
+@ApiModel("参数设定实体")
+@TableName("t_iron_param")
+public class IronParamDTO implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    @TableId(value="id", type= IdType.AUTO)
+    @ApiModelProperty(value = "id")
+    private Long id;
+
+    @ApiModelProperty(value = "参数名称")
+    private String paramName;
+
+    @ApiModelProperty(value = "参数值")
+    private String paramValue;
+
+    @ApiModelProperty(value = "参数说明")
+    private String paramDesc;
+
+
+}

+ 0 - 23
taphole-iron/src/main/java/com/sckj/iron/dto/TrendData.java

@@ -1,23 +0,0 @@
-package com.sckj.iron.dto;
-
-import com.sckj.opc.entity.OPCData;
-import lombok.Data;
-import org.springframework.stereotype.Component;
-
-/***
- * 趋势数据
- */
-@Data
-@Component
-public class TrendData {
-    //铁水温度
-    private Object ironTemp;
-
-    //铁水流速1
-    private Object ironSpeed1;
-
-    //铁水流速2
-    private Object ironSpeed2;
-
-
-}

+ 10 - 16
taphole-iron/src/main/java/com/sckj/iron/entity/TIronParam.java

@@ -31,24 +31,9 @@ public class TIronParam implements Serializable {
     private Date updateTime;
 
     @TableId(value="id", type= IdType.AUTO)
-    @ApiModelProperty(value = "")
+    @ApiModelProperty(value = "id")
     private Long id;
 
-//    @ApiModelProperty(value = "开口耗时(s)")
-//    private BigDecimal openHours;
-//
-//    @ApiModelProperty(value = "出铁时间(s)")
-//    private BigDecimal ironTime;
-//
-//    @ApiModelProperty(value = "出铁量(t)")
-//    private BigDecimal ironWeight;
-//
-//    @ApiModelProperty(value = "出铁流速(t/s)")
-//    private BigDecimal ironSpeed;
-//
-//    @ApiModelProperty(value = "铁水温度变化(℃/s)")
-//    private BigDecimal ironwaterTemp;
-
     @ApiModelProperty(value = "铁口区域编号")
     private Long tapholeId;
 
@@ -64,4 +49,13 @@ public class TIronParam implements Serializable {
     @ApiModelProperty(value = "参数值")
     private String paramValue;
 
+    @ApiModelProperty(value = "参数说明")
+    private String paramDesc;
+
+    @ApiModelProperty(value = "状态(1正常 0停用)")
+    private String status;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
+
 }

+ 15 - 1
taphole-iron/src/main/java/com/sckj/iron/entity/TL2Data.java

@@ -2,6 +2,11 @@ package com.sckj.iron.entity;
 
 import com.alibaba.excel.annotation.ExcelIgnore;
 import com.alibaba.excel.annotation.ExcelProperty;
+import com.alibaba.excel.annotation.write.style.ColumnWidth;
+import com.alibaba.excel.annotation.write.style.HeadFontStyle;
+import com.alibaba.excel.annotation.write.style.HeadRowHeight;
+import com.alibaba.excel.annotation.write.style.HeadStyle;
+import com.alibaba.excel.enums.poi.FillPatternTypeEnum;
 import com.baomidou.mybatisplus.annotation.IdType;
 import com.baomidou.mybatisplus.annotation.TableId;
 import com.baomidou.mybatisplus.annotation.TableName;
@@ -12,6 +17,9 @@ import lombok.Data;
 import java.io.Serializable;
 import java.util.Date;
 
+@HeadStyle(fillPatternType = FillPatternTypeEnum.NO_FILL,fillForegroundColor = -1)
+@HeadFontStyle(fontHeightInPoints = 16)
+@HeadRowHeight(40)
 @Data
 @ApiModel("L2数据")
 @TableName("t_l2_data")
@@ -34,22 +42,27 @@ public class TL2Data implements Serializable {
 
     @ApiModelProperty(value = "铁口区域编号")
     @ExcelProperty("铁口区域编号")
+    @ColumnWidth(25)
     private Long tapholeId;
 
     @ApiModelProperty(value = "出铁次数编号")
     @ExcelProperty("出铁次数编号")
+    @ColumnWidth(25)
     private String ironNo;
 
     @ApiModelProperty(value = "出铁时间")
     @ExcelProperty("出铁时间")
+    @ColumnWidth(25)
     private String ironCosttime;
 
     @ApiModelProperty(value = "实际出铁量")
     @ExcelProperty("实际出铁量")
+    @ColumnWidth(25)
     private Double ironWeight;
 
     @ApiModelProperty(value = "实际渣量")
     @ExcelProperty("实际渣量")
+    @ColumnWidth(25)
     private String slagWeight;
 
     @ApiModelProperty(value = "铁水平均温度")
@@ -74,13 +87,14 @@ public class TL2Data implements Serializable {
 
     @ApiModelProperty(value = "开始时间")
     @ExcelProperty("开始时间")
+    @ColumnWidth(25)
     private String ironStarttime;
 
     @ExcelProperty("结束时间")
+    @ColumnWidth(25)
     @ApiModelProperty(value = "结束时间")
     private String ironEndtime;
 
-
     @ApiModelProperty(value = "碳")
     @ExcelIgnore
     private String elementC;

+ 59 - 21
taphole-iron/src/main/java/com/sckj/iron/service/impl/TIronParamServiceImpl.java

@@ -1,13 +1,16 @@
 package com.sckj.iron.service.impl;
 
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
 import com.baomidou.mybatisplus.core.metadata.IPage;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.sckj.common.TapholeAdminThreadLocal;
 import com.sckj.common.core.AjaxResult;
 import com.sckj.common.core.PageResult;
+import com.sckj.common.exception.OperateException;
 import com.sckj.common.validate.commons.PageValidate;
+import com.sckj.iron.dto.IronParamDTO;
 import com.sckj.iron.entity.TIronParam;
 import com.sckj.iron.mapper.TIronParamMapper;
 import com.sckj.iron.validate.TIronParamCreateValidate;
@@ -15,8 +18,10 @@ import com.sckj.iron.validate.TIronParamSearchValidate;
 import com.sckj.iron.validate.TIronParamUpdateValidate;
 import com.sckj.iron.vo.TIronParamDetailVo;
 import com.sckj.iron.vo.TIronParamListedVo;
+import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.Assert;
 import org.springframework.util.CollectionUtils;
 
@@ -27,39 +32,40 @@ import java.util.List;
 
 /**
  * 参数设定实现类
+ *
  * @author zhnaghao
  */
 @Service
 public class TIronParamServiceImpl extends ServiceImpl<TIronParamMapper, TIronParam> {
-        
+
     @Resource
     TIronParamMapper tIronParamMapper;
 
     /**
      * 参数设定列表
      *
-     * @author zhnaghao
-     * @param pageValidate 分页参数
+     * @param pageValidate   分页参数
      * @param searchValidate 搜索参数
      * @return PageResult<TIronParamListedVo>
+     * @author zhnaghao
      */
     public PageResult<TIronParamListedVo> list(PageValidate pageValidate, TIronParamSearchValidate searchValidate) {
-        Integer page  = pageValidate.getPageNo();
+        Integer page = pageValidate.getPageNo();
         Integer limit = pageValidate.getPageSize();
 
         QueryWrapper<TIronParam> queryWrapper = new QueryWrapper<>();
         queryWrapper.orderByDesc("id");
 
         tIronParamMapper.setSearch(queryWrapper, searchValidate, new String[]{
-            "=:kkhs:str",
-            "=:ctsj:str",
-            "=:ctl:str",
+                "=:kkhs:str",
+                "=:ctsj:str",
+                "=:ctl:str",
         });
 
         IPage<TIronParam> iPage = tIronParamMapper.selectPage(new Page<>(page, limit), queryWrapper);
 
         List<TIronParamListedVo> list = new LinkedList<>();
-        for(TIronParam item : iPage.getRecords()) {
+        for (TIronParam item : iPage.getRecords()) {
             TIronParamListedVo vo = new TIronParamListedVo();
             BeanUtils.copyProperties(item, vo);
             list.add(vo);
@@ -71,15 +77,15 @@ public class TIronParamServiceImpl extends ServiceImpl<TIronParamMapper, TIronPa
     /**
      * 参数设定详情
      *
-     * @author zhnaghao
      * @param id 主键参数
      * @return TIronParam
+     * @author zhnaghao
      */
     public TIronParamDetailVo detail(Integer id) {
         TIronParam model = tIronParamMapper.selectOne(
                 new QueryWrapper<TIronParam>()
-                    .eq("id", id)
-                    .last("limit 1"));
+                        .eq("id", id)
+                        .last("limit 1"));
 
         Assert.notNull(model, "数据不存在");
 
@@ -91,8 +97,8 @@ public class TIronParamServiceImpl extends ServiceImpl<TIronParamMapper, TIronPa
     /**
      * 参数设定新增
      *
-     * @author zhnaghao
      * @param createValidate 参数
+     * @author zhnaghao
      */
     public void add(TIronParamCreateValidate createValidate) {
         TIronParam model = new TIronParam();
@@ -107,14 +113,14 @@ public class TIronParamServiceImpl extends ServiceImpl<TIronParamMapper, TIronPa
     /**
      * 参数设定编辑
      *
-     * @author zhnaghao
      * @param updateValidate 参数
+     * @author zhnaghao
      */
     public void edit(TIronParamUpdateValidate updateValidate) {
         TIronParam model = tIronParamMapper.selectOne(
                 new QueryWrapper<TIronParam>()
-                    .eq("id",  updateValidate.getId())
-                    .last("limit 1"));
+                        .eq("id", updateValidate.getId())
+                        .last("limit 1"));
 
         Assert.notNull(model, "数据不存在!");
 
@@ -129,14 +135,14 @@ public class TIronParamServiceImpl extends ServiceImpl<TIronParamMapper, TIronPa
     /**
      * 参数设定删除
      *
-     * @author zhnaghao
      * @param id 主键ID
+     * @author zhnaghao
      */
     public void del(Integer id) {
         TIronParam model = tIronParamMapper.selectOne(
                 new QueryWrapper<TIronParam>()
-                    .eq("id", id)
-                    .last("limit 1"));
+                        .eq("id", id)
+                        .last("limit 1"));
 
         Assert.notNull(model, "数据不存在!");
 
@@ -146,19 +152,51 @@ public class TIronParamServiceImpl extends ServiceImpl<TIronParamMapper, TIronPa
     /**
      * 参数设定批量删除
      *
-     * @author zhanghao
      * @param ids 主键数组
+     * @author zhanghao
      */
-    public AjaxResult<Object> del_ex(List<Long> ids){
+    public AjaxResult<Object> del_ex(List<Long> ids) {
         List<TIronParam> models = tIronParamMapper.selectList(
                 new QueryWrapper<TIronParam>()
                         .in("id", ids));
 
-        if (CollectionUtils.isEmpty(models)){
+        if (CollectionUtils.isEmpty(models)) {
             return AjaxResult.failed("数据不存在");
         }
         tIronParamMapper.delete(new QueryWrapper<TIronParam>().in("id", ids));
         return AjaxResult.success();
     }
 
+
+    @Transactional
+    public void updateBatchs(List<IronParamDTO> paramList) {
+        for (IronParamDTO ironParam : paramList) {
+            TIronParam queryData = getById(ironParam.getId());
+            if (ObjectUtils.isEmpty(queryData)) {
+                throw new OperateException(String.format("传入的ID不存在:%s", ironParam.getId()));
+            }
+            LambdaUpdateWrapper<TIronParam> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(TIronParam::getId, ironParam.getId());
+            if (ObjectUtils.isNotEmpty(ironParam.getParamValue())) {
+                wrapper.set(TIronParam::getParamValue, ironParam.getParamValue());
+            }
+            update(wrapper);
+        }
+    }
+
+    public void updateBatchData(List<TIronParam> paramList) {
+        for (TIronParam ironParam : paramList) {
+            TIronParam queryData = getById(ironParam.getId());
+            if (ObjectUtils.isEmpty(queryData)) {
+                throw new OperateException(String.format("传入的ID不存在:%s", ironParam.getId()));
+            }
+            LambdaUpdateWrapper<TIronParam> wrapper = new LambdaUpdateWrapper<>();
+            wrapper.eq(TIronParam::getId, ironParam.getId());
+            if (ObjectUtils.isNotEmpty(ironParam.getParamValue())) {
+                wrapper.set(TIronParam::getParamValue, ironParam.getParamValue());
+            }
+            update(wrapper);
+        }
+    }
+
 }

+ 0 - 11
taphole-iron/src/main/java/com/sckj/iron/service/impl/TL2DataServiceImpl.java

@@ -37,17 +37,6 @@ public class TL2DataServiceImpl extends ServiceImpl<TL2DataMapper, TL2Data> {
      * 获取最新6条数据
      * @return
      */
-    public List<TL2Data> getLatest6Data() {
-        LambdaQueryWrapper<TL2Data> queryWrapper = new LambdaQueryWrapper<>();
-        queryWrapper.isNotNull(TL2Data::getIronEndtime).orderByDesc(TL2Data::getIronNo).last("limit 6");
-        List<TL2Data> list = list(queryWrapper);
-        return list;
-    }
-
-    /***
-     * 获取最新6条数据
-     * @return
-     */
     public List<TL2Data> queryIronData(TL2Data tl2Data) {
         QueryWrapper<TL2Data> queryWrapper = new QueryWrapper<>();
         queryWrapper.lambda()

+ 309 - 284
taphole-iron/src/main/java/com/sckj/iron/socketio/DeviceEventListener.java

@@ -5,21 +5,24 @@ import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.corundumstudio.socketio.SocketIOClient;
 import com.corundumstudio.socketio.annotation.OnEvent;
 import com.google.common.eventbus.Subscribe;
+import com.sckj.camera.util.LocalDateUtils;
 import com.sckj.common.core.AjaxResult;
 import com.sckj.common.eventbus.EventListener;
 import com.sckj.common.socketio.SocketUtil;
 import com.sckj.common.util.RedisUtils;
 import com.sckj.iron.dto.IronStepDTO;
 import com.sckj.iron.dto.RealtimeData;
-import com.sckj.iron.dto.TrendData;
 import com.sckj.iron.entity.TIronData;
+import com.sckj.iron.entity.TIronParam;
 import com.sckj.iron.entity.TL2Data;
 import com.sckj.iron.service.impl.*;
 import com.sckj.iron.vo.IronStepVO;
 import com.sckj.opc.dto.L2Data;
 import com.sckj.opc.entity.OPCData;
 import com.sckj.opc.opcua.L2DataServiceImpl;
+import com.sckj.opc.opcua.OPCDAServiceImpl;
 import com.sckj.opc.service.OPCDataServiceImpl;
+import com.sckj.warn.service.ITExceptionLogService;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.springframework.beans.BeanUtils;
@@ -33,6 +36,9 @@ import javax.annotation.Resource;
 import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 /**
  * @Author feng
@@ -68,47 +74,17 @@ public class DeviceEventListener extends EventListener {
     TL2DataServiceImpl tl2DataService;
 
     @Resource
-    private L2DataServiceImpl l2DataServiceImpl;
+    L2DataServiceImpl l2DataServiceImpl;
 
     @Resource
     OPCDataServiceImpl opcDataService;
 
-    //实时数据
-    Map<String, Object> mRealtimeData = new HashMap<>();
-
-    //实时状态
-    Map<String, Object> mRealtimeStatus = new HashMap<>();
-
-
     @Resource
-    TrendData trendData;
-
-    //L1
-    private OPCData mOPCData;
-
-    //L2
-    private L2Data mL2Data;
-
-    // 1.创建表达式解析器
-    private SpelExpressionParser parser = new SpelExpressionParser();
-
-    // 2.创建变量上下文,设置变量
-    private StandardEvaluationContext mContext = new StandardEvaluationContext();
-
-    //出铁步骤
-    private List<IronStepVO> mSteps;
-
-    private static final String NODE = "node";
+    ITExceptionLogService iTExceptionLogService;
 
-    //定时器,用于铁口开口超时记录
-    private Timer timer = new Timer();
+    @Resource
+    OPCDAServiceImpl opcdaService;
 
-    //是否出铁中
-    //1 出铁中    0 出铁结束
-    private boolean ironLoading1 = false;
-    private boolean ironLoading2 = false;
-    private boolean ironLoading3 = false;
-    private boolean ironLoading4 = false;
 
     //1号出铁状态标记
     private static final String TAG_TAPHOLE1_STATUS = "AOD25606.PV";
@@ -135,12 +111,6 @@ public class DeviceEventListener extends EventListener {
     //铁量差计算
     private static final String tlc = "tlc";
 
-    //最近任一铁口出铁结束时间
-    private Date lastIronEndTimeRecently;
-
-    @Resource(name = "taskExecutor")
-    ThreadPoolTaskExecutor taskExecutor;
-
     //铁水成分
     public static final String IRON_ELEMENT = "ironElement";
     //铁水温度
@@ -163,10 +133,58 @@ public class DeviceEventListener extends EventListener {
     //预计出铁结束时间
     private static final String PLAN_END_TIME = "planEndTime";
 
+    //实时数据
+    Map<String, Object> mRealtimeData = new ConcurrentHashMap<>();
+
+    //实时状态
+    Map<String, Object> mRealtimeStatus = new ConcurrentHashMap<>();
+
+    // 1.创建表达式解析器
+    private SpelExpressionParser parser = new SpelExpressionParser();
+
+    // 2.创建变量上下文,设置变量
+    private StandardEvaluationContext mContext = new StandardEvaluationContext();
+
+    //出铁步骤
+    private List<IronStepVO> mSteps;
+
+    //出铁参数
+    private Map<String, TIronParam> mIronParamMap;
+
+    private static final String NODE = "node";
+
+    //定时器,用于铁口开口超时记录
+    private Timer timer = new Timer();
+
+    //是否出铁中
+    //1 出铁中    0 出铁结束
+    private boolean ironLoading1 = false;
+    private boolean ironLoading2 = false;
+    private boolean ironLoading3 = false;
+    private boolean ironLoading4 = false;
+
+    //最近任一铁口出铁结束时间
+    private Date mIronEndTimeRecently;
+
+    @Resource(name = "taskExecutor")
+    ThreadPoolTaskExecutor taskExecutor;
+
+    private float speed1, speed2;
 
     @PostConstruct
     public void init() {
+        timer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                opcdaService.subscribeAvailable();
+            }
+        }, 10 * 1000);
         mSteps = ironStepService.getTreeSteps();
+        List<TIronParam> mIronParams = ironParamService.lambdaQuery().eq(TIronParam::getStatus, "1").eq(TIronParam::getParamType, "iron_judge").orderByAsc(TIronParam::getSort).list();
+        if (ObjectUtils.isNotEmpty(mIronParams)) {
+            mIronParamMap = mIronParams.stream()
+                    .collect(Collectors.toMap(TIronParam::getParamName, ironParam -> ironParam, (existing, replacement) -> existing));
+        }
     }
 
     /***
@@ -175,20 +193,17 @@ public class DeviceEventListener extends EventListener {
      */
     @Subscribe
     public void onMessageEvent(OPCData opcData) {
-        if (SocketUtil.clientUserIds.isEmpty()) {
-            return;
-        }
-        this.mOPCData = opcData;
         //异步保存OPC数据
-        taskExecutor.submit(() -> opcDataService.save(mOPCData));
+        taskExecutor.submit(() -> {
+            opcDataService.save(opcData);
+        });
         //出铁操作
-        operate();
-
-        //趋势数据
-        trenddata();
+        taskExecutor.submit(() -> operate(opcData));
 
         //实时数据
-        realtime();
+        taskExecutor.submit(() -> {
+            setRealtimeDataAndStatus(opcData, null);
+        });
 
     }
 
@@ -198,110 +213,225 @@ public class DeviceEventListener extends EventListener {
      */
     @Subscribe
     public void onL2MessageEvent(L2Data l2Data) {
-        if (SocketUtil.clientUserIds.isEmpty()) {
-            return;
-        }
-        this.mL2Data = l2Data;
-        realtime();
-
         TL2Data tl2Data = new TL2Data();
         //出铁操作
         BeanUtils.copyProperties(l2Data, tl2Data);
-
         //将L2实时数据保存到数据库
-        tl2DataService.saveOrUpdate(tl2Data);
-
+        taskExecutor.submit(() -> {
+            tl2DataService.saveOrUpdate(tl2Data);
+        });
         //将L2实时数据保存到Redis
-        RedisUtils.addFixedElement(IRON_ELEMENT, l2Data, 6);
-
-        for (IronStepVO stepDTO : mSteps) {
-            if (NODE.equalsIgnoreCase(stepDTO.getNodeType())) {
-                //处理子项
-                for (IronStepVO child : stepDTO.getChilds()) {
-                    if (tlc.equals(child.getIdentifier())) {
-                        List<TL2Data> latest2Data = tl2DataService.getLatest2Data();
-                        if (latest2Data.size() >= 2) {
-                            HashMap[] hashMaps = new HashMap[6];
-                            child.setExtraInfo(hashMaps);
-                            //理论出铁量 = 矿批 × 综合品位 × 1.06
-                            //铁量差 = 理论出铁量 - 实际出铁量
-                            TL2Data tl2Data1Last = latest2Data.get(0);
-                            double llLast = tl2Data1Last.getTotalDry() * 1.0 * 1.06;
-                            double ironWeightLast = tl2Data1Last.getIronWeight();
-                            double tlcLast = llLast - ironWeightLast;
-
-                            TL2Data tl2Data1LastLast = latest2Data.get(1);
-                            double llLastLast = tl2Data1LastLast.getTotalDry() * 1.0 * 1.06;
-                            double ironWeightLastLast = tl2Data1Last.getIronWeight();
-                            double tlcLastLast = llLastLast - ironWeightLastLast;
-
-                            //铁量差在合理范围内
-                            // 上一次铁量差:-30       上上次铁量差:20 t
-                            // 理论出铁量:1500 t      理论出铁量:1400 t
-                            // 实际出铁量:1530 t      实际出铁量: 1380 t
-                            final String sctlc = "sctlc";
-                            final String ssctlc = "ssctlc";
-                            final String scll = "scll";
-                            final String sscll = "sscll";
-                            final String scsj = "scsj";
-                            final String sscsj = "sscsj";
-
-                            //child.setPassResult(1);
-                            for (IronStepVO childChild : child.getChilds()) {
-                                if (sctlc.equals(childChild.getIdentifier())) {
-                                    childChild.setData(tlcLast);
-                                } else if (ssctlc.equals(childChild.getIdentifier())) {
-                                    childChild.setData(tlcLastLast);
-                                } else if (scll.equals(childChild.getIdentifier())) {
-                                    childChild.setData(llLast);
-                                } else if (sscll.equals(childChild.getIdentifier())) {
-                                    childChild.setData(llLastLast);
-                                } else if (scsj.equals(childChild.getIdentifier())) {
-                                    childChild.setData(ironWeightLast);
-                                } else if (sscsj.equals(childChild.getIdentifier())) {
-                                    childChild.setData(ironWeightLastLast);
+        taskExecutor.submit(() -> {
+            RedisUtils.addFixedElement(IRON_ELEMENT, l2Data, 6);
+            PushData.send2TrendIronElement(RedisUtils.getFixedElement(IRON_ELEMENT));
+        });
+
+        taskExecutor.submit(() -> {
+            setRealtimeDataAndStatus(null, l2Data);
+        });
+
+        taskExecutor.submit(() -> {
+
+            for (IronStepVO stepDTO : mSteps) {
+                if (NODE.equalsIgnoreCase(stepDTO.getNodeType())) {
+                    //处理子项
+                    for (IronStepVO child : stepDTO.getChilds()) {
+                        if (tlc.equals(child.getIdentifier())) {
+                            List<TL2Data> latest2Data = tl2DataService.getLatest2Data();
+                            if (latest2Data.size() >= 2) {
+                                HashMap[] hashMaps = new HashMap[6];
+                                child.setExtraInfo(hashMaps);
+                                //理论出铁量 = 矿批 × 综合品位 × 1.06
+                                //铁量差 = 理论出铁量 - 实际出铁量
+                                TL2Data tl2Data1Last = latest2Data.get(0);
+                                double llLast = tl2Data1Last.getTotalDry() * 1.0 * 1.06;
+                                double ironWeightLast = tl2Data1Last.getIronWeight();
+                                double tlcLast = llLast - ironWeightLast;
+
+                                TL2Data tl2Data1LastLast = latest2Data.get(1);
+                                double llLastLast = tl2Data1LastLast.getTotalDry() * 1.0 * 1.06;
+                                double ironWeightLastLast = tl2Data1Last.getIronWeight();
+                                double tlcLastLast = llLastLast - ironWeightLastLast;
+
+                                //铁量差在合理范围内
+                                // 上一次铁量差:-30       上上次铁量差:20 t
+                                // 理论出铁量:1500 t      理论出铁量:1400 t
+                                // 实际出铁量:1530 t      实际出铁量: 1380 t
+                                final String sctlc = "sctlc";
+                                final String ssctlc = "ssctlc";
+                                final String scll = "scll";
+                                final String sscll = "sscll";
+                                final String scsj = "scsj";
+                                final String sscsj = "sscsj";
+
+                                //child.setPassResult(1);
+                                for (IronStepVO childChild : child.getChilds()) {
+                                    if (sctlc.equals(childChild.getIdentifier())) {
+                                        childChild.setData(tlcLast);
+                                    } else if (ssctlc.equals(childChild.getIdentifier())) {
+                                        childChild.setData(tlcLastLast);
+                                    } else if (scll.equals(childChild.getIdentifier())) {
+                                        childChild.setData(llLast);
+                                    } else if (sscll.equals(childChild.getIdentifier())) {
+                                        childChild.setData(llLastLast);
+                                    } else if (scsj.equals(childChild.getIdentifier())) {
+                                        childChild.setData(ironWeightLast);
+                                    } else if (sscsj.equals(childChild.getIdentifier())) {
+                                        childChild.setData(ironWeightLastLast);
+                                    }
                                 }
+
                             }
                         }
                     }
                 }
             }
-        }
-        setStepResult(mSteps);
+            setStepResult(mSteps);
+            PushData.send2Operation(mSteps, ironLoading1);
+        });
+
     }
 
+    //1号铁口正在出铁的操作项目
+    private void taphole1Start(L2Data mL2Data) {
+        //通过“预判和确认出铁”标记开始出铁
+        boolean isReady = false;
+
+        for (IronStepVO stepDTO : mSteps) {
+            if (ypqrct.equalsIgnoreCase(stepDTO.getIdentifier()) && 1 == stepDTO.getPassResult()) {
+                isReady = true;
+                break;
+            }
+        }
+
+        //炉前在接受到炉内出铁要求后,10分钟内打开铁口,未打开系统告警并记录
+        if (isReady) {
+            TimerTask task = new TimerTask() {
+                @Override
+                public void run() {
+                    System.out.println("倒计时结束!10分钟已到。");
+                    timer.cancel(); // 终止定时器
+                    // 出铁预警,打开系统告警并记录
+                    PushData.send2Warn("请立即打开铁口");
+                    log.info("准备出铁但是未及时出铁口,此处数据库记录");
+                }
+            };
+
+            // 倒计时10分钟(600秒)
+            long delay = 10 * 60 * 1000; // 10分钟转换为毫秒
+            // 在指定延迟后执行任务
+            timer.schedule(task, delay);
+        }
+
 
-    //趋势数据
-    private void trenddata() {
+        //由 0 -> 1 表明1号铁口开始出铁
         //
+        //根据理论铁量、实时铁水流速,推测距离出铁结束的剩余时间
+        //剩余时间=总时间-已经流去的时间
+//                mContext.lookupVariable("");
+        //计算理论铁量= 矿批 × 综合品位 × 1.06,其中矿批是指L2中的干量
+
+//      Date ironTime = mOPCData.getServerTime();
+//      lastIronEndTimeRecently
+        //获取总干量
+        BigDecimal totalDry = new BigDecimal(ObjectUtils.defaultIfNull(mL2Data.getTotalDry(), "0"));
+        //计算出理论铁量
+        BigDecimal multiply = totalDry.multiply(new BigDecimal(1.0)).multiply(new BigDecimal(1.0));
+        //
+        float totalSpeed = speed1 + speed2;
+        if (totalSpeed > 0) {
+            //理论时间
+            BigDecimal divide = multiply.divide(new BigDecimal(totalSpeed), 2, BigDecimal.ROUND_HALF_UP);
+            String plainString = divide.toPlainString();
+            log.info("理论出铁时间:{}min", plainString);
+        }
+
+        //开始计算打泥量,通过打泥量公式
+        //打泥量公式关联因素:铁口深度、钻杆直径、
+        //
+
+        timer.schedule(new TimerTask() {
+            @Override
+            public void run() {
+                //堵口预警
+                if (speed1 > 20 || speed2 > 20) {
+                    /// 流速过大可能是由于铁口深度不足或发生跑大流问题,则提示将当前铁口堵口
+                    PushData.send2Warn("流速过快,堵口");
+                } else if ((speed1 < 20 || speed2 < 20) && (ironLoading2 || ironLoading3 || ironLoading4)) {
+                    //若流速过小,但其它铁口正在出铁,则提示将当前铁口堵口
+                    PushData.send2Warn("当前铁口堵口");
+                } else if ((speed1 < 20 || speed2 < 20) && (!ironLoading2 && !ironLoading3 && !ironLoading4)) {
+                    //若流速过小且其他铁口均未出铁,则提示先将其它铁口打开,再进行堵口
+                    PushData.send2Warn("先将其它铁口打开,再进行堵口");
+                }
+            }
+        }, 10 * 60 * 1000);
+
+
+    }
+
+    //1号铁口结束出铁的操作项目
+    private void taphole1End() {
+        //由 1-> 0 表明1号铁口结束出铁
+        totalWeight = BigDecimal.ZERO;
+        try {
+            timer.cancel(); // 终止定时器
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        recordAfter();
+        recordBlock();
+
+        //出铁结束后,查询最近两次的数据
+        LambdaQueryWrapper<TIronData> queryWrapper = new QueryWrapper<TIronData>().lambda().orderByDesc(TIronData::getCtcsbh);
+        List<TIronData> oldIronDataList = ironDataService.list(queryWrapper);
+
+        //开始出铁诊断
+        //获取开口耗时、出铁时间、实际出铁量、平均铁水流速、平均铁水温度等数据,进行阈值判定,诊断出铁是否正常
+
+        //1分钟延迟
+
+    }
+
+    //出铁后,记录炉次、开口时间、鱼雷罐车车号、铁口深度、铁水流速
+    private void recordAfter() {
+        ironAfterService.add(null);
+    }
 
+    //堵口后,记录堵口时间、出铁量,打泥量、是否喷溅、是否跑泥
+    private void recordBlock() {
+        ironBlockService.add(null);
     }
 
 
-    //实时数据显示
-    private void realtime() {
+    private BigDecimal totalWeight = BigDecimal.ZERO;
+
+
+    /***
+     * 设置实时数据值和状态
+     */
+    private synchronized void setRealtimeDataAndStatus(OPCData opcData, L2Data l2Data) {
         //铁水温度
         //铁水流速
         //铁水成分
         //铁水流量
         //WI5401.PV  1TH-1号车总重
         //WI5402.PV  1TH-2号车TPC总重
-        if (ObjectUtils.isNotEmpty(mOPCData)) {
-            if (mOPCData.getPointName().contains(TAG_IRON_TEMP)) {
+        if (ObjectUtils.isNotEmpty(opcData)) {
+            if (opcData.getPointName().contains(TAG_IRON_TEMP)) {
                 RealtimeData realtimeData = new RealtimeData();
-                realtimeData.setValue(mOPCData.getData());
+                realtimeData.setValue(opcData.getData());
                 realtimeData.setUnit("℃");
                 realtimeData.setDesc("铁水温度");
-                realtimeData.setTime(mOPCData.getServerTime().toString());
+                realtimeData.setTime(LocalDateUtils.formatDate(opcData.getServerTime()));
                 mRealtimeData.put(IRON_TEMP, realtimeData);
                 //redis添加数据
                 RedisUtils.addFixedElement(IRON_TEMP, realtimeData, 6);
-            }
-
-            if (mOPCData.getPointName().contains(TAG_CAR11) || mOPCData.getPointName().contains(TAG_CAR12)) {
+                PushData.send2TrendIronTemp(RedisUtils.getFixedElement(IRON_TEMP));
+            } else if (opcData.getPointName().contains(TAG_CAR11) || opcData.getPointName().contains(TAG_CAR12)) {
 //            1TH-1号车受铁速度
                 RealtimeData realtimeData = new RealtimeData();
-                realtimeData.setValue(mOPCData.getData());
+                realtimeData.setValue(opcData.getData());
                 realtimeData.setUnit("t/s");
 
                 RealtimeData ironSpeed = (RealtimeData) mRealtimeData.get(IRON_SPEED);
@@ -316,12 +446,14 @@ public class DeviceEventListener extends EventListener {
                     speeds = (RealtimeData[]) ironSpeed.getValue();
                 }
 
-                if (mOPCData.getPointName().contains(TAG_CAR11)) {
+                if (opcData.getPointName().contains(TAG_CAR11)) {
                     realtimeData.setDesc("1号车");
                     speeds[0] = realtimeData;
+                    speed1 = Float.parseFloat(opcData.getData().toString());
                 } else {
                     realtimeData.setDesc("2号车");
                     speeds[1] = realtimeData;
+                    speed2 = Float.parseFloat(opcData.getData().toString());
                 }
 
                 //只在两个都有数据的时候才添加
@@ -329,75 +461,62 @@ public class DeviceEventListener extends EventListener {
                         && ObjectUtils.isNotEmpty(speeds[0]) && ObjectUtils.isNotEmpty(speeds[0].getValue())
                         && ObjectUtils.isNotEmpty(speeds[1]) && ObjectUtils.isNotEmpty(speeds[1].getValue())
                 ) {
-                    ironSpeed.setTime(mOPCData.getServerTime().toString());
+                    ironSpeed.setTime(LocalDateUtils.formatDate(opcData.getServerTime()));
                     RedisUtils.addFixedElement(IRON_SPEED, ironSpeed, 6);
+                    PushData.send2TrendIronSpeed(RedisUtils.getFixedElement(IRON_SPEED));
                 }
-            }
-
-            if (mOPCData.getPointName().contains(TAG_IRON_WEIGHT11) || mOPCData.getPointName().contains(TAG_IRON_WEIGHT12)) {
-//              铁水流量
-                RealtimeData ironWeight = (RealtimeData) mRealtimeData.get(IRON_WEIGHT);
-                if (ObjectUtils.isEmpty(ironWeight)) {
-                    ironWeight = new RealtimeData();
-                    ironWeight.setDesc("铁水流量");
-                    ironWeight.setUnit("t");
-                    ironWeight.setValue(new BigDecimal(String.valueOf(mOPCData.getData())));
-                    mRealtimeData.put(IRON_WEIGHT, ironWeight);
-
-                    ironWeight.setTime(mOPCData.getServerTime().toString());
-                    RedisUtils.addFixedElement(IRON_WEIGHT, ironWeight, 6);
-                } else {
-                    BigDecimal bigDecimalOld = ((BigDecimal) ironWeight.getValue());
-                    BigDecimal bigDecimalNew = new BigDecimal(mOPCData.getData().toString());
-                    BigDecimal add = bigDecimalOld.add(bigDecimalNew);
-                    ironWeight.setValue(add);
-
-                    ironWeight.setTime(mOPCData.getServerTime().toString());
-                    RedisUtils.addFixedElement(IRON_WEIGHT, ironWeight, 6);
-                }
-            }
-
-
-            if (mOPCData.getPointName().contains(TAG_TAPHOLE1_STATUS)) {
+            } else if (opcData.getPointName().contains(TAG_TAPHOLE1_STATUS)) {
                 RealtimeData realtimeData = new RealtimeData();
-                realtimeData.setValue(mOPCData.getData());
+                realtimeData.setValue(opcData.getData());
                 realtimeData.setDesc("出铁状态");
                 mRealtimeStatus.put(IRON_STATUS, realtimeData);
-            }
 
-//            if (mOPCData.getPointName().contains(CAR_STATUS)) {
-//                RealtimeData realtimeData = new RealtimeData();
-//                realtimeData.setValue(mOPCData.getData());
-//                realtimeData.setDesc("鱼雷罐车到位状态");
-//                mRealtimeDataMap.put(CAR_STATUS, realtimeData);
-//            }
-
-
-//            if (mOPCData.getPointName().contains(TAG_IRON_STATUS1)) {
-//                RealtimeData realtimeData = new RealtimeData();
-//                realtimeData.setValue(mOPCData.getData());
-//                realtimeData.setDesc("拔炮状态");
-//                mRealtimeDataMap.put(GUN_STATUS, realtimeData);
-//            }
-//
-//
-//            if (mOPCData.getPointName().contains(TAG_IRON_STATUS1)) {
-//                RealtimeData realtimeData = new RealtimeData();
-//                realtimeData.setValue(mOPCData.getData());
-//                realtimeData.setDesc("摆动溜咀");
-//                mRealtimeDataMap.put(MOUTH_STATUS, realtimeData);
-//            }
-
-            if (mOPCData.getPointName().contains(FLUSH_STATUS)) {
+                ironLoading1 = "1".equals(opcData.getData().toString());
+
+                if (ironLoading1) {
+                    taphole1Start(l2Data);
+                } else {
+                    taphole1End();
+                }
+
+            } else if (opcData.getPointName().contains(TAG_TAPHOLE2_STATUS)) {
+                ironLoading2 = "1".equals(opcData.getData().toString());
+                if (!ironLoading2) {
+                    mIronEndTimeRecently = opcData.getServerTime();
+                }
+            } else if (opcData.getPointName().contains(TAG_TAPHOLE3_STATUS)) {
+                ironLoading3 = "1".equals(opcData.getData().toString());
+                if (!ironLoading3) {
+                    mIronEndTimeRecently = opcData.getServerTime();
+                }
+            } else if (opcData.getPointName().contains(TAG_TAPHOLE4_STATUS)) {
+                ironLoading4 = "1".equals(opcData.getData().toString());
+                if (!ironLoading4) {
+                    mIronEndTimeRecently = opcData.getServerTime();
+                }
+            } else if (opcData.getPointName().contains(TAG_IRON_WEIGHT11) || opcData.getPointName().contains(TAG_IRON_WEIGHT12)) {
+                //铁水流量
+                RealtimeData ironWeight = new RealtimeData();
+                ironWeight.setDesc("铁水流量");
+                ironWeight.setUnit("t");
+                BigDecimal bigDecimalNew = new BigDecimal(opcData.getData().toString());
+                totalWeight = totalWeight.add(bigDecimalNew);
+                ironWeight.setValue(totalWeight);
+                mRealtimeData.put(IRON_WEIGHT, ironWeight);
+                log.info(">>>>>>>>>>>>>{}:{},total:{}", opcData.getPointName(), opcData.getData(), totalWeight.toPlainString());
+
+                ironWeight.setTime(LocalDateUtils.formatDate(opcData.getServerTime()));
+                RedisUtils.addFixedElement(IRON_WEIGHT, ironWeight, 6);
+                PushData.send2TrendIronWeight(RedisUtils.getFixedElement(IRON_WEIGHT));
+
+            } else if (opcData.getPointName().contains(FLUSH_STATUS)) {
                 RealtimeData realtimeData = new RealtimeData();
-                realtimeData.setValue(mOPCData.getData());
+                realtimeData.setValue(opcData.getData());
                 realtimeData.setDesc("冲渣状态");
                 mRealtimeStatus.put(FLUSH_STATUS, realtimeData);
-            }
-
-            if (mOPCData.getPointName().contains(PLAN_END_TIME)) {
+            } else if (opcData.getPointName().contains(PLAN_END_TIME)) {
                 RealtimeData realtimeData = new RealtimeData();
-                realtimeData.setValue(mOPCData.getData());
+                realtimeData.setValue(opcData.getData());
                 realtimeData.setDesc("预计出铁结束时间");
                 mRealtimeData.put(PLAN_END_TIME, realtimeData);
             }
@@ -409,13 +528,14 @@ public class DeviceEventListener extends EventListener {
                 PushData.send2Warn(AjaxResult.success("预警出铁"));
             }
 
+
         }
 
-        if (ObjectUtils.isNotEmpty(mL2Data)) {
+        if (ObjectUtils.isNotEmpty(l2Data)) {
             //铁水成分
             //预计出铁结束时间
-            String elementSi = mL2Data.getElementSi();
-            String elementS = mL2Data.getElementS();
+            String elementSi = l2Data.getElementSi();
+            String elementS = l2Data.getElementS();
 
             RealtimeData realtimeData = new RealtimeData();
             realtimeData.setValue(elementSi);
@@ -446,10 +566,7 @@ public class DeviceEventListener extends EventListener {
     }
 
 
-    private void operate() {
-        if (ObjectUtils.isEmpty(mOPCData)) {
-            return;
-        }
+    private synchronized void operate(OPCData mOPCData) {
         String pointName = mOPCData.getPointName();
         Object data = mOPCData.getData();
         for (IronStepVO stepDTO : mSteps) {
@@ -497,9 +614,6 @@ public class DeviceEventListener extends EventListener {
         setStepResult(mSteps);
 
 
-        ironReady();
-
-
         PushData.send2Operation(mSteps, ironLoading1);
 
     }
@@ -543,87 +657,6 @@ public class DeviceEventListener extends EventListener {
     }
 
 
-    private void ironReady() {
-        if (ObjectUtils.isEmpty(mOPCData)) {
-            return;
-        }
-        //通过“预判和确认出铁”标记开始出铁
-        boolean isReady = false;
-
-        for (IronStepVO stepDTO : mSteps) {
-            if (ypqrct.equalsIgnoreCase(stepDTO.getIdentifier()) && 1 == stepDTO.getPassResult()) {
-                isReady = true;
-                break;
-            }
-        }
-
-        //炉前在接受到炉内出铁要求后,10分钟内打开铁口,未打开系统告警并记录
-        if (isReady) {
-            TimerTask task = new TimerTask() {
-                @Override
-                public void run() {
-                    System.out.println("倒计时结束!10分钟已到。");
-                    timer.cancel(); // 终止定时器
-                    // 打开系统告警并记录
-                    PushData.send2Warn("warn");
-                    log.info("准备出铁但是未及时出铁口,此处数据库记录");
-                }
-            };
-
-            // 倒计时10分钟(600秒)
-            long delay = 10 * 60 * 1000; // 10分钟转换为毫秒
-            // 在指定延迟后执行任务
-            timer.schedule(task, delay);
-        }
-
-        //根据PLC订阅的数据,AOD25606.PV=1为出铁中,AOD25606.PV=0出铁结束的信号,进行判断
-        //为1表示开始出铁,此时如果未超过10分钟,就取消定时器
-        //出铁结束
-        if (mOPCData.getPointName().contains(TAG_TAPHOLE1_STATUS)) {
-            //1:出铁中
-            //0:出铁结束
-            ironLoading1 = "1".equals(mOPCData.getData());
-
-            if ("1".equals(mOPCData.getData())) {
-                //由 0 -> 1
-                //表明1号铁口正在出铁
-                //根据理论铁量、实时铁水流速,推测距离出铁结束的剩余时间
-                //剩余时间=总时间-已经流去的时间
-//                mContext.lookupVariable("");
-                //计算理论铁量= 矿批 × 综合品位 × 1.06,其中矿批是指L2中的干量
-
-//                Date ironTime = mOPCData.getServerTime();
-//                lastIronEndTimeRecently
-
-
-            } else if ("0".equals(mOPCData.getData())) {
-                //由 1-> 0
-                try {
-                    timer.cancel(); // 终止定时器
-                } catch (Exception e) {
-                    e.printStackTrace();
-                }
-                recordAfter();
-                recordBlock();
-
-                //出铁结束后,查询最近两次的数据
-                LambdaQueryWrapper<TIronData> queryWrapper = new QueryWrapper<TIronData>().lambda().orderByDesc(TIronData::getCtcsbh);
-                List<TIronData> oldIronDataList = ironDataService.list(queryWrapper);
-            }
-
-        }
-
-
-        if (mOPCData.getPointName().contains(TAG_TAPHOLE1_STATUS)
-                || mOPCData.getPointName().contains(TAG_TAPHOLE2_STATUS)
-                || mOPCData.getPointName().contains(TAG_TAPHOLE3_STATUS)
-                || mOPCData.getPointName().contains(TAG_TAPHOLE4_STATUS)
-        ) {
-            lastIronEndTimeRecently = mOPCData.getServerTime();
-        }
-
-    }
-
     /***
      * 判断是否通过
      * @param stepVO
@@ -640,11 +673,12 @@ public class DeviceEventListener extends EventListener {
             }
             stepVO.setStepName(flowName);
         } catch (Exception e) {
-            log.error("stepId:{},identifier:{},stepName:{}", stepVO.getStepId(), stepVO.getIdentifier(), flowName);
+            //log.info("stepId:{},identifier:{},stepName:{}", stepVO.getStepId(), stepVO.getIdentifier(), flowName);
         }
 
         //非流程必须项,直接放行
-        if ("0".equals(stepVO.getRequired())) {
+        //正在出铁中,直接发行
+        if ("0".equals(stepVO.getRequired()) || ironLoading1) {
             stepVO.setPassResult(1);
             return;
         }
@@ -661,15 +695,6 @@ public class DeviceEventListener extends EventListener {
 
     }
 
-    //出铁后,记录炉次、开口时间、鱼雷罐车车号、铁口深度、铁水流速
-    private void recordAfter() {
-        ironAfterService.add(null);
-    }
-
-    //堵口后,记录堵口时间、出铁量,打泥量、是否喷溅、是否跑泥
-    private void recordBlock() {
-        ironBlockService.add(null);
-    }
 
     /***
      * 用户端点击触发

+ 0 - 56
taphole-iron/src/main/java/com/sckj/iron/socketio/IronTrendListener.java

@@ -1,56 +0,0 @@
-package com.sckj.iron.socketio;
-
-import com.google.common.eventbus.Subscribe;
-import com.sckj.common.eventbus.EventListener;
-import com.sckj.common.socketio.SocketUtil;
-import com.sckj.iron.service.impl.TIronStepServiceImpl;
-import com.sckj.opc.entity.OPCData;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-import javax.annotation.Resource;
-
-/**
- * @Author feng
- * @Date 2024-11-19 上午 11:05
- * @Description 趋势数据推送
- */
-@Component
-@Slf4j
-public class IronTrendListener extends EventListener {
-
-    @Resource
-    TIronStepServiceImpl ironStepService;
-
-
-
-    @Subscribe
-    public void onMessageEvent(OPCData opcData) {
-        if (SocketUtil.clientUserIds.isEmpty()) {
-            return;
-        }
-        trend(opcData);
-    }
-
-
-    /***
-     * 铁水成分
-     * 铁水流速
-     * 铁水流量
-     * 铁水温度
-     * @param opcData
-     */
-    private void trend(OPCData opcData) {
-        String pointName = opcData.getPointName();
-        Object data = opcData.getData();
-
-        PushData.send2Trend("");
-    }
-
-
-
-
-
-
-
-}

+ 70 - 5
taphole-iron/src/main/java/com/sckj/iron/socketio/PushData.java

@@ -25,7 +25,22 @@ public class PushData {
     /**
      * 趋势数据
      **/
-    public static final String IRON_TREND = "IRON_TREND";
+    public static final String TrendIronWeight = "TrendIronWeight";
+
+    /**
+     * 趋势数据
+     **/
+    public static final String TrendIronTemp = "TrendIronTemp";
+
+    /**
+     * 趋势数据
+     **/
+    public static final String TrendIronSpeed = "TrendIronSpeed";
+
+    /**
+     * 趋势数据
+     **/
+    public static final String TrendIronElement = "TrendIronElement";
 
     /**
      * 实时数据
@@ -63,13 +78,14 @@ public class PushData {
         //单独发消息
         socketClient.sendEvent(PushData.IRON_OPERATION, AjaxResult.success(message));
     }
+
     /**
      * 出铁操作
      *
      * @return
      * @Param
      **/
-    public static void send2Operation(Object message, String  userId) {
+    public static void send2Operation(Object message, String userId) {
         if (SocketUtil.connectMap.isEmpty()) {
             return;
         }
@@ -94,7 +110,7 @@ public class PushData {
      * @param message 发送的消息内容
      * @param isStopSendMsg  是否停止发送信息
      */
-    public static void send2Operation(Object message,boolean isStopSendMsg) {
+    public static void send2Operation(Object message, boolean isStopSendMsg) {
         if (SocketUtil.connectMap.isEmpty() || isStopSendMsg) {
             return;
         }
@@ -106,18 +122,66 @@ public class PushData {
 
 
     /**
+     * 趋势-铁水流量
+     *
+     * @return
+     * @Param
+     **/
+    public static void send2TrendIronWeight(Object message) {
+        if (SocketUtil.connectMap.isEmpty()) {
+            return;
+        }
+        //
+        for (Map.Entry<String, SocketIOClient> entry : SocketUtil.connectMap.entrySet()) {
+            entry.getValue().sendEvent(PushData.TrendIronWeight, AjaxResult.success(message));
+        }
+    }
+
+    /**
+     * 趋势-铁水温度
+     *
+     * @return
+     * @Param
+     **/
+    public static void send2TrendIronTemp(Object message) {
+        if (SocketUtil.connectMap.isEmpty()) {
+            return;
+        }
+        //
+        for (Map.Entry<String, SocketIOClient> entry : SocketUtil.connectMap.entrySet()) {
+            entry.getValue().sendEvent(PushData.TrendIronTemp, AjaxResult.success(message));
+        }
+    }
+
+    /**
+     * 趋势-
+     *
+     * @return
+     * @Param
+     **/
+    public static void send2TrendIronSpeed(Object message) {
+        if (SocketUtil.connectMap.isEmpty()) {
+            return;
+        }
+        //
+        for (Map.Entry<String, SocketIOClient> entry : SocketUtil.connectMap.entrySet()) {
+            entry.getValue().sendEvent(PushData.TrendIronSpeed, AjaxResult.success(message));
+        }
+    }
+
+    /**
      * 趋势
      *
      * @return
      * @Param
      **/
-    public static void send2Trend(Object message) {
+    public static void send2TrendIronElement(Object message) {
         if (SocketUtil.connectMap.isEmpty()) {
             return;
         }
         //
         for (Map.Entry<String, SocketIOClient> entry : SocketUtil.connectMap.entrySet()) {
-            entry.getValue().sendEvent(PushData.IRON_TREND, AjaxResult.success(message));
+            entry.getValue().sendEvent(PushData.TrendIronElement, AjaxResult.success(message));
         }
     }
 
@@ -136,6 +200,7 @@ public class PushData {
             entry.getValue().sendEvent(PushData.IRON_REALTIME_DATA, AjaxResult.success(message));
         }
     }
+
     /**
      * 实时数据
      *

+ 0 - 15
taphole-iron/src/main/java/com/sckj/iron/validate/TIronParamUpdateValidate.java

@@ -21,21 +21,6 @@ public class TIronParamUpdateValidate implements Serializable {
     @ApiModelProperty(value = "主键id")
     private Long id;
 
-//    @ApiModelProperty(value = "开口耗时(s)")
-//    private BigDecimal kkhs;
-//
-//    @ApiModelProperty(value = "出铁时间(s)")
-//    private BigDecimal ctsj;
-//
-//    @ApiModelProperty(value = "出铁量(t)")
-//    private BigDecimal ctl;
-//
-//    @ApiModelProperty(value = "出铁流速(t/s)")
-//    private BigDecimal ctls;
-//
-//    @ApiModelProperty(value = "铁水温度变化(℃/s)")
-//    private BigDecimal tswdbh;
-
     @ApiModelProperty(value = "参数类型")
     private String paramType;
 

+ 16 - 10
taphole-iron/src/main/java/com/sckj/iron/vo/TIronParamDetailVo.java

@@ -22,20 +22,26 @@ public class TIronParamDetailVo implements Serializable {
     @ApiModelProperty(value = "")
     private Long id;
 
-    @ApiModelProperty(value = "开口耗时(s)")
-    private BigDecimal kkhs;
+    @ApiModelProperty(value = "铁口区域编号")
+    private Long tapholeId;
 
-    @ApiModelProperty(value = "出铁时间(s)")
-    private BigDecimal ctsj;
+    @ApiModelProperty(value = "锅炉编号")
+    private Long boilerId;
 
-    @ApiModelProperty(value = "出铁量(t)")
-    private BigDecimal ctl;
+    @ApiModelProperty(value = "参数类型")
+    private String paramType;
 
-    @ApiModelProperty(value = "出铁流速(t/s)")
-    private BigDecimal ctls;
+    @ApiModelProperty(value = "参数名称")
+    private String paramName;
 
-    @ApiModelProperty(value = "铁水温度变化(℃/s)")
-    private BigDecimal tswdbh;
+    @ApiModelProperty(value = "参数值")
+    private String paramValue;
+
+    @ApiModelProperty(value = "状态(1正常 0停用)")
+    private String status;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
 
 
 }

+ 16 - 10
taphole-iron/src/main/java/com/sckj/iron/vo/TIronParamListedVo.java

@@ -22,20 +22,26 @@ public class TIronParamListedVo implements Serializable {
     @ApiModelProperty(value = "")
     private Long id;
 
-    @ApiModelProperty(value = "开口耗时(s)")
-    private BigDecimal kkhs;
+    @ApiModelProperty(value = "铁口区域编号")
+    private Long tapholeId;
 
-    @ApiModelProperty(value = "出铁时间(s)")
-    private BigDecimal ctsj;
+    @ApiModelProperty(value = "锅炉编号")
+    private Long boilerId;
 
-    @ApiModelProperty(value = "出铁量(t)")
-    private BigDecimal ctl;
+    @ApiModelProperty(value = "参数类型")
+    private String paramType;
 
-    @ApiModelProperty(value = "出铁流速(t/s)")
-    private BigDecimal ctls;
+    @ApiModelProperty(value = "参数名称")
+    private String paramName;
 
-    @ApiModelProperty(value = "铁水温度变化(℃/s)")
-    private BigDecimal tswdbh;
+    @ApiModelProperty(value = "参数值")
+    private String paramValue;
+
+    @ApiModelProperty(value = "状态(1正常 0停用)")
+    private String status;
+
+    @ApiModelProperty(value = "排序")
+    private Integer sort;
 
 
 }

+ 7 - 0
taphole-opc/src/main/java/com/sckj/opc/dto/L2Data.java

@@ -86,6 +86,12 @@ public class L2Data implements Serializable {
         dos.writeUTF(totalDry);
         dos.writeUTF(ironStarttime);
         dos.writeUTF(ironEndtime);
+        dos.writeUTF(elementC);
+        dos.writeUTF(elementSi);
+        dos.writeUTF(elementMn);
+        dos.writeUTF(elementP);
+        dos.writeUTF(elementS);
+        dos.writeUTF(elementTi);
     }
 
     public static L2Data fromDataStream(DataInputStream dis) throws Exception {
@@ -101,6 +107,7 @@ public class L2Data implements Serializable {
         data.openDepth = dis.readUTF();
         data.totalDry = dis.readUTF();
         data.ironStarttime = dis.readUTF();
+        data.ironEndtime = dis.readUTF();
         data.elementC = dis.readUTF();
         data.elementSi = dis.readUTF();
         data.elementMn = dis.readUTF();

+ 68 - 45
taphole-opc/src/main/java/com/sckj/opc/opcua/OPCDAServiceImpl.java

@@ -13,20 +13,21 @@ import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang3.ObjectUtils;
 import org.jinterop.dcom.common.JIException;
 import org.openscada.opc.lib.common.ConnectionInformation;
-import org.openscada.opc.lib.common.NotConnectedException;
 import org.openscada.opc.lib.da.*;
 import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
 import org.springframework.stereotype.Service;
 
 import javax.annotation.PreDestroy;
 import javax.annotation.Resource;
-import java.net.UnknownHostException;
-import java.util.*;
-import java.util.concurrent.*;
-
-import static org.eclipse.milo.opcua.stack.core.types.builtin.unsigned.Unsigned.uint;
+import java.text.DecimalFormat;
+import java.util.Calendar;
+import java.util.List;
+import java.util.Objects;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
 
 @Service
 @Slf4j
@@ -48,16 +49,16 @@ public class OPCDAServiceImpl {
     ThreadPoolTaskExecutor taskExecutor;
 
     private ConcurrentHashMap<Long, Server> mOPCDaClientMap = new ConcurrentHashMap<>();
-    private ConcurrentHashMap<Long, Object> mOPCDaPointsMap = new ConcurrentHashMap<>();
+    private ConcurrentHashMap<String, OPCData> mOPCDaPointsMap = new ConcurrentHashMap<>();
 
 
     /**
      * 获得基础的连接信息
      */
     public Server createServer(OPCServer opcServer) {
-        if (mOPCDaClientMap.containsKey(opcServer.getId())) {
-            return mOPCDaClientMap.get(opcServer.getId());
-        }
+//        if (mOPCDaClientMap.containsKey(opcServer.getId())) {
+//            return mOPCDaClientMap.get(opcServer.getId());
+//        }
         final ConnectionInformation ci = new ConnectionInformation();
         ci.setHost(opcServer.getIp());          // OPCDA IP
         ci.setUser(opcServer.getUsername());              // 用户名,配置DCOM时配置的
@@ -66,21 +67,20 @@ public class OPCDAServiceImpl {
 
         log.info("Create Server : {}", opcServer);
 
-        log.info("availableProcessors:{}",Runtime.getRuntime().availableProcessors());
+        log.info("availableProcessors:{}", Runtime.getRuntime().availableProcessors());
         // 启动服务
         final Server server = new Server(ci, Executors.newSingleThreadScheduledExecutor());
         AutoReconnectController controller = new AutoReconnectController(server);
         // 连接到服务
         controller.connect();
-        mOPCDaClientMap.put(opcServer.getId(), server);
+//        mOPCDaClientMap.put(opcServer.getId(), server);
         return server;
     }
 
 
     public Object createSubscription(OPCServer opcServer, OPCPoint opcPoint) {
         StringBuilder sb = new StringBuilder();
-        if (ObjectUtils.isNotEmpty(opcPoint) && !mOPCDaPointsMap.containsKey(opcPoint.getId())) {
-            Map<String, Object> pointChangedMap = new LinkedHashMap<>();
+        if (ObjectUtils.isNotEmpty(opcPoint) && !mOPCDaPointsMap.containsKey(opcPoint.getPointName())) {
             Future<String> future = taskExecutor.submit(new Callable<String>() {
                 @Override
                 public String call() {
@@ -90,17 +90,19 @@ public class OPCDAServiceImpl {
 
                         String newPointName = opcPoint.getPointName();
 
-                        if(ObjectUtils.isEmpty(newPointName)){
+                        if (ObjectUtils.isEmpty(newPointName)) {
                             return null;
                         }
 
-                        if(newPointName.contains(".")){
+                        if (newPointName.contains(".")) {
                             newPointName = "channel." + newPointName;
-                        }else{
+                        } else {
                             newPointName = "channel.device." + newPointName;
                         }
 
-                        log.info("{} start subscribe",newPointName);
+                        log.info("{} start subscribe", newPointName);
+
+                        mOPCDaPointsMap.put(opcPoint.getPointName(), OPCData.builder().build());
 
                         access.addItem(newPointName, (item, itemstate) -> {
                             int errorCode = itemstate.getErrorCode();
@@ -112,30 +114,47 @@ public class OPCDAServiceImpl {
                             } catch (JIException e) {
                                 e.printStackTrace();
                             }
-                            //DA中订阅是按照定时计算的,存在重复的数据项,进行过滤
-                            if (!Objects.equals(pointChangedMap.get(item.getId()), object)) {
-                                pointChangedMap.put(item.getId(), object);
-                                OPCData opcData = OPCData.builder()
-                                        .data(object)
-                                        .serverTime(calendar.getTime())
-                                        .sourceTime(calendar.getTime())
-                                        .statusCode((long) errorCode)
-                                        .pointName(pointName)
-                                        .build();
-                                //post给其他模块使用
-                                asyncEventBus.post(opcData);
-                                //opcDataService.save(opcData);
-                                log.info("DA,{},{}",item.getId(), itemstate.toString());
+                            synchronized (mOPCDaPointsMap) {
+                                //DA中订阅是按照定时计算的,存在重复的数据项,进行过滤
+                                OPCData previousData = mOPCDaPointsMap.get(opcPoint.getPointName());
+                                Object currentData = object;
+
+                                //直接比较原始对象,避免字符串转换误差
+                                boolean isNewData = previousData == null ||
+                                        !Objects.equals(previousData.getData(), currentData);
+
+                                // 添加数值精度处理(处理小数点后2位)
+                                if (!isNewData && currentData instanceof Number) {
+                                    DecimalFormat df = new DecimalFormat("#.##");
+                                    String prev = df.format(previousData.getData());
+                                    String curr = df.format(currentData);
+                                    isNewData = !prev.equals(curr);
+                                }
+
+                                if (isNewData) {
+                                    OPCData opcData = OPCData.builder()
+                                            .data(object)
+                                            .serverTime(calendar.getTime())
+                                            .sourceTime(calendar.getTime())
+                                            .statusCode((long) errorCode)
+                                            .pointName(pointName)
+                                            .build();
+                                    // 使用put原子操作更新数据
+                                    mOPCDaPointsMap.put(opcPoint.getPointName(), opcData);
+                                    //post给其他模块使用
+                                    asyncEventBus.post(opcData);
+                                    log.debug("DA,{},{}", item.getId(), itemstate);
+                                }
                             }
                         });
 
                         access.bind();
-                        mOPCDaPointsMap.put(opcPoint.getId(), opcPoint);
-                        while (mOPCDaPointsMap.containsKey(opcPoint.getId())) {
+
+                        while (mOPCDaPointsMap.containsKey(opcPoint.getPointName())) {
                             //阻塞,直到关闭订阅
                         }
                         access.unbind();
-                        log.info("{} stop subscribe",opcPoint.getPointName());
+                        log.info("{} stop subscribe", opcPoint.getPointName());
                     } catch (Exception e) {
                         e.printStackTrace();
                         return e.getMessage();
@@ -144,15 +163,17 @@ public class OPCDAServiceImpl {
                 }
             });
 
-            try {
-                String result = future.get(1,TimeUnit.SECONDS); //
-                log.error(">>> error:{}", result);
-                if (ObjectUtils.isNotEmpty(result)) {
-                    sb.append(opcPoint.getPointName() + "订阅异常:" + result);
-                }
-            } catch (Exception e) {
-                e.printStackTrace();
-            }
+//            try {
+//                String result = future.get(10, TimeUnit.SECONDS); //
+//                log.error(">>> error:{}", result);
+//                if (ObjectUtils.isNotEmpty(result)) {
+//                    sb.append(opcPoint.getPointName() + "订阅异常:" + result);
+//                }
+//            } catch (Exception e) {
+//                e.printStackTrace();
+//                log.info("订阅异常:{}", opcPoint.getPointName());
+//            }
+
         }
         return sb;
     }
@@ -202,7 +223,9 @@ public class OPCDAServiceImpl {
             pointQueryWrapper.lambda().eq(OPCPoint::getOpcServerId, opcServer.getId()).eq(OPCPoint::getStatus, "1");
             List<OPCPoint> opcPointList = opcPointService.list(pointQueryWrapper);
             if (ObjectUtils.isNotEmpty(opcPointList)) {
+                log.info("start point list:");
                 for (OPCPoint opcPoint : opcPointList) {
+                    log.info(opcPoint.getPointName());
                     createSubscription(opcServer, opcPoint);
                 }
             }

+ 4 - 1
taphole-warn/src/main/java/com/sckj/warn/vo/TExceptionLogDetailVo.java

@@ -28,5 +28,8 @@ public class TExceptionLogDetailVo implements Serializable {
     private String reportedStatus;
 
     @ApiModelProperty(value = "锅炉编号")
-    private Integer glId;
+    private Integer boilerId;
+
+    @ApiModelProperty(value = "铁口区域编号")
+    private Integer tapholeId;
 }

+ 4 - 1
taphole-warn/src/main/java/com/sckj/warn/vo/TExceptionLogListedVo.java

@@ -31,7 +31,10 @@ public class TExceptionLogListedVo implements Serializable {
     private String reportedStatus;
 
     @ApiModelProperty(value = "锅炉编号")
-    private Integer glId;
+    private Integer boilerId;
+
+    @ApiModelProperty(value = "铁口区域编号")
+    private Integer tapholeId;
 
 
 }