/* * Control.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 IEC61850.Common; namespace IEC61850 { /// /// IEC 61850 common API parts (used by client and server API) /// namespace Common { /// /// Control model /// public enum ControlModel { /** status only */ STATUS_ONLY = 0, /** direct with normal security */ DIRECT_NORMAL= 1, /** select before operate (SBO) with normal security */ SBO_NORMAL = 2, /** direct with enhanced security */ DIRECT_ENHANCED = 3, /** select before operate (SBO) with enhanced security */ SBO_ENHANCED = 4 } /// /// Originator category /// public enum OrCat { /** Not supported - should not be used */ NOT_SUPPORTED = 0, /** Control operation issued from an operator using a client located at bay level */ BAY_CONTROL = 1, /** Control operation issued from an operator using a client located at station level */ STATION_CONTROL = 2, /** Control operation from a remote operator outside the substation (for example network control center) */ REMOTE_CONTROL = 3, /** Control operation issued from an automatic function at bay level */ AUTOMATIC_BAY = 4, /** Control operation issued from an automatic function at station level */ AUTOMATIC_STATION = 5, /** Control operation issued from a automatic function outside of the substation */ AUTOMATIC_REMOTE = 6, /** Control operation issued from a maintenance/service tool */ MAINTENANCE = 7, /** Status change occurred without control action (for example external trip of a circuit breaker or failure inside the breaker) */ PROCESS = 8 } } namespace Client { [StructLayout(LayoutKind.Sequential)] internal struct LastApplErrorInternal { public int ctlNum; public int error; public int addCause; } public class LastApplError { public int ctlNum; public int error; public ControlAddCause addCause; internal LastApplError (LastApplErrorInternal lastApplError) { this.addCause = (ControlAddCause) lastApplError.addCause; this.error = lastApplError.error; this.ctlNum = lastApplError.ctlNum; } } /// /// Control object. /// public class ControlObject : IDisposable { [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern LastApplErrorInternal ControlObjectClient_getLastApplError(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern IntPtr ControlObjectClient_create(string objectReference, IntPtr connection); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern void ControlObjectClient_destroy(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern int ControlObjectClient_getControlModel(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] private static extern bool ControlObjectClient_operate(IntPtr self, IntPtr ctlVal, UInt64 operTime); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] private static extern bool ControlObjectClient_select(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] private static extern bool ControlObjectClient_selectWithValue(IntPtr self, IntPtr ctlVal); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] [return: MarshalAs(UnmanagedType.I1)] private static extern bool ControlObjectClient_cancel(IntPtr self); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern void ControlObjectClient_setOrigin(IntPtr self, string orIdent, int orCat); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern void ControlObjectClient_setInterlockCheck(IntPtr self, bool value); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern void ControlObjectClient_setSynchroCheck(IntPtr self, bool value); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern void ControlObjectClient_setTestMode(IntPtr self, bool value); [UnmanagedFunctionPointer(CallingConvention.Cdecl)] private delegate void InternalCommandTerminationHandler(IntPtr parameter,IntPtr controlClient); [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] private static extern void ControlObjectClient_setCommandTerminationHandler(IntPtr self, InternalCommandTerminationHandler handler, IntPtr handlerParameter); public delegate void CommandTerminationHandler (Object parameter, ControlObject controlObject); private IedConnection iedConnection; private IntPtr controlObject; private CommandTerminationHandler commandTerminationHandler = null; private Object commandTerminationHandlerParameter = null; private void MyCommandTerminationHandler (IntPtr paramter, IntPtr controlClient) { if (commandTerminationHandler != null) commandTerminationHandler(commandTerminationHandlerParameter, this); } private InternalCommandTerminationHandler intCommandTerminationHandler; internal ControlObject (string objectReference, IntPtr connection, IedConnection iedConnection) { this.iedConnection = iedConnection; this.controlObject = ControlObjectClient_create(objectReference, connection); if (this.controlObject == System.IntPtr.Zero) throw new IedConnectionException("Control object not found", 0); intCommandTerminationHandler = new InternalCommandTerminationHandler (MyCommandTerminationHandler); ControlObjectClient_setCommandTerminationHandler(controlObject, intCommandTerminationHandler, controlObject); } /// /// Gets the control model. /// /// /// The control model. /// public ControlModel GetControlModel () { ControlModel controlModel = (ControlModel) ControlObjectClient_getControlModel(controlObject); return controlModel; } /// /// Sets the origin parameter used by control commands. /// /// /// Originator. An arbitrary string identifying the controlling client. /// /// /// Originator category. /// public void SetOrigin (string originator, OrCat originatorCategory) { ControlObjectClient_setOrigin(controlObject, originator, (int) originatorCategory); } /// /// Operate the control with the specified control value. /// /// the new value of the control /// true when the operation has been successful, false otherwise public bool Operate (bool ctlVal) { return Operate (ctlVal, 0); } /// /// Operate the control with the specified control value (time activated control). /// /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise public bool Operate (bool ctlVal, UInt64 operTime) { MmsValue value = new MmsValue(ctlVal); return Operate (value, operTime); } /// /// Operate the control with the specified control value. /// /// the new value of the control /// true when the operation has been successful, false otherwise public bool Operate (float ctlVal) { return Operate (ctlVal, 0); } /// /// Operate the control with the specified control value (time activated control). /// /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise public bool Operate (float ctlVal, UInt64 operTime) { MmsValue value = new MmsValue(ctlVal); return Operate (value, operTime); } /// /// Operate the control with the specified control value. /// /// the new value of the control /// true when the operation has been successful, false otherwise public bool Operate (int ctlVal) { return Operate (ctlVal, 0); } /// /// Operate the control with the specified control value (time activated control). /// /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise public bool Operate (int ctlVal, UInt64 operTime) { MmsValue value = new MmsValue(ctlVal); return Operate (value, operTime); } /// /// Operate the control with the specified control value. /// /// the new value of the control /// true when the operation has been successful, false otherwise public bool Operate (MmsValue ctlVal) { return Operate (ctlVal, 0); } /// /// Operate the control with the specified control value (time activated control). /// /// the new value of the control /// the time when the operation will be executed /// true when the operation has been successful, false otherwise public bool Operate (MmsValue ctlVal, UInt64 operTime) { return ControlObjectClient_operate(controlObject, ctlVal.valueReference, operTime); } /// /// Select the control object. /// /// true when the selection has been successful, false otherwise public bool Select () { return ControlObjectClient_select(controlObject); } /// /// Send a select with value command for generic MmsValue instances /// /// /// the value to be checked. /// /// true when the selection has been successful, false otherwise public bool SelectWithValue (MmsValue ctlVal) { return ControlObjectClient_selectWithValue(controlObject, ctlVal.valueReference); } /// /// Send a select with value command for boolean controls /// /// /// the value to be checked. /// /// true when the selection has been successful, false otherwise public bool SelectWithValue (bool ctlVal) { return SelectWithValue(new MmsValue(ctlVal)); } /// /// Send a select with value command for integer controls /// /// /// the value to be checked. /// /// true when the selection has been successful, false otherwise public bool SelectWithValue (int ctlVal) { return SelectWithValue(new MmsValue(ctlVal)); } /// /// Send a select with value command for float controls /// /// /// the value to be checked. /// /// true when the selection has been successful, false otherwise public bool SelectWithValue (float ctlVal) { return SelectWithValue(new MmsValue(ctlVal)); } /// /// Cancel a selection or time activated operation /// /// true when the cancelation has been successful, false otherwise public bool Cancel () { return ControlObjectClient_cancel(controlObject); } /// /// Enables the synchro check for operate commands /// [Obsolete("use SetSynchroCheck instead")] public void EnableSynchroCheck () { ControlObjectClient_setSynchroCheck (controlObject, true); } /// /// Enables the interlock check for operate and select commands /// [Obsolete("use SetInterlockCheck instead")] public void EnableInterlockCheck () { ControlObjectClient_setInterlockCheck (controlObject, true); } /// /// Sets the value of the interlock check flag for operate and select commands /// public void SetInterlockCheck (bool value) { ControlObjectClient_setInterlockCheck (controlObject, value); } /// /// Sets the value of the synchro check flag for operate command /// public void SetSynchroCheck (bool value) { ControlObjectClient_setSynchroCheck (controlObject, value); } /// /// Sets the value of the test flag for the operate command /// public void SetTestMode (bool value) { ControlObjectClient_setTestMode (controlObject, value); } /// /// Gets the last received LastApplError (Additional Cause Diagnostics) value. /// /// /// The last appl error. /// public LastApplError GetLastApplError () { LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(controlObject); return new LastApplError(lastApplError); } /// /// Sets the command termination handler. /// /// /// the handler (delegate) that is invoked when a CommandTerminationMessage is received. /// /// /// Parameter. /// public void SetCommandTerminationHandler (CommandTerminationHandler handler, Object parameter) { this.commandTerminationHandler = handler; this.commandTerminationHandlerParameter = parameter; } protected virtual void Dispose(bool disposing) { if (this.controlObject != System.IntPtr.Zero) { ControlObjectClient_destroy (controlObject); this.controlObject = System.IntPtr.Zero; } } public void Dispose() { Dispose (true); } } } }