Browse Source

印花机米长取数修改

wukai 1 week ago
parent
commit
341940c92b

+ 18 - 0
jjt-admin/src/test/java/com/jjt/rziot/DataTest.java

@@ -1,10 +1,15 @@
 package com.jjt.rziot;
 
+import cn.hutool.json.JSONObject;
 import com.jjt.JjtApplication;
+import com.jjt.rz.domain.TwinDeviceRz;
+import com.jjt.rz.service.ITwinDeviceRzService;
 import com.jjt.utils.IotService;
+import org.junit.jupiter.api.Test;
 import org.springframework.boot.test.context.SpringBootTest;
 
 import javax.annotation.Resource;
+import java.util.List;
 
 /**
  * DataTest$
@@ -17,4 +22,17 @@ public class DataTest {
     @Resource
     private IotService iotService;
 
+    @Resource
+    private ITwinDeviceRzService rzService;
+
+    @Test
+    void test() {
+        List<TwinDeviceRz> list = rzService.selectTwinDeviceRzList(new TwinDeviceRz());
+        for (TwinDeviceRz rz : list) {
+            String sql = "select * from " + rz.getDevicePath();
+            JSONObject jsonObject = iotService.query(sql);
+            System.out.println(jsonObject);
+        }
+    }
+
 }

+ 36 - 0
jjt-admin/src/test/java/com/jjt/rziot/Test.java

@@ -0,0 +1,36 @@
+package com.jjt.rziot;
+
+/**
+ * Test$
+ *
+ * @author wukai
+ * @date 2025/5/24 03:19
+ */
+public class Test {
+    public static void main(String[] args) {
+        for (String machineName : machineNames) {
+            String[] tmp = machineName.split("_");
+            String line = tmp[1].replace("线", "");
+            String name = tmp[0];
+            String ws = tmp[2];
+            String cj = "Forward";
+            if (ws.indexOf("后整") != -1) {
+                cj = "Back";
+            }
+            String no = tmp[3].replace("号", "");
+
+            String path = "root.tl.suxi.dingxingji6jLine" + line + cj + "No" + no + "_PLC1";
+            System.err.println(machineName + "\t" + path);
+        }
+    }
+
+
+    static String[] machineNames = {
+            "6节定型机_8线_后整_1号",
+            "6节定型机_7线_后整_1号",
+            "6节定型机_6线_后整_1号",
+            "6节定型机_5线_后整_1号",
+            "6节定型机_4线_后整_1号",
+            "6节定型机_3线_后整_1号"
+    };
+}

+ 69 - 0
jjt-admin/src/test/java/com/jjt/task/YhjTaskTest.java

@@ -0,0 +1,69 @@
+package com.jjt.task;
+
+import com.jjt.JjtApplication;
+import com.jjt.calc.service.ITwinCalcDayYhjService;
+import com.jjt.calc.service.ITwinCalcHourYhjService;
+import com.jjt.utils.IotService;
+import org.junit.jupiter.api.Test;
+import org.springframework.boot.test.context.SpringBootTest;
+
+import javax.annotation.Resource;
+import java.time.LocalDate;
+import java.time.LocalDateTime;
+import java.time.LocalTime;
+
+/**
+ * DataProcess$
+ *
+ * @author wukai
+ * @date 2024/5/7 11:49
+ */
+@SpringBootTest(classes = JjtApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+public class YhjTaskTest {
+    @Resource
+    private ITwinCalcDayYhjService dayService;
+    @Resource
+    private IotService iotService;
+    @Resource
+    private ITwinCalcHourYhjService yhjService;
+
+
+    @Test
+    public void last() {
+        iotService.setToken();
+        yhjService.last();
+        String date = "2025-05-28";
+        LocalDate localDate = LocalDate.parse(date);
+        LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.MIN);
+        for (int i = 7; i < 21; i++) {
+            LocalDateTime tt = ldt.plusHours(i);
+            System.err.println(tt.toLocalDate().toString() + tt.getHour());
+            yhjService.calc(tt.toLocalDate().toString(), tt.getHour());
+        }
+    }
+
+    @Test
+    public void test() {
+        iotService.setToken();
+        String st = "2025-05-28";
+        String ed = "2025-05-28";
+        LocalDate localDate = LocalDate.parse(st);
+        LocalDate endDate = LocalDate.parse(ed);
+        LocalDateTime start = LocalDateTime.of(localDate, LocalTime.MIN).plusHours(7);
+        LocalDateTime end = LocalDateTime.of(endDate.plusDays(1), LocalTime.MIN).plusHours(6);
+        LocalDateTime curr = LocalDateTime.now();
+        if (end.isAfter(curr)) {
+            end = curr.minusHours(1);
+        }
+        do {
+            int i = start.getHour();
+            System.err.println(start.toLocalDate().toString() + "\t" + i);
+            yhjService.calc(start.toLocalDate().toString(), i);
+            if (i == 6) {
+                dayService.day(start.toLocalDate().minusDays(1));
+            }
+            start = start.plusHours(1);
+        } while (!start.isAfter(end));
+    }
+}
+

+ 8 - 0
jjt-biz/src/main/java/com/jjt/calc/service/ITwinCalcHourYhjService.java

@@ -61,6 +61,14 @@ public interface ITwinCalcHourYhjService {
     public int deleteTwinCalcHourYhjById(Long id);
 
     /**
+     * 统计指定日期指定时段数据
+     *
+     * @param date   指定日期 yyyy-mm-dd
+     * @param period 时段
+     */
+    public void calc(String date, int period);
+
+    /**
      * 统计上一时段数据
      */
     void last();

+ 38 - 72
jjt-biz/src/main/java/com/jjt/calc/service/impl/TwinCalcHourYhjServiceImpl.java

@@ -1,7 +1,5 @@
 package com.jjt.calc.service.impl;
 
-import cn.hutool.json.JSONArray;
-import cn.hutool.json.JSONObject;
 import com.jjt.biz.domain.TwinDeviceYhj;
 import com.jjt.biz.service.ITwinDeviceYhjService;
 import com.jjt.calc.domain.TwinCalcHourYhj;
@@ -9,6 +7,7 @@ import com.jjt.calc.mapper.TwinCalcHourYhjMapper;
 import com.jjt.calc.service.ITwinCalcDayYhjService;
 import com.jjt.calc.service.ITwinCalcHourYhjService;
 import com.jjt.common.utils.DateUtils;
+import com.jjt.utils.AsyncYhjService;
 import com.jjt.utils.IotService;
 import com.jjt.utils.Tools;
 import lombok.extern.slf4j.Slf4j;
@@ -21,8 +20,13 @@ import javax.annotation.Resource;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.LocalTime;
-import java.time.ZoneOffset;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
 
 /**
  * 印花机1小时统计数据Service业务层处理
@@ -43,6 +47,8 @@ public class TwinCalcHourYhjServiceImpl implements ITwinCalcHourYhjService {
     private ITwinDeviceYhjService yhjService;
     @Resource
     private ITwinCalcDayYhjService dayYhjService;
+    @Resource
+    private AsyncYhjService asyncYhjService;
 
     /**
      * 查询印花机1小时统计数据
@@ -111,6 +117,21 @@ public class TwinCalcHourYhjServiceImpl implements ITwinCalcHourYhjService {
     }
 
     /**
+     * 统计指定日期指定时段数据
+     *
+     * @param date   指定日期 yyyy-mm-dd
+     * @param period 时段
+     */
+    @Override
+    public void calc(String date, int period) {
+        LocalDate localDate = LocalDate.parse(date);
+        LocalDateTime ldt = LocalDateTime.of(localDate, LocalTime.MIN);
+        LocalDateTime start = ldt.plusHours(period);
+        LocalDateTime end = start.plusHours(1);
+        calc(start, end);
+    }
+
+    /**
      * 统计上一时段数据
      */
     @Override
@@ -132,82 +153,27 @@ public class TwinCalcHourYhjServiceImpl implements ITwinCalcHourYhjService {
      */
     @Override
     public void calc(LocalDateTime start, LocalDateTime end) {
-        Long startTime = start.toInstant(ZoneOffset.of("+8")).toEpochMilli();
-        Long endTime = end.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        //先删除当前时段的统计数据
         deleteTwinCalcHourYhj(DateUtils.toDate(start.toLocalDate()), start.getHour());
         List<TwinDeviceYhj> list = yhjService.selectTwinDeviceYhjList(new TwinDeviceYhj());
+        List<Future<TwinCalcHourYhj>> futureList = new ArrayList<>();
         List<TwinCalcHourYhj> calcList = new ArrayList<>();
-        //  使用设备编码作为Map的key, 使用设备对象本身作为Map的value, 如果有重复的key,保留现有的value
-        Map<String, TwinDeviceYhj> yhjMap = new HashMap<>(16);
-        List<String> fieldList = new ArrayList<>();
-        String prefix = "root.tl.suxi";
-        String[] fields = {"Formula_data_set_1", "Formula_data_act_5"};
         for (TwinDeviceYhj yhj : list) {
-            for (String field : fields) {
-                String tmp = yhj.getDeviceCode() + "." + field;
-                fieldList.add(tmp);
-                yhjMap.put(prefix + "." + tmp, yhj);
-            }
+            futureList.add(asyncYhjService.process(yhj, start, end));
         }
-        String sql = "select %s from " + prefix + " where time>%s and time <=%s";
 
-        sql = String.format(sql, String.join(",", fieldList), startTime, endTime);
-        JSONObject jsonObject = iotService.query(sql);
-        JSONObject data = jsonObject.getJSONObject("data");
-        JSONArray columnNames = data.getJSONArray("columnNames");
-        JSONArray values = data.getJSONArray("values");
-        JSONArray timestamps = data.getJSONArray("timestamps");
-        //记录上一次记录的值
-        Integer[] last = new Integer[columnNames.size()];
-        //记录最后一次的值,防中间有数,后面没数
-        Integer[] over = new Integer[columnNames.size()];
-        //当前记录值
-        Integer[] total = new Integer[columnNames.size()];
-        //记录第一次记录的值,如果清0,则记录清零时刻的值
-        Integer[] first = new Integer[columnNames.size()];
-        //记录统计值
-        Integer[] curr = new Integer[columnNames.size()];
-        for (int i = 0; i < values.size(); i++) {
-            JSONArray da = values.getJSONArray(i);
-            da.toList(Integer.class).toArray(curr);
-            if (i == 0) {
-                cloneArray(curr, last);
-                cloneArray(curr, first);
-                cloneArray(curr, over);
-                continue;
-            }
-            for (int j = 0; j < columnNames.size(); j++) {
-                String name = columnNames.getStr(j);
-                if (name.contains("Formula_data_set_1")) {
-                    //如果是版距,则需要记录变化
-                    if (curr[j] != null && last[j] != null && curr[j].intValue() != last[j].intValue()) {
-                        //这里要用j+1才行
-                        calcLength(j + 1, last, first, total);
-                        combo(calcList, start, yhjMap.get(name), last[j], total[j + 1]);
-                        total[j + 1] = 0;
-                    }
+        try {
+            for (Future<TwinCalcHourYhj> future : futureList) {
+                // 任务完成后获取结果
+                try {
+                    TwinCalcHourYhj calcYhj = future.get(10L, TimeUnit.SECONDS);
+                    calcList.add(calcYhj);
+                } catch (TimeoutException e) {
+                    log.error("有超时的哟{}", e.getMessage());
                 }
-                if (name.contains("Formula_data_act_5")) {
-                    //如果是米长,则需要记录是否清0
-                    //如果当前值为小于上一个,且上一个值不为0,则计算
-                    //因为会出现数据波动,停机再启动之后的第一个点不为0,为0.00几几几的
-                    if (curr[j] != null && last[j] != null && curr[j] < last[j] && last[j] != 0) {
-                        calcLength(j, last, first, total);
-                        cloneArray(curr, first);
-                    }
-                }
-            }
-            //将本次的值,设为上一条记录了
-            cloneArray(curr, last);
-            cloneArray(curr, over);
-            cloneArrayFirst(curr, first);
-        }
-        for (int j = 0; j < columnNames.size(); j++) {
-            String name = columnNames.getStr(j);
-            if (name.contains("Formula_data_set_1")) {
-                calcLength(j + 1, over, first, total);
-                combo(calcList, start, yhjMap.get(name), over[j], total[j + 1]);
             }
+        } catch (InterruptedException | ExecutionException e) {
+            throw new RuntimeException(e);
         }
 
         try (SqlSession sqlSession = factory.openSession(ExecutorType.BATCH, false)) {

+ 199 - 0
jjt-biz/src/main/java/com/jjt/utils/AsyncYhjService.java

@@ -0,0 +1,199 @@
+package com.jjt.utils;
+
+import cn.hutool.json.JSONArray;
+import cn.hutool.json.JSONObject;
+import com.jjt.biz.domain.TwinDevice;
+import com.jjt.biz.domain.TwinDeviceYhj;
+import com.jjt.calc.domain.TwinCalcHourYhj;
+import com.jjt.common.utils.DateUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.scheduling.annotation.AsyncResult;
+import org.springframework.stereotype.Service;
+
+import javax.annotation.Resource;
+import java.time.LocalDateTime;
+import java.time.ZoneOffset;
+import java.util.*;
+import java.util.concurrent.Future;
+import java.util.stream.Collectors;
+
+/**
+ * 多线程执行任务
+ *
+ * @author wukai
+ * @date 2024/5/4 20:35
+ */
+@Service
+@Slf4j
+public class AsyncYhjService {
+    @Resource
+    private IotService iotService;
+    /**
+     * 字段列表,方便看下标
+     */
+    private final String[] fields = {"Capacity_data_2", "Capacity_data_37", "Capacity_data_38", "Capacity_data_39", "Capacity_data_42",
+            "Capacity_data_43", "Capacity_data_44", "Capacity_data_48", "Formula_data_3", "Formula_data_13",
+            "Capacity_data_36", "Capacity_data_41", "Alarm_unit_1", "Alarm_unit_2", "Alarm_unit_3",
+            "Alarm_unit_4", "Alarm_unit_5", "Alarm_unit_6", "Alarm_unit_7", "Alarm_unit_8",
+            "Alarm_unit_9", "Alarm_unit_10", "Alarm_unit_11", "Alarm_unit_12", "Alarm_unit_13",
+            "Alarm_unit_14", "Alarm_unit_15", "Alarm_unit_16", "Alarm_unit_17", "Alarm_unit_18",
+            "Alarm_unit_19", "Alarm_unit_20", "Alarm_unit_21", "Alarm_unit_22", "Alarm_unit_23",
+            "Alarm_unit_24", "Alarm_unit_25", "Alarm_unit_26", "Alarm_unit_27", "Capacity_data_33",
+            "Capacity_data_15", "Capacity_data_16", "Capacity_data_17", "Capacity_data_18", "Capacity_data_19",
+            "Capacity_data_34", "Formula_data_24", "Formula_data_15", "Capacity_data_1"
+    };
+
+
+    /**
+     * 字段列表,方便查找位置
+     */
+    private final List<String> fieldList = Arrays.stream(fields).collect(Collectors.toList());
+
+    @Async("threadPoolTaskExecutor")
+    public Future<Map<String, Object>> currData(TwinDevice twinDevice) {
+        String table = twinDevice.getDevicePath();
+        String sql = "select last * from " + table;
+        JSONObject jsonObject = iotService.query(sql);
+        JSONObject data = jsonObject.getJSONObject("data");
+        JSONArray values = data.getJSONArray("values");
+        JSONArray timestamps = data.getJSONArray("timestamps");
+        Map<String, Object> dataMap = new HashMap<>();
+        dataMap.put("device", twinDevice);
+        if (timestamps.size() > 0 && (System.currentTimeMillis() - new Date(timestamps.getLong(0)).getTime()) > 5 * 60 * 100) {
+            //如果最后一条记录 超过5分钟,则视为无效记录
+            dataMap.put("total", 0);
+        } else {
+            dataMap.put("total", values.size());
+            dataMap.putAll(Tools.json2Map(values, table));
+        }
+        return new AsyncResult<>(dataMap);
+    }
+
+    /**
+     * 根据设备获取指定时段数据
+     *
+     * @param yhj   印花机设备
+     * @param start 开始时间
+     * @param end   结束时间
+     * @return
+     */
+    @Async("threadPoolTaskExecutor")
+    public Future<TwinCalcHourYhj> process(TwinDeviceYhj yhj, LocalDateTime start, LocalDateTime end) {
+        Long startTime = start.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        Long endTime = end.toInstant(ZoneOffset.of("+8")).toEpochMilli();
+        TwinCalcHourYhj calcYhj = new TwinCalcHourYhj();
+        String[] fields = {"Formula_data_set_1", "Formula_data_act_5"};
+
+        String sql = "select %s from " + yhj.getDevicePath() + " where time>%s and time <=%s";
+
+        sql = String.format(sql, String.join(",", fields), startTime, endTime);
+        JSONObject jsonObject = iotService.query(sql);
+        JSONObject data = jsonObject.getJSONObject("data");
+        JSONArray columnNames = data.getJSONArray("columnNames");
+        JSONArray values = data.getJSONArray("values");
+        JSONArray timestamps = data.getJSONArray("timestamps");
+        //记录上一次记录的值
+        Integer[] last = new Integer[columnNames.size()];
+        //记录最后一次的值,防中间有数,后面没数
+        Integer[] over = new Integer[columnNames.size()];
+        //当前记录值
+        Integer[] curr = new Integer[columnNames.size()];
+        //记录第一次记录的值,如果清0,则记录清零时刻的值
+        Integer[] first = new Integer[columnNames.size()];
+        //记录统计值
+        Integer[] total = new Integer[columnNames.size()];
+        for (int i = 0; i < values.size(); i++) {
+            JSONArray da = values.getJSONArray(i);
+            da.toList(Integer.class).toArray(curr);
+            if (i == 0) {
+                cloneArray(curr, last);
+                cloneArray(curr, first);
+                cloneArray(curr, over);
+                continue;
+            }
+            for (int j = 0; j < columnNames.size(); j++) {
+                String name = columnNames.getStr(j);
+                if (name.contains("Formula_data_set_1")) {
+                    //如果是版距,则需要记录变化
+                    if (curr[j] != null && last[j] != null && curr[j].intValue() != last[j].intValue()) {
+                        //这里要用j+1才行
+                        calcLength(j + 1, last, first, total);
+                        combo(calcYhj, start, yhj, last[j], total[j + 1]);
+                        total[j + 1] = 0;
+                    }
+                }
+                if (name.contains("Formula_data_act_5")) {
+                    //如果是米长,则需要记录是否清0
+                    //如果当前值为小于上一个,且上一个值不为0,则计算
+                    //因为会出现数据波动,停机再启动之后的第一个点不为0,为0.00几几几的
+                    if (curr[j] != null && last[j] != null && curr[j] < last[j] && last[j] != 0) {
+                        calcLength(j, last, first, total);
+                        cloneArray(curr, first);
+                    }
+                }
+            }
+            //将本次的值,设为上一条记录了
+            cloneArray(curr, last);
+            cloneArray(curr, over);
+            cloneArrayFirst(curr, first);
+        }
+        for (int j = 0; j < columnNames.size(); j++) {
+            String name = columnNames.getStr(j);
+            if (name.contains("Formula_data_set_1")) {
+                calcLength(j + 1, over, first, total);
+                combo(calcYhj, start, yhj, over[j], total[j + 1]);
+            }
+        }
+
+        return new AsyncResult<>(calcYhj);
+    }
+
+
+    /**
+     * 初始值,如果当前值不为空,并且原来值为空
+     */
+    void cloneArrayFirst(Integer[] arr, Integer[] target) {
+        for (int i = 0; i < arr.length; i++) {
+            if (arr[i] != null && target[i] == null) {
+                target[i] = arr[i];
+            }
+        }
+    }
+
+    /**
+     * 复制数组,如果当前值不为空
+     */
+    void cloneArray(Integer[] arr, Integer[] target) {
+        for (int i = 0; i < arr.length; i++) {
+            if (arr[i] != null) {
+                target[i] = arr[i];
+            }
+        }
+    }
+
+    /**
+     * 组合入库数据
+     */
+    void combo(TwinCalcHourYhj calcYhj, LocalDateTime start, TwinDeviceYhj yhj, Integer distance, Integer length) {
+        if (distance != null && length != null) {
+            calcYhj.setDeviceId(yhj.getDeviceId());
+            calcYhj.setDataDate(DateUtils.toDate(start.toLocalDate()));
+            calcYhj.setHour(start.getHour());
+            calcYhj.setDistance(distance);
+            calcYhj.setLength(length);
+        }
+    }
+
+    /**
+     * 计算米长
+     */
+    void calcLength(int j, Integer[] last, Integer[] first, Integer[] total) {
+        if (last[j] != null && first[j] != null) {
+            if (total[j] == null) {
+                total[j] = 0;
+            }
+            total[j] += (last[j] - first[j]);
+        }
+    }
+}

+ 4 - 1
jjt-biz/src/main/resources/mapper/calc/TwinCalcHourYhjMapper.xml

@@ -34,6 +34,7 @@
                 and DATEADD(hour, HOUR, DATA_DATE) between #{params.sTime} and #{params.eTime}
             </if>
         </where>
+        order by id desc
     </select>
 
     <select id="selectTwinCalcHourYhjById" parameterType="Long" resultMap="TwinCalcHourYhjResult">
@@ -41,7 +42,9 @@
         where ID = #{id}
     </select>
     <select id="lastRecord" resultType="com.jjt.calc.domain.TwinCalcHourYhj">
-        select top 1 * from TWIN_CALC_HOUR_YHJ order by id desc
+        select top 1 *
+        from TWIN_CALC_HOUR_YHJ
+        order by id desc
     </select>
 
     <insert id="insertTwinCalcHourYhj" parameterType="TwinCalcHourYhj">