Ok to be more precise, my application is a Windows Service C# application. When I Unsubscribe from a single item it stops updates from the rest of the subscribed items in that client and updates resume after 6, 7 hours later automatically. Here is the exact code I have:
Code:
namespace DES
{
public partial class DataExport : ServiceBase
{
private AutoResetEvent areServiceMain; //Service AutoReset event handler.
private System.Timers.Timer SubscriptionTimer; //Timer to subscribe to new points
private System.Timers.Timer RemoveSubTimer; //Timer to remove subscriptions once a point is deleted.
public String strConnString = ConfigurationManager.ConnectionStrings["ConnectionString"].ToString(); //Database connection string
public SqlCommand cmdCommand;
private EasyDAClient AnalogDAV; //OPC object for subscribing to Analog point values
private EasyDAClient AnalogDAS; //OPC Object for subscribing to Analog point states
private EasyDAClient StatusDAV; //OPC object for subscribing to Status point values
private EasyDAClient StatusDAS; //OPC Object for subscribing to Status point states
private EasyDAClient RemoteDAV; //OPC object for subscribing to Remote Device point values
private EasyDAClient RemoteDAS; //OPC Object for subscribing to Remote Device point states
private EasyDAClient CommDAV; //OPC object for subscribing to Communication point values
private Dictionary<string, string> dicAnalogStatus = new Dictionary<string, string>();
private Dictionary<string, string> dicStatusStatus = new Dictionary<string, string>();
private Dictionary<string, string> dicRemoteStatus = new Dictionary<string, string>();
private Dictionary<string, string> dicCommStatus = new Dictionary<string, string>();
private Dictionary<string, bool> dicUpdatedFlag = new Dictionary<string, bool>();
private Dictionary<string, string> dct = new Dictionary<string, string>(); //Dictionary object to hold point ID's
private Dictionary<string, string> dctStatus = new Dictionary<string, string>(); //Dictionary object to hold status values
private Dictionary<string, string> dctType = new Dictionary<string, string>(); //Dictionary object to hold point types
private Dictionary<string, string> dctADAVH = new Dictionary<string, string>(); //Dictionary object to hold analog value handles returned when subscribing to the point
private Dictionary<string, string> dctADASH = new Dictionary<string, string>(); //Dictionary object to hold analog state value handles returned when subscribing to the point
private Dictionary<string, string> dctSDAVH = new Dictionary<string, string>(); //Dictionary object to hold status value handles returned when subscribing to the point
private Dictionary<string, string> dctSDASH = new Dictionary<string, string>(); //Dictionary object to hold status state value handles returned when subscribing to the point
private Dictionary<string, string> dctRDAVH = new Dictionary<string, string>();
private Dictionary<string, string> dctCDAVH = new Dictionary<string, string>();
public DateTime dStart;
public List<EasyDAItemSubscriptionArguments> itemSubList = new List<EasyDAItemSubscriptionArguments>();
public string theState = "";
EventLog evtLog = new EventLog();
public DataExport()
{
InitializeComponent();
try
{
areServiceMain = new AutoResetEvent(false);
CanPauseAndContinue = false;
EasyDAClient.ClientParameters.TopicProcessingIntervalTimeout = 10;
EasyDAClient.ClientParameters.TopicProcessingTotalTimeout = 500;
EasyDAClient.ClientParameters.LinkCallbackQueueSize = 300000;
EasyDAClient.ClientParameters.RequestQueueSize = 300000;
EasyDAClient.ClientParameters.ResponseQueueSize = 300000;
EasyDAClient.ClientParameters.ClientReconnectDelay = 10000;
EasyDAClient.ClientParameters.TopicRetrialPeriod = 1000;
EasyDAClient.TopicParameters.ExactManualGroupMatch = true;
EasyDAClient.TopicParameters.FastestAutomaticUpdateRate = 10;
EasyDAClient.TopicParameters.SlowestAutomaticUpdateRate = 10000;
EasyDAClient.TopicParameters.TopicRetrialDelay = 10000;
EasyDAClient.EngineParameters.ClientLruSize = 200;
EasyDAClient.EngineParameters.AutoAdjustmentPeriod = 1000;
EasyDAClient.EngineParameters.MaxClientAge = 5000;
EasyDAClient.EngineParameters.TopicLruSize = 300000;
EasyDAClient.EngineParameters.DefaultEventQueueSize = 300000;
AnalogDAV = new EasyDAClient(); //OPC object for subscribing to Analog point values
AnalogDAS = new EasyDAClient(); //OPC Object for subscribing to Analog point states
StatusDAV = new EasyDAClient(); //OPC object for subscribing to Status point values
StatusDAS = new EasyDAClient(); //OPC Object for subscribing to Status point states
RemoteDAV = new EasyDAClient(); //OPC object for subscribing to Remote Device point values
RemoteDAS = new EasyDAClient(); //OPC Object for subscribing to Remote Device point states
CommDAV = new EasyDAClient(); //OPC object for subscribing to Communication point values
}
catch (Exception ex)
{
EventLog.WriteEntry("Application", ex.ToString(), EventLogEntryType.Error);
}
}
#region [Service Events]
protected override void OnStart(string[] args)
{
try
{
evtLog.Source = "DES";
WriteLogEntry("Starting CygNet Data Export Service");
ServiceThread = new Thread(this.ServiceMain);
ServiceThread.Name = "ServiceMain";
ServiceThread.Start();
Thread.Sleep(1000);
}
catch (Exception ex)
{
WriteLogEntry("Service Start Error: " + ex.Message);
}
}
protected override void OnStop()
{
try
{
evtLog.WriteEntry("CygNet Data Export Stopping", EventLogEntryType.Information);
intStopRetry = 1;
intServiceState = ServiceState.isStopping;
areServiceMain.Set(); //Set the signal on the event incase the service is paused before stopping.
//AnalogDAV.Dispose();
//AnalogDAS.Dispose();
//StatusDAV.Dispose();
//StatusDAS.Dispose();
//RemoteDAV.Dispose();
//RemoteDAS.Dispose();
//CommDAV.Dispose();
WriteLogEntry("CygNet Data Export Unsubscribing from all Analog items.");
evtLog.WriteEntry("CygNet Data Export Unsubscribing from all Analog items.", EventLogEntryType.Information);
AnalogDAV.UnsubscribeAllItems();
WriteLogEntry("CygNet Data Export Unsubscribing from all Analog;STATUS items.");
evtLog.WriteEntry("CygNet Data Export Unsubscribing from all Analog;STATUS items.", EventLogEntryType.Information);
AnalogDAS.UnsubscribeAllItems();
WriteLogEntry("CygNet Data Export Unsubscribing from all Status items.");
evtLog.WriteEntry("CygNet Data Export Unsubscribing from all Status items.", EventLogEntryType.Information);
StatusDAV.UnsubscribeAllItems();
WriteLogEntry("CygNet Data Export Unsubscribing from all Status;STATUS items.");
evtLog.WriteEntry("CygNet Data Export Unsubscribing from all Status;STATUS items.", EventLogEntryType.Information);
StatusDAS.UnsubscribeAllItems();
WriteLogEntry("CygNet Data Export Unsubscribing from all Remote items.");
evtLog.WriteEntry("CygNet Data Export Unsubscribing from all Remote items.", EventLogEntryType.Information);
RemoteDAV.UnsubscribeAllItems();
WriteLogEntry("CygNet Data Export Unsubscribing from all Comm items.");
evtLog.WriteEntry("CygNet Data Export Unsubscribing from all Comm items.", EventLogEntryType.Information);
CommDAV.UnsubscribeAllItems();
while (intStopRetry < 91)
{
WriteLogEntry("CygNet Data Export Stopping: " + intStopRetry.ToString());
evtLog.WriteEntry("CygNet Data Export Stopping: " + intStopRetry.ToString(), EventLogEntryType.Information);
if (intServiceState == ServiceState.isStopped)
{
WriteLogEntry("Service is stopped");
break;
}
else
{
RequestAdditionalTime(3000);
Thread.Sleep(1000);
intStopRetry = intStopRetry + 1;
}
}
if (intServiceState != ServiceState.isStopped)
{
WriteLogEntry("CygNet Data Export Aborting");
ServiceThread.Abort();
}
}
catch (Exception ex)
{
WriteLogEntry("CygNet Data Export Service stop error: " + ex.Message);
}
finally
{
//StopTimer.Dispose();
}
}
#endregion
#region [Timer Functions]
private void SubscriptionTimerEvent(object obj, ElapsedEventArgs e)
{
//This timer calls the subscribe subroutine to subscribe to new points inserted in the database
//WriteLogEntry("Attempting to subscribe to new items...");
try
{
Console.WriteLine(DateTime.Now.ToString() + ": SubscriptionTimerEvent fired.");
WriteLogEntry("SubscriptionTimerEvent fired.");
Subscribe(true, false, "ANALOG");
Subscribe(true, false, "STATUS");
Subscribe(true, false, "REMOTE");
Subscribe(true, false, "COMM");
}
catch (Exception ex)
{
WriteLogEntry("EXCEPTION: SubscriptionTimerEvent: " + ex.Message);
}
}
private void RemoveSubTimerEvent(object obj, ElapsedEventArgs e)
{
//This timer attempts to remove points from subscription if they are marked as deleted.
WriteLogEntry("RemoveSubTimerEvent fired.");
try
{
RemoveSubscriptions("ANALOG");
RemoveSubscriptions("STATUS");
RemoveSubscriptions("REMOTE");
RemoveSubscriptions("COMM");
}
catch (Exception ex)
{
WriteLogEntry("EXCEPTION: RemoveSubTimerEvent: " + ex.Message);
}
}
#endregion
#region [Service Main Process]
public void ServiceMain()
{
string strServerName = Environment.MachineName; //Hold variable for processing changes in the app.config file.
ConnectionOptions connOptions = new ConnectionOptions();
ManagementScope mgntScope = new ManagementScope();
ManagementPath mgntPath = new ManagementPath();
try
{
AnalogDAV.ClientMode.AllowAsynchronousMethod = true;
AnalogDAV.ClientMode.DesiredMethod = DAReadWriteMethod.Asynchronous;
AnalogDAV.HoldPeriods.ItemDetach = 0;
AnalogDAV.HoldPeriods.ServerDetach = 30000;
AnalogDAV.HoldPeriods.TopicRead = 120000;
AnalogDAV.UpdateRates.ReadAutomatic = 10;
AnalogDAV.Timeouts.ReadItem = 20000;
AnalogDAV.Timeouts.GetProperty = 10000;
//AnalogDAV.SynchronizationContext = null;
AnalogDAV.Isolated = true;
AnalogDAS.ClientMode.AllowAsynchronousMethod = true;
AnalogDAS.ClientMode.DesiredMethod = DAReadWriteMethod.Asynchronous;
AnalogDAS.HoldPeriods.ItemDetach = 0;
AnalogDAS.HoldPeriods.ServerDetach = 30000;
AnalogDAS.HoldPeriods.TopicRead = 120000;
AnalogDAS.UpdateRates.ReadAutomatic = 10;
AnalogDAS.Timeouts.ReadItem = 20000;
AnalogDAS.Timeouts.GetProperty = 10000;
//AnalogDAS.SynchronizationContext = null;
AnalogDAS.Isolated = true;
StatusDAV.ClientMode.AllowAsynchronousMethod = true;
StatusDAV.ClientMode.DesiredMethod = DAReadWriteMethod.Asynchronous;
StatusDAV.HoldPeriods.ItemDetach = 0;
StatusDAV.HoldPeriods.ServerDetach = 30000;
StatusDAV.HoldPeriods.TopicRead = 120000;
StatusDAV.UpdateRates.ReadAutomatic = 10;
StatusDAV.Timeouts.ReadItem = 20000;
StatusDAV.Timeouts.GetProperty = 10000;
//StatusDAV.SynchronizationContext = null;
StatusDAV.Isolated = true;
StatusDAS.ClientMode.AllowAsynchronousMethod = true;
StatusDAS.ClientMode.DesiredMethod = DAReadWriteMethod.Asynchronous;
StatusDAS.HoldPeriods.ItemDetach = 0;
StatusDAS.HoldPeriods.ServerDetach = 30000;
StatusDAS.HoldPeriods.TopicRead = 120000;
StatusDAS.UpdateRates.ReadAutomatic = 10;
StatusDAS.Timeouts.ReadItem = 20000;
StatusDAS.Timeouts.GetProperty = 10000;
//StatusDAS.SynchronizationContext = null;
StatusDAS.Isolated = true;
RemoteDAV.ClientMode.AllowAsynchronousMethod = true;
RemoteDAV.ClientMode.DesiredMethod = DAReadWriteMethod.Asynchronous;
RemoteDAV.HoldPeriods.ItemDetach = 0;
RemoteDAV.HoldPeriods.ServerDetach = 30000;
RemoteDAV.HoldPeriods.TopicRead = 120000;
RemoteDAV.UpdateRates.ReadAutomatic = 10;
RemoteDAV.Timeouts.ReadItem = 20000;
RemoteDAV.Timeouts.GetProperty = 10000;
//RemoteDAV.SynchronizationContext = null;
RemoteDAV.Isolated = true;
RemoteDAS.ClientMode.AllowAsynchronousMethod = true;
RemoteDAS.ClientMode.DesiredMethod = DAReadWriteMethod.Asynchronous;
RemoteDAS.HoldPeriods.ItemDetach = 0;
RemoteDAS.HoldPeriods.ServerDetach = 30000;
RemoteDAS.HoldPeriods.TopicRead = 120000;
RemoteDAS.UpdateRates.ReadAutomatic = 10;
RemoteDAS.Timeouts.ReadItem = 20000;
RemoteDAS.Timeouts.GetProperty = 10000;
//RemoteDAS.SynchronizationContext = null;
RemoteDAS.Isolated = true;
CommDAV.ClientMode.AllowAsynchronousMethod = true;
CommDAV.ClientMode.DesiredMethod = DAReadWriteMethod.Asynchronous;
CommDAV.HoldPeriods.ItemDetach = 0;
CommDAV.HoldPeriods.ServerDetach = 30000;
CommDAV.HoldPeriods.TopicRead = 120000;
CommDAV.UpdateRates.ReadAutomatic = 10;
CommDAV.Timeouts.ReadItem = 20000;
CommDAV.Timeouts.GetProperty = 10000;
//CommDAV.SynchronizationContext = null;
CommDAV.Isolated = true;
intServiceState = ServiceState.isRunning;
evtLog.Source = "DES";
//Initialize the Subscription Timer.
SubscriptionTimer = new System.Timers.Timer();
SubscriptionTimer.Elapsed += new System.Timers.ElapsedEventHandler(SubscriptionTimerEvent);
SubscriptionTimer.Enabled = false;
string strSubInt = ConfigurationManager.AppSettings.Get("SubscriptionTimer");
string strSubEn = ConfigurationManager.AppSettings.Get("SubscriptionTimerEnable");
int SubInt = 0;
if (Information.IsNumeric(strSubInt))
SubInt = Convert.ToInt32(strSubInt);
SubscriptionTimer.Interval = (SubInt * 60000);
//Initialize the Remove Subscription Timer.
RemoveSubTimer = new System.Timers.Timer();
RemoveSubTimer.Elapsed += new System.Timers.ElapsedEventHandler(RemoveSubTimerEvent);
RemoveSubTimer.Enabled = false;
string strRemSubInt = ConfigurationManager.AppSettings.Get("UnsubscribeTimer");
string strRemSubEn = ConfigurationManager.AppSettings.Get("UnsubscribeTimerEnable");
int RemSubInt = 0;
if (Information.IsNumeric(strRemSubInt))
RemSubInt = Convert.ToInt32(strRemSubInt);
RemoveSubTimer.Interval = (RemSubInt * 60000);
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
Subscribe(false, false, "ANALOG");
});
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
Subscribe(false, false, "STATUS");
});
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
Subscribe(false, false, "REMOTE");
});
System.Threading.Tasks.Task.Factory.StartNew(() =>
{
Subscribe(false, false, "COMM");
}).Wait();
while (true)
{
try
{
if (!SubscriptionTimer.Enabled & strSubEn == "true")
{
WriteLogEntry("Subscription Timer Started...");
SubscriptionTimer.Enabled = true;
SubscriptionTimer.Start();
}
if (!RemoveSubTimer.Enabled & strRemSubEn == "true")
{
WriteLogEntry("Remove Subscription Timer Started...");
RemoveSubTimer.Enabled = true;
RemoveSubTimer.Start();
}
if (intServiceState == ServiceState.isStopping)
intServiceState = ServiceState.isStopped;
if (intServiceState == ServiceState.isStopped) //If the service is marked as stopped exit the while(true) loop.
break;
ConfigurationManager.RefreshSection("appSettings");
}
catch (Exception ex)
{
evtLog.WriteEntry("Failed (while(true)): " + ex.Message, EventLogEntryType.Error);
}
finally
{
if (bolDebug)
Console.WriteLine("Ping " + System.DateTime.Now.ToString());
areServiceMain.WaitOne(20000);
}
} //while (true)
WriteLogEntry("Exited while loop");
areServiceMain.Set();
}
catch (Exception ex)
{
evtLog.WriteEntry("Data Export failed (Main Loop): " + ex.Message, EventLogEntryType.Error);
}
finally
{
System.Environment.Exit(0);
}
}
#endregion
#region [Point Subscriptions]
public void Subscribe(bool onTimer, bool isPointState, string strType)
{
//This routine subscribes to points by getting the records in 1 of 4 tables. It is called on startup and when subscribing to new points
dStart = DateTime.Now;
string strTag = "";
string strSQL = "";
string strSiteService = ConfigurationManager.AppSettings.Get("SiteService");
string strFacility = "";
string strUDC = "";
string strPointId = "";
string strPointType = "";
int Result = 0;
int ResultStatus = 0;
int i = 0;
string strCommStatusUDC = ConfigurationManager.AppSettings.Get("CommUDC.Status");
string strCommStateUDC = ConfigurationManager.AppSettings.Get("CommUDC.State");
string strRemoteStateUDC = ConfigurationManager.AppSettings.Get("RemoteUDC.State");
try
{
//Identify the proper SQL statement to use
switch (strType)
{
case "ANALOG":
if (onTimer)
{
strSQL = "SELECT * from [TABLE_ANA] WHERE [SubFlag] = 'Add'";
}
else
{
strSQL = "SELECT * from [TABLE_ANA] WHERE [SubFlag]='Yes'";
}
break;
case "STATUS":
if (onTimer)
{
strSQL = "SELECT * from [TABLE_ST] WHERE [SubFlag] = 'Add'";
}
else
{
strSQL = "SELECT * from [TABLE_ST] WHERE [SubFlag]='Yes'";
}
break;
case "COMM":
if (onTimer)
{
strSQL = "SELECT * from [TABLE_COMM] WHERE [SubFlag] = 'Add'";
}
else
{
strSQL = "SELECT * from [TABLE_COMM] WHERE [SubFlag]='Yes'";
}
break;
case "REMOTE":
if (onTimer)
{
strSQL = "SELECT * from [TABLE_RMT] WHERE [SubFlag] = 'Add'";
}
else
{
strSQL = "SELECT * from [TABLE_RMT] WHERE [SubFlag]='Yes'";
}
break;
}
SqlDataAdapter AnalogDataAdapter = new SqlDataAdapter(strSQL, strConnString);
DataSet AnalogDataSet = new DataSet("Analog");
AnalogDataAdapter.Fill(AnalogDataSet);
if (AnalogDataSet.Tables[0].Rows.Count > 0)
{
foreach (DataRow dRow in AnalogDataSet.Tables[0].Rows)
{
if (strType == "ANALOG" | strType == "STATUS")
{
strSiteService = dRow["SiteService"].ToString();
strFacility = dRow["Facility"].ToString();
strUDC = dRow["PointCode"].ToString();
}
else
{
//Added a dummy UDC to get past the next if block
strUDC = "XXX";
}
if (strUDC != "") //The process will error out if the UDC is blank
{
switch (strType)
{
case "ANALOG":
strPointType = dRow["PointType"].ToString();
strPointId = dRow["ANA_ID"].ToString();
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strUDC);
if (dct.ContainsKey(strTag))
dct[strTag] = strPointId;
else
dct.Add(strTag, strPointId);
if (dctType.ContainsKey(strTag + ";TYPE"))
dctType[strTag + ";TYPE"] = strPointType;
else
dctType.Add(strTag + ";TYPE", strPointType);
Result = AnalogDAV.SubscribeItem("", "CygNet.OPCServer.1", strTag, 500, new System.EventHandler<EasyDAItemChangedEventArgs>(AnalogItemChanged));
ResultStatus = AnalogDAS.SubscribeItem("", "CygNet.OPCServer.1", strTag + ";STATUS", 1000, new System.EventHandler<EasyDAItemChangedEventArgs>(AnalogItemStatusChanged));
//Add the resulting index to the dictionary so we can unsubscribe later if needed
if (dctADAVH.ContainsKey(strTag))
dctADAVH[strTag] = Result.ToString();
else
dctADAVH.Add(strTag, Result.ToString());
if (dctADASH.ContainsKey(strTag))
dctADASH[strTag] = ResultStatus.ToString();
else
dctADASH.Add(strTag, ResultStatus.ToString());
if (onTimer)
//Mark the new records so we don't subscribe to them again
UpdateSubscriptionFlag(strType, strPointId, "Yes");
break;
case "STATUS":
strPointType = dRow["DATATYPE"].ToString();
strPointId = dRow["Status_id"].ToString();
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strUDC);
if (dct.ContainsKey(strTag))
dct[strTag] = strPointId;
else
dct.Add(strTag, strPointId);
if (dctType.ContainsKey(strTag + ";TYPE"))
dctType[strTag + ";TYPE"] = strPointType;
else
dctType.Add(strTag + ";TYPE", strPointType);
Result = StatusDAV.SubscribeItem("", "CygNet.OPCServer.1", strTag, 1000, new System.EventHandler<EasyDAItemChangedEventArgs>(StatusItemChanged));
ResultStatus = StatusDAS.SubscribeItem("", "CygNet.OPCServer.1", strTag + ";STATUS", 1000, new System.EventHandler<EasyDAItemChangedEventArgs>(StatusItemStatusChanged));
//Add the resulting index to the dictionary so we can unsubscribe later if needed
if (dctSDAVH.ContainsKey(strTag))
dctSDAVH[strTag] = Result.ToString();
else
dctSDAVH.Add(strTag, Result.ToString());
if (dctSDASH.ContainsKey(strTag))
dctSDASH[strTag] = ResultStatus.ToString();
else
dctSDASH.Add(strTag, ResultStatus.ToString());
if (onTimer)
//Mark the new records so we don't subscribe to them again
UpdateSubscriptionFlag(strType, strPointId, "Yes");
break;
case "COMM":
strFacility = dRow["NAME"].ToString();
//Add the Comm State tag
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strCommStateUDC);
Result = CommDAV.SubscribeItem("", "CygNet.OPCServer.1", strTag, 1000, new System.EventHandler<EasyDAItemChangedEventArgs>(CommItemChanged));
//Add the resulting index to the dictionary so we can unsubscribe later if needed
if (dctCDAVH.ContainsKey(strTag))
dctCDAVH[strTag] = Result.ToString();
else
dctCDAVH.Add(strTag, Result.ToString());
i++;
//Add the Comm Status tag
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strCommStatusUDC);
Result = CommDAV.SubscribeItem("", "CygNet.OPCServer.1", strTag, 1000, new System.EventHandler<EasyDAItemChangedEventArgs>(CommItemChanged));
//Add the resulting index to the dictionary so we can unsubscribe later if needed
if (dctCDAVH.ContainsKey(strTag))
dctCDAVH[strTag] = Result.ToString();
else
dctCDAVH.Add(strTag, Result.ToString());
if (onTimer)
//Mark the new records so we don't subscribe to them again
UpdateSubscriptionFlag(strType, strFacility, "Yes");
break;
case "REMOTE":
strFacility = dRow["NAME"].ToString();
//Add the Remote State tag
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strRemoteStateUDC);
Result = RemoteDAV.SubscribeItem("", "CygNet.OPCServer.1", strTag, 1000, new System.EventHandler<EasyDAItemChangedEventArgs>(RemoteItemChanged));
//Add the resulting index to the dictionary so we can unsubscribe later if needed
if (dctRDAVH.ContainsKey(strTag))
dctRDAVH[strTag] = Result.ToString();
else
dctRDAVH.Add(strTag, Result.ToString());
if (onTimer)
//Mark the new records so we don't subscribe to them again
UpdateSubscriptionFlag(strType, strFacility, "Yes");
break;
}
i++;
}
}
//AnalogDAV.SubscribeMultipleItems(itemSubList.ToArray());
if (!onTimer & i > 0) //Log the first run. After that, only log if new points are added.
{
WriteLogEntry("Added " + i.ToString() + " " + strType + " points to monitor in " + DateAndTime.DateDiff(DateInterval.Second, dStart, DateTime.Now).ToString() + " seconds");
evtLog.WriteEntry("Added " + i.ToString() + " " + strType + " points to monitor in " + DateAndTime.DateDiff(DateInterval.Second, dStart, DateTime.Now).ToString() + " seconds");
}
}
}
catch(Exception ex)
{
WriteLogEntry("EXCEPTION: SubcribeFromTable: " + ex.ToString() + ": " + strTag);
}
}
#endregion
#region[Event Handlers]
private void AnalogItemChanged(object sender, EasyDAItemChangedEventArgs e)
{
//This handles the Analog point value change
string strTag = "";
string strStatusValue = "";
string strIsManualInput = "";
try
{
DAVtq analogVtq = e.Vtq;
strTag = e.ItemDescriptor.ItemId;
if (e.Exception != null)
{
Console.WriteLine("Analog Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
WriteLogEntry("Analog Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
}
else
{
if (analogVtq.HasValue()) //Check to see if the object has a valid value. Otherwise several unnecessary errors are thrown
{
strStatusValue = AnalogDAV.GetPropertyValueString("", "CygNet.OPCServer.1", e.ItemDescriptor.ItemId, 5008);
if (dicAnalogStatus.ContainsKey(strTag))
dicAnalogStatus[strTag] = strStatusValue.ToString().Trim();
else
dicAnalogStatus.Add(strTag, strStatusValue.ToString().Trim());
UpdateAnalog(e.ItemDescriptor.ItemId, analogVtq.Value.ToString().Trim(), analogVtq.Timestamp.ToString(), strStatusValue, strIsManualInput);//updates the database with values
}
else
{
Console.WriteLine("Analog Item has no value. ItemId: " + e.ItemDescriptor.ItemId);
}
}
}
catch (Exception ex)
{
String errorStr = "";
errorStr = ex.GetBaseException().Message + "\n" + ex.Source + "\n" + ex.StackTrace + "\n" + ex.InnerException.StackTrace;
WriteLogEntry("EXCEPTION: Failed on AnalogItemChanged: " + errorStr + " ItemId: " + e.ItemDescriptor.ItemId);
}
}
private void AnalogItemStatusChanged(object sender, EasyDAItemChangedEventArgs e)
{
//This handles the Analog point status value change
string strTag = "";
int intStatus = 0;
int intPrevStatus = -99;
string strCygVal = "";
try
{
DAVtq analogVtq = e.Vtq;
strTag = e.ItemDescriptor.ItemId;
if (e.Exception != null)
{
Console.WriteLine("Analog Status Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
WriteLogEntry("Analog Status Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
}
else
{
//{
if (analogVtq.HasValue()) //Check to see if the object has a valid value. Otherwise several unnecessary errors are thrown
{
strCygVal = AnalogDAV.GetPropertyValueString("", "CygNet.OPCServer.1", e.ItemDescriptor.ItemId.Replace(";STATUS", ""), 2);
intStatus = Convert.ToInt32(analogVtq.Value.ToString().Trim());
if (dicAnalogStatus.ContainsKey(strTag))
{
intPrevStatus = Convert.ToInt32(dicAnalogStatus[strTag]);
dicAnalogStatus[strTag] = analogVtq.Value.ToString().Trim();
}
else
dicAnalogStatus.Add(strTag, analogVtq.Value.ToString().Trim());
UpdateItemStatus(e.ItemDescriptor.ItemId, analogVtq.Value.ToString().Trim(), analogVtq.Timestamp.ToString(), "ANALOG", strCygVal);//updates the database with values
}
else
{
Console.WriteLine("Analog Item Status has no value. ItemId: " + e.ItemDescriptor.ItemId);
}
}
}
catch (Exception ex)
{
String errorStr = "";
errorStr = ex.GetBaseException().Message + "\n" + ex.Source + "\n" + ex.StackTrace;
WriteLogEntry("EXCEPTION: Failed on AnalogItemStatusChanged: " + errorStr + " ItemId: " + e.ItemDescriptor.ItemId);
}
}
private void StatusItemChanged(object sender, EasyDAItemChangedEventArgs e)
{
//This handles the status point value change
string strStatusValue = "";
string strTag = "";
string strIsManualInput = "";
try
{
DAVtq statusVtq = e.Vtq;
strTag = e.ItemDescriptor.ItemId;
if (e.Exception != null)
{
Console.WriteLine("Status Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
}
else
{
if (statusVtq.HasValue()) //Check to see if the object has a valid value. Otherwise several unnecessary errors are thrown
{
strStatusValue = StatusDAV.GetPropertyValueString("", "CygNet.OPCServer.1", e.ItemDescriptor.ItemId, 5008);
if (dicStatusStatus.ContainsKey(strTag))
dicStatusStatus[strTag] = strStatusValue.ToString().Trim();
else
dicStatusStatus.Add(strTag, strStatusValue.ToString().Trim());
UpdateStatus(e.ItemDescriptor.ItemId, statusVtq.Value.ToString().Trim(), statusVtq.Timestamp.ToString(), strStatusValue, strIsManualInput);//updates the database with values
}
else
{
Console.WriteLine("Status Item has no value. ItemId: " + e.ItemDescriptor.ItemId);
}
}
}
catch (Exception ex)
{
String errorStr = "";
errorStr = ex.GetBaseException().Message + "\n" + ex.Source + "\n" + ex.StackTrace;
WriteLogEntry("EXCEPTION: Failed on StatusItemChanged: " + errorStr + ": " + e.ItemDescriptor.ItemId);
}
}
private void StatusItemStatusChanged(object sender, EasyDAItemChangedEventArgs e)
{
//This handles the Status point status value change
string strTag = "";
int intStatus = 0;
int intPrevStatus = 0;
string strCygVal = "";
try
{
DAVtq statusVtq = e.Vtq;
strTag = e.ItemDescriptor.ItemId;
if (e.Exception != null)
{
Console.WriteLine("Status Status Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
}
else
{
if (statusVtq.HasValue()) //Check to see if the object has a valid value. Otherwise several unnecessary errors are thrown
{
strCygVal = StatusDAV.GetPropertyValueString("", "CygNet.OPCServer.1", e.ItemDescriptor.ItemId.Replace(";STATUS", ""), 2);
intStatus = Convert.ToInt32(statusVtq.Value.ToString().Trim());
if (dicStatusStatus.ContainsKey(strTag))
{
intPrevStatus = Convert.ToInt32(dicStatusStatus[strTag]);
dicStatusStatus[strTag] = statusVtq.Value.ToString().Trim();
}
else
dicStatusStatus.Add(strTag, statusVtq.Value.ToString().Trim());
UpdateItemStatus(e.ItemDescriptor.ItemId, statusVtq.Value.ToString().Trim(), statusVtq.Timestamp.ToString(), "STATUS", strCygVal);//updates the database with values
}
else
{
Console.WriteLine("Status Item Status has no value. ItemId: " + e.ItemDescriptor.ItemId);
}
}
}
catch (Exception ex)
{
String errorStr = "";
errorStr = ex.GetBaseException().Message + "\n" + ex.Source + "\n" + ex.StackTrace;
WriteLogEntry("EXCEPTION: Failed on StatusItemStatusChanged: " + errorStr + " ItemId: " + e.ItemDescriptor.ItemId);
}
}
private void RemoteItemChanged(object sender, EasyDAItemChangedEventArgs e)
{
string strStatusValue = "";
string strTag = "";
string strIsManualInput = "";
try
{
DAVtq remoteVtq = e.Vtq;
strTag = e.ItemDescriptor.ItemId;
if (e.Exception != null)
{
Console.WriteLine("Remote Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
WriteLogEntry("Remote Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
}
else
{
if (remoteVtq.HasValue())
{
RemoteDAS.UpdateRates.ReadAutomatic = 10;
strStatusValue = RemoteDAS.GetPropertyValueString("", "CygNet.OPCServer.1", e.ItemDescriptor.ItemId, 5008);
UpdateRemote(e.ItemDescriptor.ItemId, remoteVtq.Value.ToString().Trim(), remoteVtq.Timestamp.ToString(), strStatusValue, strIsManualInput);//updates the database with values
}
else
{
Console.WriteLine("Remote Item has no value. ItemId: " + e.ItemDescriptor.ItemId);
}
}
}
catch (Exception ex)
{
String errorStr = "";
errorStr = ex.GetBaseException().Message + "\n" + ex.Source + "\n" + ex.StackTrace;
WriteLogEntry("EXCEPTION: Failed on RemoteItemChanged: " + errorStr + ": " + e.ItemDescriptor.ItemId);
}
}
private void CommItemChanged(object sender, EasyDAItemChangedEventArgs e)
{
string strStatusValue = "";
string strTag = "";
string strIsManualInput = "";
try
{
DAVtq commVtq = e.Vtq;
strTag = e.ItemDescriptor.ItemId;
if (e.Exception != null)
{
Console.WriteLine("Comm Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
WriteLogEntry("Comm Error: " + e.ErrorMessage + " " + e.Exception.Source + " " + e.Exception.ToString());
}
else
{
if (commVtq.HasValue())
{
UpdateComm(e.ItemDescriptor.ItemId, commVtq.Value.ToString().Trim(), commVtq.Timestamp.ToString(), strStatusValue, strIsManualInput);//updates the database with values
}
else
{
Console.WriteLine("Comm Item has no value. ItemId: " + e.ItemDescriptor.ItemId);
}
}
}
catch (Exception ex)
{
String errorStr = "";
errorStr = ex.GetBaseException().Message + "\n" + ex.Source + "\n" + ex.StackTrace;
WriteLogEntry("EXCEPTION: Failed on CommItemChanged: " + errorStr + ": " + e.ItemDescriptor.ItemId);
}
}
#endregion
#region[Database Updates]
private void UpdateSubscriptionFlag(string strType, string strPointId, string flagStr)
{
try
{
string strSQL = "";
int retries = 0;
switch (strType)
{
case "ANALOG":
strSQL = String.Format("UPDATE [TABLE_ANA] SET [SubFlag] = '" + flagStr + "' WHERE [name] = {0}", strPointId);
break;
case "STATUS":
strSQL = String.Format("UPDATE [TABLE_ST] SET [SubFlag] = '" + flagStr + "' WHERE [name] = {0}", strPointId);
break;
case "COMM":
strSQL = String.Format("UPDATE [TABLE_COMM] SET [SubFlag] = '" + flagStr + "' WHERE [name] = {0}", strPointId);
break;
case "REMOTE":
strSQL = String.Format("UPDATE [TABLE_RMT] SET [SubFlag] = '" + flagStr + "' WHERE [name] = {0}", strPointId);
break;
}
using (SqlConnection sqlConn = new SqlConnection(strConnString))
{
while (true)
{
try
{
if (sqlConn.State == ConnectionState.Closed)
sqlConn.Open();
else if (sqlConn.State == ConnectionState.Broken)
{
sqlConn.Close();
sqlConn.Open();
}
SqlCommand command = new SqlCommand(strSQL, sqlConn);
command.CommandTimeout = 120;
command.ExecuteNonQuery();
if (sqlConn.State != ConnectionState.Closed)
sqlConn.Close();
break;
}
catch (Exception)
{
retries++;
if (retries > 2) throw;
}
}
}
//WriteLogEntry(strSQL);
WriteLogEntry("UpdateSubscriptionFlag: Flagged " + strPointId + " of type " + strType + " as: " + flagStr);
}
catch(Exception ex)
{
WriteLogEntry("EXCEPTION: UpdateSubscriptionFlag: " + ex.Message);
}
}
private void RemoveSubscriptions(string strType)
{
//This routine attempts to remove points from the subscription
//*** Note: When this was originally tested, it appeared that if a point was unsubscribed, then none of the other subscribed points would continue updating
try
{
string strSQL = "";
string strSiteService = ConfigurationManager.AppSettings.Get("SiteService");
string strFacility = "";
string strUDC = "";
string strTag = "";
string strPointId = "";
string strTagStatus = "";
string strResult = "";
string strResultStatus = "";
int intResult = 0;
int intResultStatus = 0;
int x = 0;
string strCommStatusUDC = ConfigurationManager.AppSettings.Get("CommUDC.Status");
string strCommStateUDC = ConfigurationManager.AppSettings.Get("CommUDC.State");
string strRemoteStateUDC = ConfigurationManager.AppSettings.Get("RemoteUDC.State");
switch (strType)
{
case "ANALOG":
strSQL = "SELECT * from [TABLE_ANA] WHERE [SubFlag] = 'Rem'";
break;
case "STATUS":
strSQL = "SELECT * from [TABLE_ST] WHERE [SubFlag] = 'Rem'";
break;
case "COMM":
strSQL = "SELECT * from [TABLE_COMM] WHERE [SubFlag] = 'Rem'";
break;
case "REMOTE":
strSQL = "SELECT * from [TABLE_RMT] WHERE [SubFlag] = 'Rem'";
break;
}
SqlDataAdapter DA = new SqlDataAdapter(strSQL, strConnString);
DataSet DS = new DataSet("Analog");
DA.Fill(DS);
foreach (DataRow dRow in DS.Tables[0].Rows)
{
switch (strType)
{
case "ANALOG":
strSiteService = dRow["SiteService"].ToString();
strFacility = dRow["Facility"].ToString();
strUDC = dRow["PointCode"].ToString();
strPointId = dRow["ANA_ID"].ToString();
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strUDC);
if (dctADAVH.TryGetValue(strTag, out strResult) && dctADASH.TryGetValue(strTag, out strResultStatus))
{
if (Information.IsNumeric(strResult) && Information.IsNumeric(strResultStatus))
{
intResult = Convert.ToInt32(strResult);
intResultStatus = Convert.ToInt32(strResultStatus);
AnalogDAV.UnsubscribeItem(intResult);
AnalogDAS.UnsubscribeItem(intResultStatus);
dctADAVH.Remove(strTag);
dctADASH.Remove(strTag);
UpdateSubscriptionFlag(strType, strPointId, "No");
WriteLogEntry("RemoveSubscriptions: Removed Analog subscription for " + strTag);
}
}
else
{
WriteLogEntry("RemoveSubscriptions: Could not remove Analog " + strTag + ", tag not in subscription dictionary.");
}
break;
case "STATUS":
strSiteService = dRow["SiteService"].ToString();
strFacility = dRow["Facility"].ToString();
strUDC = dRow["PointCode"].ToString();
strPointId = dRow["Status_id"].ToString();
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strUDC);
if (dctSDAVH.TryGetValue(strTag, out strResult) && dctSDASH.TryGetValue(strTag, out strResultStatus))
{
if (Information.IsNumeric(strResult) && Information.IsNumeric(strResultStatus))
{
intResult = Convert.ToInt32(strResult);
intResultStatus = Convert.ToInt32(strResultStatus);
StatusDAV.UnsubscribeItem(intResult);
StatusDAS.UnsubscribeItem(intResultStatus);
dctSDAVH.Remove(strTag);
dctSDASH.Remove(strTag);
UpdateSubscriptionFlag(strType, strPointId, "No");
WriteLogEntry("RemoveSubscriptions: Removed Status subscription for " + strTag);
}
}
else
{
WriteLogEntry("RemoveSubscriptions: Could not remove Status " + strTag + ", tag not in subscription dictionary.");
}
break;
case "COMM":
strFacility = dRow["NAME"].ToString();
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strCommStateUDC);
strTagStatus = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strCommStatusUDC);
if (dctCDAVH.TryGetValue(strTag, out strResult) && dctCDAVH.TryGetValue(strTagStatus, out strResultStatus))
{
if (Information.IsNumeric(strResult) && Information.IsNumeric(strResultStatus))
{
intResult = Convert.ToInt32(strResult);
intResultStatus = Convert.ToInt32(strResultStatus);
CommDAV.UnsubscribeItem(intResult);
CommDAV.UnsubscribeItem(intResultStatus);
dctCDAVH.Remove(strTag);
dctCDAVH.Remove(strTagStatus);
UpdateSubscriptionFlag(strType, strFacility, "No");
WriteLogEntry("RemoveSubscriptions: Removed Comm subscription for " + strTag + " and " + strTagStatus);
}
}
else
{
WriteLogEntry("RemoveSubscriptions: Could not remove Comm " + strTag + ", tag not in subscription dictionary.");
}
break;
case "REMOTE":
strFacility = dRow["NAME"].ToString();
strTag = String.Format("{0}::{1}.{2}", strSiteService, strFacility, strRemoteStateUDC);
if (dctRDAVH.TryGetValue(strTag, out strResult))
{
if (Information.IsNumeric(strResult))
{
intResult = Convert.ToInt32(strResult);
RemoteDAV.UnsubscribeItem(intResult);
dctRDAVH.Remove(strTag);
UpdateSubscriptionFlag(strType, strFacility, "No");
WriteLogEntry("RemoveSubscriptions: Removed Remote subscription for " + strTag);
}
}
else
{
WriteLogEntry("RemoveSubscriptions: Could not remove Remote " + strTag + ", tag not in 'dctRDAVH' subscription dictionary.");
}
break;
}
x++;
}
WriteLogEntry("RemoveSubscriptions: Removed " + x + " " + strType + " points from subscription");
}
catch (Exception ex)
{
WriteLogEntry("EXCEPTION: RemoveSubscriptions: " + ex.Message);
}
}
private void UpdateAnalog(string Tag, string Value, string Timestamp, string cygStatus, string cygIsManual)
{
//This routine updates the Analog table with current values and status
}
public void UpdateItemStatus(string Tag, string Value, string Timestamp, string recordType, string cygValue)
{
//This routine updates the table with current status
}
private void UpdateStatus(string Tag, string Value, string Timestamp, string cygStatus, string cygIsManual)
{
//This routine updates the Status table with values and status for Enumeration and Digital points
}
private void UpdateRemote(string Tag, string Value, string Timestamp, string cygStatus, string cygIsManual)
{
//This routine updates the current state for the Remote devices
}
private void UpdateComm(string strTag, string strValue, string strTimestamp, string cygStatus, string cygIsManual)
{
//This routine updates the Comm table with current state values
}
#endregion
private void InitializeComponent()
{
//
// DataExport
//
this.ServiceName = "DES";
}
}
}