@libs-scripts-mep/mpai
Version:
Inference MPAI client
189 lines (143 loc) • 7.11 kB
JavaScript
import Log from "../../script-loader/utils-script.js"
import FWLink from "../../daq-fwlink/FWLink.js"
export class MPAI {
static port = 8866
/**@type {WebSocket} */
static ws = new WebSocket(`ws://localhost:${this.port}`)
/**@type {{error: string; tag: string; image: string; counts: string; centers: string; classes: string; fingerprint: string} | {info: string} | {error: string} | null} */
static serverResponse = null
static async connect(url = `ws://localhost:${this.port}`) {
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
console.warn(`🟢 Serial client already connected`)
return true
}
return new Promise((resolve, reject) => {
this.ws = new WebSocket(url)
this.setCallbacks()
this.ws.onopen = () => {
console.warn(`🟢 Conectado ao servidor mpai na porta ${this.port}`)
resolve(true)
}
this.ws.onerror = (error) => {
console.warn(`Erro no WebSocket: ${error.message}`)
reject(error)
}
this.ws.onclose = () => {
console.warn(`🔴 Desconectado do servidor na porta ${this.port}`)
this.ws = null
reject(new Error('WebSocket closed'))
}
})
}
static async delay(ms) {
return new Promise((resolve) => setTimeout(resolve, ms))
}
static setCallbacks() {
if (!this.ws) return
this.ws.onopen = () => {
console.warn(`🟢 Conectado ao servidor mpai na porta ${this.port}`)
}
this.ws.onclose = () => {
console.warn(`🔴 Desconectado do servidor mpai na porta ${this.port}`)
this.ws = null // Limpar ws para permitir reconexão
}
this.ws.onerror = (error) => {
console.warn(`Erro no WebSocket: ${error.message}`)
// Não rejeitar aqui, pois a reconexão será tentada em sendRequest
}
this.ws.onmessage = (event) => {
try {
const result = JSON.parse(event.data)
MPAI.serverResponse = result
} catch (error) {
console.log(error)
}
}
}
static async infer(base64Img, tag, confidence, referencePath) {
if (MPAI.ws == null || MPAI.ws.readyState != WebSocket.OPEN) {
await MPAI.connect()
}
MPAI.serverResponse = null
// Remove o cabeçalho 'data:image/xxx;base64,' se existir
const cleanBase64 = base64Img.replace(/^data:image\/\w+;base64,/, '')
MPAI.ws.send(JSON.stringify({ image: cleanBase64, tag, confidence, reference_path: referencePath }))
while (MPAI.serverResponse == null) { await MPAI.delay(100) }
return MPAI.serverResponse
}
static async loadModel(modelPath) {
MPAI.serverResponse = null
MPAI.ws.send(JSON.stringify({ model_path: modelPath }))
while (MPAI.serverResponse == null) { await MPAI.delay(100) }
return MPAI.serverResponse
}
static async killServer() { MPAI.ws.send(JSON.stringify({ kill: true })) }
static async delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)) }
static { window.MPAI = MPAI; MPAI.connect() }
}
export class MPAIServer {
static debugMode = true
static async delay(ms) { return new Promise(resolve => setTimeout(resolve, ms)) }
static async init(depCheckerFilePath, serverFilePath) {
await MPAIServer.checkDependencies(depCheckerFilePath)
await MPAIServer.startWebsocket(serverFilePath)
await MPAI.connect()
}
static async startWebsocket(pyFilePath = MPAIServer.getScriptPath() + '/node_modules/@libs-scripts-mep/mpai/apps/mpai_server.py') {
const start = Date.now()
while (true) {
const elapsed = Date.now() - start
if (MPAI.ws?.readyState === WebSocket.OPEN) {
Log.warn(`✅ MPAI server already running on port ${MPAI.port}`, Log.Colors.Orange.Orange)
return { success: true, msg: "MPAI server already running on port " + MPAI.port }
} else if (elapsed > 1000) {
Log.warn(`⚙️ Starting MPAI server on port ${MPAI.port}`, Log.Colors.Orange.Orange)
FWLink.runInstructionS("EXEC", ["Python", pyFilePath, "true", "true"])
return Promise.race([
new Promise((resolve) => {
const id = FWLink.PVIEventObserver.add((message, params) => {
const msg = params?.[0]
if (MPAIServer.debugMode && msg.includes("[MPAI SERVER]")) { Log.warn(msg, Log.Colors.Brown.SandyBrown) }
if (msg.includes("[MPAI SERVER]") && msg?.includes("Subindo Servidor MPAI na porta")) {
FWLink.PVIEventObserver.remove(id)
resolve({ success: true, msg })
}
}, "PVI.Sniffer.sniffer.PID_")
}),
new Promise((resolve) =>
setTimeout(() => {
resolve({ success: false, msg: `❌ MPAI server failed to start on port ${MPAI.port}` })
}, 10000)
)
])
}
await MPAI.delay(100)
}
}
static getScriptPath() {
const pathC = location.pathname.slice(location.pathname.indexOf("C:/"), location.pathname.lastIndexOf("/"))
const pathI = location.pathname.slice(location.pathname.indexOf("I:/"), location.pathname.lastIndexOf("/"))
if (pathC.length > 0) {
return pathC
} else if (pathI.length > 0) {
return pathI
}
}
static async checkDependencies(pyFilePath = MPAIServer.getScriptPath() + '/node_modules/@libs-scripts-mep/mpai/core/compat.py') {
return new Promise((resolve) => {
const id = FWLink.PVIEventObserver.add((message, params) => {
const msg = params?.[0]
if (MPAIServer.debugMode && msg.includes("[MPAI DEP]")) { Log.warn(msg, Log.Colors.Brown.SandyBrown) }
if (msg.includes("[MPAI DEP]") && msg.includes("Package version check and update completed.")) {
FWLink.PVIEventObserver.remove(id)
Log.console("MPAI: Dependências instaladas com sucesso.", Log.Colors.Green.SpringGreen)
resolve({ success: true, msg: msg, })
}
}, "PVI.Sniffer.sniffer.PID_")
setTimeout(() => {
FWLink.runInstructionS("EXEC", ["Python", pyFilePath, "true", "true"])
}, 300)
})
}
static { window.MPAIServer = MPAIServer }
}