Browse Source

add: 增加石墨消解仪所有的子模块的调试

master
HSZ_HeSongZhen 3 months ago
parent
commit
b6280a6663
  1. 19
      pom.xml
  2. 2
      src/main/java/iflytop/app/hardware/channel/A8kCanBusConnection.java
  3. 127
      src/main/java/iflytop/app/hardware/channel/keyChannel.java
  4. 85
      src/main/java/iflytop/app/hardware/channel/modbus/JSerialCommWrapper.java
  5. 13
      src/main/java/iflytop/app/hardware/channel/modbus/ModbusMasterFactory.java
  6. 283
      src/main/java/iflytop/app/hardware/channel/modbus/ModbusMasterService.java
  7. 25
      src/main/java/iflytop/app/hardware/driver/FillLightDriver.java
  8. 125
      src/main/java/iflytop/app/hardware/driver/HeaterRodDriver.java
  9. 37
      src/main/java/iflytop/app/hardware/driver/InputDetectDriver.java
  10. 30
      src/main/java/iflytop/app/hardware/driver/TricolorLightDriver.java
  11. 44
      src/main/java/iflytop/app/hardware/type/CmdDevice.java
  12. 14
      src/main/java/iflytop/app/hardware/type/CmdId.java
  13. 51
      src/main/java/iflytop/app/hardware/type/HeaterRodSlavedId.java
  14. 39
      src/main/java/iflytop/app/hardware/type/InputIOMId.java
  15. 5
      src/main/java/iflytop/app/menu/ExtApiPageGroupCfgMgr.java
  16. 22
      src/main/java/iflytop/app/page/DeviceInitPage.java
  17. 91
      src/main/java/iflytop/app/page/HeaterRodPage.java
  18. 61
      src/main/java/iflytop/app/page/IOBoardCtrlPage.java
  19. 96
      src/main/java/iflytop/app/page/InputIOStateScannerPage.java
  20. 5
      src/main/java/iflytop/app/page/OutputIOCtrlPage.java
  21. 22
      src/main/java/iflytop/app/service/appsetup/A8kSubModuleRegInitService.java
  22. 12
      src/main/resources/application.yml

19
pom.xml

@ -75,11 +75,20 @@
</dependency>
<!-- <dependency>-->
<!-- <groupId>io.springfox</groupId>-->
<!-- <artifactId>springfox-boot-starter</artifactId>-->
<!-- <version>3.0.0</version>-->
<!-- </dependency>-->
<dependency>
<groupId>com.fazecast</groupId>
<artifactId>jSerialComm</artifactId>
<version>2.11.0</version>
</dependency>
<!-- 引入本地 modbus jar 包-->
<dependency>
<groupId>com.github.infiniteautomation</groupId>
<artifactId>modbus4j</artifactId>
<version>3.1.0</version>
<scope>system</scope>
<systemPath>${project.basedir}/lib/modbus4j-3.1.0.jar</systemPath>
</dependency>
<dependency>

2
src/main/java/iflytop/app/hardware/channel/A8kCanBusConnection.java

@ -139,7 +139,7 @@ public class A8kCanBusConnection extends WebSocketClient {
synchronized public A8kPacket callcmd(MId moduleId, CmdId cmdId, Integer... param) throws HardwareException {
var packet = packParamsToPacket(moduleId.toInt(), cmdId.toInt(), ZList.of(param));
var packet = packParamsToPacket(moduleId.toInt(), cmdId.toInt(), ZList.of(param));
return autoReSend(packet, A8kPacket.CMD_OVERTIME);
}

127
src/main/java/iflytop/app/hardware/channel/keyChannel.java

@ -0,0 +1,127 @@
package iflytop.app.hardware.channel;
import iflytop.app.config.IflytophaldConnectionConfig;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.enums.ReadyState;
import org.java_websocket.handshake.ServerHandshake;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.util.LinkedList;
import java.util.Queue;
@Slf4j
@Component
@RequiredArgsConstructor
public class keyChannel {
WebSocketClient conn;
private final IflytophaldConnectionConfig config;
private Queue<byte[]> sendQueue = new LinkedList<>();
private Boolean logEnable = false;
@PostConstruct
void init() {
String url = config.getDatachUrl("key");
log.info("Key Channel url: {}", url);
conn = new WebSocketClient(URI.create(url)) {
@Override
public void onOpen(ServerHandshake serverHandshake) {
keyChannel.this.onOpen(serverHandshake);
}
@Override
public void onMessage(String s) {
keyChannel.this.onMessage(s);
}
@Override
public void onClose(int i, String s, boolean b) {
keyChannel.this.onClose(i, s, b);
}
@Override
public void onError(Exception e) {
keyChannel.this.onError(e);
}
};
conn.connect();
}
public void setLogEnable(Boolean logEnable) {
this.logEnable = logEnable;
}
private void onOpen(ServerHandshake serverHandshake) {
log.info("gd key connect sucess");
}
private void onMessage(String s) {
if(logEnable)
{
log.info("gd key message: {}", s);
}
}
private void onClose(int i, String s, boolean b) {
log.warn("gd key lost connection...");
}
private void onError(Exception e) {
log.info("gd key-websocket-channel on error");
}
synchronized private void pushToSend(byte[] toSend) {
sendQueue.add(toSend);
}
synchronized private byte[] popToSend() {
if (!sendQueue.isEmpty()) {
return sendQueue.poll();
}
return null;
}
@Scheduled(fixedRate = 400)
private void autoSend() {
while (true) {
var tosend = popToSend();
if (tosend != null) {
if (conn.isOpen()) {
conn.send(tosend);
}
if (tosend.length > 2) {
break;
}
} else {
break;
}
}
}
@Scheduled(fixedRate = 10000)
private void autoConnect() {
if (!conn.isOpen()) {
if (conn.getReadyState().equals(ReadyState.NOT_YET_CONNECTED)) {
try {
conn.connect();
} catch (IllegalStateException ignored) {
}
} else if (conn.getReadyState().equals(ReadyState.CLOSED)) {
conn.reconnect();
}
}
}
}

85
src/main/java/iflytop/app/hardware/channel/modbus/JSerialCommWrapper.java

@ -0,0 +1,85 @@
package iflytop.app.hardware.channel.modbus;
import com.fazecast.jSerialComm.SerialPort;
import com.serotonin.modbus4j.serial.SerialPortWrapper;
import lombok.extern.slf4j.Slf4j;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
@Slf4j
public class JSerialCommWrapper implements SerialPortWrapper {
private final int baudRate;
private final int dataBits;
private final int stopBits;
private final int parity;
private final SerialPort serialPort;
public JSerialCommWrapper(String portName, int baudRate, int dataBits, int stopBits, int parity) {
this.baudRate = baudRate;
this.dataBits = dataBits;
this.stopBits = stopBits;
this.parity = parity;
serialPort = SerialPort.getCommPort(portName);
serialPort.setBaudRate(this.baudRate);
serialPort.setNumDataBits(this.dataBits);
serialPort.setNumStopBits(this.stopBits);
serialPort.setParity(this.parity);
}
@Override
public void open() throws Exception {
if (!serialPort.openPort()) {
log.error("Could not open serial port {}", serialPort.getSystemPortName());
throw new IOException("Failed to open serial port: " + serialPort.getSystemPortName());
}
else{
log.info("Opened serial port: " + serialPort.getSystemPortName());
}
}
@Override
public void close() throws Exception {
if (serialPort != null) {
serialPort.closePort();
log.info("Closed serial port: {}", serialPort.getSystemPortName());
}
else
{
log.warn("Could not close serial port: {} null", serialPort.getSystemPortName());
}
}
@Override
public InputStream getInputStream() {
return serialPort.getInputStream();
}
@Override
public OutputStream getOutputStream() {
return serialPort.getOutputStream();
}
@Override
public int getBaudRate() {
return this.baudRate;
}
@Override
public int getStopBits() {
return this.stopBits;
}
@Override
public int getParity() {
return this.parity;
}
@Override
public int getDataBits() {
return this.dataBits;
}
}

13
src/main/java/iflytop/app/hardware/channel/modbus/ModbusMasterFactory.java

@ -0,0 +1,13 @@
package iflytop.app.hardware.channel.modbus;
import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
public class ModbusMasterFactory {
static final ModbusFactory factory = new ModbusFactory();
public static ModbusMaster createModbusRtuMaster(String portName, int baudRate) {
JSerialCommWrapper wrapper = new JSerialCommWrapper(portName, baudRate, 8, 1, 0);
return factory.createRtuMaster(wrapper);
}
}

283
src/main/java/iflytop/app/hardware/channel/modbus/ModbusMasterService.java

@ -0,0 +1,283 @@
package iflytop.app.hardware.channel.modbus;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.msg.*;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.concurrent.locks.ReentrantLock;
@Slf4j
@Component
@RequiredArgsConstructor
public class ModbusMasterService {
private ModbusMaster modbusMaster_;
private final ReentrantLock lock = new ReentrantLock();
@Value("${modbus.port}")
private String port;
@Value("${modbus.baudrate}")
private int baudrate;
@PostConstruct
public void init() {
modbusMaster_ = ModbusMasterFactory.createModbusRtuMaster(port, baudrate);
log.info("============== ============== ============== ============== ==============");
log.info("============== ============== ============== ============== ==============");
try {
this.connect();
log.info("Modbus master 端口: {} 波特率:{} initialized successfully.", port, baudrate);
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to initialize Modbus master: {} 端口: {} 波特率: {}",
e.getMessage(), port, baudrate);
}
log.info("============== ============== ============== ============== ==============");
log.info("============== ============== ============== ============== ==============");
}
/**
* 检查连接状态
*/
private boolean isConnectionInvalid() {
if (modbusMaster_ == null) {
log.error("Modbus master is not initialized.");
return true;
}
// if (!modbusMaster_.isConnected()) {
// log.error("Modbus master is not connected.");
// return true;
// }
return false;
}
// ==== ==== ==== ==== ==== ==== Modbus 功能封装 ==== ==== ==== ==== ==== ====
/**
* 读取线圈状态 (功能码: 1, READ_COILS)
*/
public boolean[] readCoils(int slaveId, int startAddress, int length) {
lock.lock();
try {
if (isConnectionInvalid()) return null;
ReadCoilsRequest request = new ReadCoilsRequest(slaveId, startAddress, length);
ReadCoilsResponse response = (ReadCoilsResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error reading coils: {}", response.getExceptionMessage());
return null;
}
return response.getBooleanData();
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to read coils: {}", e.getMessage());
return null;
} finally {
lock.unlock();
}
}
/**
* 读取离散输入 (功能码: 2, READ_DISCRETE_INPUTS)
*/
public boolean[] readDiscreteInputs(int slaveId, int startAddress, int length) {
lock.lock();
try {
if (isConnectionInvalid()) return null;
ReadDiscreteInputsRequest request = new ReadDiscreteInputsRequest(slaveId, startAddress, length);
ReadDiscreteInputsResponse response = (ReadDiscreteInputsResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error reading discrete inputs: {}", response.getExceptionMessage());
return null;
}
return response.getBooleanData();
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to read discrete inputs: {}", e.getMessage());
return null;
} finally {
lock.unlock();
}
}
/**
* 读取保持寄存器 (功能码: 3, READ_HOLDING_REGISTERS)
*/
public short[] readHoldingRegisters(int slaveId, int startAddress, int length) {
lock.lock();
try {
if (isConnectionInvalid()) return null;
ReadHoldingRegistersRequest request = new ReadHoldingRegistersRequest(slaveId, startAddress, length);
ReadHoldingRegistersResponse response = (ReadHoldingRegistersResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error reading holding registers: {}", response.getExceptionMessage());
return null;
}
return response.getShortData();
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to read holding registers: {}", e.getMessage());
return null;
} finally {
lock.unlock();
}
}
/**
* 读取输入寄存器 (功能码: 4, READ_INPUT_REGISTERS)
*/
public short[] readInputRegisters(int slaveId, int startAddress, int length) {
lock.lock();
try {
if (isConnectionInvalid()) return null;
ReadInputRegistersRequest request = new ReadInputRegistersRequest(slaveId, startAddress, length);
ReadInputRegistersResponse response = (ReadInputRegistersResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error reading input registers: {}", response.getExceptionMessage());
return null;
}
return response.getShortData();
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to read input registers: {}", e.getMessage());
return null;
} finally {
lock.unlock();
}
}
/**
* 写单个线圈 (功能码: 5, WRITE_COIL)
*/
public boolean writeCoil(int slaveId, int address, boolean value) {
lock.lock();
try {
if (isConnectionInvalid()) return false;
WriteCoilRequest request = new WriteCoilRequest(slaveId, address, value);
WriteCoilResponse response = (WriteCoilResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error writing coil: {}", response.getExceptionMessage());
return false;
}
return true;
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to write coil: {}", e.getMessage());
return false;
} finally {
lock.unlock();
}
}
/**
* 写单个寄存器 (功能码: 6, WRITE_REGISTER)
*/
public boolean writeRegister(int slaveId, int address, int value) {
lock.lock();
try {
if (isConnectionInvalid()) return false;
WriteRegisterRequest request = new WriteRegisterRequest(slaveId, address, value);
WriteRegisterResponse response = (WriteRegisterResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error writing register: {}", response.getExceptionMessage());
return false;
}
return true;
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to write register: {}", e.getMessage());
return false;
} finally {
lock.unlock();
}
}
/**
* 写多个线圈 (功能码: 15, WRITE_COILS)
*/
public boolean writeCoils(int slaveId, int startAddress, boolean[] values) {
lock.lock();
try {
if (isConnectionInvalid()) return false;
WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startAddress, values);
WriteCoilsResponse response = (WriteCoilsResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error writing coils: {}", response.getExceptionMessage());
return false;
}
return true;
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to write coils: {}", e.getMessage());
return false;
} finally {
lock.unlock();
}
}
/**
* 写多个寄存器 (功能码: 16, WRITE_REGISTERS)
*/
public boolean writeRegisters(int slaveId, int startAddress, short[] values) {
lock.lock();
try {
if (isConnectionInvalid()) return false;
WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startAddress, values);
WriteRegistersResponse response = (WriteRegistersResponse) modbusMaster_.send(request);
if (response.isException()) {
modbusMaster_.setConnected(false);
log.error("Error writing registers: {}", response.getExceptionMessage());
return false;
}
return true;
} catch (Exception e) {
modbusMaster_.setConnected(false);
log.error("Failed to write registers: {}", e.getMessage());
return false;
} finally {
lock.unlock();
}
}
// ==== ==== ==== ==== ==== ==== 自动重连 ==== ==== ==== ==== ==== ====
void connect() throws Exception
{
modbusMaster_.init();
modbusMaster_.setRetries(3);
// modbusMaster_.setIoLog(new BasicLogger());
modbusMaster_.setTimeout(2000);
modbusMaster_.setConnected(true);
}
/**
* 自动重连
*/
@Scheduled(fixedRate = 1000)
public void autoReconnect() {
lock.lock();
try {
if(modbusMaster_ ==null || !modbusMaster_.isInitialized() || modbusMaster_.isConnected())
return;
this.connect();
log.info("Modbus master 重连成功 端口: {} 波特率:{}.", port, baudrate);
} catch (Exception e) {
log.error("Modbus master : {}", e.getMessage());
log.info("Modbus master 重连失败 端口: {} 波特率:{}. {}", port, baudrate, e.getMessage());
} finally {
lock.unlock();
}
}
}

25
src/main/java/iflytop/app/hardware/driver/FillLightDriver.java

@ -0,0 +1,25 @@
package iflytop.app.hardware.driver;
import iflytop.app.hardware.channel.A8kCanBusService;
import iflytop.app.hardware.type.CmdId;
import iflytop.app.hardware.type.MId;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import static iflytop.app.hardware.type.MId.PWMLight;
@Slf4j
@Component
@RequiredArgsConstructor
public class FillLightDriver {
private final A8kCanBusService canBus;
public void open(Integer brightness) throws Exception {
// 模拟打开
canBus.callcmd(PWMLight, CmdId.pwm_light_on, brightness);
}
public void close() throws Exception {
canBus.callcmd(PWMLight, CmdId.pwm_light_off);
}
}

125
src/main/java/iflytop/app/hardware/driver/HeaterRodDriver.java

@ -0,0 +1,125 @@
package iflytop.app.hardware.driver;
import cn.hutool.core.util.StrUtil;
import iflytop.app.hardware.channel.A8kCanBusService;
import iflytop.app.hardware.channel.modbus.ModbusMasterService;
import iflytop.app.hardware.type.A8kPacket;
import iflytop.app.hardware.type.CmdId;
import iflytop.app.hardware.type.HeaterRodSlavedId;
import iflytop.app.type.exception.HardwareException;
import io.swagger.v3.oas.models.security.SecurityScheme;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
@Slf4j
@Component
@RequiredArgsConstructor
public class HeaterRodDriver {
private final ModbusMasterService modbusMaster;
private final A8kCanBusService canBus;
private static final int SV_ADDRESS = 0x2000;
private static final int PV_ADDRESS = 0x2010;
private static final int CONTROL_REGISTER = 0x2106;
private static final int DP_ADDRESS = 0x2107;
private static final int DEVICE_ADDRESS_REGISTER = 0x2112;
private final Map<Integer, Integer> dpCache = new ConcurrentHashMap<>();
private static final int DEFAULT_DP = 1;
public void setDeviceAddress(HeaterRodSlavedId heaterRodId, int newAddress) throws Exception {
int slaveId = heaterRodId.getSlaveId();
if (!modbusMaster.writeRegister(slaveId, DEVICE_ADDRESS_REGISTER, newAddress)) {
throw new Exception("Failed to set device address for heater rod with ID: " + heaterRodId.name());
}
log.info("Device address for heater rod with ID: {} set to: {}", heaterRodId.name(), newAddress);
}
public int getDecimalPoint(int slaveId) throws Exception {
return dpCache.computeIfAbsent(slaveId, id -> {
try {
short[] response = modbusMaster.readHoldingRegisters(id, DP_ADDRESS, 1);
if (response != null && response.length > 0) {
return (int) response[0];
}
} catch (Exception e) {
log.warn("Failed to read DP for slave ID: {}, using default DP: {}", id, DEFAULT_DP);
}
return DEFAULT_DP;
});
}
public void openPower(HeaterRodSlavedId heaterRodId) throws Exception
{
int slaveId = heaterRodId.getSlaveId();
if (!modbusMaster.writeRegister(slaveId, CONTROL_REGISTER, 1)) { // 1 = Start
throw new Exception("Failed to start heater rod with ID: " + heaterRodId.name());
}
}
public void closePower(HeaterRodSlavedId heaterRodId) throws Exception
{
int slaveId = heaterRodId.getSlaveId();
if (!modbusMaster.writeRegister(slaveId, CONTROL_REGISTER, 2)) { // 2 = Stop
throw new Exception("Failed to stop heater rod with ID: " + heaterRodId.name());
}
log.info("{} stopped.", heaterRodId.name());
}
public void setTemperature(HeaterRodSlavedId heaterRodId, double temperature) throws Exception {
int slaveId = heaterRodId.getSlaveId();
int decimalPoint = getDecimalPoint(slaveId);
int scaledTemperature = (int) (temperature * Math.pow(10, decimalPoint));
if (!modbusMaster.writeRegister(slaveId, SV_ADDRESS, scaledTemperature)) {
throw new Exception("Failed to set temperature for heater rod with ID: " + heaterRodId.name());
}
log.info("{} started with temperature: {}", heaterRodId.name(), temperature);
}
public double getTemperature(HeaterRodSlavedId heaterRodId) throws Exception {
int slaveId = heaterRodId.getSlaveId();
int decimalPoint = getDecimalPoint(slaveId);
short[] response = modbusMaster.readHoldingRegisters(slaveId, PV_ADDRESS, 1);
if (response == null || response.length == 0) {
throw new Exception(StrUtil.format("Failed to read temperature {}", heaterRodId.name()));
}
double temperature = response[0] / Math.pow(10, decimalPoint);
log.info("{} GET temperature {}", heaterRodId.name(), temperature);
return temperature;
}
/**
* 获取电流
* @return
*/
public Integer getCurrent(HeaterRodSlavedId heaterRodId) throws HardwareException
{
A8kPacket packet = canBus.callcmd(heaterRodId.getMid(), CmdId.adc_read_adc, heaterRodId.getAdcCurrentIndex());
Integer current = packet.getContentI32(0);
return current;
}
// ==== ==== ==== ==== ==== ==== application ==== ==== ==== ==== ==== ====
public void open(HeaterRodSlavedId heaterRodId, double temperature) throws Exception {
this.openPower(heaterRodId);
this.setTemperature(heaterRodId, temperature);
}
public void close(HeaterRodSlavedId heaterRodId) throws Exception {
this.closePower(heaterRodId);
}
}

37
src/main/java/iflytop/app/hardware/driver/InputDetectDriver.java

@ -0,0 +1,37 @@
package iflytop.app.hardware.driver;
import iflytop.app.hardware.channel.A8kCanBusService;
import iflytop.app.hardware.type.CmdId;
import iflytop.app.hardware.type.InputIOMId;
import iflytop.app.type.exception.HardwareException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class InputDetectDriver {
private final A8kCanBusService canBus;
public Boolean getIOState(InputIOMId ioid) throws HardwareException {
while (true) {
Boolean firstReadIO = priGetIOState(ioid);
Boolean secondReadIO = priGetIOState(ioid);
if (firstReadIO == secondReadIO) {
if (ioid.mirror) {
return !firstReadIO;
}
return firstReadIO;
} else {
log.warn("getIOState {} not match, retry", ioid);
}
}
}
private Boolean priGetIOState(InputIOMId ioid) throws HardwareException {
return canBus.callcmd(ioid.mid, CmdId.read_in_io, ioid.ioIndex).getContentI32(0) != 0;
}
}

30
src/main/java/iflytop/app/hardware/driver/TricolorLightDriver.java

@ -0,0 +1,30 @@
package iflytop.app.hardware.driver;
import iflytop.app.hardware.channel.A8kCanBusService;
import iflytop.app.hardware.type.CmdId;
import iflytop.app.hardware.type.MId;
import iflytop.app.type.exception.HardwareException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Slf4j
@Component
@RequiredArgsConstructor
public class TricolorLightDriver {
private final A8kCanBusService canBus;
public enum Color {
RED, GREEN, BLUE
}
public void open(MId mid, Color color) throws HardwareException {
log.info("Open TricolorLight driver Color {}", color);
canBus.callcmd(mid, CmdId.tricolor_light_on, color.ordinal());
}
public void close(MId mid) throws HardwareException{
log.info("Close TricolorLight driver Color");
canBus.callcmd(mid, CmdId.tricolor_light_off);
}
}

44
src/main/java/iflytop/app/hardware/type/CmdDevice.java

@ -0,0 +1,44 @@
package iflytop.app.hardware.type;
public enum CmdDevice {
door_motor,
shake_motor,
tray_motor,
dual_robot,
gantry_x,
gantry_y,
gantry_z,
heater_motor_1,
heater_motor_2,
heater_motor_3,
heater_motor_4,
heater_motor_5,
heater_motor_6,
acid_pump_1,
acid_pump_2,
acid_pump_3,
acid_pump_4,
acid_pump_5,
acid_pump_6,
acid_pump_7,
acid_pump_8,
claw,
fan_1,
fan_2,
fan_3,
fan_4,
fan_5,
fan_6,
water_pump_power,
ventilator_power,
heat_rod_1,
heat_rod_2,
heat_rod_3,
heat_rod_4,
heat_rod_5,
heat_rod_6,
tricolor_light,
fill_light,
cold_trap,
photo
}

14
src/main/java/iflytop/app/hardware/type/CmdId.java

@ -86,15 +86,15 @@ public enum CmdId {
read_out_io_index_in_stm32(0x4005, "READ_OUT_IO_INDEX_IN_STM32"),
read_out_io(0x4006, "READ_OUT_IO"),
tricolor_light_on(0x110001, "TRICOLOR_LIGHT_ON"),
tricolor_light_off(0x110002, "TRICOLOR_LIGHT_OFF"),
tricolor_light_on(0x5101, "TRICOLOR_LIGHT_ON"),
tricolor_light_off(0x5102, "TRICOLOR_LIGHT_OFF"),
pwm_light_on(0x012001, "PWM_LIGHT_ON"),
pwm_light_off(0x120002, "PWM_LIGHT_OFF"),
pwm_light_on(0x5201, "PWM_LIGHT_ON"),
pwm_light_off(0x5202, "PWM_LIGHT_OFF"),
adc_enable_log(0x130001, "ADC_ENABLE_LOG"),
adc_read_adc(0x130002, "ADC_READ_ADC"),
adc_read_multi_adc(0x130003, "ADC_READ_MULTI_ADC"),
adc_enable_log(0x05301, "ADC_ENABLE_LOG"),
adc_read_adc(0x05302, "ADC_READ_ADC"),
adc_read_multi_adc(0x05303, "ADC_READ_MULTI_ADC"),
;
public final static int ATTACH_IS_BYTES = 1;

51
src/main/java/iflytop/app/hardware/type/HeaterRodSlavedId.java

@ -0,0 +1,51 @@
package iflytop.app.hardware.type;
public enum HeaterRodSlavedId {
HEATER_ROD1_ID(CmdDevice.heat_rod_1, 1, MId.IO1_ADC,0),
HEATER_ROD2_ID(CmdDevice.heat_rod_2, 2, MId.IO1_ADC,1),
HEATER_ROD3_ID(CmdDevice.heat_rod_3, 3, MId.IO1_ADC,2),
HEATER_ROD4_ID(CmdDevice.heat_rod_4, 4, MId.IO1_ADC,3),
HEATER_ROD5_ID(CmdDevice.heat_rod_5, 5, MId.IO1_ADC,4),
HEATER_ROD6_ID(CmdDevice.heat_rod_6, 6, MId.IO1_ADC,5),
;
private final CmdDevice cmdDevice;
private final Integer slaveId;
private final MId mid;
private final Integer adcCurrentIndex; // ADC电流索引
HeaterRodSlavedId(CmdDevice cmdDevice, Integer slaveId, MId mid, Integer adcCurrentIndex) {
this.cmdDevice = cmdDevice;
this.slaveId = slaveId;
this.mid = mid;
this.adcCurrentIndex = adcCurrentIndex;
}
public CmdDevice getCmdDevice() {
return cmdDevice;
}
public Integer getSlaveId() {
return slaveId;
}
public MId getMid()
{
return mid;
}
public Integer getAdcCurrentIndex()
{
return adcCurrentIndex;
}
static public HeaterRodSlavedId getByCmdDevice(CmdDevice cmdDevice) {
for (HeaterRodSlavedId value : HeaterRodSlavedId.values()) {
if (value.cmdDevice == cmdDevice) {
return value;
}
}
return null;
}
}

39
src/main/java/iflytop/app/hardware/type/InputIOMId.java

@ -0,0 +1,39 @@
package iflytop.app.hardware.type;
public enum InputIOMId {
Heater_CAP1_EXSIT("Heater_CAP1_EXSIT [ 加热模块拍子1到位 ]", MId.IO1_IO, 0,false),
Heater_CAP2_EXSIT("Heater_CAP2_EXSIT [ 加热模块拍子2到位 ]", MId.IO1_IO, 1,false),
Heater_CAP3_EXSIT("Heater_CAP3_EXSIT [ 加热模块拍子3到位 ]", MId.IO1_IO, 2,false),
Heater_CAP4_EXSIT("Heater_CAP4_EXSIT [ 加热模块拍子4到位 ]", MId.IO1_IO, 3,false),
Heater_CAP5_EXSIT("Heater_CAP5_EXSIT [ 加热模块拍子5到位 ]", MId.IO1_IO, 4,false),
Heater_CAP6_EXSIT("Heater_CAP6_EXSIT [ 加热模块拍子6到位 ]", MId.IO1_IO, 5,false),
Heater_TUBE1_EXSIT("Heater_TUBE1_EXSIT [ 加热模块托盘1到位 ]", MId.IO1_IO, 6,false),
Heater_TUBE2_EXSIT("Heater_TUBE2_EXSIT [ 加热模块托盘2到位 ]", MId.IO1_IO, 7,false),
Heater_TUBE3_EXSIT("Heater_TUBE3_EXSIT [ 加热模块托盘3到位 ]", MId.IO1_IO, 8,false),
Heater_TUBE4_EXSIT("Heater_TUBE4_EXSIT [ 加热模块托盘4到位 ]", MId.IO1_IO, 9,false),
Heater_TUBE5_EXSIT("Heater_TUBE5_EXSIT [ 加热模块托盘5到位 ]", MId.IO1_IO, 10,false),
Heater_TUBE6_EXSIT("Heater_TUBE6_EXSIT [ 加热模块托盘6到位 ]", MId.IO1_IO, 11,false),
TRAY_CAP1_EXSIT("TRAY_CAP1_EXSIT [ 拍子存放位拍子1到位 ]", MId.IO1_IO, 12,false),
TRAY_CAP2_EXSIT("TRAY_CAP2_EXSIT [ 拍子存放位拍子2到位 ]", MId.IO1_IO, 13,false),
TRAY_CAP3_EXSIT("TRAY_CAP3_EXSIT [ 拍子存放位拍子3到位 ]", MId.IO1_IO, 14,false),
TRAY_CAP4_EXSIT("TRAY_CAP4_EXSIT [ 拍子存放位拍子4到位 ]", MId.IO1_IO, 15,false),
TRAY_CAP5_EXSIT("TRAY_CAP5_EXSIT [ 拍子存放位拍子5到位 ]", MId.IO1_IO, 16,false),
TRAY_CAP6_EXSIT("TRAY_CAP6_EXSIT [ 拍子存放位拍子6到位 ]", MId.IO1_IO, 17,false),
E_STOP("E_STOP [ 急停 ]", MId.IO1_IO, 18,false),
;
final public String description;
final public MId mid;
final public int ioIndex;
final public boolean mirror;
InputIOMId(String description, MId mid, int ioIndex, boolean mirror) {
this.description = description;
this.mid = mid;
this.ioIndex = ioIndex;
this.mirror = mirror;
}
}

5
src/main/java/iflytop/app/menu/ExtApiPageGroupCfgMgr.java

@ -71,7 +71,10 @@ public class ExtApiPageGroupCfgMgr {
new Menu(LiquidArmPage.class, "加液臂驱动"),
new Menu(LeisaiServoPage.class, "雷赛伺服电机驱动"),
new Menu(OutputIOCtrlPage.class, "输出IO控制"),
new Menu(MotorParameterQuickConfigPage.class, "电机参数快速配置")
new Menu(MotorParameterQuickConfigPage.class, "电机参数快速配置"),
new Menu(HeaterRodPage.class, "加热棒控制"),
new Menu(IOBoardCtrlPage.class, "IO 板控制"),
new Menu(InputIOStateScannerPage.class, "IO 扫描板")
)));

22
src/main/java/iflytop/app/page/DeviceInitPage.java

@ -1,5 +1,6 @@
package iflytop.app.page;
import iflytop.app.hardware.channel.keyChannel;
import iflytop.app.hardware.driver.ModuleEnableCtrlDriver;
import iflytop.app.service.appsetup.A8kSubModuleRegInitService;
import iflytop.app.type.exception.HardwareException;
@ -13,7 +14,8 @@ import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class DeviceInitPage {
@Resource
keyChannel keyChannel;
private final ModuleEnableCtrlDriver moduleEnableCtrlDriver;
private final A8kSubModuleRegInitService a8kSubModuleRegInitService;
@ -23,6 +25,10 @@ public class DeviceInitPage {
return a8kSubModuleRegInitService.getIsInited();
}
public void deviceInit() throws HardwareException {
a8kSubModuleRegInitService.initDevice();
}
public String moveAllStepMotorToZero() throws HardwareException {
return "TODO::Complete";
}
@ -37,6 +43,13 @@ public class DeviceInitPage {
return "已使能所有电机";
}
public void enableKeyLog(Boolean enable)
{
keyChannel.setLogEnable(enable);
}
@Resource
ExtApiPageMgr extApiPageMgr;
@ -45,11 +58,18 @@ public class DeviceInitPage {
public void init() {
var page = extApiPageMgr.newPage(this);
page.newGroup("设备初始化");
page.addFunction("设备初始化", this::deviceInit);
page.newGroup("模块批量控制");
page.addFunction("电机归零", this::moveAllStepMotorToZero);
page.addFunction("使能所有", this::enableAll);
page.addFunction("失能所有", this::disableAll);
page.newGroup("日志");
page.addFunction("急停日志", this::enableKeyLog);
extApiPageMgr.addPage(page);
}
}

91
src/main/java/iflytop/app/page/HeaterRodPage.java

@ -0,0 +1,91 @@
package iflytop.app.page;
import iflytop.app.hardware.driver.HeaterRodDriver;
import iflytop.app.hardware.type.HeaterRodSlavedId;
import iflytop.app.type.exception.HardwareException;
import iflytop.extui.mgr.ExtApiPageMgr;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
@RequiredArgsConstructor
public class HeaterRodPage {
@Resource
ExtApiPageMgr extApiPageMgr;
@Resource
HeaterRodDriver heaterRodDriver;
HeaterRodSlavedId id = HeaterRodSlavedId.HEATER_ROD1_ID;
public void setHeaterRodId(HeaterRodSlavedId id) {
this.id = id;
}
public Integer getDecimalPoint() throws Exception
{
return heaterRodDriver.getDecimalPoint(id.getSlaveId());
}
public void openPower() throws Exception
{
heaterRodDriver.openPower(id);
}
public void closePower() throws Exception
{
heaterRodDriver.closePower(id);
}
public void setTemperature(Double temperature) throws Exception
{
heaterRodDriver.setTemperature(id, temperature);
}
public double getTemperature() throws Exception
{
return heaterRodDriver.getTemperature(id);
}
public Integer getCurrent() throws HardwareException
{
return heaterRodDriver.getCurrent(id);
}
public void open(double temperature) throws Exception {
heaterRodDriver.open(id, temperature);
}
public void close() throws Exception {
heaterRodDriver.close(id);
}
@PostConstruct
void init() {
var page = extApiPageMgr.newPage(this);
page.newGroup("加热棒上下文");
page.addFunction("设置加热棒ID", this::setHeaterRodId);
page.newGroup("加热棒独立指令");
page.addFunction("读取加热棒温度", this::getTemperature);
page.addFunction("读取加热棒电流", this::getCurrent);
page.addFunction("获取小数点", this::getDecimalPoint);
page.addFunction("设置加热棒温度", this::setTemperature).
setParamVal("temperature", () -> 20.0); // 默认值20.0
page.newGroup("加热棒复合指令");
page.addFunction("打开加热棒", this::openPower);
page.addFunction("关闭加热棒", this::closePower);
extApiPageMgr.addPage(page);
}
}

61
src/main/java/iflytop/app/page/IOBoardCtrlPage.java

@ -0,0 +1,61 @@
package iflytop.app.page;
import iflytop.app.hardware.driver.FillLightDriver;
import iflytop.app.hardware.driver.HeaterRodDriver;
import iflytop.app.hardware.driver.TricolorLightDriver;
import iflytop.app.hardware.type.MId;
import iflytop.extui.mgr.ExtApiPageMgr;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import static iflytop.app.hardware.driver.TricolorLightDriver.Color.GREEN;
@Component
@Slf4j
@RequiredArgsConstructor
public class IOBoardCtrlPage {
@Resource
ExtApiPageMgr extApiPageMgr;
@Resource
FillLightDriver fillLightDriver;
@Resource
TricolorLightDriver tricolorLightDriver;
public void openFillLight(Integer brightness) throws Exception {
fillLightDriver.open(brightness);
}
public void closeFillLight() throws Exception {
fillLightDriver.close();
}
public void openTricolorLight(TricolorLightDriver.Color color) throws Exception {
tricolorLightDriver.open(MId.TriColorLight, color);
}
public void closeTricolorLight() throws Exception {
tricolorLightDriver.close(MId.TriColorLight);
}
@PostConstruct
void init() {
var page = extApiPageMgr.newPage(this);
page.newGroup("补光灯");
page.addFunction("打开补光灯", this::openFillLight).setParamVal("brightness", () -> 50);
page.addFunction("关闭补光灯", this::closeFillLight);
page.newGroup("三色灯");
page.addFunction("打开三色灯", this::openTricolorLight).setParamVal("color", () -> GREEN);
page.addFunction("关闭三色灯", this::closeTricolorLight);
extApiPageMgr.addPage(page);
}
}

96
src/main/java/iflytop/app/page/InputIOStateScannerPage.java

@ -0,0 +1,96 @@
package iflytop.app.page;
import iflytop.app.hardware.driver.InputDetectDriver;
import iflytop.app.hardware.type.InputIOMId;
import iflytop.app.type.exception.HardwareException;
import iflytop.extui.mgr.ExtApiPageMgr;
import iflytop.extui.type.ExtApiStatu;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class InputIOStateScannerPage {
final private ExtApiPageMgr extApiPageMgr;
final private InputDetectDriver inputDetectDriver;
@ExtApiStatu(name = "加热模块拍子1到位", order = 0)
public Boolean getTubeHeightPPS() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_CAP1_EXSIT);}
@ExtApiStatu(name = "加热模块拍子2到位", order = 1)
public Boolean getTubeHeightPPS2() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_CAP2_EXSIT);}
@ExtApiStatu(name = "加热模块拍子3到位", order = 2)
public Boolean getTubeHeightPPS3() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_CAP3_EXSIT);}
@ExtApiStatu(name = "加热模块拍子4到位", order = 3)
public Boolean getTubeHeightPPS4() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_CAP4_EXSIT);}
@ExtApiStatu(name = "加热模块拍子5到位", order = 4)
public Boolean getTubeHeightPPS5() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_CAP5_EXSIT);}
@ExtApiStatu(name = "加热模块拍子6到位", order = 5)
public Boolean getTubeHeightPPS6() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_CAP6_EXSIT);}
@ExtApiStatu(name = "加热模块托盘1到位", order = 6)
public Boolean getTubeHeightPPS7() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_TUBE1_EXSIT);}
@ExtApiStatu(name = "加热模块托盘2到位", order = 7)
public Boolean getTubeHeightPPS8() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_TUBE2_EXSIT);}
@ExtApiStatu(name = "加热模块托盘3到位", order = 8)
public Boolean getTubeHeightPPS9() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_TUBE3_EXSIT);}
@ExtApiStatu(name = "加热模块托盘4到位", order = 9)
public Boolean getTubeHeightPPS10() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_TUBE4_EXSIT);}
@ExtApiStatu(name = "加热模块托盘5到位", order = 10)
public Boolean getTubeHeightPPS11() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_TUBE5_EXSIT);}
@ExtApiStatu(name = "加热模块托盘6到位", order = 11)
public Boolean getTubeHeightPPS12() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.Heater_TUBE6_EXSIT);}
@ExtApiStatu(name = "拍子存放位拍子1到位", order = 12)
public Boolean getTubeHeightPPS13() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.TRAY_CAP1_EXSIT);}
@ExtApiStatu(name = "拍子存放位拍子2到位", order = 13)
public Boolean getTubeHeightPPS14() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.TRAY_CAP2_EXSIT);}
@ExtApiStatu(name = "拍子存放位拍子3到位", order = 14)
public Boolean getTubeHeightPPS15() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.TRAY_CAP3_EXSIT);}
@ExtApiStatu(name = "拍子存放位拍子4到位", order = 15)
public Boolean getTubeHeightPPS16() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.TRAY_CAP4_EXSIT);}
@ExtApiStatu(name = "拍子存放位拍子5到位", order = 16)
public Boolean getTubeHeightPPS17() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.TRAY_CAP5_EXSIT);}
@ExtApiStatu(name = "拍子存放位拍子6到位", order = 17)
public Boolean getTubeHeightPPS18() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.TRAY_CAP6_EXSIT);}
@ExtApiStatu(name = "急停", order = 18)
public Boolean getTubeHeightPPS19() throws HardwareException {return inputDetectDriver.getIOState(InputIOMId.E_STOP);}
public Boolean getIOState(InputIOMId iomId) throws HardwareException {
return inputDetectDriver.getIOState(iomId);
}
@PostConstruct
void init() {
var page = extApiPageMgr.newPage(this);
page.newGroup("IO 输入");
page.addFunction("获取IO 状态", this::getIOState);
page.addFunction("获取IO 状态", this::getIOState);
page.addFunction("获取IO 状态", this::getIOState);
page.addFunction("获取IO 状态", this::getIOState);
page.addFunction("获取IO 状态", this::getIOState);
page.addFunction("获取IO 状态", this::getIOState);
extApiPageMgr.addPage(page);
}
}

5
src/main/java/iflytop/app/page/OutputIOCtrlPage.java

@ -30,6 +30,11 @@ public class OutputIOCtrlPage {
void init() {
var page = extApiPageMgr.newPage(this);
page.addFunction("设置IO状态", this::setIOState);
page.addFunction("设置IO状态", this::setIOState);
page.addFunction("设置IO状态", this::setIOState);
page.addFunction("设置IO状态", this::setIOState);
page.addFunction("设置IO状态", this::setIOState);
page.addFunction("设置IO状态", this::setIOState);
extApiPageMgr.addPage(page);

22
src/main/java/iflytop/app/service/appsetup/A8kSubModuleRegInitService.java

@ -5,6 +5,7 @@ import iflytop.app.config.A8kSubModuleInitRegConfig;
import iflytop.app.dao.type.db.SubModuleRegInitialValue;
import iflytop.app.hardware.channel.A8kCanBusService;
import iflytop.app.hardware.driver.ModuleEnableCtrlDriver;
import iflytop.app.hardware.type.A8kEcode;
import iflytop.app.hardware.type.MId;
import iflytop.app.hardware.type.ModuleType;
import iflytop.app.hardware.type.RegIndex;
@ -36,6 +37,7 @@ public class A8kSubModuleRegInitService {
private final A8kSubModuleInitRegConfig a8kSubModuleInitRegConfig;
private final SubModuleRegInitialValueMgrService subModuleRegInitialValueMgrService;
private Boolean isInited = false;
private Boolean isCanConnected = false;
@PostConstruct
void init() {
@ -49,10 +51,24 @@ public class A8kSubModuleRegInitService {
private void onAppEvent(AppEvent event) {
if (event instanceof A8kCanBusOnConnectEvent) {
var initThread = new Thread(this::initModuleRegVal);
initThread.setName("initModuleRegVal");
initThread.start();
// var initThread = new Thread(this::initModuleRegVal);
// initThread.setName("initModuleRegVal");
// initThread.start();
isCanConnected = true;
}
}
public void initDevice() throws HardwareException
{
if(!isCanConnected)
{
log.error("can bus not connected, please check");
throw HardwareException.of(A8kEcode.WEBSOCKET_CONNECT_ERROR);
}
var initThread = new Thread(this::initModuleRegVal);
initThread.setName("initModuleRegVal");
initThread.start();
}
private void initModuleRegVal() {

12
src/main/resources/application.yml

@ -4,7 +4,7 @@ server:
device.enableCanBus: true
iflytophald:
ip: 192.168.8.168
ip: 192.168.8.188
cmdch.port: 19004
datach.port: 19005
@ -36,3 +36,13 @@ springdoc:
path: /doc/apitest.html # 自定义路径,默认为"/swagger-ui/index.html
operationsSorter: method # 接口按照方法排序
#window config
#modbus:
# port: COM18
# baudrate: 9600
#工控机 config
modbus:
port: ttyS1
baudrate: 9600
Loading…
Cancel
Save