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.
This commit is contained in:
parent
9d1be9e260
commit
e8f5a9f67a
|
|
@ -21,6 +21,7 @@ interface LineConfig {
|
|||
outlet: number
|
||||
output: string
|
||||
status: string
|
||||
baud: number
|
||||
openCLI: boolean
|
||||
userEmailOpenCLI: string
|
||||
userOpenCLI: string
|
||||
|
|
|
|||
|
|
@ -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<void>((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<void>((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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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<SwitchPortsProps[]>([]);
|
||||
const [latestTicket, setLatestTicket] = useState<TDataTicket>(INIT_TICKET);
|
||||
const [dataTicket, setDataTicket] = useState<TDataTicket>(INIT_TICKET);
|
||||
const [valueBaud, setValueBaud] = useState<string>("");
|
||||
|
||||
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 = ({
|
|||
</Box>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
<Menu
|
||||
closeOnItemClick={false}
|
||||
closeOnClickOutside={false}
|
||||
trigger="hover"
|
||||
shadow="md"
|
||||
position="top"
|
||||
>
|
||||
<Menu.Target>
|
||||
<Button
|
||||
fw={400}
|
||||
disabled={isDisable}
|
||||
variant="filled"
|
||||
size="xs"
|
||||
style={{ height: "30px", width: "100px" }}
|
||||
onClick={() => {}}
|
||||
>
|
||||
BAUD
|
||||
</Button>
|
||||
</Menu.Target>
|
||||
<Menu.Dropdown style={{ width: "110px" }}>
|
||||
<Flex
|
||||
justify={"space-between"}
|
||||
direction={"column"}
|
||||
style={{
|
||||
gap: "8px",
|
||||
}}
|
||||
>
|
||||
{listBaudDefault.map((el, i) => (
|
||||
<Button
|
||||
key={i}
|
||||
disabled={isDisable}
|
||||
variant="outline"
|
||||
size="xs"
|
||||
fw={400}
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
socket?.emit("set_baud", {
|
||||
lineId: line?.id,
|
||||
baud: el,
|
||||
stationId: Number(stationItem?.id),
|
||||
});
|
||||
setIsDisable(true);
|
||||
setTimeout(() => {
|
||||
setIsDisable(false);
|
||||
}, 5000);
|
||||
}}
|
||||
>
|
||||
{el}
|
||||
</Button>
|
||||
))}
|
||||
<Input
|
||||
placeholder="Custom"
|
||||
value={valueBaud}
|
||||
onChange={(e) => 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);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</Flex>
|
||||
</Menu.Dropdown>
|
||||
</Menu>
|
||||
<Button
|
||||
disabled={true}
|
||||
fw={400}
|
||||
|
|
|
|||
Loading…
Reference in New Issue