Update status is ready for line

This commit is contained in:
nguyentrungthat 2026-02-24 09:36:36 +07:00
parent 669c30ca11
commit 05950726bf
7 changed files with 108 additions and 22 deletions

View File

@ -4,6 +4,7 @@ import net from 'node:net'
import {
appendLog,
buildBody,
canInputCommand,
classifyLog,
cleanData,
convertFromKilobytesString,
@ -139,6 +140,7 @@ export default class LineConnection {
private testingPortPoE: boolean
private outputTestingPortPoE: string
private debounceSendSummaryReport: NodeJS.Timeout | null = null
public isReady: boolean
constructor(config: LineConfig, socketIO: any, handleClearLine: () => void) {
this.config = config
@ -172,6 +174,7 @@ export default class LineConnection {
this.debounceSendSummaryReport = null
this.testingPortPoE = false
this.outputTestingPortPoE = ''
this.isReady = false
}
/**
* Connect to line with socket
@ -203,7 +206,7 @@ export default class LineConnection {
this.sendFeatureTested()
this.checkLog()
resolve()
}, 1000)
}, 2000)
})
this.client.on('data', (data) => {
@ -248,11 +251,15 @@ export default class LineConnection {
}
this.config.output += cleanData(rawData)
this.config.output = this.config.output.slice(-15000)
if (!this.isReady && canInputCommand(message)) {
this.isReady = true
}
this.socketIO.emit('line_output', {
stationId,
lineId: id,
data: message,
ports: this.config.ports,
isReady: this.isReady ? true : canInputCommand(message),
})
setTimeout(() => {
if (!this.config.inventory) {
@ -289,6 +296,7 @@ export default class LineConnection {
this.config.listFeatureTested = []
this.config.latestScenario = undefined
this.physicalTest = new PhysicalPortTest([])
this.isReady = false
// this.config.inventory = undefined
this.socketIO.emit('line_disconnected', {
stationId,
@ -342,7 +350,7 @@ export default class LineConnection {
/**
* Write a command with socket.write
*/
async writeCommand(cmd: string | Buffer<ArrayBuffer>, userName = '') {
async writeCommand(cmd: string | Buffer<ArrayBuffer>) {
if (this.client.destroyed) {
console.log(`⚠️ Cannot send, line ${this.config.lineNumber} is closed`)
this.disconnect()
@ -394,6 +402,10 @@ export default class LineConnection {
this.outputBuffer = ''
return
}
if (!this.isReady) {
console.log('Device is not ready')
return
}
if (this.config.runningScenario || this.config.runningPhysical) {
console.log('Script already running')
return
@ -594,18 +606,8 @@ export default class LineConnection {
]
this.sendFeatureTested()
// Debounce send summary report
if (this.debounceSendSummaryReport) clearTimeout(this.debounceSendSummaryReport)
// Snapshot toàn bộ data tại thời điểm này
const snapshot = {
snapConfig: this.config,
snapPhysical: this.physicalTest,
}
this.debounceSendSummaryReport = setTimeout(() => {
this.config.listFeatureTested = ['DPELP', 'PHYSICAL']
this.sendFeatureTested()
this.sendReportSummary(snapshot)
}, 600000) // 10p debounce
// Set timeout send report
this.setTimeoutSendSummaryReport(600000)
// }
if (this.config.latestScenario)
@ -1262,6 +1264,8 @@ export default class LineConnection {
async sendReportPhysicalTest() {
this.config.listFeatureTested = [...new Set([...this.config.listFeatureTested, 'PHYSICAL'])]
this.sendFeatureTested()
// Set timeout send report
this.setTimeoutSendSummaryReport(180000)
const formReport = this.physicalTest.getFormReport()
await sendMessageToMail(
`[ATC] - [${this.config.stationName} - Line: ${this.config.lineNumber}] - Physical Ports Test`,
@ -1836,4 +1840,30 @@ ${log}
}
this.physicalTest = new PhysicalPortTest([])
}
setTimeoutSendSummaryReport(timeout: number) {
// Debounce send summary report
if (this.debounceSendSummaryReport) clearTimeout(this.debounceSendSummaryReport)
// Snapshot toàn bộ data tại thời điểm này
const snapshot = {
snapConfig: this.config,
snapPhysical: this.physicalTest,
}
this.debounceSendSummaryReport = setTimeout(() => {
this.config.listFeatureTested = ['DPELP', 'PHYSICAL']
this.sendFeatureTested()
this.sendReportSummary(snapshot)
}, timeout)
}
/**
* Send is ready
*/
sendIsReady = async () => {
this.socketIO.emit('line_is_ready', {
stationId: this.config.stationId,
lineId: this.config.id,
isReady: this.isReady,
})
}
}

View File

@ -1579,3 +1579,32 @@ export function convertFromKilobytesString(input: string, decimals = 0): string
return `${displayValue.toFixed(decimals)} ${units[unitIndex]}`
}
export function canInputCommand(buffer: string): boolean {
if (!buffer) return false
const data = buffer.toString()
// IOS prompt (hostname> hoặc hostname#)
if (/[\r\n]?[\w.-]+[>#]\s?$/.test(data)) return true
// Username / Password
if (data.includes('Username:')) return true
if (data.includes('Password:')) return true
// ROMMON
if (/rommon\s+\d+\s+>/i.test(data)) return true
// Switch loader
if (data.includes('switch:')) return true
// Press RETURN
if (data.includes('Press RETURN to get started!')) return true
// yes/no cases
if (/\[(yes\/no|confirm)\]/i.test(data)) return true
if (/\((yes\/no|y\/n)\)/i.test(data)) return true
if (/yes\/no/i.test(data)) return true
return false
}

View File

@ -195,7 +195,7 @@ export class WebSocketIo {
stationId,
lineIds,
async (line) =>
command === 'spam_break' ? line.breakSpam() : line.writeCommand(command, userName),
command === 'spam_break' ? line.breakSpam() : line.writeCommand(command),
{ command }
)
})
@ -257,7 +257,7 @@ export class WebSocketIo {
io,
stationId,
[lineId],
async (lineCon) => lineCon.writeCommand('\r\n', userName),
async (lineCon) => lineCon.writeCommand('\r\n'),
{ command: '\r\n' }
)
} else {

View File

@ -264,11 +264,11 @@ function App() {
socket?.on("line_output", (data) => {
const { lineId, data: text } = data;
// updateValueLineStation(
// data?.lineId,
// { netOutput: data.data, commands: data.commands || [] },
// data?.stationId
// );
updateValueLineStation(
data?.lineId,
{ isReady: data.isReady },
data?.stationId
);
const buf = lineBuffersRef.current.get(lineId) || "";
lineBuffersRef.current.set(lineId, buf + text);

View File

@ -130,7 +130,7 @@ const CardLine = ({
Array.isArray(line?.latestScenario?.detectAI?.issue)
? "- " + line?.latestScenario?.detectAI?.issue?.join("\n- ")
: "";
if (data) setIsShowIssue(true);
if (data && !data.includes("No issues detected")) setIsShowIssue(true);
else setIsShowIssue(false);
} else setIsShowIssue(false);
}, [line?.latestScenario]);
@ -336,6 +336,19 @@ const CardLine = ({
connecting...
</motion.div>
)}
{!line?.isReady && line?.status === "connected" && (
<motion.div
style={{ fontSize: "11px", color: "red" }}
animate={{ opacity: [0.2, 1, 0.2] }}
transition={{
duration: 1.2,
repeat: Infinity,
ease: "easeInOut",
}}
>
booting...
</motion.div>
)}
{line?.runningScenario && (
<motion.div
style={{ fontSize: "11px", color: "red" }}

View File

@ -590,6 +590,19 @@ const ModalTerminal = ({
connecting...
</motion.div>
)}
{!line?.isReady && line?.status === "connected" && (
<motion.div
style={{ fontSize: "12px", color: "red" }}
animate={{ opacity: [0.2, 1, 0.2] }}
transition={{
duration: 1.2,
repeat: Infinity,
ease: "easeInOut",
}}
>
booting...
</motion.div>
)}
{line?.runningScenario && (
<motion.div
style={{ fontSize: "12px", color: "red" }}

View File

@ -108,6 +108,7 @@ export type TLine = {
runningPhysical?: boolean;
listPortsPhysical?: string[];
listFeatureTested?: string[];
isReady?: boolean;
};
export type TUser = {