From e8f5a9f67a21488574d9bd47197444483f094cb6 Mon Sep 17 00:00:00 2001 From: nguyentrungthat <80239428+nguentrungthat@users.noreply.github.com> Date: Mon, 24 Nov 2025 16:42:20 +0700 Subject: [PATCH] Add baud rate management for line connections Introduces baud rate configuration and detection for line connections in both backend and frontend. Backend now supports setting and checking baud rates via socket events, and frontend provides UI controls for users to select or input baud rates. Real-time updates are handled through new socket events, improving line management and visibility. --- BACKEND/app/services/line_connection.ts | 1 + BACKEND/providers/socket_io_provider.ts | 146 +++++++++++++++++++--- FRONTEND/src/App.tsx | 12 ++ FRONTEND/src/components/ModalTerminal.tsx | 76 +++++++++++ 4 files changed, 218 insertions(+), 17 deletions(-) diff --git a/BACKEND/app/services/line_connection.ts b/BACKEND/app/services/line_connection.ts index 40f45a3..24a7cef 100644 --- a/BACKEND/app/services/line_connection.ts +++ b/BACKEND/app/services/line_connection.ts @@ -21,6 +21,7 @@ interface LineConfig { outlet: number output: string status: string + baud: number openCLI: boolean userEmailOpenCLI: string userOpenCLI: string diff --git a/BACKEND/providers/socket_io_provider.ts b/BACKEND/providers/socket_io_provider.ts index b40fd13..ac04ae7 100644 --- a/BACKEND/providers/socket_io_provider.ts +++ b/BACKEND/providers/socket_io_provider.ts @@ -9,7 +9,7 @@ import { CustomServer, CustomSocket } from '../app/ultils/types.js' import Line from '#models/line' import Station from '#models/station' import APCController from '#services/apc_connection' -import { appendLog, sleep } from '../app/ultils/helper.js' +import { appendLog, cleanData, sleep } from '../app/ultils/helper.js' import SwitchController from '#services/switch_connection' import redis from '@adonisjs/redis/services/main' @@ -178,7 +178,7 @@ export class WebSocketIo { } Object.assign(line, { baud }) line?.save() - await this.setBaudByLineNumber(data.stationId, line?.lineNumber, baud) + await this.setBaudByClearLine(data.stationId, line?.lineClear, baud, lineId, io) }) socket.on('open_cli', async (data) => { @@ -510,6 +510,7 @@ export class WebSocketIo { stationId: station.id, apcName: line.apcName, outlet: line.outlet, + baud: line.baud, output: output, status: '', openCLI: false, @@ -529,6 +530,9 @@ export class WebSocketIo { await lineConn.connect() lineConn.writeCommand('\r\n\r\n') this.setTimeoutConnect(line.id, lineConn) + + if (line.lineClear && line.lineClear > 0) + await this.checkBaudByClearLine(station.id, line.lineClear, line.id, socket) } } catch (error) { console.log(error) @@ -781,7 +785,12 @@ export class WebSocketIo { this.intervalKeepConnect[`${ip}`] = interval } - private async setBaudByLineNumber(stationId: number, lineNumber: number, baud: number) { + private async checkBaudByClearLine( + stationId: number, + lineClear: number, + lineId: number, + io: any + ) { const station = await Station.find(stationId) if (!station) { console.log('[ERROR connect station] Not found!') @@ -790,43 +799,146 @@ export class WebSocketIo { // Kết nối tới station qua Telnet / Socket const client = new net.Socket() + let buffer = '' + return new Promise((resolve, reject) => { - client.setTimeout(5000) + client.setTimeout(8000) client.connect(station.port, station.ip, async () => { console.log(`Connected to station ${station.name} (${station.ip})`) - // Gửi lệnh clear line - client.write(`conf t\r\n`) - await sleep(500) - client.write(`line ${lineNumber}\r\n`) - await sleep(500) - client.write(`speed ${baud.toString()}\r\n`) - await sleep(500) - client.write(`end`) - await sleep(500) client.write(`\r\n`) await sleep(500) + client.write(`show line\r\n`) + await sleep(2000) client.destroy() resolve() }) client.on('data', (data) => { - appendLog(data.toString(), 0, 0, lineNumber) + const text = data.toString() + buffer += cleanData(text) }) client.on('error', (err) => { - console.error(`Error clearing line ${lineNumber}:`, err) + console.error(`Error clearing line ${lineClear}:`, err) resolve() }) client.on('close', () => { - console.log(`Station connection closed (line ${lineNumber})`) + console.log(`Station connection closed (line ${lineClear})`) + const result = this.detectBaudFromShowLine(buffer) + const found = result.find((x) => x.clearLine === lineClear) + if (found) { + const line = this.lineMap.get(lineId) + if (line) { + line.config.baud = found.baud + this.lineMap.set(lineId, line) + io.emit('update_baud', { + stationId, + lineId, + data: found.baud, + }) + } + } + resolve() }) client.on('timeout', () => { - console.log(`Station connection timeout (line ${lineNumber})`) + console.log(`Station connection timeout (line ${lineClear})`) client.destroy() resolve() }) }) } + + private async setBaudByClearLine( + stationId: number, + lineClear: number, + baud: number, + lineId: number, + io: any + ) { + const station = await Station.find(stationId) + if (!station) { + console.log('[ERROR connect station] Not found!') + return + } + + // Kết nối tới station qua Telnet / Socket + const client = new net.Socket() + let buffer = '' + + return new Promise((resolve, reject) => { + client.setTimeout(8000) + client.connect(station.port, station.ip, async () => { + console.log(`Connected to station ${station.name} (${station.ip})`) + // Gửi lệnh clear line + client.write(`conf t\r\n`) + await sleep(500) + client.write(`line ${lineClear}\r\n`) + await sleep(500) + client.write(`speed ${baud.toString()}\r\n`) + await sleep(500) + client.write(`end\r\n`) + await sleep(500) + client.write(`\r\n`) + await sleep(500) + client.write(`show line\r\n`) + await sleep(2000) + client.destroy() + resolve() + }) + + client.on('data', (data) => { + const text = data.toString() + buffer += text + }) + + client.on('error', (err) => { + console.error(`Error clearing line ${lineClear}:`, err) + resolve() + }) + + client.on('close', () => { + console.log(`Station connection closed (line ${lineClear})`) + const result = this.detectBaudFromShowLine(buffer) + const found = result.find((x) => x.clearLine === lineClear) + if (found) { + const line = this.lineMap.get(lineId) + if (line) { + line.config.baud = found.baud + io.emit('update_baud', { + stationId, + lineId, + data: found.baud, + }) + } + } + + resolve() + }) + client.on('timeout', () => { + console.log(`Station connection timeout (line ${lineClear})`) + client.destroy() + resolve() + }) + }) + } + + private detectBaudFromShowLine(output: string) { + const lines = output.split(/\r?\n/) + const result: { clearLine: number; baud: number }[] = [] + + const regex = /^\s*\S+\s+(\d+)\s+\S+\s+(\d+)\/(\d+)/ + + for (const line of lines) { + const match = line.replace('*', '').match(regex) + if (match) { + const clearLine = Number.parseInt(match[1], 10) + const baud = Number.parseInt(match[2], 10) + + result.push({ clearLine, baud }) + } + } + return result + } } diff --git a/FRONTEND/src/App.tsx b/FRONTEND/src/App.tsx index a93c271..8c1391b 100644 --- a/FRONTEND/src/App.tsx +++ b/FRONTEND/src/App.tsx @@ -295,6 +295,18 @@ function App() { }, 100); }); + socket?.on("update_baud", (data) => { + setTimeout(() => { + updateValueLineStation( + data.lineId, + { + baud: data.data, + }, + data?.stationId + ); + }, 100); + }); + // ✅ cleanup on unmount or when socket changes return () => { socket.off("init"); diff --git a/FRONTEND/src/components/ModalTerminal.tsx b/FRONTEND/src/components/ModalTerminal.tsx index 876a9c8..47d1026 100644 --- a/FRONTEND/src/components/ModalTerminal.tsx +++ b/FRONTEND/src/components/ModalTerminal.tsx @@ -32,6 +32,7 @@ import moment from "moment"; import axios from "axios"; import { notifications } from "@mantine/notifications"; import classes from "./Component.module.css"; +import { listBaudDefault } from "../untils/constanst"; const apiUrl = import.meta.env.VITE_BACKEND_URL; const INIT_TICKET = { @@ -71,6 +72,7 @@ const ModalTerminal = ({ const [listPorts, setListPorts] = useState([]); const [latestTicket, setLatestTicket] = useState(INIT_TICKET); const [dataTicket, setDataTicket] = useState(INIT_TICKET); + const [valueBaud, setValueBaud] = useState(""); useEffect(() => { if (opened && line?.tickets && line?.tickets?.length > 0) { @@ -80,6 +82,7 @@ const ModalTerminal = ({ } else { setLatestTicket(INIT_TICKET); setDataTicket(INIT_TICKET); + setValueBaud(""); } }, [opened, line?.tickets]); @@ -664,6 +667,79 @@ const ModalTerminal = ({ + + + + + + + {listBaudDefault.map((el, i) => ( + + ))} + setValueBaud(e.target.value)} + onKeyDown={(e) => { + if (e.key === "Enter") { + socket?.emit("set_baud", { + lineId: line?.id, + baud: Number(valueBaud), + stationId: Number(stationItem?.id), + }); + setValueBaud(""); + setIsDisable(true); + setTimeout(() => { + setIsDisable(false); + }, 5000); + } + }} + /> + + +