-- -- EEEEEEEEEE GGGGGG TTTTTTTTTTTTTT -- EEEEEEEEEE GGGGGGGGGG TTTTTTTTTTTTTT -- EEEE GGGG GGGG TTTT -- EEEE GGGG TTTT -- EEEEEEE GGGG GGGGGGG TTTT -- EEEEEEE GGGG GGGGGGG TTTT -- EEEE GGGG GGGG TTTT -- EEEE GGGG GGGG TTTT -- EEEEEEEEEE GGGGGGGGGG TTTT -- EEEEEEEEEE GGGGGG TTTT -- -- BeamRESTPipe by Egalware s.r.l. 2025/12/02 -- Questo script gestisce le richieste REST che arrivano da LUX per le travi require( 'EgtBase') _ENV = EgtProtectGlobal() EgtEnableDebug( false) -- modalita' di chiamata QUESTION_MODES = { NULL = 0, PREVIEW = 1, BOM = 2, HARDWARE = 3, CONFIG = 4, ORDER = 5, VERIFY = 6, } QUESTION_ORDER_SUBMODES = { NULL = 0, CREATE = 1, ESTIMATE = 2, CONFIRM = 3, } PART_VERIFICATION_RESULTS = { CALCULATIONFAILED = -1, NOTMACHINABLE = 0, MACHINABLE = 1, } _G.package.loaded.JSON = nil local JSON = require( 'JSON') local sIniFilePath = EgtGetIniFile() local sScriptDir = EgtGetStringFromIni( 'Lux', 'ScriptDir', '', sIniFilePath) EgtAddToPackagePath( sScriptDir .. '\\?.lua') local sBaseDir = EgtGetStringFromIni( 'Beam', 'BaseDir', '', sIniFilePath) EgtAddToPackagePath( sBaseDir .. '\\?.lua') _G.package.loaded.BeamWallPipeLib = nil local BeamWallPipeLib = require( 'BeamWallPipeLib') -- Connessiona a Redis local bRedisConnect, nRedisConnectionId = EgtRedisAsyncConnect( ENG.Param2) if bRedisConnect then EgtOutLog('Connessione con il server Redis dal Lua effettuata con successo con Id=' .. nRedisConnectionId .. '!') else nRedisConnectionId = 0 EgtOutLog('Errore! Impossibile connettersi con il server Redis dal Lua!') end local function Create_Order( QuestionArgs) -- leggo argomenti passati local sFile = QuestionArgs["FileName"] local sBtl = QuestionArgs["SerializedData"] local sOrderUID = QuestionArgs["OrderUID"] local sUID = QuestionArgs["UID"] local sTagList = QuestionArgs["TagsList"] if sFile and #sFile > 0 then if sBtl and #sBtl > 0 then if sOrderUID and #sOrderUID > 0 then if sUID and #sUID > 0 then if sTagList and #sTagList > 0 then -- scrivo testo su file local sDataDir = EgtGetStringFromIni( 'Lux', 'DataDir', '', sIniFilePath) -- creo cartella ordine local sBtlFilePath = sDataDir .. '\\Beam\\' .. sOrderUID if not EgtExistsDirectory( sBtlFilePath) then if not EgtCreateDirectory( sBtlFilePath) then local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sBtlFilePath .. ' per il progetto ' .. sOrderUID .. '!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end end -- creo cartella riga d'ordine sBtlFilePath = sDataDir .. '\\Beam\\' .. sOrderUID .. '\\' .. sUID if EgtExistsDirectory( sBtlFilePath) then if not EgtEmptyDirectory( sBtlFilePath) then local sErrorMsg = 'Errore! Impossibile svuotare cartella ' .. sBtlFilePath .. ' per il progetto ' .. sOrderUID .. '!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end else if not EgtCreateDirectory( sBtlFilePath) then local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sBtlFilePath .. ' per il progetto ' .. sOrderUID .. '!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end end _, _, sExt = EgtSplitPath( sFile) sBtlFilePath = sBtlFilePath .. '\\' .. sUID .. sExt -- Apro file Input in scrittura local fhBtl = io.open( sBtlFilePath, 'w') if not fhBtl then local sErrorMsg = 'Errore! Apertura file ' .. sBtlFilePath .. ' per scrittura btl non riuscita!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end -- Scrittura nuova linea fhBtl:write( sBtl .. '\n') -- Chiudo file fhBtl:close() -- verifico tipo di file local bOk = false if string.lower( sExt) == '.btl' then bOk = EgtImportBtl( sBtlFilePath) elseif string.lower( sExt) == '.btlx' then bOk = EgtImportBtlx( sBtlFilePath) else local sErrorMsg = 'Errore! Estensione file non riconosciuta!' EgtOutLog(sErrorMsg) os.remove(sBtlFilePath) return 0, { Error = sErrorMsg} end if not bOk then local sErrorMsg = 'Errore! Importazione file non riuscita!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end -- assegno etichette ai pezzi local TagList = EgtSplitString( sTagList, ',') local nPartId = EgtGetFirstPart() local nTagIndex = 1 while nPartId do local nCnt = EgtGetInfo( nPartId, "CNT", 'i') local sPartTagList = '' for nCntIndex = 1, nCnt do sPartTagList = sPartTagList .. TagList[nTagIndex] .. EgtIf( nCntIndex < nCnt, ',', '') nTagIndex = nTagIndex + 1 end EgtSetInfo( nPartId, 'LuxTagList', sPartTagList) nPartId = EgtGetNextPart( nPartId) end local sNgeFilePath = sDataDir .. '\\Beam\\' .. sOrderUID .. '\\' .. sUID .. '\\' .. sUID .. '.nge' EgtSaveFile( sNgeFilePath, GDB_NT.CMPTXT) -- do risultato return 1, {} else local sErrorMsg = 'Errore! Lista etichette vuota!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end else local sErrorMsg = 'Errore! UID vuoto!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end else local sErrorMsg = 'Errore! Nome ordine vuoto!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end else local sErrorMsg = 'Errore! Btl file vuoto!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end else local sErrorMsg = 'Errore! Nome file vuoto!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end end local function Calc_Estimate( QuestionArgs) -- leggo argomenti passati local sOrderUID = QuestionArgs["OrderUID"] local sUID = QuestionArgs["UID"] if sOrderUID and #sOrderUID > 0 then if sUID and #sUID > 0 then -- apro progetto local sDataDir = EgtGetStringFromIni( 'Lux', 'DataDir', '', sIniFilePath) local sOrderDirPath = sDataDir .. '\\Beam\\' .. sOrderUID .. '\\' .. sUID if not EgtExistsDirectory( sOrderDirPath) then local sErrorMsg = 'Errore! Cartella della riga d\'ordine non trovata!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end local sNgeFilePath = sOrderDirPath .. '\\' .. sUID .. '.nge' if not EgtOpenFile( sNgeFilePath) then local sErrorMsg = 'Errore! Fallita apertura del file!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end -- recupero cartella macchine local MachineDirPath = EgtGetStringFromIni( 'Mach', 'MachinesDir', '', sIniFilePath) if not MachineDirPath or #MachineDirPath <=0 then local sErrorMsg = 'Errore! Cartella delle macchine non impostata!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end --local MachinesDir = EgtFindAllFiles( MachineDirPath .. '\\*.*') local MachinesDir = { MachineDirPath .. '\\Saomad-Kairos', MachineDirPath .. '\\Essetre-FAST', MachineDirPath .. '\\Essetre-PF1250MAX' } --local MachinesDir = { MachineDirPath .. '\\Essetre-FAST'} local BeamMachineList = {} local AnswerChannelList = {} for nMachineIndex = 1, #MachinesDir do local _, sMachineName, _ = EgtSplitPath( MachinesDir[nMachineIndex]) local sMaterial = EgtGetStringFromIni( 'General', 'Material', '', MachineDirPath .. '\\' .. sMachineName .. '\\' .. sMachineName .. '.ini') if sMaterial == 'Beam' then local sMachineOrderDirPath = sOrderDirPath .. '\\' .. sMachineName -- creo cartella per macchina if EgtExistsDirectory( sMachineOrderDirPath) then if not EgtEmptyDirectory( sMachineOrderDirPath) then local sErrorMsg = 'Errore! Impossibile svuotare cartella ' .. sMachineOrderDirPath .. ' per il progetto ' .. sOrderUID .. '!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end else if not EgtCreateDirectory( sMachineOrderDirPath) then local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sMachineOrderDirPath .. ' per il progetto ' .. sOrderUID .. '!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end end local sMachineNgeFilePath = sMachineOrderDirPath .. '\\' .. sUID .. '.nge' -- e copio file nge if not EgtCopyFile( sNgeFilePath, sMachineNgeFilePath) then local sErrorMsg = 'Errore! Copia del file nge per macchina ' .. sMachineName .. ' e progetto ' .. sUID .. ' fallita!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end if not EgtOpenFile( sMachineNgeFilePath) then local sErrorMsg = 'Errore! Fallita apertura del file per macchina ' .. sMachineName .. '!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end -- creo i singoli bwe e li mando da eseguire via redis local nPartId = EgtGetFirstPart() local AnswerArgs = {} local TagTimeList = {} local dTotTime = 0 local nNotMachinedPart = 0 while nPartId do local BarPath = sMachineOrderDirPath local ProjType = BWTYPES.BEAM local GlobState = CALCSTATES.NOTCALCULATED local bResult, AnswerChannel = BeamWallPipeLib.AsyncVerifyBtlPartCalc( nPartId, BarPath, ProjType, sMachineName, GlobState) if bResult then table.insert( AnswerChannelList, { Channel = AnswerChannel, PartId = nPartId, Machine = sMachineName}) else local sErrorMsg = 'Errore! Tentativo di verifica del pezzo ' .. nPartId .. ' fallito!' EgtOutLog(sErrorMsg) end nPartId = EgtGetNextPart( nPartId) end table.insert( BeamMachineList, { Name = sMachineName, PartList = { }}) end end local nTimeCount = 0 local nTimeClock = 100 while nTimeCount < 1200 and #AnswerChannelList > 0 do local RemoveAnswerList = {} for nAnswerIndex = 1, #AnswerChannelList do local AnswerChannel = AnswerChannelList[nAnswerIndex] -- verifico se ci sono i risultati e aspetto che arrivino tutti local bOk, bAnswerReceived, PartAnswerArgs = BeamWallPipeLib.AsyncVerifyBtlPartResult( AnswerChannel.Channel) if bOk then if bAnswerReceived then if PartAnswerArgs then local sTagList = EgtGetInfo( AnswerChannel.PartId, 'LuxTagList') local TagList = EgtSplitString( sTagList, ',') local CalcResult CalcResult = EgtIf( tonumber( PartAnswerArgs.MachiningOk) == 1, PART_VERIFICATION_RESULTS.MACHINABLE, PART_VERIFICATION_RESULTS.NOTMACHINABLE) local BeamMachine = '' for nMachineIndex = 1, #BeamMachineList do if BeamMachineList[nMachineIndex].Name == AnswerChannel.Machine then BeamMachine = BeamMachineList[nMachineIndex] end end for nTagIndex = 1, #TagList do table.insert( BeamMachine.PartList, { Tag = TagList[nTagIndex], CalcResult = CalcResult, Time = ( PartAnswerArgs.Time or 0)}) end table.insert( RemoveAnswerList, nAnswerIndex) else local sErrorMsg = 'Errore! Tentativo di verifica del pezzo sul canale' .. AnswerChannel.Channel .. ' fallito!' EgtOutLog(sErrorMsg) end end elseif bOk then local sErrorMsg = 'Errore! Funzione di lettura risultato sul canale ' .. AnswerChannel.Channel .. ' fallita!' EgtOutLog(sErrorMsg) end end for nRemoveAnswerCount = #RemoveAnswerList, 1, -1 do table.remove( AnswerChannelList, RemoveAnswerList[nRemoveAnswerCount]) end EgtPause( nTimeClock, true) nTimeCount = nTimeCount + 1 end if #AnswerChannelList > 0 then for nAnswerCount = 1, #AnswerChannelList do local sTagList = EgtGetInfo( AnswerChannelList[nAnswerCount].PartId, 'LuxTagList') local TagList = EgtSplitString( sTagList, ',') CalcResult = PART_VERIFICATION_RESULTS.CALCULATIONFAILED local sErrorMsg = 'Errore! Verifica sul pezzo ' .. AnswerChannelList[nAnswerCount].PartId .. ' fallita!' EgtOutLog(sErrorMsg) local BeamMachine for nMachineIndex = 1, #BeamMachineList do if BeamMachineList[nMachineIndex].Name == AnswerChannelList[nAnswerCount].Machine then BeamMachine = BeamMachineList[nMachineIndex] end end for nTagIndex = 1, #TagList do table.insert( BeamMachine.PartList, { Tag = TagList[nTagIndex], CalcResult = CalcResult, Time = 0}) end end end -- do risultato local JsonBeamMachineList = JSON:encode( BeamMachineList) return 1, { Estimate = JsonBeamMachineList} else local sErrorMsg = 'Errore! UID vuoto!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end else local sErrorMsg = 'Errore! OrderUID vuoto!' EgtOutLog(sErrorMsg) return 0, { Error = sErrorMsg} end end local nErr = 999 local nNilCount = 0 local bRun = true while bRun do local sReadLine = io.stdin:read( 'l') EgtOutLog( 'Letta riga da stdin') if sReadLine then if sReadLine == 'quit' then EgtOutLog( 'Chiusura processo') break end if sReadLine ~= '' and sReadLine:find( '^#8477271#') and sReadLine:find( '#8477271#$') then EgtOutLog( 'Lettura istruzione valida') sReadLine = string.sub( sReadLine, 10, #sReadLine - 9) local sSanitizedReadLine = EgtSanitizeUtf8( sReadLine) local Question = JSON:decode( sSanitizedReadLine) local nThreadIndex = -1 local nId = -1 local ExecEnvironment = -1 local nResult = 0 local AnswerArgs = {} if Question and Question.nThreadIndex and Question.nId and Question.Args then nThreadIndex = tonumber( Question["nThreadIndex"]) nId = tonumber( Question["nId"]) ExecEnvironment = tonumber( Question["ExecEnvironment"]) local QuestionArgs = Question["Args"] if QuestionArgs and QuestionArgs.Mode and QuestionArgs.UID then local sUid = QuestionArgs["UID"] local sRUID = QuestionArgs["RUID"] local nMode = tonumber( QuestionArgs["Mode"]) -- esecuzione della corretta modilita' EgtOutLog('Ricevuta richiesta calcolo: nThreadIndex=' .. nThreadIndex .. ', nId=' .. nId .. ', UID=' .. sUid .. ', nMode=' .. nMode) local Result = {} if nMode == QUESTION_MODES.ORDER then if QuestionArgs.SubMode then local nSubMode = tonumber( QuestionArgs["SubMode"]) EgtOutLog('SubMode=' .. nSubMode) if nSubMode == QUESTION_ORDER_SUBMODES.CREATE then nResult, AnswerArgs = Create_Order( QuestionArgs) elseif nSubMode == QUESTION_ORDER_SUBMODES.ESTIMATE then _G.LUX = {} LUX.REDISID = nRedisConnectionId nResult, AnswerArgs = Calc_Estimate( QuestionArgs) else nResult = 0 local sErrorMsg = 'Errore! Valore di SubMode errato!' AnswerArgs = { Error = sErrorMsg} EgtOutLog( sErrorMsg) end if AnswerArgs then AnswerArgs.Mode = nMode AnswerArgs.SubMode = nSubMode end else nResult = 0 local sErrorMsg = 'Errore! Domanda senza SubMode che é obbligatorio!' AnswerArgs = { Error = sErrorMsg} EgtOutLog( sErrorMsg) end end AnswerArgs.UID = sUid AnswerArgs.RUID = sRUID or 0 else nResult = 0 local sErrorMsg = 'Errore! Domanda senza argomenti o senza UID o Mode che sono obbligatori!' AnswerArgs = { Error = sErrorMsg} EgtOutLog( sErrorMsg) end else nResult = 0 local sErrorMsg = 'Errore! Formato domanda non riconosciuto o senza nThreadIndex, nId o Args!' AnswerArgs = { Error = sErrorMsg} EgtOutLog( sErrorMsg) end -- do risultato local Result = { nThreadIndex = nThreadIndex, nId = nId, ExecEnvironment = ExecEnvironment, nResult = nResult, Args = AnswerArgs} -- invio risposta EgtOutLog( 'Invio risposta') local JsonResult = JSON:encode( Result) io.stdout:write( "#8376261#" .. JsonResult .. "#8376261#" .. '\n') io.stdout:flush() EgtOutLog( 'Risposta inviata') EgtNewFile() end else if nNilCount >= 20 then bRun = false EgtOutLog( 'Errore! Lettura da stdin fallita!') end nNilCount = nNilCount + 1 EgtPause( 100, true) end end EgtRedisAsyncDisconnect( nRedisConnectionId)