天台祥和485串口数据采集

dev
ccongli 2 years ago
parent 9b60d9da7a
commit 169a9ba45f

@ -1,7 +1,6 @@
package org.jeecg.modules.demo.ttpouringequip.entity;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.math.BigDecimal;
@ -10,7 +9,6 @@ import lombok.Data;
import com.fasterxml.jackson.annotation.JsonFormat;
import org.springframework.format.annotation.DateTimeFormat;
import org.jeecgframework.poi.excel.annotation.Excel;
import org.jeecg.common.aspect.annotation.Dict;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.EqualsAndHashCode;

@ -1,88 +0,0 @@
package org.jeecg;
import com.fazecast.jSerialComm.SerialPort;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.rscom.RS485Handler;
import org.jeecg.rscom.enums.DEVICE_TYPE;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
@Slf4j
//@Component
public class CustomRunner implements ApplicationRunner {
private ExecutorService executorService = Executors.newFixedThreadPool(DEVICE_TYPE.values().length); // todo
@Override
public void run(ApplicationArguments args) {
System.out.println(args); // 通过启动参数配置 // todo
List<String> comlist = Arrays.stream(DEVICE_TYPE.values())
.map(DEVICE_TYPE::name)
.collect(Collectors.toList());
log.info("device sum = {} | list = {}" , comlist.size(), comlist);
Map<String, RS485Handler> handlerMap = initCOM(comlist);
Set<Map.Entry<String, RS485Handler>> entries = handlerMap.entrySet();
for(Map.Entry<String, RS485Handler> entry : entries) {
RS485Handler handler = entry.getValue();
String com = entry.getKey();
try {
DEVICE_TYPE deviceType = DEVICE_TYPE.valueOf(com);
Runnable task = () -> {
while (true) {
try {
Thread.sleep(3000); // todo
String str = handler.write(deviceType.getCommand());
// XhDeviceRecordDO entity = handler.makeRecord(deviceType.getParity(), str);
// xhDeviceRecordService.create(entity);
} catch (Exception exp) {
log.error("task appear error!", exp);
}
}
};
executorService.submit(task);
} catch (Exception exp) {
try {
handler.closePort();
} catch (Exception ex) {
ex.printStackTrace();
}
log.info("handle task error 500", exp);
}
}
}
// 初始化COM串口表
private Map<String, RS485Handler> initCOM(List<String> comlist) {
Map<String, RS485Handler> handlerMap = new HashMap<>();
for(String com : comlist) {
// 查找指定的串口
SerialPort serialPort = SerialPort.getCommPort(com);
DEVICE_TYPE deviceType = DEVICE_TYPE.valueOf(com);
// 初始化工作
RS485Handler handler = new RS485Handler(serialPort);
Boolean isOpen = handler.openPort(deviceType.getParity());
if (isOpen) {
handlerMap.put(com, handler);
}
// handler.listen();
}
return handlerMap;
}
public static void main(String[] args) {
// 查找所有串口
for(SerialPort port: SerialPort.getCommPorts()){
System.out.println("Port:" + port.getSystemPortName()); //打印串口名称如COM4
System.out.println("PortDesc:" + port.getPortDescription()); //打印串口类型如USB Serial
System.out.println("PortDesc:" + port.getDescriptivePortName()); //打印串口的完整类型如USB-SERIAL CH340(COM4)
}
}
}

@ -0,0 +1,110 @@
package org.jeecg.custom.enums;
import com.fazecast.jSerialComm.SerialPort;
import org.apache.commons.lang3.StringUtils;
import java.util.Arrays;
import java.util.List;
// 设备枚举
public enum DEVICE_TYPE {
COM1("192.168.10.201", "烘箱1", "", SerialPort.EVEN_PARITY),
COM2("192.168.10.202", "烘箱2", "", 2),
COM3("192.168.10.203", "烘箱3", "", 2),
COM4("192.168.10.204", "烘箱4", "", 2),
COM5("192.168.10.205", "烘箱5", "",2),
COM6("192.168.10.218", "烘箱6", "",2),
COM11("192.168.10.211", "模具1", "",2),
COM12("192.168.10.212", "模具2", "",2),
COM21("192.168.10.215", "罐子1", "",2),
COM22("192.168.10.216", "罐子2", "",2),
COM23("192.168.10.217", "罐子3", "",2),
COM24("192.168.10.229", "罐子4", "",2),
COM31("192.168.10.225", "数字电表1", "1B 03 00 32 00 02 67 FE", SerialPort.NO_PARITY),
COM32("192.168.10.226", "数字电表2", "07 03 00 32 00 02 65 A2", 0),
COM33("192.168.10.227", "数字电表3", "A0 03 00 32 00 02 7C B5",0),
COM34("192.168.10.228", "数字电表4", "1D 03 00 32 00 02 67 98",0);
private String hostNum;
private String name;
private String command;
private Integer parity;
private static final String tempCmd = "01 03 20 00 00 01 8F CA";
private DEVICE_TYPE(String hostNum, String name, String cmd, Integer parity) {
this.hostNum = hostNum;
this.name = name;
this.parity = parity;
this.command = StringUtils.isEmpty(cmd) ? tempCmd : cmd;
}
public String getHostNum() {
return hostNum;
}
public String getName() {
return name;
}
public String getCommand(){
return command;
}
public Integer getParity(){
return parity;
}
// 模具设备列表
public static List<DEVICE_TYPE> getJzjMolds() {
List<DEVICE_TYPE> jzjMolds = Arrays.asList(
DEVICE_TYPE.COM11,
DEVICE_TYPE.COM12
);
return jzjMolds;
}
// 浇注机设备列表
public static List<DEVICE_TYPE> getJzjDevice() {
List<DEVICE_TYPE> jzjDevice = Arrays.asList(
DEVICE_TYPE.COM1,
DEVICE_TYPE.COM2,
DEVICE_TYPE.COM3,
DEVICE_TYPE.COM4,
DEVICE_TYPE.COM5,
DEVICE_TYPE.COM6,
DEVICE_TYPE.COM11,
DEVICE_TYPE.COM12
);
return jzjDevice;
}
// 集中供料罐列表
public static List<DEVICE_TYPE> getGzDevice() {
List<DEVICE_TYPE> gzDevice = Arrays.asList(
DEVICE_TYPE.COM21,
DEVICE_TYPE.COM22,
DEVICE_TYPE.COM23,
DEVICE_TYPE.COM24
);
return gzDevice;
}
// 数字电表列表
public static List<DEVICE_TYPE> getMeterDevice() {
List<DEVICE_TYPE> meterDevice = Arrays.asList(
DEVICE_TYPE.COM31,
DEVICE_TYPE.COM32,
DEVICE_TYPE.COM33,
DEVICE_TYPE.COM34
);
return meterDevice;
}
}

@ -0,0 +1,211 @@
package org.jeecg.custom.task;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fazecast.jSerialComm.SerialPort;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.custom.enums.DEVICE_TYPE;
import org.jeecg.custom.utils.RS485Handler;
import org.jeecg.modules.demo.ttelectricmeter.entity.TtElectricMeter;
import org.jeecg.modules.demo.ttelectricmeter.service.ITtElectricMeterService;
import org.jeecg.modules.demo.tteqtbase.entity.TtEqtBase;
import org.jeecg.modules.demo.tteqtbase.service.ITtEqtBaseService;
import org.jeecg.modules.demo.ttfeedingequip.entity.TtFeedingEquip;
import org.jeecg.modules.demo.ttfeedingequip.service.ITtFeedingEquipService;
import org.jeecg.modules.demo.ttpouringequip.entity.TtPouringEquip;
import org.jeecg.modules.demo.ttpouringequip.service.ITtPouringEquipService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import org.springframework.scheduling.support.CronTrigger;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.stream.Collectors;
@Configuration //1.主要用于标记配置类兼备Component的效果。
@EnableScheduling // 2.开启定时任务
@Slf4j
public class TtDataCollectTask implements SchedulingConfigurer {
private static Map<DEVICE_TYPE, RS485Handler> jzjHandlerMap = new HashMap<>();
private static Map<DEVICE_TYPE, RS485Handler> gzHandlerMap = new HashMap<>();
private static Map<DEVICE_TYPE, RS485Handler> meterHandlerMap = new HashMap<>();
private ScheduledTaskRegistrar taskRegistrar;
@Autowired
ITtPouringEquipService pouringEquipService;
@Autowired
ITtFeedingEquipService feedingEquipService;
@Autowired
ITtElectricMeterService electricMeterService;
@Autowired
ITtEqtBaseService iTtEqtBaseService;
// 初始化
static {
initDeviceCOM(DEVICE_TYPE.getJzjDevice(),1);
initDeviceCOM(DEVICE_TYPE.getGzDevice(),2);
initDeviceCOM(DEVICE_TYPE.getMeterDevice(),3);
}
/**
* .
*/
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
this.taskRegistrar = taskRegistrar;
this.taskRegistrar.setScheduler(Executors.newScheduledThreadPool(10));
String cron1 = "0 0/5 * * * ?";
Map<String, String> eqtNoIpMap = getEqtNoIpMapping();
// 获取浇注机模具列表
List<DEVICE_TYPE> jzjMolds = DEVICE_TYPE.getJzjMolds();
// 创建浇注设备定时任务
for(Map.Entry<DEVICE_TYPE, RS485Handler> entry : jzjHandlerMap.entrySet()) {
RS485Handler handler = entry.getValue();
DEVICE_TYPE deviceType = entry.getKey();
Runnable runnable = () -> {
log.info("5min执行一次浇注设备温度采集:" + LocalDateTime.now().toLocalTime());
String str = handler.write(deviceType.getCommand());
String temp = handler.parseData(str, 1);
log.info("device com {} read str = {} | parse temp = {}", deviceType.name(), str, temp);
if (StringUtils.isNotBlank(temp)) {
Integer type = jzjMolds.contains(deviceType) ? 2 : 1;
String eqtIp = deviceType.getHostNum();
TtPouringEquip ttPouringEquip = new TtPouringEquip();
ttPouringEquip.setTemperature(new BigDecimal(temp));
ttPouringEquip.setCreateTime(new Date());
ttPouringEquip.setType(type);
ttPouringEquip.setEqtNo(Optional.ofNullable(eqtNoIpMap.get(eqtIp)).orElse("0"));
ttPouringEquip.setEqtIp(eqtIp);
pouringEquipService.save(ttPouringEquip);
}
};
this.addTriggerTask(runnable, cron1);
}
// 创建集中供料设备定时任务
for(Map.Entry<DEVICE_TYPE, RS485Handler> entry : gzHandlerMap.entrySet()) {
RS485Handler handler = entry.getValue();
DEVICE_TYPE deviceType = entry.getKey();
Runnable runnable = () -> {
log.info("5min执行一次供料设备温度采集:" + LocalDateTime.now().toLocalTime());
String str = handler.write(deviceType.getCommand());
String temp = handler.parseData(str, 1);
log.info("device com {} read str = {} | parse temp = {}", deviceType.name(), str, temp);
if (StringUtils.isNotBlank(temp)) {
String eqtIp = deviceType.getHostNum();
TtFeedingEquip ttFeedingEquip = new TtFeedingEquip();
ttFeedingEquip.setTemperature(new BigDecimal(temp));
ttFeedingEquip.setCreateTime(new Date());
ttFeedingEquip.setEqtNo(Optional.ofNullable(eqtNoIpMap.get(eqtIp)).orElse("0"));
ttFeedingEquip.setEqtIp(eqtIp);
feedingEquipService.save(ttFeedingEquip);
}
};
this.addTriggerTask(runnable, cron1);
}
// String cron2 = "0 0 8 * * ?";
String cron2 = "0/5 * * * * ?";
// 创建数字电表定时任务
for(Map.Entry<DEVICE_TYPE, RS485Handler> entry : meterHandlerMap.entrySet()) {
RS485Handler handler = entry.getValue();
DEVICE_TYPE deviceType = entry.getKey();
Runnable runnable = () -> {
// 电量计算
log.info("每天8点执行一次数字电表电量采集:" + LocalDateTime.now().toLocalTime());
String str = handler.write(deviceType.getCommand());
String power = handler.parseData(str, 2);
log.info("device com {} read str = {} | parse power = {}", deviceType.name(), str, power);
if (StringUtils.isNotBlank(power)) {
String eqtIp = deviceType.getHostNum();
BigDecimal totalPower = new BigDecimal(power);
TtElectricMeter ttElectricMeter = new TtElectricMeter();
ttElectricMeter.setTotalPower(totalPower);
ttElectricMeter.setCreateTime(new Date());
ttElectricMeter.setEqtNo(Optional.ofNullable(eqtNoIpMap.get(eqtIp)).orElse("0"));
ttElectricMeter.setEqtIp(eqtIp);
// 获取昨日用电量
LambdaQueryWrapper<TtElectricMeter> lqw = new LambdaQueryWrapper<>();
lqw.eq(TtElectricMeter::getEqtIp, eqtIp).orderByDesc(TtElectricMeter::getCreateTime).last("limit 1");
TtElectricMeter lastElectricMeter = electricMeterService.getOne(lqw);
BigDecimal lastTotalPower = Optional.ofNullable(lastElectricMeter)
.map(TtElectricMeter::getTotalPower).orElse(new BigDecimal(0));
BigDecimal lastUse = totalPower.subtract(lastTotalPower);
ttElectricMeter.setLastUse(lastUse);
electricMeterService.save(ttElectricMeter);
}
log.info("device com {} read power data={}", deviceType.name(), str);
};
this.addTriggerTask(runnable, cron2);
}
}
// 获取所有运行状态正常的Ip设备
private Map<String,String> getEqtNoIpMapping() {
Map<String,String> map;
LambdaQueryWrapper<TtEqtBase> lqw = new LambdaQueryWrapper<>();
lqw.isNotNull(TtEqtBase::getEqtIp);
lqw.eq(TtEqtBase::getEqtStatus,1); // 运行正常
List<TtEqtBase> list = iTtEqtBaseService.list(lqw);
map = list.stream().collect(Collectors.toMap(TtEqtBase::getEqtIp, TtEqtBase::getEqtNo));
log.info("running eqt ip no mappings = {}", map);
return map;
}
private void addTriggerTask(Runnable runnable, String cron) {
taskRegistrar.addTriggerTask(
//1.添加任务内容(Runnable)
runnable,
//2.设置执行周期(Trigger)
triggerContext -> {
if (StringUtils.isEmpty(cron)) {
log.error("cron expr invalid!");
}
//2.3 返回执行周期(Date)
return new CronTrigger(cron).nextExecutionTime(triggerContext);
}
);
}
/**
*
* @param COMList
* @return Map
*/
private static void initDeviceCOM(List<DEVICE_TYPE> COMList, Integer type) {
for(DEVICE_TYPE COM : COMList) {
// 查找指定的串口
String COMName = COM.name();
SerialPort serialPort = SerialPort.getCommPort(COMName);
// 初始化工作
RS485Handler handler = new RS485Handler(serialPort);
Boolean isOpen = handler.openPort(COM.getParity());
if (isOpen) {
if (type == 1) {
jzjHandlerMap.put(COM, handler);
} else if (type == 2) {
gzHandlerMap.put(COM, handler);
} else {
meterHandlerMap.put(COM, handler);
}
}
// handler.listen();
}
}
}

@ -1,4 +1,4 @@
package org.jeecg.rscom;
package org.jeecg.custom.utils;
import com.fazecast.jSerialComm.SerialPort;
import com.fazecast.jSerialComm.SerialPortDataListener;
@ -6,8 +6,6 @@ import com.fazecast.jSerialComm.SerialPortEvent;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import java.util.Date;
@Slf4j
public class RS485Handler {
@ -59,7 +57,6 @@ public class RS485Handler {
// 休眠1秒等待下位机读取数据
Thread.sleep(1000);
data = read();
log.info("portName {} | read data list = {}", portName, data);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
@ -86,26 +83,22 @@ public class RS485Handler {
}
// 返回数据处理
// public XhDeviceRecordDO makeRecord(Integer type, String str){
// XhDeviceRecordDO entity = new XhDeviceRecordDO();
// entity.setCom(portName);
// entity.setCreatetime(new Date());
// entity.setPower(""); // sql字段不为null设置默认值
// entity.setTemp("");
// if (type == 0) { // 解析用电量指标
// String kwHex = StringUtils.substring(str,6, 14);
// if(!kwHex.equals(str) && StringUtils.isNotBlank(kwHex)) {
// entity.setPower(hex2Float(kwHex));
// }
// } else if (type == 2){ // 解析温度指标
// String tempHex = StringUtils.substring(str,6, 10);
// if(!tempHex.equals(str) && StringUtils.isNotBlank(tempHex)) {
// entity.setTemp(hex2Decimal(tempHex));
// }
// }
// return entity;
// }
// 数据解析处理
public String parseData(String str, Integer type){
String content = null;
if (type == 1) { // 解析温度指标
String tempHex = StringUtils.substring(str,6, 10);
if(!tempHex.equals(str) && StringUtils.isNotBlank(tempHex)) {
content = hex2Decimal(tempHex);
}
} else if (type == 2){ // 解析用电量指标
String kwHex = StringUtils.substring(str,6, 14);
if(!kwHex.equals(str) && StringUtils.isNotBlank(kwHex)) {
content = hex2Float(kwHex);
}
}
return content;
}

@ -1,56 +0,0 @@
package org.jeecg.rscom.enums;
import com.fazecast.jSerialComm.SerialPort;
import org.apache.commons.lang3.StringUtils;
// 设备枚举
public enum DEVICE_TYPE {
COM1("201", "烘箱1", "", SerialPort.EVEN_PARITY),
COM2("202", "烘箱2", "", 2),
COM3("203", "烘箱3", "", 2),
COM4("204", "烘箱4", "", 2),
COM5("205", "烘箱5", "",2),
COM6("218", "烘箱6", "",2),
COM11("211", "模具1", "",2),
COM12("212", "模具2", "",2),
COM21("215", "罐子1", "",2),
COM22("216", "罐子2", "",2),
COM23("217", "罐子3", "",2),
COM31("225", "数字电表1", "1B 03 00 32 00 02 67 FE", SerialPort.NO_PARITY),
COM32("226", "数字电表2", "07 03 00 32 00 02 65 A2", 0),
COM33("227", "数字电表3", "A0 03 00 32 00 02 7C B5",0),
COM34("228", "数字电表4", "1D 03 00 32 00 02 67 98",0),
COM35("229", "数字电表5", "",0); // todo
private String hostNum;
private String name;
private String command;
private Integer parity;
private static final String tempCmd = "01 03 20 00 00 01 8F CA";
private DEVICE_TYPE(String hostNum, String name, String cmd, Integer parity) {
this.hostNum = hostNum;
this.name = name;
this.parity = parity;
this.command = StringUtils.isEmpty(cmd) ? tempCmd : cmd;
}
public String getHostNum() {
return hostNum;
}
public String getName() {
return name;
}
public String getCommand(){
return command;
}
public Integer getParity(){
return parity;
}
}
Loading…
Cancel
Save