Update physical test, load ios
This commit is contained in:
parent
07cfde8c15
commit
28059f85ed
|
|
@ -54,7 +54,9 @@ export default class HealCheckController {
|
||||||
serialNumberA: dataSN?.serialNumberA,
|
serialNumberA: dataSN?.serialNumberA,
|
||||||
productModelId: dataSN?.productModelId,
|
productModelId: dataSN?.productModelId,
|
||||||
orgId: dataSN?.orgId,
|
orgId: dataSN?.orgId,
|
||||||
|
condition: dataSN?.condition,
|
||||||
testNotes: dataSN?.testNotes,
|
testNotes: dataSN?.testNotes,
|
||||||
|
healthCheck: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
@ -71,10 +73,11 @@ export default class HealCheckController {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
...dataCheckNote,
|
...dataCheckNote,
|
||||||
status: resSN.data?.error ? false : true,
|
status: resSN?.data?.Status === 'ERROR' ? false : true,
|
||||||
message: resSN.data?.error
|
message:
|
||||||
? `Checking api update note SN false: '${resSN.data?.error?.message}'`
|
resSN?.data?.Status === 'ERROR'
|
||||||
: 'Checking api update note SN success',
|
? `Checking api update note SN false: '${resSN.data?.Msg}'`
|
||||||
|
: 'Checking api update note SN success',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ import {
|
||||||
updateNoteToERP,
|
updateNoteToERP,
|
||||||
} from '../ultils/helper.js'
|
} from '../ultils/helper.js'
|
||||||
import Scenario from '#models/scenario'
|
import Scenario from '#models/scenario'
|
||||||
import path from 'node:path'
|
import path, { join } from 'node:path'
|
||||||
import axios from 'axios'
|
import axios from 'axios'
|
||||||
import redis from '@adonisjs/redis/services/main'
|
import redis from '@adonisjs/redis/services/main'
|
||||||
import Line from '#models/line'
|
import Line from '#models/line'
|
||||||
|
|
@ -27,6 +27,7 @@ import { ErrorRow, TestResult } from '../ultils/types.js'
|
||||||
import momentTZ from 'moment-timezone'
|
import momentTZ from 'moment-timezone'
|
||||||
import { PhysicalPortTest } from './physical_test_service.js'
|
import { PhysicalPortTest } from './physical_test_service.js'
|
||||||
import Station from '#models/station'
|
import Station from '#models/station'
|
||||||
|
import IosLicenseController from '#controllers/ios_license_controller'
|
||||||
|
|
||||||
type Inventory = {
|
type Inventory = {
|
||||||
pid: string
|
pid: string
|
||||||
|
|
@ -126,6 +127,7 @@ export default class LineConnection {
|
||||||
private session: TestSession
|
private session: TestSession
|
||||||
public physicalTest: PhysicalPortTest
|
public physicalTest: PhysicalPortTest
|
||||||
private outputPhysicalTest: string
|
private outputPhysicalTest: string
|
||||||
|
private listDeviceIos: string[]
|
||||||
|
|
||||||
constructor(config: LineConfig, socketIO: any, handleClearLine: () => void) {
|
constructor(config: LineConfig, socketIO: any, handleClearLine: () => void) {
|
||||||
this.config = config
|
this.config = config
|
||||||
|
|
@ -153,6 +155,7 @@ export default class LineConnection {
|
||||||
this.handleClearLine = handleClearLine
|
this.handleClearLine = handleClearLine
|
||||||
this.physicalTest = new PhysicalPortTest([])
|
this.physicalTest = new PhysicalPortTest([])
|
||||||
this.outputPhysicalTest = ''
|
this.outputPhysicalTest = ''
|
||||||
|
this.listDeviceIos = []
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(timeoutMs = 5000) {
|
connect(timeoutMs = 5000) {
|
||||||
|
|
@ -922,10 +925,10 @@ export default class LineConnection {
|
||||||
</td>
|
</td>
|
||||||
<td style="padding:6px; text-align:center;">${r.rule}</td>
|
<td style="padding:6px; text-align:center;">${r.rule}</td>
|
||||||
<td style="padding:6px; text-align:center;">${r.message}</td>
|
<td style="padding:6px; text-align:center;">${r.message}</td>
|
||||||
<td style="padding:6px; font-family:monospace;">
|
<td style="padding:6px; font-family:monospace;">*${escapeHtml(r.log.trim())
|
||||||
<div style="white-space: break-spaces;"><span style="color: black;">
|
.split('*')
|
||||||
${escapeHtml(r.log.trim())}</span></div>
|
.filter((el) => el)
|
||||||
</td>
|
.join('<br/>*')}</td>
|
||||||
</tr>
|
</tr>
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
@ -939,26 +942,10 @@ export default class LineConnection {
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
renderAIDetectTable(row: any): string {
|
|
||||||
return `
|
|
||||||
<table border="1" cellpadding="6" style="border-collapse: collapse; width:100%; margin-bottom: 15px;">
|
|
||||||
<tr>
|
|
||||||
<th style="padding:6px;">Summary</th>
|
|
||||||
<th style="padding:6px;">Issues</th>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td style="text-wrap: wrap;">${row.summary || ''}</td>
|
|
||||||
<td style="width:1000px; text-wrap: wrap;">${row.issues?.length ? `- ` + row.issues.join(`<br>- `) : '- No issues detected.'}</td>
|
|
||||||
</tr>
|
|
||||||
</table>
|
|
||||||
`
|
|
||||||
}
|
|
||||||
|
|
||||||
buildEmailContent(result: TestResult): string {
|
buildEmailContent(result: TestResult): string {
|
||||||
const rows = mapErrorsToRows(result.errors)
|
const rows = mapErrorsToRows(result.errors)
|
||||||
const table = this.renderErrorTable(rows)
|
const table = this.renderErrorTable(rows)
|
||||||
// const tableAI = this.renderAIDetectTable(value)
|
console.log(table)
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<h3>Cisco Device Log Result</h3>
|
<h3>Cisco Device Log Result</h3>
|
||||||
<p>Line: <b>${this.config.lineNumber}</b> - Station: <b>${this.config.stationName}</b></p>
|
<p>Line: <b>${this.config.lineNumber}</b> - Station: <b>${this.config.stationName}</b></p>
|
||||||
|
|
@ -1034,7 +1021,7 @@ export default class LineConnection {
|
||||||
async getPorts(): Promise<string[]> {
|
async getPorts(): Promise<string[]> {
|
||||||
this.writeCommand(' show power inline\r\n')
|
this.writeCommand(' show power inline\r\n')
|
||||||
this.writeCommand(' \r\n')
|
this.writeCommand(' \r\n')
|
||||||
await this.sleep(3000)
|
await this.sleep(5000)
|
||||||
const statusOutput = this.outputPhysicalTest
|
const statusOutput = this.outputPhysicalTest
|
||||||
this.outputPhysicalTest = ''
|
this.outputPhysicalTest = ''
|
||||||
|
|
||||||
|
|
@ -1107,14 +1094,14 @@ export default class LineConnection {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expect: 'rommon',
|
expect: 'rommon',
|
||||||
send: `tftpdnld`,
|
send: this.listDeviceIos?.includes(nameIos) ? '' : `tftpdnld`,
|
||||||
delay: '1',
|
delay: '1',
|
||||||
repeat: '1',
|
repeat: '1',
|
||||||
note: '',
|
note: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expect: 'y/n',
|
expect: this.listDeviceIos?.includes(nameIos) ? '' : 'y/n',
|
||||||
send: `y`,
|
send: this.listDeviceIos?.includes(nameIos) ? '' : `y`,
|
||||||
delay: '2',
|
delay: '2',
|
||||||
repeat: '1',
|
repeat: '1',
|
||||||
note: '',
|
note: '',
|
||||||
|
|
@ -1200,9 +1187,10 @@ export default class LineConnection {
|
||||||
timeout: 1000,
|
timeout: 1000,
|
||||||
body: JSON.stringify(body),
|
body: JSON.stringify(body),
|
||||||
}
|
}
|
||||||
|
|
||||||
await sleep(5000)
|
await sleep(5000)
|
||||||
await this.runScript(script as any, userName)
|
await this.runScript(script as any, userName)
|
||||||
await this.endEmailLoadIos(nameIos, startTime)
|
await this.sendEmailLoadIos(nameIos, startTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadIosSwitch(nameIos: string, userName: string) {
|
async loadIosSwitch(nameIos: string, userName: string) {
|
||||||
|
|
@ -1213,6 +1201,8 @@ export default class LineConnection {
|
||||||
const [a, b] = network.split('.').map(Number)
|
const [a, b] = network.split('.').map(Number)
|
||||||
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
||||||
const startTime = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
const startTime = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||||
|
await this.backupIos(nameIos)
|
||||||
|
|
||||||
const body = [
|
const body = [
|
||||||
{
|
{
|
||||||
expect: '',
|
expect: '',
|
||||||
|
|
@ -1286,21 +1276,21 @@ export default class LineConnection {
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expect: '#',
|
expect: '#',
|
||||||
send: `copy tftp: flash:`,
|
send: this.listDeviceIos?.includes(nameIos) ? '' : `copy tftp: flash:`,
|
||||||
delay: '1',
|
delay: '1',
|
||||||
repeat: '1',
|
repeat: '1',
|
||||||
note: '',
|
note: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expect: '',
|
expect: '',
|
||||||
send: `${tftpIp}`,
|
send: this.listDeviceIos?.includes(nameIos) ? '' : `${tftpIp}`,
|
||||||
delay: '1',
|
delay: '1',
|
||||||
repeat: '1',
|
repeat: '1',
|
||||||
note: '',
|
note: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
expect: '',
|
expect: '',
|
||||||
send: `ios/${nameIos}`,
|
send: this.listDeviceIos?.includes(nameIos) ? '' : `ios/${nameIos}`,
|
||||||
delay: '1',
|
delay: '1',
|
||||||
repeat: '1',
|
repeat: '1',
|
||||||
note: '',
|
note: '',
|
||||||
|
|
@ -1409,10 +1399,10 @@ export default class LineConnection {
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.runScript(script as any, userName)
|
await this.runScript(script as any, userName)
|
||||||
await this.endEmailLoadIos(nameIos, startTime)
|
await this.sendEmailLoadIos(nameIos, startTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
async endEmailLoadIos(nameIos: string, startTime: string) {
|
async sendEmailLoadIos(nameIos: string, startTime: string) {
|
||||||
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
const timeZone = process.env.TIME_ZONE || 'Australia/Sydney'
|
||||||
const dataFormat = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
const dataFormat = momentTZ().tz(timeZone).format('YYYY/MM/DD, HH:mm:ss')
|
||||||
const body = `
|
const body = `
|
||||||
|
|
@ -1431,4 +1421,100 @@ export default class LineConnection {
|
||||||
body
|
body
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async checkDeviceFlash() {
|
||||||
|
this.writeCommand(' enable\r\n')
|
||||||
|
this.writeCommand('show flash:\r\n')
|
||||||
|
await sleep(2000)
|
||||||
|
const ios = []
|
||||||
|
const binRegex = /^\s*\d+\s+-rwx\s+\d+\s+.*?\s+([^\s]+\.bin)\s*$/gim
|
||||||
|
|
||||||
|
let match
|
||||||
|
while ((match = binRegex.exec(this.outputBuffer)) !== null) {
|
||||||
|
ios.push(match[1])
|
||||||
|
}
|
||||||
|
return ios
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteFileOnFlash(fileName: string) {
|
||||||
|
await this.writeCommand(`delete flash:${fileName}\r\n`)
|
||||||
|
await this.writeCommand(`\r\n`)
|
||||||
|
await this.writeCommand(`\r\n`)
|
||||||
|
await sleep(3000)
|
||||||
|
}
|
||||||
|
|
||||||
|
async uploadFileToServerTFTP(fileName: string, server: string) {
|
||||||
|
this.config.runningScenario = 'Upload file'
|
||||||
|
await this.writeCommand(`copy flash: tftp:\r\n`)
|
||||||
|
await this.writeCommand(`${fileName}\r\n`)
|
||||||
|
await this.writeCommand(`${server}\r\n`)
|
||||||
|
await this.writeCommand(`ios/${fileName}\r\n`)
|
||||||
|
await sleep(5000)
|
||||||
|
while (true) {
|
||||||
|
if (this.outputBuffer.includes('#')) {
|
||||||
|
this.outputBuffer = ''
|
||||||
|
this.config.runningScenario = ''
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
await sleep(5000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// function get list ios
|
||||||
|
async getListIos() {
|
||||||
|
try {
|
||||||
|
const controller = new IosLicenseController()
|
||||||
|
const listIos = await controller.getIos()
|
||||||
|
return listIos
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Error get ios', error)
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async getCurrentBootIos() {
|
||||||
|
this.writeCommand('show version | include System image\r\n')
|
||||||
|
await sleep(2000)
|
||||||
|
|
||||||
|
const match = this.outputBuffer.match(/"flash:(.+?)"/i)
|
||||||
|
this.outputBuffer = ''
|
||||||
|
|
||||||
|
return match ? match[1] : null
|
||||||
|
}
|
||||||
|
|
||||||
|
async backupIos(nameIos: string) {
|
||||||
|
const station = await Station.find(this.config.stationId)
|
||||||
|
if (!station) return
|
||||||
|
const server = station?.tftp_ip || '172.16.7.69'
|
||||||
|
// const currentBootIos = await this.getCurrentBootIos()
|
||||||
|
this.config.runningScenario = 'Backup IOS'
|
||||||
|
this.socketIO.emit('running_scenario', {
|
||||||
|
stationId: this.config.stationId,
|
||||||
|
lineId: this.config.id,
|
||||||
|
title: 'Backup IOS',
|
||||||
|
})
|
||||||
|
await sleep(1000)
|
||||||
|
const listIos = await this.getListIos()
|
||||||
|
const dataDevice = await this.checkDeviceFlash()
|
||||||
|
this.listDeviceIos = [...dataDevice]
|
||||||
|
console.log('Data Device Flash', dataDevice)
|
||||||
|
if (dataDevice && Array.isArray(dataDevice)) {
|
||||||
|
for (const ios of dataDevice) {
|
||||||
|
// if (ios === nameIos) {
|
||||||
|
// console.log(`SKIP active IOS: ${ios}`)
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
if (listIos?.includes(ios)) {
|
||||||
|
console.log(`Already backed up: ${ios}`)
|
||||||
|
if (ios !== nameIos) await this.deleteFileOnFlash(ios)
|
||||||
|
} else {
|
||||||
|
const ok = await this.uploadFileToServerTFTP(ios, server)
|
||||||
|
if (ok && ios !== nameIos) await this.deleteFileOnFlash(ios)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
this.outputBuffer = ''
|
||||||
|
this.config.runningScenario = ''
|
||||||
|
await sleep(1000)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,11 @@
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
import { normalizeInterface } from '../ultils/helper.js'
|
import { normalizeInterface } from '../ultils/helper.js'
|
||||||
import { PhysicalTestReport, PhysicalTestResult, PortState } from '../ultils/types.js'
|
import { PhysicalTestReport, PhysicalTestResult, PortState } from '../ultils/types.js'
|
||||||
const LINK_UPDOWN_REGEX =
|
const LINK_REGEX =
|
||||||
/Interface\s+((?:FastEthernet|GigabitEthernet|TenGigabitEthernet|TwentyFiveGigE|FortyGigabitEthernet|HundredGigE|Ethernet|Port-channel|Fa|Gi|Te|Hu|Eth)[\w\/.-]+),\s+changed state to\s+(up|down)/i
|
/Interface\s+((?:FastEthernet|GigabitEthernet|TenGigabitEthernet|TwentyFiveGigE|FortyGigabitEthernet|HundredGigE|Ethernet|Port-channel|Fa|Gi|Te|Hu|Eth)[\w\/.-]+),\s+changed state to\s+(up|down)/i
|
||||||
|
const POE_GRANTED_REGEX = /%ILPOWER-\d+-POWER_GRANTED:\s+Interface\s+([\w\/.-]+):\s+Power granted/i
|
||||||
|
const POE_DISCONNECT_REGEX =
|
||||||
|
/%ILPOWER-\d+-IEEE_DISCONNECT:\s+Interface\s+([\w\/.-]+):\s+PD removed/i
|
||||||
|
|
||||||
export class PhysicalPortTest {
|
export class PhysicalPortTest {
|
||||||
public ports = new Map<string, PortState>()
|
public ports = new Map<string, PortState>()
|
||||||
|
|
@ -44,24 +47,44 @@ export class PhysicalPortTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
handleLog(line: string) {
|
handleLog(line: string) {
|
||||||
const match = line.match(LINK_UPDOWN_REGEX)
|
let iface: string | null = null
|
||||||
if (!match) return
|
let markTested = false
|
||||||
|
let state: 'up' | 'down' | undefined
|
||||||
|
|
||||||
const rawIface = match[1]
|
// 1️⃣ LINK / LINEPROTO
|
||||||
const state = match[2] as 'up' | 'down'
|
let match = line.match(LINK_REGEX)
|
||||||
const iface = normalizeInterface(rawIface)
|
if (match) {
|
||||||
|
iface = normalizeInterface(match[1])
|
||||||
|
state = match[2] as 'up' | 'down'
|
||||||
|
if (state === 'up') markTested = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2️⃣ POE POWER GRANTED
|
||||||
|
match = line.match(POE_GRANTED_REGEX)
|
||||||
|
if (match) {
|
||||||
|
iface = normalizeInterface(match[1])
|
||||||
|
markTested = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3️⃣ POE DISCONNECT
|
||||||
|
match = line.match(POE_DISCONNECT_REGEX)
|
||||||
|
if (match) {
|
||||||
|
iface = normalizeInterface(match[1])
|
||||||
|
markTested = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iface) return
|
||||||
|
|
||||||
const port = this.ports.get(iface)
|
const port = this.ports.get(iface)
|
||||||
if (!port) return
|
if (!port) return
|
||||||
|
|
||||||
// tránh update trùng state liên tiếp
|
|
||||||
if (port.lastState === state) return
|
|
||||||
|
|
||||||
port.lastState = state
|
|
||||||
port.lastSeen = new Date()
|
port.lastSeen = new Date()
|
||||||
|
|
||||||
// chỉ cần UP 1 lần là pass
|
if (state && port.lastState === state) return
|
||||||
if (state === 'up' && !port.tested) {
|
if (state) port.lastState = state
|
||||||
|
|
||||||
|
// ⭐ PASS nếu có ít nhất 1 event hợp lệ
|
||||||
|
if (markTested && !port.tested) {
|
||||||
port.tested = true
|
port.tested = true
|
||||||
this.checkDone()
|
this.checkDone()
|
||||||
}
|
}
|
||||||
|
|
@ -141,7 +164,7 @@ export class PhysicalPortTest {
|
||||||
Serial Number : <b>${report.device.serial ?? 'N/A'}</b><br/>
|
Serial Number : <b>${report.device.serial ?? 'N/A'}</b><br/>
|
||||||
Started At : ${moment(report.startTime).format('YYYY/MM/DD, HH:mm:ss')}<br/>
|
Started At : ${moment(report.startTime).format('YYYY/MM/DD, HH:mm:ss')}<br/>
|
||||||
Finished At : ${moment(report.endTime).format('YYYY/MM/DD, HH:mm:ss')}<br/>
|
Finished At : ${moment(report.endTime).format('YYYY/MM/DD, HH:mm:ss')}<br/>
|
||||||
Duration : ${Math.floor(report.durationMs / 1000)} sec<br/>
|
Duration : ${this.formatDuration(report.durationMs)}<br/>
|
||||||
Status : ${status === 'PASS' ? '✅ PASS' : '⚠️ WARNING'}<br/>
|
Status : ${status === 'PASS' ? '✅ PASS' : '⚠️ WARNING'}<br/>
|
||||||
<br/>
|
<br/>
|
||||||
────────────────────────────────<br/>
|
────────────────────────────────<br/>
|
||||||
|
|
@ -169,4 +192,12 @@ export class PhysicalPortTest {
|
||||||
<br/>
|
<br/>
|
||||||
`.trim()
|
`.trim()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
formatDuration(ms: number): string {
|
||||||
|
const totalSeconds = Math.floor(ms / 1000)
|
||||||
|
const minutes = Math.floor(totalSeconds / 60)
|
||||||
|
const seconds = totalSeconds % 60
|
||||||
|
|
||||||
|
return `${minutes}m ${seconds}s`
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,8 +8,8 @@ import axios from 'axios'
|
||||||
import moment from 'moment'
|
import moment from 'moment'
|
||||||
|
|
||||||
const mailTo = 'andrew.ng@apactech.io'
|
const mailTo = 'andrew.ng@apactech.io'
|
||||||
const mailCC = ['ips@ipsupply.com.au', 'kay@ipsupply.com.au', 'joseph@apactech.io']
|
// const mailCC = ['ips@ipsupply.com.au', 'kay@ipsupply.com.au', 'joseph@apactech.io']
|
||||||
// const mailCC = ''
|
const mailCC = ''
|
||||||
|
|
||||||
type DetectAI = {
|
type DetectAI = {
|
||||||
status: string[]
|
status: string[]
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,8 @@ export interface PortState {
|
||||||
tested: boolean
|
tested: boolean
|
||||||
lastState?: 'up' | 'down'
|
lastState?: 'up' | 'down'
|
||||||
lastSeen?: Date
|
lastSeen?: Date
|
||||||
|
poeGranted?: boolean
|
||||||
|
poeDisconnected?: boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface PhysicalTestResult {
|
export interface PhysicalTestResult {
|
||||||
|
|
|
||||||
|
|
@ -663,13 +663,31 @@ export class WebSocketIo {
|
||||||
})
|
})
|
||||||
|
|
||||||
socket.on('load_ios_router', async (data) => {
|
socket.on('load_ios_router', async (data) => {
|
||||||
const { stationId, lineId, iosName } = data
|
const { stationId, lineId, iosName, outletNumber, station, apcName, isReboot } = data
|
||||||
await this.handleLineOperation(
|
await this.handleLineOperation(
|
||||||
io,
|
io,
|
||||||
stationId,
|
stationId,
|
||||||
[lineId],
|
[lineId],
|
||||||
async (lineCon) => {
|
async (lineCon) => {
|
||||||
lineCon.loadIosRouter(iosName, userName)
|
await lineCon.backupIos(iosName)
|
||||||
|
if (isReboot) {
|
||||||
|
if (!outletNumber || outletNumber < 0) return
|
||||||
|
if (!station) return
|
||||||
|
const apcIp = (station as any)[`${apcName}_ip`] as string
|
||||||
|
if (!this.apcsControl.get(apcIp)) await this.connectApc(io, apcName, station)
|
||||||
|
const apc = this.apcsControl.get(apcIp)
|
||||||
|
if (apc && apc.status !== 'CONNECTED') {
|
||||||
|
await apc.reconnect()
|
||||||
|
this.keepConnectAPC(apcIp, io)
|
||||||
|
}
|
||||||
|
if (apc) {
|
||||||
|
await apc?.restartOutlet(outletNumber)
|
||||||
|
setTimeout(() => {
|
||||||
|
apc?.navigateToOutlets()
|
||||||
|
}, 10000)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await lineCon.loadIosRouter(iosName, userName)
|
||||||
},
|
},
|
||||||
{}
|
{}
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -153,18 +153,16 @@ const ModalSelectIOS = ({
|
||||||
size="sm"
|
size="sm"
|
||||||
leftSection={<IconPlayerPlay size={16} />}
|
leftSection={<IconPlayerPlay size={16} />}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (isReboot)
|
const payload = {
|
||||||
socket?.emit("control_apc", {
|
|
||||||
outletNumbers: [line?.outlet],
|
|
||||||
station: { ...station, lines: [] },
|
|
||||||
action: "restart",
|
|
||||||
apcName: line?.apc_name || line?.apcName,
|
|
||||||
});
|
|
||||||
socket?.emit("load_ios_router", {
|
|
||||||
stationId: Number(station?.id),
|
stationId: Number(station?.id),
|
||||||
lineId: Number(line?.id),
|
lineId: Number(line?.id),
|
||||||
iosName: ios,
|
iosName: ios,
|
||||||
});
|
station: station,
|
||||||
|
outletNumber: line?.outlet || -1,
|
||||||
|
apcName: line?.apcName || line?.apc_name,
|
||||||
|
isReboot: isReboot,
|
||||||
|
};
|
||||||
|
socket?.emit("load_ios_router", payload);
|
||||||
close();
|
close();
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -1032,7 +1032,7 @@ const ModalTerminal = ({
|
||||||
setIsDisable(true);
|
setIsDisable(true);
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setIsDisable(false);
|
setIsDisable(false);
|
||||||
}, 4000);
|
}, 10000);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Start Physical Test
|
Start Physical Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue