Merge branch 'Feature/Giacovelli' into SDK/Icoel

This commit is contained in:
S.E.Locatelli
2022-05-24 16:24:23 +02:00
27 changed files with 1230 additions and 191 deletions
+25
View File
@@ -9,6 +9,19 @@ namespace EgwProxy.Icoel.Test
{
#region Internal Methods
/// <summary>
/// Mostra tutte le metriche di performance ricevute
/// </summary>
/// <param name="perfMeter"></param>
internal static void DisplayPerfMeter(Dictionary<string, double> perfMeter)
{
// mostra tutti i parametri rilevati...
foreach (var item in perfMeter)
{
Console.WriteLine(item.Key, $"{item.Value:N2}");
}
}
/// <summary>
/// Generazione di una list di info sui dati variety
/// </summary>
@@ -203,6 +216,17 @@ namespace EgwProxy.Icoel.Test
Console.WriteLine("Premere un tasto x continuare...");
userInput = Console.ReadLine();
Console.WriteLine("------------ Parametri velocità rilevati ------------");
var perfMeter = IcoelSizer.GetPerfMeters();
if (perfMeter != null)
{
DisplayPerfMeter(perfMeter);
}
Console.WriteLine();
Console.WriteLine("Premere un tasto x continuare...");
userInput = Console.ReadLine();
// solo attive
Console.WriteLine("------------ solo attive ------------");
varList = IcoelSizer.GetVarietyList();
@@ -251,6 +275,7 @@ namespace EgwProxy.Icoel.Test
}
}
#endregion Private Methods
}
}
+107
View File
@@ -0,0 +1,107 @@
# Appunti impiego connesisoni ICOEL
## Icoel SOAP
Oltre ai metodi legati al batch, ci sono questi metodi x recuperare informazioni specifiche di produttività
| Metodo | Descrizione |
| ---------- | ---------- |
| GetMachineTonnesPH() | valore tonnellate/ora di velocità impianto |
| GetMachineTotalFPM() | valore frutti per minuto |
| GetMachineRodsPM() | velocità catena (carrellini / minuto) |
| GetMachineCupfill() | percentuale riempimento carrellini (100% = 1 frutto x ogni carrellino) |
## Icoel DB
Appunti sulla gestione tabelle di frontiera
### Products total
/****** Script for SelectTopNRows command from SSMS ******/
SELECT TOP (1000) [SizerBatchId]
,[Index]
,[Nome]
,[Qualities]
,[Grado]
,[Calibro]
,[NumeroFrutti]
,[Decigrammi]
FROM [IcoelExport].[dbo].[ProductsTotals]
### Entrata Ciliegie
SELECT *
FROM [frontiera].[dbo].[ENTRATACILIEGIE]
-- utilizzare codice e descrizione prodotto...
### Fine lavorazione
select top 100 *
from ProductsTotals
/*
SizerBatch id = id del batch da WS SOAP
Index = indice di prodotto FINITO, di cui ho il NOME
- prodotti da matrice: colonne = gradi, righe = taglie(sizes)
- grado a colore rosso
- do il nome prodotto rosse 26- (che sono da 22 a 26 in grado A)
- colonna qualities = è la "somma dei qualities" ovvero le colonne che passano nelcontrollo prodotto
- codice in 3 parametri, che sono a,b,c
- a = qualità interna (SEMPRE NULL x le ciliegie)
- b grado = qualità esterna del frutto, es rosse, nere, con stelo... ricircolo = scarto per cattiva disposizione
- c : calibri che mi definiscono la dimensione, tipicamente 22..32
si scrive tutto quando è chiuso il lotto
inizialmente 1 solo lotto x entrambe le linee
*/
### Conferimento MES
<code>
SELECT *
FROM DettagliConferimentoMES
where FillingId = 31729
order by PackId
</code>
/*
Numero lotto = sigla giorno
sigla lotto: incrementale giornaliero
in particoalre x il prodotto grosso --> seleziono da + fornitori (es fornitori grossi)
PackId = id univoco scatoletta
FillingId / FillingRow NON USATI: li posso ignorare, si applicano al caso "travaso" da bins ingresso / bins uscita "tipizzati" --> serve x precalibrare
scaricoId = operazione di scannerizzazione ( è il barcode letto)
codice a barre è letto x ogni etichetta di conferimento
codice e nome fornitore = grower
codice e descrizione prodotto : sono il GREZZO specifico
cdice prodotto grezzo è il "ceppo" / famiglia
sigla e numero lotto: colonna di entrata ciliegie (frontiera)
idem x data e qta entrata
*/
### Confezioni Mes
<code>
SELECT *
FROM DettagliConfezioniMES
</code>
pack id = singola cassetta/scatoal/cartone
ean = barcode in uscita
batch id / batch name = dati tracciabilità, legato ai lotti in entrata sul sizer
lane [1/2]sizerBatchId = lotti del sizer
pesoDecigram = peso netto confezionato (tolleranza +/-10g...20gr)
tabella scritta dal momento in cui arriva il cartone/cassetta per iniziare riempimento
dati live li vediamo dal sizer
*/
+24
View File
@@ -1,5 +1,6 @@
using EgwProxy.Icoel.SizerService;
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.ServiceModel;
@@ -174,6 +175,29 @@ namespace EgwProxy.Icoel.Compac
SSClient.AddBatch(batch);
}
/// <summary>
/// Recupera elenco parametri performance impianto
/// </summary>
/// <returns>Dizionario delle variabili di performance dell'impianto in formato Dictionary<string,double></returns>
internal Dictionary<string, double> GetPerfMeters()
{
Dictionary<string, double> answ = new Dictionary<string, double>();
// indicata in tonnOra
double velTonnOra = SSClient.GetMachineTonnesPH();
// velocità espressa in frutti/minuto
double velFruttiMinuto = SSClient.GetMachineTotalFPM();
// percentuale riempimento carrellini
double percRiemp = SSClient.GetMachineCupfill();
//// indicata in carrelli/minuto
//int[] velCarrMinuto = SSClient.GetMachineRodsPM();
// accodo i valori ricavati
answ.Add("VelTonnOra", velTonnOra);
answ.Add("VelFruttiMinuto", velFruttiMinuto);
answ.Add("PercRiemp", percRiemp);
return answ;
}
#endregion Internal Methods
#region Private Properties
+15
View File
@@ -38,6 +38,21 @@ namespace EgwProxy.Icoel
Client.CheckGrower(GrowerData.GrowerCode, GrowerData.GrowerName);
}
}
/// <summary>
/// Recupera array varie velocità rilevate
/// </summary>
/// <returns>Dictionary<string, double> delle velocità rilevate sul sizer</returns>
public Dictionary<string, double> GetPerfMeters()
{
Dictionary<string, double> answ = new Dictionary<string, double>();
using (var Client = new ComClient(ipAddress, tcpPort))
{
answ = Client.GetPerfMeters();
}
return answ;
}
/// <summary>
/// Invia un lotto in coda produzione sul sizer
@@ -1078,14 +1078,80 @@ Namespace CNC
''' <summary>
''' Legge o scrive le variabile Custom Macro
''' </summary>
''' <param name="bWrite">Se True SCRIVE, se False LEGGE</param>
''' <param name="MacroIndex">Indice di memoria</param>
''' <param name="Value">Matrice di valori da scrivere su scrittura o letti su lettura</param>
''' <returns>True se andata a buon fine</returns>
Public Overloads Function F_RW_Macro_Short(ByVal bWrite As Boolean, ByVal MacroIndex As Integer, ByRef Value() As Short) As Boolean
''' <summary>
''' Legge una variabile macro (#)
''' </summary>
''' <param name="nVar">Indirizzo da leggere</param>
''' <param name="dValue">Valore letto (restituito per riferimento)</param>
''' <returns>Boolean di eseguito/errore</returns>
Public Function F_Read_macro(ByVal nVar As Integer, ByRef dValue As Double) As Boolean
Const ONE_DATA_ONLY As Integer = 1
Const CUSTOM_MACRO_SIZE As Integer = 10
Dim ODBM As Focas1.ODBM
Dim MacroInfo3 As Focas1.IODBMRN3 = Nothing
Dim n_ret_code As Short
Dim sz_routine As String = "-", sz_temp As String = "", d As Double = 0.0
Try
If nVar >= &H8000 Then ' if var like 98xxx then use the other read routine .... ( :(( no comment )
n_ret_code = Focas1.cnc_rdmacror3(nLibHandle(1), nVar, ONE_DATA_ONLY, MacroInfo3)
If (n_ret_code = Focas1.EW_OK) Then ' no Fanuc error
dValue = MacroInfo3.mcr_val
Else
'Error reading parameter :
dValue = 0.0
Return False
End If ' no Fanuc error
Else ' good ole boys
' cnc_rdmacro : read custom macro variable
n_ret_code = Focas1.cnc_rdmacro(nLibHandle(1), nVar, CUSTOM_MACRO_SIZE, ODBM)
If (n_ret_code = Focas1.EW_OK) Then ' no Fanuc error
If ODBM.mcr_val = 0 And ODBM.dec_val = -1 Then ' variabile non definita
dValue = 0 '"Null"
Else
dValue = ODBM.mcr_val * (10 ^ -(ODBM.dec_val))
End If
Else
'Error reading parameter :
dValue = 0.0
Return False
End If ' no Fanuc error
End If ' var > 8000h
Catch ex As Exception
dValue = 0.0
Return False
End Try
End Function
''' <summary>
''' Legge o scrive le variabile Custom Macro
''' </summary>
''' <param name="bWrite">Se True SCRIVE, se False LEGGE</param>
''' <param name="MacroIndex">Indice di memoria</param>
''' <param name="Value">Matrice di valori da scrivere su scrittura o letti su lettura</param>
''' <returns>True se andata a buon fine</returns>
Public Overloads Function F_RW_Macro_Short(ByVal bWrite As Boolean, ByVal MacroIndex As Integer, ByRef Value() As Short) As Boolean
Dim iodbmr As Focas1.IODBMR
Dim nlength As Integer
Dim nReturn As Integer
@@ -10949,4 +10949,21 @@ Public Class Focas1
Declare Function cnc_rdetherinfo Lib "FWLIB32.DLL" _
(ByVal FlibHndl As Integer, ByRef a As Short, ByRef b As Short) As Short
'
'-------------------------------------------------------- 28 - VI - 2019 cv ------------------------------
'
' cnc_rdmacror3 :read Custom macro names(area specified)
<StructLayout(LayoutKind.Sequential, Pack:=4)>
Public Structure IODBMRN3
Public mcr_val As Double
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=36)>
Public name As String ' var name
End Structure
' read custom macro variables:read Custom macro names(area specified)
Declare Function cnc_rdmacror3 Lib "FWLIB32.DLL" _
(ByVal FlibHndl As Integer, ByVal a As Integer, ByRef b As Integer, ByRef c As IODBMRN3) As Short
End Class 'Focas1
+53 -18
View File
@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using System;
namespace IOB_UT_NEXT
{
@@ -11,7 +10,7 @@ namespace IOB_UT_NEXT
public enum boolCheckMode
{
/// <summary>
/// AND: tutte vere -> true
/// AND: tutte vere -&gt; true
/// </summary>
AND = 0,
@@ -21,17 +20,6 @@ namespace IOB_UT_NEXT
OR
}
/// <summary>
/// Modalità gestione setup macchina
/// </summary>
public enum MachineSetupMode
{
ND=0,
// Modalità Mecolpress (3 parametri IN, se variati --> porto a 1 la variabile di controllo)
MECOLPRESS = 1
}
/// <summary>
/// Elenco MODI CNC
/// </summary>
@@ -182,6 +170,17 @@ namespace IOB_UT_NEXT
VLF
}
/// <summary>
/// Modalità gestione setup macchina
/// </summary>
public enum MachineSetupMode
{
ND = 0,
// Modalità Mecolpress (3 parametri IN, se variati --> porto a 1 la variabile di controllo)
MECOLPRESS = 1
}
/// <summary>
/// StFlag32: set di 32 bit (4 word) contente semaforo di variabili
/// </summary>
@@ -281,10 +280,20 @@ namespace IOB_UT_NEXT
//FILE_XYLOG,
/// <summary>
/// adapter KAWASAKI e-controller
/// Adapter KAWASAKI e-controller
/// </summary>
KAWASAKI,
/// <summary>
/// Adapter Icoel per DB (barcode, tracciatura, produzione,...)
/// </summary>
IcoelDb,
/// <summary>
/// Adapter Icoel per WS SOAP (sizer)
/// </summary>
IcoelSoap,
/// <summary>
/// Adapter non specificato
/// </summary>
@@ -396,7 +405,7 @@ namespace IOB_UT_NEXT
SIEMENS_APROCHIM,
/// <summary>
/// Adapter SIEMENS, interfaccia versione VIPA @2001
/// Adapter SIEMENS, interfaccia versione VIPA @2001
/// </summary>
SIEMENS_AT2001,
@@ -505,9 +514,35 @@ namespace IOB_UT_NEXT
/// </summary>
SignIN,
/// <summary>
/// Salvataggio RawTransf (valori raw da decodificare a valle)
/// </summary>
RawTransf,
/// <summary>
/// Salvataggio UserLog (valori log attività utente)
/// </summary>
ULog
}
/// <summary>
/// Tipologia dato Raw Transfer (derivare da MapoSdk e togliere qui)
/// </summary>
/// serializzazione Native
/// [JsonConverter(typeof(JsonStringEnumConverter))]
/// serializzazione Newtonsoft json
/// [JsonConverter(typeof(StringEnumConverter))]
[JsonConverter(typeof(StringEnumConverter))]
public enum rawTransfType
{
ND = 0,
/// <summary>
/// Icoel: Batch info
/// </summary>
IcoelBatch,
/// <summary>
/// Icoel: Variety + layout info relative
/// </summary>
IcoelVarInfo
}
}
+2 -2
View File
@@ -59,8 +59,8 @@
<Reference Include="ICSharpCode.SharpZipLib, Version=1.3.1.9, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
<HintPath>..\packages\SharpZipLib.1.3.1\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
</Reference>
<Reference Include="MapoSDK, Version=6.14.2204.2115, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MapoSDK.6.14.2204.2115\lib\net40\MapoSDK.dll</HintPath>
<Reference Include="MapoSDK, Version=6.14.2204.2616, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\MapoSDK.6.14.2204.2616\lib\MapoSDK.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Bcl.AsyncInterfaces, Version=6.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\packages\Microsoft.Bcl.AsyncInterfaces.6.0.0\lib\net461\Microsoft.Bcl.AsyncInterfaces.dll</HintPath>
+202 -91
View File
@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace IOB_UT_NEXT
{
@@ -118,6 +117,68 @@ namespace IOB_UT_NEXT
#endregion Public Methods
}
/// <summary>
/// Classe di base per trasferimento informazioni di tipo RawTransfer
/// FixMe Todo Fare !!!: elimnare usando SDK MAPO
/// </summary>
public class BaseRawTransf
{
#region Public Properties
/// <summary>
/// Data-Ora riferimento (x ordinamento fifo)
/// </summary>
public DateTime dataRif { get; set; } = DateTime.Now;
/// <summary>
/// Messaggio in modalità raw/stringa
/// </summary>
public object mesContent { get; set; } = null;
/// <summary>
/// Tipo di messaggio trasmesso
/// </summary>
public rawTransfType mesType { get; set; } = rawTransfType.ND;
/// <summary>
/// Costruttore senza parametri
/// </summary>
public BaseRawTransf()
{
this.dataRif = DateTime.Now;
this.mesContent = "";
this.mesType = rawTransfType.ND;
}
/// <summary>
/// Costruttore oggetto
/// </summary>
/// <param name="dataRif"></param>
/// <param name="mesContent"></param>
/// <param name="mesType"></param>
public BaseRawTransf(DateTime dataRif, object mesContent, rawTransfType mesType)
{
this.dataRif = dataRif;
this.mesContent = mesContent;
this.mesType = mesType;
}
#endregion Public Properties
}
/// <summary>
/// Array valori tipo BaseRawTransf inviati come JSon
/// FixMe Todo Fare !!!: elimnare usando SDK MAPO
/// </summary>
public class rawTransfJsonPayload
{
#region Public Properties
public List<BaseRawTransf> rawTransfData { get; set; }
#endregion Public Properties
}
/// <summary>
/// Cache a tempo valori INT
/// </summary>
@@ -268,8 +329,56 @@ namespace IOB_UT_NEXT
/// </summary>
public int queueMsLen { get; set; } = 0;
/// <summary>
/// Lungh coda UserLog in uscita
/// </summary>
public int queueRawTransfLen { get; set; } = 0;
/// <summary>
/// Lungh coda UserLog in uscita
/// </summary>
public int queueUlLen { get; set; } = 0;
#endregion Public Properties
/// <summary>
/// Override metodo di equality
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public override bool Equals(object obj)
{
if (!(obj is IobWinStatus item))
return false;
if (online != item.online)
return false;
if (lastDataIn != item.lastDataIn)
return false;
if (counterIOB != item.counterIOB)
return false;
if (counterMAC != item.counterMAC)
return false;
if (queueAlLen != item.queueAlLen)
return false;
if (queueEvLen != item.queueEvLen)
return false;
if (queueFlLen != item.queueFlLen)
return false;
if (queueMsLen != item.queueMsLen)
return false;
if (queueRawTransfLen != item.queueRawTransfLen)
return false;
if (queueUlLen!= item.queueUlLen)
return false;
return true;
}
public override int GetHashCode()
{
return base.GetHashCode();
}
}
/// <summary>
@@ -398,6 +507,97 @@ namespace IOB_UT_NEXT
/// </summary>
public class sampleVect
{
#region Public Constructors
/// <summary>
/// Inizializzo l'oggetto
/// </summary>
public sampleVect()
{
// init valori default...
windSize = baseUtils.CRI("countWindSize") > 0 ? baseUtils.CRI("countWindSize") : 60;
lTime = new List<DateTime>();
lVal = new List<int>();
}
#endregion Public Constructors
#region Public Properties
/// <summary>
/// Calcola il valore mediano...
/// </summary>
public double vcMedian
{
get
{
double answ = 0;
// restituisce la mediana SE valida, altrimenti null...
if (numElem > 2 && flWindSize > windSize)
{
try
{
// calcolo mediana!
//answ = Statistics.Median(lVal.ToArray());
// rif: https://blogs.msmvps.com/deborahk/linq-mean-median-and-mode/
var sortedNumbers = lVal.OrderBy(n => n);
int numCount = lVal.Count;
int indice50 = lVal.Count / 2;
if ((numCount % 2) == 0)
{
answ = ((sortedNumbers.ElementAt(indice50) + sortedNumbers.ElementAt(indice50 - 1)) / 2);
}
else
{
answ = sortedNumbers.ElementAt(indice50);
}
}
catch
{ }
}
return answ;
}
}
/// <summary>
/// Verifica se la vc sia valida (ovvero almeno 2 valori e intervallo &gt; window richiesta)
/// </summary>
public bool vcValid
{
get
{
return (flWindSize > windSize && numElem > 1);
}
}
#endregion Public Properties
#region Public Methods
/// <summary>
/// Aggiunge un valore alla serie ed eventualmente elimina i valori superflui a garantirne
/// una finestra temporale valida
/// </summary>
/// <param name="tempo"></param>
/// <param name="valore"></param>
public void addValue(DateTime tempo, int valore)
{
lTime.Add(tempo);
lVal.Add(valore);
// verifico se siano da accorciare le serie... ovvero i 2 intervalli ENTRAMBI sono
// superiori al periodo minimo (in tal caso riduco..
while (flWindSize > windSize && slWindSize > windSize)
{
// elimino i 2 valori + vecchi
lTime.RemoveAt(0);
lVal.RemoveAt(0);
// ora ricontrollo...
}
}
#endregion Public Methods
#region Protected Fields
/// <summary>
@@ -417,21 +617,6 @@ namespace IOB_UT_NEXT
#endregion Protected Fields
#region Public Constructors
/// <summary>
/// Inizializzo l'oggetto
/// </summary>
public sampleVect()
{
// init valori default...
windSize = baseUtils.CRI("countWindSize") > 0 ? baseUtils.CRI("countWindSize") : 60;
lTime = new List<DateTime>();
lVal = new List<int>();
}
#endregion Public Constructors
#region Protected Properties
/// <summary>
@@ -485,80 +670,6 @@ namespace IOB_UT_NEXT
}
#endregion Protected Properties
#region Public Properties
/// <summary>
/// Calcola il valore mediano...
/// </summary>
public double vcMedian
{
get
{
double answ = 0;
// restituisce la mediana SE valida, altrimenti null...
if (numElem > 2 && flWindSize > windSize)
{
try
{
// calcolo mediana!
//answ = Statistics.Median(lVal.ToArray());
// rif: https://blogs.msmvps.com/deborahk/linq-mean-median-and-mode/
var sortedNumbers = lVal.OrderBy(n => n);
int numCount = lVal.Count;
int indice50 = lVal.Count / 2;
if ((numCount % 2) == 0)
{
answ = ((sortedNumbers.ElementAt(indice50) + sortedNumbers.ElementAt(indice50 - 1)) / 2);
}
else
{
answ = sortedNumbers.ElementAt(indice50);
}
}
catch
{ }
}
return answ;
}
}
/// <summary>
/// Verifica se la vc sia valida (ovvero almeno 2 valori e intervallo > window richiesta)
/// </summary>
public bool vcValid
{
get
{
return (flWindSize > windSize && numElem > 1);
}
}
#endregion Public Properties
#region Public Methods
/// <summary>
/// Aggiunge un valore alla serie ed eventualmente elimina i valori superflui a garantirne una finestra temporale valida
/// </summary>
/// <param name="tempo"></param>
/// <param name="valore"></param>
public void addValue(DateTime tempo, int valore)
{
lTime.Add(tempo);
lVal.Add(valore);
// verifico se siano da accorciare le serie... ovvero i 2 intervalli ENTRAMBI sono superiori al periodo minimo (in tal caso riduco..
while (flWindSize > windSize && slWindSize > windSize)
{
// elimino i 2 valori + vecchi
lTime.RemoveAt(0);
lVal.RemoveAt(0);
// ora ricontrollo...
}
}
#endregion Public Methods
}
/// <summary>
@@ -625,7 +736,7 @@ namespace IOB_UT_NEXT
/// <summary>
/// Codice univoco chiamata: tipo R4 (read 4 byte), W2 (write 2 Byte)
/// </summary>
/// </summary>
public string codCall;
/// <summary>
+18 -18
View File
@@ -1,39 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0"/>
<assemblyIdentity name="System.Runtime" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0"/>
<assemblyIdentity name="System.Threading.Tasks" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.6.10.0" newVersion="2.6.10.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.IO.Pipelines" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
<assemblyIdentity name="System.IO.Pipelines" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0" />
</dependentAssembly>
<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"/>
<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.Channels" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
<assemblyIdentity name="System.Threading.Channels" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.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"/>
<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>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2"/></startup></configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" /></startup></configuration>
+1 -1
View File
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="MapoSDK" version="6.14.2204.2115" targetFramework="net462" />
<package id="MapoSDK" version="6.14.2204.2616" targetFramework="net462" />
<package id="Microsoft.Bcl.AsyncInterfaces" version="6.0.0" targetFramework="net462" />
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net462" />
<package id="NLog" version="4.7.13" targetFramework="net462" />
+43 -18
View File
@@ -51,6 +51,8 @@
this.tabMes = new System.Windows.Forms.TabPage();
this.btnForceAutoOdl = new System.Windows.Forms.Button();
this.panel1 = new System.Windows.Forms.Panel();
this.label24 = new System.Windows.Forms.Label();
this.lblQueueULog = new System.Windows.Forms.Label();
this.label19 = new System.Windows.Forms.Label();
this.lblQueueAlarmLen = new System.Windows.Forms.Label();
this.label13 = new System.Windows.Forms.Label();
@@ -107,8 +109,8 @@
this.lblOutMessage3 = new System.Windows.Forms.Label();
this.lblOutMessage2 = new System.Windows.Forms.Label();
this.tabData = new System.Windows.Forms.TabControl();
this.label24 = new System.Windows.Forms.Label();
this.lblQueueULog = new System.Windows.Forms.Label();
this.label25 = new System.Windows.Forms.Label();
this.lblQueueRwTrLog = new System.Windows.Forms.Label();
this.statusStrip1.SuspendLayout();
this.tableLayoutPanel1.SuspendLayout();
this.tabMes.SuspendLayout();
@@ -364,6 +366,8 @@
// panel1
//
this.panel1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D;
this.panel1.Controls.Add(this.label25);
this.panel1.Controls.Add(this.lblQueueRwTrLog);
this.panel1.Controls.Add(this.label24);
this.panel1.Controls.Add(this.lblQueueULog);
this.panel1.Controls.Add(this.label19);
@@ -384,9 +388,28 @@
this.panel1.Location = new System.Drawing.Point(4, 6);
this.panel1.Margin = new System.Windows.Forms.Padding(2);
this.panel1.Name = "panel1";
this.panel1.Size = new System.Drawing.Size(343, 248);
this.panel1.Size = new System.Drawing.Size(343, 306);
this.panel1.TabIndex = 88;
//
// label24
//
this.label24.AutoSize = true;
this.label24.Location = new System.Drawing.Point(10, 236);
this.label24.Name = "label24";
this.label24.Size = new System.Drawing.Size(85, 13);
this.label24.TabIndex = 94;
this.label24.Text = "ULog Queue len";
//
// lblQueueULog
//
this.lblQueueULog.AutoSize = true;
this.lblQueueULog.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblQueueULog.Location = new System.Drawing.Point(104, 236);
this.lblQueueULog.Name = "lblQueueULog";
this.lblQueueULog.Size = new System.Drawing.Size(31, 13);
this.lblQueueULog.TabIndex = 95;
this.lblQueueULog.Text = "###";
//
// label19
//
this.label19.AutoSize = true;
@@ -1024,24 +1047,24 @@
this.tabData.TabIndex = 71;
this.tabData.Selected += new System.Windows.Forms.TabControlEventHandler(this.TabData_Selected);
//
// label24
// label25
//
this.label24.AutoSize = true;
this.label24.Location = new System.Drawing.Point(15, 214);
this.label24.Name = "label24";
this.label24.Size = new System.Drawing.Size(85, 13);
this.label24.TabIndex = 94;
this.label24.Text = "ULog Queue len";
this.label25.AutoSize = true;
this.label25.Location = new System.Drawing.Point(10, 213);
this.label25.Name = "label25";
this.label25.Size = new System.Drawing.Size(85, 13);
this.label25.TabIndex = 96;
this.label25.Text = "RwTr Queue len";
//
// lblQueueULog
// lblQueueRwTrLog
//
this.lblQueueULog.AutoSize = true;
this.lblQueueULog.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblQueueULog.Location = new System.Drawing.Point(105, 214);
this.lblQueueULog.Name = "lblQueueULog";
this.lblQueueULog.Size = new System.Drawing.Size(31, 13);
this.lblQueueULog.TabIndex = 95;
this.lblQueueULog.Text = "###";
this.lblQueueRwTrLog.AutoSize = true;
this.lblQueueRwTrLog.Font = new System.Drawing.Font("Microsoft Sans Serif", 8F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.lblQueueRwTrLog.Location = new System.Drawing.Point(104, 213);
this.lblQueueRwTrLog.Name = "lblQueueRwTrLog";
this.lblQueueRwTrLog.Size = new System.Drawing.Size(31, 13);
this.lblQueueRwTrLog.TabIndex = 97;
this.lblQueueRwTrLog.Text = "###";
//
// AdapterForm
//
@@ -1168,5 +1191,7 @@
private System.Windows.Forms.TabControl tabData;
private System.Windows.Forms.Label label24;
private System.Windows.Forms.Label lblQueueULog;
private System.Windows.Forms.Label label25;
private System.Windows.Forms.Label lblQueueRwTrLog;
}
}
+52 -8
View File
@@ -274,6 +274,8 @@ namespace IOB_WIN_NEXT
protected int maxFlQueue { get; set; }
protected int maxMsQueue { get; set; }
protected int maxRwTrQueue { get; set; }
protected int maxUlQueue { get; set; }
@@ -284,6 +286,8 @@ namespace IOB_WIN_NEXT
protected int qFlLen { get; set; }
protected int qMsLen { get; set; }
protected int qRTrLen { get; set; }
protected int qUlLen { get; set; }
@@ -643,6 +647,31 @@ namespace IOB_WIN_NEXT
}
}
public int rtrQueueLen
{
set
{
qRTrLen = value;
lblQueueRwTrLog.Text = qRTrLen.ToString();
showQueueData();
// se supero max precedente, ed è > 10... loggo!
if (qRTrLen > maxRwTrQueue && qRTrLen > 10)
{
maxRwTrQueue = qRTrLen;
lgInfo($"[WARN] Coda RawTransf di {value} record");
}
else
{
maxRwTrQueue--;
maxRwTrQueue = maxRwTrQueue < qRTrLen ? qRTrLen : maxRwTrQueue;
}
}
get
{
return qRTrLen;
}
}
public int ulQueueLen
{
set
@@ -1132,14 +1161,14 @@ namespace IOB_WIN_NEXT
tipoIob = tipoScelto,
optPar = optParRead,
versIOB = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(),
codIOB = CurrIOB,
codIOB = fIni.ReadString("IOB", "IOB_NAME", CurrIOB),
cncIpAddr = fIni.ReadString("CNC", "IP", "::1"),
cncPort = fIni.ReadString("CNC", "PORT", "0"),
iniFileName = iniConfFile,
cpuType = fIni.ReadString("CNC", "CPUTYPE", ""),
rack = (short)fIni.ReadInteger("CNC", "RACK", 0),
slot = (short)fIni.ReadInteger("CNC", "SLOT", 0),
serverData = new serverMapo(fIni.ReadString("SERVER", "MPIP", "::1"), fIni.ReadString("SERVER", "MPURL", "/MP/IO"), fIni.ReadString("SERVER", "CMDBASE", "/IOB/input/"), fIni.ReadString("SERVER", "CMDFLOG", "/IOB/flog/"), fIni.ReadString("SERVER", "CMDULOG", "/IOB/ulog/"), fIni.ReadString("SERVER", "CMDALIVE", "/"), fIni.ReadString("SERVER", "CMDENABLED", "/"), fIni.ReadString("SERVER", "CMDREBO", "/"), fIni.ReadString("SERVER", "CMD_ODL_STARTED", "/IOB/getCurrOdlStart/"), fIni.ReadString("SERVER", "CLI_INST", "SW_CLI"), fIni.ReadString("SERVER", "CMD_FORCLE_SPLIT_ODL", "/IOB/forceSplitOdlFull/")),
serverData = new serverMapo(fIni.ReadString("SERVER", "MPIP", "::1"), fIni.ReadString("SERVER", "MPURL", "/MP/IO"), fIni.ReadString("SERVER", "CMDBASE", "/IOB/input/"), fIni.ReadString("SERVER", "CMDFLOG", "/IOB/flog/"), fIni.ReadString("SERVER", "CMDULOG", "/IOB/ulog/"), fIni.ReadString("SERVER", "CMDALIVE", "/"), fIni.ReadString("SERVER", "CMDENABLED", "/"), fIni.ReadString("SERVER", "CMDREBO", "/"), fIni.ReadString("SERVER", "CMD_ODL_STARTED", "/IOB/getCurrOdlStart/"), fIni.ReadString("SERVER", "CLI_INST", "SW_CLI"), fIni.ReadString("SERVER", "CMD_FORCLE_SPLIT_ODL", "/IOB/forceSplitOdlFull/"), fIni.ReadString("SERVER", "CMDRAWTRANSF", "/IOB/rawTransfJson/")),
MAX_COUNTER_BLINK = Convert.ToInt32(fIni.ReadString("BLINK", "MAX_COUNTER_BLINK", "1")),
BLINK_FILT = Convert.ToInt32(fIni.ReadString("BLINK", "BLINK_FILT", "0")),
TCMaxDelayFactor = Convert.ToDouble(fIni.ReadString("OPTPAR", "TC_MAX_TC_FACTOR", "1.2").Replace(".", ",")),
@@ -1210,6 +1239,15 @@ namespace IOB_WIN_NEXT
start.Enabled = true;
break;
case tipoAdapter.IcoelDb:
iobObj = new IobIcoelDb(this, IOBConf);
start.Enabled = true;
break;
case tipoAdapter.IcoelSoap:
iobObj = new IobIcoelSoap(this, IOBConf);
start.Enabled = true;
break;
case tipoAdapter.MODBUS_TCP:
iobObj = new IobModbusTCP(this, IOBConf);
start.Enabled = true;
@@ -1280,7 +1318,7 @@ namespace IOB_WIN_NEXT
iobObj = new IobOpcUaOmronIcoel(this, IOBConf);
start.Enabled = true;
break;
case tipoAdapter.PingWatchdog:
iobObj = new IobPing(this, IOBConf);
start.Enabled = true;
@@ -1445,11 +1483,12 @@ namespace IOB_WIN_NEXT
private void refreshFormData()
{
// aggiorno visualizzazioni varie in form...
alQueueLen = iobObj.QueueAlarm.Count;
evQueueLen = iobObj.QueueIN.Count;
flQueueLen = iobObj.QueueFLog.Count;
alQueueLen = iobObj.QueueAlarm.Count;
msQueueLen = iobObj.QueueMessages.Count;
ulQueueLen = iobObj.QueueMessages.Count;
rtrQueueLen = iobObj.QueueRawTransf.Count;
ulQueueLen = iobObj.QueueULog.Count;
// aggiorno labels counters...
counterIob = $"pz IOB {iobObj.contapezziIOB}";
counterMac = $"pz PLC {iobObj.contapezziPLC}";
@@ -1458,10 +1497,12 @@ namespace IOB_WIN_NEXT
{
CodIob = iobObj.cIobConf.codIOB,
IobType = iobObj.cIobConf.tipoIob.ToString(),
queueAlLen = alQueueLen,
queueEvLen = evQueueLen,
queueFlLen = flQueueLen,
queueAlLen = alQueueLen,
queueMsLen = msQueueLen,
queueRawTransfLen = rtrQueueLen,
queueUlLen = ulQueueLen,
counterIOB = iobObj.contapezziIOB,
counterMAC = iobObj.contapezziPLC,
lastUpdate = lastIobStatus.lastUpdate,
@@ -1469,7 +1510,7 @@ namespace IOB_WIN_NEXT
lastDataIn = iobObj.lastReadPLC
};
// se diverso SALVO!
if (lastIobStatus.online != currIobStatus.online || lastIobStatus.lastDataIn != currIobStatus.lastDataIn || lastIobStatus.counterIOB != currIobStatus.counterIOB || lastIobStatus.counterMAC != currIobStatus.counterMAC || lastIobStatus.queueEvLen != currIobStatus.queueEvLen || lastIobStatus.queueFlLen != currIobStatus.queueFlLen || lastIobStatus.queueAlLen != currIobStatus.queueAlLen || lastIobStatus.queueMsLen != currIobStatus.queueMsLen)
if (!lastIobStatus.Equals(currIobStatus))
{
// aggiorno data
currIobStatus.lastUpdate = DateTime.Now;
@@ -1531,8 +1572,11 @@ namespace IOB_WIN_NEXT
{
stop.Enabled = false;
evQueueLen = 0;
alQueueLen = 0;
flQueueLen = 0;
msQueueLen = 0;
rtrQueueLen = 0;
ulQueueLen = 0;
nLine2show = utils.CRI("numRowConsole");
}
+13
View File
@@ -39,6 +39,7 @@
<add key="pauseSendMSec" value="1000" />
<!--gestione coda-->
<add key="maxQueueFLog" value="16384" />
<add key="maxQueueRawTransf" value="1024" />
<!--gestione max num errori-->
<add key="maxAliveErrors" value="1000" />
<add key="maxSendErrors" value="100" />
@@ -144,9 +145,21 @@
<basicHttpBinding>
<binding name="OPENcontrol" />
</basicHttpBinding>
<netNamedPipeBinding>
<binding name="NetNamedPipeBinding_ISizerService">
<security mode="None" />
</binding>
</netNamedPipeBinding>
<wsHttpBinding>
<binding name="WSHttpBinding_ISizerService" maxReceivedMessageSize="2147483647">
<security mode="None" />
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://192.168.20.2:8080" binding="basicHttpBinding" bindingConfiguration="OPENcontrol" contract="OpenControl.OPENcontrolPortType" name="OPENcontrol" />
<endpoint address="http://localhost:8001/SizerService/" binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_ISizerService" contract="SizerService.ISizerService" name="WSHttpBinding_ISizerService" />
<endpoint address="net.pipe://localhost/Compac/8001/SizerService" binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_ISizerService" contract="SizerService.ISizerService" name="NetNamedPipeBinding_ISizerService" />
</client>
</system.serviceModel>
</configuration>
+5 -2
View File
@@ -26,7 +26,7 @@ CMDREBO=/sendReboot.aspx?idxMacchina=
; Red: Y31.4 | Yellow: Y31.5 | Green Y31.6 | riscaldamento Y7.4 ???
;BIT0=CONN
BIT1=Y31.6
BIT2=PZCOUNT.PAR.6711
BIT2=STD.MACRO.10100
BIT3=Y31.4
BIT4=Y31.5
BIT5=Y7.4
@@ -59,7 +59,10 @@ BLINK_FILT=0
[OPTPAR]
;PZCOUNT_MODE=STD|BIT
PZCOUNT_MODE=STD.PAR.6711
;PZCOUNT_MODE=STD.PAR.6711
;PZREQ_MODE=STD.PAR.6713
PZCOUNT_MODE=STD.MACRO.10100
PZREQ_MODE=STD.MACRO.10000
PZGTOT_MODE=STD.PAR.6712
PZREQ_MODE=STD.PAR.6713
;PZCAD_MODE=STD.D.6408.DW
@@ -3,6 +3,7 @@
;Centro di lavoro OpcUa
CNCTYPE=OpcUaOmronIcoel
PING_MS_TIMEOUT=500
IOB_NAME=GIACO_ICOEL
[MACHINE]
VENDOR=ICOEL
@@ -0,0 +1,74 @@
;Configurazione IOB-WIN
[IOB]
;WebService SOAP x sizer
CNCTYPE=IcoelSoap
PING_MS_TIMEOUT=500
IOB_NAME=GIACO_ICOEL
[MACHINE]
VENDOR=ICOEL
MODEL=Impianto Ciliegie Turi
[CNC]
IP=192.168.137.50
PORT=8001
GETPRGNAME=false
[SERVER]
MPIP=http://192.168.1.14
MPURL=/MP/IO
CMDBASE=/IOB/input/
CMDFLOG=/IOB/flog/
CMDRAWTRANSF=/IOB/rawTransfJson/
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
;BIT0=CONN
;BIT1=DB60.DBB1
;BIT2=PZCOUNT.STD.DB700.DBW22
;BIT3=DB60.DBB3
;BIT4=DB60.DBB4
[BLINK]
;MAX_COUNTER_BLINK = 30
MAX_COUNTER_BLINK = 15
;bit0 = 0
;bit1 = 0
;bit2 = 1
;bit3 = 1
;bit4 = 1
;bit5 = 0
;bit6 = 0
;bit7 = 0
BLINK_FILT=0
;BLINK_FILT=28
[OPTPAR]
AUTO_CHANGE_ODL=false
CHANGE_ODL_MODE=TIME
CHANGE_ODL_HOURS=24
CHANGE_ODL_IDLE_MIN=5
PZCOUNT_MODE=Icoel
DISABLE_PZCOUNT=FALSE
ENABLE_SEND_PZC_BLOCK=TRUE
MIN_SEND_PZC_BLOCK=0
MAX_SEND_PZC_BLOCK=100
ENABLE_DYN_DATA=FALSE
FORCE_DYN_DATA=TRUE
ENABLE_DATA_FILTER=TRUE
ENABLE_CLI_RESTART=TRUE
VETO_SIG_IN=TRUE
; conf parametri memoria READ/WRITE
OPC_PARAM_CONF=GIACO_ICOEL_001.json
[BRANCH]
NAME=master
+1 -1
View File
@@ -79,6 +79,6 @@ CLI_INST=SteamWareSim
;STARTLIST=VL25
;STARTLIST=SIMUL_03
;STARTLIST=GIACO_CEDAX_01
STARTLIST=GIACO_ICOEL_001
STARTLIST=GIACO_ICOEL_002
MAXCNC=10
+9 -4
View File
@@ -87,16 +87,16 @@
<HintPath>..\packages\EasyModbusTCP.5.6.0\lib\net40\EasyModbus.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.Icoel, Version=1.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.Icoel.3.6.2205.2012\lib\EgwProxy.Icoel.dll</HintPath>
<HintPath>..\packages\EgwProxy.Icoel.3.6.2205.2018\lib\EgwProxy.Icoel.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.MultiCncLib, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.MultiCncLib.3.6.2205.2012\lib\EgwProxy.MultiCncLib.dll</HintPath>
<HintPath>..\packages\EgwProxy.MultiCncLib.3.6.2205.2319\lib\EgwProxy.MultiCncLib.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.OsaiCncLib, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.OsaiCncLib.3.6.2205.2012\lib\EgwProxy.OsaiCncLib.dll</HintPath>
<HintPath>..\packages\EgwProxy.OsaiCncLib.3.6.2205.2015\lib\EgwProxy.OsaiCncLib.dll</HintPath>
</Reference>
<Reference Include="EgwProxy.OsaiCncLib.XmlSerializers, Version=0.0.0.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\EgwProxy.OsaiCncLib.3.6.2205.2012\lib\EgwProxy.OsaiCncLib.XmlSerializers.dll</HintPath>
<HintPath>..\packages\EgwProxy.OsaiCncLib.3.6.2205.2015\lib\EgwProxy.OsaiCncLib.XmlSerializers.dll</HintPath>
</Reference>
<Reference Include="krcc, Version=0.0.0.0, Culture=neutral, processorArchitecture=x86">
<SpecificVersion>False</SpecificVersion>
@@ -194,6 +194,8 @@
<Compile Include="..\VersGen\VersGen.cs">
<Link>VersGen.cs</Link>
</Compile>
<Compile Include="IobIcoelDb.cs" />
<Compile Include="IobIcoelSoap.cs" />
<Compile Include="IobModbusTCPHelpi.cs" />
<Compile Include="IobModbusTCPCedax.cs" />
<Compile Include="IobOpcUaOmronIcoel.cs" />
@@ -305,6 +307,9 @@
<None Include="DATA\CONF\FINASSI_HELPI_01_MBlock.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="DATA\CONF\GIACO_ICOEL_002.ini">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="DATA\CONF\GT594.ini">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
+7 -1
View File
@@ -147,7 +147,7 @@ namespace IOB_WIN_NEXT
/// <param name="CMDREBO_">Comando x reboot</param>
/// <param name="CMD_ODL_STARTED_">Comando x check data avvio ODL</param>
/// <param name="CMD_FORCLE_SPLIT_ODL_">Comando x forzare split ODL</param>
public serverMapo(string MPIP_, string MPURL_ = "/MP/IO", string CMDBASE_ = "/IOB/input/", string CMDFLOG_ = "/IOB/flog/", string CMDULOG_ = "/IOB/ulog/", string CMDALIVE_ = "IOB", string CMDENABLED_ = "/IOB/enabled/", string CMDREBO_ = "/sendReboot.aspx?idxMacchina=", string CMD_ODL_STARTED_ = "/IOB/getCurrOdlStart/", string CLI_INST_ = "SteamWare", string CMD_FORCLE_SPLIT_ODL_ = "/IOB/forceSplitOdlFull/", string CMD_IDLE_TIME_ = "/IOB/getIdlePeriod/")
public serverMapo(string MPIP_, string MPURL_ = "/MP/IO", string CMDBASE_ = "/IOB/input/", string CMDFLOG_ = "/IOB/flog/", string CMDULOG_ = "/IOB/ulog/", string CMDALIVE_ = "IOB", string CMDENABLED_ = "/IOB/enabled/", string CMDREBO_ = "/sendReboot.aspx?idxMacchina=", string CMD_ODL_STARTED_ = "/IOB/getCurrOdlStart/", string CLI_INST_ = "SteamWare", string CMD_FORCLE_SPLIT_ODL_ = "/IOB/forceSplitOdlFull/", string CMD_IDLE_TIME_ = "/IOB/getIdlePeriod/", string CMDRAWTRANSFJSON_ = "/IOB/rawTransfJson/")
{
if (!string.IsNullOrEmpty(MPIP_))
{
@@ -160,6 +160,7 @@ namespace IOB_WIN_NEXT
MPURL = MPURL_;
CMDBASE = CMDBASE_;
CMDFLOG = CMDFLOG_;
CMDRAWTRANSF_JSON = CMDRAWTRANSFJSON_;
CMDULOG = CMDULOG_;
if (!string.IsNullOrEmpty(CMDBASE_))
{
@@ -241,6 +242,11 @@ namespace IOB_WIN_NEXT
/// </summary>
public string CMDULOG { get; set; } = "";
/// <summary>
/// comando base x Raw Transf LOG - salvataggio valori generici in modalità JSON payload come lista
/// </summary>
public string CMDRAWTRANSF_JSON { get; set; } = "";
/// <summary>
/// comando base x USER LOG - salvataggio parametri extra sistema MAPO in modalità JSON payload come lista
/// </summary>
+38 -7
View File
@@ -212,7 +212,7 @@ namespace IOB_WIN_NEXT
}
catch (Exception exc)
{
lgError(exc, "Errore in contapezzi FANUC");
lgError(exc, "Errore in contapezzi FANUC 01");
}
}
// finisco INIT ADAPTER
@@ -587,6 +587,23 @@ namespace IOB_WIN_NEXT
// salvo valore
answ = outputVal.ToString();
}
// 2022.05.23 gestione MACRO da testare (Jetco)
else if (memAddr.StartsWith("MACRO."))
{
lgTrace($"Decodifica memoria MACRO | memAddr: {memAddr}");
// recupero parametro...
int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr);
// processo parametro
stopwatch.Restart();
double macroVal = 0;
FANUC_ref.F_Read_macro(cntAddr, ref macroVal);
if (utils.CRB("recTime"))
{
TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MACRO", 5), stopwatch.ElapsedTicks);
}
// salvo valore
answ = macroVal.ToString();
}
// altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW
else
{
@@ -1012,7 +1029,6 @@ namespace IOB_WIN_NEXT
{
cntAddr = 6711;
}
// processo parametro contapezzi (lavorati)
stopwatch.Restart();
FANUC_ref.F_RW_Param_Integer(false, cntAddr, 3, ref outputVal);
@@ -1020,22 +1036,38 @@ namespace IOB_WIN_NEXT
{
TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-PAR", 4), stopwatch.ElapsedTicks);
}
// salvo ultimo conteggio rilevato
int newVal = -1;
Int32.TryParse(outputVal.ToString(), out newVal);
contapezziPLC = newVal > -1 ? newVal : contapezziPLC;
}
// 2022.05.23 gestione MACRO da testare (Jetco)
else if (memAddr.StartsWith("MACRO."))
{
lgTrace($"Decodifica memoria MACRO | memAddr: {memAddr}");
// recupero parametro...
int.TryParse(memAddr.Replace("MACRO.", ""), out cntAddr);
// processo parametro
stopwatch.Restart();
double macroVal = 0;
FANUC_ref.F_Read_macro(cntAddr, ref macroVal);
if (utils.CRB("recTime"))
{
TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MACRO", 5), stopwatch.ElapsedTicks);
}
// salvo ultimo conteggio rilevato
int newVal = -1;
Int32.TryParse($"{macroVal}", out newVal);
contapezziPLC = newVal > -1 ? newVal : contapezziPLC;
}
// altrimenti se legge da area memoria specifica leggo da li... formto tipo STD.D.1604.DW
else
{
memAddressFanuc areaCounter = new memAddressFanuc(memAddr);
if (isVerboseLog)
{
lgInfo("[0] area memoria: {0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType);
}
// leggo!
stopwatch.Restart();
// switch x tipo dati --> tipo lettura... e salvo ultimo conteggio rilevato
@@ -1076,7 +1108,6 @@ namespace IOB_WIN_NEXT
{
TimingData.addResult(cIobConf.codIOB, string.Format("R-{0}.{1}.{2}", areaCounter.mType, areaCounter.mPos, areaCounter.vType), stopwatch.ElapsedTicks);
}
// salvo...
int newVal = -1;
Int32.TryParse(outputVal.ToString(), out newVal);
@@ -1093,7 +1124,7 @@ namespace IOB_WIN_NEXT
}
catch (Exception exc)
{
lgError(exc, "Errore in contapezzi FANUC");
lgError(exc, "Errore in contapezzi FANUC 02");
connectionOk = false;
}
}
+176 -6
View File
@@ -386,6 +386,12 @@ namespace IOB_WIN_NEXT
/// </summary>
public ConcurrentQueue<string> QueueMessages = new ConcurrentQueue<string>();
/// <summary>
/// Oggetto della coda degli elementi di tipo RawTransf (e non ancora trasmessi)
/// NB: sono salvati serializzati come stringhe
/// </summary>
public ConcurrentQueue<string> QueueRawTransf = new ConcurrentQueue<string>();
/// <summary>
/// Coda valori LOG UTENTE (da non sottocampionare come samples)...
/// </summary>
@@ -753,6 +759,10 @@ namespace IOB_WIN_NEXT
/// Coda massima ammessa per FLog (se <=0 disattivata...)
/// </summary>
protected int maxQueueFLog { get; set; } = utils.CRI("maxQueueFLog");
/// <summary>
/// Coda massima ammessa per FLog (se <=0 disattivata...)
/// </summary>
protected int maxQueueRawTransf { get; set; } = utils.CRI("maxQueueRawTransf");
/// <summary>
/// Valore MINIMO limite x decidere invio di dati come array Json
@@ -1107,6 +1117,11 @@ namespace IOB_WIN_NEXT
/// </summary>
public int counterSigIN { get; set; }
/// <summary>
/// Contatore x invio dati RawTransf
/// </summary>
public int counterRawTransf { get; set; }
/// <summary>
/// Contatore x invio dati UserLog
/// </summary>
@@ -2083,10 +2098,11 @@ namespace IOB_WIN_NEXT
// svuoto code se richiesto
if (resetQueue)
{
QueueAlarm = new ConcurrentQueue<string>();
QueueIN = new ConcurrentQueue<string>();
QueueFLog = new ConcurrentQueue<string>();
QueueAlarm = new ConcurrentQueue<string>();
QueueMessages = new ConcurrentQueue<string>();
QueueRawTransf = new ConcurrentQueue<string>();
QueueULog = new ConcurrentQueue<string>();
}
// imposto contatori blink a zero...
@@ -2212,7 +2228,66 @@ namespace IOB_WIN_NEXT
}
}
// <summary>
/// <summary>
/// Processo la coda RawTransf...
/// </summary>
private void svuotaCodaRawTransf()
{
// verifico SE la coda abbia dei valori...
if (QueueRawTransf.Count > 0)
{
// invio pacchetto di dati (max da conf)
for (int i = 0; i < nMaxSend; i++)
{
// SE ho qualcosa in coda...
if (QueueRawTransf.Count > 0)
{
string currVal = "";
if (MPOnline)
{
if (IobOnline)
{
List<string> listaValori = new List<string>();
// se ho + di maxJsonData elementi --> invio un set di dati alla volta
if (QueueRawTransf.Count > maxJsonData)
{
// prendoi primi maxJsonDataValori
for (int j = 0; j < maxJsonData; j++)
{
QueueRawTransf.TryDequeue(out currVal);
listaValori.Add(currVal);
}
sendDataBlock(urlType.RawTransf, listaValori);
}
else
{
// invio in blocco
listaValori = QueueRawTransf.ToList();
// invio
sendDataBlock(urlType.RawTransf, listaValori);
// svuoto!
QueueRawTransf = new ConcurrentQueue<string>();
}
}
else
{
break;
}
}
else
{
break;
}
}
else
{
break;
}
}
}
}
/// <summary>
/// Processo la coda UserLog...
/// </summary>
private void svuotaCodaULog()
@@ -2302,6 +2377,7 @@ namespace IOB_WIN_NEXT
// invio con thread separato...
Task taskSigIN = Task.Run(() => svuotaCodaSignIN());
Task taskFLog = Task.Run(() => svuotaCodaFLog());
Task taskRawTransf = Task.Run(() => svuotaCodaRawTransf());
Task taskULog = Task.Run(() => svuotaCodaULog());
}
else
@@ -2316,6 +2392,8 @@ namespace IOB_WIN_NEXT
raiseRefresh(currDispData);
// gestione queue FluxLog (invio, display)
svuotaCodaFLog();
// coda RawTransf
svuotaCodaRawTransf();
// coda UserLog
svuotaCodaULog();
// refresh
@@ -3426,6 +3504,56 @@ namespace IOB_WIN_NEXT
}
}
/// <summary>
/// Accumula in coda i valori RawData + log
/// </summary>
/// <param name="mesType"></param>
/// <param name="mesContent"></param>
public void accodaRawData(IOB_UT_NEXT.rawTransfType mesType, object mesContent)
{
/*--------------------------------
* nuova gestione coda dictionary
* fixme todo da fare !!!
*
* - conterrà una lista di oggetti baseRawTransf
* - i dati vanno poi "scodati" dal + vecchio ed inviati a MP/IO
* - mostra un sunto delle info da inviare
* - accodamento vero e proprio
* - verifica (opzionale) coda massima x gestire roundRobin ultimi eventi
* - trace della coda
* - counter invio??? valutare se c'è dataora e poi sono da salvare su MongoDb / Redis
*
* */
// serializzo il valore...
BaseRawTransf newVal = new BaseRawTransf(DateTime.Now, mesContent, mesType);
string encodedVal = JsonConvert.SerializeObject(newVal);
// --> accodo (valore già formattato)!
QueueRawTransf.Enqueue(encodedVal);
// se abilitato controllo coda Max (superiore a 0...)
if (maxQueueRawTransf > 0)
{
// se ho una coda superiore a max ammesso
if (QueueRawTransf.Count > maxQueueRawTransf)
{
// elimino valori iniziali fino a tornare al max ammesso...
while (QueueRawTransf.Count > maxQueueRawTransf)
{
string currVal = "";
QueueRawTransf.TryDequeue(out currVal);
lgInfo($"Eliminazione da coda RawTransf per superamento maxLengh: {currVal}");
}
}
}
// loggo!
lgTrace(string.Format("[QUEUE-RTRANSF] {0}", encodedVal));
counterRawTransf++;
if (counterRawTransf > 9999)
{
counterRawTransf = 0;
}
}
/// <summary>
/// Accoda (visualizzando in cima allo stack) la nuova stringa di output per area OTHER DATA
/// </summary>
@@ -3446,10 +3574,19 @@ namespace IOB_WIN_NEXT
{
// mostro dati variati letti...
displayInData(ref currDispData);
// --> accodo (valore già formattato)!
QueueIN.Enqueue(qEncodeIN);
// loggo!
lgTrace(string.Format("[QUEUE-IN] {0}", qEncodeIN));
// verifico veto a invio status macchina
string keyName = "VETO_SIG_IN";
if (getOptPar(keyName).ToUpper() == "TRUE")
{
lgTrace($"Filtrato accodamento valore da conf IOB | {keyName} | [QUEUE-IN] {qEncodeIN}");
}
else
{
// --> accodo (valore già formattato)!
QueueIN.Enqueue(qEncodeIN);
// loggo!
lgTrace(string.Format("[QUEUE-IN] {0}", qEncodeIN));
}
// aggiorno counters ed eventuale reset
nReadFilt++;
if (nReadFilt > int.MaxValue - 1)
@@ -3833,6 +3970,7 @@ namespace IOB_WIN_NEXT
}
else if (ciclo == gatherCycle.LF)
{
processCustomTaskLF();
processOtherCounters();
processProgram();
// verifico se devo gestire cambio ODL in modo automatico
@@ -3920,6 +4058,13 @@ namespace IOB_WIN_NEXT
raiseRefresh(currDispData);
}
/// <summary>
/// Effettua processing CUSTOM x l'IOB corrente (ed invia ad IO)
/// (task svolto tipicamente ogni 5 sec se base timer 10ms, vedere app.config)
/// </summary>
public virtual void processCustomTaskLF()
{ }
/// <summary>
/// Recupera eventuali allarmi CNC...
/// </summary>
@@ -4143,6 +4288,27 @@ namespace IOB_WIN_NEXT
}
break;
case urlType.RawTransf:
BaseRawTransf currRTData = new BaseRawTransf();
rawTransfJsonPayload fullRTObj = new rawTransfJsonPayload();
fullRTObj.rawTransfData = new List<BaseRawTransf>();
// inizio processando ogni valore
foreach (var item in elencoValori)
{
currRTData = JsonConvert.DeserializeObject<BaseRawTransf>(item);
fullRTObj.rawTransfData.Add(currRTData);
}
// conversione finale
try
{
answ = JsonConvert.SerializeObject(fullRTObj);
}
catch (Exception exc)
{
lgError($"RawTransf Errore in costruzione jsonPayload:{Environment.NewLine}{exc}");
}
break;
case urlType.ULog:
int numVal = 0;
int matrOp = 0;
@@ -5524,6 +5690,10 @@ namespace IOB_WIN_NEXT
tipoComando = cIobConf.serverData.CMDBASE_JSON;
break;
case urlType.RawTransf:
tipoComando = cIobConf.serverData.CMDRAWTRANSF_JSON;
break;
case urlType.ULog:
tipoComando = cIobConf.serverData.CMDULOG_JSON;
break;
+31
View File
@@ -0,0 +1,31 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace IOB_WIN_NEXT
{ /// <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 IobIcoelDb : IobGeneric
{
/// <summary>
/// Costruttore dell'IOB Icoel DB
/// </summary>
/// <param name="caller">AdapterForm chiamante</param>
/// <param name="IOBConf">Configurazione IOB per avvio</param>
public IobIcoelDb(AdapterForm caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
}
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
return base.executeTasks(task2exe);
}
}
}
+236
View File
@@ -0,0 +1,236 @@
using EgwProxy.Icoel;
using EgwProxy.Icoel.SizerService;
using IOB_UT_NEXT;
using MapoSDK;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Net.NetworkInformation;
namespace IOB_WIN_NEXT
{
/// <summary>
/// Adapter specializzato per ICOEL e le chiamate tramite WS Soap al Sizer, con libreria EgwProxy.Icoel
/// </summary>
public class IobIcoelSoap : IobGeneric
{
#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 IobIcoelSoap(AdapterForm 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);
}
/// <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 ho batch NON chiusi (data = minValue) allora lavora
if (currBatchList[1].EndTime == DateTime.MinValue || currBatchList[1].EndTime == DateTime.MinValue)
{
B_input = 3;
}
}
}
else
{
B_input = 0;
currDispData.semIn = Semaforo.SR;
}
}
#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?)
*
*---------------------------------------*/
return base.executeTasks(task2exe);
}
/// <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();
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 = (currBatchList[item.Key].Id != item.Value.Id);
}
}
// se devo inviare impacchetto dati
if (doSend)
{
// accodo per invio...
accodaRawData(IOB_UT_NEXT.rawTransfType.IcoelBatch, currBatch);
currBatchList = currBatch;
}
}
}
/// <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();
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)
{
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.cncIpAddr}");
}
}
}
}
else
{
needRefresh = true;
}
}
public override void tryDisconnect()
{
// registro solo che è disconnesso
connectionOk = false;
}
#endregion Public Methods
#region Protected Properties
/// <summary>
/// elenco dei BAtch correntemente caricati x testing variazione
/// </summary>
protected Dictionary<int, Batch> currBatchList { get; set; }
protected Connector IcoelSizer { get; set; }
#endregion Protected Properties
#region Protected Methods
/// <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);
if (varList != null && varList.Length > 0)
{
var varietyData = IcoelSizer.GetLayoutForVarietyList(varList);
// invio dai al server IO
}
}
#endregion Protected Methods
}
}
+2 -2
View File
@@ -164,8 +164,8 @@ namespace IOB_WIN_NEXT
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// Effettua lettura semafori principale
/// <paramref name="currDispData">Parametri da aggiornare x display in form</paramref>
/// </summary>
public override void readSemafori(ref newDisplayData currDispData)
{
+1 -1
View File
@@ -460,7 +460,7 @@ namespace IOB_WIN_NEXT
}
/// <summary>
/// effettua verifica del datablock icoel invianod eventualmente i dati variati
/// effettua verifica del datablock icoel inviando eventualmente i dati variati
/// </summary>
/// <param name="startNodeId"></param>
/// <param name="blockName"></param>
+3 -3
View File
@@ -2,9 +2,9 @@
<packages>
<package id="Autoupdater.NET.Official" version="1.7.0" targetFramework="net462" />
<package id="EasyModbusTCP" version="5.6.0" targetFramework="net462" />
<package id="EgwProxy.Icoel" version="3.6.2205.2012" targetFramework="net462" />
<package id="EgwProxy.MultiCncLib" version="3.6.2205.2012" targetFramework="net462" />
<package id="EgwProxy.OsaiCncLib" version="3.6.2205.2012" targetFramework="net462" />
<package id="EgwProxy.Icoel" version="3.6.2205.2018" targetFramework="net462" />
<package id="EgwProxy.MultiCncLib" version="3.6.2205.2319" targetFramework="net462" />
<package id="EgwProxy.OsaiCncLib" version="3.6.2205.2015" targetFramework="net462" />
<package id="MapoSDK" version="6.14.2204.2616" targetFramework="net462" />
<package id="MathNet.Numerics" version="4.15.0" targetFramework="net462" />
<package id="Microsoft.CodeAnalysis.NetAnalyzers" version="6.0.0" targetFramework="net462" developmentDependency="true" />