Merge pull request 'Add baud rate management for line connections' (#3) from that into main
Reviewed-on: #3
This commit is contained in:
commit
3123262c7f
|
|
@ -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