From 4dbbf0e79d484f64deba6b0e7ec3e0dcc363fb8f Mon Sep 17 00:00:00 2001 From: zhaohe Date: Mon, 27 Jan 2025 21:08:42 +0800 Subject: [PATCH] update --- .../java/iflytop/app/controler/UserControler.java | 2 +- .../app/controler/ws/AppEventWSEndpoint.java | 2 +- .../app/controler/ws/AppStateWSEndpoint.java | 2 +- .../iflytop/app/service/AppEventBusService.java | 79 ---------- .../app/service/AppWebSocketEndpointMgr.java | 99 ------------- .../app/service/MeasurementTaskCtrlService.java | 14 -- .../service/SubDeviceUartClientMockService.java | 163 --------------------- .../java/iflytop/app/service/UserMgrService.java | 12 -- .../app/service/base/AppEventBusService.java | 79 ++++++++++ .../iflytop/app/service/data/UserMgrService.java | 12 ++ .../mock/SubDeviceUartClientMockService.java | 163 +++++++++++++++++++++ .../service/task/MeasurementTaskCtrlService.java | 24 +++ .../app/service/ui/AppWebSocketEndpointMgr.java | 100 +++++++++++++ .../app/service/ui/UIStateControlService.java | 2 + 14 files changed, 383 insertions(+), 370 deletions(-) delete mode 100644 src/main/java/iflytop/app/service/AppEventBusService.java delete mode 100644 src/main/java/iflytop/app/service/AppWebSocketEndpointMgr.java delete mode 100644 src/main/java/iflytop/app/service/MeasurementTaskCtrlService.java delete mode 100644 src/main/java/iflytop/app/service/SubDeviceUartClientMockService.java delete mode 100644 src/main/java/iflytop/app/service/UserMgrService.java create mode 100644 src/main/java/iflytop/app/service/base/AppEventBusService.java create mode 100644 src/main/java/iflytop/app/service/data/UserMgrService.java create mode 100644 src/main/java/iflytop/app/service/mock/SubDeviceUartClientMockService.java create mode 100644 src/main/java/iflytop/app/service/task/MeasurementTaskCtrlService.java create mode 100644 src/main/java/iflytop/app/service/ui/AppWebSocketEndpointMgr.java create mode 100644 src/main/java/iflytop/app/service/ui/UIStateControlService.java diff --git a/src/main/java/iflytop/app/controler/UserControler.java b/src/main/java/iflytop/app/controler/UserControler.java index 2d1aa58..034b9a2 100644 --- a/src/main/java/iflytop/app/controler/UserControler.java +++ b/src/main/java/iflytop/app/controler/UserControler.java @@ -1,7 +1,7 @@ package iflytop.app.controler; -import iflytop.app.service.UserMgrService; +import iflytop.app.service.data.UserMgrService; import iflytop.app.type.db.AppUser; import iflytop.app.type.db.IflytopRet; import iflytop.app.type.exception.AppException; diff --git a/src/main/java/iflytop/app/controler/ws/AppEventWSEndpoint.java b/src/main/java/iflytop/app/controler/ws/AppEventWSEndpoint.java index 271c0ab..76c1b78 100644 --- a/src/main/java/iflytop/app/controler/ws/AppEventWSEndpoint.java +++ b/src/main/java/iflytop/app/controler/ws/AppEventWSEndpoint.java @@ -1,6 +1,6 @@ package iflytop.app.controler.ws; -import iflytop.app.service.AppWebSocketEndpointMgr; +import iflytop.app.service.ui.AppWebSocketEndpointMgr; import iflytop.app.utils.SpringBootBeanUtil; import jakarta.websocket.*; import jakarta.websocket.server.ServerEndpoint; diff --git a/src/main/java/iflytop/app/controler/ws/AppStateWSEndpoint.java b/src/main/java/iflytop/app/controler/ws/AppStateWSEndpoint.java index d9b4545..e1ed75c 100644 --- a/src/main/java/iflytop/app/controler/ws/AppStateWSEndpoint.java +++ b/src/main/java/iflytop/app/controler/ws/AppStateWSEndpoint.java @@ -1,6 +1,6 @@ package iflytop.app.controler.ws; -import iflytop.app.service.AppWebSocketEndpointMgr; +import iflytop.app.service.ui.AppWebSocketEndpointMgr; import iflytop.app.utils.SpringBootBeanUtil; import jakarta.websocket.*; import jakarta.websocket.server.ServerEndpoint; diff --git a/src/main/java/iflytop/app/service/AppEventBusService.java b/src/main/java/iflytop/app/service/AppEventBusService.java deleted file mode 100644 index 10a9ee0..0000000 --- a/src/main/java/iflytop/app/service/AppEventBusService.java +++ /dev/null @@ -1,79 +0,0 @@ -package iflytop.app.service; - -import iflytop.app.type.event.AppEvent; -import jakarta.annotation.PostConstruct; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.springframework.context.ApplicationListener; -import org.springframework.context.event.ContextRefreshedEvent; -import org.springframework.stereotype.Component; - -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; - -/** - * 事件总线 - */ -@Component -public class AppEventBusService implements ApplicationListener { - public static final Logger logger = LoggerFactory.getLogger(AppEventBusService.class); - - @FunctionalInterface - public interface AppEventListener { - void onAppEvent(AppEvent event); - } - - - Thread eventProcessorThread; - BlockingQueue eventQueue = new LinkedBlockingQueue<>(); - List listeners = new ArrayList<>(); - - @PostConstruct - public void init() { - - } - - public void regListener(AppEventListener listener) { - listeners.add(listener); - } - - public void pushEvent(AppEvent event) { -// logger.info("pushEvent: {} {}", event.getClass().getSimpleName(), event); - eventQueue.add(event); - } - - - private void eventBusSchedule() { - while (!Thread.currentThread().isInterrupted()) { - AppEvent event = null; - try { - event = eventQueue.take(); - } catch (InterruptedException ignored) { - } - callOnEvent(event); - } - } - - private void callOnEvent(AppEvent event) { - for (AppEventListener listener : listeners) { - listener.onAppEvent(event); - } - } - - @Override - public void onApplicationEvent(ContextRefreshedEvent event) { - logger.info("Spring context refreshed"); - if (eventProcessorThread == null) { - eventProcessorThread = new Thread(new Runnable() { - public void run() { - logger.info("Starting event bus schedule"); - eventBusSchedule(); - } - }); - eventProcessorThread.start(); - } - } - -} diff --git a/src/main/java/iflytop/app/service/AppWebSocketEndpointMgr.java b/src/main/java/iflytop/app/service/AppWebSocketEndpointMgr.java deleted file mode 100644 index fdc8689..0000000 --- a/src/main/java/iflytop/app/service/AppWebSocketEndpointMgr.java +++ /dev/null @@ -1,99 +0,0 @@ -package iflytop.app.service; - -import iflytop.app.utils.ZJsonHelper; -import jakarta.annotation.PostConstruct; -import jakarta.annotation.Resource; -import jakarta.websocket.Session; -import lombok.extern.slf4j.Slf4j; -import org.springframework.scheduling.annotation.EnableScheduling; -import org.springframework.stereotype.Component; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; - -/** - * 当前项目所有WebSocket连接与上传管理 - */ - -@Component -@EnableScheduling -@Slf4j -public class AppWebSocketEndpointMgr { - - public static class Report { - public String messageType = "Report"; - public String dataType; - public Object data; - public Integer timestamp = (int) (System.currentTimeMillis() / 1000); - - public Report(String dataType, Object object) { - this.dataType = dataType; - this.data = object; - } - } - - @Resource - AppEventBusService appEventBusService; - - - List stateWebsocketSessions = new ArrayList<>(); - List eventWebsocketSessions = new ArrayList<>(); - - synchronized public void pushStateWebsocketSession(Session session) { - stateWebsocketSessions.add(session); - } - - synchronized public void removeStateWebsocketSession(Session session) { - stateWebsocketSessions.remove(session); - } - - synchronized public void pushEventWebsocketSession(Session session) { - eventWebsocketSessions.add(session); - } - - synchronized public void removeEventWebsocketSession(Session session) { - eventWebsocketSessions.remove(session); - } - - synchronized void broadcastState(String message) { - for (Session session : stateWebsocketSessions) { - try { - session.getBasicRemote().sendText(message); - } catch (IOException | IllegalStateException e) { - log.warn("broadcastState: session.getBasicRemote().sendText() failed, ignore it"); - } - } - } - - synchronized void broadcastEvent(String message) { - for (Session session : eventWebsocketSessions) { - try { - session.getBasicRemote().sendText(message); - } catch (IOException | IllegalStateException e) { - log.warn("broadcastEvent: session.getBasicRemote().sendText() failed, ignore it"); - } - } - } - - @PostConstruct - public void init() { - } - - - synchronized public void reportState(String type, Object object) { - var message = ZJsonHelper.objectToJson(new Report(type, object)); - broadcastState(message); - } - - synchronized public void reportEvent(String type, Object object) { - var message = ZJsonHelper.objectToJson(new Report(type, object)); - broadcastEvent(message); - } - - // - // Scheduled tasks - // - - -}; diff --git a/src/main/java/iflytop/app/service/MeasurementTaskCtrlService.java b/src/main/java/iflytop/app/service/MeasurementTaskCtrlService.java deleted file mode 100644 index fe8174a..0000000 --- a/src/main/java/iflytop/app/service/MeasurementTaskCtrlService.java +++ /dev/null @@ -1,14 +0,0 @@ -package iflytop.app.service; - -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - - -@Component -@Slf4j -public class MeasurementTaskCtrlService { - - - - -} diff --git a/src/main/java/iflytop/app/service/SubDeviceUartClientMockService.java b/src/main/java/iflytop/app/service/SubDeviceUartClientMockService.java deleted file mode 100644 index 57b383a..0000000 --- a/src/main/java/iflytop/app/service/SubDeviceUartClientMockService.java +++ /dev/null @@ -1,163 +0,0 @@ -package iflytop.app.service; - -import com.fazecast.jSerialComm.SerialPort; -import com.fazecast.jSerialComm.SerialPortDataListener; -import com.fazecast.jSerialComm.SerialPortEvent; -import iflytop.app.factory.TPMIPacketFactory; -import iflytop.app.type.error.AppEcode; -import iflytop.app.type.exception.AppException; -import iflytop.app.type.protocol.TPMIPacket; -import iflytop.app.utils.*; -import jakarta.annotation.PostConstruct; -import lombok.extern.slf4j.Slf4j; -import org.springframework.stereotype.Component; - -@Component -@Slf4j -public class SubDeviceUartClientMockService { - public static final int SERIAL_BAUD_RATE = 115200; - - public SerialPort client; - private Thread thread; - ZByteRxBuffer rxBuffer = new ZByteRxBuffer(1024); - - - @PostConstruct - void init() throws AppException { - thread = new Thread(() -> { - while (true) { - processUartRxData(); - } - }); - thread.setName("SubDeviceUartClientMock"); - thread.start(); - - openCom("COM1"); - } - - void processUartRxData() { - if (rxBuffer.isOverflow()) { - log.warn("RX buffer overflow, clear buffer"); - rxBuffer.clear(); - return; - } - - byte[] processbuf = rxBuffer.cpy(); - int offset = 0; - - for (offset = 0; offset < processbuf.length; ) { - var report = TPMIPacketFactory.analysisRawRxData(processbuf, processbuf.length, offset); - if (report.result.equals(TPMIPacketFactory.PacketAnalysisResult.SUC)) { - // log.info("RX: {}", report.packet); - offset += report.packet.getPacketLen(); - processRXPacket(report.packet); - } else if (report.result.equals(TPMIPacketFactory.PacketAnalysisResult.CHECKSUM_ERROR)) { - log.error("RX: CHECKSUM_ERROR PACKET: {}", report.packet); - offset += report.packet.getPacketLen(); - } else if (report.result.equals(TPMIPacketFactory.PacketAnalysisResult.PACKE_NOT_FULLY_RECEIVED)) { - break; - } else { - offset += 1; - } - } - rxBuffer.pop(offset); - } - - void processRXPacket(TPMIPacket rx) { - if (rx.getCommand().equals(TPMIPacket.Command.GET_SN)) { - var respPacket = TPMIPacketFactory.buildReceipt(rx, "SN000000"); - sendPacket(respPacket); - } else if (rx.getCommand().equals(TPMIPacket.Command.GET_CALIBRATION_TIME)) { - var respPacket = TPMIPacketFactory.buildReceipt(rx, 2024, 12, 1); - sendPacket(respPacket); - } else if (rx.getCommand().equals(TPMIPacket.Command.GET_VERSION)) { - var respPacket = TPMIPacketFactory.buildReceipt(rx, 1, 2, 3); - sendPacket(respPacket); - } else { - var respPacket = TPMIPacketFactory.buildReceipt(rx); - sendPacket(respPacket); - } - } - - synchronized public void sendPacket(TPMIPacket packet) { - if (client == null) { - log.error("COM not open"); - return; - } - //TX VAL - client.writeBytes(packet.rawpacket, packet.rawpacket.length); - } - - /** - * Open COM - * @param comName COM name - * @throws AppException AppException - */ - synchronized public void openCom(String comName) throws AppException { - if (client != null) { - log.info("Force close COM {}", client.getSystemPortName()); - client.closePort(); - client = null; - } - - SerialPort clientPort = SerialPort.getCommPort(comName); - ZAsser.isTrue(clientPort != null, AppEcode.USART_ERROR_COM_NOT_FOUND, null); - - try { - ZAsser.isTrue(clientPort.setBaudRate(SERIAL_BAUD_RATE), - AppEcode.USART_OPERATION_ERROR_SET_BAUD_RATE, null); - ZAsser.isTrue(clientPort.openPort(50), - AppEcode.USART_OPERATION_ERROR_OPEN_PORT, null); - ZAsser.isTrue(clientPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED), - AppEcode.USART_OPERATION_ERROR_SET_FLOW_CONTROL, null); - ZAsser.isTrue(clientPort.setComPortParameters(SERIAL_BAUD_RATE, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY), - AppEcode.USART_OPERATION_ERROR_SET_COM_PORT_PARAMETERS, null); - ZAsser.isTrue(clientPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 10, 10), - AppEcode.USART_OPERATION_ERROR_SET_COM_PORT_TIMEOUTS, null); - - /* - * 注意事项 - * 1. 如果接收到DISCONNECTED事件,说明串口已经被拔掉,需要关闭串口 - * 2. 如果接收到DATA_AVAILABLE事件,说明串口有数据到来,需要读取数据 - * 3. LISTENING_EVENT_DATA_AVAILABLE 和 LISTENING_EVENT_DATA_RECEIVED 是互斥的,只能监听一个。 - * https://fazecast.github.io/jSerialComm/javadoc/com/fazecast/jSerialComm/SerialPortDataListener.html - */ - clientPort.addDataListener(new SerialPortDataListener() { - @Override public int getListeningEvents() { - return SerialPort.LISTENING_EVENT_DATA_AVAILABLE | - SerialPort.LISTENING_EVENT_PORT_DISCONNECTED; - } - - @Override public void serialEvent(SerialPortEvent serialPortEvent) { - if (serialPortEvent.getEventType() == SerialPort.LISTENING_EVENT_DATA_AVAILABLE) { - byte[] newData = new byte[clientPort.bytesAvailable()]; - int numRead = clientPort.readBytes(newData, newData.length); - rxBuffer.push(newData, numRead); - log.debug("RX RAW: {} ({})", ZByteUtils.bytesToHexString(newData, numRead), numRead); - } else if (serialPortEvent.getEventType() == SerialPort.LISTENING_EVENT_PORT_DISCONNECTED) { - log.warn("serialEvent: port disconnected"); - closeCom(); - } - } - }); - this.client = clientPort; - log.info("Open COM {}, connectState {}", comName, clientPort.isOpen()); - } catch (Exception e) { - clientPort.closePort(); - throw e; - } - } - - /** - * Close COM - */ - synchronized public void closeCom() { - if (client != null) { - log.info("Close COM {}", client.getSystemPortName()); - client.closePort(); - client = null; - } - } - - -} diff --git a/src/main/java/iflytop/app/service/UserMgrService.java b/src/main/java/iflytop/app/service/UserMgrService.java deleted file mode 100644 index a043f07..0000000 --- a/src/main/java/iflytop/app/service/UserMgrService.java +++ /dev/null @@ -1,12 +0,0 @@ -package iflytop.app.service; - -import iflytop.app.type.db.AppUser; -import org.springframework.stereotype.Service; - -@Service -public class UserMgrService { - - public AppUser login(Integer id, String password) { - return new AppUser(); - } -} diff --git a/src/main/java/iflytop/app/service/base/AppEventBusService.java b/src/main/java/iflytop/app/service/base/AppEventBusService.java new file mode 100644 index 0000000..181fc9f --- /dev/null +++ b/src/main/java/iflytop/app/service/base/AppEventBusService.java @@ -0,0 +1,79 @@ +package iflytop.app.service.base; + +import iflytop.app.type.event.AppEvent; +import jakarta.annotation.PostConstruct; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationListener; +import org.springframework.context.event.ContextRefreshedEvent; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; + +/** + * 事件总线 + */ +@Component +public class AppEventBusService implements ApplicationListener { + public static final Logger logger = LoggerFactory.getLogger(AppEventBusService.class); + + @FunctionalInterface + public interface AppEventListener { + void onAppEvent(AppEvent event); + } + + + Thread eventProcessorThread; + BlockingQueue eventQueue = new LinkedBlockingQueue<>(); + List listeners = new ArrayList<>(); + + @PostConstruct + public void init() { + + } + + public void regListener(AppEventListener listener) { + listeners.add(listener); + } + + public void pushEvent(AppEvent event) { +// logger.info("pushEvent: {} {}", event.getClass().getSimpleName(), event); + eventQueue.add(event); + } + + + private void eventBusSchedule() { + while (!Thread.currentThread().isInterrupted()) { + AppEvent event = null; + try { + event = eventQueue.take(); + } catch (InterruptedException ignored) { + } + callOnEvent(event); + } + } + + private void callOnEvent(AppEvent event) { + for (AppEventListener listener : listeners) { + listener.onAppEvent(event); + } + } + + @Override + public void onApplicationEvent(ContextRefreshedEvent event) { + logger.info("Spring context refreshed"); + if (eventProcessorThread == null) { + eventProcessorThread = new Thread(new Runnable() { + public void run() { + logger.info("Starting event bus schedule"); + eventBusSchedule(); + } + }); + eventProcessorThread.start(); + } + } + +} diff --git a/src/main/java/iflytop/app/service/data/UserMgrService.java b/src/main/java/iflytop/app/service/data/UserMgrService.java new file mode 100644 index 0000000..1dc6cf4 --- /dev/null +++ b/src/main/java/iflytop/app/service/data/UserMgrService.java @@ -0,0 +1,12 @@ +package iflytop.app.service.data; + +import iflytop.app.type.db.AppUser; +import org.springframework.stereotype.Service; + +@Service +public class UserMgrService { + + public AppUser login(Integer id, String password) { + return new AppUser(); + } +} diff --git a/src/main/java/iflytop/app/service/mock/SubDeviceUartClientMockService.java b/src/main/java/iflytop/app/service/mock/SubDeviceUartClientMockService.java new file mode 100644 index 0000000..6b30a5f --- /dev/null +++ b/src/main/java/iflytop/app/service/mock/SubDeviceUartClientMockService.java @@ -0,0 +1,163 @@ +package iflytop.app.service.mock; + +import com.fazecast.jSerialComm.SerialPort; +import com.fazecast.jSerialComm.SerialPortDataListener; +import com.fazecast.jSerialComm.SerialPortEvent; +import iflytop.app.factory.TPMIPacketFactory; +import iflytop.app.type.error.AppEcode; +import iflytop.app.type.exception.AppException; +import iflytop.app.type.protocol.TPMIPacket; +import iflytop.app.utils.*; +import jakarta.annotation.PostConstruct; +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + +@Component +@Slf4j +public class SubDeviceUartClientMockService { + public static final int SERIAL_BAUD_RATE = 115200; + + public SerialPort client; + private Thread thread; + ZByteRxBuffer rxBuffer = new ZByteRxBuffer(1024); + + + @PostConstruct + void init() throws AppException { + thread = new Thread(() -> { + while (true) { + processUartRxData(); + } + }); + thread.setName("SubDeviceUartClientMock"); + thread.start(); + + openCom("COM1"); + } + + void processUartRxData() { + if (rxBuffer.isOverflow()) { + log.warn("RX buffer overflow, clear buffer"); + rxBuffer.clear(); + return; + } + + byte[] processbuf = rxBuffer.cpy(); + int offset = 0; + + for (offset = 0; offset < processbuf.length; ) { + var report = TPMIPacketFactory.analysisRawRxData(processbuf, processbuf.length, offset); + if (report.result.equals(TPMIPacketFactory.PacketAnalysisResult.SUC)) { + // log.info("RX: {}", report.packet); + offset += report.packet.getPacketLen(); + processRXPacket(report.packet); + } else if (report.result.equals(TPMIPacketFactory.PacketAnalysisResult.CHECKSUM_ERROR)) { + log.error("RX: CHECKSUM_ERROR PACKET: {}", report.packet); + offset += report.packet.getPacketLen(); + } else if (report.result.equals(TPMIPacketFactory.PacketAnalysisResult.PACKE_NOT_FULLY_RECEIVED)) { + break; + } else { + offset += 1; + } + } + rxBuffer.pop(offset); + } + + void processRXPacket(TPMIPacket rx) { + if (rx.getCommand().equals(TPMIPacket.Command.GET_SN)) { + var respPacket = TPMIPacketFactory.buildReceipt(rx, "SN000000"); + sendPacket(respPacket); + } else if (rx.getCommand().equals(TPMIPacket.Command.GET_CALIBRATION_TIME)) { + var respPacket = TPMIPacketFactory.buildReceipt(rx, 2024, 12, 1); + sendPacket(respPacket); + } else if (rx.getCommand().equals(TPMIPacket.Command.GET_VERSION)) { + var respPacket = TPMIPacketFactory.buildReceipt(rx, 1, 2, 3); + sendPacket(respPacket); + } else { + var respPacket = TPMIPacketFactory.buildReceipt(rx); + sendPacket(respPacket); + } + } + + synchronized public void sendPacket(TPMIPacket packet) { + if (client == null) { + log.error("COM not open"); + return; + } + //TX VAL + client.writeBytes(packet.rawpacket, packet.rawpacket.length); + } + + /** + * Open COM + * @param comName COM name + * @throws AppException AppException + */ + synchronized public void openCom(String comName) throws AppException { + if (client != null) { + log.info("Force close COM {}", client.getSystemPortName()); + client.closePort(); + client = null; + } + + SerialPort clientPort = SerialPort.getCommPort(comName); + ZAsser.isTrue(clientPort != null, AppEcode.USART_ERROR_COM_NOT_FOUND, null); + + try { + ZAsser.isTrue(clientPort.setBaudRate(SERIAL_BAUD_RATE), + AppEcode.USART_OPERATION_ERROR_SET_BAUD_RATE, null); + ZAsser.isTrue(clientPort.openPort(50), + AppEcode.USART_OPERATION_ERROR_OPEN_PORT, null); + ZAsser.isTrue(clientPort.setFlowControl(SerialPort.FLOW_CONTROL_DISABLED), + AppEcode.USART_OPERATION_ERROR_SET_FLOW_CONTROL, null); + ZAsser.isTrue(clientPort.setComPortParameters(SERIAL_BAUD_RATE, 8, SerialPort.ONE_STOP_BIT, SerialPort.NO_PARITY), + AppEcode.USART_OPERATION_ERROR_SET_COM_PORT_PARAMETERS, null); + ZAsser.isTrue(clientPort.setComPortTimeouts(SerialPort.TIMEOUT_READ_SEMI_BLOCKING | SerialPort.TIMEOUT_WRITE_BLOCKING, 10, 10), + AppEcode.USART_OPERATION_ERROR_SET_COM_PORT_TIMEOUTS, null); + + /* + * 注意事项 + * 1. 如果接收到DISCONNECTED事件,说明串口已经被拔掉,需要关闭串口 + * 2. 如果接收到DATA_AVAILABLE事件,说明串口有数据到来,需要读取数据 + * 3. LISTENING_EVENT_DATA_AVAILABLE 和 LISTENING_EVENT_DATA_RECEIVED 是互斥的,只能监听一个。 + * https://fazecast.github.io/jSerialComm/javadoc/com/fazecast/jSerialComm/SerialPortDataListener.html + */ + clientPort.addDataListener(new SerialPortDataListener() { + @Override public int getListeningEvents() { + return SerialPort.LISTENING_EVENT_DATA_AVAILABLE | + SerialPort.LISTENING_EVENT_PORT_DISCONNECTED; + } + + @Override public void serialEvent(SerialPortEvent serialPortEvent) { + if (serialPortEvent.getEventType() == SerialPort.LISTENING_EVENT_DATA_AVAILABLE) { + byte[] newData = new byte[clientPort.bytesAvailable()]; + int numRead = clientPort.readBytes(newData, newData.length); + rxBuffer.push(newData, numRead); + log.debug("RX RAW: {} ({})", ZByteUtils.bytesToHexString(newData, numRead), numRead); + } else if (serialPortEvent.getEventType() == SerialPort.LISTENING_EVENT_PORT_DISCONNECTED) { + log.warn("serialEvent: port disconnected"); + closeCom(); + } + } + }); + this.client = clientPort; + log.info("Open COM {}, connectState {}", comName, clientPort.isOpen()); + } catch (Exception e) { + clientPort.closePort(); + throw e; + } + } + + /** + * Close COM + */ + synchronized public void closeCom() { + if (client != null) { + log.info("Close COM {}", client.getSystemPortName()); + client.closePort(); + client = null; + } + } + + +} diff --git a/src/main/java/iflytop/app/service/task/MeasurementTaskCtrlService.java b/src/main/java/iflytop/app/service/task/MeasurementTaskCtrlService.java new file mode 100644 index 0000000..c868bfb --- /dev/null +++ b/src/main/java/iflytop/app/service/task/MeasurementTaskCtrlService.java @@ -0,0 +1,24 @@ +package iflytop.app.service.task; + +import lombok.extern.slf4j.Slf4j; +import org.springframework.stereotype.Component; + + +/** + * 测量任务控制服务 + * + */ +@Component +@Slf4j +public class MeasurementTaskCtrlService { + + // + // API + // new Task + // start + // commit report + // reMeasure + // + + +} diff --git a/src/main/java/iflytop/app/service/ui/AppWebSocketEndpointMgr.java b/src/main/java/iflytop/app/service/ui/AppWebSocketEndpointMgr.java new file mode 100644 index 0000000..3d5583b --- /dev/null +++ b/src/main/java/iflytop/app/service/ui/AppWebSocketEndpointMgr.java @@ -0,0 +1,100 @@ +package iflytop.app.service.ui; + +import iflytop.app.service.base.AppEventBusService; +import iflytop.app.utils.ZJsonHelper; +import jakarta.annotation.PostConstruct; +import jakarta.annotation.Resource; +import jakarta.websocket.Session; +import lombok.extern.slf4j.Slf4j; +import org.springframework.scheduling.annotation.EnableScheduling; +import org.springframework.stereotype.Component; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; + +/** + * 当前项目所有WebSocket连接与上传管理 + */ + +@Component +@EnableScheduling +@Slf4j +public class AppWebSocketEndpointMgr { + + public static class Report { + public String messageType = "Report"; + public String dataType; + public Object data; + public Integer timestamp = (int) (System.currentTimeMillis() / 1000); + + public Report(String dataType, Object object) { + this.dataType = dataType; + this.data = object; + } + } + + @Resource + AppEventBusService appEventBusService; + + + List stateWebsocketSessions = new ArrayList<>(); + List eventWebsocketSessions = new ArrayList<>(); + + synchronized public void pushStateWebsocketSession(Session session) { + stateWebsocketSessions.add(session); + } + + synchronized public void removeStateWebsocketSession(Session session) { + stateWebsocketSessions.remove(session); + } + + synchronized public void pushEventWebsocketSession(Session session) { + eventWebsocketSessions.add(session); + } + + synchronized public void removeEventWebsocketSession(Session session) { + eventWebsocketSessions.remove(session); + } + + synchronized void broadcastState(String message) { + for (Session session : stateWebsocketSessions) { + try { + session.getBasicRemote().sendText(message); + } catch (IOException | IllegalStateException e) { + log.warn("broadcastState: session.getBasicRemote().sendText() failed, ignore it"); + } + } + } + + synchronized void broadcastEvent(String message) { + for (Session session : eventWebsocketSessions) { + try { + session.getBasicRemote().sendText(message); + } catch (IOException | IllegalStateException e) { + log.warn("broadcastEvent: session.getBasicRemote().sendText() failed, ignore it"); + } + } + } + + @PostConstruct + public void init() { + } + + + synchronized public void reportState(String type, Object object) { + var message = ZJsonHelper.objectToJson(new Report(type, object)); + broadcastState(message); + } + + synchronized public void reportEvent(String type, Object object) { + var message = ZJsonHelper.objectToJson(new Report(type, object)); + broadcastEvent(message); + } + + // + // Scheduled tasks + // + + +}; diff --git a/src/main/java/iflytop/app/service/ui/UIStateControlService.java b/src/main/java/iflytop/app/service/ui/UIStateControlService.java new file mode 100644 index 0000000..38e8646 --- /dev/null +++ b/src/main/java/iflytop/app/service/ui/UIStateControlService.java @@ -0,0 +1,2 @@ +package iflytop.app.service.ui;public class UIStateControlService { +}