Update gestione lettura da LUT

This commit is contained in:
Samuele Locatelli
2021-11-04 16:10:39 +01:00
parent ac7d7d763b
commit 7a0dbe288e
4 changed files with 254 additions and 173 deletions
+152 -152
View File
@@ -1,155 +1,155 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<appSettings>
<add key="appName" value="IOB-WIN-NEXT" />
<!--<add key="appVers" value="develop" />-->
<add key="enableTest" value="true" />
<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="1000" />
<!-- 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="1000" />
<!--gestione coda-->
<add key="maxQueueFLog" value="16384" />
<!--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="20000" />
<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="MMapR" value="MMapR.map" />
<add key="MMapW" value="MMapW.map" />
<add key="AUpdAsAdm" value="true" />
<add key="ConfToCloud" value="true" />
<!--logging-->
<add key="recTime" value="true" />
<add key="verbose" value="true" />
<add key="logEvery" value="100" />
<add key="zipLogOldDay" value="1" />
<add key="maxLogDirSize" value="300" />
<add key="maxLogDays" value="120" />
<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" />
<probing privatePath="lib;libs" xmlns="" />
<dependentAssembly>
<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" />
</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" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.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" />
</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="BouncyCastle.Crypto" publicKeyToken="0e99375e54769942" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.9.0.0" newVersion="1.9.0.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>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="OPENcontrol" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://192.168.20.2:8080" binding="basicHttpBinding" bindingConfiguration="OPENcontrol" contract="OpenControl.OPENcontrolPortType" name="OPENcontrol" />
</client>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.2" />
</startup>
<appSettings>
<add key="appName" value="IOB-WIN-NEXT" />
<!--<add key="appVers" value="develop" />-->
<add key="enableTest" value="true" />
<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="1000" />
<!-- 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="1000" />
<!--gestione coda-->
<add key="maxQueueFLog" value="16384" />
<!--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="20000" />
<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="MMapR" value="MMapR.map" />
<add key="MMapW" value="MMapW.map" />
<add key="AUpdAsAdm" value="true" />
<add key="ConfToCloud" value="true" />
<!--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="120" />
<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" />
<probing privatePath="lib;libs" xmlns="" />
<dependentAssembly>
<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" />
</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" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Runtime.CompilerServices.Unsafe" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.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" />
</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="BouncyCastle.Crypto" publicKeyToken="0e99375e54769942" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.9.0.0" newVersion="1.9.0.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>
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="OPENcontrol" />
</basicHttpBinding>
</bindings>
<client>
<endpoint address="http://192.168.20.2:8080" binding="basicHttpBinding" bindingConfiguration="OPENcontrol" contract="OpenControl.OPENcontrolPortType" name="OPENcontrol" />
</client>
</system.serviceModel>
</configuration>
+3
View File
@@ -391,6 +391,9 @@
<None Include="DATA\CONF\IMI_50.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="DATA\CONF\PIZ04_MBlock.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="DATA\CONF\PIZ05_MBlock.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
+95 -12
View File
@@ -36,6 +36,11 @@ namespace IOB_WIN_NEXT
protected ModbusClient currPLC;
/// <summary>
/// Copia locale dei valori in Holding Registry, come array chiave (int) valori int[] letti tramite ModBus, da convertire secondo tipo
/// </summary>
protected Dictionary<int, int[]> HoldingRegisterLUT = new Dictionary<int, int[]>();
/// <summary>
/// Ultimo controllo ping x evitare ping flood...
/// </summary>
@@ -208,7 +213,13 @@ namespace IOB_WIN_NEXT
return valUInt;
}
private Dictionary<string, dataConfTSVC> getDataDictionary(Dictionary<string, dataConfTSVC> memItemList, ref Dictionary<string, string> outVal)
/// <summary>
/// Recupero dati da singole letture
/// </summary>
/// <param name="memItemList">Valori da processare</param>
/// <param name="outVal">Dizionario valori in uscita</param>
/// <returns>Errori di lettura</returns>
private Dictionary<string, dataConfTSVC> getDataDictionary(Dictionary<string, dataConfTSVC> memItemList, bool useLUT, ref Dictionary<string, string> outVal)
{
Dictionary<string, dataConfTSVC> readErrorList = new Dictionary<string, dataConfTSVC>();
// inizializzo i valori
@@ -218,7 +229,10 @@ namespace IOB_WIN_NEXT
foreach (var item in memItemList)
{
// attesa 50 ms prima di procedere x evitare burst dati
Thread.Sleep(50);
if (useLUT)
{
Thread.Sleep(50);
}
double valore = 0;
double valoreScal = 0;
bool dataOk = false;
@@ -244,7 +258,18 @@ namespace IOB_WIN_NEXT
break;
case modBusAddrType.HoldingRegister:
listInt = readHoldReg(item.Value.index - 1, item.Value.size);
if (useLUT)
{
int lutAddress = 40000 + item.Value.index;
if (HoldingRegisterLUT.ContainsKey(lutAddress))
{
listInt = HoldingRegisterLUT[lutAddress];
}
}
else
{
listInt = readHoldReg(item.Value.index - 1, item.Value.size);
}
valore = convertFromReg(listInt, item.Value.size, item.Value.tipoMem);
break;
@@ -301,6 +326,54 @@ namespace IOB_WIN_NEXT
}
}
/// <summary>
/// Effettua lettura blocco memoria indicato e lo salva in copia locale HoldingRegisterLUT
/// </summary>
/// <param name="startAddr">Indirizzo di aprtenza</param>
/// <param name="numReg">NUm registri da leggere (max 120)</param>
private void readBlockHoldingReg(int startAddr, int numReg)
{
// fix massima lunghezza pacchetto
if (numReg > 120)
{
lgError($"Attenzione richiesta lettura blocco troppo grande: numReg {numReg} --> 120");
numReg = 120;
}
// si lavora rispetto all'indirizzo base 40001
int baseAddr = 40001;
int[] rawData = new int[2];
try
{
stopwatch.Restart();
rawData = currPLC.ReadHoldingRegisters(startAddr - baseAddr, numReg);
stopwatch.Stop();
lgInfo($"Lettura in blocco HoldingRegisters| startAddr: {startAddr} | numReg {numReg} | {stopwatch.ElapsedMilliseconds}ms");
// salvo in LUT la versione ESPLOSA 2 byte alla volta...
if (rawData.Length > 0)
{
for (int i = 0; i < rawData.Length / 2; i++)
{
int[] thisSet = new int[2];
Array.Copy(rawData, i * 2, thisSet, 0, 2);
// salvo nel registro...
int currAddr = startAddr + i * 2;
if (HoldingRegisterLUT.ContainsKey(currAddr))
{
HoldingRegisterLUT[currAddr] = thisSet;
}
else
{
HoldingRegisterLUT.Add(currAddr, thisSet);
}
}
}
}
catch (Exception exc)
{
lgError($"Eccezione in readBlockHoldingReg{Environment.NewLine}{exc}");
}
}
#endregion Private Methods
#region Protected Methods
@@ -795,29 +868,39 @@ namespace IOB_WIN_NEXT
}
else
{
Dictionary<string, dataConfTSVC> readErrorList = new Dictionary<string, dataConfTSVC>();
Dictionary<string, dataConfTSVC> readErrorListRepeat = new Dictionary<string, dataConfTSVC>();
bool useLUT = memSetR != null && memSetR.Count > 0;
// se configurato leggo IN BLOCCHI da memoria...
if (useLUT)
{
foreach (var item in memSetR)
{
readBlockHoldingReg(item.Key, item.Value);
}
}
// procedo ...
try
{
// processo x ogni valore configurato...
if (memMap.mMapRead.Count > 0)
{
Dictionary<string, dataConfTSVC> readErrorList = new Dictionary<string, dataConfTSVC>();
Dictionary<string, dataConfTSVC> readErrorListRepeat = new Dictionary<string, dataConfTSVC>();
var memItemList = memMap.mMapRead;
readErrorList = getDataDictionary(memItemList, ref outVal);
readErrorList = getDataDictionary(memItemList, useLUT, ref outVal);
// se qualcosa è andato storto riprovo a caricare SOLO gli errori... 1 sola volta
if (readErrorList.Count > 0)
{
lgInfo("Attesa prima di rilettura");
lgInfo($"Attesa prima di rilettura | LUT: {useLUT}");
// attendo 3 sec
Thread.Sleep(3000);
lgInfo($"Effettuo rilettura per {readErrorList.Count} variabili");
readErrorListRepeat = getDataDictionary(readErrorList, ref outVal);
lgInfo($"Effettuo rilettura per {readErrorList.Count} variabili | LUT: {useLUT}");
readErrorListRepeat = getDataDictionary(readErrorList, useLUT, ref outVal);
}
// se avessi ancora errori --> disconnetto
if (readErrorListRepeat.Count > 0)
{
lgInfo("Trovati valori non validi al secondo tentativo --> invalido valori letti e resetto adapter con tryDisconnect!");
lgInfo($"Trovati valori non validi al secondo tentativo | LUT: {useLUT} --> invalido valori letti e resetto adapter con tryDisconnect!");
tryDisconnect();
// invalido output
outVal = new Dictionary<string, string>();
@@ -830,12 +913,12 @@ namespace IOB_WIN_NEXT
}
else
{
lgInfo($"getDynData: {memMap.mMapRead.Count} record in mMapRead");
lgInfo($"getDynData: {memMap.mMapRead.Count} record in mMapRead | LUT: {useLUT}");
}
}
catch (Exception exc)
{
lgError(exc, "Errore in getDynData x ModBus TCP PLC --> ciclo disconnect/reconnect");
lgError(exc, "Errore in getDynData x ModBus TCP PLC --> ciclo disconnect/reconnect | LUT: {useLUT}");
tryDisconnect();
outVal = new Dictionary<string, string>();
tryConnect();
+4 -9
View File
@@ -41,8 +41,6 @@ namespace IOB_WIN_NEXT
try
{
processDynData();
testRead();
}
catch (Exception exc)
{
@@ -138,13 +136,10 @@ namespace IOB_WIN_NEXT
//modbusClient.WriteMultipleCoils(4, new bool[] { true, true, true, true, true, true, true, true, true, true }); //Write Coils starting with Address 5
//bool[] readCoils = modbusClient.ReadCoils(9, 10); //Read 10 Coils from Server, starting with address 10
//int[] readHoldingRegisters = currPLC.ReadHoldingRegisters(0, 34); //Read 10 Holding Registers from Server, starting with Address 1
//testBlockRead(40001, 32);
testBlockRead(40001, 64);
//testBlockRead(40001, 120);
testBlockRead(40421, 72);
//testBlockRead(40401, 100);
foreach (var item in memSetR)
{
testBlockRead(item.Key, item.Value);
}
}
#endregion Private Methods