22 changed files with 1189 additions and 19 deletions
-
19pom.xml
-
2src/main/java/iflytop/app/hardware/channel/A8kCanBusConnection.java
-
127src/main/java/iflytop/app/hardware/channel/keyChannel.java
-
85src/main/java/iflytop/app/hardware/channel/modbus/JSerialCommWrapper.java
-
13src/main/java/iflytop/app/hardware/channel/modbus/ModbusMasterFactory.java
-
283src/main/java/iflytop/app/hardware/channel/modbus/ModbusMasterService.java
-
25src/main/java/iflytop/app/hardware/driver/FillLightDriver.java
-
125src/main/java/iflytop/app/hardware/driver/HeaterRodDriver.java
-
37src/main/java/iflytop/app/hardware/driver/InputDetectDriver.java
-
30src/main/java/iflytop/app/hardware/driver/TricolorLightDriver.java
-
44src/main/java/iflytop/app/hardware/type/CmdDevice.java
-
14src/main/java/iflytop/app/hardware/type/CmdId.java
-
51src/main/java/iflytop/app/hardware/type/HeaterRodSlavedId.java
-
39src/main/java/iflytop/app/hardware/type/InputIOMId.java
-
5src/main/java/iflytop/app/menu/ExtApiPageGroupCfgMgr.java
-
22src/main/java/iflytop/app/page/DeviceInitPage.java
-
91src/main/java/iflytop/app/page/HeaterRodPage.java
-
61src/main/java/iflytop/app/page/IOBoardCtrlPage.java
-
96src/main/java/iflytop/app/page/InputIOStateScannerPage.java
-
5src/main/java/iflytop/app/page/OutputIOCtrlPage.java
-
22src/main/java/iflytop/app/service/appsetup/A8kSubModuleRegInitService.java
-
12src/main/resources/application.yml
@ -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(); |
|||
} |
|||
} |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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(); |
|||
} |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
@ -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 |
|||
} |
@ -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; |
|||
} |
|||
} |
@ -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; |
|||
|
|||
} |
|||
} |
@ -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); |
|||
|
|||
|
|||
} |
|||
|
|||
|
|||
} |
@ -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); |
|||
|
|||
|
|||
} |
|||
} |
@ -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); |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue