Files
egwwindowlua/CAMAuto/BatchProcessWin.lua
T
andrea.villa e623f2d789 Nuova versione BatchProcess:
- gestione WIN.FLAG ( per ora valori ammessi 0, 1 e 2)
- Cancellato funzioni non più utilizzate
- Aggiunta nuove funzioni scrittura file di log
- Aggiunta stima tempi
2026-02-19 09:33:25 +01:00

422 lines
15 KiB
Lua

-- BatchProcessNew.lua by Egalware s.r.l. 2025/04/24
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- TODO DA CANCELLARE!!!! quando verrà passato automaticamente da programma
--local WIN = {}
--WIN.BASEDIR = 'C:\\EgtData\\Window\\CAMAuto'
--WIN.FILE = 'C:\\Temp\\TestSerramenti\\4.bwe'
--WIN.MACHINE = 'Saomad-Just3500'
--WIN.FLAG = 2
-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
-- Imposto direttorio libreria specializzata per serramenti
EgtAddToPackagePath( WIN.BASEDIR .. '\\LuaLibs\\?.lua')
-- Imposto direttorio strategie. N.B. Le strategie dovranno essere caricate con il nome del direttorio padre
EgtAddToPackagePath( WIN.BASEDIR .. '\\Strategies\\?.lua')
-- carico il progetto
EgtOpenFile( WIN.FILE)
local nMachGroupId = EgtGetFirstMachGroup()
if not nMachGroupId then
EgtOutLog( 'Errore! Nessun gruppo di lavorazione presente!')
return
end
EgtSetCurrMachGroup( nMachGroupId)
-- controlli preliminari
local sMachDir = EgtGetCurrMachineDir()
local sMachine = WIN.MACHINE
EgtResetCurrMachGroup()
if not sMachDir then
WIN.ERR = 11
WIN.MSG = 'Errore nel caricamento della macchina corrente'
WriteErrToLogFile( WIN.ERR, WIN.MSG)
return
end
if not EgtExistsFile( sMachDir .. '\\Window\\WinData.lua') then
WIN.ERR = 11
WIN.MSG = 'La macchina corrente non è configurata per lavorare serramenti'
WriteErrToLogFile( WIN.ERR, WIN.MSG)
return
end
if not EgtSetCurrMachine( sMachine) then
WIN.ERR = 11
WIN.MSG = 'Error selecting machine : ' .. sMachine
WriteErrToLogFile( WIN.ERR, WIN.MSG)
return
end
local sTxtLogFile = EgtChangePathExtension( WIN.FILE, '.txt')
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Window\\?.lua')
-- Segnalazione avvio
EgtOutLog( '*** Window Process Start ***', 1)
-- Carico le librerie
_G.package.loaded.WinData = nil
_G.package.loaded.WinExec = nil
_G.package.loaded.WinLib = nil
_G.package.loaded.FeatureData = nil
_G.package.loaded.MachiningLib = nil
local WinExec = require( 'WinExec')
local WinLib = require( 'WinLib')
local JSON = require( 'JSON')
-- Carico i dati globali
local WinData = require( 'WinData')
-- Variabili globali
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
-------------------------------------------------------------------------------------------------------------
local function GetDataConfig()
-- recupero utensili dal magazzino
WinExec.GetToolsFromDB()
-- TODO da gestire eventuali errori bloccanti
return true
end
-------------------------------------------------------------------------------------------------------------
-- scrittura JSON risultati
-- TODO da migliorare/completare
local function WriteResultToJson( RESULT)
local sData = JSON:encode_pretty( RESULT)
-- Salvataggio e visualizzazione tabella
local sOutFile = EgtChangePathExtension( WIN.FILE, '.json')
local DestFh = io.open( sOutFile, 'w+')
if not DestFh then
EgtOutBox( 'Error opening ' .. sOutFile, 'TestJson', 'ERROR')
return false
end
DestFh:write( sData)
DestFh:close()
return true
end
-------------------------------------------------------------------------------------------------------------
local function WriteErrToLogFile( nErr, sMsg, nRot, idCut, idTask)
local hFile = io.open( sTxtLogFile, 'a')
hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
hFile:write( sMsg .. '\n')
hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
hFile:write( 'CUTID=' .. tostring( idCut or 0) .. '\n')
hFile:write( 'TASKID=' .. tostring( idTask or 0) .. '\n')
hFile:close()
end
local function WriteTimeToLogFile( dTime)
local hFile = io.open( sTxtLogFile, 'a')
hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
hFile:close()
end
-------------------------------------------------------------------------------------------------------------
-- *** Recupero i pezzi da processare ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessInputData()
local nId = EgtGetFirstPart()
while nId do
-- TODO caricare il file di costanti
-- si processano solo BOTTOMRAIL (WIN_PART_TYPES.BOTTOMRAIL = 2) o STANDARD (WIN_PART_TYPES.STD = 3)
if EgtGetInfo( nId, 'PART_TYPE', 'd') == 2 or EgtGetInfo( nId, 'PART_TYPE', 'd') == 3 then
table.insert( PARTS, { id = nId, sName = ( EgtGetName( nId) or ( 'Id=' .. tonumber( nId)))})
end
nId = EgtGetNext( nId)
end
if #PARTS == 0 then
EgtOutBox( 'Non ci sono pezzi', 'Lavora Pezzi', 'ERROR')
return false
else
-- recupero tutte le dimensioni necessarie
local sOut = ''
for i = 1, #PARTS do
PARTS[i].b3Raw = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'GeoRaw') or GDB_ID.NULL, GDB_BB.STANDARD)
PARTS[i].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Geo') or GDB_ID.NULL, GDB_BB.STANDARD)
local idFrame = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'GeoRaw'), 'AuxFrame')
PARTS[i].frame = EgtFR( idFrame)
sOut = sOut .. PARTS[i].sName .. ', '
end
sOut = sOut:sub( 1, -3)
EgtOutLog( 'Pezzi selezionati : ' .. sOut, 1)
end
EgtDeselectAll()
return true
end
-------------------------------------------------------------------------------------------------------------
local function GetDispOffsetFromNotes( nPieceIndex)
local bAllOffsetsAreOk = false
PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetX = 0 -- dovrà essere calcolato in base alle lavorazioni
PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetY = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFY_1', 'd')
PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetZ = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFZ_1', 'd')
PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetX = 0 -- dovrà essere calcolato in base alle lavorazioni
PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetY = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFY_2', 'd')
PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetZ = EgtGetInfo( PARTS[nPieceIndex].id, 'OFFZ_2', 'd')
-- controllo se tutti gli offset siano settati
if PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetY and PARTS[nPieceIndex].DispOffsets.Phase1.dOffsetZ and
PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetY and PARTS[nPieceIndex].DispOffsets.Phase2.dOffsetZ then
bAllOffsetsAreOk = true
end
return bAllOffsetsAreOk
end
---------------------------------------------------------------------
-- Crea il grezzo che verrà messo in macchina
---------------------------------------------------------------------
local function AddOverMaterialToRaw( PARTS)
for i = 1, #PARTS do
-- prima di aggiungere sovramateriale al grezzo, calcolo dimensioni del finito
local b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Geo') or GDB_ID.NULL, GDB_BB.STANDARD)
PARTS[i].b3Part = b3Part
PARTS[i].dPartLength = PARTS[i].b3Part:getDimX()
PARTS[i].dPartWidth = PARTS[i].b3Part:getDimY()
PARTS[i].dPartHeight = PARTS[i].b3Part:getDimZ()
-- recupero sovramateriale
PARTS[i].RawOffset = {}
-- recupero info sovramateriale
PARTS[i].RawOffset.dOverMatIn = EgtGetInfo( PARTS[i].id, 'OVERMAT_IN', 'd') or 5
PARTS[i].RawOffset.dOverMatOut = EgtGetInfo( PARTS[i].id, 'OVERMAT_OUT', 'd') or 5
PARTS[i].RawOffset.dOverMatLeft = EgtGetInfo( PARTS[i].id, 'OVERMAT_LEFT', 'd') or 5
PARTS[i].RawOffset.dOverMatRight = EgtGetInfo( PARTS[i].id, 'OVERMAT_RIGHT', 'd') or 5
PARTS[i].dRawLength = PARTS[i].RawOffset.dOverMatLeft + PARTS[i].dPartLength + PARTS[i].RawOffset.dOverMatRight
PARTS[i].dRawWidth = PARTS[i].RawOffset.dOverMatOut + PARTS[i].dPartWidth + PARTS[i].RawOffset.dOverMatIn
PARTS[i].dRawHeight = PARTS[i].dPartHeight
EgtModifyRawPartSize( PARTS[i].idRaw, PARTS[i].dRawLength, PARTS[i].dRawWidth, PARTS[i].dPartHeight)
local vtMove = Vector3d( PARTS[i].RawOffset.dOverMatLeft, PARTS[i].RawOffset.dOverMatOut, 0)
EgtMovePartInRawPart( PARTS[i].id, vtMove)
-- TODO da controllare, se ruotato di 180° bisognerebbe prendere dOverMatIn. Lo stesso per la X
PARTS[i].OffsetPartToRaw = {}
PARTS[i].OffsetPartToRaw.X = PARTS[i].RawOffset.dOverMatLeft
PARTS[i].OffsetPartToRaw.Y = PARTS[i].RawOffset.dOverMatOut
end
end
-------------------------------------------------------------------------------------------------------------
-- *** Inserimento delle travi nel grezzo ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessPieces()
-- recupero macchinata (è sempre la prima e ce n'è solo una)
local nMachGroup = EgtGetFirstMachGroup()
EgtSetCurrMachGroup( nMachGroup)
for i = 1, #PARTS do
PARTS[i].idRaw = EgtGetRawPartFromPart( PARTS[i].id)
end
-- aggiungo sovramateriale ai grezzi
AddOverMaterialToRaw( PARTS)
-- recupero offset per posizionamento
for i = 1, #PARTS do
PARTS[i].DispOffsets = {}
PARTS[i].DispOffsets.Phase1 = {}
PARTS[i].DispOffsets.Phase2 = {}
local bInsertedAllOffs = GetDispOffsetFromNotes( i)
-- se non sono stati inseriti o c'è stato un errore esco subito
if not bInsertedAllOffs then
return false
end
end
-- si dispongono i pezzi sulla tavola
local bDispOk, sErr = WinData.AdjustDisposition( PARTS)
if not bDispOk then
if not sErr then
sErr = 'Errore non gestito in WinData.AdjustDisposition'
end
EgtOutBox( sErr, 'ProcessWin', 'ERROR', 'OK')
return false
end
-- Impostazione dell'attrezzaggio di default
local bOk = EgtImportSetup()
if not bOk then
EgtImportSetup( 'Default')
end
return true
end
-------------------------------------------------------------------------------------------------------------
-- *** Esecuzione ***
-------------------------------------------------------------------------------------------------------------
-- WIN.FLAG :
-- 0 = generazione e stima, esegue solo un aggiornamento (eventuale) delle lavorazioni
-- 1 = da processare completamente, applicazione lavorazioni, simulazione, generazioen e stima
-- 2 = da processare in preverifica, applicazione lavorazioni e stima
-- In generale va completamente riprocessato
local bToProcess = true
local bToRecalc = false
local bCheckNoSim = false
-- se il progetto deve essere completamente riprocessato
if WIN.FLAG == 1 then
bToProcess = true
-- se deve essere fatta la preverifica, senza simulazione
elseif WIN.FLAG == 2 then
bToProcess = true
bCheckNoSim = true
-- altrimenti solo aggiornato (se necessario)
else
bToProcess = false
end
local sLog = 'BatchProcess : ' .. WIN.FILE .. ', ' .. ( WIN.MACHINE or EgtGetCurrMachineName()) .. ', ' .. 'FLAG='..tostring( WIN.FLAG)
EgtOutLog( sLog)
-- se bisogna processare
if bToProcess then
-- Se da elaborare
EgtOutLog( ' +++ Processing Parts >>>')
-- nascondo geometrie varie
local vAuxId = { EgtGetFirstNameInGroup( GDB_ID.ROOT, 'Profile'), EgtGetFirstNameInGroup( GDB_ID.ROOT, 'Area*'), EgtGetFirstNameInGroup( GDB_ID.ROOT, 'Aux')}
EgtSetStatus( vAuxId, GDB_ST.OFF)
if not MyProcessInputData() then return end
if not MyProcessPieces() then return end
if not GetDataConfig() then return end
-- Abilito Vmill
EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
WinExec.ProcessFeatures( PARTS)
-- Imposto Nome file CN
local _, sName, _ = EgtSplitPath( WIN.FILE)
EgtSetInfo( EgtGetCurrMachGroup(), 'NcName', sName .. '.cnc')
-- Salvo il progetto
EgtSaveFile( WIN.FILE)
-- altrimenti è solo da ricalcolare (eventualmente)
else
-- se cambiata configurazione macchina da ultima elaborazione, devo aggiornare
if EgtCompareFilesLastWriteTime( WIN.FILE, sMachDir .. '\\Tools\\Tools.data') == -1 or
EgtCompareFilesLastWriteTime( WIN.FILE, sMachDir .. '\\' .. sMachine ..'.mlde') == -1 then
bToRecalc = true
end
EgtOutLog( ' +++ Loading Project already processed >>>')
-- Passo in modalità lavora
EgtSetCurrMachGroup( EgtGetLastMachGroup())
-- Se necessario eseguo aggiornamento con setup corrente e ricalcolo delle lavorazioni
if bToRecalc then
EgtOutLog( ' +++ Recalculating all dispositions and machinings >>>')
EgtImportSetup()
EgtApplyAllMachinings()
-- Salvo il progetto
EgtSaveFile( WIN.FILE)
end
end
-- se è da riprocessare o da ricalcolare, si lancia simulazione e calcolo stima tempi
if bToProcess or bToRecalc then
-- simulazione e generazione eseguiti se non è la pre-verifica per stima tempi
if not bCheckNoSim then
-- *** Eseguo simulazione con verifica collisione in cieco ***
local bSimOk, nErr, sErr = EgtSimulate()
if not bSimOk then
if nErr == MCH_SHE.INIT then
WIN.ERR = 19
WIN.MSG = 'Error starting simulation'
elseif nErr == MCH_SHE.COLLISION then
WIN.ERR = 22
WIN.MSG = 'Head-part collision'
elseif nErr == MCH_SHE.OUTSTROKE then
WIN.ERR = 23
WIN.MSG = 'Axis outstroke ' .. sErr
elseif nErr == MCH_SHE.SPECIAL then
WIN.ERR = 24
WIN.MSG = 'Special error ' .. sErr
else
WIN.ERR = 25
WIN.MSG = 'General failure (contact supplier)'
end
WIN.ROT = 0
WIN.CUTID = 0
WIN.TASKID = 0
local vItem = EgtSplitString( sErr, ';') or {}
for i = 1, #vItem do
vItem[i] = EgtTrim( vItem[i] or '')
if string.find( vItem[i], 'CUTID', 1, true) then
WIN.CUTID = EgtGetVal( vItem[i], 'CUTID', 'i') or 0
elseif string.find( vItem[i], 'TASKID', 1, true) then
WIN.TASKID = EgtGetVal( vItem[i], 'TASKID', 'i') or 0
end
end
WriteErrToLogFile( WIN.ERR, WIN.MSG, WIN.ROT, WIN.CUTID, WIN.TASKID)
-- TODO gestire collisione su feature specifica!!!!!!!!!!!!!!!!!!!!!!!!!!!!
WinExec.AddApplyResultToGlobalList( WIN.ERR, WIN.CUTID, WIN.MSG)
WIN.RESULT = WinLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
end
end
-- *** Genero programma CN *** ( se richiesto)
local bIsGenerationEnabled = ( EgtVerifyKeyOption( 110) == false)
if bIsGenerationEnabled then
EgtOutLog( ' +++ Generating NC part program >>>')
-- TODO gestire generazione
end
-- *** Eseguo stima tempi ***
EgtOutLog( ' +++ Estimating T&L >>>')
if not EgtEstimate( '', 'EgtCAM5 - ' .. WIN.FILE) then
WIN.ERR = 21
WIN.MSG = 'Error estimating production time : ' .. WIN.FILE
WriteErrToLogFile( WIN.ERR, WIN.MSG)
WinExec.AddApplyResultToGlobalList( WIN.ERR, 0, WIN.MSG)
WIN.RESULT = WinLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
local Ttot = EgtGetInfo( EgtGetCurrMachGroup(), 'Ttot', 'd')
local sTime = 'Total Time = ' .. EgtNumToString( Ttot, 1)
EgtOutLog( sTime)
-- Scrittura tempo totale stimato di lavorazione
WriteTimeToLogFile( Ttot)
RESULT[#RESULT+1] = { dTime = Ttot, sType = 'Time'}
-- Riporto risultati in tabella globale WIN
WIN.RESULT = WinLib.TableCopyDeep( RESULT)
-- Scrittura json risultati
WriteResultToJson( RESULT)
EgtOutLog( ' +++ BatchProcess completed')