324 lines
11 KiB
C#
324 lines
11 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using System.Net.NetworkInformation;
|
|
using System.Threading;
|
|
using TwinCAT;
|
|
using TwinCAT.Ads;
|
|
using TwinCAT.Ads.TypeSystem;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Linq;
|
|
using System.Threading.Tasks;
|
|
using TwinCAT.TypeSystem;
|
|
|
|
namespace Test_Beckhoff
|
|
{
|
|
|
|
//var handle = adsClient.AddDeviceNotification("MAIN.boolVal", dataStream, 0, 1,
|
|
// AdsTransMode.OnChange, 100, 0, new object() );
|
|
|
|
// Structure declaration for handles
|
|
|
|
public enum EnuStates //Stato Macchina
|
|
{
|
|
Errore = -1,
|
|
Ferma = 0,
|
|
Automatica = 1,
|
|
Manuale = 2,
|
|
Emergenza = 3,
|
|
AzzeraTavola = 4,
|
|
ManualeStazione = 5,
|
|
Avviamento = 7,
|
|
}
|
|
|
|
public class ADS
|
|
|
|
{
|
|
|
|
public class ComandiADS
|
|
{
|
|
|
|
public TcAdsSymbolInfo Symbol;
|
|
public string SymbolName;
|
|
public bool ComandoScrittua;
|
|
public object Value;
|
|
public ManualResetEventSlim Updating;
|
|
public bool Error;
|
|
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);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dizionario di conversione da indice a index group e index offset
|
|
/// </summary>
|
|
private Dictionary<int, Tuple<int, int>> addressList;
|
|
public delegate void StatusChangedEventHandler(ADS sender, EnuStates newStatus);
|
|
public TcAdsSymbolInfoCollection Symbols;
|
|
private TcAdsClient adsClient;
|
|
public TcAdsClient Client
|
|
{
|
|
get { return adsClient; }
|
|
}
|
|
public TwinCAT.Ads.TcAdsSymbolInfoLoader InfoLoader;
|
|
public TwinCAT.TypeSystem.ISymbolLoader SymbolLoaderInstance;
|
|
|
|
private List<int> addedSignalationList = new List<int>();
|
|
|
|
private int notifyposition;
|
|
private int eventHandle;
|
|
private int SegnalazioniADSEventHandle, StatusChangedEventHandle, MessageQueuedEventHandle;
|
|
|
|
private AdsStream notifyStream;
|
|
private AdsStream newNotificationStream;
|
|
|
|
public bool EnableEvents { get; set; }
|
|
|
|
private EnuStates _status;
|
|
private object lockobj = new object();
|
|
|
|
//private Action<object> dispatcher;
|
|
private System.Threading.Tasks.Task dispatchertask;
|
|
public System.Collections.Concurrent.ConcurrentQueue<ComandiADS> CodaComandi;
|
|
private CancellationTokenSource cts;
|
|
|
|
Symbol StatoMacchina;
|
|
|
|
|
|
public event StatusChangedEventHandler StatusChanged;
|
|
|
|
|
|
public ADS(string indirizzo = "local", int porta = 851)
|
|
{
|
|
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 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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
StatoMacchina = (Symbol)SymbolLoaderInstance.Symbols["VarADS.StatoMacchina"];
|
|
StatoMacchina.NotificationSettings = new AdsNotificationSettings(AdsTransMode.OnChange, 100, 100);
|
|
StatoMacchina.ValueChanged += StatoMacchina_ValueChanged;
|
|
|
|
|
|
notifyposition = 0;
|
|
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;
|
|
dispatchertask = new Task(Azione, cts.Token, TaskCreationOptions.PreferFairness); //Definisce e Crea un Task di base a priorità favorevole
|
|
dispatchertask.Start();
|
|
}
|
|
|
|
|
|
private void StatoMacchina_ValueChanged(object sender, TwinCAT.TypeSystem.ValueChangedArgs e)
|
|
{
|
|
EnuStates newStatus = (EnuStates)e.Value;
|
|
if (StatusChanged != null) StatusChanged(this, newStatus);
|
|
}
|
|
|
|
public void dispose()
|
|
{
|
|
//adsClient.Dispose();
|
|
}
|
|
|
|
|
|
public TcAdsSymbolInfo GetSymbolInfo(string nome)
|
|
{
|
|
try
|
|
{
|
|
var symbol = InfoLoader.FindSymbol(nome);
|
|
return symbol;
|
|
}
|
|
catch (Exception)
|
|
{
|
|
|
|
throw;
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
}
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
|
|
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;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
|
|
|
|
public EnuStates Status
|
|
{
|
|
get
|
|
{
|
|
var stato = ReadVariabile("VarADS.StatoMacchina");
|
|
if (stato != null) _status = (EnuStates)stato;
|
|
else
|
|
{
|
|
throw new Exception("Errore lettura stato");
|
|
}
|
|
return _status;
|
|
}
|
|
}
|
|
}
|
|
|
|
} |