|
@@ -0,0 +1,318 @@
|
|
|
|
+package com.imcs.admin.common.collection;
|
|
|
|
+
|
|
|
|
+import cn.hutool.core.collection.CollectionUtil;
|
|
|
|
+import cn.hutool.core.date.DateUnit;
|
|
|
|
+import cn.hutool.core.date.DateUtil;
|
|
|
|
+import cn.hutool.json.JSONArray;
|
|
|
|
+import cn.hutool.json.JSONObject;
|
|
|
|
+import cn.hutool.json.JSONUtil;
|
|
|
|
+import com.imcs.admin.db.service.JdbcService;
|
|
|
|
+import lombok.extern.slf4j.Slf4j;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
|
+import org.springframework.http.HttpEntity;
|
|
|
|
+import org.springframework.http.HttpHeaders;
|
|
|
|
+import org.springframework.http.MediaType;
|
|
|
|
+import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
+import org.springframework.web.client.RestTemplate;
|
|
|
|
+
|
|
|
|
+import java.io.BufferedWriter;
|
|
|
|
+import java.io.File;
|
|
|
|
+import java.io.FileWriter;
|
|
|
|
+import java.io.IOException;
|
|
|
|
+import java.math.BigDecimal;
|
|
|
|
+import java.util.*;
|
|
|
|
+import java.util.concurrent.CompletableFuture;
|
|
|
|
+
|
|
|
|
+@Component
|
|
|
|
+@Slf4j
|
|
|
|
+public class DeviceCollectionTaskJob {
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private RestTemplate restTemplate;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private RedisTemplate<String,String> redisTemplate;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private JdbcService jdbcService;
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设备采集任务FANUC
|
|
|
|
+ * FANUC
|
|
|
|
+ */
|
|
|
|
+ @Scheduled(cron = "0/5 * * * * *")
|
|
|
|
+ void deviceCollectionTaskFanuc() throws Exception {
|
|
|
|
+ Object fanucObj = this.redisGet("FANUC_COLLECTION");
|
|
|
|
+ this.executorHandle(fanucObj);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设备采集任务Opcua
|
|
|
|
+ * 西门子
|
|
|
|
+ */
|
|
|
|
+ @Scheduled(cron = "0/5 * * * * *")
|
|
|
|
+ void deviceCollectionTaskOpcua() throws Exception {
|
|
|
|
+ Object opcuaObj = this.redisGet("OPCUA_COLLECTION");
|
|
|
|
+ this.executorHandle(opcuaObj);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设备采集任务Heidenhain
|
|
|
|
+ * 海德汉
|
|
|
|
+ */
|
|
|
|
+ @Scheduled(cron = "0/5 * * * * *")
|
|
|
|
+ void deviceCollectionTaskHeidenhain() throws Exception {
|
|
|
|
+ Object heidenhainObj = this.redisGet("HEIDENHAIN_COLLECTION");
|
|
|
|
+ this.executorHandle(heidenhainObj);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设备采集任务Mitsubishi
|
|
|
|
+ * 三菱
|
|
|
|
+ */
|
|
|
|
+ @Scheduled(cron = "0/5 * * * * *")
|
|
|
|
+ void deviceCollectionTaskMitsubishi() throws Exception {
|
|
|
|
+ Object mitsubishiObj = this.redisGet("MITSUBISHI_COLLECTION");
|
|
|
|
+ this.executorHandle(mitsubishiObj);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 设备采集任务MtConnect
|
|
|
|
+ * 赫克
|
|
|
|
+ */
|
|
|
|
+ @Scheduled(cron = "0/5 * * * * *")
|
|
|
|
+ void deviceCollectionTaskMtConnect() throws Exception {
|
|
|
|
+ Object mtConnectObj = this.redisGet("MTCONNECT_COLLECTION");
|
|
|
|
+ this.executorHandle(mtConnectObj);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 多线程处理
|
|
|
|
+ */
|
|
|
|
+ public void executorHandle(Object obj){
|
|
|
|
+ if(obj !=null){
|
|
|
|
+ JSONArray jsonArray = JSONUtil.parseArray(obj);
|
|
|
|
+ List<Map> list = JSONUtil.toList(jsonArray, Map.class);
|
|
|
|
+ CompletableFuture[] task = list.stream().map(map -> CompletableFuture.runAsync(() -> {
|
|
|
|
+ map.put("type","Collect");
|
|
|
|
+ // if("192.168.10.101".equals(map.get("serverUrl").toString())){
|
|
|
|
+ String data = JSONUtil.toJsonStr(map);
|
|
|
|
+ String returnInfo = this.httpPost(data);
|
|
|
|
+ if(returnInfo !=null){
|
|
|
|
+ JSONObject returnJson = JSONUtil.parseObj(returnInfo);
|
|
|
|
+ if((boolean)returnJson.get("result")){
|
|
|
|
+ this.saveOrUpdateDeviceCollection(returnJson,map.get("serverUrl"));
|
|
|
|
+ this.saveOrUpdateDeviceCollectionDetail(returnJson,map.get("serverUrl"));
|
|
|
|
+ this.deviceCollectionInfoWriteFile(returnJson,map.get("serverUrl"));
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ // }
|
|
|
|
+
|
|
|
|
+ })).toArray(CompletableFuture[]::new);
|
|
|
|
+ CompletableFuture.allOf(task).join();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 新增或更新设备采集表信息
|
|
|
|
+ * @param returnJson
|
|
|
|
+ * @param ip
|
|
|
|
+ */
|
|
|
|
+ public void saveOrUpdateDeviceCollection(JSONObject returnJson,Object ip){
|
|
|
|
+ //组装参数,更新设备采集表
|
|
|
|
+ JSONObject deviceInfo = new JSONObject();
|
|
|
|
+ deviceInfo.putOnce("mainProg",returnJson.get("mainProg"));
|
|
|
|
+ deviceInfo.putOnce("actFeed",returnJson.get("actFeed"));
|
|
|
|
+ deviceInfo.putOnce("spindleMagnification",returnJson.get("spindleMagnification"));
|
|
|
|
+ deviceInfo.putOnce("actSpindle",returnJson.get("actSpindle"));
|
|
|
|
+ deviceInfo.putOnce("powerOnTime",returnJson.get("powerOnTime"));
|
|
|
|
+ deviceInfo.putOnce("deviceState",returnJson.get("deviceState"));
|
|
|
|
+
|
|
|
|
+ Map<String, Object> deviceCollection = jdbcService.findOne("select * from device_collection where ip = ? ", ip);
|
|
|
|
+
|
|
|
|
+ if(CollectionUtil.isNotEmpty(deviceCollection)){
|
|
|
|
+ //更新
|
|
|
|
+ String sql = "update device_collection set device_info = ? , update_time = ? where id = ? ";
|
|
|
|
+ jdbcService.update("更新",sql,deviceInfo.toString(), DateUtil.format(new Date(),"yyyy-MM-dd HH:mm:ss"),deviceCollection.get("id"));
|
|
|
|
+ }else{
|
|
|
|
+ //新增
|
|
|
|
+ Map<String, Object> device = jdbcService.findOne("select * from a_device where ip = ? ", ip);
|
|
|
|
+ if(CollectionUtil.isNotEmpty(device)){
|
|
|
|
+ Object deviceId = device.get("id");
|
|
|
|
+ String sql = "insert into device_collection (device_id,device_info,ip) values(?,?,?) ";
|
|
|
|
+ jdbcService.insert(sql,deviceId,deviceInfo.toString(),ip);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ /**
|
|
|
|
+ * 新增或更新设备采集明细表信息
|
|
|
|
+ * @param returnJson
|
|
|
|
+ * @param ip
|
|
|
|
+ */
|
|
|
|
+ public void saveOrUpdateDeviceCollectionDetail(JSONObject returnJson,Object ip){
|
|
|
|
+
|
|
|
|
+ Map<String,Object> map = new HashMap<>();
|
|
|
|
+ map.put("mainProg",returnJson.get("mainProg"));
|
|
|
|
+ map.put("actFeed",returnJson.get("actFeed"));
|
|
|
|
+ map.put("spindleMagnification",returnJson.get("spindleMagnification"));
|
|
|
|
+ map.put("actSpindle",returnJson.get("actSpindle"));
|
|
|
|
+ map.put("powerOnTime",returnJson.get("powerOnTime"));
|
|
|
|
+ map.put("deviceState",returnJson.get("deviceState"));
|
|
|
|
+
|
|
|
|
+ Object powerOnTime = returnJson.get("powerOnTime"); //当前设备开机总时长(分钟)
|
|
|
|
+
|
|
|
|
+ Date date = new Date();
|
|
|
|
+ String nowDate = DateUtil.format(date, "yyyy-MM-dd");
|
|
|
|
+
|
|
|
|
+ Map<String, Object> deviceCollectionDetailInfoMap = jdbcService.findOne("select id,device_rate,today_earliest_power_on_time,detail_info from device_collection_detail where device_ip = ? and create_date = ?", ip,nowDate);
|
|
|
|
+
|
|
|
|
+ String detailInfo = "";
|
|
|
|
+ if(CollectionUtil.isNotEmpty(deviceCollectionDetailInfoMap)){
|
|
|
|
+
|
|
|
|
+ //更新
|
|
|
|
+ Object deviceCollectionDetailInfo = deviceCollectionDetailInfoMap.get("detailInfo");
|
|
|
|
+
|
|
|
|
+ //最近的上一次采集开机总时长
|
|
|
|
+ BigDecimal hisPowerOnTime = BigDecimal.ZERO;
|
|
|
|
+
|
|
|
|
+ if(!Objects.isNull(deviceCollectionDetailInfo)){
|
|
|
|
+ JSONArray jsonArray = JSONUtil.parseArray(deviceCollectionDetailInfo.toString());
|
|
|
|
+ List<Map> list = JSONUtil.toList(jsonArray, Map.class);
|
|
|
|
+ if(CollectionUtil.isNotEmpty(list)){
|
|
|
|
+ //最近的上一次采集开机总时长
|
|
|
|
+ Object histPowerOnTimeObj = list.get(0).get("powerOnTime");
|
|
|
|
+
|
|
|
|
+ if(!Objects.isNull(histPowerOnTimeObj)){
|
|
|
|
+ hisPowerOnTime = new BigDecimal(histPowerOnTimeObj.toString());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(list.size()>=5) {
|
|
|
|
+ list.remove(list.size() - 1); //移除最后一个
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ list.add(0,map); //头插法
|
|
|
|
+ detailInfo = JSONUtil.toJsonStr(list);
|
|
|
|
+ }
|
|
|
|
+ }else {
|
|
|
|
+ List<Map> list = new ArrayList<>();
|
|
|
|
+ list.add(map);
|
|
|
|
+ detailInfo = JSONUtil.toJsonStr(list);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ //当日设备开机时长
|
|
|
|
+ Object todayPowerOnTimeObj = deviceCollectionDetailInfoMap.get("todayPowerOnTime");
|
|
|
|
+ //设备主轴利用率
|
|
|
|
+ Object deviceRateObj = deviceCollectionDetailInfoMap.get("deviceRate");
|
|
|
|
+
|
|
|
|
+ BigDecimal todayPowerOnTime = BigDecimal.ZERO;
|
|
|
|
+ if(!Objects.isNull(todayPowerOnTimeObj)){
|
|
|
|
+ todayPowerOnTime = new BigDecimal(todayPowerOnTimeObj.toString());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ BigDecimal deviceRate = BigDecimal.ZERO;
|
|
|
|
+ if(!Objects.isNull(deviceRateObj)){
|
|
|
|
+ deviceRate = new BigDecimal(deviceRateObj.toString());
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if(!Objects.isNull(returnJson.get("deviceState")) && "在线".equals(returnJson.get("deviceState").toString())){
|
|
|
|
+ BigDecimal currentPowerOnTime = new BigDecimal(powerOnTime.toString());
|
|
|
|
+ // 间隔时间 = 当前开机总时长 - 最近的上一次采集开机总时长
|
|
|
|
+ BigDecimal intervalTime = currentPowerOnTime.subtract(hisPowerOnTime);
|
|
|
|
+ //当日设备开机时长 = 当日设备开机时长 + 间隔时间
|
|
|
|
+ todayPowerOnTime = todayPowerOnTime.add(intervalTime);
|
|
|
|
+
|
|
|
|
+ String startDate = nowDate + " " + "08:00:00"; //默认早上八点
|
|
|
|
+
|
|
|
|
+ //计算设备利用率
|
|
|
|
+ long workhour = DateUtil.between(DateUtil.parse(startDate), date, DateUnit.MINUTE);//当天的实际工作时长(分钟)
|
|
|
|
+
|
|
|
|
+ BigDecimal sumBig = new BigDecimal(workhour);
|
|
|
|
+ deviceRate = todayPowerOnTime.divide(sumBig, 2, BigDecimal.ROUND_HALF_UP).multiply(new BigDecimal("100"));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ String sql = "update device_collection_detail set detail_info = ? , device_rate = ? , today_power_on_time = ? where id = ? ";
|
|
|
|
+ jdbcService.update("更新",sql,detailInfo, deviceRate,todayPowerOnTime,deviceCollectionDetailInfoMap.get("id"));
|
|
|
|
+
|
|
|
|
+ }else{
|
|
|
|
+ //新增
|
|
|
|
+ List<Map> list = new ArrayList<>();
|
|
|
|
+ list.add(map);
|
|
|
|
+ detailInfo = JSONUtil.toJsonStr(list);
|
|
|
|
+
|
|
|
|
+ String sql = "insert into device_collection_detail (device_rate,today_earliest_power_on_time,detail_info,create_date,device_ip) values(?,?,?,?,?) ";
|
|
|
|
+ jdbcService.insert(sql,0,Long.parseLong(powerOnTime.toString()),detailInfo,nowDate,ip);
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void deviceCollectionInfoWriteFile(JSONObject returnJson,Object ip){
|
|
|
|
+ Date date = new Date();
|
|
|
|
+ String nowDate = DateUtil.format(date, "yyyy-MM-dd");
|
|
|
|
+
|
|
|
|
+ String folderPath = "D:\\collection" + File.separator + DateUtil.format(date, "yyyy-MM");
|
|
|
|
+
|
|
|
|
+ // 创建文件夹(如果不存在)
|
|
|
|
+ File folder = new File(folderPath);
|
|
|
|
+ if (!folder.exists()) {
|
|
|
|
+ folder.mkdirs();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 构建文件名,以每天 + ip 一个文件
|
|
|
|
+ String fileName = ip + "_" + nowDate + ".txt";
|
|
|
|
+
|
|
|
|
+ String filePath = folderPath + File.separator + fileName;
|
|
|
|
+
|
|
|
|
+ // 写入数据到文件
|
|
|
|
+ try (BufferedWriter writer = new BufferedWriter(new FileWriter(filePath, true))) {
|
|
|
|
+
|
|
|
|
+ String deviceCollectionInfo = JSONUtil.toJsonStr(returnJson);
|
|
|
|
+
|
|
|
|
+ String data = DateUtil.format(date, "yyyy-MM-dd HH:mm:ss") + ":" + deviceCollectionInfo;
|
|
|
|
+
|
|
|
|
+ // 追加写入数据,并在每条数据后面添加换行符
|
|
|
|
+ writer.write(data + System.lineSeparator());
|
|
|
|
+ } catch (IOException e) {
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public String redisGet(String key){
|
|
|
|
+ return redisTemplate.opsForValue().get(key);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public String httpPost(String data){
|
|
|
|
+ log.info("请求参数:{}",data);
|
|
|
|
+ //组装接口参数
|
|
|
|
+ HttpHeaders headers = new HttpHeaders();
|
|
|
|
+ headers.setContentType(MediaType.parseMediaType("application/json;charset=UTF-8"));
|
|
|
|
+ HttpEntity<String> formEntity = new HttpEntity<String>(data, headers);
|
|
|
|
+ String url = "http://localhost:9000/DeviceApi";
|
|
|
|
+ String returnInfo = null;
|
|
|
|
+ try{
|
|
|
|
+ // returnInfo = restTemplate.postForObject(url, formEntity, String.class);
|
|
|
|
+ }catch (Exception e){
|
|
|
|
+ e.printStackTrace();
|
|
|
|
+ log.info("连接报错,参数:{}",data);
|
|
|
|
+ }
|
|
|
|
+ returnInfo = "{" +
|
|
|
|
+ "code:0," +
|
|
|
|
+ "result:true," +
|
|
|
|
+ "msg:调用成功," +
|
|
|
|
+ "statusCode:200," +
|
|
|
|
+ "mainProg:7777," +
|
|
|
|
+ "actFeed:2," +
|
|
|
|
+ "spindleMagnification:2," +
|
|
|
|
+ "actSpindle:1," +
|
|
|
|
+ "powerOnTime:26947355," +
|
|
|
|
+ "deviceState:不在线" +
|
|
|
|
+ "}";
|
|
|
|
+ log.info("返回值:{}",returnInfo);
|
|
|
|
+ return returnInfo;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|