| | |
| | | */ |
| | | public class ElongationMqttConstants { |
| | | public final static String NSTSSC_TSSC_SCL = "NSTSSC.TSSC.SCL"; |
| | | public final static String NSTSSC1_TSSC_SCL = "NSTSSC1.TSSC.SCL"; |
| | | |
| | | public final static String NSTSSC_TSSC_LSSDSD = "NSTSSC.TSSC.LSSDSD"; |
| | | |
| | |
| | | switch (topic){ |
| | | case "/ztt/v3/2455220/publish": |
| | | //耐丝:直流电阻数据解析NS-ER02001 |
| | | mqCallback.collectBridgeService.dcResistanceDataAnalysis(parse); |
| | | mqCallback.collectBridgeService.dcResistanceDataAnalysis(parse,"NS-ER02001"); |
| | | break; |
| | | // case "/aiot/8fac9fa0-c517-11f0-954c-255ce11213f1": |
| | | // //耐丝:直流电阻数据解析NS-ER02002 |
| | | // mqCallback.collectBridgeService.dcResistanceDataAnalysis(parse,"NS-ER02002"); |
| | | // break; |
| | | case "/ztt/v3/2455221/publish": |
| | | //耐丝:伸长率数据解析NS-FM05003 |
| | | mqCallback.collectBridgeService.elongationDataAnalysis(parse); |
| | | mqCallback.collectBridgeService.elongationDataAnalysis(parse,"NS-FM05003"); |
| | | // break; |
| | | // case "/aiot/38568140-c697-11f0-8b13-c14e8310d70b": |
| | | // //耐丝:伸长率数据解析NS-FM05002 |
| | | // mqCallback.collectBridgeService.elongationDataAnalysis(parse,"NS-FM05002"); |
| | | break; |
| | | } |
| | | } catch (Exception e) { |
| | |
| | | @ApiModelProperty("委托编号") |
| | | private String entrustCode; |
| | | |
| | | @ApiModelProperty("设备编号") |
| | | private String deviceCode; |
| | | |
| | | @ApiModelProperty("采集值") |
| | | private BigDecimal collectValue; |
| | | |
| | |
| | | @ApiModelProperty("最后一次采集时间") |
| | | private LocalDateTime lastCollectDate; |
| | | |
| | | public CollectBridge(String entrustCode, BigDecimal collectValue, Double collectTemperature, LocalDateTime firstCollectDate, LocalDateTime lastCollectDate) { |
| | | public CollectBridge(String entrustCode,String deviceCode, BigDecimal collectValue, Double collectTemperature, LocalDateTime firstCollectDate, LocalDateTime lastCollectDate) { |
| | | this.entrustCode = entrustCode; |
| | | this.deviceCode = deviceCode; |
| | | this.collectValue = collectValue; |
| | | this.collectTemperature = collectTemperature; |
| | | this.firstCollectDate = firstCollectDate; |
| | |
| | | */ |
| | | void addBridgeValue(JSONObject jsonObject); |
| | | |
| | | void dcResistanceDataAnalysis(String jsonStr); |
| | | void dcResistanceDataAnalysis(String jsonStr,String deviceCode); |
| | | |
| | | void elongationDataAnalysis(String jsonStr); |
| | | void elongationDataAnalysis(String jsonStr,String deviceCode); |
| | | } |
| | | |
| | |
| | | import lombok.extern.slf4j.Slf4j; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.stereotype.Service; |
| | | import org.springframework.transaction.annotation.Transactional; |
| | | |
| | | import java.math.BigDecimal; |
| | | import java.math.RoundingMode; |
| | | import java.time.Duration; |
| | | import java.time.Instant; |
| | | import java.time.LocalDateTime; |
| | | import java.time.ZoneId; |
| | | import java.util.List; |
| | | import java.util.Map; |
| | | import java.util.Objects; |
| | |
| | | } |
| | | |
| | | @Override |
| | | public void dcResistanceDataAnalysis(String jsonStr) { |
| | | @Transactional(rollbackFor = Exception.class) |
| | | public void dcResistanceDataAnalysis(String jsonStr,String deviceCode) { |
| | | Map<String, Object> dataMap = JSONObject.parseObject(jsonStr, new TypeReference<Map<String, Object>>(){}.getType()); |
| | | if(CollectionUtil.isNotEmpty(dataMap) && Objects.nonNull(dataMap.get("data"))){ |
| | | List<DeviceMqttVO> dataList = JSONArray.parseObject(dataMap.get("data").toString(), new TypeReference<List<DeviceMqttVO>>(){}.getType()); |
| | |
| | | .set(CollectBridge::getCollectValue,value) |
| | | .set(CollectBridge::getCollectTemperature,tempValue) |
| | | .set(CollectBridge::getLastCollectDate,LocalDateTime.now()) |
| | | .eq(CollectBridge::getDeviceCode,deviceCode) |
| | | .eq(CollectBridge::getEntrustCode,entrustCode)); |
| | | }else{ |
| | | collectBridgeMapper.insert(new CollectBridge(entrustCode,value,tempValue,LocalDateTime.now(),LocalDateTime.now())); |
| | | collectBridgeMapper.insert(new CollectBridge(entrustCode,deviceCode,value,tempValue,LocalDateTime.now(),LocalDateTime.now())); |
| | | } |
| | | } |
| | | } |
| | | |
| | | @Override |
| | | public void elongationDataAnalysis(String jsonStr) { |
| | | public void elongationDataAnalysis(String jsonStr,String deviceCode) { |
| | | Map<String, Object> dataMap = JSONObject.parseObject(jsonStr, new TypeReference<Map<String, Object>>(){}.getType()); |
| | | if(CollectionUtil.isNotEmpty(dataMap) && Objects.nonNull(dataMap.get("data"))){ |
| | | List<DeviceMqttVO> dataList = JSONArray.parseObject(dataMap.get("data").toString(), new TypeReference<List<DeviceMqttVO>>(){}.getType()); |
| | | // 伸长率:处理 NSTSSC.TSSC.SCL 数据 |
| | | processMultipleValueDataStream(dataList, ElongationMqttConstants.NSTSSC_TSSC_SCL,3,10.0); |
| | | processMultipleValueDataStream(dataList, ElongationMqttConstants.NSTSSC_TSSC_SCL,3,10.0,deviceCode); |
| | | }else{ |
| | | processMultipleValueDataStream(dataMap, ElongationMqttConstants.NSTSSC1_TSSC_SCL,3,10.0,deviceCode); |
| | | } |
| | | } |
| | | |
| | |
| | | * @param dataStream 数据流标识 |
| | | * @param maxSize 保存的最大个数 |
| | | * @param minVal 存储数据的最小值,低于该值则跳过;-1代表不限制 |
| | | * @param deviceCode 设备编号 |
| | | */ |
| | | private void processMultipleValueDataStream(List<DeviceMqttVO> dataList, String dataStream,int maxSize,Double minVal){ |
| | | private void processMultipleValueDataStream(List<DeviceMqttVO> dataList, String dataStream,int maxSize,Double minVal,String deviceCode){ |
| | | // 筛选出当前数据流对应的数据 |
| | | Double value = Double.parseDouble(getValueByDataStream(dataList, dataStream)); |
| | | // Double value = BigDecimal.valueOf(Math.random()*100).setScale(7, RoundingMode.HALF_EVEN).doubleValue(); |
| | | //如果最小值不为空且不为-1,获取到的值小于最小值则跳过不做处理 |
| | | if(Objects.nonNull(minVal)&&minVal!=-1&&value<minVal){ |
| | | return; |
| | |
| | | RedisUtil.delZSetRange(dataStream,0,0); |
| | | } |
| | | } |
| | | RedisUtil.addZSet(dataStream,System.currentTimeMillis(),value); |
| | | RedisUtil.addZSet(dataStream+"."+deviceCode,System.currentTimeMillis(),value); |
| | | } |
| | | |
| | | /** |
| | | * 处理需要保存多个值的数据流,并保存到 Redis |
| | | * @param dataMap 数据列表 |
| | | * @param dataStream 数据流标识 |
| | | * @param maxSize 保存的最大个数 |
| | | * @param minVal 存储数据的最小值,低于该值则跳过;-1代表不限制 |
| | | * @param deviceCode 设备编号 |
| | | */ |
| | | private void processMultipleValueDataStream(Map<String,Object> dataMap, String dataStream,int maxSize,Double minVal,String deviceCode){ |
| | | // 筛选出当前数据流对应的数据 |
| | | Double value = Double.parseDouble(dataMap.get(dataStream).toString()); |
| | | //如果最小值不为空且不为-1,获取到的值小于最小值则跳过不做处理 |
| | | if(Objects.nonNull(minVal)&&minVal!=-1&&value<minVal){ |
| | | return; |
| | | } |
| | | //判断key是否存在 |
| | | boolean existKey = RedisUtil.hasKey(dataStream); |
| | | if(existKey){ |
| | | long zSetSize = RedisUtil.getZSetSize(dataStream); |
| | | //如果数据长度超过最大个数,则删除分数最低的数据 |
| | | if(zSetSize>=maxSize){ |
| | | RedisUtil.delZSetRange(dataStream,0,0); |
| | | } |
| | | } |
| | | RedisUtil.addZSet(dataStream+"."+deviceCode,System.currentTimeMillis(),value); |
| | | } |
| | | |
| | | /** |
| | |
| | | String dbPassword = StringUtils.isNotBlank(dto.getDbPassword())?dto.getDbPassword():""; |
| | | String dbTable = StringUtils.isNotBlank(dto.getDbTable())?dto.getDbTable():""; |
| | | map.putAll(DataAcquisition.dataAcquisitionEntrance(list, device, dto.getEntrustCode(), dto.getLotBatchNo(),dto.getLotBatchNo(), ip, insProducts.get(0).getCableTag(),dbUserName,dbPassword,dbTable)); |
| | | if(StringUtils.equals(".mysql",device.getFileType())){ |
| | | |
| | | }else{ |
| | | } |
| | | } |
| | | } |
| | | |
| | |
| | | list.add(2,collectBridge.getCollectValue());//实际电阻值 |
| | | }else { |
| | | // 从 Redis 中获取列表数据 |
| | | Set<Object> objectList = RedisUtil.getZSetRange(refery, 0, -1); |
| | | Set<Object> objectList = RedisUtil.getZSetRange(refery, 0, -1,"DESC"); |
| | | list.addAll(objectList); |
| | | } |
| | | numberOfDataEntries.getAndIncrement(); |
| | |
| | | case ".docx": |
| | | map = analysisString(data, userMap, device, entrustCode, sampleCode); |
| | | break; |
| | | case ".xls": |
| | | case ".xlsx": |
| | | map = analysisList(data, userMap, device, entrustCode, sampleCode); |
| | | break; |
| | | case ".xls": |
| | | map = analysisTxt(data, userMap, device, entrustCode, sampleCode); |
| | | case ".pngInExcel": |
| | | map = analysisPngInExcel(data, userMap, device, entrustCode, sampleCode); |
| | | break; |
| | | case ".txt": |
| | | map = analysisTxt(data, userMap, device, entrustCode, sampleCode); |
| | |
| | | } |
| | | |
| | | /** |
| | | * 解析excel中识别到的图片内容 |
| | | * |
| | | * @param data 采集到的文件字符串 |
| | | * @param dataConfig 用户配置好的x,y轴定位数据与参照物 |
| | | * @return |
| | | */ |
| | | private static Map<String, Object> analysisPngInExcel(String data, Map<String, List<DataConfig>> dataConfig, |
| | | Device device, String entrustCode, String sampleCode) { |
| | | Map<String, Object> map = new HashMap<>(); |
| | | //处理data |
| | | Map<String,List<Object>> dataMap = new HashMap<>(); |
| | | String[] rows = data.split("\n"); |
| | | String[] headRow = rows[0].split(" ");//获取表头列表 |
| | | for (int i = 0; i < headRow.length; i++) { |
| | | //数据最多五条 |
| | | List<Object> vals = new ArrayList<>(); |
| | | for (int j = 1; j <= 5; j++) { |
| | | String[] cols = rows[j].split(" "); |
| | | vals.add(cols[i]); |
| | | } |
| | | dataMap.put(headRow[i],vals); |
| | | } |
| | | dataConfig.forEach((k, v) -> { |
| | | List<Object> list = new ArrayList<>(); |
| | | v.stream().sorted(Comparator.comparing(DataConfig::getX)).forEach(config->{ |
| | | for (Map.Entry<String, List<Object>> entry : dataMap.entrySet()) { |
| | | if(entry.getKey().contains(config.getReferx())){ |
| | | list.addAll(entry.getValue()); |
| | | } |
| | | } |
| | | }); |
| | | // 进行公式计算 |
| | | Object resultValue = calculationFormula(list, v.get(0), k, device); |
| | | map.put(k, resultValue); |
| | | }); |
| | | return map; |
| | | } |
| | | |
| | | /** |
| | | * @param data 采集到的文件字符串 |
| | | * @param dataConfig 用户配置好的x,y轴定位数据与参照物 |
| | | * @return |
| | |
| | | lettuce: |
| | | pool: |
| | | # 连接池中的最小空闲连接 |
| | | min-idle: 0 |
| | | min-idle: 2 |
| | | # 连接池中的最大空闲连接 |
| | | max-idle: 8 |
| | | # 连接池的最大数据库连接数 |
| | |
| | | completion-timeout: 3000 # 连接超时时间(单位:秒) |
| | | clientId: ztns01a # clientId |
| | | subscribe: /ztt/v3/2455220/publish # 订阅主题 |
| | | client: true # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | | client: false # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | | - url: tcp://mqtt-ztt.zttiot.com:1883 # 服务器ip |
| | | username: 2455221 # MQTT-服务端-用户名,后期会修改为用户登录名 |
| | | password: 108295 # MQTT-服务端-密码,,后期会修改为用户登录密码 |
| | |
| | | completion-timeout: 3000 # 连接超时时间(单位:秒) |
| | | clientId: ztns02b # clientId |
| | | subscribe: /ztt/v3/2455221/publish # 订阅主题 |
| | | client: true # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | | |
| | | client: false # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | | - url: tcp://mqtt.ztt.cn:1883 # 服务器ip |
| | | username: admin # MQTT-服务端-用户名,后期会修改为用户登录名 |
| | | password: public # MQTT-服务端-密码,,后期会修改为用户登录密码 |
| | | timeout: 100 # 超时时间 (单位:秒) |
| | | keepalive: 60 # 心跳 (单位:秒) |
| | | qos: 1 # 心跳包级别 |
| | | completion-timeout: 3000 # 连接超时时间(单位:秒) |
| | | clientId: ztns_gc_scl_108303 # clientId,过程试验室伸长率设备 |
| | | subscribe: /aiot/38568140-c697-11f0-8b13-c14e8310d70b # 订阅主题 |
| | | client: false # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | | - url: tcp://mqtt.ztt.cn.com:1883 # 服务器ip |
| | | username: admin # MQTT-服务端-用户名,后期会修改为用户登录名 |
| | | password: public # MQTT-服务端-密码,,后期会修改为用户登录密码 |
| | | timeout: 100 # 超时时间 (单位:秒) |
| | | keepalive: 60 # 心跳 (单位:秒) |
| | | qos: 1 # 心跳包级别 |
| | | completion-timeout: 3000 # 连接超时时间(单位:秒) |
| | | clientId: ztns_gc_dz_108301 # clientId |
| | | subscribe: /aiot/8fac9fa0-c517-11f0-954c-255ce11213f1 # 订阅主题 |
| | | client: false # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | |
| | | clientId: ztns02 # clientId |
| | | subscribe: /ztt/v3/2455221/publish # 订阅主题 |
| | | client: true # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | | # - url: tcp://mqtt.ztt.cn:1883 # 服务器ip |
| | | # username: admin # MQTT-服务端-用户名,后期会修改为用户登录名 |
| | | # password: public # MQTT-服务端-密码,,后期会修改为用户登录密码 |
| | | # timeout: 100 # 超时时间 (单位:秒) |
| | | # keepalive: 60 # 心跳 (单位:秒) |
| | | # qos: 1 # 心跳包级别 |
| | | # completion-timeout: 3000 # 连接超时时间(单位:秒) |
| | | # clientId: ztns_gc_scl_108303 # clientId,过程试验室伸长率设备 |
| | | # subscribe: /aiot/38568140-c697-11f0-8b13-c14e8310d70b # 订阅主题 |
| | | # client: true # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | | # - url: tcp://mqtt.ztt.cn.com:1883 # 服务器ip |
| | | # username: admin # MQTT-服务端-用户名,后期会修改为用户登录名 |
| | | # password: public # MQTT-服务端-密码,,后期会修改为用户登录密码 |
| | | # timeout: 100 # 超时时间 (单位:秒) |
| | | # keepalive: 60 # 心跳 (单位:秒) |
| | | # qos: 1 # 心跳包级别 |
| | | # completion-timeout: 3000 # 连接超时时间(单位:秒) |
| | | # clientId: ztns_gc_dz_108301 # clientId |
| | | # subscribe: /aiot/8fac9fa0-c517-11f0-954c-255ce11213f1 # 订阅主题 |
| | | # client: true # 如果开发需要启动测试,需要改为false不然会一直报错 |
| | |
| | | wri.setRequestName(requestName); |
| | | //todo: oa提交 1: 直接发送流程, 0:存入草稿箱 |
| | | // wri.setIsnextflow("1"); |
| | | wri.setIsnextflow("0"); |
| | | // wri.setIsnextflow("0"); |
| | | //创建主表 |
| | | OAWorkflowTable wmi = oaService.createOAMainWorkflowTable(mainFields); |
| | | // 将主表信息填充到流程信息里 |
| | |
| | | * @param key 键 |
| | | * @param start 开始索引 |
| | | * @param end 结束索引 |
| | | * @param sort 顺序或倒序 |
| | | * @return |
| | | */ |
| | | public static Set<Object> getZSetRange(String key,long start,long end){ |
| | | public static Set<Object> getZSetRange(String key,long start,long end,String sort){ |
| | | try { |
| | | if(StringUtils.equals("DESC",sort)){ |
| | | return redisTemplate.opsForZSet().reverseRange(key,start,end); |
| | | } |
| | | return redisTemplate.opsForZSet().range(key,start,end); |
| | | }catch(Exception e){ |
| | | e.printStackTrace(); |
| | |
| | | } |
| | | } |
| | | |
| | | public static Set<Object> getZSetRange(String key,long start,long end){ |
| | | return getZSetRange(key,start,end,"ASC"); |
| | | } |
| | | |
| | | } |
| | | |