/* * ReportControlBlock.cs * * Copyright 2014 Michael Zillgith * * This file is part of libIEC61850. * * libIEC61850 is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * libIEC61850 is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with libIEC61850. If not, see . * * See COPYING file for the complete license text. */ using System; using System.Runtime.InteropServices; using System.Diagnostics; using IEC61850.Common; namespace IEC61850 { namespace Client { /// /// Report handler. /// public delegate void ReportHandler (Report report, object parameter); /// /// Report control block (RCB) representation. /// /// /// This class is used as a client side representation (copy) of a report control block (RCB). /// Values from the server will only be read when the GetRCBValues method is called. /// Values at the server are only affected when the SetRCBValues method is called. /// public class ReportControlBlock { [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientReportControlBlock_create (string dataAttributeReference); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr IedConnection_getRCBValues (IntPtr connection, out int error, string rcbReference, IntPtr updateRcb); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedConnection_setRCBValues (IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, bool singleRequest); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] static extern bool ClientReportControlBlock_isBuffered (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientReportControlBlock_getRptId (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setRptId (IntPtr self, string rptId); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] static extern bool ClientReportControlBlock_getRptEna (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setRptEna(IntPtr self, bool rptEna); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] static extern bool ClientReportControlBlock_getResv (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setResv (IntPtr self, bool resv); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientReportControlBlock_getDataSetReference (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setDataSetReference (IntPtr self, string dataSetReference); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 ClientReportControlBlock_getConfRev (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern int ClientReportControlBlock_getOptFlds (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setOptFlds (IntPtr self, int optFlds); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 ClientReportControlBlock_getBufTm (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setBufTm (IntPtr self, UInt32 bufTm); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt16 ClientReportControlBlock_getSqNum (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern int ClientReportControlBlock_getTrgOps (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setTrgOps (IntPtr self, int trgOps); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt32 ClientReportControlBlock_getIntgPd (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setIntgPd (IntPtr self, UInt32 intgPd); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] static extern bool ClientReportControlBlock_getGI (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setGI (IntPtr self, bool gi); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] static extern bool ClientReportControlBlock_getPurgeBuf (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setPurgeBuf (IntPtr self, bool purgeBuf); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern Int32 ClientReportControlBlock_getResvTms (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setResvTms (IntPtr self, Int16 resvTms); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientReportControlBlock_getEntryId (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void ClientReportControlBlock_setEntryId (IntPtr self, IntPtr entryId); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern UInt64 ClientReportControlBlock_getEntryTime (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr ClientReportControlBlock_getOwner (IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedConnection_installReportHandler (IntPtr connection, string rcbReference, string rptId, InternalReportHandler handler, IntPtr handlerParameter); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern void IedConnection_uninstallReportHandler(IntPtr connection, string rcbReference); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void InternalReportHandler (IntPtr parameter, IntPtr report); private IntPtr self; private IntPtr connection; private IedConnection iedConnection = null; private string objectReference; private bool flagRptId = false; private bool flagRptEna = false; private bool flagResv = false; private bool flagDataSetReference = false; private bool flagConfRev = false; private bool flagOptFlds = false; private bool flagBufTm = false; private bool flagSqNum = false; private bool flagTrgOps = false; private bool flagIntgPd = false; private bool flagGI = false; private bool flagPurgeBuf = false; private bool flagResvTms = false; private bool flagEntryId = false; private event ReportHandler reportHandler = null; private object reportHandlerParameter; private bool reportHandlerInstalled = false; private event InternalReportHandler internalHandler = null; private void resetSendFlags () { flagRptId = false; flagRptEna = false; flagResv = false; flagDataSetReference = false; flagConfRev = false; flagOptFlds = false; flagBufTm = false; flagSqNum = false; flagTrgOps = false; flagIntgPd = false; flagGI = false; flagPurgeBuf = false; flagResvTms = false; flagEntryId = false; } private Report report = null; private void internalReportHandler (IntPtr parameter, IntPtr report) { try { if (this.report == null) this.report = new Report (report); if (reportHandler != null) reportHandler(this.report, reportHandlerParameter); } catch (Exception e) { // older versions of mono 2.10 (for linux?) cause this exception Console.WriteLine(e.Message); } } internal ReportControlBlock (string objectReference, IedConnection iedConnection, IntPtr connection) { self = ClientReportControlBlock_create (objectReference); this.iedConnection = iedConnection; this.connection = connection; this.objectReference = objectReference; } internal void DisposeInternal() { IedConnection_uninstallReportHandler(connection, objectReference); } /// /// Releases all resource used by the object. /// /// Call when you are finished using the . The /// method leaves the in an unusable state. /// After calling , you must release all references to the /// so the garbage collector can reclaim the memory that the /// was occupying. public void Dispose() { DisposeInternal (); iedConnection.RemoveRCB (this); } public string GetObjectReference () { return this.objectReference; } /// /// Installs the report handler. /// /// /// This will install a callback handler (delegate) that is invoked whenever a report /// related to this RCB is received. Any call of this method will replace an previously registered /// handler! /// /// /// report handler /// /// /// parameter is passed to the handler when the handler is invoked. /// public void InstallReportHandler (ReportHandler reportHandler, object parameter) { this.reportHandler = new ReportHandler(reportHandler); this.reportHandlerParameter = parameter; if (reportHandlerInstalled == false) { string reportId = this.GetRptId (); if (internalHandler == null) { internalHandler = new InternalReportHandler(internalReportHandler); } IedConnection_installReportHandler(this.connection, objectReference, reportId, internalHandler, IntPtr.Zero); reportHandlerInstalled = true; } } /// /// Read all RCB values from the server /// /// This exception is thrown if there is a connection or service error public void GetRCBValues () { int error; IedConnection_getRCBValues (connection, out error, objectReference, self); if (error != 0) throw new IedConnectionException ("getRCBValues service failed", error); } /// /// Write changed RCB values to the server. /// /// /// This function will only write the RCB values that were set by one of the setter methods. /// The RCB values are sent by a single MMS write request. /// /// This exception is thrown if there is a connection or service error public void SetRCBValues () { SetRCBValues (true); } /// /// Write changed RCB values to the server. /// /// /// This function will only write the RCB values that were set by one of the setter methods. /// /// This exception is thrown if there is a connection or service error /// /// If true the values are sent by single MMS write request. Otherwise the values are all sent by their own MMS write requests. /// public void SetRCBValues (bool singleRequest) { UInt32 parametersMask = 0; if (flagRptId) parametersMask += 1; if (flagRptEna) parametersMask += 2; if (flagResv) parametersMask += 4; if (flagDataSetReference) parametersMask += 8; if (flagConfRev) parametersMask += 16; if (flagOptFlds) parametersMask += 32; if (flagBufTm) parametersMask += 64; if (flagSqNum) parametersMask += 128; if (flagTrgOps) parametersMask += 256; if (flagIntgPd) parametersMask += 512; if (flagGI) parametersMask += 1024; if (flagPurgeBuf) parametersMask += 2048; if (flagEntryId) parametersMask += 4096; if (flagResvTms) parametersMask += 16384; int error; IedConnection_setRCBValues (connection, out error, self, parametersMask, singleRequest); resetSendFlags(); if (error != 0) throw new IedConnectionException ("setRCBValues service failed", error); if (flagRptId) { if (reportHandlerInstalled) { reportHandlerInstalled = false; InstallReportHandler(this.reportHandler, this.reportHandlerParameter); } } } /// /// Determines whether this instance is a buffered or unbuffered RCB. /// /// /// true if this instance is a buffered RCB; otherwise, false. /// public bool IsBuffered () { return ClientReportControlBlock_isBuffered (self); } /// /// Gets the entry time of the RCB as ms time /// /// /// The entry time is the timestamp of the last report sent. /// /// /// The entry time as ms timestamp /// public UInt64 GetEntryTime () { return ClientReportControlBlock_getEntryTime (self); } /// /// Gets the entry time of the RCB as DateTimeOffset /// /// /// The entry time is the timestamp of the last report sent. /// /// /// The entry time as DataTimeOffset /// public DateTimeOffset GetEntryTimeAsDateTimeOffset () { UInt64 entryTime = GetEntryTime (); DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero); return retVal.AddMilliseconds (entryTime); } /// /// Gets the entryID of RCB /// /// Returns the EntryID of the last received GetRCBValues service response. /// The EntryID is only present in buffered RCBs (BRCBs). /// /// The entry ID public byte[] GetEntryID() { IntPtr entryIdRef = ClientReportControlBlock_getEntryId (self); if (entryIdRef == IntPtr.Zero) return null; else { MmsValue entryId = new MmsValue (entryIdRef); return entryId.getOctetString (); } } public void SetEntryID(byte[] entryId) { flagEntryId = true; MmsValue entryID = MmsValue.NewOctetString (entryId.Length); entryID.setOctetString (entryId); ClientReportControlBlock_setEntryId (self, entryID.valueReference); } /// /// Gets the data set reference of the associated data set /// /// /// The data set reference. /// public string GetDataSetReference () { IntPtr dataSetRefPtr = ClientReportControlBlock_getDataSetReference (self); return Marshal.PtrToStringAnsi (dataSetRefPtr); } /// /// Sets the data set reference. Use this method to select the associated data set for the RCB /// /// /// The data set reference. /// public void SetDataSetReference (string dataSetReference) { ClientReportControlBlock_setDataSetReference (self, dataSetReference); flagDataSetReference = true; } /// /// Gets the report identifier. /// /// /// The report identifier. /// public string GetRptId () { IntPtr rptIdPtr = ClientReportControlBlock_getRptId (self); return Marshal.PtrToStringAnsi (rptIdPtr); } /// /// Sets the RptId (report ID) of the RCB /// /// /// The new RptId /// public void SetRptId (string rptId) { ClientReportControlBlock_setRptId(self, rptId); flagRptId = true; } /// /// Check if reporting is currently enabled /// /// /// true, if reporting is enabled, false otherwise /// public bool GetRptEna () { return ClientReportControlBlock_getRptEna (self); } /// /// Sets report enable flag. Use this to enable reporting /// /// /// true to enable reporting, false to disable /// public void SetRptEna (bool rptEna) { ClientReportControlBlock_setRptEna (self, rptEna); flagRptEna = true; } /// /// Get the purgeBuf flag of the report control block /// /// the prugeBuf value public bool GetPurgeBuf () { return ClientReportControlBlock_getPurgeBuf(self); } /// /// Set the purgeBuf flag of the report control block /// /// This is only for buffered RCBs. If set to true the report buffer of a buffered RCB will be cleaned. /// set to true to flush report buffer public void SetPurgeBuf (bool purgeBuf) { ClientReportControlBlock_setPurgeBuf(self, purgeBuf); flagPurgeBuf = true; } /// /// Gets the buffer time. /// /// /// The buffer time in ms. /// public UInt32 GetBufTm() { return ClientReportControlBlock_getBufTm (self); } /// /// Sets the buffer time. /// /// /// Buffer time is ms. /// public void SetBufTm (UInt32 bufTm) { ClientReportControlBlock_setBufTm (self, bufTm); flagBufTm = true; } /// /// Gets the GI flag /// /// /// true, if GI flag is set /// public bool GetGI () { return ClientReportControlBlock_getGI (self); } /// /// Sets the GI flag. Use this to trigger a GI (general interrogation) command. /// /// /// request general interrogation of true /// public void SetGI (bool GI) { ClientReportControlBlock_setGI (self, GI); flagGI = true; } /// /// Check if RCB is reserved by a client /// /// /// true, the RCB is reserver by a client /// public bool GetResv () { return ClientReportControlBlock_getResv (self); } /// /// Gets the configuration revision of the RCB /// /// /// The conf rev. /// public UInt32 GetConfRev () { return ClientReportControlBlock_getConfRev (self); } /// /// Sets RESV flag. Use this to reserve (allocate) this RCB. /// /// /// true: reserver this RCB for exclusive use /// public void SetResv (bool resv) { ClientReportControlBlock_setResv (self, resv); flagResv = true; } /// /// Gets the trigger options of the RCB /// /// /// trigger options /// public TriggerOptions GetTrgOps() { return (TriggerOptions) ClientReportControlBlock_getTrgOps (self); } /// /// Sets the trigger options of the RCB. /// /// /// trigger options /// public void SetTrgOps(TriggerOptions trgOps) { ClientReportControlBlock_setTrgOps (self, (int) trgOps); flagTrgOps = true; } /// /// Gets the integrity period /// /// /// integrity period in ms /// public UInt32 GetIntgPd () { return ClientReportControlBlock_getIntgPd (self); } /// /// Sets the integrity period /// /// /// integrity period in ms /// public void SetIntgPd (UInt32 intgPd) { ClientReportControlBlock_setIntgPd (self, intgPd); flagIntgPd = true; } /// /// Gets the option fields. /// /// /// The option fields /// public ReportOptions GetOptFlds() { return (ReportOptions) ClientReportControlBlock_getOptFlds (self); } /// /// Sets the option field. Used to enable or disable optional report elements /// /// /// Option field. /// public void SetOptFlds(ReportOptions optFlds) { ClientReportControlBlock_setOptFlds (self, (int)optFlds); flagOptFlds = true; } } } }