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); + } + }} + /> + + +