491da764ff
- verifica sulla stima fatta per sezione - aggiunta funziona CreateProduction ed abbozzo CalcProduction - anticipato subscribe a risposta verifica via Redis - aggiunta lettura dati del profilo
1294 lines
55 KiB
Lua
1294 lines
55 KiB
Lua
--
|
|
-- 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,
|
|
BALANCE = 3,
|
|
CREATE_PRODUCTION = 4,
|
|
CALC_PRODUCTION = 5,
|
|
}
|
|
|
|
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"]
|
|
if not sFile or #sFile <= 0 then
|
|
local sErrorMsg = 'Errore! Nome file vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sBtl = QuestionArgs["SerializedData"]
|
|
if not sBtl or #sBtl <= 0 then
|
|
local sErrorMsg = 'Errore! Btl file vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sOrderUID = QuestionArgs["OrderUID"]
|
|
if not sOrderUID or #sOrderUID <= 0 then
|
|
local sErrorMsg = 'Errore! Nome ordine vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sUID = QuestionArgs["UID"]
|
|
if not sUID or #sUID <= 0 then
|
|
local sErrorMsg = 'Errore! UID vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sTagList = QuestionArgs["TagList"]
|
|
if not sTagList or #sTagList <= 0 then
|
|
local sErrorMsg = 'Errore! Lista etichette vuota!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
-- 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 nImportFlag = EgtGetNumberFromIni( 'Import', 'BtlFlag', 8, sIniFilePath) -- da poi modificare per gestire anche flag pareti??
|
|
local bOk = false
|
|
if string.lower( sExt) == '.btl' then
|
|
bOk = EgtImportBtl( sBtlFilePath, nImportFlag)
|
|
elseif string.lower( sExt) == '.btlx' then
|
|
bOk = EgtImportBtlx( sBtlFilePath, nImportFlag)
|
|
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, {}
|
|
end
|
|
|
|
local function Calc_Estimate( QuestionArgs)
|
|
-- leggo argomenti passati
|
|
local sOrderUID = QuestionArgs["OrderUID"]
|
|
if not sOrderUID or #sOrderUID <= 0 then
|
|
local sErrorMsg = 'Errore! OrderUID vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sUID = QuestionArgs["UID"]
|
|
if not sUID or #sUID <= 0 then
|
|
local sErrorMsg = 'Errore! UID vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
-- recupero cartella 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
|
|
-- verifico esistenza cartella per progetti di stima
|
|
local sEstimateDirPath = sOrderDirPath .. '\\Estimate'
|
|
if EgtExistsDirectory( sEstimateDirPath) then
|
|
if not EgtEmptyDirectory( sEstimateDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile svuotare cartella ' .. sEstimateDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
else
|
|
if not EgtCreateDirectory( sEstimateDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sEstimateDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
end
|
|
-- creo cartella per progetto di stima corrente
|
|
local nCurrTime = os.time()
|
|
local sCurrEstimateDirPath = sEstimateDirPath .. '\\' .. nCurrTime
|
|
if not EgtCreateDirectory( sCurrEstimateDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sCurrEstimateDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sNgeFilePath = sOrderDirPath .. '\\' .. sUID .. '.nge'
|
|
local sEstimateNgeFilePath = sCurrEstimateDirPath .. '\\' .. sUID .. '_' .. nCurrTime .. '.nge'
|
|
if not EgtCopyFile( sNgeFilePath, sEstimateNgeFilePath) then
|
|
local sErrorMsg = 'Errore! Fallita copia del file!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
if not EgtOpenFile( sEstimateNgeFilePath) 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 .. '\\Saomad-Kairos', MachineDirPath .. '\\Essetre-FAST'}
|
|
--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 = sCurrEstimateDirPath .. '\\' .. 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( sEstimateNgeFilePath, 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.AsyncVerifyPartCalc( 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.AsyncVerifyPartResult( 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! (' .. AnswerChannelList[nAnswerCount].Channel .. ')'
|
|
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}
|
|
end
|
|
|
|
local function IsTagInPart( nPartId, TagList)
|
|
local sPartTagList = EgtGetInfo( nPartId, 'LuxTagList')
|
|
local PartTagList = EgtSplitString( sPartTagList, ',')
|
|
local nQuantity = 0
|
|
local FoundTagList = { }
|
|
for nPartTagListIndex = 1, #PartTagList do
|
|
for nTagListIndex = 1, #TagList do
|
|
if PartTagList[nPartTagListIndex] == TagList[nTagListIndex] then
|
|
nQuantity = nQuantity + 1
|
|
table.insert( FoundTagList, PartTagList[nPartTagListIndex])
|
|
end
|
|
end
|
|
end
|
|
return nQuantity > 0, nQuantity, FoundTagList
|
|
end
|
|
|
|
-- Calcola la deviazione rispetto alle percentuali desiderate
|
|
local function computeDeviation(machineLoads, percentages)
|
|
local total = 0
|
|
for _, load in ipairs(machineLoads) do
|
|
total = total + load
|
|
end
|
|
if total == 0 then
|
|
return 0
|
|
end
|
|
|
|
local dev = 0
|
|
for j, load in ipairs(machineLoads) do
|
|
local q = load / total
|
|
local p = percentages[j]
|
|
dev = dev + (q - p) * (q - p)
|
|
end
|
|
return dev
|
|
end
|
|
|
|
-- Algoritmo greedy per assegnare i pezzi alle macchine
|
|
local function assignGreedy(items, percentages)
|
|
local N = #items
|
|
local M = #items[1].MachGroupList
|
|
|
|
-- carico iniziale per macchina
|
|
local machineLoads = {}
|
|
for j = 1, M do
|
|
machineLoads[j] = 0
|
|
end
|
|
|
|
-- assegnazione: per ogni pezzo, indice della macchina scelta (1..M)
|
|
local assignment = {}
|
|
|
|
-- ORDINAMENTO INTELLIGENTE:
|
|
-- 1) prima i pezzi con meno macchine valide
|
|
-- 2) a parità, quelli più pesanti
|
|
table.sort(items, function(a, b)
|
|
local validA, validB = 0, 0
|
|
for _, m in ipairs(a.MachGroupList) do
|
|
if m.CalcResult and m.CalcResult > 0 then
|
|
validA = validA + 1
|
|
end
|
|
end
|
|
for _, m in ipairs(b.MachGroupList) do
|
|
if m.CalcResult and m.CalcResult > 0 then
|
|
validB = validB + 1
|
|
end
|
|
end
|
|
if validA ~= validB then
|
|
return validA < validB
|
|
end
|
|
local maxA, maxB = 0, 0
|
|
for _, m in ipairs(a.MachGroupList) do
|
|
if m.Time > maxA then
|
|
maxA = m.Time
|
|
end
|
|
end
|
|
for _, m in ipairs(b.MachGroupList) do
|
|
if m.Time > maxB then
|
|
maxB = m.Time
|
|
end
|
|
end
|
|
return maxA > maxB
|
|
end)
|
|
|
|
for i, item in ipairs(items) do
|
|
local bestMachine = nil
|
|
local bestDev = nil
|
|
|
|
-- prova ad assegnare il pezzo a ciascuna macchina
|
|
for j = 1, M do local mInfo = item.MachGroupList[j]
|
|
-- VINCOLO: CalcResult deve essere > 0
|
|
if mInfo.CalcResult and mInfo.CalcResult > 0 then
|
|
local time = mInfo.Time
|
|
-- prova temporaneamente
|
|
machineLoads[j] = machineLoads[j] + time
|
|
local dev = computeDeviation(machineLoads, percentages)
|
|
machineLoads[j] = machineLoads[j] - time
|
|
if bestDev == nil or dev < bestDev then
|
|
bestDev = dev
|
|
bestMachine = j
|
|
end
|
|
end
|
|
end
|
|
-- Se nessuna macchina è valida → errore
|
|
-- DA MIGLIORARE! se nessuna macchina riesce a farlo, devo rivalutare i pezzi singoli su ogni macchina e farne la somma
|
|
if not bestMachine then
|
|
local sErrorMsg = 'Errore! Nessuna macchina valida per il MachGroup ' .. tostring(item.Index) .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
bestMachine = 0
|
|
end
|
|
|
|
-- assegna definitivamente
|
|
assignment[i] = bestMachine
|
|
local chosenTime = 0
|
|
if bestMachine ~= 0 then
|
|
chosenTime = item.MachGroupList[bestMachine].Time
|
|
machineLoads[bestMachine] = machineLoads[bestMachine] + chosenTime
|
|
end
|
|
end
|
|
|
|
return assignment, machineLoads
|
|
end
|
|
|
|
local function Calc_Balance( QuestionArgs)
|
|
-- leggo argomenti passati
|
|
local sOrderUID = QuestionArgs["OrderUID"]
|
|
if not sOrderUID or #sOrderUID <= 0 then
|
|
local sErrorMsg = 'Errore! OrderUID vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sUID = QuestionArgs["UID"]
|
|
if not sUID or #sUID <= 0 then
|
|
local sErrorMsg = 'Errore! UID vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local dBarLenght = tonumber( QuestionArgs["BarLenght"])
|
|
if not dBarLenght or dBarLenght <= 0 then
|
|
local sErrorMsg = 'Errore! BarLenght vuoto o non valido! (' .. QuestionArgs["BarLenght"] .. ')'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sTagList = QuestionArgs["TagList"]
|
|
if not sTagList or #sTagList <= 0 then
|
|
local sErrorMsg = 'Errore! TagList vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sReqBalance = QuestionArgs["ReqBalance"]
|
|
if not sReqBalance or #sReqBalance <= 0 then
|
|
local sErrorMsg = 'Errore! ReqBalance vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
-- recupero cartella 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
|
|
-- verifico esistenza cartella per progetti di bilanciamento
|
|
local sBalanceDirPath = sOrderDirPath .. '\\Balance'
|
|
if EgtExistsDirectory( sBalanceDirPath) then
|
|
if not EgtEmptyDirectory( sBalanceDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile svuotare cartella ' .. sBalanceDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
else
|
|
if not EgtCreateDirectory( sBalanceDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sBalanceDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
end
|
|
-- creo cartella per progetto di bilanciamento corrente
|
|
local nCurrTime = os.time()
|
|
local sCurrBalanceDirPath = sBalanceDirPath .. '\\' .. nCurrTime
|
|
if not EgtCreateDirectory( sCurrBalanceDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sCurrBalanceDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sNgeFilePath = sOrderDirPath .. '\\' .. sUID .. '.nge'
|
|
local sBalanceNgeFilePath = sCurrBalanceDirPath .. '\\' .. sUID .. '_' .. nCurrTime .. '.nge'
|
|
if not EgtCopyFile( sNgeFilePath, sBalanceNgeFilePath) then
|
|
local sErrorMsg = 'Errore! Fallita copia del file!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
if not EgtOpenFile( sBalanceNgeFilePath) then
|
|
local sErrorMsg = 'Errore! Fallita apertura del file!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
-- recupero Id dei pezzi da nestare
|
|
local TagList = EgtSplitString( sTagList)
|
|
local nPartId = EgtGetFirstPart()
|
|
local PartIdList = {}
|
|
local SectionList = {}
|
|
local nPartCount = 0
|
|
while nPartId do
|
|
local bFound, nQuantity, _ = IsTagInPart( nPartId, TagList)
|
|
if bFound then
|
|
PartIdList[nPartId] = nQuantity
|
|
-- recupero la sezione
|
|
--local dL = EgtGetInfo( nPartId, 'L', 'd')
|
|
local dH = EgtGetInfo( nPartId, 'H', 'd')
|
|
local dW = EgtGetInfo( nPartId, 'W', 'd')
|
|
local bInSectionList = false
|
|
for nSectionIndex = 1, #SectionList do
|
|
local Section = SectionList[nSectionIndex]
|
|
if Section.H == dH and Section.W == dW then
|
|
Section.PartIdList[nPartId] = nQuantity
|
|
bInSectionList = true
|
|
break
|
|
end
|
|
end
|
|
if not bInSectionList then
|
|
table.insert( SectionList, { H = dH, W = dW, PartIdList = { [nPartId] = nQuantity}})
|
|
end
|
|
nPartCount = nPartCount + nQuantity
|
|
end
|
|
nPartId = EgtGetNextPart( nPartId)
|
|
end
|
|
local RawList = { { Len = dBarLenght, Qty = nPartCount}}
|
|
-- 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 .. '\\Saomad-Kairos', MachineDirPath .. '\\Essetre-FAST'}
|
|
--local MachinesDir = { MachineDirPath .. '\\Essetre-FAST'}
|
|
local ReqBalance = JSON:decode( sReqBalance)
|
|
if not ReqBalance or not next( ReqBalance) then
|
|
local sErrorMsg = 'Errore! Richiesto bilanciamento senza macchine!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local MachineNameList = {}
|
|
local PercentageList = {}
|
|
local nPairCount = 0
|
|
local sManualMachineName = 'Manual'
|
|
local bManualParts = false
|
|
for sMachineName, dPercentage in pairs(ReqBalance) do
|
|
if sMachineName and #sMachineName > 0 then
|
|
if sMachineName == sManualMachineName then
|
|
bManualParts = true
|
|
elseif EgtExistsDirectory( MachineDirPath .. '\\' .. sMachineName) then
|
|
table.insert( MachineNameList, sMachineName)
|
|
table.insert( PercentageList, dPercentage)
|
|
end
|
|
end
|
|
nPairCount = nPairCount + 1
|
|
end
|
|
if bManualParts and (#MachineNameList > 0 or #PercentageList > 0) then
|
|
local sErrorMsg = 'Errore! Richiesto bilanciamento tra macchine e pezzi da fare a mano!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
if not bManualParts and ( #MachineNameList == 0 or #PercentageList == 0 or #MachineNameList ~= #PercentageList or #MachineNameList ~= nPairCount) then
|
|
local sErrorMsg = 'Errore! Richiesto bilanciamento con macchine o percentuali non valide!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
if bManualParts then
|
|
local sFakeManualMachineName = 'Essetre-FAST' -- da gestire da ini file o in altro modo?
|
|
table.insert( MachineNameList, sFakeManualMachineName)
|
|
end
|
|
local StartOffset = 20
|
|
local Offset = 6
|
|
-- per ogni sezione
|
|
for nSectionIndex = 1, #SectionList do
|
|
local Section = SectionList[nSectionIndex]
|
|
-- faccio nesting dei pezzi
|
|
local sNestingLogFilePath = sCurrBalanceDirPath .. '\\' .. sUID .. '_' .. nCurrTime .. 'NestLog.txt'
|
|
local bOk, sErrorMsg = BeamWallPipeLib.NestBeam( Section.PartIdList, RawList, MachineNameList, StartOffset, Offset, sNestingLogFilePath)
|
|
if not bOk then
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
end
|
|
local MachineTagList = { }
|
|
if bManualParts then
|
|
-- recupero etichette divise per risposta
|
|
MachineTagList = { [sManualMachineName] = { TagList = { }, BarQty = 0, Time = 0}}
|
|
local nMachGroupId = EgtGetFirstMachGroup()
|
|
while nMachGroupId do
|
|
EgtSetCurrMachGroup( nMachGroupId)
|
|
local nRawPartId = EgtGetFirstRawPart()
|
|
while nRawPartId do
|
|
local nPartId = EgtGetFirstPartInRawPart( nRawPartId)
|
|
while nPartId do
|
|
local sTag = EgtGetInfo( nPartId, 'LuxTag')
|
|
--if not MachineTagList[sManualMachineName] then
|
|
-- MachineTagList[sMachineName] = { }
|
|
-- MachineTagList[sMachineName].TagList = { }
|
|
-- MachineTagList[sMachineName].BarQty = 0
|
|
-- MachineTagList[sMachineName].Time = 0
|
|
--end
|
|
table.insert( MachineTagList[sManualMachineName].TagList, sTag)
|
|
nPartId = EgtGetNextPartInRawPart( nPartId)
|
|
end
|
|
nRawPartId = EgtGetNextRawPart( nRawPartId)
|
|
end
|
|
MachineTagList['Manual'].BarQty = MachineTagList[sManualMachineName].BarQty + 1
|
|
nMachGroupId = EgtGetNextMachGroup( nMachGroupId)
|
|
end
|
|
else
|
|
-- eseguo verifica dei gruppi di lavorazione creati
|
|
-- creo i singoli bwe e li mando da eseguire via redis
|
|
local AnswerChannelList = {}
|
|
local nMachGroupId = EgtGetFirstMachGroup()
|
|
local AnswerArgs = {}
|
|
local TagTimeList = {}
|
|
local dTotTime = 0
|
|
local nNotMachinedPart = 0
|
|
local MachGroupList = {}
|
|
local NestList = {}
|
|
while nMachGroupId do
|
|
local BarPath = sCurrBalanceDirPath
|
|
local ProjType = BWTYPES.BEAM
|
|
local sMachineName = EgtGetMachGroupMachineName( nMachGroupId)
|
|
local GlobState = CALCSTATES.NOTCALCULATED
|
|
local bResult, AnswerChannel = BeamWallPipeLib.AsyncVerifyPartCalc( nMachGroupId, BarPath, ProjType, sMachineName, GlobState, true)
|
|
if bResult then
|
|
table.insert( AnswerChannelList, { Channel = AnswerChannel, PartId = nMachGroupId, Machine = sMachineName})
|
|
else
|
|
local sErrorMsg = 'Errore! Tentativo di verifica della barra ' .. nMachGroupId .. ' fallito!'
|
|
EgtOutLog(sErrorMsg)
|
|
end
|
|
local nNestIndex = EgtGetInfo( nMachGroupId, "NestIndex", 'i')
|
|
local bFound = false
|
|
for nMachGroupIndex = 1, #NestList do
|
|
local CurrNest = NestList[nMachGroupIndex]
|
|
if nNestIndex == CurrNest.NestIndex then
|
|
bFound = true
|
|
table.insert( CurrNest.MachGroupList, { PartId = nMachGroupId, Machine = sMachineName})
|
|
end
|
|
end
|
|
if not bFound then
|
|
table.insert( NestList, { NestIndex = nNestIndex, MachGroupList = { { PartId = nMachGroupId, Machine = sMachineName}}})
|
|
end
|
|
table.insert( MachGroupList, { PartId = nMachGroupId, NestIndex = nNestIndex, Machine = sMachineName})
|
|
nMachGroupId = EgtGetNextMachGroup( nMachGroupId)
|
|
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.AsyncVerifyPartResult( AnswerChannel.Channel)
|
|
if bOk then
|
|
if bAnswerReceived then
|
|
if PartAnswerArgs then
|
|
if PartAnswerArgs.Error then
|
|
local sErrorMsg = 'Errore! La verifica del pezzo ' .. AnswerChannel.PartId .. ' ha restituito un errore! (' .. PartAnswerArgs.Error .. ')'
|
|
EgtOutLog(sErrorMsg)
|
|
else
|
|
--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)
|
|
for nMachGroupIndex = 1, #MachGroupList do
|
|
local CurrMachGroup = MachGroupList[nMachGroupIndex]
|
|
if CurrMachGroup.PartId == tonumber( PartAnswerArgs.BarId) then
|
|
CurrMachGroup.CalcResult = CalcResult
|
|
CurrMachGroup.Time = ( tonumber( PartAnswerArgs.Time) or 0)
|
|
end
|
|
end
|
|
local bNestFound = false
|
|
for nNestIndex = 1, #NestList do
|
|
if not bNestFound then
|
|
for nMachGroupIndex = 1, #NestList[nNestIndex].MachGroupList do
|
|
local CurrMachGroup = NestList[nNestIndex].MachGroupList[nMachGroupIndex]
|
|
if CurrMachGroup.PartId == tonumber( PartAnswerArgs.BarId) then
|
|
CurrMachGroup.CalcResult = CalcResult
|
|
CurrMachGroup.Time = ( tonumber( PartAnswerArgs.Time) or 0)
|
|
bNestFound = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
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)
|
|
for nMachGroupIndex = 1, #MachGroupList do
|
|
local CurrMachGroup = MachGroupList[nMachGroupIndex]
|
|
if CurrMachGroup.PartId == AnswerChannelList.PartId then
|
|
CurrMachGroup.CalcResult = 0
|
|
CurrMachGroup.Time = 0
|
|
end
|
|
end
|
|
local bNestFound = false
|
|
for nNestIndex = 1, #NestList do
|
|
if not bNestFound then
|
|
for nMachGroupIndex = 1, #NestList[nNestIndex].MachGroupList do
|
|
local CurrMachGroup = NestList[nNestIndex].MachGroupList[nMachGroupIndex]
|
|
if CurrMachGroup.PartId == AnswerChannelList.PartId then
|
|
CurrMachGroup.CalcResult = 0
|
|
CurrMachGroup.Time = 0
|
|
bNestFound = true
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
-- divido le barre sulle macchine secondo le percentuali dei tempi
|
|
local assignment, loads = assignGreedy(NestList, PercentageList)
|
|
-- recupero etichette divise per risposta
|
|
for nAssignmentIndex = 1, #assignment do
|
|
if assignment[nAssignmentIndex] == 0 then
|
|
-- faccio verifica su pezzi singoli per avere un tempo???????????
|
|
EgtOutLog( 'Errore! Barra non assegnata a nessuna macchina!!')
|
|
|
|
|
|
else
|
|
local nMachGroupId = NestList[nAssignmentIndex].MachGroupList[assignment[nAssignmentIndex]].PartId
|
|
local sMachineName = NestList[nAssignmentIndex].MachGroupList[assignment[nAssignmentIndex]].Machine
|
|
EgtSetCurrMachGroup( nMachGroupId)
|
|
local nRawPartId = EgtGetFirstRawPart()
|
|
while nRawPartId do
|
|
local nPartId = EgtGetFirstPartInRawPart( nRawPartId)
|
|
while nPartId do
|
|
local sTag = EgtGetInfo( nPartId, 'LuxTag')
|
|
if not MachineTagList[sMachineName] then
|
|
MachineTagList[sMachineName] = { }
|
|
MachineTagList[sMachineName].TagList = { }
|
|
MachineTagList[sMachineName].BarQty = 0
|
|
MachineTagList[sMachineName].Time = 0
|
|
end
|
|
table.insert( MachineTagList[sMachineName].TagList, sTag)
|
|
nPartId = EgtGetNextPartInRawPart( nPartId)
|
|
end
|
|
nRawPartId = EgtGetNextRawPart( nRawPartId)
|
|
end
|
|
MachineTagList[sMachineName].BarQty = MachineTagList[sMachineName].BarQty + 1
|
|
MachineTagList[sMachineName].Time = MachineTagList[sMachineName].Time + NestList[nAssignmentIndex].MachGroupList[assignment[nAssignmentIndex]].Time
|
|
end
|
|
end
|
|
end
|
|
EgtResetCurrMachGroup()
|
|
local bDebug = true
|
|
if bDebug then
|
|
EgtSaveFile()
|
|
else
|
|
EgtEmptyDirectory( sCurrBalanceDirPath)
|
|
EgtEraseDirectory( sCurrBalanceDirPath)
|
|
end
|
|
-- do risultato
|
|
local JsonMachineTagList = JSON:encode( MachineTagList)
|
|
return 1, { Balance = JsonMachineTagList}
|
|
end
|
|
|
|
local function Create_Production( QuestionArgs)
|
|
-- leggo argomenti passati
|
|
--local sOrderUID = QuestionArgs["ProductionOrderUID"]
|
|
--if not sOrderUID or #sOrderUID <= 0 then
|
|
-- local sErrorMsg = 'Errore! ProductionOrderUID vuoto!'
|
|
-- EgtOutLog(sErrorMsg)
|
|
-- return 0, { Error = sErrorMsg}
|
|
--end
|
|
local sUID = QuestionArgs["UID"]
|
|
if not sUID or #sUID <= 0 then
|
|
local sErrorMsg = 'Errore! UID vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
--local dBarLenght = tonumber( QuestionArgs["BarLenght"])
|
|
--if not dBarLenght or dBarLenght <= 0 then
|
|
-- local sErrorMsg = 'Errore! BarLenght vuoto o non valido! (' .. QuestionArgs["BarLenght"] .. ')'
|
|
-- EgtOutLog(sErrorMsg)
|
|
-- return 0, { Error = sErrorMsg}
|
|
--end
|
|
local sProdCreate = QuestionArgs["ProdCreate"]
|
|
if not sProdCreate or #sProdCreate <= 0 then
|
|
local sErrorMsg = 'Errore! ProdCreate vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
--local sReqBalance = QuestionArgs["ReqBalance"]
|
|
--if not sReqBalance or #sReqBalance <= 0 then
|
|
-- local sErrorMsg = 'Errore! ReqBalance vuoto!'
|
|
-- EgtOutLog(sErrorMsg)
|
|
-- return 0, { Error = sErrorMsg}
|
|
--end
|
|
-- leggo dati per creare ordine
|
|
local ProdCreate = JSON:decode( sProdCreate)
|
|
if not ProdCreate or not next( ProdCreate) then
|
|
local sErrorMsg = 'Errore! Lista pezzi da mettere in produzione vuota o non leggibile!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
-- creo cartella per ordine di produzione
|
|
local sDataDir = EgtGetStringFromIni( 'Lux', 'DataDir', '', sIniFilePath)
|
|
local sProductionDirPath = sDataDir .. '\\Beam\\' .. ProdCreate.ProdName
|
|
if EgtExistsDirectory( sProductionDirPath) then
|
|
if not EgtEmptyDirectory( sProductionDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile svuotare cartella ' .. sProductionDirPath .. ' per il progetto ' .. sUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
else
|
|
if not EgtCreateDirectory( sProductionDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sProductionDirPath .. ' per il progetto ' .. sUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
end
|
|
-- creo il contesto secondario
|
|
local nDefaultContext = EgtGetContext()
|
|
local nTempContext = EgtCreateContext()
|
|
-- importo tutti i pezzi richiesti
|
|
EgtNewFile()
|
|
for sOrderID, Order in pairs(ProdCreate.OrderTagDict) do
|
|
for sOrderRowID, TagList in pairs(Order) do
|
|
-- imposto il contesto secondario
|
|
EgtSetContext( nTempContext)
|
|
-- apro il progetto
|
|
local sNgeFilePath = sDataDir .. '\\Beam\\' .. sOrderID .. '\\' .. sOrderRowID .. '\\' .. sOrderRowID .. '.nge'
|
|
if not EgtOpenFile( sNgeFilePath) then
|
|
local sErrorMsg = 'Errore! Fallita apertura del file!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
-- cerco i pezzi
|
|
local nPartId = EgtGetFirstPart()
|
|
local PartIdList = {}
|
|
local SectionList = {}
|
|
local nPartCount = 0
|
|
while nPartId do
|
|
local bFound, _, FoundTagList = IsTagInPart( nPartId, TagList)
|
|
if bFound then
|
|
local sNewTagList = ''
|
|
for nFoundTagIndex = 1, #FoundTagList do
|
|
sNewTagList = sNewTagList .. FoundTagList[nFoundTagIndex] .. EgtIf( nFoundTagIndex == #FoundTagList, '', ',')
|
|
end
|
|
EgtSetInfo( nPartId, 'LuxTagList', sNewTagList)
|
|
EgtCopyEx( nTempContext, nPartId, nDefaultContext, GDB_ID.ROOT)
|
|
end
|
|
nPartId = EgtGetNextPart( nPartId)
|
|
end
|
|
end
|
|
end
|
|
EgtSetContext( nDefaultContext)
|
|
local sProductionNgeFilePath = sProductionDirPath .. '\\' .. sUID .. '.nge'
|
|
EgtSaveFile( sProductionNgeFilePath, GDB_NT.CMPTXT)
|
|
-- calcolo quantita' barre, volume, barre lineari
|
|
local SectionList = {}
|
|
local TotVol = 0
|
|
local nPartId = EgtGetFirstPart( nRawPartId)
|
|
while nPartId do
|
|
local dW = EgtGetInfo( nPartId, "W", 'd')
|
|
local dH = EgtGetInfo( nPartId, "H", 'd')
|
|
local dL = EgtGetInfo( nPartId, "L", 'd')
|
|
local sMaterial = EgtGetInfo( nPartId, "MATERIAL")
|
|
local sTagList = EgtGetInfo( nPartId, 'LuxTagList')
|
|
local TagList = EgtSplitString( sTagList, ',')
|
|
local nCnt = #TagList
|
|
local Section = nil
|
|
for nSectionIndex = 1, #SectionList do
|
|
if SectionList[nSectionIndex].W == dW and SectionList[nSectionIndex].H == dH and SectionList[nSectionIndex].Material == sMaterial then
|
|
Section = SectionList[nSectionIndex]
|
|
end
|
|
end
|
|
if Section then
|
|
Section.Qty = Section.Qty + nCnt
|
|
Section.TotLen = Section.TotLen + ( dL * nCnt)
|
|
Section.Volume = Section.Volume + ( dW * dH * dL * nCnt)
|
|
else
|
|
table.insert( SectionList, { W = dW, H = dH, Material = sMaterial, Qty = nCnt, TotLen = ( dL * nCnt), Volume = (dW * dH * dL * nCnt)})
|
|
end
|
|
TotVol = TotVol + ((( dW / 1000) * ( dH / 1000) * ( dL / 1000)) * nCnt)
|
|
nPartId = EgtGetNextPart( nPartId)
|
|
end
|
|
local BOM = {}
|
|
for nSectionIndex = 1, #SectionList do
|
|
local Section = SectionList[nSectionIndex]
|
|
table.insert( BOM, { ClassCode = 'BeamTrunk',
|
|
ItemCode = 'Pine-' .. Section.W .. 'x' .. Section.H,
|
|
ItemQty = Section.Qty,
|
|
DescriptionCode = '',
|
|
Volume = Section.Volume / 1000000000,
|
|
Qty = Section.TotLen / 1000})
|
|
end
|
|
-- do risultato
|
|
local JsonBOM = JSON:encode( BOM)
|
|
-- do risultato
|
|
return 1, { BOM = JsonBOM}
|
|
end
|
|
|
|
local function Calc_Production( QuestionArgs)
|
|
-- leggo argomenti passati
|
|
local sUID = QuestionArgs["UID"]
|
|
if not sUID or #sUID <= 0 then
|
|
local sErrorMsg = 'Errore! UID vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sProdCalc = QuestionArgs["ProdCalc"]
|
|
if not sProdCalc or #sProdCalc <= 0 then
|
|
local sErrorMsg = 'Errore! ProdCalc vuoto!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
-- leggo dati per creare ordine
|
|
local ProdCalc = JSON:decode( sProdCalc)
|
|
if not ProdCalc or not next( ProdCalc) then
|
|
local sErrorMsg = 'Errore! Lista pezzi da mettere in produzione vuota o non leggibile!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
|
|
-- recupero cartella 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
|
|
-- verifico esistenza cartella per progetti di stima
|
|
local sEstimateDirPath = sOrderDirPath .. '\\Estimate'
|
|
if EgtExistsDirectory( sEstimateDirPath) then
|
|
if not EgtEmptyDirectory( sEstimateDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile svuotare cartella ' .. sEstimateDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
else
|
|
if not EgtCreateDirectory( sEstimateDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sEstimateDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
end
|
|
-- creo cartella per progetto di stima corrente
|
|
local nCurrTime = os.time()
|
|
local sCurrEstimateDirPath = sEstimateDirPath .. '\\' .. nCurrTime
|
|
if not EgtCreateDirectory( sCurrEstimateDirPath) then
|
|
local sErrorMsg = 'Errore! Impossibile creare cartella ' .. sCurrEstimateDirPath .. ' per il progetto ' .. sOrderUID .. '!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
local sNgeFilePath = sOrderDirPath .. '\\' .. sUID .. '.nge'
|
|
local sEstimateNgeFilePath = sCurrEstimateDirPath .. '\\' .. sUID .. '_' .. nCurrTime .. '.nge'
|
|
if not EgtCopyFile( sNgeFilePath, sEstimateNgeFilePath) then
|
|
local sErrorMsg = 'Errore! Fallita copia del file!'
|
|
EgtOutLog(sErrorMsg)
|
|
return 0, { Error = sErrorMsg}
|
|
end
|
|
if not EgtOpenFile( sEstimateNgeFilePath) 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 .. '\\Saomad-Kairos', MachineDirPath .. '\\Essetre-FAST'}
|
|
--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 = sCurrEstimateDirPath .. '\\' .. 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( sEstimateNgeFilePath, 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.AsyncVerifyPartCalc( 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.AsyncVerifyPartResult( 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! (' .. AnswerChannelList[nAnswerCount].Channel .. ')'
|
|
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}
|
|
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)
|
|
elseif nSubMode == QUESTION_ORDER_SUBMODES.BALANCE then
|
|
_G.LUX = {}
|
|
LUX.REDISID = nRedisConnectionId
|
|
nResult, AnswerArgs = Calc_Balance( QuestionArgs)
|
|
AnswerArgs.Group = QuestionArgs['Group']
|
|
elseif nSubMode == QUESTION_ORDER_SUBMODES.CREATE_PRODUCTION then
|
|
--_G.LUX = {}
|
|
--LUX.REDISID = nRedisConnectionId
|
|
nResult, AnswerArgs = Create_Production( QuestionArgs)
|
|
elseif nSubMode == QUESTION_ORDER_SUBMODES.CALC_PRODUCTION then
|
|
_G.LUX = {}
|
|
LUX.REDISID = nRedisConnectionId
|
|
nResult, AnswerArgs = Calc_Production( 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) |