Difference between revisions of "QuickOPC.NET: How to log OPC Alarms and Events notifications into an XML file"

From OPC Labs Knowledge Base
Jump to navigation Jump to search
(Created page with "The example below subscribes to all notifications from an OPC A&E Server, and logs the event notifications to an XML file. There are three factors that make the code very sho...")
 
Line 6: Line 6:
 
* There is no need for reconnection logic (more about this further down in this post).  
 
* There is no need for reconnection logic (more about this further down in this post).  
  
 +
        <span style='color:#800000; font-weight:bold; '>static</span> <span style='color:#800000; font-weight:bold; '>void</span> Main<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span>
 +
        <span style='color:#800080; '>{</span>
 +
            Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>Starting up...</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
            <span style='color:#800000; font-weight:bold; '>var</span> xmlSerializer <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>new</span> XmlSerializer<span style='color:#808030; '>(</span><span style='color:#800000; font-weight:bold; '>typeof</span><span style='color:#808030; '>(</span>EasyAENotificationEventArgs<span style='color:#808030; '>)</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
            <span style='color:#800000; font-weight:bold; '>var</span> xmlWriter <span style='color:#808030; '>=</span> XmlWriter<span style='color:#808030; '>.</span>Create<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>OpcEvents.xml</span><span style='color:#800000; '>"</span><span style='color:#808030; '>,</span> <span style='color:#800000; font-weight:bold; '>new</span> XmlWriterSettings
 +
            <span style='color:#800080; '>{</span>
 +
                Indent <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>true</span><span style='color:#808030; '>,</span>
 +
                CloseOutput <span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>true</span>
 +
            <span style='color:#800080; '>}</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
            <span style='color:#696969; '>// The root element can have any name you need, but the name below also allows reading the log back as .NET array</span>
 +
            xmlWriter<span style='color:#808030; '>.</span>WriteStartElement<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>ArrayOfEasyAENotificationEventArgs</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
 +
            Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>Logging for 30 seconds...</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
            <span style='color:#800000; font-weight:bold; '>int</span> handle <span style='color:#808030; '>=</span> EasyAEClient<span style='color:#808030; '>.</span>SharedInstance<span style='color:#808030; '>.</span>SubscribeEvents<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#800000; '>"</span><span style='color:#808030; '>,</span> <span style='color:#800000; '>"</span><span style='color:#0000e6; '>OPCLabs.KitEventServer.2</span><span style='color:#800000; '>"</span><span style='color:#808030; '>,</span> <span style='color:#008c00; '>100</span><span style='color:#808030; '>,</span>
 +
              <span style='color:#808030; '>(</span>_<span style='color:#808030; '>,</span> eventArgs<span style='color:#808030; '>)</span> <span style='color:#808030; '>=</span><span style='color:#808030; '>></span>
 +
                  <span style='color:#800080; '>{</span>
 +
                      Debug<span style='color:#808030; '>.</span>Assert<span style='color:#808030; '>(</span>eventArgs <span style='color:#808030; '>!</span><span style='color:#808030; '>=</span> <span style='color:#800000; font-weight:bold; '>null</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
                      xmlSerializer<span style='color:#808030; '>.</span>Serialize<span style='color:#808030; '>(</span>xmlWriter<span style='color:#808030; '>,</span> eventArgs<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
                  <span style='color:#800080; '>}</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
            System<span style='color:#808030; '>.</span>Threading<span style='color:#808030; '>.</span>Thread<span style='color:#808030; '>.</span>Sleep<span style='color:#808030; '>(</span><span style='color:#008c00; '>30</span> <span style='color:#808030; '>*</span> <span style='color:#008c00; '>1000</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
 +
            Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>Shutting down...</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
            EasyAEClient<span style='color:#808030; '>.</span>SharedInstance<span style='color:#808030; '>.</span>UnsubscribeEvents<span style='color:#808030; '>(</span>handle<span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
            xmlWriter<span style='color:#808030; '>.</span>WriteEndElement<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>    <span style='color:#696969; '>// not really necessary - XmlWriter would write the end tag for us anyway</span>
 +
            xmlWriter<span style='color:#808030; '>.</span>Close<span style='color:#808030; '>(</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
 +
            Console<span style='color:#808030; '>.</span>WriteLine<span style='color:#808030; '>(</span><span style='color:#800000; '>"</span><span style='color:#0000e6; '>Finished.</span><span style='color:#800000; '>"</span><span style='color:#808030; '>)</span><span style='color:#800080; '>;</span>
 +
        <span style='color:#800080; '>}</span>
  
 
The output file generated by the logger (OpcEvents.xml) is listed at the bottom.
 
The output file generated by the logger (OpcEvents.xml) is listed at the bottom.

Revision as of 14:26, 31 July 2016

The example below subscribes to all notifications from an OPC A&E Server, and logs the event notifications to an XML file.

There are three factors that make the code very short:

  • You can use anonymous methods (or lambdas) to specify the handler (callback) for event notifications.
  • The event arguments that are passed to the event handler or callback are directly serializable to XML (same as with most QuickOPC objects).
  • There is no need for reconnection logic (more about this further down in this post).
       static void Main()
       {
           Console.WriteLine("Starting up...");
           var xmlSerializer = new XmlSerializer(typeof(EasyAENotificationEventArgs));
           var xmlWriter = XmlWriter.Create("OpcEvents.xml", new XmlWriterSettings
           {
               Indent = true,
               CloseOutput = true
           });
           // The root element can have any name you need, but the name below also allows reading the log back as .NET array
           xmlWriter.WriteStartElement("ArrayOfEasyAENotificationEventArgs");

           Console.WriteLine("Logging for 30 seconds...");
           int handle = EasyAEClient.SharedInstance.SubscribeEvents("", "OPCLabs.KitEventServer.2", 100,
              (_, eventArgs) =>
                  {
                      Debug.Assert(eventArgs != null);
                      xmlSerializer.Serialize(xmlWriter, eventArgs);
                  });
           System.Threading.Thread.Sleep(30 * 1000);

           Console.WriteLine("Shutting down...");
           EasyAEClient.SharedInstance.UnsubscribeEvents(handle);
           xmlWriter.WriteEndElement();    // not really necessary - XmlWriter would write the end tag for us anyway
           xmlWriter.Close();

           Console.WriteLine("Finished.");
       }

The output file generated by the logger (OpcEvents.xml) is listed at the bottom.

What makes this example quite nice is the fact it is is fairly complete - it is fully resistant against network problems, OPC server crashes etc. You do not need to write any additional code for that! To prove it, increase the logging time in the code to e.g. 10 minutes, start the logger, and then find and select the OPC Simulation Server process (opcrtkit.exe) in the Task Manager, and "kill it" by pressing the "End process" button. The logger will log an en exception record into the output XML. If you, however, wait for some minutes, you will see that the server process restarts itself (this is caused by the reconnection facility in the QuickOPC component), and events from the OPC server will be outputted to the XML file again. The reconnection delays can be influenced by setting various properties on EasyAEClient object. This example project is included with the product. Please use the example from the product itself for the most up-to-date code of the example. There is also an example that shows logging of OPC Data Access Item changes into XML – in a separate application note.

OpcEvents.xml: