diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 77cc3a55..e55ad93b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -312,6 +312,19 @@ IOB-WIN-SIEMENS:build: script: - '& "$env:MSBUILD_PATH" "$env:APP_NAME\$env:APP_NAME.csproj" -target:Build /p:Configuration=Release /p:Platform="x86" /p:OutputPath=bin/ /nodeReuse:false /verbosity:minimal /m' +IOB-WIN-SQL:build: + stage: build + tags: + - win + variables: + APP_NAME: IOB-WIN-SQL + before_script: + - *nuget-fix + - '& "$env:NUGET_PATH" restore "$env:APP_NAME.sln" -verbosity quiet' + - *version-fix + script: + - '& "$env:MSBUILD_PATH" "$env:APP_NAME\$env:APP_NAME.csproj" -target:Build /p:Configuration=Release /p:Platform="x86" /p:OutputPath=bin/ /nodeReuse:false /verbosity:minimal /m' + IOB-WIN-WPS:build: stage: build tags: @@ -566,6 +579,31 @@ IOB-WIN-SIEMENS:release: - *nexusUpload - *SendToVersionsLog +IOB-WIN-SQL:release: + stage: release + needs: ["IOB-WIN-SQL:build"] + tags: + - win + variables: + APP_NAME: IOB-WIN-SQL + NEXUS_PATH: MAPO/IOB-WIN-SQL + rules: + - if: $CI_COMMIT_BRANCH == 'master' + changes: + - IOB-WIN-SQL/* + when: always + before_script: + - *nuget-fix + - '& "$env:NUGET_PATH" restore "$env:APP_NAME.sln" -verbosity quiet' + - *version-fix + - *cleanup-zip + script: + - '& "$env:MSBUILD_PATH" "$env:APP_NAME\$env:APP_NAME.csproj" -target:Build /p:Configuration=Release /p:Platform="x86" /p:OutputPath=bin/ /nodeReuse:false /verbosity:minimal /m' + - *zipper + - *hashBuild + - *nexusUpload + - *SendToVersionsLog + IOB-WIN-WPS:release: stage: release needs: ["IOB-WIN-WPS:build"] @@ -780,6 +818,26 @@ IOB-WIN-SIEMENS:docfx: - mv $env:APP_NAME/_site "docfx" - *DocReplica +IOB-WIN-SQL:docfx: + stage: docfx + needs: ["IOB-WIN-SQL:build"] + tags: + - win + variables: + APP_NAME: IOB-WIN-SQL + rules: + - if: $CI_COMMIT_BRANCH == 'master' + changes: + - IOB-WIN-SQL/* + when: always + before_script: + - *nuget-fix + - '& "$env:NUGET_PATH" restore "$env:APP_NAME.sln" -verbosity quiet' + script: + - docfx $env:APP_NAME/docfx.json + - mv $env:APP_NAME/_site "docfx" + - *DocReplica + IOB-WIN-WPS:docfx: stage: docfx needs: ["IOB-WIN-WPS:build"] diff --git a/IOB-WIN-NEXT/AdapterFormNext.cs b/IOB-WIN-NEXT/AdapterFormNext.cs index f02f8fff..b833faf7 100644 --- a/IOB-WIN-NEXT/AdapterFormNext.cs +++ b/IOB-WIN-NEXT/AdapterFormNext.cs @@ -64,15 +64,10 @@ namespace IOB_WIN_NEXT btnStart.Enabled = true; break; +#if false case tipoAdapter.IcoelDb: iobObj = new IobSql.IcoelDb(this, IOBConf); btnStart.Enabled = true; - break; - -#if false - case tipoAdapter.IcoelSoap: - iobObj = new IobNet.IcoelSoap(this, IOBConf); - btnStart.Enabled = true; break; #endif @@ -95,22 +90,6 @@ namespace IOB_WIN_NEXT break; #if false - case tipoAdapter.REST: - iobObj = new IobRest.Base(this, IOBConf); - btnStart.Enabled = true; - break; - - case tipoAdapter.REST_CITIZEN: - iobObj = new IobRest.Citizen(this, IOBConf); - btnStart.Enabled = true; - break; - - case tipoAdapter.SOAP_GOMBA: - iobObj = new IobSoap.Gomba(this, IOBConf); - btnStart.Enabled = true; - break; -#endif - case tipoAdapter.SQLSERVER_LANTEK: iobObj = new IobSql.SqlServLantek(this, IOBConf); btnStart.Enabled = true; @@ -119,7 +98,8 @@ namespace IOB_WIN_NEXT case tipoAdapter.SQLSERVER_PAMA: iobObj = new IobSql.SqlServPama(this, IOBConf); btnStart.Enabled = true; - break; + break; +#endif case tipoAdapter.ND: default: diff --git a/IOB-WIN-NEXT/DATA/CONF/FTP_SONATEST.ini b/IOB-WIN-NEXT/DATA/CONF/FTP_SONATEST.ini deleted file mode 100644 index 9aa6c689..00000000 --- a/IOB-WIN-NEXT/DATA/CONF/FTP_SONATEST.ini +++ /dev/null @@ -1,79 +0,0 @@ -;Configurazione IOB-WIN -[IOB] -;Macchina TEST FTP simile a ultrasuoni Sonatest x IMI Remosa -CNCTYPE=FTP -PING_MS_TIMEOUT=500 - -[MACHINE] -VENDOR=TEST_FTP -MODEL=TRUESCALE_FTP - -[CNC] -IP=10.74.82.204 -PORT=21 -PING_IP=10.74.82.204 -GETPRGNAME=false - -[SERVER] -MPIP=http://10.74.82.218 -MPURL=/MP/IO -CMDBASE=/IOB/input/ -CMDFLOG=/IOB/flog/ -CMDALIVE=/IOB -CMDENABLED=/IOB/enabled/ -CMDADV1=?valore= -CMDREBO=/sendReboot.aspx?idxMacchina= - -[MEMORY] -ADDR_READ=DB9999.DBB0 -ADDR_WRITE=DB9999.DBB0 -SIZE_READ=0 -SIZE_WRITE=0 - - -[BLINK] -;MAX_COUNTER_BLINK = 30 -MAX_COUNTER_BLINK = 30 -BLINK_FILT=0 - -[OPTPAR] -; imposto breve sennò non riesce a partire... -WAIT_REC_MSEC = 1000 -; indica gestione folder ritorno dati ODL -ODL_FOLDER = TRUE -; gestione contapezzi -PZCOUNT_MODE=NONE -DISABLE_PZCOUNT=TRUE -ENABLE_SEND_PZC_BLOCK=FALSE -MIN_SEND_PZC_BLOCK=0 -MAX_SEND_PZC_BLOCK=100 -;errori verifica folder FTP MAX -MAX_ERR_CHECK=10 -; gestione DynData -ENABLE_DYN_DATA=TRUE -FORCE_DYN_DATA=TRUE -DISABLE_DYN_DATA=TRUE -DISABLE_SEND_WDST=TRUE - -; gestioni PING -MAX_TRY_PING=3 -VETO_QUEUE_IN=4 -VETO_PING_SEC=4 -VETO_CHECKDIR_SEC=10 -MAX_ELAPSED_TIME_SEC=60 - -;VETO_SEND_SNAPSHOT=3 -POWEROFF_TIMEOUT_SEC=60 - -; conf parametri memoria READ/WRITE -FTP_PARAM=FTP_SONATEST.json - -[BRANCH] -NAME=master - -; Tags manuali -[TAGS] -Customer=SteamWare -HostOS=WIN -HostName=IOB-WIN-SIMULA -HostAddr=10.74.82.76 \ No newline at end of file diff --git a/IOB-WIN-NEXT/DATA/CONF/FTP_SONATEST.json b/IOB-WIN-NEXT/DATA/CONF/FTP_SONATEST.json deleted file mode 100644 index de2bdc0f..00000000 --- a/IOB-WIN-NEXT/DATA/CONF/FTP_SONATEST.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "ListTask": [ - { - "ActionId": "FtpDownload", - "ServerAddr": "egw-tscale-04", - "ServerPort": 21, - "ConnUser": "testftpuser", - "ConnPasswd": "we4reFromB3rghem!", - "RawCert": "", - "SkipCert": true, - "ReExecVeto": 90, - "Note": "Sync periodico completo", - "StepsList": [ - { - "Id": "01", - "Description": "Mirror Remote 2 Local Directory", - "Action": "mirrorDirR2L", - "ParamList": { - "RemoteDir": "ftpdata/syncfolder", - "LocalDir": "\\\\iis01\\W$\\Files" - } - } - ] - } - ] -} \ No newline at end of file diff --git a/IOB-WIN-NEXT/DATA/CONF/IMI_SONATEST.ini b/IOB-WIN-NEXT/DATA/CONF/IMI_SONATEST.ini deleted file mode 100644 index 399dd54e..00000000 --- a/IOB-WIN-NEXT/DATA/CONF/IMI_SONATEST.ini +++ /dev/null @@ -1,79 +0,0 @@ -;Configurazione IOB-WIN -[IOB] -;Macchina controllo ultrasuoni Sonatest x IMI Remosa -CNCTYPE=FTP -PING_MS_TIMEOUT=500 - -[MACHINE] -VENDOR=SONATEST -MODEL=VEO - -[CNC] -IP=172.28.30.208 -PORT=21 -PING_IP=172.28.30.208 -GETPRGNAME=false - -[SERVER] -MPIP=http://192.168.0.110 -MPURL=/MP/IO -CMDBASE=/IOB/input/ -CMDFLOG=/IOB/flog/ -CMDALIVE=/IOB -CMDENABLED=/IOB/enabled/ -CMDADV1=?valore= -CMDREBO=/sendReboot.aspx?idxMacchina= - -[MEMORY] -ADDR_READ=DB9999.DBB0 -ADDR_WRITE=DB9999.DBB0 -SIZE_READ=0 -SIZE_WRITE=0 - - -[BLINK] -;MAX_COUNTER_BLINK = 30 -MAX_COUNTER_BLINK = 30 -BLINK_FILT=0 - -[OPTPAR] -; imposto breve sennò non riesce a partire... -WAIT_REC_MSEC = 1000 -; indica gestione folder ritorno dati ODL -ODL_FOLDER = TRUE -; gestione contapezzi -PZCOUNT_MODE=NONE -DISABLE_PZCOUNT=TRUE -ENABLE_SEND_PZC_BLOCK=FALSE -MIN_SEND_PZC_BLOCK=0 -MAX_SEND_PZC_BLOCK=100 -;errori verifica folder FTP MAX -MAX_ERR_CHECK=10 -; gestione DynData -ENABLE_DYN_DATA=TRUE -FORCE_DYN_DATA=TRUE -DISABLE_DYN_DATA=TRUE -DISABLE_SEND_WDST=TRUE - -; gestioni PING -MAX_TRY_PING=3 -VETO_QUEUE_IN=5 -VETO_PING_SEC=5 -VETO_CHECKDIR_SEC=10 -MAX_ELAPSED_TIME_SEC=60 - -;VETO_SEND_SNAPSHOT=3 -POWEROFF_TIMEOUT_SEC=60 - -; conf parametri memoria READ/WRITE -FTP_PARAM=IMI_SONATEST.json - -[BRANCH] -NAME=master - -; Tags manuali -[TAGS] -Customer=IMI-Remosa -HostOS=WIN -HostName=MAPO-SRV-60 -HostAddr=192.168.0.12 diff --git a/IOB-WIN-NEXT/DATA/CONF/IMI_SONATEST.json b/IOB-WIN-NEXT/DATA/CONF/IMI_SONATEST.json deleted file mode 100644 index c6ff3c6e..00000000 --- a/IOB-WIN-NEXT/DATA/CONF/IMI_SONATEST.json +++ /dev/null @@ -1,27 +0,0 @@ -{ - "ListTask": [ - { - "ActionId": "FtpDownload", - "ServerAddr": "172.28.30.208", - "ServerPort": 21, - "ConnUser": "ftpuser", - "ConnPasswd": "SOnaTEst", - "RawCert": "", - "SkipCert": true, - "ReExecVeto": 90, - "Note": "Sync periodico completo", - "StepsList": [ - { - "Id": "01", - "Description": "Mirror Remote 2 Local Directory", - "Action": "mirrorDirR2L", - "ParamList": { - "RemoteDir": "internal/MES", - "LocalDir": "\\\\308file\\shares\\QUAL\\Sonatest_Reports\\MES" - } - } - - ] - } - ] -} \ No newline at end of file diff --git a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj index 085bfc57..56653fd8 100644 --- a/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj +++ b/IOB-WIN-NEXT/IOB-WIN-NEXT.csproj @@ -103,15 +103,6 @@ ..\packages\EasyModbusTCP.5.6.0\lib\net40\EasyModbus.dll - - ..\packages\EgwProxy.Gomba.3.6.2309.1416\lib\EgwProxy.Gomba.dll - - - ..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.dll - - - ..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.DataLayer.dll - ..\packages\EgwProxy.MultiCncLib.3.6.2207.1211\lib\EgwProxy.MultiCncLib.dll @@ -121,18 +112,12 @@ ..\packages\EgwProxy.OsaiCncLib.3.6.2205.2015\lib\EgwProxy.OsaiCncLib.XmlSerializers.dll - - ..\packages\EgwProxy.SqlDb.3.6.2303.1515\lib\EgwProxy.SqlDb.dll - ..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.dll ..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.SqlServer.dll - - ..\packages\FluentFTP.51.1.0\lib\net462\FluentFTP.dll - False ExtLib\krcc.dll @@ -404,9 +389,6 @@ Form - - - Form @@ -666,9 +648,7 @@ - - - + diff --git a/IOB-WIN-NEXT/IobFile/IobFileSoitaab.cs b/IOB-WIN-NEXT/IobFile/IobFileSoitaab.cs index d2bb11bb..0a894adf 100644 --- a/IOB-WIN-NEXT/IobFile/IobFileSoitaab.cs +++ b/IOB-WIN-NEXT/IobFile/IobFileSoitaab.cs @@ -1,4 +1,6 @@ -using EgwProxy.SqlDb.DbModels; +#if false +using EgwProxy.SqlDb.DbModels; +#endif using IOB_UT_NEXT; using MapoSDK; using System; @@ -221,10 +223,12 @@ namespace IOB_WIN_NEXT.IobFile #region Protected Properties +#if false /// /// Stato di sync delle tab gestite /// - protected List elencoSyncState { get; set; } = new List(); + protected List elencoSyncState { get; set; } = new List(); +#endif #endregion Protected Properties diff --git a/IOB-WIN-NEXT/IobNet/IcoelSoap.cs b/IOB-WIN-NEXT/IobNet/IcoelSoap.cs deleted file mode 100644 index 730b83a2..00000000 --- a/IOB-WIN-NEXT/IobNet/IcoelSoap.cs +++ /dev/null @@ -1,471 +0,0 @@ -using EgwProxy.Icoel; -using EgwProxy.Icoel.SizerService; -using IOB_UT_NEXT; -using MapoSDK; -using System; -using System.Collections.Generic; -using System.Net.NetworkInformation; - -namespace IOB_WIN_NEXT.IobNet -{ - /// - /// Adapter specializzato per ICOEL e le chiamate tramite WS Soap al Sizer, con libreria EgwProxy.Icoel - /// - public class IcoelSoap : Iob.GenericNext - { - #region Public Constructors - - /// - /// Costruttore dell'IOB Icoel SOAP - /// - /// AdapterForm chiamante - /// Configurazione IOB per avvio - public IcoelSoap(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf) - { - /* -------------------------------------- - * todo's - * -------------------------------------- - * - init obj comunicazione da conf e nuget - * - test comunicazione - * - estensione IOB come OPT_PAR di OVERRIDE (x inviare dati di un unico iOB da più IOB programs) - * - gestione processCustomTaskLF - * - x lettura dei 2 batch correnti (sx/dx) - * - calcolo batch in corso/chiusi da date inizio/fine - * - trasmettere a MP/IO risultato valutazioni - * - gestione executeTasks - * - task di invio batch configurato in coda - * - task di recupero info anagrafiche (grower, variety, layout,...) - * - contapezzi (SE ha senso con sizer oppure saltare) - */ - - IcoelSizer = new Connector(IOBConf.cncIpAddr, IOBConf.cncPort); - lastPING = DateTime.Now.AddHours(-1); - } - - #endregion Public Constructors - - #region Public Methods - - /// - /// Implementazione custom esecuzione task specifici - /// - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - /*--------------------------------------- - * fixme todo fare !!! - * gestione execute task SPECIFICI x il sizer: - * - recupero anagrafice variety/layout (attivi) - * - recupero grower - * - invio batch da accodare - * - recupero dati da sizer (OVE disponibili) - * - recupero batch corrente (modalità force/resync?) - * - *---------------------------------------*/ - - // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - if (task2exe != null) - { - // controllo se memMap != null... - if (memMap != null) - { - bool taskOk = false; - string taskVal = ""; - // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 - foreach (var item in task2exe) - { - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - // controllo sulla KEY... - switch (tName) - { - case taskType.setSupplier: - - string cmdArgs = item.Value; - taskVal = executeSetSupplier(cmdArgs); - break; - - case taskType.setParameter: - // richiedo da URL i parametri WRITE da popolare - lgInfo("Chiamata setParameter --> processMemWriteRequests"); - taskVal = processMemWriteRequests(); - // se restituiscce "" faccio altra prova... - if (string.IsNullOrEmpty(taskVal)) - { - // i parametri me li aspetto come stringa composta paramName|paramvalue - if (item.Value.Contains("|")) - { - string[] paramsJob = item.Value.Split('|'); - taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; - } - else - { - taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; - } - } - break; - - default: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - } - // aggiungo task! - taskDone.Add(item.Key, taskVal); - } - } - else - { - lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!"); - } - } - - return taskDone; - } - - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - // valore non presente in vers default... se gestito fare override - Dictionary outVal = new Dictionary(); - // recupero da libreria il dizionario dei performance parameters... - perfParamDict = IcoelSizer.GetPerfMeters(); - lgTrace("SOAP: effettuata chiamata IcoelSizer.GetPerfMeters()"); - foreach (var item in perfParamDict) - { - saveValue(ref outVal, item.Key, item.Value); - } - // ora leggo i batch data - batchDataDict = IcoelSizer.GetCurrBatchData(); - lgTrace("SOAP: effettuata chiamata IcoelSizer.GetCurrBatchData()"); - foreach (var item in batchDataDict) - { - saveValueString(ref outVal, item.Key, item.Value); - } - - lastReadPLC = DateTime.Now; - return outVal; - } - - /// - /// Effettua processing CUSTOM x Icoel: - /// - recupera elenco batch delle 2 linee - /// - invia al sistema - /// - public override void processCustomTaskLF() - { - lgInfo($"Richiesto processCustomTaskLF"); - var currBatch = IcoelSizer.GetCurrentBatch(); - lgTrace("SOAP: effettuata chiamata IcoelSizer.GetCurrentBatch()"); - if (currBatch != null) - { - // verifico se i batch siano variati... e quindi da inviare... - bool doSend = (currBatchList == null || currBatchList.Count == 0); - if (currBatch.Count > 0 && !doSend) - { - foreach (var item in currBatch) - { - // se variato ID è cambiato - doSend = doSend || (currBatchList[item.Key].Id != item.Value.Id); - } - } - // se devo inviare impacchetto dati - if (doSend) - { - accodaRawData(rawTransfType.IcoelBatch, currBatch); - currBatchList = currBatch; - } - } - - lastReadPLC = DateTime.Now; - } - - /// - /// Effettua lettura semafori principale Parametri da - /// aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - if (connectionOk) - { - B_input = 1; - currDispData.semIn = Semaforo.SV; - if (currBatchList == null) - { - // se nullo --> provo a leggere! - var currBatch = IcoelSizer.GetCurrentBatch(); - lgTrace("SOAP: effettuata chiamata IcoelSizer.GetCurrentBatch()"); - if (currBatch != null) - { - currBatchList = currBatch; - accodaRawData(rawTransfType.IcoelBatch, currBatch); - } - } - else - { - //se i perf parameters mi danno valire > 0 x quantità frutta... - if (perfParamDict != null && perfParamDict.Count > 0) - { - if (perfParamDict.ContainsKey("VelFruttiMinuto")) - { - if (perfParamDict["VelFruttiMinuto"] > 0) - { - B_input += (1 << 1); - } - // metto manuale - else - { - B_input += (1 << 4); - } - } - } - - //usato altro criterio x stato verde da vel frutti minuto -#if false - // se ho batch NON chiusi (data = minValue) allora lavora - if (currBatchList[1].EndTime == DateTime.MinValue || currBatchList[1].EndTime == DateTime.MinValue) - { - B_input = 3; - } -#endif - } - // accodo NON emergenza - B_input += (1 << 7); - } - else - { - B_input = 0; - currDispData.semIn = Semaforo.SR; - } - } - - /// - /// Override connessione - /// - public override void tryConnect() - { - if (!connectionOk) - { - // controllo che il ping sia stato tentato almeno pingTestSec fa... - if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) - { - if (verboseLog || periodicLog) - { - lgInfo("IcoelSoap: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - // se passa il ping faccio il resto... - if (testPingMachine == IPStatus.Success) - { - string szStatusConnection = ""; - try - { - // ora provo connessione... - parentForm.commPlcActive = true; - // recupero elenco batch... se != vuoto -_> connesso! - var batchList = IcoelSizer.GetCurrentBatch(); - lgTrace("SOAP: effettuata chiamata IcoelSizer.GetCurrentBatch()"); - if (batchList != null && batchList.Count > 0) - { - lgInfo($"szStatusConnection IcoelSoap, recuperato elenco di {batchList.Count} batch"); - parentForm.commPlcActive = false; - connectionOk = true; - } - // refresh stato connessione!!! - if (connectionOk) - { - queueInEnabCurr = true; - if (adpRunning) - { - lgInfo("Connessione OK"); - } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } - } - catch (Exception exc) - { - lgFatal($"Errore nella connessione all'adapter IcoelSoap: {szStatusConnection}{Environment.NewLine}{exc}"); - connectionOk = false; - lgInfo($"Eccezione in TryConnect, Adapter IcoelSoap NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); - } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - if (verboseLog || periodicLog) - { - lgInfo($"Attenzione: IcoelSoap controllo PING fallito per IP {cIobConf.cncPingAddr}"); - } - } - } - } - else - { - needRefresh = true; - } - } - - public override void tryDisconnect() - { - // registro solo che è disconnesso - connectionOk = false; - queueInEnabCurr = false; - } - - #endregion Public Methods - - #region Protected Properties - - /// - /// Dizionario dati Batch correnti - /// - protected Dictionary batchDataDict { get; set; } = new Dictionary(); - - /// - /// elenco dei BAtch correntemente caricati x testing variazione - /// - protected Dictionary currBatchList { get; set; } - - protected Connector IcoelSizer { get; set; } - - /// - /// Dizionario parametri correnti - /// - protected Dictionary perfParamDict { get; set; } = new Dictionary(); - - #endregion Protected Properties - - #region Protected Methods - - /// - /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC - /// - /// - protected override void plcWriteParams(ref List updatedPar) - { - foreach (var item in updatedPar) - { - // cerco se sia setSupplier - if (item.uid == "setSupplier") - { - string reqVal = !string.IsNullOrEmpty(item.reqValue) ? item.reqValue : item.value; - // chiamo - var taskVal = executeSetSupplier(reqVal); - bool fatto = taskVal.StartsWith("REQUEST"); - // se fatto --> aggiorno! - if (fatto) - { - //item.value = item.reqValue; - item.reqValue = ""; - item.lastRead = DateTime.Now; - item.UM = ""; - } - } - } - } - - /// - /// recupera le variety ed i rispettivi layout e li invia al sistema MP/IO - /// - protected void refreshVarietyData() - { - ///determina se recuperare SOLO varietà attive o tutte - bool soloAttive = false; - var varList = IcoelSizer.GetVarietyList(soloAttive); - lgTrace("SOAP: effettuata chiamata IcoelSizer.GetVarietyList()"); - if (varList != null && varList.Length > 0) - { - var varietyData = IcoelSizer.GetLayoutForVarietyList(varList); - lgTrace("SOAP: effettuata chiamata IcoelSizer.GetLayoutForVarietyList()"); - } - - lastReadPLC = DateTime.Now; - } - - #endregion Protected Methods - - #region Private Methods - - private string executeSetSupplier(string cmdArgs) - { - string taskVal; - // loggo i parametri ricevuti da popolare - lgInfo($"Chiamata setSupplier --> params payload: {cmdArgs}"); - // recupero batch corrente x preselezionare i dati guid layout/varietà... - var currBatch = IcoelSizer.GetCurrentBatch(); - // recupero GUID x variety e layout di default - var varGuid = currBatch[1].VarietyId; - var layGuid = currBatch[1].LayoutId; - // predispongo grower di default - GrowerInfo GrowerData = new GrowerInfo(); - // le info sono una stringa separata da valore | di GrowerCode|GrowerName|varietyGuid|LayoutGuid; - string[] reqParams = cmdArgs.Split('|'); - // se ho dati sistemo grower... - if (reqParams.Length >= 2) - { - //GrowerData.GrowerCode = reqParams[0]; - //GrowerData.GrowerName = reqParams[1]; - // sistemo commenti - var comments = new List(); - comments.Add($"sent {DateTime.Now: yyyy.MM.dd HH:mm:ss}"); - comments.Add("Qty: no set"); - comments.Add("------------"); - //GrowerData.Comments = comments; - - GrowerData = new GrowerInfo() - { - GrowerCode = reqParams[0], - GrowerName = reqParams[1], - Comments = comments - }; - lgInfo($"Set grower data | GrowerCode: {GrowerData.GrowerCode} | GrowerName: {GrowerData.GrowerName}"); - } - if (reqParams.Length >= 3) - { - Guid.TryParse(reqParams[2], out varGuid); - lgInfo($"Set Variety data | VarGUID: {varGuid}"); - } - if (reqParams.Length >= 4) - { - Guid.TryParse(reqParams[3], out layGuid); - lgInfo($"Set Layout data | LayGUID: {layGuid}"); - } - - // invio richiesta!!! - IcoelSizer.EnqueueBatch(GrowerData, varGuid, layGuid); - lgInfo($"Request sent!"); - - taskVal = $"REQUEST SET SUPPLIER | EnqueueBatch | GrowCode: {GrowerData.GrowerCode} | GrowName: {GrowerData.GrowerName} | Var: {varGuid} | Lay: {layGuid} "; - // se restituiscce "" faccio altra prova... - if (string.IsNullOrEmpty(taskVal)) - { - // i parametri me li aspetto come stringa composta paramName|paramvalue - if (cmdArgs.Contains("|")) - { - string[] paramsJob = cmdArgs.Split('|'); - taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; - } - else - { - taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {cmdArgs} doesnt contain pipe for splitting key/value"; - } - } - - return taskVal; - } - - #endregion Private Methods - } -} \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobRest/Base.cs b/IOB-WIN-NEXT/IobRest/Base.cs deleted file mode 100644 index bd2d8ae3..00000000 --- a/IOB-WIN-NEXT/IobRest/Base.cs +++ /dev/null @@ -1,633 +0,0 @@ -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; -using RestSharp; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net.NetworkInformation; -using System.Text.RegularExpressions; -using System.Windows.Forms; - -namespace IOB_WIN_NEXT.IobRest -{ - /// - /// Adapter base per sviluppo chiamate con servizi REST - /// - public class Base : Iob.GenericNext - { - #region Public Constructors - - /// - /// Costruttore dell'IOB Rest generico - /// - /// AdapterForm chiamante - /// Configurazione IOB per avvio - public Base(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf) - { - lgInfo($"Richiesto Adapter IobRest.Base con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}"); - lastPING = DateTime.Now.AddHours(-1); - // predispongo configurazione specifica Rest... - if (!string.IsNullOrEmpty(getOptPar("REST_CONF"))) - { - setupRestConf(getOptPar("REST_CONF")); - } - } - - #endregion Public Constructors - - #region Public Methods - - /// - /// Implementazione custom esecuzione task specifici - /// - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - /*--------------------------------------- - * gestione execute task SPECIFICI x pesa: - * - salva i parametri richiesta (RM, cod1..cod6) - * - esegue metodo richiesta (IN/OUT) - *---------------------------------------*/ - - // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); -#if false - if (task2exe != null) - { - lgTrace($"executeTasks: richiesta esecuzione {task2exe.Count} task"); - // controllo se memMap != null... - if (memMap != null) - { - bool taskOk = false; - string taskVal = ""; - // cerco task specifici: qui sono NON standard... - foreach (var item in task2exe) - { - lgInfo($"TASK | {item.Key} --> {item.Value}"); - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - // controllo sulla KEY... - switch (tName) - { - case taskType.setParameter: - // richiedo da URL i parametri WRITE da popolare - lgInfo("Chiamata setParameter --> processMemWriteRequests"); - taskVal = processMemWriteRequests(); - // se restituiscce "" faccio altra prova... - if (string.IsNullOrEmpty(taskVal)) - { - // i parametri me li aspetto come stringa composta paramName|paramvalue - if (item.Value.Contains("|")) - { - string[] paramsJob = item.Value.Split('|'); - taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; - } - else - { - taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; - } - } - break; - - default: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - } - // aggiungo task! - taskDone.Add(item.Key, taskVal); - } - } - else - { - lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!"); - } - } -#endif - - return taskDone; - } - - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - // valore non presente in vers default... se gestito fare override - Dictionary outVal = new Dictionary(); - // indico esecuzione e proseguo - lastReadPLC = DateTime.Now; - return outVal; - } - - /// - /// Effettua lettura semafori principale Parametri da - /// aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - DateTime adesso = DateTime.Now; - lastReadPLC = adesso; - // verifico non sia in veto invio iniziale... - if (queueInEnabCurr) - { - try - { - if (verboseLog) - { - lgInfo("inizio read semafori"); - } - - currDispData.semIn = Semaforo.SV; - // effettua refresh dati da leggere SPECIFICi x citizen... - refreshData(); - // decodifica e gestione - decodeToBaseBitmap(ref currDispData); - // display - reportRawInput(ref currDispData); - } - catch (Exception exc) - { - currDispData.semIn = Semaforo.SR; - lgError($"Eccezione in readSemafori:{Environment.NewLine}{exc}"); - } - } - else - { - lgDebug($"[VETO readSemafori] | veto attivo alle {adesso:yyyy.MM.dd HH:mm:ss}"); - checkVetoQueueIn(); - } - } - - /// - /// Override connessione - /// - public override void tryConnect() - { - if (!connectionOk) - { - // controllo che il ping sia stato tentato almeno pingTestSec fa... - if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) - { - if (verboseLog || periodicLog) - { - lgInfo("Rest: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - // se passa il ping faccio il resto... - if (testPingMachine == IPStatus.Success) - { - string szStatusConnection = ""; - try - { - // ora provo connessione... - parentForm.commPlcActive = true; - - // chiamo metodo connect - var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"), true); - // forse va eliminato... - lgInfo($"GetConnection | {checkResp} (Base.tryConnect)"); - if (checkResp != null && checkResp.ToLower().Contains("true")) - { - connectionOk = true; - } - else - { - lgError($"Errore check connessione | checkResp: {checkResp}"); - } - // refresh stato connessione!!! - if (connectionOk) - { - queueInEnabCurr = true; - if (adpRunning) - { - lgInfo("Connessione OK"); - } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } - } - catch (Exception exc) - { - lgFatal($"Errore nella connessione all'Adapter IobRest.Base: {szStatusConnection}{Environment.NewLine}{exc}"); - connectionOk = false; - lgInfo($"Eccezione in TryConnect, Adapter IobRest.Base NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); - } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - if (verboseLog || periodicLog) - { - lgInfo($"Attenzione: Rest controllo PING fallito per IP {cIobConf.cncPingAddr}"); - } - } - } - } - else - { - needRefresh = true; - } - } - - public override void tryDisconnect() - { - // registro solo che è disconnesso - connectionOk = false; - queueInEnabCurr = false; - } - - #endregion Public Methods - - #region Protected Fields - - /// - /// Api Url di base x chiamate REST - /// - protected string apiUrl = "http://localhost:8733"; - - /// - /// Num err connessioni corrente - /// - protected int connErrCur = 0; - - /// - /// Max num err connesisone prima di disconnettere - /// - protected int connErrMax = 5; - - /// - /// LookUpTable informazioni raccolte - /// - protected Dictionary RestDataLUT = new Dictionary(); - - /// - /// Timeout chiamate REST - /// - protected int tOutSec = 60; - - #endregion Protected Fields - - #region Protected Properties - - /// - /// Parametri specifici Client Rest - /// - protected RestParamConf restParams { get; set; } = new RestParamConf(); - - #endregion Protected Properties - - #region Protected Methods - - /// - /// verifica stato ok ovvero connected oppure open - /// - /// - /// - protected bool checkStateOk(System.ServiceModel.CommunicationState currState) - { - bool answ = false; - return answ; - } - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - protected virtual void decodeToBaseBitmap(ref newDisplayData currDispData) - { - // init a zero... - B_input = 0; - if (queueInEnabCurr) - { - /* ----------------------------------------------------- - * bitmap MAPO STD 60 - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * B5: allarme TCiclo (SLOW) - * B6: WarmUp_CoolDown - * B7: EmergArmed (1 = NON emergenza, 0 = emergenza) - ----------------------------------------------------- */ - - // per prima cosa controllo ping e se sia connesso... - -#if false - if (connectionOk) - { - B_input = 1; - currDispData.semIn = Semaforo.SV; - - // se ho pesate in memoria nel periodo richiesto --> RUN - if (listPesateCurr != null && listPesateCurr.Count > 0) - { - B_input += (1 << 1); - } - // metto manuale - else - { - B_input += (1 << 4); - } - - // accodo NON emergenza - B_input += (1 << 7); - } - else - { - B_input = 0; - currDispData.semIn = Semaforo.SR; - } -#endif - } - else - { - lgDebug($"[VETO getDataItemValue] | veto attivo alle {DateTime.Now:yyyy.MM.dd HH:mm:ss}"); - } - } - - /// - /// Esecuzione chiamata Rest tipo GET - /// - /// URI da chiamare - /// Chiamata rapida (timeout rapido = 5sec) - /// - protected string ExecuteCallGet(string resource, bool fastCall = false) - { - string answ = ""; - if (!string.IsNullOrEmpty(resource)) - { - if (fastCall) - { - restOptStd.Timeout = TimeSpan.FromSeconds(5); - } - try - { - // client chiamate rest - using (var client = new RestClient(restOptStd)) - { - var actReq = new RestRequest(resource, Method.Get); - // effettuo vera chiamata - var currResp = client.Get(actReq); - if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null) - { - answ = currResp.Content ?? ""; - } - } - } - catch (Exception exc) - { - lgError($"Eccezione in ExecuteCallGet{Environment.NewLine}{exc}"); - } - } - return answ; - } - - /// - /// Esecuzione chiamata Rest tipo POST - /// - /// URI da chiamare - /// Payload da allegare (già serializzato) - /// Chiamata rapida (timeout rapido = 5sec) - /// - protected string ExecuteCallPost(string resource, string payload, bool fastCall = false) - { - string answ = ""; - if (!string.IsNullOrEmpty(resource)) - { - if (fastCall) - { - restOptStd.Timeout = TimeSpan.FromSeconds(5); - } - try - { - // client chiamate rest - using (var client = new RestClient(restOptStd)) - { - var actReq = new RestRequest(resource, Method.Post); - actReq.AddJsonBody(payload); - // effettuo vera chiamata - var currResp = client.Post(actReq); - if (currResp.StatusCode == System.Net.HttpStatusCode.OK && currResp.Content != null) - { - answ = currResp.Content ?? ""; - } - } - } - catch (Exception exc) - { - lgError($"Eccezione in ExecuteCallPost{Environment.NewLine}{exc}"); - } - } - return answ; - } - - /// - /// restituisce URL della risorsa eventualmente completato con token o altro - /// - /// - /// - protected string GetUrlResource(string resName) - { - string answ = ""; - if (restParams != null && restParams.CallList != null && restParams.CallList.Count > 0) - { - if (restParams.CallList.ContainsKey(resName)) - { - answ = restParams.CallList[resName].Url; - // eseguo eventuale sostituzione (se trovo "[[") - if (answ.Contains("[[")) - { - string pattern = @"\[\[.*\]\]"; - Regex regex = new Regex(pattern); - Match match = regex.Match(answ); - if (match.Success) - { - string key = match.Value.Replace("[[", "").Replace("]]", ""); - // cerco nella LUT... - if (RestDataLUT.ContainsKey(key)) - { - // sostituisco! - answ = answ.Replace($"[[{key}]]", RestDataLUT[key]); - } - } - } - } - } - return answ; - } - - /// - /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC - /// - /// - protected override void plcWriteParams(ref List updatedPar) - { - lgTrace($"plcWriteParams: richiesta per {updatedPar.Count} params"); - foreach (var item in updatedPar) - { - lgInfo($"ITEM | {item.uid} | {item.value}"); - // salvo i valori di setup x prox volta... - upsertKey(item.uid, item.value); -#if false - bool fatto = false; - bool isPesata = false; - bool isIN = false; - gestWeightOut answ = new gestWeightOut(); - // se è richiesta pesata IN/OUT --> mando chiamata - if (item.uid == "reqPesata") - { - isPesata = true; - isIN = item.reqValue.ToUpper() == "IN"; - //isIN = item.value.ToUpper() == "IN"; - try - { - answ = reqWeight(isIN); - } - catch (Exception exc) - { - lgError($"Eccezione in plcWriteParams.reqWeight | isIn: {isIN}{Environment.NewLine}{exc}"); - } - } - else if (item.uid == "RM" || item.uid.StartsWith("Cod")) - { - // comunque segno fatto x altri casi - fatto = true; - } - - // se è pesata... - if (isPesata) - { - // se è OK - if (answ.feedback == "C") - { - lgInfo($"reqWeight | Effettuato richiesta | {answ.feedback} | {answ.notes}"); - // resetto pesata - upsertKey(item.uid, ""); - } - else - { - lgError($"reqWeight | Errore in richiesta peso Rest | {answ.feedback} | {answ.notes}"); - } - item.value = ""; - item.reqValue = ""; - item.lastRead = DateTime.Now; - item.UM = ""; - // salvo esito richiesta comunque - upsertKey("logReq", $"{answ.feedback} | {answ.notes}"); - // faccio in modo di eseguire subito getDynData - demFactDynData = 1; - processDynData(); - } - else - { - // se fatto --> aggiorno! - if (fatto) - { - //item.value = item.reqValue; - item.reqValue = ""; - item.lastRead = DateTime.Now; - item.UM = ""; - } - } -#endif - } - } - - /// - /// Esegue lettura dati + salvataggio in LUT - /// - protected virtual void refreshData() - { } - - /// - /// Recupero valore da cache LUT - /// - /// - /// - protected string RestLutGet(string key) - { - string value = ""; - if (RestDataLUT.ContainsKey(key)) - { - value = RestDataLUT[key]; - } - return value; - } - - /// - /// Upsert in cache LUT del parametro - /// - /// - /// - protected void RestLutUpsert(string key, string value) - { - if (RestDataLUT.ContainsKey(key)) - { - RestDataLUT[key] = value; - } - else - { - RestDataLUT.Add(key, value); - } - } - - protected void setupRestConf(string restConfFile) - { - // se ho file specifico - if (!string.IsNullOrEmpty(getOptPar("REST_CONF"))) - { - string rawData = ""; - // leggo file e decodifico... - string confPath = $"{Application.StartupPath}/DATA/CONF/{restConfFile}"; - lgInfo($"Apertura file {confPath}"); - using (StreamReader sr = new StreamReader(confPath)) - { - rawData = sr.ReadToEnd().Replace("\n", "").Replace("\r", ""); - } - // continuo decodifica - if (!string.IsNullOrEmpty(rawData)) - { - restParams = JsonConvert.DeserializeObject(rawData); - if (restParams != null) - { - // inizializzo dal file di conf le variabili necessarie... - tOutSec = restParams.timeOutSec; - apiUrl = restParams.apiUrl ?? "http://localhost:8733"; - // sistemo parametri specali come samplePeriod ed errori conn... - samplePeriod = restParams.samplePeriod; - connErrMax = restParams.connErrorMax; - } - } - } - - // sistemo conf standard x call REST - restOptStd = new RestClientOptions - { - Timeout = TimeSpan.FromSeconds(tOutSec), - BaseUrl = new Uri(apiUrl) - }; - } - - #endregion Protected Methods - - #region Private Fields - - /// - /// Conf client RestSharp standard: - /// - timeout 1 min - /// - private RestClientOptions restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60) }; - - #endregion Private Fields - } -} \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobRest/Citizen.cs b/IOB-WIN-NEXT/IobRest/Citizen.cs deleted file mode 100644 index 8810f02b..00000000 --- a/IOB-WIN-NEXT/IobRest/Citizen.cs +++ /dev/null @@ -1,733 +0,0 @@ -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Data.Entity.Core.Mapping; -using System.IO; -using System.Net.NetworkInformation; -using System.Threading.Tasks; -using static IOB_WIN_NEXT.IobRest.Citizen.Responses; -using static System.Windows.Forms.VisualStyles.VisualStyleElement; - -namespace IOB_WIN_NEXT.IobRest -{ - /// - /// Adapter specializzato per Citizen (Colcom, MT70) - /// - public class Citizen : Base - { - #region Public Constructors - - /// - /// Costruttore dell'IOB SOAP della bilancia RestCitizen - /// - /// AdapterForm chiamante - /// Configurazione IOB per avvio - public Citizen(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf) - { - lgInfo($"Richiesto Adapter IobRest.RestCitizen con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}"); - lastPING = DateTime.Now.AddHours(-1); - redKeyAlarm = redisMan.redHash($"IOB:Status:{cIobConf.codIOB}:Alarm:LastRead"); - lastPING = DateTime.Now.AddHours(-1); - // predispongo configurazione specifica Rest... - lgInfo("Rest - 01"); - if (!string.IsNullOrEmpty(getOptPar("REST_CONF"))) - { - setupRestConf(getOptPar("REST_CONF")); - } - // sistemo conf errori e samplePeriod... - - lgInfo("Rest - 02"); - if (EnableTest) - { - PrelimCitizenRestTest(); - } - } - - #endregion Public Constructors - - #region Public Methods - - /// - /// Implementazione custom esecuzione task specifici - /// - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - /*--------------------------------------- - * gestione execute task SPECIFICI: - * - setArt - * - setComm - * - setPzComm - *---------------------------------------*/ - - // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - if (task2exe != null) - { - lgTrace($"executeTasks: richiesta esecuzione {task2exe.Count} task"); - // controllo se memMap != null... - if (memMap != null) - { - bool taskOk = false; - string taskVal = ""; - // cerco task specifici: qui sono NON standard... - foreach (var item in task2exe) - { - lgInfo($"TASK | {item.Key} --> {item.Value}"); - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - // controllo sulla KEY... - switch (tName) - { - case taskType.setArt: - case taskType.setComm: - case taskType.setPzComm: - lgInfo($"Task: {item.Key} | {item.Value}"); - // salvo valori in memoria prod data - upsertKey(item.Key, item.Value); - taskVal = $"SET task: {item.Key} --> {item.Value}"; - // invio una chiamata al sistema con i valori attuali - taskOk = SetJobDataCitizen(); - break; - - case taskType.setParameter: - // richiedo da URL i parametri WRITE da popolare - lgInfo("Chiamata setParameter --> processMemWriteRequests"); - taskVal = processMemWriteRequests(); - // se restituiscce "" faccio altra prova... - if (string.IsNullOrEmpty(taskVal)) - { - // i parametri me li aspetto come stringa composta paramName|paramvalue - if (item.Value.Contains("|")) - { - string[] paramsJob = item.Value.Split('|'); - taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; - } - else - { - taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; - } - } - break; - - default: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - } - // aggiungo task! - taskDone.Add(item.Key, taskVal); - } - } - else - { - lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!"); - } - } - return taskDone; - } - - /// - /// Recupera dizionario allarmi (SE PRESENTE) - /// - /// - public override Dictionary getAlarmData() - { - Dictionary outVal = new Dictionary(); - // verifico SE HO allarmi attivi e nel caso li invia... - string rawData = ExecuteCallGet(GetUrlResource("GetCurrAlarm")); - string bankVal = "OK"; - WarnInfo alarmResp = JsonConvert.DeserializeObject(rawData); - bankVal = (alarmResp != null && alarmResp.IsAlarm) ? alarmResp.message : "OK"; - saveAlarmString(ref outVal, bankVal, "Alarms"); - // verificare eventuale invio allarmi "storici" - return outVal; - } - - /// - /// Recupero dati DYN, impiegando i valori della LUT... - /// - /// - public override Dictionary getDynData() - { - var answ = RestDataLUT; - // aggiungo DynData... calcolato come variazione pezzi e lampade... - if (answ.ContainsKey("DYNDATA")) - { - answ.Remove("DYNDATA"); - } - answ.Add("DYNDATA", $"LAMP_{RestLutGet("gLamp")}{RestLutGet("yLamp")}{RestLutGet("rLamp")}_PzReq_{RestLutGet("qtyReq")}_PzWrk_{RestLutGet("qtyWrk")}_PzTot_{RestLutGet("qtyTot")}"); - - return answ; - } - - /// - /// Recupera il progName in modalità custom... - /// - /// - public override string getPrgName() - { - return RestLutGet("pName"); - } - - /// - /// Esegue gestioen contapezzi... - /// - public override void processContapezzi() - { - DateTime adesso = DateTime.Now; - // controllo se sia passato il samplePeriod minimo x 3... - if (adesso.Subtract(lastRestProcPzCount.AddMilliseconds(samplePeriod * 3)).TotalSeconds > 0) - { - lastRestProcPzCount = adesso; - bool checkMachine = false; - LadderIO ladderResp = new LadderIO(); - // in primis testo che sia connessa... - var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"), true); - lgInfo($"GetConnection | {checkResp} | Citizen.processContapezzi"); - bool.TryParse(checkResp, out checkMachine); - - // proseguo SOLO SE macchina OK, altrimenti disconnetto... - if (checkMachine) - { - // faccio refresh token comunque... - string token = ExecuteCallGet(GetUrlResource("GetToken")); - token = token.Replace("\"", ""); - RestLutUpsert("token", token); - - // contapezzi corrente - int intVal = 0; - string qtyWrk = ExecuteCallGet(GetUrlResource("GetQtyProd")); - int.TryParse(qtyWrk, out intVal); - contapezziPLC = intVal; - RestLutUpsert("qtyWrk", qtyWrk); - - // gestione altri contapezzi x - string qtyTot = ExecuteCallGet(GetUrlResource("GetQtyTot")); - string qtyReq = ExecuteCallGet(GetUrlResource("GetQtyReq")); - RestLutUpsert("qtyTot", qtyTot); - RestLutUpsert("qtyReq", qtyReq); - // gestione tempociclo e nome programma... - string cTime = ExecuteCallGet(GetUrlResource("GetCycleTime")); - string pName = ExecuteCallGet(GetUrlResource("GetProgName")); - RestLutUpsert("cTime", cTime); - RestLutUpsert("pName", pName); - - lgInfo($"Citizen | contapezziPLC {qtyWrk} | qtyReq: {qtyReq} | qtyTot: {qtyTot}"); - } - } - } - - /// - /// Override connessione - /// - public override void tryConnect() - { - if (!connectionOk) - { - // controllo che il ping sia stato tentato almeno pingTestSec fa... - if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) - { - if (verboseLog || periodicLog) - { - lgInfo("Rest: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - bool checkMachine = false; - // se passa il ping faccio il resto... - if (testPingMachine == IPStatus.Success) - { - string szStatusConnection = ""; - try - { - // ora provo connessione... - parentForm.commPlcActive = true; - - // chiamo metodo connect - var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"), true); - lgInfo($"GetConnection | {checkResp} | Citizen.tryConnect"); - bool.TryParse(checkResp, out checkMachine); - if (checkMachine) - { - connectionOk = true; - queueInEnabCurr = true; - if (adpRunning) - { - lgInfo("Connessione Citizen OK"); - } - } - else - { - lgError($"Errore check connessione Citizen | checkResp: {checkResp}"); - } - } - catch (Exception exc) - { - lgFatal($"Errore nella connessione all'Adapter IobRest.Base: {szStatusConnection}{Environment.NewLine}{exc}"); - connectionOk = false; - lgInfo($"Eccezione in TryConnect, Adapter IobRest.Base NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); - } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - if (verboseLog || periodicLog) - { - lgInfo($"Attenzione: Rest controllo PING fallito per IP {cIobConf.cncPingAddr}"); - } - } - } - } - else - { - needRefresh = true; - } - } - - #endregion Public Methods - - #region Internal Classes - - /// - /// Struttura delle risposte alle chiamare REST specifiche - /// - internal class Responses - { - #region Internal Classes - - /// - /// Struttura info restituiti da AlarmList - /// - internal class AlarmInfo - { - #region Public Properties - - public DateTime date { get; set; } = DateTime.Today.AddYears(-10); - public string ErrorMessage { get; set; } = ""; - public int id { get; set; } = 0; - public string message { get; set; } = ""; - public string type { get; set; } = ""; - - #endregion Public Properties - } - - /// - /// Struttura info JobData da inviare x setup - /// - internal class CitizenJobData - { - #region Public Properties - - public string itemcode { get; set; } = ""; - public string itemdescription { get; set; } = ""; - public string ordercode { get; set; } = ""; - public int piecestodo { get; set; } = 0; - public string token { get; set; } = ""; - - #endregion Public Properties - } - - /// - /// Struttura info restituiti x lettura Ladder - /// - internal class LadderIO - { - #region Public Properties - - public string Address { get; set; } = ""; - public string Description { get; set; } = ""; - public string ErrorMessage { get; set; } = ""; - public string IOType { get; set; } = ""; - public string VarValue { get; set; } = ""; - - #endregion Public Properties - } - - /// - /// Struttura info QtyData da inviare x impostazioni quantità - /// - internal class QtyData - { - #region Public Properties - - public string token { get; set; } = ""; - public int value { get; set; } = 0; - - #endregion Public Properties - } - - /// - /// Struttura dato AlarmState (singolo, corrente) - /// - internal class WarnInfo - { - #region Public Properties - - public string ErrorMessage { get; set; } = ""; - public bool IsAlarm { get; set; } = false; - public bool IsCaution { get; set; } = false; - public string message { get; set; } = ""; - - #endregion Public Properties - } - - /// - /// Struttura risposta x scrittura parametri numerici (es qty) - /// - internal class WriteResult - { - #region Public Properties - - public string ErrorMessage { get; set; } = null; - public bool Result { get; set; } = false; - - #endregion Public Properties - } - - #endregion Internal Classes - } - - #endregion Internal Classes - - #region Protected Methods - - /// - /// Effettua decodifica aree memoria alla bitmap usata x MAPO - /// - protected override void decodeToBaseBitmap(ref newDisplayData currDispData) - { - // init a zero... - B_input = 0; - if (queueInEnabCurr) - { - /* ----------------------------------------------------- - * bitmap MAPO STD 60 - * B0: POWER_ON - * B1: RUN - * B2: pzCount - * B3: allarme - * B4: manuale - * B5: allarme TCiclo (SLOW) - * B6: WarmUp_CoolDown - * B7: EmergArmed (1 = NON emergenza, 0 = emergenza) - ----------------------------------------------------- */ - - // per prima cosa controllo ping e se sia connesso... - - if (connectionOk) - { - B_input = 1; - currDispData.semIn = Semaforo.SV; - - // controllo lampade... da rosso a verde... - if (RestLutGet("rLamp") == "1") - { - B_input += (1 << 3); - } - else if (RestLutGet("yLamp") == "1") - { - B_input += (1 << 4); - } - else if (RestLutGet("gLamp") == "1") - { - B_input += (1 << 1); - } - - // accodo NON emergenza ... poi da cercare meglio... - B_input += (1 << 7); - } - else - { - B_input = 0; - currDispData.semIn = Semaforo.SR; - } - } - else - { - lgDebug($"[VETO queueInEnabCurr] | veto attivo alle {DateTime.Now:yyyy.MM.dd HH:mm:ss}"); - } - } - - /// - /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC - /// - /// - protected override void plcWriteParams(ref List updatedPar) - { - lgTrace($"plcWriteParams: richiesta per {updatedPar.Count} params"); - foreach (var item in updatedPar) - { - lgInfo($"ITEM | {item.uid} | {item.value}"); - // salvo i valori ricevuti - upsertKey(item.uid, item.reqValue); - // resetto richiesta! - item.reqValue = ""; - // chiamo scrittura commessa! - var taskOk = SetJobDataCitizen(); - } - } - - /// - /// Esegue lettura dati + salvataggio in LUT - /// - protected override void refreshData() - { - DateTime adesso = DateTime.Now; - // controllo se sia passato il samplePeriod minimo... - if (adesso.Subtract(lastRestRefreshData.AddMilliseconds(samplePeriod)).TotalSeconds > 0) - { - lastRestRefreshData = adesso; - bool checkMachine = false; - LadderIO ladderResp = new LadderIO(); - // in primis testo che sia connessa... - var checkResp = ExecuteCallGet(GetUrlResource("GetConnection"), true); - lgInfo($"GetConnection | {checkResp} | Citizen.refreshData"); - bool.TryParse(checkResp, out checkMachine); - - // proseguo SOLO SE macchina OK, altrimenti disconnetto... - if (checkMachine) - { - //riporto err conn a zero - connErrCur = 0; - // faccio refresh token comunque... - string token = ExecuteCallGet(GetUrlResource("GetToken")); - token = token.Replace("\"", ""); - RestLutUpsert("token", token); - - // ora controllo valori lampada SE scaduti resetto 3 valori lamp - RestLutUpsert("gLamp", "0"); - RestLutUpsert("yLamp", "0"); - RestLutUpsert("rLamp", "0"); - - int signVal = 0; - string gLamp = ExecuteCallGet(GetUrlResource("GetLampGreen")); - ladderResp = JsonConvert.DeserializeObject(gLamp); - if (string.IsNullOrEmpty(ladderResp.ErrorMessage)) - { - int.TryParse(ladderResp.VarValue, out signVal); - RestLutUpsert("gLamp", $"{signVal}"); - } - - // se il valore è zero --> proseguo con yellow! - if (signVal == 0) - { - Task.Delay(samplePeriod / 4); - string yLamp = ExecuteCallGet(GetUrlResource("GetLampYellow")); - ladderResp = JsonConvert.DeserializeObject(yLamp); - if (string.IsNullOrEmpty(ladderResp.ErrorMessage)) - { - int.TryParse(ladderResp.VarValue, out signVal); - RestLutUpsert("yLamp", $"{signVal}"); - } - } - - // se il valore è zero --> proseguo con red! - if (signVal == 0) - { - Task.Delay(samplePeriod / 4); - string rLamp = ExecuteCallGet(GetUrlResource("GetLampRed")); - ladderResp = JsonConvert.DeserializeObject(rLamp); - if (string.IsNullOrEmpty(ladderResp.ErrorMessage)) - { - int.TryParse(ladderResp.VarValue, out signVal); - RestLutUpsert("rLamp", $"{signVal}"); - } - } - } - else - { - // verifico se devo disconnettere - if (connErrCur >= connErrMax) - { - connErrCur = 0; - tryDisconnect(); - } - else - { - connErrCur++; - } - } - } - } - - #endregion Protected Methods - - #region Private Fields - - private string basePath = ""; - - private DateTime lastRestProcPzCount = DateTime.Now; - - private DateTime lastRestRefreshData = DateTime.Now; - - #endregion Private Fields - - #region Private Properties - - /// - /// Elenco pesate attuali - /// - private List listAllarmiCurr { get; set; } = new List(); - - /// - /// CHiave redis di salvataggio ultimo set di allarmi scaricato - /// - private string redKeyAlarm { get; set; } = ""; - - #endregion Private Properties - - #region Private Methods - - /// - /// Test preliminare comunicazione Rest Citizen - /// - private void PrelimCitizenRestTest() - { - lgInfo("Rest - 03"); - // test folder salvataggio log - var appPath = System.Reflection.Assembly.GetExecutingAssembly().Location; - var fPath = Directory.GetParent(appPath).FullName; - basePath = Path.Combine(fPath, "Test"); - if (!Directory.Exists(basePath)) - { - Directory.CreateDirectory(basePath); - } - lgInfo("Rest - 04"); - - bool checkMachine = false; - string checkResp = TestCitizenCall("checkconnection", true); - lgInfo($"checkconnection | {checkResp}"); - bool.TryParse(checkResp, out checkMachine); - if (checkMachine) - { - string token = TestCitizenCall("gettoken/mecmaticames/mecmatica@mes"); - token = token.Replace("\"", ""); - if (string.IsNullOrEmpty(token)) - { - lgError("Errore: token vuoto"); - } - else - { - string gLamp = TestCitizenCall($"getsingleladderio/{token}/Y/8E"); - string yLamp = TestCitizenCall($"getsingleladderio/{token}/Y/21"); - string rLamp = TestCitizenCall($"getsingleladderio/{token}/Y/22"); - string qtyTot = TestCitizenCall($"gettotalquantity/{token}"); - string qtyReq = TestCitizenCall($"getneededquantity/{token}"); - string qtyWrk = TestCitizenCall($"getworkedquantity/{token}"); - string cTime = TestCitizenCall($"getcycletime/{token}"); - string pName = TestCitizenCall($"getmainprogram/{token}"); - - string cAlarm = ExecuteCallGet($"getalarm/{token}"); - var sAlarm = JsonConvert.DeserializeObject(cAlarm); - cAlarm = JsonConvert.SerializeObject(sAlarm, Formatting.Indented); - lgInfo($"Call: getalarm/{token} | resp: {cAlarm}"); - - string allAlarm = ExecuteCallGet($"getallalarmlog/{token}"); - var alarmList = JsonConvert.DeserializeObject>(allAlarm); - allAlarm = JsonConvert.SerializeObject(alarmList, Formatting.Indented); - lgInfo($"Call: getallalarmlog/{token} | resp: {allAlarm}"); - - string err = TestCitizenCall($"getsingleladderio/ABC/Y/22"); - - // salvo i valori - File.WriteAllText(Path.Combine(basePath, "token.txt"), token); - File.WriteAllText(Path.Combine(basePath, "gLamp.txt"), gLamp); - File.WriteAllText(Path.Combine(basePath, "yLamp.txt"), yLamp); - File.WriteAllText(Path.Combine(basePath, "rLamp.txt"), rLamp); - File.WriteAllText(Path.Combine(basePath, "qtyTot.txt"), qtyTot); - File.WriteAllText(Path.Combine(basePath, "qtyReq.txt"), qtyReq); - File.WriteAllText(Path.Combine(basePath, "qtyWrk.txt"), qtyWrk); - File.WriteAllText(Path.Combine(basePath, "cTime.txt"), cTime); - File.WriteAllText(Path.Combine(basePath, "pName.txt"), pName); - File.WriteAllText(Path.Combine(basePath, "cAlarm.txt"), cAlarm); - File.WriteAllText(Path.Combine(basePath, "allAlarm.txt"), allAlarm); - File.WriteAllText(Path.Combine(basePath, "err.txt"), err); - } - } - } - - /// - /// Effettua scrittura set di parametri del job e restitusice task eseguito... - /// - /// - private bool SetJobDataCitizen() - { - bool answ = false; - string varValue = ""; - CitizenJobData jobReq = new CitizenJobData(); - QtyData qtyReq = new QtyData(); - - // Token! - varValue = RestLutGet("token"); - jobReq.token = varValue; - qtyReq.token = varValue; - - // Commessa - varValue = getCurrProdData("setComm", ""); - jobReq.ordercode = varValue; - - // Articolo - varValue = getCurrProdData("setArt", ""); - jobReq.itemcode = varValue; - jobReq.itemdescription = $"ART: {varValue}"; - - // Qty - varValue = getCurrProdData("setPzComm", ""); - int pzReq = 0; - int.TryParse(varValue, out pzReq); - jobReq.piecestodo = pzReq; - qtyReq.value = pzReq; - - try - { - // preparo payload - string jobPayload = JsonConvert.SerializeObject(jobReq); - // faccio chiamata POST x invio - var rawResp = ExecuteCallPost(GetUrlResource("SetJobData"), jobPayload); - bool.TryParse(rawResp, out answ); - // se andatae se ho la chaive x invio abilitata invio anche la qty richiesta... - if (answ) - { - string urlNeedQty = GetUrlResource("SetNeededQuantity"); - if (string.IsNullOrEmpty(urlNeedQty)) - { - lgInfo($"Set NeedQty NON abilitato, non invio"); - } - else - { - jobPayload = JsonConvert.SerializeObject(qtyReq); - var rawRespQty = ExecuteCallPost(GetUrlResource("SetNeededQuantity"), jobPayload); - } - } - } - catch (Exception exc) - { - lgError($"Eccezione in SetJobDataCitizen{Environment.NewLine}{exc}"); - } - return answ; - } - - /// - /// Test Chiamata Citizen - /// - /// - /// - private string TestCitizenCall(string urlReq, bool fastCall = false) - { - lgInfo($"TestCitizenCall: {urlReq}"); - string answ = ExecuteCallGet(urlReq, fastCall); - lgInfo($"TestCitizenCall resp: {answ}"); - return answ; - } - - #endregion Private Methods - } -} \ No newline at end of file diff --git a/IOB-WIN-NEXT/IobSoap/Gomba.cs b/IOB-WIN-NEXT/IobSoap/Gomba.cs deleted file mode 100644 index 773bbbf5..00000000 --- a/IOB-WIN-NEXT/IobSoap/Gomba.cs +++ /dev/null @@ -1,740 +0,0 @@ -using EgwProxy.Gomba.GombaServ; -using IOB_UT_NEXT; -using MapoSDK; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Globalization; -using System.Linq; -using System.Net.NetworkInformation; - -namespace IOB_WIN_NEXT.IobSoap -{ - /// - /// Adapter specializzato per GOMA e le chiamate tramite WS Soap alla bilancia, libreria EgwProxy.Gomba - /// - public class Gomba : Iob.GenericNext - { - #region Public Constructors - - /// - /// Costruttore dell'IOB SOAP della bilancia GOMBA - /// - /// AdapterForm chiamante - /// Configurazione IOB per avvio - public Gomba(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf) - { - lgInfo($"Richiesto Adapter IobSoap.Gomba con i parametri seguenti | ADDR: {IOBConf.cncIpAddr} | PORT: {IOBConf.cncPort}"); - redKeyPesate = redisMan.redHash($"IOB:Status:{cIobConf.codIOB}:ListPesate"); - lastPING = DateTime.Now.AddHours(-1); - // verifico se sia attiva gestione riduzione FluxLog... - if (!string.IsNullOrEmpty(getOptJsonKVP("numLastWeight"))) - { - int.TryParse(getOptJsonKVP("numLastWeight"), out numLastWeight); - lgInfo($"Gomba: setup specifico | numLastWeight: {numLastWeight}"); - } - } - - #endregion Public Constructors - - #region Public Methods - - /// - /// Implementazione custom esecuzione task specifici - /// - /// - /// - public override Dictionary executeTasks(Dictionary task2exe) - { - /*--------------------------------------- - * gestione execute task SPECIFICI x pesa: - * - salva i parametri richiesta (RM, cod1..cod6) - * - esegue metodo richiesta (IN/OUT) - *---------------------------------------*/ - - // Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti... - Dictionary taskDone = new Dictionary(); - if (task2exe != null) - { - lgTrace($"executeTasks: richiesta esecuzione {task2exe.Count} task"); - // controllo se memMap != null... - if (memMap != null) - { - bool taskOk = false; - string taskVal = ""; - // cerco task specifici: qui sono NON standard... - foreach (var item in task2exe) - { - lgInfo($"TASK | {item.Key} --> {item.Value}"); - taskOk = false; - taskVal = ""; - // converto richiesta in enum... - taskType tName = taskType.nihil; - Enum.TryParse(item.Key, out tName); - // controllo sulla KEY... - switch (tName) - { - case taskType.setParameter: - // richiedo da URL i parametri WRITE da popolare - lgInfo("Chiamata setParameter --> processMemWriteRequests"); - taskVal = processMemWriteRequests(); - // se restituiscce "" faccio altra prova... - if (string.IsNullOrEmpty(taskVal)) - { - // i parametri me li aspetto come stringa composta paramName|paramvalue - if (item.Value.Contains("|")) - { - string[] paramsJob = item.Value.Split('|'); - taskVal = $"REQUEST SET PARAMETERS: {paramsJob[0]} --> {paramsJob[1]}"; - } - else - { - taskVal = $"WRONG REQUEST FOR SET PARAMETERS: {item.Value} doesnt contain pipe for splitting key/value"; - } - } - break; - - default: - taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; - lgInfo($"Chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); - break; - } - // aggiungo task! - taskDone.Add(item.Key, taskVal); - } - } - else - { - lgError($"Attenzione! memMap è nullo, non posso eseguire task2exe!"); - } - } - - return taskDone; - } - - /// - /// Recupero dati dinamici... - /// - public override Dictionary getDynData() - { - // valore non presente in vers default... se gestito fare override - Dictionary outVal = new Dictionary(); - // controllo se ho indicato ancora che ci siano pesate già lette da inviare... - if (num2send() > 0) - { - // preparo oggetti x confronto ... - List listaArch = listPesateArchivio; - - // se non ho nulla in archivio prendo ultima pesata (essendo DESC è la prima cronologicamente) - if (listaArch.Count == 0) - { - WeightRec lastRec = listPesateCurr.LastOrDefault(); - // aggiungo... - SavePesata(ref outVal, lastRec); - } - // ora il confronto è cronologico sulle pesate + recenti... - else - { - // prendo prima della lista pesate archiviate = più recente come dt da cui partire... - DateTime dtRif = listaArch.FirstOrDefault().DtEvent; - var firstRec = listPesateCurr - .Where(x => x.DtEvent > dtRif) - .OrderBy(x => x.DtEvent) - .FirstOrDefault(); - if (firstRec != null) - { - SavePesata(ref outVal, firstRec); - } - } - - // processo comunque le aree memoria READ... - if (memMap.mMapRead.Count > 0) - { - foreach (var item in memMap.mMapRead) - { - var currVal = getCurrProdData(item.Key, ""); - if (!outVal.ContainsKey(item.Key)) - { - outVal.Add(item.Key, $"{currVal}"); - } - // se fosse logReq --> resetto... - if (item.Key == "logReq" && !string.IsNullOrEmpty(currVal)) - { - upsertKey(item.Key, ""); - } - } - } - } - // altrimenti rileggo e cerco se ci siano - else - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - try - { - // test lettura elenco pesate... se NON nullo --> OK! - var weightArray = gombaConn.reqWeightList("ALL", dataFrom, dataTo); - // riordino DESC - listPesateCurr = WeightRec.ConvertPesate(weightArray.OrderByDescending(x => x.dateIn).ToList()); - } - catch (Exception exc) - { - lgError($"Eccezione in gombaConn.reqWeightList{Environment.NewLine}{exc}"); - } - sw.Stop(); - lgInfo($"getDynData | SOAP: effettuata chiamata reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo} | {listPesateCurr.Count} rec"); - } - // indico esecuzione e proseguo - lastReadPLC = DateTime.Now; - return outVal; - } - - /// - /// Effettua lettura semafori principale Parametri da - /// aggiornare x display in form - /// - public override void readSemafori(ref newDisplayData currDispData) - { - if (connectionOk) - { - B_input = 1; - currDispData.semIn = Semaforo.SV; - - // se ho pesate in memoria nel periodo richiesto --> RUN - if (listPesateCurr != null && listPesateCurr.Count > 0) - { - B_input += (1 << 1); - } - // metto manuale - else - { - B_input += (1 << 4); - } - - // accodo NON emergenza - B_input += (1 << 7); - } - else - { - B_input = 0; - currDispData.semIn = Semaforo.SR; - } - } - - /// - /// Override connessione - /// - public override void tryConnect() - { - if (!connectionOk) - { - // controllo che il ping sia stato tentato almeno pingTestSec fa... - if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) - { - if (verboseLog || periodicLog) - { - lgInfo("Gomba: ConnKO - tryConnect"); - } - // in primis salvo data ping... - lastPING = DateTime.Now; - // se passa il ping faccio il resto... - if (testPingMachine == IPStatus.Success) - { - string szStatusConnection = ""; - try - { - // ora provo connessione... - parentForm.commPlcActive = true; - - // init del proxy!!! - string endpointAddr = $"https://{cIobConf.cncIpAddr}:{cIobConf.cncPort}/ws"; - lgInfo($"Tentativo avvio SOAP su endpoint {endpointAddr}"); - Stopwatch sw = new Stopwatch(); - sw.Start(); - - // salto verifica certificato - System.Net.ServicePointManager.ServerCertificateValidationCallback = (senderX, certificate, chain, sslPolicyErrors) => { return true; }; - - // riprovo connessione SE non fosse andata... - int maxTry = 5; - int nTry = 1; - // tento avvio WS SOAP! - gombaConn = new EgwProxy.Gomba.GombaServ.lwpServiceClient("lwpServicePort", new System.ServiceModel.EndpointAddress(endpointAddr)); - while (gombaConn == null || (nTry <= maxTry && !checkStateOk(gombaConn.State))) - { - lgInfo($"Tentativo connessione Gomba: | endpointAddr: {endpointAddr} | nTry: {nTry}"); - // tento avvio WS SOAP! - gombaConn = new EgwProxy.Gomba.GombaServ.lwpServiceClient("lwpServicePort", new System.ServiceModel.EndpointAddress(endpointAddr)); - nTry++; - } - if (checkStateOk(gombaConn.State)) - { - connectionOk = true; - List weightArray = new List(); - try - { - // test lettura elenco pesate... se NON nullo --> OK! - weightArray = gombaConn.reqWeightList("ALL", dataFrom, dataTo).OrderByDescending(x => x.dateIn).ToList(); - // riordino DESC - listPesateCurr = WeightRec.ConvertPesate(weightArray); - } - catch (Exception exc) - { - lgError($"Eccezione in gombaConn.reqWeightList{Environment.NewLine}{exc}"); - } - sw.Stop(); - lgInfo($"SOAP: effettuata chiamata connessione + reqWeightList in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo}"); - if (listPesateCurr != null && listPesateCurr.Count >= 0) - { - lgInfo($"szStatusConnection Gomba, recuperato elenco di {listPesateCurr.Count} pesate"); - parentForm.commPlcActive = false; - connectionOk = true; - // sistemo data da cui iniziare recuperi successivi se ho + di numLastWeight - if (weightArray.Count > numLastWeight) - { - var lastRec = weightArray - .OrderByDescending(x => x.dateIn) - .Skip(numLastWeight).FirstOrDefault(); - // metto giorno antecedente - dtStartLive = lastRec.dateIn.Date.AddDays(-1); - } - // processo pesate! - demFactDynData = 1; - processDynData(); - } - } - // refresh stato connessione!!! - if (connectionOk) - { - queueInEnabCurr = true; - if (adpRunning) - { - lgInfo("Connessione OK"); - } - } - else - { - lgError("Impossibile procedere, connessione mancante..."); - } - } - catch (Exception exc) - { - lgFatal($"Errore nella connessione all'adapter Gomba: {szStatusConnection}{Environment.NewLine}{exc}"); - connectionOk = false; - lgInfo($"Eccezione in TryConnect, Adapter Gomba NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); - } - } - else - { - // loggo no risposta ping ... - connectionOk = false; - if (verboseLog || periodicLog) - { - lgInfo($"Attenzione: Gomba controllo PING fallito per IP {cIobConf.cncPingAddr}"); - } - } - } - } - else - { - needRefresh = true; - } - } - - public override void tryDisconnect() - { - // registro solo che è disconnesso - connectionOk = false; - queueInEnabCurr = false; - } - - #endregion Public Methods - - #region Protected Fields - - /// - /// Proxy per connessione al SOAP webservice GOMBA - /// - protected EgwProxy.Gomba.GombaServ.lwpServiceClient gombaConn; - - protected int numLastWeight = 100; - - #endregion Protected Fields - - #region Protected Methods - - /// - /// verifica stato ok ovvero connected oppure open - /// - /// - /// - protected bool checkStateOk(System.ServiceModel.CommunicationState currState) - { - return currState == System.ServiceModel.CommunicationState.Opened || currState == System.ServiceModel.CommunicationState.Created; - } - - /// - /// Metodo da overridare x scrivere DAVVERO i parametri sul PLC - /// - /// - protected override void plcWriteParams(ref List updatedPar) - { - lgTrace($"plcWriteParams: richiesta per {updatedPar.Count} params"); - foreach (var item in updatedPar) - { - lgInfo($"ITEM | {item.uid} | {item.value}"); - // salvo i valori di setup x prox pesata... - upsertKey(item.uid, item.value); - bool fatto = false; - bool isPesata = false; - bool isIN = false; - gestWeightOut answ = new gestWeightOut(); - // se è richiesta pesata IN/OUT --> mando chiamata - if (item.uid == "reqPesata") - { - isPesata = true; - isIN = item.reqValue.ToUpper() == "IN"; - //isIN = item.value.ToUpper() == "IN"; - try - { - answ = reqWeight(isIN); - } - catch (Exception exc) - { - lgError($"Eccezione in plcWriteParams.reqWeight | isIn: {isIN}{Environment.NewLine}{exc}"); - } - } - else if (item.uid == "RM" || item.uid.StartsWith("Cod")) - { - // comunque segno fatto x altri casi - fatto = true; - } - - // se è pesata... - if (isPesata) - { - // se è OK - if (answ.feedback == "C") - { - lgInfo($"reqWeight | Effettuato richiesta | {answ.feedback} | {answ.notes}"); - // resetto pesata - upsertKey(item.uid, ""); - } - else - { - lgError($"reqWeight | Errore in richiesta peso GOMBA | {answ.feedback} | {answ.notes}"); - } - item.value = ""; - item.reqValue = ""; - item.lastRead = DateTime.Now; - item.UM = ""; - // salvo esito richiesta comunque - upsertKey("logReq", $"{answ.feedback} | {answ.notes}"); - // faccio in modo di eseguire subito getDynData - demFactDynData = 1; - processDynData(); - } - else - { - // se fatto --> aggiorno! - if (fatto) - { - //item.value = item.reqValue; - item.reqValue = ""; - item.lastRead = DateTime.Now; - item.UM = ""; - } - } - } - } - - /// - /// Esegue richiesta PESO - /// - /// Tipo richiesta: IN (true) / OUT (false) - /// - protected gestWeightOut reqWeight(bool reqIN) - { - lgInfo($"reqWeight | IN: {reqIN}"); - gestWeightOut answ = null; - try - { - Stopwatch sw = new Stopwatch(); - sw.Start(); - // preparo parametri - string tipoRic = reqIN ? "IN" : "OUT"; - string rm = getCurrProdData("RM", $"{DateTime.Now:yyyyMMdd-HHmmss}");// string.IsNullOrEmpty(currProdData["RM"]) ? $"{DateTime.Now:yyyyMMdd-HHmmss}" : currProdData["RM"]; - string Cod1 = getCurrProdData("Cod1", ""); //string.IsNullOrEmpty(currProdData["Cod1"]) ? "" : currProdData["Cod1"]; - string Cod2 = getCurrProdData("Cod2", ""); //string.IsNullOrEmpty(currProdData["Cod2"]) ? "" : currProdData["Cod2"]; - string Cod3 = getCurrProdData("Cod3", ""); //string.IsNullOrEmpty(currProdData["Cod3"]) ? "" : currProdData["Cod3"]; - string Cod4 = getCurrProdData("Cod4", ""); //string.IsNullOrEmpty(currProdData["Cod4"]) ? "" : currProdData["Cod4"]; - string Cod5 = getCurrProdData("Cod5", ""); //string.IsNullOrEmpty(currProdData["Cod5"]) ? "" : currProdData["Cod5"]; - string Cod6 = getCurrProdData("Cod6", ""); //string.IsNullOrEmpty(currProdData["Cod6"]) ? "" : currProdData["Cod6"]; - // faccio chiamata - answ = gombaConn.memWeight(tipoRic, rm, Cod1, Cod2, Cod3, Cod4, Cod5, Cod6); - sw.Stop(); - lgInfo($"reqWeight: effettuata chiamata SOAP in {sw.Elapsed.TotalMilliseconds}ms | {dataFrom} --> {dataTo}"); - } - catch (Exception exc) - { - lgError($"reqWeight | errore richiesta pesatura{Environment.NewLine}{exc}"); - } - return answ; - } - - protected void SavePesata(ref Dictionary currDict, WeightRec newRec) - { - DictUpsert(ref currDict, "RM", newRec.RM ?? ""); - string tag = newRec.isIn ? "In" : "Out"; - DictUpsert(ref currDict, $"lastWeight{tag}", $"{newRec.weight:N2}"); - // registro record completo ultima pesata - DictUpsert(ref currDict, $"lastRec{tag}", formatPesata(newRec)); - // la aggiungo alle pesate archiviate... - AppendPesata(newRec); - } - - #endregion Protected Methods - - #region Protected Classes - - protected class WeightRec - { - #region Public Properties - - public string cod1 { get; set; } = ""; - - public string cod2 { get; set; } = ""; - - public string cod3 { get; set; } = ""; - - public string cod4 { get; set; } = ""; - - public string cod5 { get; set; } = ""; - - public string cod6 { get; set; } = ""; - - public DateTime DtEvent { get; set; } = DateTime.Today; - - public bool isIn { get; set; } = true; - - public string RM { get; set; } = "ND"; - - public double weight { get; set; } = 0; - - #endregion Public Properties - - #region Public Methods - - /// - /// Effettua converione come lista cronologica pesate (singoli record IN/OUT) - /// - /// - /// - public static List ConvertPesate(List pesateOrig) - { - List answ = new List(); - foreach (var item in pesateOrig) - { - // verifico se ci sia record IN... - if (item.dateInSpecified) - { - var newRec = new WeightRec() - { - RM = item.rm, - DtEvent = item.dateIn, - isIn = true, - cod1 = item.cod1, - cod2 = item.cod2, - cod3 = item.cod3, - cod4 = item.cod4, - cod5 = item.cod5, - cod6 = item.cod6, - weight = double.Parse(item.weightIn, NumberStyles.Any, CultureInfo.InvariantCulture) - }; - answ.Add(newRec); - } - // verifico se ci sia record IN... - if (item.dateOutSpecified) - { - var newRec = new WeightRec() - { - RM = item.rm, - DtEvent = item.dateOut, - isIn = false, - cod1 = item.cod1, - cod2 = item.cod2, - cod3 = item.cod3, - cod4 = item.cod4, - cod5 = item.cod5, - cod6 = item.cod6, - weight = double.Parse(item.weightOut, NumberStyles.Any, CultureInfo.InvariantCulture) - }; - answ.Add(newRec); - } - } - // riordino... - answ = answ.OrderByDescending(x => x.DtEvent).ToList(); - // restituisco! - return answ; - } - - #endregion Public Methods - } - - #endregion Protected Classes - - #region Private Properties - - /// - /// Data inizio periodo dati Bilancia: - /// - al boot impostato a -6 mesi - /// - dopo lettura impostato a data ultimi 5 record - /// - private string dataFrom - { - get => dtStartLive.ToString("dd/MM/yyyy"); - } - - /// - /// Data fine periodo dati Bilancia: oggi + 1gg - /// - private string dataTo - { - get => DateTime.Today.AddDays(1).ToString("dd/MM/yyyy"); - } - - /// - /// Data riferimento x avvio processo controllo - /// - private DateTime dtStartLive { get; set; } = DateTime.Today.AddMonths(-6); - - /// - /// Gestione archivio serializzato delle pesate già processate - /// - private List listPesateArchivio - { - get - { - List answ = new List(); - string redKey = $"{redKeyPesate}:ALL"; - string rawData = redisMan.getRSV(redKey); - if (!string.IsNullOrEmpty(rawData)) - { - try - { - answ = JsonConvert.DeserializeObject>(rawData); - lgInfo($"Rilettura status listPesateArchivio: trovati {answ.Count} record"); - answ = answ.OrderByDescending(x => x.DtEvent).ToList(); - } - catch (Exception exc) - { - lgError($"Errore in deserializzazione listPesateArchivio{Environment.NewLine}{exc}"); - answ = new List(); - } - } - // rendo - return answ; - } - set - { - // riordino prima di procedere... - var tempList = value.OrderByDescending(x => x.DtEvent).ToList(); - // ...trimmo se fossero + di xxx record... - if (tempList.Count > numLastWeight) - { - tempList = tempList.Take(numLastWeight).ToList(); - } - string redKey = $"{redKeyPesate}:ALL"; - string rawVal = JsonConvert.SerializeObject(tempList); - redisMan.setRSV(redKey, rawVal); - lgInfo($"Salvataggio status listPesateArchivio | {tempList.Count} record"); - } - } - - /// - /// Elenco pesate attuali - /// - private List listPesateCurr { get; set; } = new List(); - - private string redKeyPesate { get; set; } = ""; - - #endregion Private Properties - - #region Private Methods - - private static string formatCode(string currCode) - { - string code = string.IsNullOrEmpty(currCode) ? "-" : currCode; - return $" | {code}"; - } - - /// - /// Formatta record completo pesata - /// - /// record completo pesate Gomba - /// Indica se deve formattare i dati tipo IN (true) o OUT (false) - /// - private static string formatPesata(WeightRec rec) - { - string currVal = $"RM: {rec.RM} | "; - try - { - if (rec.isIn) - { - currVal += $"IN | "; - } - else - { - currVal += $"OUT | "; - } - currVal += $"{rec.DtEvent:yyyy-MM-dd HH:mm:ss} | {rec.weight:N2} kg"; - } - catch - { } - currVal += formatCode(rec.cod1); - currVal += formatCode(rec.cod2); - currVal += formatCode(rec.cod3); - currVal += formatCode(rec.cod4); - currVal += formatCode(rec.cod5); - currVal += formatCode(rec.cod6); - return currVal; - } - - private void AppendPesata(WeightRec newRec) - { - var tmpPesate = listPesateArchivio; - tmpPesate.Add(newRec); - listPesateArchivio = tmpPesate; - } - - /// - /// Calcola numero pesate da inviare confrontando lista curr ed arch - /// - private int num2send() - { - int answ = 0; - if (listPesateCurr.Count > 0) - { - var listaArch = listPesateArchivio.OrderByDescending(x => x.DtEvent).ToList(); - // se NON ne ho in archivio --> tutte! - if (listaArch.Count == 0) - { - answ = listPesateCurr.Count; - } - // altrimenti solo nuove - else - { - // prendo prima della lista pesate archiviate = più recente come dt da cui partire... - DateTime dtRif = listaArch.FirstOrDefault().DtEvent; - answ = listPesateCurr - .Where(x => x.DtEvent > dtRif) - .Count(); - } - } - return answ; - } - - #endregion Private Methods - } -} \ No newline at end of file diff --git a/IOB-WIN-NEXT/packages.config b/IOB-WIN-NEXT/packages.config index 2259562c..07d9c7e9 100644 --- a/IOB-WIN-NEXT/packages.config +++ b/IOB-WIN-NEXT/packages.config @@ -1,12 +1,8 @@  - - - - diff --git a/IOB-WIN-SQL.sln b/IOB-WIN-SQL.sln index f74b9464..8d4cf8a2 100644 --- a/IOB-WIN-SQL.sln +++ b/IOB-WIN-SQL.sln @@ -69,8 +69,8 @@ Global {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Release|Any CPU.Build.0 = Release|Any CPU {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Release|x86.ActiveCfg = Release|Any CPU {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Release|x86.Build.0 = Release|Any CPU - {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Remote_DEBUG|Any CPU.ActiveCfg = Release|Any CPU - {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Remote_DEBUG|Any CPU.Build.0 = Release|Any CPU + {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Remote_DEBUG|Any CPU.ActiveCfg = Remote_DEBUG|Any CPU + {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Remote_DEBUG|Any CPU.Build.0 = Remote_DEBUG|Any CPU {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Remote_DEBUG|x86.ActiveCfg = Release|Any CPU {4B67E8A4-7AE3-47EF-9E06-EF0FA74969F7}.Remote_DEBUG|x86.Build.0 = Release|Any CPU EndGlobalSection diff --git a/IOB-WIN-SQL/App.config b/IOB-WIN-SQL/App.config index 93faf2cd..adc54a0b 100644 --- a/IOB-WIN-SQL/App.config +++ b/IOB-WIN-SQL/App.config @@ -1,170 +1,181 @@  - - -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/IOB-WIN-SQL/ILLink/ILLink.Descriptors.LibraryBuild.xml b/IOB-WIN-SQL/ILLink/ILLink.Descriptors.LibraryBuild.xml new file mode 100644 index 00000000..a42d7f0e --- /dev/null +++ b/IOB-WIN-SQL/ILLink/ILLink.Descriptors.LibraryBuild.xml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/IOB-WIN-SQL/IOB-WIN-SQL.csproj b/IOB-WIN-SQL/IOB-WIN-SQL.csproj index d7d64285..2c767b1d 100644 --- a/IOB-WIN-SQL/IOB-WIN-SQL.csproj +++ b/IOB-WIN-SQL/IOB-WIN-SQL.csproj @@ -1,5 +1,6 @@ + Debug @@ -12,9 +13,11 @@ 512 true true + + - AnyCPU + x86 true full false @@ -32,9 +35,82 @@ prompt 4 + + true + bin\Remote_DEBUG\ + DEBUG;TRACE + full + x86 + 7.3 + prompt + + + ..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.dll + + + ..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.DataLayer.dll + + + ..\packages\EgwProxy.SqlDb.3.6.2303.1515\lib\EgwProxy.SqlDb.dll + + + ..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.dll + + + ..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.SqlServer.dll + + + ..\packages\MapoSDK.6.14.2411.518\lib\MapoSDK.dll + + + ..\packages\Microsoft.Bcl.AsyncInterfaces.9.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll + + + ..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.9.0.0\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll + + + ..\packages\Microsoft.Extensions.Logging.Abstractions.9.0.0\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll + + + ..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll + + + ..\packages\NLog.5.3.4\lib\net46\NLog.dll + + + ..\packages\StackExchange.Redis.2.8.24\lib\net461\StackExchange.Redis.dll + + + ..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll + + + + + ..\packages\System.Diagnostics.DiagnosticSource.9.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll + + + + ..\packages\System.IO.Pipelines.9.0.0\lib\net462\System.IO.Pipelines.dll + + + ..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll + + + + ..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll + + + ..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll + + + ..\packages\System.Threading.Channels.9.0.0\lib\net462\System.Threading.Channels.dll + + + ..\packages\System.Threading.Tasks.Extensions.4.6.0\lib\net462\System.Threading.Tasks.Extensions.dll + @@ -52,12 +128,16 @@ Form + + + Form + Always @@ -139,6 +219,7 @@ Designer + true PreserveNewest @@ -169,4 +250,23 @@ + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + \ No newline at end of file diff --git a/IOB-WIN-SQL/IobSql/IcoelDb.cs b/IOB-WIN-SQL/IobSql/IcoelDb.cs new file mode 100644 index 00000000..43367bc3 --- /dev/null +++ b/IOB-WIN-SQL/IobSql/IcoelDb.cs @@ -0,0 +1,288 @@ +using EgwProxy.Icoel; +using IOB_UT_NEXT; +using MapoSDK; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Net.NetworkInformation; + +namespace IOB_WIN_SQL.IobSql +{ + /// + /// Adapter specializzato per ICOEL e le chiamate tramite DB per i dati + /// - accettazione lotti prodotto (frontiera / entrata ciliegie) + /// - export (totale per prodotti) + /// - tracciabilità (confezioni + /// + + public class IcoelDb : Iob.GenericNext + { + #region Public Constructors + + /// + /// Costruttore dell'IOB Icoel DB + /// + /// AdapterForm chiamante + /// Configurazione IOB per avvio + public IcoelDb(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + /* -------------------------------------- + * todo's + * -------------------------------------- + * - init obj comunicazione da conf e nuget + * - lanciare sync e verifica stato sync + */ + + string SyncStateServer = getOptPar("SyncStateServer"); + string SyncStateDb = getOptPar("SyncStateDb"); + string SyncStateUser = getOptPar("SyncStateUser"); + string SyncStatePwd = getOptPar("SyncStatePwd"); + string SyncStateCTout = getOptPar("SyncStateCTout"); + + string connSyncState = $"data source={SyncStateServer};initial catalog={SyncStateDb};persist security info=True;user id={SyncStateUser};password={SyncStatePwd};MultipleActiveResultSets=True;App=IOB-WIN-NEXT"; + + // gestione command timeout da https://erikej.github.io/sqlclient/2020/10/26/sqlclient-commandtimeout-preview.html + if (!string.IsNullOrEmpty(SyncStateCTout)) + { + connSyncState = $"{connSyncState};Command Timeout={SyncStateCTout}"; + } + + // eccezione: NON TROVA EntityFramework 6.0.0 o successivo... why?!? + dbProxy = new DbProxy(connSyncState); + + lastPING = DateTime.Now.AddHours(-1); + } + + #endregion Public Constructors + + #region Public Methods + + /// + /// Implementazione custom esecuzione task specifici + /// + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + // unico task ammissibile: fare un SYNC forzato... + Dictionary taskDone = new Dictionary(); + if (task2exe != null) + { + // controllo se memMap != null... + if (memMap != null) + { + bool taskOk = false; + string taskVal = ""; + // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + // controllo sulla KEY... + switch (tName) + { + case taskType.syncDbData: + lgInfo($"executeTasks --> syncDbData"); + // effettua sync + refreshElencoStati(); + + break; + + default: + taskVal = $"IobIcoelDb | taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + lgInfo($"IobIcoelDb | chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + } + } + } + } + lastReadPLC = DateTime.Now; + return taskDone; + } + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + // valore non presente in vers default... se gestito fare override + Dictionary outVal = new Dictionary(); + // recupero da DB locale stato sync attuale + var elencoSyncStateCurr = dbProxy.DataController.SyncStateGetAll(); + foreach (var item in elencoSyncStateCurr) + { + saveValue(ref outVal, $"{item.TableName}_NumRec", item.NumRec); + saveValue(ref outVal, $"{item.TableName}_NumRecIn", item.NumRecIn); + saveValue(ref outVal, $"{item.TableName}_LastIdx", item.LastIdx); + saveValue(ref outVal, $"{item.TableName}_LastIdxIn", item.LastIdxIn); + } + + // aggiungo anche i campi currData + var currData = dbProxy.DataController.CurrDataGetAll(); + foreach (var item in currData) + { + saveValue(ref outVal, item.Topic, (double)item.CurrVal); + } + + lastReadPLC = DateTime.Now; + return outVal; + } + + /// + /// Effettua processing CUSTOM x Icoel: + /// - recupera elenco batch delle 2 linee + /// - invia al sistema + /// + public override void processCustomTaskLF() + { + lgInfo($"Richiesto processCustomTaskLF"); + // effettua sync + refreshElencoStati(); + lastReadPLC = DateTime.Now; + } + + /// + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + if (connectionOk) + { + B_input = 1; + currDispData.semIn = Semaforo.SV; + + if (dbProxy != null && elencoSyncState != null && elencoSyncState.Count > 0) + { + B_input += (1 << 1); + } + + // accodo NON emergenza + B_input += (1 << 7); + } + else + { + B_input = 0; + currDispData.semIn = Semaforo.SR; + } + } + + /// + /// Override connessione + /// + public override void tryConnect() + { + if (!connectionOk) + { + // controllo che il ping sia stato tentato almeno pingTestSec fa... + if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) + { + if (verboseLog || periodicLog) + { + lgInfo("IcoelSoap: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // se passa il ping faccio il resto... + if (testPingMachine == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + if (dbProxy != null) + { + elencoSyncState = dbProxy.DataController.SyncStateDoImportAll(); + + if (elencoSyncState != null && elencoSyncState.Count > 0) + { + parentForm.commPlcActive = false; + connectionOk = true; + } + } + // refresh stato connessione!!! + if (connectionOk) + { + queueInEnabCurr = true; + if (adpRunning) + { + lgInfo("Connessione OK"); + lastReadPLC = DateTime.Now; + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal($"Errore nella connessione all'adapter IcoelSoap: {szStatusConnection}{Environment.NewLine}{exc}"); + connectionOk = false; + lgInfo($"Eccezione in TryConnect, Adapter IcoelSoap NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (verboseLog || periodicLog) + { + lgInfo($"Attenzione: IcoelSoap controllo PING fallito per IP {cIobConf.cncPingAddr}"); + } + } + } + } + else + { + needRefresh = true; + } + } + + public override void tryDisconnect() + { + // registro solo che è disconnesso + connectionOk = false; + queueInEnabCurr = false; + } + + #endregion Public Methods + + #region Protected Properties + + protected EgwProxy.Icoel.DbProxy dbProxy { get; set; } = null; + + /// + /// Stato di sync delle tab gestite + /// + protected List elencoSyncState { get; set; } = new List(); + + #endregion Protected Properties + + #region Private Methods + + private void refreshElencoStati() + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + elencoSyncState = dbProxy.DataController.SyncStateDoImportAll(); + sw.Stop(); + lastReadPLC = DateTime.Now; + lgInfo($"DB: esecuzione task dbProxy.DataController.SyncStateGetAll() in {sw.ElapsedMilliseconds} ms"); + + if (elencoSyncState != null) + { + foreach (var item in elencoSyncState) + { + lgTrace($"TAB: {item.TableName} | IdxIN / IdxLocal {item.LastIdxIn} / {item.LastIdx} | NumIn / NumLocal {item.NumRecIn} / {item.NumRec}"); + } + } + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/IOB-WIN-SQL/IobSql/SqlServLantek.cs b/IOB-WIN-SQL/IobSql/SqlServLantek.cs new file mode 100644 index 00000000..64007b8f --- /dev/null +++ b/IOB-WIN-SQL/IobSql/SqlServLantek.cs @@ -0,0 +1,523 @@ +using EgwProxy.SqlDb.Controllers; +using EgwProxy.SqlDb.DbModels; +using IOB_UT_NEXT; +using MapoSDK; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.NetworkInformation; +using static IOB_UT_NEXT.CustomObj; + +namespace IOB_WIN_SQL.IobSql +{ + /// + /// Adapter specializzato per LANTEK e le chiamate tramite DB per i dati + /// - PODL (ordini MES --> MACCHINA) + /// - ProdLog (da NestingDaLantek + RigheNestingDaLantek) + /// + + public class SqlServLantek : Iob.GenericNext + { + #region Public Constructors + + /// + /// Costruttore dell'IOB DB LANTEK + /// + /// AdapterForm chiamante + /// Configurazione IOB per avvio + public SqlServLantek(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + DateTime adesso = DateTime.Now; + string SyncStateServ = getOptPar("SyncStateServer"); + string SyncStateDb = getOptPar("SyncStateDb"); + string SyncStateUser = getOptPar("SyncStateUser"); + string SyncStatePwd = getOptPar("SyncStatePwd"); + string SyncStateCTout = getOptPar("SyncStateCTout"); + string VetoReadSec = getOptPar("VetoReadSec"); + string VetoSyncSec = getOptPar("VetoSyncSec"); + string sFullPodlUrl = getOptPar("FullPodlUrl"); + + setupSpecialParams(); + + string connSyncState = $"data source={SyncStateServ};initial catalog={SyncStateDb};persist security info=True;user id={SyncStateUser};password={SyncStatePwd};MultipleActiveResultSets=True;App=IOB-WIN-NEXT"; + + // gestione command timeout da https://erikej.github.io/sqlclient/2020/10/26/sqlclient-commandtimeout-preview.html + if (!string.IsNullOrEmpty(SyncStateCTout)) + { + connSyncState = $"{connSyncState};Command Timeout={SyncStateCTout}"; + } + if (!string.IsNullOrEmpty(VetoReadSec)) + { + int.TryParse(VetoReadSec, out vetoReadDbSec); + } + if (!string.IsNullOrEmpty(VetoSyncSec)) + { + int.TryParse(VetoSyncSec, out VetoSyncDbSec); + } + if (!string.IsNullOrEmpty(sFullPodlUrl)) + { + bool.TryParse(sFullPodlUrl, out FullPodlUrl); + } + + // avvio DB controller + dbProxy = new DbController(connSyncState); + + lastPING = DateTime.Now.AddHours(-1); + } + + #endregion Public Constructors + + #region Public Methods + + /// + /// Implementazione custom esecuzione task specifici + /// + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + DateTime adesso = DateTime.Now; + // unico task ammissibile: fare un SYNC forzato... + Dictionary taskDone = new Dictionary(); + if (task2exe != null) + { + // controllo se memMap != null... + if (memMap != null) + { + bool taskOk = false; + string taskVal = ""; + // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + // controllo sulla KEY... + switch (tName) + { + case taskType.setComm: + case taskType.syncDbData: + lgInfo($"executeTasks --> {tName}"); + // per prima cosa recupero elenco PODL attivi x la macchina + List listaPODL = new List(); + bool okPodl = false; + var rawListPODL = callUrl(urlGetCurrPODL, false); + if (!string.IsNullOrEmpty(rawListPODL)) + { + try + { + listaPODL = JsonConvert.DeserializeObject>(rawListPODL); + okPodl = listaPODL.Count > 0; + } + catch (Exception exc) + { + lg.Error($"Errore: chiamata elenco PODL ha restituito errore{Environment.NewLine}{exc}"); + } + } + else + { + lg.Error($"Errore: chiamata elenco PODL ({urlGetCurrPODL}) ha restituito valore vuoto"); + } + if (okPodl) + { + //mando elenco PODL... + List CurrPodlReq = listaPODL + .Select(x => new MesPODLReqModel() + { + Attivabile = x.Attivabile, + CodArticolo = x.CodArticolo, + CodCli = x.CodCli, + CodGruppo = x.CodGruppo, + DueDate = x.DueDate ?? DateTime.Now, + IdxMacchina = x.IdxMacchina, + IdxODL = x.IdxOdl, + IdxPromessa = x.IdxPromessa, + InsertDate = x.InsertDate, + KeyBCode = x.KeyBCode, + KeyRichiesta = x.KeyRichiesta, + Note = x.Note, + NumPezzi = x.NumPezzi, + Priorita = x.Priorita, + PzPallet = x.PzPallet, + TCAssegnato = x.Tcassegnato + }) + .ToList(); + // scrivo i record richiesti + bool fatto = dbProxy.MesPodlWriteReq(CurrPodlReq); + if (fatto) + { + taskVal = $"EXECUTED task: {item.Key} / {item.Value}"; + // registro evento chiamata scrittura in syncState... + string tabName = item.Key; + var currSyncState = elencoSyncState.FirstOrDefault(x => x.TableName == tabName); + // verifico x registrare azione + if (currSyncState == null) + { + currSyncState = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabName, + Note = "Init" + }; + } + else + { + var lastRec = CurrPodlReq.OrderBy(x => x.IdxPromessa).LastOrDefault(); + currSyncState.LastIdx = lastRec != null ? lastRec.IdxPromessa : -1; + currSyncState.Note = $"Esecuzione {tabName} per {CurrPodlReq.Count} rec | last code: {currSyncState.LastIdx}"; + currSyncState.LastUpdate = adesso; + } + // salvo sync... + dbProxy.SyncStateUpsert(currSyncState); + } + + // effettua sync scrivendo i dati in export (PODL) + execExportAll(); + } + + break; + + default: + taskVal = $"IobSqlServLantek | taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + lgInfo($"IobSqlServLantek | chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + } + // aggiungo task! + taskDone.Add(item.Key, taskVal); + } + } + } + lastReadPLC = DateTime.Now; + return taskDone; + } + + /// + /// Recupero dati dinamici... FAKE! + /// + public override Dictionary getDynData() + { + DateTime adesso = DateTime.Now; + + // dizionario vuoto / gestito da altro adapter file-based + Dictionary outVal = new Dictionary(); + + lastReadPLC = DateTime.Now; + return outVal; + } + + /// + /// Effettua processing CUSTOM: + /// - esegue tutti gli import + /// + public override void processCustomTaskLF() + { + lgInfo($"Richiesto processCustomTaskLF"); + // effettua sync + execExportAll(); + execImportAll(); + lastReadPLC = DateTime.Now; + } + + /// + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + DateTime adesso = DateTime.Now; + if (connectionOk) + { + // controllo veto checkDB + if (adesso > vetoDataRead) + { + // predispongo prox veto... + vetoDataRead = adesso.AddSeconds(vetoReadDbSec); + if (adesso > vetoDataSync) + { + // effettua sync + execImportAll(); + vetoDataSync = adesso.AddSeconds(VetoSyncDbSec); + } + + // semaforo + currDispData.semIn = Semaforo.SV; + // recupero syncState + elencoSyncState = dbProxy.SyncStateGetAll(); + // verifico ProdData e processo + bool sentProdData = processProdDataTable(adesso); + } + } + else + { + B_input = 0; + currDispData.semIn = Semaforo.SR; + } + } + + /// + /// Override connessione + /// + public override void tryConnect() + { + if (!connectionOk) + { + // controllo che il ping sia stato tentato almeno pingTestSec fa... + if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) + { + if (verboseLog || periodicLog) + { + lgInfo("SqlDb LANTEK: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // se passa il ping faccio il resto... + if (testPingMachine == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + if (dbProxy != null) + { + elencoSyncState = dbProxy.SyncStateDoImportAll(); + + if (elencoSyncState != null && elencoSyncState.Count > 0) + { + parentForm.commPlcActive = false; + connectionOk = true; + } + } + // refresh stato connessione!!! + if (connectionOk) + { + queueInEnabCurr = true; + if (adpRunning) + { + lgInfo("Connessione OK"); + lastReadPLC = DateTime.Now; + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal($"Errore nella connessione all'adapter SqlDb LANTEK: {szStatusConnection}{Environment.NewLine}{exc}"); + connectionOk = false; + lgInfo($"Eccezione in TryConnect, Adapter SqlDb LANTEK NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (verboseLog || periodicLog) + { + lgInfo($"Attenzione: SqlDb LANTEK controllo PING fallito per IP {cIobConf.cncPingAddr}"); + } + } + } + } + else + { + needRefresh = true; + } + } + + public override void tryDisconnect() + { + // registro solo che è disconnesso + connectionOk = false; + queueInEnabCurr = false; + } + + #endregion Public Methods + + #region Protected Fields + + protected bool FullPodlUrl = false; + protected int vetoReadDbSec = 3; + + protected int VetoSyncDbSec = 20; + + #endregion Protected Fields + + #region Protected Properties + + protected DbController dbProxy { get; set; } = null; + + /// + /// Stato di sync delle tab gestite + /// + protected List elencoSyncState { get; set; } = new List(); + + #endregion Protected Properties + + #region Private Methods + + /// + /// Esegue task EXPORT (MES PODL to MACHINE) + /// + private void execExportAll() + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + elencoSyncState = dbProxy.SyncStateDoExportAll(); + sw.Stop(); + DateTime adesso = DateTime.Now; + lastReadPLC = adesso; + lgInfo($"DB: esecuzione task dbProxy.SyncStateDoExportAll() in {sw.ElapsedMilliseconds} ms"); + + if (elencoSyncState != null) + { + // registro evento chiamata scrittura in syncState... + string tabName = "ExportAll"; + var currSyncState = elencoSyncState.FirstOrDefault(x => x.TableName == tabName); + // verifico x registrare azione + if (currSyncState == null) + { + currSyncState = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabName, + Note = "Init" + }; + } + else + { + // calcolo lastIDX valore da datetime + int valInt = -1; + var nowString = $"{adesso:HHmmss}"; + int.TryParse(nowString, out valInt); + currSyncState.LastIdx = valInt; + currSyncState.Note = $"Esecuzione {tabName} | DT code: {currSyncState.LastIdx}"; + currSyncState.LastUpdate = adesso; + } + // salvo sync... + dbProxy.SyncStateUpsert(currSyncState); + foreach (var item in elencoSyncState) + { + lgTrace($"TAB {item.TableName} | LastIdx {item.LastIdx} | Note {item.Note} | Last Upd {item.LastUpdate}"); + } + } + } + + /// + /// Esegue task IMPORT (MES PODL to MACHINE) + /// + private void execImportAll() + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + elencoSyncState = dbProxy.SyncStateDoImportAll(); + sw.Stop(); + lastReadPLC = DateTime.Now; + lgInfo($"DB: esecuzione task dbProxy.SyncStateDoImportAll() in {sw.ElapsedMilliseconds} ms"); + + if (elencoSyncState != null) + { + foreach (var item in elencoSyncState) + { + lgTrace($"TAB {item.TableName} | LastIdx {item.LastIdx} | Note {item.Note} | Last Upd {item.LastUpdate}"); + } + } + } + + /// + /// Esegue processing + invio dati tab ProdData + /// + /// + /// + private bool processProdDataTable(DateTime adesso) + { + bool fatto = false; + string tabNameIn = "ProdData"; + string tabNameOut = "ProdDataToMes"; + // cerco info sui SignLog (ToMes e letti) + var currSignLogRead = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameIn); + // se nullo inizializzo + if (currSignLogRead == null) + { + currSignLogRead = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameIn, + Note = "Init" + }; + } + var currSignLogSent = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameOut); + // se nullo inizializzo + if (currSignLogSent == null) + { + currSignLogSent = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameOut, + Note = "Init" + }; + } + // verifica se ci siano dati da trasmettere (sui valori LastIdx) + if (currSignLogRead.LastIdx > currSignLogSent.LastIdx) + { + // recupero i dati dal DB... + var data2send = dbProxy.MachProdDataGetNew(currSignLogSent.LastIdx); + // se ho dati preparo invio + if (data2send != null && data2send.Count > 0) + { + foreach (var sLog2send in data2send) + { + if (sLog2send.Action == "StartOrd") + { + if (FullPodlUrl) + { + // se il record è apertura PODL chiamo apertura + trySetupPODL(sLog2send.IdxPodl, true, sLog2send.DtEve, DateTime.Now); + } + else + { + trySetupPODL(0); + } + } + else if (sLog2send.Action == "EndOrd") + { + // se il record è chiusura PODL chiamo chiusura... DOPO aver cercato + // PODL --> ODL + if (FullPodlUrl) + { + tryClosePODL(sLog2send.IdxPodl, sLog2send.DtEve, DateTime.Now); + } + else + { + tryClosePODL(0); + } + } + } + } + + // aggiorno idx inviato... + currSignLogSent.Note = $"Updated from {currSignLogRead.LastIdx}"; + currSignLogSent.LastUpdate = adesso; + currSignLogSent.LastIdx = currSignLogRead.LastIdx; + fatto = true; + } + + // alla fine aggiorno i dati inviati! + dbProxy.SyncStateUpsert(currSignLogSent); + + return fatto; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/IOB-WIN-SQL/IobSql/SqlServPama.cs b/IOB-WIN-SQL/IobSql/SqlServPama.cs new file mode 100644 index 00000000..ee9abb43 --- /dev/null +++ b/IOB-WIN-SQL/IobSql/SqlServPama.cs @@ -0,0 +1,686 @@ +using EgwProxy.SqlDb.Controllers; +using EgwProxy.SqlDb.DbModels; +using IOB_UT_NEXT; +using MapoSDK; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Net.NetworkInformation; +using static IOB_UT_NEXT.CustomObj; + +namespace IOB_WIN_SQL.IobSql +{ + /// + /// Adapter specializzato per PAMA e le chiamate tramite DB per i dati + /// - PODL (ordini MES --> MACCHINA) + /// - SignLog (da stato macchina) + /// - FluxLog (da stato macchina) + /// - ProdLog (da stato Prod) + /// + public class SqlServPama : Iob.GenericNext + { + #region Public Constructors + + /// + /// Costruttore dell'IOB DB PAMA + /// + /// AdapterForm chiamante + /// Configurazione IOB per avvio + public SqlServPama(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf) + { + string SyncStateServ = getOptPar("SyncStateServer"); + string SyncStateDb = getOptPar("SyncStateDb"); + string SyncStateUser = getOptPar("SyncStateUser"); + string SyncStatePwd = getOptPar("SyncStatePwd"); + string SyncStateCTout = getOptPar("SyncStateCTout"); + string VetoReadSec = getOptPar("VetoReadSec"); + string VetoSyncSec = getOptPar("VetoSyncSec"); + string sFullPodlUrl = getOptPar("FullPodlUrl"); + + string connSyncState = $"data source={SyncStateServ};initial catalog={SyncStateDb};persist security info=True;user id={SyncStateUser};password={SyncStatePwd};MultipleActiveResultSets=True;App=IOB-WIN-NEXT"; + + // gestione command timeout da https://erikej.github.io/sqlclient/2020/10/26/sqlclient-commandtimeout-preview.html + if (!string.IsNullOrEmpty(SyncStateCTout)) + { + connSyncState = $"{connSyncState};Command Timeout={SyncStateCTout}"; + } + if (!string.IsNullOrEmpty(VetoReadSec)) + { + int.TryParse(VetoReadSec, out vetoReadDbSec); + } + if (!string.IsNullOrEmpty(VetoSyncSec)) + { + int.TryParse(VetoSyncSec, out VetoSyncDbSec); + } + if (!string.IsNullOrEmpty(sFullPodlUrl)) + { + bool.TryParse(sFullPodlUrl, out FullPodlUrl); + } + + // eccezione: NON TROVA EntityFramework 6.0.0 o successivo... why?!? + dbProxy = new DbController(connSyncState); + + lastPING = DateTime.Now.AddHours(-1); + } + + #endregion Public Constructors + + #region Public Methods + + /// + /// Implementazione custom esecuzione task specifici + /// + /// + /// + public override Dictionary executeTasks(Dictionary task2exe) + { + DateTime adesso = DateTime.Now; + // unico task ammissibile: fare un SYNC forzato... + Dictionary taskDone = new Dictionary(); + if (task2exe != null) + { + // controllo se memMap != null... + if (memMap != null) + { + bool taskOk = false; + string taskVal = ""; + // cerco task specifici: se ho startSetup --> imposto bit DBB701.DBB0.4 + foreach (var item in task2exe) + { + taskOk = false; + taskVal = ""; + // converto richiesta in enum... + taskType tName = taskType.nihil; + Enum.TryParse(item.Key, out tName); + // controllo sulla KEY... + switch (tName) + { + case taskType.setComm: + case taskType.syncDbData: + lgInfo($"executeTasks --> {tName}"); + // per prima cosa recupero elenco PODL attivi x la macchina + List listaPODL = new List(); + bool okPodl = false; + var rawListPODL = callUrl(urlGetNextPODL, false); + if (!string.IsNullOrEmpty(rawListPODL)) + { + try + { + listaPODL = JsonConvert.DeserializeObject>(rawListPODL); + okPodl = listaPODL.Count > 0; + } + catch (Exception exc) + { + lg.Error($"Errore: chiamata elenco PODL ha restituito errore{Environment.NewLine}{exc}"); + } + } + else + { + lg.Error($"Errore: chiamata elenco PODL ({urlGetNextPODL}) ha restituito valore vuoto"); + } + if (okPodl) + { + //mando elenco PODL... + List CurrPodlReq = listaPODL + .Select(x => new MesPODLReqModel() + { + Attivabile = x.Attivabile, + CodArticolo = x.CodArticolo, + CodCli = x.CodCli, + CodGruppo = x.CodGruppo, + DueDate = x.DueDate ?? DateTime.Now, + IdxMacchina = x.IdxMacchina, + IdxODL = x.IdxOdl, + IdxPromessa = x.IdxPromessa, + InsertDate = x.InsertDate, + KeyBCode = x.KeyBCode, + KeyRichiesta = x.KeyRichiesta, + Note = x.Note, + NumPezzi = x.NumPezzi, + Priorita = x.Priorita, + PzPallet = x.PzPallet, + TCAssegnato = x.Tcassegnato + }) + .ToList(); + // scrivo i record richiesti + bool fatto = dbProxy.MesPodlWriteReq(CurrPodlReq); + if (fatto) + { + taskVal = $"EXECUTED task: {item.Key} / {item.Value}"; + // registro evento chiamata scrittura in syncState... + string tabName = item.Key; + var currSyncState = elencoSyncState.FirstOrDefault(x => x.TableName == tabName); + // verifico x registrare azione + if (currSyncState == null) + { + currSyncState = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabName, + Note = "Init" + }; + } + else + { + var lastRec = CurrPodlReq.OrderBy(x => x.IdxPromessa).LastOrDefault(); + currSyncState.LastIdx = lastRec != null ? lastRec.IdxPromessa : -1; + currSyncState.Note = $"Esecuzione {tabName} per {CurrPodlReq.Count} rec | last code: {currSyncState.LastIdx}"; + currSyncState.LastUpdate = adesso; + } + // salvo sync... + dbProxy.SyncStateUpsert(currSyncState); + } + + // effettua sync scrivendo i dati in export (PODL) + execExportAll(); + } + + break; + + default: + taskVal = $"IobSqlServPama | taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC"; + lgInfo($"IobSqlServPama | chiamata senza processing: taskOk: {taskOk} | taskVal: {taskVal}"); + break; + } + // aggiungo task! + taskDone.Add(item.Key, taskVal); + } + } + } + lastReadPLC = DateTime.Now; + return taskDone; + } + + /// + /// Recupero dati dinamici... + /// + public override Dictionary getDynData() + { + DateTime adesso = DateTime.Now; + + // dizionario vuoto / faccio direttamente accodamento in FluxLog + Dictionary outVal = new Dictionary(); + + // processo ed accodo! + processFluxLogTable(adesso); + + lastReadPLC = DateTime.Now; + return outVal; + } + + /// + /// Effettua processing CUSTOM: + /// - esegue tutti gli import + /// + public override void processCustomTaskLF() + { + lgInfo($"Richiesto processCustomTaskLF"); + // effettua sync + execImportAll(); + lastReadPLC = DateTime.Now; + } + + /// + /// Effettua lettura semafori principale Parametri da + /// aggiornare x display in form + /// + public override void readSemafori(ref newDisplayData currDispData) + { + DateTime adesso = DateTime.Now; + if (connectionOk) + { + // controllo veto checkDB + if (adesso > vetoDataRead) + { + // predispongo prox veto... + vetoDataRead = adesso.AddSeconds(vetoReadDbSec); + if (adesso > vetoDataSync) + { + // effettua sync + execImportAll(); + vetoDataSync = adesso.AddSeconds(VetoSyncDbSec); + } + + // semaforo + currDispData.semIn = Semaforo.SV; + // recupero syncState + elencoSyncState = dbProxy.SyncStateGetAll(); + // verifico SignLog e processo + bool sentSignLog = processSignLogTable(adesso); + // verifico ProdData e processo + bool sentProdData = processProdDataTable(adesso); + } + } + else + { + B_input = 0; + currDispData.semIn = Semaforo.SR; + } + } + + /// + /// Override connessione + /// + public override void tryConnect() + { + if (!connectionOk) + { + // controllo che il ping sia stato tentato almeno pingTestSec fa... + if (DateTime.Now.Subtract(lastPING).TotalSeconds > utils.CRI("pingTestSec")) + { + if (verboseLog || periodicLog) + { + lgInfo("SqlDb PAMA: ConnKO - tryConnect"); + } + // in primis salvo data ping... + lastPING = DateTime.Now; + // se passa il ping faccio il resto... + if (testPingMachine == IPStatus.Success) + { + string szStatusConnection = ""; + try + { + // ora provo connessione... + parentForm.commPlcActive = true; + if (dbProxy != null) + { + elencoSyncState = dbProxy.SyncStateDoImportAll(); + + if (elencoSyncState != null && elencoSyncState.Count > 0) + { + parentForm.commPlcActive = false; + connectionOk = true; + } + } + // refresh stato connessione!!! + if (connectionOk) + { + queueInEnabCurr = true; + if (adpRunning) + { + lgInfo("Connessione OK"); + lastReadPLC = DateTime.Now; + } + } + else + { + lgError("Impossibile procedere, connessione mancante..."); + } + } + catch (Exception exc) + { + lgFatal($"Errore nella connessione all'adapter SqlDb PAMA: {szStatusConnection}{Environment.NewLine}{exc}"); + connectionOk = false; + lgInfo($"Eccezione in TryConnect, Adapter SqlDb PAMA NON running, pausa di {utils.CRI("waitRecMSec")} msec prima di ulteriori tentativi di riconnessione"); + } + } + else + { + // loggo no risposta ping ... + connectionOk = false; + if (verboseLog || periodicLog) + { + lgInfo($"Attenzione: SqlDb PAMA controllo PING fallito per IP {cIobConf.cncPingAddr}"); + } + } + } + } + else + { + needRefresh = true; + } + } + + public override void tryDisconnect() + { + // registro solo che è disconnesso + connectionOk = false; + queueInEnabCurr = false; + } + + #endregion Public Methods + + #region Protected Fields + + protected bool FullPodlUrl = false; + protected int vetoReadDbSec = 3; + + protected int VetoSyncDbSec = 20; + + #endregion Protected Fields + + #region Protected Properties + + protected DbController dbProxy { get; set; } = null; + + /// + /// Stato di sync delle tab gestite + /// + protected List elencoSyncState { get; set; } = new List(); + + #endregion Protected Properties + + #region Private Methods + + /// + /// Esegue task EXPORT (MES PODL to MACHINE) + /// + private void execExportAll() + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + elencoSyncState = dbProxy.SyncStateDoExportAll(); + sw.Stop(); + DateTime adesso = DateTime.Now; + lastReadPLC = adesso; + lgInfo($"DB: esecuzione task dbProxy.SyncStateDoExportAll() in {sw.ElapsedMilliseconds} ms"); + + if (elencoSyncState != null) + { + // registro evento chiamata scrittura in syncState... + string tabName = "ExportAll"; + var currSyncState = elencoSyncState.FirstOrDefault(x => x.TableName == tabName); + // verifico x registrare azione + if (currSyncState == null) + { + currSyncState = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabName, + Note = "Init" + }; + } + else + { + // calcolo lastIDX valore da datetime + int valInt = -1; + var nowString = $"{adesso:HHmmss}"; + int.TryParse(nowString, out valInt); + currSyncState.LastIdx = valInt; + currSyncState.Note = $"Esecuzione {tabName} | DT code: {currSyncState.LastIdx}"; + currSyncState.LastUpdate = adesso; + } + // salvo sync... + dbProxy.SyncStateUpsert(currSyncState); + foreach (var item in elencoSyncState) + { + lgTrace($"TAB {item.TableName} | LastIdx {item.LastIdx} | Note {item.Note} | Last Upd {item.LastUpdate}"); + } + } + } + + /// + /// Esegue task IMPORT (MES PODL to MACHINE) + /// + private void execImportAll() + { + Stopwatch sw = new Stopwatch(); + sw.Start(); + elencoSyncState = dbProxy.SyncStateDoImportAll(); + sw.Stop(); + lastReadPLC = DateTime.Now; + lgInfo($"DB: esecuzione task dbProxy.SyncStateDoImportAll() in {sw.ElapsedMilliseconds} ms"); + + if (elencoSyncState != null) + { + foreach (var item in elencoSyncState) + { + lgTrace($"TAB {item.TableName} | LastIdx {item.LastIdx} | Note {item.Note} | Last Upd {item.LastUpdate}"); + } + } + } + + /// + /// Esegue processing + invio dati tab SignLog + /// + /// + /// + private bool processFluxLogTable(DateTime adesso) + { + bool fatto = false; + string tabNameIn = "FluxLog"; + string tabNameOut = "FluxLogToMes"; + // cerco info sui FluxLog (ToMes e letti) + var currFluxLogRead = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameIn); + // se nullo inizializzo + if (currFluxLogRead == null) + { + currFluxLogRead = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameIn, + Note = "Init" + }; + } + var currFluxLogSent = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameOut); + // se nullo inizializzo + if (currFluxLogSent == null) + { + currFluxLogSent = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameOut, + Note = "Init" + }; + } + // verifica se ci siano dati da trasmettere (sui valori LastIdx) + if (currFluxLogRead.LastIdx > currFluxLogSent.LastIdx) + { + // recupero i dati dal DB... + var data2send = dbProxy.MachFluxLogGetNew(currFluxLogSent.LastIdx); + // se ho dati preparo invio + if (data2send != null && data2send.Count > 0) + { + string sVal = ""; + foreach (var fLog2send in data2send) + { + sVal = $"[DYNDATA] |{fLog2send.DtEvento:yyyy-MM-dd HH:mm:ss}|{fLog2send.CodFlux}|{fLog2send.Valore}"; + // chiamo accodamento con dataora corretta... + accodaFLog(sVal, qEncodeFLog(fLog2send.DtEvento, fLog2send.CodFlux, fLog2send.Valore)); + } + fatto = true; + } + + // aggiorno idx inviato... + currFluxLogSent.Note = $"Updated from {currFluxLogRead.LastIdx}"; + currFluxLogSent.LastUpdate = adesso; + currFluxLogSent.LastIdx = currFluxLogRead.LastIdx; + } + + // alla fine aggiorno i dati inviati! + dbProxy.SyncStateUpsert(currFluxLogSent); + + return fatto; + } + + /// + /// Esegue processing + invio dati tab ProdData + /// + /// + /// + private bool processProdDataTable(DateTime adesso) + { + bool fatto = false; + string tabNameIn = "ProdData"; + string tabNameOut = "ProdDataToMes"; + // cerco info sui SignLog (ToMes e letti) + var currSignLogRead = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameIn); + // se nullo inizializzo + if (currSignLogRead == null) + { + currSignLogRead = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameIn, + Note = "Init" + }; + } + var currSignLogSent = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameOut); + // se nullo inizializzo + if (currSignLogSent == null) + { + currSignLogSent = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameOut, + Note = "Init" + }; + } + // verifica se ci siano dati da trasmettere (sui valori LastIdx) + if (currSignLogRead.LastIdx > currSignLogSent.LastIdx) + { + // recupero i dati dal DB... + var data2send = dbProxy.MachProdDataGetNew(currSignLogSent.LastIdx); + // se ho dati preparo invio + if (data2send != null && data2send.Count > 0) + { + foreach (var sLog2send in data2send) + { + if (sLog2send.Action == "StartOrd") + { + if (FullPodlUrl) + { + // se il record è apertura PODL chiamo apertura + trySetupPODL(sLog2send.IdxPodl); + //trySetupPODL(sLog2send.IdxPodl, true, sLog2send.DtEve, DateTime.Now); + } + else + { + trySetupPODL(0); + } + } + else if (sLog2send.Action == "EndOrd") + { + // se il record è chiusura PODL chiamo chiusura... DOPO aver cercato + // PODL --> ODL + if (FullPodlUrl) + { + tryClosePODL(sLog2send.IdxPodl); + //tryClosePODL(sLog2send.IdxPodl, sLog2send.DtEve, DateTime.Now); + } + else + { + tryClosePODL(0); + } + } + } + } + + // aggiorno idx inviato... + currSignLogSent.Note = $"Updated from {currSignLogRead.LastIdx}"; + currSignLogSent.LastUpdate = adesso; + currSignLogSent.LastIdx = currSignLogRead.LastIdx; +#if false + var lastRec = data2send.LastOrDefault(); + if (lastRec != null) + { + // salvo in B_input ultimo valore letto... + B_input = lastRec.ValInt; + } +#endif + fatto = true; + } + + // alla fine aggiorno i dati inviati! + dbProxy.SyncStateUpsert(currSignLogSent); + + return fatto; + } + + /// + /// Esegue processing + invio dati tab SignLog + /// + /// + /// + private bool processSignLogTable(DateTime adesso) + { + bool fatto = false; + string tabNameIn = "SignLog"; + string tabNameOut = "SignLogToMes"; + // cerco info sui SignLog (ToMes e letti) + var currSignLogRead = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameIn); + // se nullo inizializzo + if (currSignLogRead == null) + { + currSignLogRead = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameIn, + Note = "Init" + }; + } + var currSignLogSent = elencoSyncState.FirstOrDefault(x => x.TableName == tabNameOut); + // se nullo inizializzo + if (currSignLogSent == null) + { + currSignLogSent = new SyncStateModel() + { + LastIdx = 0, + LastUpdate = adesso, + TableName = tabNameOut, + Note = "Init" + }; + } + // verifica se ci siano dati da trasmettere (sui valori LastIdx) + if (currSignLogRead.LastIdx > currSignLogSent.LastIdx) + { + // recupero i dati dal DB... + List data2send = dbProxy.MachSigLogGetNew(currSignLogSent.LastIdx); + // se ho dati preparo invio + if (data2send != null && data2send.Count > 0) + { + foreach (var sLog2send in data2send) + { + string currVal = getEncodSigLog(sLog2send.DtEve, sLog2send.ValInt, counterSigIN); + // verifico non sia in veto invio iniziale... + if (queueInEnabCurr) + { + // --> accodo (valore già formattato)! + QueueIN.Enqueue(currVal); + // loggo! + lgTrace(string.Format("[QUEUE-IN] {0}", currVal)); + counterSigIN++; + if (counterSigIN > 9999) + { + counterSigIN = 0; + } + } + else + { + lgDebug($"[VETO FOR QUEUE-IN] | {currVal} - MESSAGE NOT SENT | {adesso:yyyyMMdd_HHmmss}"); + checkVetoQueueIn(); + } + } + } + + // aggiorno idx inviato... + currSignLogSent.Note = $"Updated from {currSignLogRead.LastIdx}"; + currSignLogSent.LastUpdate = adesso; + currSignLogSent.LastIdx = currSignLogRead.LastIdx; + var lastRec = data2send.LastOrDefault(); + if (lastRec != null) + { + // salvo in B_input ultimo valore letto... + B_input = lastRec.ValInt; + } + fatto = true; + } + + // alla fine aggiorno i dati inviati! + dbProxy.SyncStateUpsert(currSignLogSent); + + return fatto; + } + + #endregion Private Methods + } +} \ No newline at end of file diff --git a/IOB-WIN-SQL/packages.config b/IOB-WIN-SQL/packages.config index bc12d868..708dc292 100644 --- a/IOB-WIN-SQL/packages.config +++ b/IOB-WIN-SQL/packages.config @@ -1,20 +1,25 @@  + + + - - + + + - + + - - - - + + + + - - + + \ No newline at end of file diff --git a/IOB-WIN-SQL/postBuildTgt.bat b/IOB-WIN-SQL/postBuildTgt.bat index d56896d2..2a03f9c8 100644 --- a/IOB-WIN-SQL/postBuildTgt.bat +++ b/IOB-WIN-SQL/postBuildTgt.bat @@ -73,23 +73,23 @@ REM copia script verso server remoto REM echo Debug remoto: effettuo robocopy sync (verificare remote per cliente) REM FINASSI -REM ROBOCOPY %2 \\10.150.0.1\Steamware\IOB-WIN-WPS-DEB /MIR +REM ROBOCOPY %2 \\10.150.0.1\Steamware\IOB-WIN-SQL-DEB /MIR REM Baglietto -REM ROBOCOPY %2 \\192.168.60.15\Steamware\IOB-WIN-WPS-DEB /MIR +REM ROBOCOPY %2 \\192.168.60.15\Steamware\IOB-WIN-SQL-DEB /MIR REM GIACOVELLI LOCOROTONDO -REM ROBOCOPY %2 \\192.168.1.93\Steamware\IOB-WIN-WPS-DEB /MIR +REM ROBOCOPY %2 \\192.168.1.93\Steamware\IOB-WIN-SQL-DEB /MIR REM IMI Remosa -REM ROBOCOPY %2 \\192.168.0.12\Steamware\IOB-WIN-WPS-DEB /MIR +REM ROBOCOPY %2 \\192.168.0.12\Steamware\IOB-WIN-SQL-DEB /MIR REM IOB-WIN-SIM -REM ROBOCOPY %2 \\IOB-WIN-SIMULA\Steamware\IOB-WIN-WPS-DEB /MIR +REM ROBOCOPY %2 \\IOB-WIN-SIMULA\Steamware\IOB-WIN-SQL-DEB /MIR REM IOBVPN4MACHINE -REM ROBOCOPY %2 \\10.51.90.5\Steamware\IOB-WIN-WPS-DEB /MIR -REM ROBOCOPY %2 \\10.51.90.5\Steamware\IOB-WIN-WPS-DEB /MIR /log:RobocopyTransfer.log -REM ROBOCOPY %2 Z:\IOB-WIN-WPS-DEB /MIR -REM ROBOCOPY %2 \\10.51.90.10\Steamware\IOB-WIN-WPS-DEB /MIR -ROBOCOPY %2 \\10.51.90.9\Steamware\IOB-WIN-WPS-DEB /MIR +REM ROBOCOPY %2 \\10.51.90.5\Steamware\IOB-WIN-SQL-DEB /MIR +REM ROBOCOPY %2 \\10.51.90.5\Steamware\IOB-WIN-SQL-DEB /MIR /log:RobocopyTransfer.log +REM ROBOCOPY %2 Z:\IOB-WIN-SQL-DEB /MIR +REM ROBOCOPY %2 \\10.51.90.10\Steamware\IOB-WIN-SQL-DEB /MIR +ROBOCOPY %2 \\10.51.90.9\Steamware\IOB-WIN-SQL-DEB /MIR goto END