Merge branch 'release/IobWinSQL_01'

This commit is contained in:
Samuele Locatelli
2025-01-15 19:12:38 +01:00
22 changed files with 1878 additions and 3027 deletions
+58
View File
@@ -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"]
+3 -23
View File
@@ -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:
-79
View File
@@ -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
-26
View File
@@ -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"
}
}
]
}
]
}
-79
View File
@@ -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
-27
View File
@@ -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"
}
}
]
}
]
}
+1 -21
View File
@@ -103,15 +103,6 @@
<Reference Include="EasyModbus, Version=5.6.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EasyModbusTCP.5.6.0\lib\net40\EasyModbus.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.Gomba, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.Gomba.3.6.2309.1416\lib\EgwProxy.Gomba.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.Icoel, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.Icoel.DataLayer, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.DataLayer.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.MultiCncLib, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.MultiCncLib.3.6.2207.1211\lib\EgwProxy.MultiCncLib.dll</HintPath>
</Reference>
@@ -121,18 +112,12 @@
<Reference Include="EgwProxy.OsaiCncLib.XmlSerializers, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.OsaiCncLib.3.6.2205.2015\lib\EgwProxy.OsaiCncLib.XmlSerializers.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.SqlDb, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.SqlDb.3.6.2303.1515\lib\EgwProxy.SqlDb.dll</HintPath>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
<Reference Include="FluentFTP, Version=51.1.0.0, Culture=neutral, PublicKeyToken=f4af092b1d8df44f, processorArchitecture=MSIL">
<HintPath>..\packages\FluentFTP.51.1.0\lib\net462\FluentFTP.dll</HintPath>
</Reference>
<Reference Include="krcc, Version=0.0.0.0, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
<HintPath>ExtLib\krcc.dll</HintPath>
@@ -404,9 +389,6 @@
<SubType>Form</SubType>
</Compile>
<Compile Include="IobFile\IobFileSoitaab.cs" />
<Compile Include="IobSql\SqlServLantek.cs" />
<Compile Include="IobSql\SqlServPama.cs" />
<Compile Include="IobSql\IcoelDb.cs" />
<Compile Include="Iob\Mitsubishi.cs" />
<Compile Include="MainFormNext.cs">
<SubType>Form</SubType>
@@ -666,9 +648,7 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="IobNet\" />
<Folder Include="IobRest\" />
<Folder Include="IobSoap\" />
<Folder Include="IobSql\" />
<Folder Include="prog\" />
</ItemGroup>
<ItemGroup>
+6 -2
View File
@@ -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
/// <summary>
/// Stato di sync delle tab gestite
/// </summary>
protected List<SyncStateModel> elencoSyncState { get; set; } = new List<SyncStateModel>();
protected List<SyncStateModel> elencoSyncState { get; set; } = new List<SyncStateModel>();
#endif
#endregion Protected Properties
-471
View File
@@ -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
{
/// <summary>
/// Adapter specializzato per ICOEL e le chiamate tramite WS Soap al Sizer, con libreria EgwProxy.Icoel
/// </summary>
public class IcoelSoap : Iob.GenericNext
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB Icoel SOAP
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
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
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> 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<string, string> taskDone = new Dictionary<string, string>();
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;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
// valore non presente in vers default... se gestito fare override
Dictionary<string, string> outVal = new Dictionary<string, string>();
// 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;
}
/// <summary>
/// Effettua processing CUSTOM x Icoel:
/// - recupera elenco batch delle 2 linee
/// - invia al sistema
/// </summary>
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;
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
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;
}
}
/// <summary>
/// Override connessione
/// </summary>
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
/// <summary>
/// Dizionario dati Batch correnti
/// </summary>
protected Dictionary<string, string> batchDataDict { get; set; } = new Dictionary<string, string>();
/// <summary>
/// elenco dei BAtch correntemente caricati x testing variazione
/// </summary>
protected Dictionary<int, Batch> currBatchList { get; set; }
protected Connector IcoelSizer { get; set; }
/// <summary>
/// Dizionario parametri correnti
/// </summary>
protected Dictionary<string, double> perfParamDict { get; set; } = new Dictionary<string, double>();
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
/// </summary>
/// <param name="updatedPar"></param>
protected override void plcWriteParams(ref List<objItem> 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 = "";
}
}
}
}
/// <summary>
/// recupera le variety ed i rispettivi layout e li invia al sistema MP/IO
/// </summary>
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<string>();
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
}
}
-633
View File
@@ -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
{
/// <summary>
/// Adapter base per sviluppo chiamate con servizi REST
/// </summary>
public class Base : Iob.GenericNext
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB Rest generico
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
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
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> 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<string, string> taskDone = new Dictionary<string, string>();
#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;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
// valore non presente in vers default... se gestito fare override
Dictionary<string, string> outVal = new Dictionary<string, string>();
// indico esecuzione e proseguo
lastReadPLC = DateTime.Now;
return outVal;
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
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();
}
}
/// <summary>
/// Override connessione
/// </summary>
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
/// <summary>
/// Api Url di base x chiamate REST
/// </summary>
protected string apiUrl = "http://localhost:8733";
/// <summary>
/// Num err connessioni corrente
/// </summary>
protected int connErrCur = 0;
/// <summary>
/// Max num err connesisone prima di disconnettere
/// </summary>
protected int connErrMax = 5;
/// <summary>
/// LookUpTable informazioni raccolte
/// </summary>
protected Dictionary<string, string> RestDataLUT = new Dictionary<string, string>();
/// <summary>
/// Timeout chiamate REST
/// </summary>
protected int tOutSec = 60;
#endregion Protected Fields
#region Protected Properties
/// <summary>
/// Parametri specifici Client Rest
/// </summary>
protected RestParamConf restParams { get; set; } = new RestParamConf();
#endregion Protected Properties
#region Protected Methods
/// <summary>
/// verifica stato ok ovvero connected oppure open
/// </summary>
/// <param name="currState"></param>
/// <returns></returns>
protected bool checkStateOk(System.ServiceModel.CommunicationState currState)
{
bool answ = false;
return answ;
}
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
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}");
}
}
/// <summary>
/// Esecuzione chiamata Rest tipo GET
/// </summary>
/// <param name="resource">URI da chiamare</param>
/// <param name="fastCall">Chiamata rapida (timeout rapido = 5sec)</param>
/// <returns></returns>
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;
}
/// <summary>
/// Esecuzione chiamata Rest tipo POST
/// </summary>
/// <param name="resource">URI da chiamare</param>
/// <param name="payload">Payload da allegare (già serializzato)</param>
/// <param name="fastCall">Chiamata rapida (timeout rapido = 5sec)</param>
/// <returns></returns>
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;
}
/// <summary>
/// restituisce URL della risorsa eventualmente completato con token o altro
/// </summary>
/// <param name="resName"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
/// </summary>
/// <param name="updatedPar"></param>
protected override void plcWriteParams(ref List<objItem> 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
}
}
/// <summary>
/// Esegue lettura dati + salvataggio in LUT
/// </summary>
protected virtual void refreshData()
{ }
/// <summary>
/// Recupero valore da cache LUT
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
protected string RestLutGet(string key)
{
string value = "";
if (RestDataLUT.ContainsKey(key))
{
value = RestDataLUT[key];
}
return value;
}
/// <summary>
/// Upsert in cache LUT del parametro
/// </summary>
/// <param name="key"></param>
/// <param name="value"></param>
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<RestParamConf>(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
/// <summary>
/// Conf client RestSharp standard:
/// - timeout 1 min
/// </summary>
private RestClientOptions restOptStd = new RestClientOptions { Timeout = TimeSpan.FromSeconds(60) };
#endregion Private Fields
}
}
-733
View File
@@ -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
{
/// <summary>
/// Adapter specializzato per Citizen (Colcom, MT70)
/// </summary>
public class Citizen : Base
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB SOAP della bilancia RestCitizen
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
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
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
/*---------------------------------------
* gestione execute task SPECIFICI:
* - setArt
* - setComm
* - setPzComm
*---------------------------------------*/
// Verificare il protocollo: dovrebbe togliere SOLO i task eseguiti...
Dictionary<string, string> taskDone = new Dictionary<string, string>();
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;
}
/// <summary>
/// Recupera dizionario allarmi (SE PRESENTE)
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> getAlarmData()
{
Dictionary<string, string> outVal = new Dictionary<string, string>();
// verifico SE HO allarmi attivi e nel caso li invia...
string rawData = ExecuteCallGet(GetUrlResource("GetCurrAlarm"));
string bankVal = "OK";
WarnInfo alarmResp = JsonConvert.DeserializeObject<WarnInfo>(rawData);
bankVal = (alarmResp != null && alarmResp.IsAlarm) ? alarmResp.message : "OK";
saveAlarmString(ref outVal, bankVal, "Alarms");
// verificare eventuale invio allarmi "storici"
return outVal;
}
/// <summary>
/// Recupero dati DYN, impiegando i valori della LUT...
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> 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;
}
/// <summary>
/// Recupera il progName in modalità custom...
/// </summary>
/// <returns></returns>
public override string getPrgName()
{
return RestLutGet("pName");
}
/// <summary>
/// Esegue gestioen contapezzi...
/// </summary>
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}");
}
}
}
/// <summary>
/// Override connessione
/// </summary>
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
/// <summary>
/// Struttura delle risposte alle chiamare REST specifiche
/// </summary>
internal class Responses
{
#region Internal Classes
/// <summary>
/// Struttura info restituiti da AlarmList
/// </summary>
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
}
/// <summary>
/// Struttura info JobData da inviare x setup
/// </summary>
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
}
/// <summary>
/// Struttura info restituiti x lettura Ladder
/// </summary>
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
}
/// <summary>
/// Struttura info QtyData da inviare x impostazioni quantità
/// </summary>
internal class QtyData
{
#region Public Properties
public string token { get; set; } = "";
public int value { get; set; } = 0;
#endregion Public Properties
}
/// <summary>
/// Struttura dato AlarmState (singolo, corrente)
/// </summary>
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
}
/// <summary>
/// Struttura risposta x scrittura parametri numerici (es qty)
/// </summary>
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
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
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}");
}
}
/// <summary>
/// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
/// </summary>
/// <param name="updatedPar"></param>
protected override void plcWriteParams(ref List<objItem> 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();
}
}
/// <summary>
/// Esegue lettura dati + salvataggio in LUT
/// </summary>
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<LadderIO>(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<LadderIO>(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<LadderIO>(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
/// <summary>
/// Elenco pesate attuali
/// </summary>
private List<AlarmInfo> listAllarmiCurr { get; set; } = new List<AlarmInfo>();
/// <summary>
/// CHiave redis di salvataggio ultimo set di allarmi scaricato
/// </summary>
private string redKeyAlarm { get; set; } = "";
#endregion Private Properties
#region Private Methods
/// <summary>
/// Test preliminare comunicazione Rest Citizen
/// </summary>
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<WarnInfo>(cAlarm);
cAlarm = JsonConvert.SerializeObject(sAlarm, Formatting.Indented);
lgInfo($"Call: getalarm/{token} | resp: {cAlarm}");
string allAlarm = ExecuteCallGet($"getallalarmlog/{token}");
var alarmList = JsonConvert.DeserializeObject<List<AlarmInfo>>(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);
}
}
}
/// <summary>
/// Effettua scrittura set di parametri del job e restitusice task eseguito...
/// </summary>
/// <returns></returns>
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;
}
/// <summary>
/// Test Chiamata Citizen
/// </summary>
/// <param name="urlReq"></param>
/// <returns></returns>
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
}
}
-740
View File
@@ -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
{
/// <summary>
/// Adapter specializzato per GOMA e le chiamate tramite WS Soap alla bilancia, libreria EgwProxy.Gomba
/// </summary>
public class Gomba : Iob.GenericNext
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB SOAP della bilancia GOMBA
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
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
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> 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<string, string> taskDone = new Dictionary<string, string>();
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;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
// valore non presente in vers default... se gestito fare override
Dictionary<string, string> outVal = new Dictionary<string, string>();
// controllo se ho indicato ancora che ci siano pesate già lette da inviare...
if (num2send() > 0)
{
// preparo oggetti x confronto ...
List<WeightRec> 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;
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
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;
}
}
/// <summary>
/// Override connessione
/// </summary>
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<gestWeightOut> weightArray = new List<gestWeightOut>();
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
/// <summary>
/// Proxy per connessione al SOAP webservice GOMBA
/// </summary>
protected EgwProxy.Gomba.GombaServ.lwpServiceClient gombaConn;
protected int numLastWeight = 100;
#endregion Protected Fields
#region Protected Methods
/// <summary>
/// verifica stato ok ovvero connected oppure open
/// </summary>
/// <param name="currState"></param>
/// <returns></returns>
protected bool checkStateOk(System.ServiceModel.CommunicationState currState)
{
return currState == System.ServiceModel.CommunicationState.Opened || currState == System.ServiceModel.CommunicationState.Created;
}
/// <summary>
/// Metodo da overridare x scrivere DAVVERO i parametri sul PLC
/// </summary>
/// <param name="updatedPar"></param>
protected override void plcWriteParams(ref List<objItem> 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 = "";
}
}
}
}
/// <summary>
/// Esegue richiesta PESO
/// </summary>
/// <param name="reqIN">Tipo richiesta: IN (true) / OUT (false)</param>
/// <returns></returns>
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<string, string> 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
/// <summary>
/// Effettua converione come lista cronologica pesate (singoli record IN/OUT)
/// </summary>
/// <param name="pesateOrig"></param>
/// <returns></returns>
public static List<WeightRec> ConvertPesate(List<gestWeightOut> pesateOrig)
{
List<WeightRec> answ = new List<WeightRec>();
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
/// <summary>
/// Data inizio periodo dati Bilancia:
/// - al boot impostato a -6 mesi
/// - dopo lettura impostato a data ultimi 5 record
/// </summary>
private string dataFrom
{
get => dtStartLive.ToString("dd/MM/yyyy");
}
/// <summary>
/// Data fine periodo dati Bilancia: oggi + 1gg
/// </summary>
private string dataTo
{
get => DateTime.Today.AddDays(1).ToString("dd/MM/yyyy");
}
/// <summary>
/// Data riferimento x avvio processo controllo
/// </summary>
private DateTime dtStartLive { get; set; } = DateTime.Today.AddMonths(-6);
/// <summary>
/// Gestione archivio serializzato delle pesate già processate
/// </summary>
private List<WeightRec> listPesateArchivio
{
get
{
List<WeightRec> answ = new List<WeightRec>();
string redKey = $"{redKeyPesate}:ALL";
string rawData = redisMan.getRSV(redKey);
if (!string.IsNullOrEmpty(rawData))
{
try
{
answ = JsonConvert.DeserializeObject<List<WeightRec>>(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<WeightRec>();
}
}
// 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");
}
}
/// <summary>
/// Elenco pesate attuali
/// </summary>
private List<WeightRec> listPesateCurr { get; set; } = new List<WeightRec>();
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}";
}
/// <summary>
/// Formatta record completo pesata
/// </summary>
/// <param name="rec">record completo pesate Gomba</param>
/// <param name="isIN">Indica se deve formattare i dati tipo IN (true) o OUT (false)</param>
/// <returns></returns>
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;
}
/// <summary>
/// Calcola numero pesate da inviare confrontando lista curr ed arch
/// </summary>
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
}
}
-4
View File
@@ -1,12 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EgwProxy.Gomba" version="3.6.2309.1416" targetFramework="net462" />
<package id="EgwProxy.Icoel" version="3.6.2309.708" targetFramework="net462" />
<package id="EgwProxy.MultiCncLib" version="3.6.2207.1211" targetFramework="net462" />
<package id="EgwProxy.OsaiCncLib" version="3.6.2205.2015" targetFramework="net462" />
<package id="EgwProxy.SqlDb" version="3.6.2303.1515" targetFramework="net462" />
<package id="EntityFramework" version="6.5.1" targetFramework="net462" />
<package id="FluentFTP" version="51.1.0" targetFramework="net462" />
<package id="MapoSDK" version="6.14.2411.518" targetFramework="net462" />
<package id="MathNet.Numerics" version="5.0.0" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.0" targetFramework="net462" />
+2 -2
View File
@@ -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
+178 -167
View File
@@ -1,170 +1,181 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<configSections>
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<appSettings>
<add key="appName" value="IOB-WIN-PING" />
<add key="enableTest" value="false" />
<add key="enableContapezzi" value="true" />
<add key="enableMode" value="true" />
<add key="enableOverrides" value="false" />
<add key="enableTSVC" value="true" />
<add key="enableDynData" value="false" />
<add key="enableSysInfo" value="false" />
<add key="enableAlarms" value="true" />
<add key="doStartMemDump" value="false" />
<add key="doSampleMemory" value="false" />
<add key="basePrgMemPath" value="CNCMEMUSER" />
<add key="pingMsTimeout" value="1500" />
<add key="serverPingDisabled" value="false" />
<add key="urlCallTOut" value="9999" />
<add key="urlRandWait" value="200" />
<!-- ciclo corto x invio a server: ms -->
<add key="timerIntMs" value="10" />
<add key="fastCount" value="20" />
<add key="normCount" value="200" />
<add key="slowCount" value="500" />
<add key="verySlowCount" value="3000" />
<add key="sampleMemCount" value="6000" />
<add key="waitEndCycle" value="0" />
<add key="comCheckTOut" value="10" />
<!-- watchdog, ping, check disconnesso -->
<add key="nMaxSend" value="10" />
<add key="pingTestSec" value="5" />
<add key="watchdogMaxSec" value="90" />
<add key="disconMaxSec" value="30" />
<add key="defIOB" value="2999" />
<add key="pauseSendMSec" value="2000" />
<add key="sendStartFLog" value="false" />
<!--gestione coda-->
<add key="maxQueueFLog" value="16384" />
<add key="maxQueueRawTransf" value="1024" />
<!--gestione max num errori-->
<add key="maxAliveErrors" value="1000" />
<add key="maxErroriCheck" value="300" />
<add key="maxSendErrors" value="100" />
<add key="maxReadErrors" value="20" />
<!--parametri SIM-->
<add key="waitSimPar" value="30" />
<!--<add key="waitSimPar" value="45" />-->
<!--gestione REDIS-->
<add key="RedisConn" value="localhost,abortConnect=false,ssl=false" />
<add key="RedisConnAdmin" value="localhost,abortConnect=false,ssl=false" />
<add key="redisDb" value="10" />
<!--gestione invio dati in blocchi Json-->
<add key="minJsonData" value="2" />
<add key="maxJsonData" value="100" />
<add key="maxJsonDataEv" value="25" />
<!--gestione multithread-->
<add key="sendDataByThread" value="false" />
<!--Modalità DEMO: DemoOUT indica che NON invia davvero al server e DemoIN che simula e NON legge da PLC-->
<add key="DemoIn" value="false" />
<add key="DemoInSample" value="false" />
<add key="DemoOut" value="false" />
<!--definizione invio dati molto variabili-->
<add key="SendAxPos" value="false" />
<add key="SendFeedSpeed" value="false" />
<!--Definizione avvio Adapter-->
<add key="autoLoadConf" value="true" />
<add key="autoStartOnLoad" value="true" />
<add key="startMinimized" value="false" />
<add key="windowCanMax" value="true" />
<add key="trayClose" value="true" />
<add key="autoSaveSec" value="60" />
<add key="waitRecMSec" value="60000" />
<add key="testCharSep" value="|" />
<add key="delayShowLogMs" value="500" />
<add key="vetoSeconds" value="5" />
<!--conf file-->
<add key="dataPath" value="DATA" />
<add key="dataConfPath" value="DATA\CONF" />
<add key="dataDatPath" value="DATA\DAT" />
<add key="resxPath" value="Resources" />
<add key="mainConfFile" value="MAIN.ini" />
<add key="defaultPersLayerFile" value="PersistData.dat" />
<!--<add key="simDataFile" value="SimData.dat" />-->
<!--<add key="memDumpFile" value="MemoryDump.dat" />-->
<add key="numSim" value="1" />
<add key="AUpdAsAdm" value="true" />
<add key="ConfToCloud" value="false" />
<add key="CacheConfToCloudDuratHour" value="24" />
<!--logging-->
<add key="recTime" value="true" />
<add key="verbose" value="false" />
<add key="logEvery" value="100" />
<add key="zipLogOldDay" value="1" />
<add key="maxLogDirSize" value="300" />
<add key="maxLogDays" value="400" />
<add key="numRowConsole" value="50" />
<add key="verboseLogTOut" value="60" />
<!--conf x FANUC-->
<add key="ClientSettingsProvider.ServiceUri" value="" />
<add key="pzCountDelay" value="2000" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib;libs" xmlns="urn:schemas-microsoft-com:asm.v1" />
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.1" newVersion="4.2.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.1" newVersion="4.0.4.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.1" newVersion="4.0.1.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipelines" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.1" newVersion="5.0.0.1" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Web.WebView2.WinForms" publicKeyToken="2a8ab48044d2601e" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.2903.40" newVersion="1.0.2903.40" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Web.WebView2.Core" publicKeyToken="2a8ab48044d2601e" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.0.2903.40" newVersion="1.0.2903.40" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<configSections>
<!-- For more information on Entity Framework configuration, visit http://go.microsoft.com/fwlink/?LinkID=237468 -->
<section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<appSettings>
<add key="appName" value="IOB-WIN-PING" />
<add key="enableTest" value="false" />
<add key="enableContapezzi" value="true" />
<add key="enableMode" value="true" />
<add key="enableOverrides" value="false" />
<add key="enableTSVC" value="true" />
<add key="enableDynData" value="false" />
<add key="enableSysInfo" value="false" />
<add key="enableAlarms" value="true" />
<add key="doStartMemDump" value="false" />
<add key="doSampleMemory" value="false" />
<add key="basePrgMemPath" value="CNCMEMUSER" />
<add key="pingMsTimeout" value="1500" />
<add key="serverPingDisabled" value="false" />
<add key="urlCallTOut" value="9999" />
<add key="urlRandWait" value="200" />
<!-- ciclo corto x invio a server: ms -->
<add key="timerIntMs" value="10" />
<add key="fastCount" value="20" />
<add key="normCount" value="200" />
<add key="slowCount" value="500" />
<add key="verySlowCount" value="3000" />
<add key="sampleMemCount" value="6000" />
<add key="waitEndCycle" value="0" />
<add key="comCheckTOut" value="10" />
<!-- watchdog, ping, check disconnesso -->
<add key="nMaxSend" value="10" />
<add key="pingTestSec" value="5" />
<add key="watchdogMaxSec" value="90" />
<add key="disconMaxSec" value="30" />
<add key="defIOB" value="2999" />
<add key="pauseSendMSec" value="2000" />
<add key="sendStartFLog" value="false" />
<!--gestione coda-->
<add key="maxQueueFLog" value="16384" />
<add key="maxQueueRawTransf" value="1024" />
<!--gestione max num errori-->
<add key="maxAliveErrors" value="1000" />
<add key="maxErroriCheck" value="300" />
<add key="maxSendErrors" value="100" />
<add key="maxReadErrors" value="20" />
<!--parametri SIM-->
<add key="waitSimPar" value="30" />
<!--<add key="waitSimPar" value="45" />-->
<!--gestione REDIS-->
<add key="RedisConn" value="localhost,abortConnect=false,ssl=false" />
<add key="RedisConnAdmin" value="localhost,abortConnect=false,ssl=false" />
<add key="redisDb" value="10" />
<!--gestione invio dati in blocchi Json-->
<add key="minJsonData" value="2" />
<add key="maxJsonData" value="100" />
<add key="maxJsonDataEv" value="25" />
<!--gestione multithread-->
<add key="sendDataByThread" value="false" />
<!--Modalità DEMO: DemoOUT indica che NON invia davvero al server e DemoIN che simula e NON legge da PLC-->
<add key="DemoIn" value="false" />
<add key="DemoInSample" value="false" />
<add key="DemoOut" value="false" />
<!--definizione invio dati molto variabili-->
<add key="SendAxPos" value="false" />
<add key="SendFeedSpeed" value="false" />
<!--Definizione avvio Adapter-->
<add key="autoLoadConf" value="true" />
<add key="autoStartOnLoad" value="true" />
<add key="startMinimized" value="false" />
<add key="windowCanMax" value="true" />
<add key="trayClose" value="true" />
<add key="autoSaveSec" value="60" />
<add key="waitRecMSec" value="60000" />
<add key="testCharSep" value="|" />
<add key="delayShowLogMs" value="500" />
<add key="vetoSeconds" value="5" />
<!--conf file-->
<add key="dataPath" value="DATA" />
<add key="dataConfPath" value="DATA\CONF" />
<add key="dataDatPath" value="DATA\DAT" />
<add key="resxPath" value="Resources" />
<add key="mainConfFile" value="MAIN.ini" />
<add key="defaultPersLayerFile" value="PersistData.dat" />
<!--<add key="simDataFile" value="SimData.dat" />-->
<!--<add key="memDumpFile" value="MemoryDump.dat" />-->
<add key="numSim" value="1" />
<add key="AUpdAsAdm" value="true" />
<add key="ConfToCloud" value="false" />
<add key="CacheConfToCloudDuratHour" value="24" />
<!--logging-->
<add key="recTime" value="true" />
<add key="verbose" value="false" />
<add key="logEvery" value="100" />
<add key="zipLogOldDay" value="1" />
<add key="maxLogDirSize" value="300" />
<add key="maxLogDays" value="400" />
<add key="numRowConsole" value="50" />
<add key="verboseLogTOut" value="60" />
<!--conf x FANUC-->
<add key="ClientSettingsProvider.ServiceUri" value="" />
<add key="pzCountDelay" value="2000" />
</appSettings>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="lib;libs" xmlns="urn:schemas-microsoft-com:asm.v1" />
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks.Extensions" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.1.0" newVersion="4.2.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Memory" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.2.0" newVersion="4.0.2.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Buffers" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.4.0" newVersion="4.0.4.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Compression" publicKeyToken="b77a5c561934e089" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.2.0.0" newVersion="4.2.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Bcl.AsyncInterfaces" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Channels" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Extensions.Logging.Abstractions" publicKeyToken="adb9793829ddae60" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipelines" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.1.0" newVersion="6.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Numerics.Vectors" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.5.0" newVersion="4.1.5.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Text.Json" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.ValueTuple" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.3.0" newVersion="4.0.3.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
<system.web>
<membership defaultProvider="ClientAuthenticationMembershipProvider">
<providers>
<add name="ClientAuthenticationMembershipProvider" type="System.Web.ClientServices.Providers.ClientFormsAuthenticationMembershipProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" />
</providers>
</membership>
<roleManager defaultProvider="ClientRoleProvider" enabled="true">
<providers>
<add name="ClientRoleProvider" type="System.Web.ClientServices.Providers.ClientRoleProvider, System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" serviceUri="" cacheTimeout="86400" />
</providers>
</roleManager>
</system.web>
<entityFramework>
<providers>
<provider invariantName="System.Data.SqlClient" type="System.Data.Entity.SqlServer.SqlProviderServices, EntityFramework.SqlServer" />
</providers>
</entityFramework>
</configuration>
@@ -0,0 +1,8 @@
<linker>
<assembly fullname="System.Diagnostics.DiagnosticSource">
<type fullname="System.Diagnostics.Metrics.MetricsEventSource">
<!-- Used by System.Private.CoreLib via reflection to init the EventSource -->
<method name="GetInstance" />
</type>
</assembly>
</linker>
+101 -1
View File
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="..\packages\EntityFramework.6.5.1\build\EntityFramework.props" Condition="Exists('..\packages\EntityFramework.6.5.1\build\EntityFramework.props')" />
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@@ -12,9 +13,11 @@
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
@@ -32,9 +35,82 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Remote_DEBUG|AnyCPU'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\Remote_DEBUG\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<LangVersion>7.3</LangVersion>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<ItemGroup>
<Reference Include="EgwProxy.Icoel, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.Icoel.DataLayer, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.Icoel.3.6.2309.708\lib\EgwProxy.Icoel.DataLayer.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.SqlDb, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.SqlDb.3.6.2303.1515\lib\EgwProxy.SqlDb.dll</HintPath>
</Reference>
<Reference Include="EntityFramework, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.dll</HintPath>
</Reference>
<Reference Include="EntityFramework.SqlServer, Version=6.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089, processorArchitecture=MSIL">
<HintPath>..\packages\EntityFramework.6.5.1\lib\net45\EntityFramework.SqlServer.dll</HintPath>
</Reference>
<Reference Include="MapoSDK, Version=6.14.2411.518, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MapoSDK.6.14.2411.518\lib\MapoSDK.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.9.0.0\lib\net462\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.DependencyInjection.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.9.0.0\lib\net462\Microsoft.Extensions.DependencyInjection.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=9.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Extensions.Logging.Abstractions.9.0.0\lib\net462\Microsoft.Extensions.Logging.Abstractions.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.5.3.4\lib\net46\NLog.dll</HintPath>
</Reference>
<Reference Include="StackExchange.Redis, Version=2.0.0.0, Culture=neutral, PublicKeyToken=c219ff1ca8c2ce46, processorArchitecture=MSIL">
<HintPath>..\packages\StackExchange.Redis.2.8.24\lib\net461\StackExchange.Redis.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Buffers, Version=4.0.4.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Buffers.4.6.0\lib\net462\System.Buffers.dll</HintPath>
</Reference>
<Reference Include="System.ComponentModel.DataAnnotations" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Diagnostics.DiagnosticSource, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Diagnostics.DiagnosticSource.9.0.0\lib\net462\System.Diagnostics.DiagnosticSource.dll</HintPath>
</Reference>
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Pipelines, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.IO.Pipelines.9.0.0\lib\net462\System.IO.Pipelines.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Memory.4.6.0\lib\net462\System.Memory.dll</HintPath>
</Reference>
<Reference Include="System.Numerics" />
<Reference Include="System.Numerics.Vectors, Version=4.1.5.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Numerics.Vectors.4.6.0\lib\net462\System.Numerics.Vectors.dll</HintPath>
</Reference>
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=6.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\packages\System.Runtime.CompilerServices.Unsafe.6.1.0\lib\net462\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Channels, Version=9.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Channels.9.0.0\lib\net462\System.Threading.Channels.dll</HintPath>
</Reference>
<Reference Include="System.Threading.Tasks.Extensions, Version=4.2.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\System.Threading.Tasks.Extensions.4.6.0\lib\net462\System.Threading.Tasks.Extensions.dll</HintPath>
</Reference>
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
@@ -52,12 +128,16 @@
<Compile Include="AdapterFormNext.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="IobSql\IcoelDb.cs" />
<Compile Include="IobSql\SqlServLantek.cs" />
<Compile Include="IobSql\SqlServPama.cs" />
<Compile Include="Iob\GenericNext.cs" />
<Compile Include="MainFormNext.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Content Include="ILLink\ILLink.Descriptors.LibraryBuild.xml" />
<Content Include="Resources\STEAM-IOB-WIN.xml">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
@@ -139,6 +219,7 @@
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
<TransformOnBuild>true</TransformOnBuild>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
@@ -169,4 +250,23 @@
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Target Name="AfterBuild">
<ItemGroup>
<MoveToLibFolder Include="$(OutputPath)*.dll ; $(OutputPath)*.pdb ; $(OutputPath)*.xml; $(OutputPath)*.so; $(OutputPath)*.dylib" />
</ItemGroup>
<Move SourceFiles="@(MoveToLibFolder)" DestinationFolder="$(OutputPath)lib" OverwriteReadOnlyFiles="true" />
</Target>
<Target Name="FinalBuild" AfterTargets="AfterBuild">
<Exec Command="$(ProjectDir)postBuildTgt.bat $(ConfigurationName) $(TargetDir)">
</Exec>
</Target>
<Import Project="..\packages\Microsoft.VisualStudio.SlowCheetah.4.0.50\build\Microsoft.VisualStudio.SlowCheetah.targets" Condition="Exists('..\packages\Microsoft.VisualStudio.SlowCheetah.4.0.50\build\Microsoft.VisualStudio.SlowCheetah.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>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}.</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\EntityFramework.6.5.1\build\EntityFramework.props')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\EntityFramework.6.5.1\build\EntityFramework.props'))" />
<Error Condition="!Exists('..\packages\EntityFramework.6.5.1\build\EntityFramework.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\EntityFramework.6.5.1\build\EntityFramework.targets'))" />
</Target>
<Import Project="..\packages\EntityFramework.6.5.1\build\EntityFramework.targets" Condition="Exists('..\packages\EntityFramework.6.5.1\build\EntityFramework.targets')" />
</Project>
+288
View File
@@ -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
{
/// <summary>
/// Adapter specializzato per ICOEL e le chiamate tramite DB per i dati
/// - accettazione lotti prodotto (frontiera / entrata ciliegie)
/// - export (totale per prodotti)
/// - tracciabilità (confezioni
/// </summary>
public class IcoelDb : Iob.GenericNext
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB Icoel DB
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
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
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
// unico task ammissibile: fare un SYNC forzato...
Dictionary<string, string> taskDone = new Dictionary<string, string>();
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;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
// valore non presente in vers default... se gestito fare override
Dictionary<string, string> outVal = new Dictionary<string, string>();
// 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;
}
/// <summary>
/// Effettua processing CUSTOM x Icoel:
/// - recupera elenco batch delle 2 linee
/// - invia al sistema
/// </summary>
public override void processCustomTaskLF()
{
lgInfo($"Richiesto processCustomTaskLF");
// effettua sync
refreshElencoStati();
lastReadPLC = DateTime.Now;
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
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;
}
}
/// <summary>
/// Override connessione
/// </summary>
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;
/// <summary>
/// Stato di sync delle tab gestite
/// </summary>
protected List<EgwProxy.Icoel.DataLayer.DatabaseModels.SyncStateModel> elencoSyncState { get; set; } = new List<EgwProxy.Icoel.DataLayer.DatabaseModels.SyncStateModel>();
#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
}
}
+523
View File
@@ -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
{
/// <summary>
/// Adapter specializzato per LANTEK e le chiamate tramite DB per i dati
/// - PODL (ordini MES --&gt; MACCHINA)
/// - ProdLog (da NestingDaLantek + RigheNestingDaLantek)
/// </summary>
public class SqlServLantek : Iob.GenericNext
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB DB LANTEK
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
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
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
DateTime adesso = DateTime.Now;
// unico task ammissibile: fare un SYNC forzato...
Dictionary<string, string> taskDone = new Dictionary<string, string>();
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<PODLModel> listaPODL = new List<PODLModel>();
bool okPodl = false;
var rawListPODL = callUrl(urlGetCurrPODL, false);
if (!string.IsNullOrEmpty(rawListPODL))
{
try
{
listaPODL = JsonConvert.DeserializeObject<List<PODLModel>>(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<MesPODLReqModel> 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;
}
/// <summary>
/// Recupero dati dinamici... FAKE!
/// </summary>
public override Dictionary<string, string> getDynData()
{
DateTime adesso = DateTime.Now;
// dizionario vuoto / gestito da altro adapter file-based
Dictionary<string, string> outVal = new Dictionary<string, string>();
lastReadPLC = DateTime.Now;
return outVal;
}
/// <summary>
/// Effettua processing CUSTOM:
/// - esegue tutti gli import
/// </summary>
public override void processCustomTaskLF()
{
lgInfo($"Richiesto processCustomTaskLF");
// effettua sync
execExportAll();
execImportAll();
lastReadPLC = DateTime.Now;
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
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;
}
}
/// <summary>
/// Override connessione
/// </summary>
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;
/// <summary>
/// Stato di sync delle tab gestite
/// </summary>
protected List<SyncStateModel> elencoSyncState { get; set; } = new List<SyncStateModel>();
#endregion Protected Properties
#region Private Methods
/// <summary>
/// Esegue task EXPORT (MES PODL to MACHINE)
/// </summary>
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}");
}
}
}
/// <summary>
/// Esegue task IMPORT (MES PODL to MACHINE)
/// </summary>
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}");
}
}
}
/// <summary>
/// Esegue processing + invio dati tab ProdData
/// </summary>
/// <param name="adesso"></param>
/// <returns></returns>
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
}
}
+686
View File
@@ -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
{
/// <summary>
/// Adapter specializzato per PAMA e le chiamate tramite DB per i dati
/// - PODL (ordini MES --&gt; MACCHINA)
/// - SignLog (da stato macchina)
/// - FluxLog (da stato macchina)
/// - ProdLog (da stato Prod)
/// </summary>
public class SqlServPama : Iob.GenericNext
{
#region Public Constructors
/// <summary>
/// Costruttore dell'IOB DB PAMA
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
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
/// <summary>
/// Implementazione custom esecuzione task specifici
/// </summary>
/// <param name="task2exe"></param>
/// <returns></returns>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
DateTime adesso = DateTime.Now;
// unico task ammissibile: fare un SYNC forzato...
Dictionary<string, string> taskDone = new Dictionary<string, string>();
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<PODLModel> listaPODL = new List<PODLModel>();
bool okPodl = false;
var rawListPODL = callUrl(urlGetNextPODL, false);
if (!string.IsNullOrEmpty(rawListPODL))
{
try
{
listaPODL = JsonConvert.DeserializeObject<List<PODLModel>>(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<MesPODLReqModel> 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;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
DateTime adesso = DateTime.Now;
// dizionario vuoto / faccio direttamente accodamento in FluxLog
Dictionary<string, string> outVal = new Dictionary<string, string>();
// processo ed accodo!
processFluxLogTable(adesso);
lastReadPLC = DateTime.Now;
return outVal;
}
/// <summary>
/// Effettua processing CUSTOM:
/// - esegue tutti gli import
/// </summary>
public override void processCustomTaskLF()
{
lgInfo($"Richiesto processCustomTaskLF");
// effettua sync
execImportAll();
lastReadPLC = DateTime.Now;
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
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;
}
}
/// <summary>
/// Override connessione
/// </summary>
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;
/// <summary>
/// Stato di sync delle tab gestite
/// </summary>
protected List<SyncStateModel> elencoSyncState { get; set; } = new List<SyncStateModel>();
#endregion Protected Properties
#region Private Methods
/// <summary>
/// Esegue task EXPORT (MES PODL to MACHINE)
/// </summary>
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}");
}
}
}
/// <summary>
/// Esegue task IMPORT (MES PODL to MACHINE)
/// </summary>
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}");
}
}
}
/// <summary>
/// Esegue processing + invio dati tab SignLog
/// </summary>
/// <param name="adesso"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Esegue processing + invio dati tab ProdData
/// </summary>
/// <param name="adesso"></param>
/// <returns></returns>
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;
}
/// <summary>
/// Esegue processing + invio dati tab SignLog
/// </summary>
/// <param name="adesso"></param>
/// <returns></returns>
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<MachSigLogModel> 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
}
}
+14 -9
View File
@@ -1,20 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="EgwProxy.Icoel" version="3.6.2309.708" targetFramework="net462" />
<package id="EgwProxy.SqlDb" version="3.6.2303.1515" targetFramework="net462" />
<package id="EntityFramework" version="6.5.1" targetFramework="net462" />
<package id="MapoSDK" version="6.14.2411.518" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net462" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="6.0.0" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="9.0.0" targetFramework="net462" />
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="9.0.0" targetFramework="net462" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="9.0.0" targetFramework="net462" />
<package id="Microsoft.VisualStudio.SlowCheetah" version="4.0.50" targetFramework="net462" developmentDependency="true" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
<package id="NLog" version="5.3.4" targetFramework="net462" />
<package id="Pipelines.Sockets.Unofficial" version="2.2.8" targetFramework="net462" />
<package id="StackExchange.Redis" version="2.8.24" targetFramework="net462" />
<package id="System.Buffers" version="4.5.1" targetFramework="net462" />
<package id="System.Buffers" version="4.6.0" targetFramework="net462" />
<package id="System.Diagnostics.DiagnosticSource" version="9.0.0" targetFramework="net462" />
<package id="System.IO.Compression" version="4.3.0" targetFramework="net462" />
<package id="System.IO.Pipelines" version="5.0.1" targetFramework="net462" />
<package id="System.Memory" version="4.5.4" targetFramework="net462" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net462" />
<package id="System.Runtime.CompilerServices.Unsafe" version="4.5.3" targetFramework="net462" />
<package id="System.IO.Pipelines" version="9.0.0" targetFramework="net462" />
<package id="System.Memory" version="4.6.0" targetFramework="net462" />
<package id="System.Numerics.Vectors" version="4.6.0" targetFramework="net462" />
<package id="System.Runtime.CompilerServices.Unsafe" version="6.1.0" targetFramework="net462" />
<package id="System.Runtime.InteropServices.RuntimeInformation" version="4.3.0" targetFramework="net462" />
<package id="System.Threading.Channels" version="5.0.0" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.5.4" targetFramework="net462" />
<package id="System.Threading.Channels" version="9.0.0" targetFramework="net462" />
<package id="System.Threading.Tasks.Extensions" version="4.6.0" targetFramework="net462" />
</packages>
+10 -10
View File
@@ -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