- Pulizia conf file da NEXT

- copia setupConsumi in MBUS (FIMAT)
- fix e conf varie
This commit is contained in:
Samuele Locatelli
2025-01-22 16:04:41 +01:00
parent b276dfc887
commit c7c61755d3
16 changed files with 66 additions and 3878 deletions
@@ -0,0 +1,31 @@
{
"addHeader": false,
"numDec": 2,
"codMag": "CH5",
"mode": "FixWidth",
"convRatio": {
"PCW0215": 0.455,
"BLU": 0.769,
"NERO": 0.714,
"ROSSO": 0.625,
"ULTRAPHO": 1.000,
"PRINTWHI": 0.571,
"GIALLORO": 0.645,
"COLANVIO": 1.000,
"GARTIT": 1.00
},
"fieldLength": {
"CodMag": 3,
"ColourCode": 8,
"Description": 6,
"UM": 2,
"WeightKgProc": 8,
"DtRif": 10
},
"fieldNDec": {
"WeightKgProc": "2"
},
"fieldLPad": {
"WeightKgProc": "0"
}
}
+4
View File
@@ -285,6 +285,7 @@
<None Include="DATA\HIST\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="DATA\MES_Setup\setupConsumi.json" />
<None Include="NLog.config">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
@@ -302,6 +303,9 @@
<Content Include="Resources\Start-IOB-WIN.bat">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="Resources\setupConsumi.json">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Include="setupTgt.bat" />
<None Include="temp\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
+31
View File
@@ -0,0 +1,31 @@
{
"addHeader": false,
"numDec": 2,
"codMag": "CH5",
"mode": "FixWidth",
"convRatio": {
"PCW0215": 0.455,
"BLU": 0.769,
"NERO": 0.714,
"ROSSO": 0.625,
"ULTRAPHO": 1.000,
"PRINTWHI": 0.571,
"GIALLORO": 0.645,
"COLANVIO": 1.000,
"GARTIT": 1.00
},
"fieldLength": {
"CodMag": 3,
"ColourCode": 8,
"Description": 6,
"UM": 2,
"WeightKgProc": 8,
"DtRif": 10
},
"fieldNDec": {
"WeightKgProc": "2"
},
"fieldLPad": {
"WeightKgProc": "0"
}
}
-45
View File
@@ -1,51 +1,6 @@
@echo off
echo Inizio processing After Build: configurazione %1 , directory %2
RD /S /Q %2"\lib\ar"
RD /S /Q %2"\lib\cs"
RD /S /Q %2"\lib\da"
RD /S /Q %2"\lib\de"
RD /S /Q %2"\lib\es"
RD /S /Q %2"\lib\fr"
RD /S /Q %2"\lib\it"
RD /S /Q %2"\lib\ja-JP"
RD /S /Q %2"\lib\ko"
RD /S /Q %2"\lib\lv"
RD /S /Q %2"\lib\nl"
RD /S /Q %2"\lib\pl"
RD /S /Q %2"\lib\pt"
RD /S /Q %2"\lib\pt-BR"
RD /S /Q %2"\lib\ru"
RD /S /Q %2"\lib\sk"
RD /S /Q %2"\lib\sv"
RD /S /Q %2"\lib\th"
RD /S /Q %2"\lib\tr"
RD /S /Q %2"\lib\zh"
RD /S /Q %2"\lib\zh-TW"
MOVE /Y %2"ar" %2"lib\"
MOVE /Y %2"cs" %2"lib\"
MOVE /Y %2"da" %2"lib\"
MOVE /Y %2"de" %2"lib\"
MOVE /Y %2"es" %2"lib\"
MOVE /Y %2"fr" %2"lib\"
MOVE /Y %2"it" %2"lib\"
MOVE /Y %2"ja-JP" %2"lib\"
MOVE /Y %2"ko" %2"lib\"
MOVE /Y %2"lv" %2"lib\"
MOVE /Y %2"nl" %2"lib\"
MOVE /Y %2"pl" %2"lib\"
MOVE /Y %2"pt" %2"lib\"
MOVE /Y %2"pt-BR" %2"lib\"
MOVE /Y %2"ru" %2"lib\"
MOVE /Y %2"sk" %2"lib\"
MOVE /Y %2"sv" %2"lib\"
MOVE /Y %2"th" %2"lib\"
MOVE /Y %2"tr" %2"lib\"
MOVE /Y %2"zh" %2"lib\"
MOVE /Y %2"zh-TW" %2"lib\"
if %1 == "Release" goto ReleaseExec
if %1 == Release goto ReleaseExec
if %1 == "Debug" goto DebugExec
-76
View File
@@ -1,76 +0,0 @@
;Configurazione IOB-WIN
[IOB]
CNCTYPE=BECKHOFF_CPA
[MACHINE]
VENDOR=CPA
MODEL=SELEZ
[CNC]
IP=5.97.72.66.1.1
PORT=851
GETPRGNAME=true
[SERVER]
MPIP=http://192.168.1.7
MPURL=/MP/IO
CMDBASE=/IOB/input/
CMDFLOG=/IOB/flog/
CMDALIVE=/IOB
CMDENABLED=/IOB/enabled/
CMDADV1=?valore=
CMDREBO=/sendReboot.aspx?idxMacchina=
[MEMORY]
; Red: Y2.0 | Yellow: Y1.7 | Green Y2.1 | riscaldamento Y7.4 | D19.1 MANCA PEZZO (SE rosso)
;BIT0=CONN
;BIT1=Y2.1
;BIT2=PZCOUNT.PAR.6711
;BIT3=Y2.0
;BIT4=Y1.7
;BIT5=Y7.4
;AREAD_START=0
;AREAD_SIZE=0
;AREAG_SIZE=48
;AREAR_START=0
;AREAR_SIZE=0
;AREAX_START=0
;AREAX_SIZE=0
;AREAY_START=0
;AREAY_SIZE=8
;PAR_START=6711
;PAR_SIZE=3
[BLINK]
;MAX_COUNTER_BLINK = 30
MAX_COUNTER_BLINK = 15
;bit0 = 0
;bit1 = 0
;bit2 = 0
;bit3 = 0
;bit4 = 1
;bit5 = 0
;bit6 = 0
;bit7 = 0
BLINK_FILT=0
;BLINK_FILT=16
[OPTPAR]
;PZCOUNT_MODE=STD|BIT
;PZCOUNT_MODE=STD.PAR.6711
;PZGTOT_MODE=STD.PAR.6712
;PZREQ_MODE=STD.PAR.6713
;PZCAD_MODE=STD.D.6408.DW
;ENABLE_PZ_RESET=TRUE
;ENABLE_PZ_RESET_stopSetup=TRUE
;gestione invio pezzi in blocco
CPA_STATE_VAR=VarADS.StatoMacchina
CPA_PZCOUNT=VarADS.TotaliLancio
ENABLE_SEND_PZC_BLOCK=TRUE
MIN_SEND_PZC_BLOCK=1
MAX_SEND_PZC_BLOCK=100
PARAM_CONF=3023.json
[BRANCH]
NAME=master
-118
View File
@@ -1,118 +0,0 @@
{
"mMapWrite": {
"setComm": {
"name": "setComm",
"description": "Commessa",
"tipoMem": "String",
"memAddr": "VarADS.NomeLancioRichiesto",
"index": 0,
"size": 0
},
"setArt": {
"name": "setArt",
"description": "Articolo",
"tipoMem": "String",
"memAddr": "VarADS.NomeDisegnoRichiesto",
"index": 0,
"size": 0
},
"setPzComm": {
"name": "setPzComm",
"description": "Qty",
"memAddr": "VarADS.nQuantitaRichiesta",
"tipoMem": "DInt",
"index": 0,
"size": 0
}
},
"mMapRead": {
//"StatoMacc": {
// "name": "StatoMacc",
// "description": "Stato Macchina",
// "memAddr": "VarADS.StatoMacchina",
// "tipoMem": "DInt",
// "index": 0,
// "size": 0,
// "func": "POINT",
// "period": 60,
// "factor": 1
//},
"CurrArt": {
"name": "CurrArt",
"description": "Articolo Corrente",
"memAddr": "VarADS.NomeDisegno",
"tipoMem": "String",
"index": 0,
"size": 0,
"func": "POINT",
"period": 60,
"factor": 1
},
"CurrComm": {
"name": "CurrComm",
"description": "Commessa Corrente",
"memAddr": "VarADS.NomeLancio",
"tipoMem": "String",
"index": 0,
"size": 0,
"func": "POINT",
"period": 60,
"factor": 1
},
"ContTotali": {
"name": "ContTotali",
"description": "Pezzi Totali",
"memAddr": "VarADS.TotaliLancio",
"tipoMem": "DInt",
"index": 0,
"size": 0,
"func": "POINT",
"period": 60,
"factor": 1
},
"ContBuoni": {
"name": "ContBuoni",
"description": "Pezzi Buoni",
"memAddr": "VarADS.BuoniLancio",
"tipoMem": "DInt",
"index": 0,
"size": 0,
"func": "POINT",
"period": 60,
"factor": 1
},
"ContScarti": {
"name": "ContScarti",
"description": "Pezzi Scarto",
"memAddr": "VarADS.ScartiLancio",
"tipoMem": "DInt",
"index": 0,
"size": 0,
"func": "POINT",
"period": 60,
"factor": 1
},
"ContGenerici": {
"name": "ContGenerici",
"description": "Pezzi Generici",
"memAddr": "VarADS.GenericiLancio",
"tipoMem": "DInt",
"index": 0,
"size": 0,
"func": "POINT",
"period": 60,
"factor": 1
}
//"LastMess": {
// "name": "LastMess",
// "description": "Ultimo Messaggio",
// "memAddr": "VarADS.MessaggioInterfaccia",
// "tipoMem": "String",
// "index": 0,
// "size": 0,
// "func": "POINT",
// "period": 60,
// "factor": 1
//}
}
}
-108
View File
@@ -1,108 +0,0 @@
[
{
"description": "Messaggi",
"tipoMem": "UInt",
"memAddr": "NumOfMessages",
"index": 0,
"size": 20,
"blockType": "ActiveList",
"blockLevel": "Warning",
"activeKeys": [
"MessageCode(0)",
"MessageCode(1)",
"MessageCode(2)",
"MessageCode(3)",
"MessageCode(4)",
"MessageCode(5)",
"MessageCode(6)",
"MessageCode(7)",
"MessageCode(8)",
"MessageCode(9)",
"MessageCode(10)",
"MessageCode(11)",
"MessageCode(12)",
"MessageCode(13)",
"MessageCode(14)",
"MessageCode(15)",
"MessageCode(16)",
"MessageCode(17)",
"MessageCode(18)",
"MessageCode(19)"
],
"activeValues": [
"MessageText(0)",
"MessageText(1)",
"MessageText(2)",
"MessageText(3)",
"MessageText(4)",
"MessageText(5)",
"MessageText(6)",
"MessageText(7)",
"MessageText(8)",
"MessageText(9)",
"MessageText(10)",
"MessageText(11)",
"MessageText(12)",
"MessageText(13)",
"MessageText(14)",
"MessageText(15)",
"MessageText(16)",
"MessageText(17)",
"MessageText(18)",
"MessageText(19)"
]
},
{
"description": "Allarmi",
"tipoMem": "UInt",
"memAddr": "NumOfAlarms",
"index": 0,
"size": 20,
"blockType": "ActiveList",
"blockLevel": "Alarm",
"activeKeys": [
"AlarmCode(0)",
"AlarmCode(1)",
"AlarmCode(2)",
"AlarmCode(3)",
"AlarmCode(4)",
"AlarmCode(5)",
"AlarmCode(6)",
"AlarmCode(7)",
"AlarmCode(8)",
"AlarmCode(9)",
"AlarmCode(10)",
"AlarmCode(11)",
"AlarmCode(12)",
"AlarmCode(13)",
"AlarmCode(14)",
"AlarmCode(15)",
"AlarmCode(16)",
"AlarmCode(17)",
"AlarmCode(18)",
"AlarmCode(19)"
],
"activeValues": [
"AlarmText(0)",
"AlarmText(1)",
"AlarmText(2)",
"AlarmText(3)",
"AlarmText(4)",
"AlarmText(5)",
"AlarmText(6)",
"AlarmText(7)",
"AlarmText(8)",
"AlarmText(9)",
"AlarmText(10)",
"AlarmText(11)",
"AlarmText(12)",
"AlarmText(13)",
"AlarmText(14)",
"AlarmText(15)",
"AlarmText(16)",
"AlarmText(17)",
"AlarmText(18)",
"AlarmText(19)"
]
}
]
Binary file not shown.
Binary file not shown.
-5
View File
@@ -360,9 +360,6 @@
<Private>True</Private>
<Private>True</Private>
</Reference>
<Reference Include="TwinCAT.Ads">
<HintPath>..\ExtLibs\AdsApi\.NET\v4.0.30319\TwinCAT.Ads.dll</HintPath>
</Reference>
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
@@ -396,7 +393,6 @@
</None>
<None Include="DATA\CONF\SIM_DP_02.json" />
<None Include="DATA\CONF\SIM_DP_01.json" />
<Content Include="ExtLib\S_Fwlib32_V6.3.1.exe" />
<None Include="temp\.placeholder">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
@@ -551,7 +547,6 @@
</None>
</ItemGroup>
<ItemGroup>
<Folder Include="IobBeckhoff\" />
<Folder Include="prog\" />
</ItemGroup>
<ItemGroup>
-771
View File
@@ -1,771 +0,0 @@
using CndexLinkDotNet;
using EgwProxy.OsaiCncLib;
using IOB_UT_NEXT;
using MapoSDK;
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;
namespace IOB_WIN_NEXT.Iob
{
public class OSAI : Iob.GenericNext
{
#region Public Fields
/// <summary>
/// Vettore degli allarmi CNC attivi
/// </summary>
public Dictionary<string, string> allarmiCNC = new Dictionary<string, string>();
/// <summary>
/// Stato corrente (da classe ENUM)
/// </summary>
public CNC_STATUS_OSAI currStatus;
#endregion Public Fields
#region Public Constructors
/// <summary>
/// estende l'init della classe base...
/// </summary>
/// <param name="caller"></param>
/// <param name="adpConf"></param>
public OSAI(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
// gestione invio ritardato contapezzi
pzCountDelay = utils.CRI("pzCountDelay");
lastPzCountSend = DateTime.Now;
lastWarnODL = DateTime.Now;
if (IOBConf != null)
{
// inizializzo correttamente aree memoria secondo CONF - iniFileName
if (!string.IsNullOrEmpty(IOBConf.iniFileName))
{
IniFile fIni = new IniFile(IOBConf.iniFileName);
// fix enable prgName
enablePrgName = fIni.ReadBoolean("CNC", "GETPRGNAME", true);
// effettuo lettura della conf sigLUT... cercando 1:1 i bit...
string currBit = "";
string memArea = "";
for (int i = 0; i < 8; i++)
{
currBit = string.Format("BIT{0}", i);
memArea = fIni.ReadString("MEMORY", currBit, "");
// se trovo un valore...
if (!string.IsNullOrEmpty(memArea))
{
signLUT.Add(currBit, memArea);
}
}
}
}
// è little endian (NON serve conversione)
hasBigEndian = false;
lgInfoStartup("Start init Adapter OSAI, tipo all'IP/NOME {0}, variante {1} per IOB {2}", IOBConf.cncIpAddr, IOBConf.tipoIob, IOBConf.codIOB);
// Creo oggetto x gestione connessione/comunicazione NC: secondo il tipo creo CNDEX o OPEN
parentForm.commPlcActive = true;
if (IOBConf.tipoIob == tipoAdapter.OSAI_OPEN)
{
OSAI_ref = new Open_Series(IOBConf.cncIpAddr, false);
}
else if (IOBConf.tipoIob == tipoAdapter.OSAI_VB6)
{
OSAI_ref = new ComCNOSAIVB6(IOBConf.cncIpAddr, false);
}
else
{
OSAI_ref = new ComCNOsai(IOBConf.cncIpAddr, false);
}
parentForm.commPlcActive = false;
if (isVerboseLog)
{
lgInfo(string.Format("INIT OSAI_ref da EgwProxy.MultiCncLib come {0}", IOBConf.tipoIob));
}
// disconnetto e connetto...
if (isVerboseLog)
{
lgInfo("OSAI: tryDisconnect");
}
tryDisconnect();
lgInfo("OSAI: tryConnect");
tryConnect();
// recupero machine status e mode da cui decodificare info sul PLC...
byte machineStatus = OSAI_ref.GetMachineStatus();
byte modeSelected = OSAI_ref.GetModeSelected();
lgInfo(string.Format("Lettura preliminare: machineStatus={0} | modeSelected={1}", machineStatus, modeSelected));
// possiamo leggere tutto da qui che contiene status, mode e last_nc_error
oData = new Cndex.GETINFO1DATA();
var ncInfo = OSAI_ref.NcInfo1(ref oData);
lgInfo(string.Format("Lettura START completa NCINFO1DATA{0} lastNcError={1}{0}status={2}{0}substatus={9}{0}mode_select={3}{0}main_progr_name={4}{0}speed_ov={5}{0}progr_speed={6}{0}real_speed={7}{0}real_feed={8}{0}", Environment.NewLine, oData.last_nc_error, oData.status, oData.mode_select, oData.main_progr_name, oData.speed_ov, oData.progr_speed, oData.real_speed, oData.real_feed, oData.substatus));
// inizio il calcolo dello status semaforico
short bitStatus = 0;
if (OSAI_ref.Connected)
{
bitStatus += 1;
}
if (utils.CRB("enableContapezzi"))
{
lgInfo("OSAI: inizio gestione contapezzi");
try
{
// verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con
// indicazione area)
if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE")))
{
if (getOptPar("PZCOUNT_MODE").StartsWith("OVAR"))
{
lgInfo("Init contapezzi OSAI: pzCntReload(true)");
pzCntReload(true);
// refresh associazione Macchina - IOB
SendM2IOB();
// invio altri dati accessori...
SendMachineConf();
// per adesso imposto lettura dal CNC == contapezzi (poi farà vera lettura...)
contapezziPLC = contapezziIOB;
}
else
{
contapezziIOB = 0;
lgInfo("Contapezzi STD disabilitato: modalità {0}", getOptPar("PZCOUNT_MODE"));
}
}
else
{
contapezziIOB = 0;
lgInfo("Parametro mancante PZCOUNT_MODE");
}
}
catch (Exception exc)
{
lgError(exc, "Errore in contapezzi OSAI");
}
}
// finisco INIT ADAPTER
lgInfo("End init Adapter OSAI");
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Recupera e processa allarmi CNC...
/// </summary>
public override Dictionary<string, string> getCncAlarms()
{
Dictionary<string, string> outVal = new Dictionary<string, string>();
// se ho allarmi li accodo...
if (oData.last_nc_error != 0)
{
try
{
outVal.Add("CNC_ALARM", (oData.last_nc_error).ToString());
}
catch (Exception exc)
{
lg.Error(exc, "Eccezione in getCncAlarms");
}
}
return outVal;
}
/// <summary>
/// Recupero dati dinamici...
/// </summary>
public override Dictionary<string, string> getDynData()
{
Dictionary<string, string> outVal = new Dictionary<string, string>();
stopwatch.Restart();
try
{
string actf = oData.real_feed.ToString();
string acts = oData.real_speed.ToString();
outVal.Add("DYNDATA", string.Format("FEED {0}#SPEED_RPM {1}", actf, acts));
if (utils.CRB("SendFeedSpeed"))
{
outVal.Add("FEED", actf);
outVal.Add("SPEED_RPM", acts);
//outVal.Add("NUM_ALARM", numAlarm);
outVal.Add("ACT_TOOL", oData.actual_tool.ToString());
}
if (utils.CRB("SendAxPos"))
{
// salvo info assi...
outVal.Add("AX_SEL", oData.ax_sel.ToString());
outVal.Add("NUM_AX_SEL", oData.num_ax_sel.ToString());
}
}
catch (Exception exc)
{
lgError(exc, "Errore in getDynData");
}
stopwatch.Stop();
return outVal;
}
/// <summary>
/// Recupero dati override (da area G che è già stata letta...)
/// </summary>
/// <returns></returns>
public override Dictionary<string, string> getOverrides()
{
Dictionary<string, string> outVal = new Dictionary<string, string>();
outVal.Add("FEED_OVER", (oData.feed_ov).ToString());
outVal.Add("RAPID_OVER", (oData.rapid_override).ToString());
return outVal;
}
/// <summary>
/// Recupero programma in lavorazione
/// </summary>
/// <returns></returns>
public override string getPrgName()
{
string prgName = "";
// recupero NUOVO prgName...
try
{
// recupero nome programma MAIN
prgName = System.Text.Encoding.Default.GetString(oData.main_progr_name);
// trimmo path del programma, ovvero "CNCMEMUSERPATH1"
prgName = prgName.Replace(utils.CRS("basePrgMemPath"), "");
lgInfo("Current PROG: {0}", prgName);
}
catch (Exception exc)
{
lgError(string.Format("Eccezione in recupero PRG NAME MAIN:{0}{1}", Environment.NewLine, exc));
connectionOk = false;
}
return prgName;
}
/// <summary>
/// Effettua vero processing contapezzi appoggiato ad area specifica da CONF
/// </summary>
public override void processContapezzi()
{
if (utils.CRB("enableContapezzi"))
{
try
{
// verifico quale modalità sia richiesta: STD (6711) oppure BIT (Custom, con
// indicazione area)
if (cIobConf.optPar.Count > 0 && !string.IsNullOrEmpty(getOptPar("PZCOUNT_MODE")))
{
string memAddr = getOptPar("PZCOUNT_MODE");
if (memAddr.StartsWith("STD"))
{
// inizio verifica area memoria/parametro levando prima parte codice
memAddr = memAddr.Replace("STD.", "");
// var di appoggio
int cntAddr = 0;
// verifico se si tratta di lettura MEMORIA... formato tipo STD.MEM.6711
if (memAddr.StartsWith("MEM."))
{
// recupero parametro...
int.TryParse(memAddr.Replace("MEM.", ""), out cntAddr);
if (cntAddr == 0)
{
cntAddr = 29;
}
// processo parametro contapezzi (lavorati)
stopwatch.Restart();
// vera lettura area memoria...
int resVal = 0;
// lettura variabili (es contapezzi)
resVal = (int)OSAI_ref.ReadVarSN((short)cntAddr);
if (utils.CRB("recTime"))
{
TimingData.addResult(cIobConf.codIOB, string.Format("R{0}-MEM", 2), stopwatch.ElapsedTicks);
}
// aggiungo in visualizzazione SE variata...
if (resVal != contapezziPLC)
{
string mCount = string.Format("MEM{0}", cntAddr);
string sVal = string.Format("[PZCOUNT]{0}|{1}", mCount, resVal);
// chiamo accodamento...
accodaFLog(sVal, qEncodeFLog(mCount, resVal.ToString()));
}
// salvo ultimo conteggio rilevato
contapezziPLC = resVal;
}
stopwatch.Stop();
}
}
}
catch (Exception exc)
{
lgError(exc, "Errore in contapezzi CNC");
connectionOk = false;
}
}
}
/// <summary>
/// Esegue processing MODE (e nel contempo recupera altri dati dell'area G)
/// </summary>
public override void processMode()
{
if (utils.CRB("enableMode"))
{
try
{
// verifico modo con valore corrente, se cambia aggiorno...
CNC_MODE newMode = decodeModeOsai(oData.mode_select);
if (newMode != currMode)
{
// aggiorno!
currMode = newMode;
// conversione NUM MODE in descrizione da ENUM
string descrMode = Enum.GetName(typeof(CNC_MODE), currMode);
// accodo x invio
string sVal = string.Format("[CNC_MODE]{0}", descrMode);
// chiamo accodamento...
accodaFLog(sVal, qEncodeFLog("CNC_MODE", descrMode));
}
}
catch (Exception exc)
{
lgError(exc, string.Format("Errore in process Mode OSAI: {0}{1}", Environment.NewLine, exc));
connectionOk = false;
stopwatch.Stop();
}
}
// lo status lo processo SEMPRE
try
{
// verifico modo con valore corrente, se cambia aggiorno...
CNC_STATUS_OSAI newStatus = (CNC_STATUS_OSAI)(oData.status);
if (newStatus != currStatus)
{
// aggiorno!
currStatus = newStatus;
// accodo x invio
string sVal = string.Format("[CNC_STATUS]{0}", currStatus.ToString());
// chiamo accodamento...
accodaFLog(sVal, qEncodeFLog("CNC_STATUS", currStatus.ToString()));
}
}
catch (Exception exc)
{
lgError(exc, string.Format("Errore in process Mode OSAI: {0}{1}", Environment.NewLine, exc));
connectionOk = false;
stopwatch.Stop();
}
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
public override void readSemafori(ref newDisplayData currDispData)
{
base.readSemafori(ref currDispData);
try
{
if (verboseLog)
{
lgInfo("inizio read semafori");
}
currDispData.semIn = Semaforo.SV;
stopwatch.Restart();
// possiamo leggere tutto da qui che contiene tutto: status, mode, last_nc_error
var ncInfo = OSAI_ref.NcInfo1(ref oData);
// time rec
if (utils.CRB("recTime"))
{
TimingData.addResult(cIobConf.codIOB, "GETINFO1DATA", stopwatch.ElapsedTicks);
}
stopwatch.Stop();
// salvo il solo BYTE dell'input decifrando il semaforo...
decodeToBitmap();
}
catch (Exception exc)
{
lgError(string.Format("Eccezione in readSemafori:{0}{1}", Environment.NewLine, exc));
connectionOk = false;
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("OSAI: ConnKO - tryConnect");
}
// PING SOLO x OPEN!!!
bool needPing = (cIobConf.tipoIob == tipoAdapter.OSAI_OPEN);
bool pingOk = false;
Ping pingSender = new Ping();
PingReply reply = pingSender.Send("127.0.0.1", 100);
// se serve PING...
if (needPing)
{
// in primis salvo data ping...
lastPING = DateTime.Now;
// ora PING!!!
IPAddress address = IPAddress.Loopback;
IPAddress.TryParse(cIobConf.cncIpAddr, out address);
try
{
// se != null --> uso address...
if (address != null)
{
reply = pingSender.Send(address, 100);
}
else
{
reply = pingSender.Send(cIobConf.cncIpAddr, 100);
}
}
catch
{
reply = pingSender.Send(IPAddress.Loopback, 100);
}
pingOk = reply.Status == IPStatus.Success;
}
// se passa il ping faccio il resto...
if (pingOk || !needPing)
{
string szStatusConnection = "";
try
{
// ora provo connessione...
parentForm.commPlcActive = true;
bool fatto = OSAI_ref.OpenSession();
if (!fatto)
{
// log errore!
lgInfo("Impossibile effettuare apertura sessione: " + OSAI_ref.ErrMsg);
}
parentForm.commPlcActive = false;
lgInfo("szStatusConnection: " + szStatusConnection);
connectionOk = true;
// refresh stato allarmi!!!
if (connectionOk)
{
dtAvvioAdp = DateTime.Now;
queueInEnabCurr = true;
if (adpRunning)
{
lgInfo("Connessione OK");
}
}
else
{
lgError("Impossibile procedere, connessione mancante...");
}
}
catch (Exception exc)
{
lgFatal(string.Format("Errore nella connessione all'adapter OSAI: {0}{1}{2}", szStatusConnection, Environment.NewLine, exc));
connectionOk = false;
lgInfo(string.Format("Eccezione in TryConnect, Adapter NON running, pausa di {0} msec prima di ulteriori tentativi di riconnessione", utils.CRI("waitRecMSec")));
}
}
else
{
// loggo no risposta ping ...
connectionOk = false;
if (needPing)
{
if (verboseLog || periodicLog)
{
lgInfo(string.Format("Attenzione: controllo PING fallito per IP {0} - {1}", cIobConf.cncPingAddr, reply.Status));
}
}
}
}
}
// se non è ancora connesso faccio procesisng memoria caso disconnesso...
if (!connectionOk)
{
// processo semafori ed invio...
processMemoryDiscon();
}
}
/// <summary>
/// Override disconnessione
/// </summary>
public override void tryDisconnect()
{
if (connectionOk)
{
string szStatusConnection = "";
try
{
OSAI_ref.CloseSession();
connectionOk = false;
// resetto timing!
TimingData.resetData();
lgInfo(szStatusConnection);
lgInfo("Effettuata disconnessione adapter OSAI!");
}
catch (Exception exc)
{
lgFatal(exc, "Errore nella disconnessione dall'adapter OSAI");
}
}
else
{
lgError("IMPOSSIBILE effettuare disconnessione: Connessione non disponibile...");
}
queueInEnabCurr = false;
}
#endregion Public Methods
#region Protected Fields
/// <summary>
/// Struttura dati principale in continuo update...
/// </summary>
protected Cndex.GETINFO1DATA oData;
/// <summary>
/// Oggetto MAIN x connessione OSAI
/// </summary>
protected ComCNOsai OSAI_ref;
#endregion Protected Fields
#region Protected Methods
/// <summary>
/// Decodifica del MODE selezionato
/// </summary>
/// <param name="mode"></param>
/// <returns></returns>
protected static CNC_MODE decodeModeOsai(int mode)
{
CNC_MODE answ = CNC_MODE.ND;
switch (mode)
{
case 1:
answ = CNC_MODE.MDI;
break;
case 2:
answ = CNC_MODE.AUTO;
break;
case 3:
answ = CNC_MODE.SEMI;
break;
case 4:
answ = CNC_MODE.JOG_MAN;
break;
case 5:
answ = CNC_MODE.JOG_INC;
break;
case 6:
answ = CNC_MODE.PROFILE;
break;
case 7:
answ = CNC_MODE.HOME;
break;
case 8:
answ = CNC_MODE.HANDLE_INC;
break;
default:
break;
}
return answ;
}
#endregion Protected Methods
#region Private Fields
/// <summary>
/// LookUpTable di decodifica da CNC a segnali tipo bitmap MAPO
/// </summary>
private Dictionary<string, string> signLUT = new Dictionary<string, string>();
#endregion Private Fields
#region Private Methods
/// <summary>
/// Effettua decodifica aree memoria alla bitmap usata x MAPO
/// </summary>
private void decodeToBitmap()
{
// init a zero...
B_input = 0;
// SE SI E' CONNESSO al CNC allora è 1=powerON...
if (OSAI_ref.Connected)
{
B_input += 1 << 0;
}
// decodifico impiegando dictionary... cercando il TIPO di memoria & co...
string bKey = "";
string bVal = "";
for (int i = 0; i < 8; i++)
{
bKey = string.Format("BIT{0}", i);
// cerco se ci sia in LUT
if (signLUT.ContainsKey(bKey))
{
// recupero nome variabile...
bVal = signLUT[bKey];
// se l'area è PZCOUNT... processo PUNTUALMENTE il CONTAPEZZI...
if (bVal.StartsWith("PZCOUNT"))
{
// procedo SOLO SE è enabled IOB
if (IobOnline)
{
try
{
currODL = utils.callUrl(urlGetCurrODL);
// solo SE HO un ODL...
if (string.IsNullOrEmpty(currODL) || currODL == "0")
{
if (periodicLog)
{
lgInfo(string.Format("Osai | Lettura ODL andata a vuoto: currODL: {0}", currODL));
}
}
else
{
lgInfo(string.Format("Osai | Lettura ODL, currODL: {0} --> currIdxODL prec: {1}", currODL, currIdxODL));
// provo a salvare nuovo ODL
int.TryParse(currODL, out currIdxODL);
}
}
catch (Exception exc)
{
if (DateTime.Now.Subtract(lastWarnODL).TotalSeconds > 15)
{
lgError(exc, "Errore in fase di chiamata URL x ODL corrente | URL chiamato: {0}", urlGetCurrODL);
lastWarnODL = DateTime.Now;
}
}
}
else
{
// imposto currODL a vuoto!
currODL = "";
if (periodicLog)
{
lgInfo($"OSAI | Lettura ODL non effettuata: IobOnline: {IobOnline} | currODL impostato a vuoto");
}
}
if (!string.IsNullOrEmpty(currODL) && currODL != "0")
{
// controllo se è passato intervallo minimo tra 2 controlli/elaborazioni
// x distanziare invio e ridurre letture
if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay))
{
// se sono differenti MOSTRO...
if (contapezziPLC != contapezziIOB)
{
// registro contapezzi
lgInfo($"Differenza Contapezzi: contapezziPLC: {contapezziPLC} | contapezziIOB {contapezziIOB}");
}
// verifico se variato contapezzi in area STD PAR6711... e se
// passato ritardo minimo...
if (contapezziPLC > contapezziIOB)
{
// salvo nuovo contapezzi (incremento di 1...) + richiesta
// refresh conteggio
contapezziIOB++;
needRefreshPzCount = true;
// salvo in semaforo!
B_input += 1 << 2;
// registro contapezzi
lgInfo($"contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}");
}
// invio a server contapezzi (aggiornato)
string retVal = utils.callUrl(urlSetPzCount + contapezziIOB.ToString());
// verifica se tutto OK
if (retVal != contapezziIOB.ToString())
{
// errore salvataggio contapezzi
lgInfo($"Errore salvataggio Contapezzi OSAI: contapezziPLC {contapezziPLC} | contapezziIOB {contapezziIOB} | risposta: {retVal}");
// rileggo il counter pezzi da server
pzCntReload(true);
}
// resetto timer...
lastPzCountSend = DateTime.Now;
}
}
else
{
if (DateTime.Now >= lastPzCountSend.AddMilliseconds(pzCountDelay))
{
lgInfo($"Attenzione: mancanza ODL non procedo con gestione contapezzi. contapezziPLC OSAI: {contapezziPLC} | contapezziIOB {contapezziIOB}");
// resetto timer...
lastPzCountSend = DateTime.Now;
}
}
}
// controllo le condizioni x costruire il bit1 RUN!
if (oData.mode_select == 2 && oData.status == 2)
{
B_input += 1 << 1;
}
// errore su bit3
if (oData.mode_select == 6)
{
B_input += 1 << 3;
}
// auto su bit4
if (oData.mode_select != 2)
{
B_input += 1 << 4;
}
// emergenza su bit5
if (oData.mode_select == 9)
{
B_input += 1 << 5;
}
}
}
// log opzionale!
if (verboseLog)
{
lgInfo(string.Format("Trasformazione B_input: {0}", B_input));
}
}
#endregion Private Methods
}
}
-168
View File
@@ -1,168 +0,0 @@
using IOB_UT_NEXT;
using System;
using System.Collections.Generic;
namespace IOB_WIN_NEXT.IobBeckhoff
{
public class Beckhoff : Iob.GenericNext
{
#region Public Fields
public List<string> dataVal = new List<string>();
#endregion Public Fields
#region Public Constructors
/// <summary>
/// Estende l'init della classe base
/// </summary>
/// <param name="caller"></param>
/// <param name="IOBConf"></param>
public Beckhoff(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
lgInfo("NEW IobBeckhoff Adapter");
// gestione invio ritardato contapezzi
pzCountDelay = utils.CRI("pzCountDelay");
// init datetime counters
DateTime adesso = DateTime.Now;
lastPzCountSend = adesso;
lastWarnODL = adesso;
vetoCheckStatus = adesso;
// ora leggo il file di conf specifico....
loadMemConf();
}
#endregion Public Constructors
#region Public Methods
/// <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>();
if (utils.CRB("enableTSVC"))
{
try
{
// processo x ogni valore configurato...
if (memMap.mMapRead.Count > 0)
{
// inizializzo i valori
string valString = "";
// procedo x ogni valore configurato......
foreach (var item in memMap.mMapRead)
{
// leggo
valString = AdsCli.ReadVariabile(item.Value.memAddr).ToString();
outVal.Add(item.Value.name, valString);
}
}
else
{
lgInfo($"getDynData: {memMap.mMapRead.Count} record in mMapRead");
}
}
catch (Exception exc)
{
lgError(exc, "Errore in getDynData x BeckHoff PLC");
}
}
else
{
lgInfo($"Non processo getDynData: enableTSVC = false");
}
if (periodicLog || outVal.Count > 0)
{
lgInfo($"Esito getDynData: {outVal.Count} valori VALIDI in outVal");
}
return outVal;
}
/// <summary>
/// Leggo le variabili correnti (status, contapezzi)
/// </summary>
public virtual void readCurrVal()
{
}
public virtual void setEventHandler()
{
if (AdsCli != null)
{
AdsCli.ValueChanged += AdsCli_ValueChanged;
}
}
/// <summary>
/// Override connessione
/// </summary>
public override void tryConnect()
{
if (!connectionOk)
{
int port = 851;
int.TryParse(cIobConf.cncPort, out port);
string addr = !string.IsNullOrEmpty(cIobConf.cncIpAddr) ? cIobConf.cncIpAddr : "local";
lgInfo($"Parametri TC client | addr: {addr} | port: {port}");
// predispongo dataVal
foreach (var item in memMap.mMapRead)
{
dataVal.Add(item.Value.memAddr);
}
// vera connessione!
AdsCli = new TcAdsClient(dataVal, addr, port);
connectionOk = AdsCli.Connected;
if (connectionOk)
{
setEventHandler();
readCurrVal();
queueInEnabCurr = true;
}
lgInfo($"Connected: {connectionOk}");
}
}
/// <summary>
/// Override disconnessione
/// </summary>
public override void tryDisconnect()
{
lgInfo("Richiesta disconnessione adapter");
if (AdsCli != null)
{
AdsCli.dispose();
}
connectionOk = false;
queueInEnabCurr = false;
}
#endregion Public Methods
#region Protected Fields
protected TcAdsClient AdsCli;
/// <summary>
/// Veto controllo status x log...
/// </summary>
protected DateTime vetoCheckStatus = DateTime.Now;
#endregion Protected Fields
#region Protected Methods
protected void AdsCli_ValueChanged(TcAdsClient sender, string key, string value)
{
lg.Info($"Monitored Value changed | sender: {sender} | key: {key} | value: {value}");
}
#endregion Protected Methods
}
}
-315
View File
@@ -1,315 +0,0 @@
using IOB_UT_NEXT;
using MapoSDK;
using System;
using System.Collections.Generic;
namespace IOB_WIN_NEXT.IobBeckhoff
{
public class BeckhoffCpa : IobBeckhoff.Beckhoff
{
#region Public Constructors
/// <summary>
/// Estende l'init della classe base
/// </summary>
/// <param name="caller"></param>
/// <param name="IOBConf"></param>
public BeckhoffCpa(AdapterFormNext caller, IobConfiguration IOBConf) : base(caller, IOBConf)
{
lgInfo("START IobBeckhoffCPA Adapter specifico");
// leggo le altre conf standard...
if (!string.IsNullOrEmpty(getOptPar("CPA_STATE_VAR")))
{
statusVar = getOptPar("CPA_STATE_VAR");
}
if (!string.IsNullOrEmpty(getOptPar("CPA_PZCOUNT")))
{
counterVar = getOptPar("CPA_PZCOUNT");
}
if (getOptPar("ADD_VARS").ToLower() == "true")
{
// fixme conf var gestite ad eventi da json
dataVal.Add(statusVar);
}
if (getOptPar("EARLY_CONNECT").ToLower() == "true")
{
tryConnect();
}
if (AdsCli != null)
{
readCurrVal();
}
}
#endregion Public Constructors
#region Public Methods
/// <summary>
/// Processo i task richiesti e li elimino dalla coda 1:1
/// </summary>
/// <param name="task2exe"></param>
public override Dictionary<string, string> executeTasks(Dictionary<string, string> task2exe)
{
lgInfo($"Chiamata executeTasks specifica IobBeckhoffCpa: {task2exe.Count} task ricevuti");
// Verificare il protocollo: dovrebeb togliere SOLO i task eseguiti...
Dictionary<string, string> taskDone = new Dictionary<string, string>();
string taskVal = "";
// inizio con 1 byte di default
byte[] MemBlock = new byte[1];
if (task2exe != null)
{
// cerco task specifici
foreach (var item in task2exe)
{
taskVal = "";
// converto richiesta in enum...
taskType tName = taskType.nihil;
Enum.TryParse(item.Key, out tName);
// controllo sulla KEY
switch (tName)
{
case taskType.nihil:
case taskType.fixStopSetup:
case taskType.forceResetPzCount:
case taskType.forceSetPzCount:
case taskType.setProg:
case taskType.sendWatchDogMes2Plc:
case taskType.startSetup:
case taskType.stopSetup:
taskVal = $"taskReq: {tName} | key: {item.Key} | val: {item.Value} | SKIPPED | NO EXEC";
break;
case taskType.setPzComm:
AdsCli.WriteVariabile(setPzReqVar, item.Value);
AdsCli.WriteVariabile(setParamsVar, 1);
break;
case taskType.setArt:
AdsCli.WriteVariabile(setArtVar, item.Value);
AdsCli.WriteVariabile(setParamsVar, 1);
break;
case taskType.setComm:
AdsCli.WriteVariabile(setCommVar, item.Value);
AdsCli.WriteVariabile(setParamsVar, 1);
break;
case taskType.setParameter:
// richiedo da URL i parametri WRITE da popolare
lgInfo("Chiamata 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";
}
}
// aggiunta finale bit a 1 x richiesta processing..
AdsCli.WriteVariabile(setParamsVar, 1);
break;
default:
taskVal = "SKIPPED | NO EXEC";
break;
}
// aggiungo task!
taskDone.Add(item.Key, taskVal);
}
}
return taskDone;
}
/// <summary>
/// Effettua vero processing contapezzi
/// </summary>
public override void processContapezzi()
{
if (utils.CRB("enableContapezzi"))
{
var rawCount = AdsCli.ReadVariabile(counterVar).ToString();
if (!string.IsNullOrEmpty(rawCount))
{
int newVal = -1;
int.TryParse(rawCount, out newVal);
contapezziPLC = newVal > -1 ? newVal : contapezziPLC;
}
}
}
/// <summary>
/// Leggo le variabili correnti (status, contapezzi)
/// </summary>
public override void readCurrVal()
{
var rawStatus = AdsCli.ReadVariabile(statusVar).ToString();
if (!string.IsNullOrEmpty(rawStatus))
{
int.TryParse(rawStatus, out currStatus);
}
var rawCount = AdsCli.ReadVariabile(counterVar).ToString();
if (!string.IsNullOrEmpty(rawCount))
{
int newVal = -1;
int.TryParse(rawCount, out newVal);
contapezziPLC = newVal > -1 ? newVal : contapezziPLC;
}
}
/// <summary>
/// Effettua lettura semafori principale <paramref name="currDispData">Parametri da
/// aggiornare x display in form</paramref>
/// </summary>
public override void readSemafori(ref newDisplayData currDispData)
{
/* -----------------------------------------------------
* STATE MACHINE 60
* --------------------------
* bitmap MAPO
* B0: POWER_ON
* B1: RUN
* B2: pzCount
* B3: allarme
* B4: manuale
* B5: slowTC
* B6: WarmUpCoolDown
* B7: emergenza
*
* --------------------------
* Enum Stato macchina
* --------------------------
* Errore = -1,
* Ferma = 0,
* Automatica = 1,
* Manuale = 2,
* Emergenza = 3,
* AzzeraTavola = 4,
* ManualeStazione = 5,
* Avviamento = 7
----------------------------------------------------- */
byte[] MemBlock = new byte[2];
try
{
if (connectionOk)
{
B_input = 1;
currDispData.semIn = Semaforo.SV;
}
else
{
B_input = 0;
currDispData.semIn = Semaforo.SR;
}
// indico emergenza ARMATA
B_input += (1 << 7);
// in base all'enum di status compilo valori...
switch (currStatus)
{
case -1:
B_input += (1 << 3);
break;
case 0:
case 2:
case 4:
case 5:
case 7:
B_input += (1 << 4);
break;
case 3:
// tolgo emergenza SE fosse premuta (force zero)
B_input &= ~(1 << 7);
break;
case 1:
B_input += (1 << 1);
break;
default:
break;
}
}
catch
{
currDispData.semIn = Semaforo.SR;
}
}
public override void setEventHandler()
{
base.setEventHandler();
if (AdsCli != null)
{
AdsCli.StatusChanged += AdsCli_StatusChanged;
AdsCli.CountChanged += AdsCli_CountChanged;
AdsCli.ValueChanged += AdsCli_ValueChanged;
}
}
#endregion Public Methods
#region Protected Fields
protected int currStatus = 0;
#endregion Protected Fields
#region Protected Methods
protected void AdsCli_CountChanged(TcAdsClient sender, int newCount)
{
contapezziPLC = newCount;
lg.Info($"Nuova lettura contapezzi | contapezziPLC: {contapezziPLC} | contapezziIOB: {contapezziIOB}");
}
protected void AdsCli_StatusChanged(TcAdsClient sender, int newStatus)
{
currStatus = newStatus;
lg.Info($"Status changed: {newStatus}");
}
#endregion Protected Methods
#region Private Fields
private string counterVar = "VarADS.BuoniLancio";
private string setArtVar = "VarADS.NomeDisegnoRichiesto";
private string setCommVar = "VarADS.NomeLancioRichiesto";
private string setParamsVar = "VarADS.bCambioArticolo";
private string setPzReqVar = "VarADS.nQuantitaRichiesta";
private string statusVar = "VarADS.StatoMacchina";
#endregion Private Fields
#if false
public enum EnuStates //Stato Macchina
{
Errore = -1,
Ferma = 0,
Automatica = 1,
Manuale = 2,
Emergenza = 3,
AzzeraTavola = 4,
ManualeStazione = 5,
Avviamento = 7,
}
#endif
}
}
-409
View File
@@ -1,409 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using TwinCAT.Ads;
using TwinCAT.Ads.TypeSystem;
namespace IOB_WIN_NEXT
{
/// <summary>
/// Client comunicazioni con PLC Beckhoff TwinCat
/// </summary>
public class TcAdsClient
{
#region Public Fields
public System.Collections.Concurrent.ConcurrentQueue<ComandiADS> CodaComandi;
public TwinCAT.Ads.TcAdsSymbolInfoLoader InfoLoader;
/// <summary>
/// Dizionario delle variabili monitorate (gestite ad evento x modifica), chiave = nome var, valore = symbol x gestione variabile
/// </summary>
public Dictionary<string, Symbol> MonitoredItems = new Dictionary<string, Symbol>();
public TwinCAT.TypeSystem.ISymbolLoader SymbolLoaderInstance;
public TcAdsSymbolInfoCollection Symbols;
#endregion Public Fields
#region Public Constructors
/// <summary>
/// Inizializza un oggetto ADS x gestione classe comunicazione con TwinCat
/// </summary>
/// <param name="MonitVars">
/// Lista dei nomi delle variabili da gestire ad eventChange (es stato macchina)
/// </param>
/// <param name="indirizzo">indirizzo tipo AmsNetId</param>
/// <param name="porta">
/// Porta comunicazione: Connect to local PLC - Runtime 1 - TwinCAT2 Port=801, TwinCAT3 Port=851
/// </param>
public TcAdsClient(List<string> MonitVars, string indirizzo = "local", int porta = 851)
{
_MonitVars = MonitVars;
MonitoredItems = new Dictionary<string, Symbol>();
notifyStream = new AdsStream();
newNotificationStream = new AdsStream();
addressList = new Dictionary<int, Tuple<int, int>>();
bool ready = false;
while (!ready)
{
try
{
//LETTURA DEL VETTORE DI INIZIALIZZAZIONE
if (adsClient == null) adsClient = new TwinCAT.Ads.TcAdsClient();
// Connect to local PLC - Runtime 1 - TwinCAT2 Port=801, TwinCAT3 Port=851
if (indirizzo == "")
{
adsClient.Connect(porta);
}
else
{
if (adsClient.IsConnected == false) adsClient.Connect(indirizzo, porta);
}
SymbolLoaderInstance = SymbolLoaderFactory.Create(adsClient, SymbolLoaderSettings.Default);
InfoLoader = adsClient.CreateSymbolInfoLoader();
Symbols = InfoLoader.GetSymbols(true);
ready = true;
}
catch (Exception ex)
{
System.Threading.Thread.Sleep(100);
ready = false;
Debug.Print(ex.Message);
}
}
// inizializzo dizionario delle variabili gestite
foreach (var item in _MonitVars)
{
var currSymbol = (Symbol)SymbolLoaderInstance.Symbols[item];
currSymbol.NotificationSettings = new AdsNotificationSettings(AdsTransMode.OnChange, 100, 100);
currSymbol.ValueChanged += MonItem_ValueChanged;
// aggiungo al dict
MonitoredItems.Add(item, currSymbol);
}
StatoMacchina = (Symbol)SymbolLoaderInstance.Symbols["VarADS.StatoMacchina"];
StatoMacchina.NotificationSettings = new AdsNotificationSettings(AdsTransMode.OnChange, 100, 100);
StatoMacchina.ValueChanged += StatoMacchina_ValueChanged;
#if false
notifyposition = 0;
#endif
cts = new CancellationTokenSource();
//adsClient.AdsNotification += new AdsNotificationEventHandler(adsClient_AdsNotification);
CodaComandi = new System.Collections.Concurrent.ConcurrentQueue<ComandiADS>();
cts = new CancellationTokenSource(); //Task require CancellationToken.cancel() to stop
Action<object> Azione = commandDispatcher;
//Definisce e Crea un Task di base a priorità favorevole
dispatchertask = new Task(Azione, cts.Token, TaskCreationOptions.PreferFairness);
dispatchertask.Start();
}
#endregion Public Constructors
#region Public Delegates
public delegate void CountChangedEventHandler(TcAdsClient sender, int newCount);
public delegate void StatusChangedEventHandler(TcAdsClient sender, int newStatus);
public delegate void ValueChangedEventHandler(TcAdsClient sender, string key, string value);
#endregion Public Delegates
#region Public Events
public event CountChangedEventHandler CountChanged;
public event StatusChangedEventHandler StatusChanged;
public event ValueChangedEventHandler ValueChanged;
#endregion Public Events
#region Public Properties
public TwinCAT.Ads.TcAdsClient Client
{
get { return adsClient; }
}
public bool Connected
{
get
{
bool answ = false;
if (adsClient != null)
{
answ = adsClient.IsConnected;
}
return answ;
}
}
public bool EnableEvents { get; set; }
public int Status
{
get
{
var stato = ReadVariabile("VarADS.StatoMacchina");
if (stato != null) _status = (int)stato;
else
{
throw new Exception("Errore lettura stato");
}
return _status;
}
}
#endregion Public Properties
#region Public Methods
public void dispose()
{
adsClient.Dispose();
}
public TcAdsSymbolInfo GetSymbolInfo(string nome)
{
try
{
var symbol = InfoLoader.FindSymbol(nome);
return symbol;
}
catch (Exception)
{
throw;
}
}
public object ReadVariabile(ref TcAdsSymbolInfo variabile)
{
var comando = new ComandiADS { ComandoScrittua = false, Symbol = variabile };
return ReadVariabile(comando);
}
public object ReadVariabile(string symbolName, Type type = null)
{
var comando = new ComandiADS { ComandoScrittua = false, SymbolName = symbolName };
return ReadVariabile(comando);
}
public bool WriteVariabile(string symbolName, object value, bool syncronous = false)
{
var comando = new ComandiADS { Value = value, ComandoScrittua = true, SymbolName = symbolName };
return WriteVariabile(comando, syncronous);
}
public bool WriteVariabile(TcAdsSymbolInfo symbol, object value, bool syncronous = false)
{
var comando = new ComandiADS { Value = value, ComandoScrittua = true, Symbol = symbol };
return WriteVariabile(comando, syncronous);
}
#endregion Public Methods
#region Public Classes
public class ComandiADS
{
#region Public Fields
public bool ComandoScrittua;
public bool Error;
public TcAdsSymbolInfo Symbol;
public string SymbolName;
public ManualResetEventSlim Updating;
public object Value;
#endregion Public Fields
#region Public Constructors
public ComandiADS()
{
Updating = new ManualResetEventSlim(false);
}
public ComandiADS(string name)
{
SymbolName = name;
Updating = new ManualResetEventSlim(false);
}
public ComandiADS(TcAdsSymbolInfo info)
{
Symbol = info;
Updating = new ManualResetEventSlim(false);
}
#endregion Public Constructors
}
#endregion Public Classes
#region Private Fields
/// <summary>
/// elenco delle variabili monitorate x change event
/// </summary>
private List<string> _MonitVars = new List<string>();
private int _status;
private List<int> addedSignalationList = new List<int>();
/// <summary>
/// Dizionario di conversione da indice a index group e index offset
/// </summary>
private Dictionary<int, Tuple<int, int>> addressList;
private TwinCAT.Ads.TcAdsClient adsClient;
private CancellationTokenSource cts;
private System.Threading.Tasks.Task dispatchertask;
#if false
//private Action<object> dispatcher;
private int eventHandle;
private int SegnalazioniADSEventHandle, StatusChangedEventHandle, MessageQueuedEventHandle;
private int notifyposition;
#endif
private object lockobj = new object();
private AdsStream newNotificationStream;
private AdsStream notifyStream;
private Symbol StatoMacchina;
#endregion Private Fields
#region Private Methods
private void commandDispatcher(object tk)
{
ComandiADS comando;
Thread.CurrentThread.Name = "ADS Command Dispatcher";
CancellationToken chiudi = (CancellationToken)tk;
while (!chiudi.IsCancellationRequested)
{
Thread.Sleep(1);
if (CodaComandi.Count <= 0)
{
Thread.Sleep(1);
continue;
}
if (CodaComandi.Count > 100) Debug.Print("CODA COMANDI! " + CodaComandi.Count.ToString());
if (!CodaComandi.TryDequeue(out comando)) continue;
if (CodaComandi.Count > 1000) continue;
if (comando.ComandoScrittua) //gestione scrittura
{
try
{
if (comando.SymbolName != "")
{
if (comando.Symbol == null) comando.Symbol = GetSymbolInfo(comando.SymbolName);
}
else
{
comando.SymbolName = comando.Symbol.Name;
}
if (comando.Value is int && comando.Symbol.Category == TwinCAT.TypeSystem.DataTypeCategory.Array)
{
var newvalue = new int[comando.Symbol.ArrayInfos[0].Elements];
newvalue[0] = (int)comando.Value;
comando.Value = newvalue;
}
if (comando.Value is double && comando.Symbol.Category == TwinCAT.TypeSystem.DataTypeCategory.Array)
{
var newvalue = new double[comando.Symbol.ArrayInfos[0].Elements];
newvalue[0] = (double)comando.Value;
comando.Value = newvalue;
}
adsClient.WriteSymbol(comando.Symbol, comando.Value);
}
catch (Exception err)
{
comando.Error = true;
Debug.Print(comando.SymbolName + " Scrittura " + err.Message);
}
comando.Updating.Set();
}
else // gestione lettura
{
try
{
if (comando.SymbolName != "")
{
if (comando.Symbol == null) comando.Symbol = GetSymbolInfo(comando.SymbolName);
}
else
{
comando.SymbolName = comando.Symbol.Name;
}
comando.Value = adsClient.ReadSymbol(comando.Symbol);
}
catch (Exception errore)
{
Debug.Print(errore.Message);
comando.Error = true;
Debug.Print("Error reading from ADS: VarName: " + comando.SymbolName);
}
comando.Updating.Set();
}
}
}
private void MonItem_ValueChanged(object sender, TwinCAT.TypeSystem.ValueChangedArgs e)
{
string newStatus = $"{e.Value}";
if (ValueChanged != null)
{
ValueChanged(this, $"{sender}", newStatus);
}
}
private object ReadVariabile(ComandiADS comando)
{
CodaComandi.Enqueue(comando);
bool test = comando.Updating.Wait(3000);
if (!test) Debug.Print("Errore attesa lettura: " + comando.SymbolName);
if (comando.Value == null) Debug.Print("ADS Variabile non trovata: " + comando.SymbolName);
return comando.Value;
}
private void StatoMacchina_ValueChanged(object sender, TwinCAT.TypeSystem.ValueChangedArgs e)
{
int newStatus = (int)e.Value;
if (StatusChanged != null) StatusChanged(this, newStatus);
}
private bool WriteVariabile(ComandiADS comando, bool syncronous)
{
bool test = true;
CodaComandi.Enqueue(comando);
if (syncronous) test = comando.Updating.Wait(3000);
if (!test) Debug.Print("Errore attesa lettura: " + comando.SymbolName);
if (comando.Error) Debug.Print("Errore ADS durante la scrittura della variabile: " + comando.SymbolName);
return !comando.Error;
}
#endregion Private Methods
}
}
File diff suppressed because it is too large Load Diff