diff --git a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs index d1b7acc3..2cb4e574 100644 --- a/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs +++ b/dotnet/IEC61850forCSharp/IEC61850ServerAPI.cs @@ -23,11 +23,14 @@ using System; using System.Collections.Generic; using System.Data; +using System.Data.Common; using System.Diagnostics; using System.Runtime.InteropServices; using System.Xml.Linq; +using IEC61850.Client; using IEC61850.Common; using IEC61850.TLS; +using static System.Collections.Specialized.BitVector32; using static System.Net.Mime.MediaTypeNames; using static IEC61850.Client.IedConnection; @@ -315,6 +318,9 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] static extern IntPtr LogicalDevice_createEx(string name, IntPtr parent, string ldName); + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + static extern IntPtr LogicalDevice_getSettingGroupControlBlock(IntPtr self); + public IedModel IedModel { get; } public LogicalDevice (IntPtr self, IedModel iedModel) : base (self) @@ -346,6 +352,20 @@ namespace IEC61850 self = LogicalDevice_createEx(inst, parent.self, ldName); } + + /// + /// Get the setting group control block (SGCB) of the logical device + /// + /// the SGCB instance or NULL if no SGCB is available + public SettingGroupControlBlock GetSettingGroupControlBlock() + { + IntPtr sgcb = LogicalDevice_getSettingGroupControlBlock(this.self); + + if(sgcb == IntPtr.Zero) + return null; + + return new SettingGroupControlBlock(sgcb); + } } /// @@ -1689,6 +1709,11 @@ namespace IEC61850 { self = SettingGroupControlBlock_create(parent.self, (byte) actSG, (byte) numOfSGs); } + + public SettingGroupControlBlock(IntPtr self) + { + this.self = self ; + } } public class ClientConnection @@ -2400,6 +2425,55 @@ namespace IEC61850 [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] public static extern void IedServer_setDirectoryAccessHandler(IntPtr self, IedServer_DirectoryAccessHandler handler, IntPtr parameter); + /// + /// Set the callback handler for the SetActSG event + /// + /// the instance of IedServer to operate on + /// the handle of the setting group control block of the setting group + /// the user provided callback handler + /// a user provided parameter that is passed to the control handler + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + public static extern void IedServer_setActiveSettingGroupChangedHandler(IntPtr self, IntPtr sgcb, ActiveSettingGroupChangedHandler handler, IntPtr parameter); + + /// + /// Set the callback handler for the SetEditSG event + /// + /// the instance of IedServer to operate on + /// the handle of the setting group control block of the setting group + /// the user provided callback handler + /// a user provided parameter that is passed to the control handler + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + public static extern void IedServer_setEditSettingGroupChangedHandler(IntPtr self, IntPtr sgcb, EditSettingGroupChangedHandler handler, IntPtr parameter); + + /// + /// Set the callback handler for the COnfEditSG event + /// + /// the instance of IedServer to operate on + /// the handle of the setting group control block of the setting group + /// the user provided callback handler + /// a user provided parameter that is passed to the control handler + [DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + public static extern void IedServer_setEditSettingGroupConfirmationHandler(IntPtr self, IntPtr sgcb, EditSettingGroupConfirmationHandler handler, IntPtr parameter); + + ///// + ///// Set a handler for SVCB control block events (enable/disable) + ///// + ///// the instance of IedServer to operate on. + ///// the SVCB control block instance + ///// the event handler to be used + ///// user provided parameter that is passed to the handler + //[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)] + //public static extern void IedServer_setSVCBHandler(IntPtr self, IntPtr svcb, SVCBEventHandler handler, IntPtr parameter); + + ///// + ///// callback handler for SVCB events + ///// + ///// the related SVCB instance + ///// event type + ///// user defined parameter + //[UnmanagedFunctionPointer(CallingConvention.Cdecl)] + //public delegate void SVCBEventHandler(IntPtr svcb, int eventType, IntPtr parameter); + /// /// callback handler to control client read access to data attributes /// User provided callback function to control MMS client read access to IEC 61850 @@ -2416,6 +2490,41 @@ namespace IEC61850 [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate MmsDataAccessError ReadAccessHandler(IntPtr ld, IntPtr ln, IntPtr dataObject, int fc, IntPtr connection, IntPtr parameter); + /// + /// Callback handler that is invoked when the active setting group is about to be changed by an external client. + /// This function is called BEFORE the active setting group is changed. The user can reject to change the active setting group by returning false. + /// + /// user provided parameter + /// sgcb the setting group control block of the setting group that is about to be changed + /// newActSg the new active setting group + /// connection the client connection that requests the change + /// true if the change is accepted, false otherwise + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool ActiveSettingGroupChangedHandler(IntPtr parameter, IntPtr sgcb, uint newActSg, IntPtr connection); + + /// + /// Callback handler that is invoked when the edit setting group is about to be changed by an external client. + /// In this function the user should update all SE data attributes associated with the given SettingGroupControlBlock. + /// This function is called BEFORE the active setting group is changed.The user can reject to change the + /// edit setting group by returning false. This can be used to implement RBAC. + /// + /// user provided parameter + /// the setting group control block of the setting group that is about to be changed + /// the new edit setting group + /// the client connection that requests the change + /// true if the change is accepted, false otherwise + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate bool EditSettingGroupChangedHandler(IntPtr parameter, IntPtr sgcb, uint newEditSg, IntPtr connection); + + /// + /// Callback handler that is invoked when the edit setting group has been confirmed by an external client. + /// + /// user provided parameter + /// the setting group control block of the setting group that is about to be changed + /// the edit setting group that has been confirmed + [UnmanagedFunctionPointer(CallingConvention.Cdecl)] + public delegate void EditSettingGroupConfirmationHandler(IntPtr parameter, IntPtr sgcb, uint editSg); + /// /// Callback that is called when the client is calling a dataset operation (create, delete, read, write, list directory) /// his callback is called before the IedServer_RCBEventHandler and only in case of operations (RCB_EVENT_GET_PARAMETER, RCB_EVENT_SET_PARAMETER, RCB_EVENT_ENABLE @@ -2762,6 +2871,120 @@ namespace IEC61850 return false; } + //------------- Setting group + + public delegate bool InternalActiveSettingGroupChangedHandler(object parameter, SettingGroupControlBlock sgcb, uint newActSg, ClientConnection connection); + + private InternalActiveSettingGroupChangedHandler internalActiveSettingGroupChangedHandler = null; + + private object activeSettingGroupChangedHandlerParameter = null; + + private ActiveSettingGroupChangedHandler activeSettingGroupChangedHandler = null; + + + public void SetActiveSettingGroupChangedHandler(InternalActiveSettingGroupChangedHandler handler,SettingGroupControlBlock settingGroupControlBlock, object parameter) + { + internalActiveSettingGroupChangedHandler = handler; + activeSettingGroupChangedHandlerParameter = parameter; + + if (activeSettingGroupChangedHandler == null) + { + activeSettingGroupChangedHandler = new ActiveSettingGroupChangedHandler(InternalActiveSettingGroupChangedImplementation); + + IedServer_setActiveSettingGroupChangedHandler(self, settingGroupControlBlock.self, activeSettingGroupChangedHandler, IntPtr.Zero); + } + } + + private bool InternalActiveSettingGroupChangedImplementation(IntPtr parameter, IntPtr sgcb, uint newActSg, IntPtr connection) + { + if (sgcb != IntPtr.Zero && connection != IntPtr.Zero) + { + ClientConnection con = null; + + this.clientConnections.TryGetValue(connection, out con); + + return internalActiveSettingGroupChangedHandler(activeSettingGroupChangedHandlerParameter, new SettingGroupControlBlock(sgcb), newActSg, con); + } + + return false; + } + + //------------ + + //public delegate bool InternalSVCBEventHandler(SampledValuesControlBlock sampledValuesControlBlock, SMVEvent sMVEvent, object parameter); + + //private InternalSVCBEventHandler internalSVCBEventHandler = null; + + //private object sVCBEventHandlerParameter = null; + + //private SVCBEventHandler sVCBEventHandler = null; + + //internal class SVCHandlerInfo + //{ + // public SampledValuesControlBlock sampledValuesControlBlock = null; + // public GCHandle handle; + + // public InternalSVCBEventHandler internalSVCBEventHandler = null; + // public object svcHandlerParameter = null; + + // public SVCHandlerInfo(SampledValuesControlBlock sampledValuesControlBlock) + // { + // this.sampledValuesControlBlock = sampledValuesControlBlock; + // this.handle = GCHandle.Alloc(this); + // } + + // ~SVCHandlerInfo() + // { + // this.handle.Free(); + // } + //} + + //private Dictionary svcHandlers = new Dictionary(); + + //private SVCHandlerInfo GetSVCHandlerInfo(SampledValuesControlBlock sampledValuesControlBlock) + //{ + // SVCHandlerInfo info; + + // svcHandlers.TryGetValue(sampledValuesControlBlock, out info); + + // if (info == null) + // { + // info = new SVCHandlerInfo(sampledValuesControlBlock); + // svcHandlers.Add(sampledValuesControlBlock, info); + // } + + // return info; + //} + + //public void SetSVCBHandler(InternalSVCBEventHandler handler, SampledValuesControlBlock sampledValuesControlBlock, object parameter) + //{ + // SVCHandlerInfo info = GetSVCHandlerInfo(sampledValuesControlBlock); + + // info.internalSVCBEventHandler = handler; + // info.svcHandlerParameter = parameter; + + // if (sVCBEventHandler == null) + // sVCBEventHandler = new SVCBEventHandler(InternalSVCBEventHandlerImplementation); + + // IedServer_setSVCBHandler(self, sampledValuesControlBlock.Self, sVCBEventHandler, GCHandle.ToIntPtr(info.handle)); + //} + + //public enum SMVEvent + //{ + // IEC61850_SVCB_EVENT_ENABLE = 1, + // IEC61850_SVCB_EVENT_DISABLE = 0, + //} + + //private void InternalSVCBEventHandlerImplementation(IntPtr svcb, int eventType, IntPtr parameter) + //{ + // GCHandle handle = GCHandle.FromIntPtr(parameter); + + // SVCHandlerInfo info = (SVCHandlerInfo)handle.Target; + + // if (info != null && info.internalSVCBEventHandler != null) + // info.internalSVCBEventHandler(info.sampledValuesControlBlock,(SMVEvent)eventType, info.svcHandlerParameter); + //} + public delegate MmsDataAccessError InternalReadAccessHandler(LogicalDevice ld, LogicalNode ln, DataObject dataObject, FunctionalConstraint fc, ClientConnection connection, object parameter); private InternalReadAccessHandler internalReadAccessHandler = null; diff --git a/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs b/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs index dc481140..733c2fb1 100644 --- a/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs +++ b/dotnet/IEC61850forCSharp/SampledValuesControlBlock.cs @@ -96,8 +96,9 @@ namespace IEC61850 private bool isDisposed = false; + public IntPtr Self { get => self;} - internal SampledValuesControlBlock(IntPtr iedConnection, string objectReference) + internal SampledValuesControlBlock(IntPtr iedConnection, string objectReference) { self = ClientSVControlBlock_create (iedConnection, objectReference); this.objectReference = objectReference; diff --git a/dotnet/server_example_access_control/Program.cs b/dotnet/server_example_access_control/Program.cs index be4b400d..133714ea 100644 --- a/dotnet/server_example_access_control/Program.cs +++ b/dotnet/server_example_access_control/Program.cs @@ -13,6 +13,8 @@ using System.Net; using static IEC61850.Server.IedServer; using System.Collections.Generic; using System.Reflection.Metadata; +using IEC61850.Client; +using ReportControlBlock = IEC61850.Server.ReportControlBlock; namespace server_access_control { @@ -216,6 +218,34 @@ namespace server_access_control iedServer.SetDirectoryAccessHandler(directoryAccessHandler, null); + /* Handler for Sampled values control block + */ + + //void sVCBEventHandler(SampledValuesControlBlock svcb, SMVEvent smvEvent, object parameter) + //{ + // Console.WriteLine(svcb.GetNoASDU() + " event: "+ smvEvent.ToString() ); + //} + + //implement IedModel_getSVControlBlock && SVControlBlock + //SampledValuesControlBlock sampledValuesControlBlock = (SampledValuesControlBlock)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO1"); + + + //iedServer.SetSVCBHandler(sVCBEventHandler,) + + //SettingGroups + + LogicalDevice logicalDevice = (LogicalDevice)iedModel.GetModelNodeByShortObjectReference("GenericIO"); ; + SettingGroupControlBlock settingGroupControlBlock = logicalDevice.GetSettingGroupControlBlock(); + + bool activeSGChangedHandler(object parameter, SettingGroupControlBlock sgcb, uint newActSg, ClientConnection connection) + { + Console.WriteLine("Switch to setting group "+ newActSg +"\n"); + + return true; + } + + iedServer.SetActiveSettingGroupChangedHandler(activeSGChangedHandler, settingGroupControlBlock, null); + iedServer.Start(102); if (iedServer.IsRunning()) diff --git a/dotnet/server_example_access_control/model.cfg b/dotnet/server_example_access_control/model.cfg index 3c8b17ae..b3d21dc4 100644 --- a/dotnet/server_example_access_control/model.cfg +++ b/dotnet/server_example_access_control/model.cfg @@ -1,6 +1,7 @@ MODEL(simpleIO){ LD(GenericIO){ LN(LLN0){ +SG(1 5) DO(Mod 0){ DA(stVal 0 12 0 17 0)=1; DA(q 0 23 0 18 0); @@ -46,16 +47,34 @@ DE(GGIO1$MX$AnIn3$q); DE(GGIO1$MX$AnIn4$mag$f); DE(GGIO1$MX$AnIn4$q); } -RC(EventsRCB01 Events1 0 Events 1 24 175 50 1000); -RC(EventsRCBPreConf01 Events1 0 Events 1 24 175 50 1000); -RC(EventsBRCB01 Events2 1 Events 1 24 175 50 1000); -RC(EventsBRCBPreConf01 Events2 1 Events 1 24 175 50 1000); +DS(ServiceTracking){ +DE(LTRK1$SR$SpcTrk); +DE(LTRK1$SR$DpcTrk); +DE(LTRK1$SR$IncTrk); +DE(LTRK1$SR$BscTrk); +DE(LTRK1$SR$UrcbTrk); +DE(LTRK1$SR$BrcbTrk); +DE(LTRK1$SR$GocbTrk); +DE(LTRK1$SR$SgcbTrk); +DE(LTRK1$SR$LocbTrk); +} +RC(EventsRCB01 Events1 0 Events2 1 24 175 50 1000); RC(EventsIndexed01 Events2 0 Events 1 24 175 50 1000); RC(EventsIndexed02 Events2 0 Events 1 24 175 50 1000); RC(EventsIndexed03 Events2 0 Events 1 24 175 50 1000); RC(Measurements01 Measurements 1 Measurements 1 16 239 50 1000); RC(Measurements02 Measurements 1 Measurements 1 16 239 50 1000); RC(Measurements03 Measurements 1 Measurements 1 16 239 50 1000); +RC(brcbServiceTracking01 ServiceTracking 1 ServiceTracking 1 19 228 0 0); +RC(brcbServiceTracking02 ServiceTracking 1 ServiceTracking 1 19 228 0 0); +RC(brcbServiceTracking03 ServiceTracking 1 ServiceTracking 1 19 228 0 0); +LC(EventLog Events GenericIO/LLN0$EventLog 19 0 1 0); +LC(GeneralLog - - 19 0 0 0); +LOG(); +LOG(EventLog); +GC(gcbEvents events Events 3 0 1000 3000){ +PA(4 1 1000 010CCD010001); +} } LN(LPHD1){ DO(PhyNam 0){ @@ -216,5 +235,241 @@ DA(q 0 23 0 18 0); DA(t 0 22 0 16 0); } } +LN(PTOC1){ +DO(Mod 0){ +DA(stVal 0 12 0 17 0); +DA(q 0 23 0 18 0); +DA(t 0 22 0 16 0); +DA(ctlModel 0 12 4 16 0); +} +DO(Beh 0){ +DA(stVal 0 12 0 17 0); +DA(q 0 23 0 18 0); +DA(t 0 22 0 16 0); +} +DO(Str 0){ +DA(general 0 0 0 17 0); +DA(dirGeneral 0 12 0 17 0); +DA(q 0 23 0 18 0); +DA(t 0 22 0 16 0); +} +DO(Op 0){ +DA(general 0 0 0 17 0); +DA(q 0 23 0 18 0); +DA(t 0 22 0 16 0); +} +DO(StrVal 0){ +DA(setMag 0 27 7 16 0){ +DA(f 0 10 7 16 0); +} +} +DO(OpDlTmms 0){ +DA(setVal 0 3 7 17 0); +} +DO(RsDlTmms 0){ +DA(setVal 0 3 7 17 0); +} +DO(RstTms 0){ +DA(setVal 0 3 7 17 0); +} +} +LN(LTRK1){ +DO(Beh 0){ +DA(stVal 0 12 0 17 0); +DA(q 0 23 0 18 0); +DA(t 0 22 0 16 0); +} +DO(SpcTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(ctlVal 0 0 8 16 0); +DA(origin 0 27 8 16 0){ +DA(orCat 0 12 8 16 0); +DA(orIdent 0 13 8 16 0); +} +DA(ctlNum 0 6 8 16 0); +DA(T 0 22 8 16 0); +DA(Test 0 0 8 16 0); +DA(Check 0 24 8 16 0); +DA(respAddCause 0 12 8 16 0); +} +DO(DpcTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(ctlVal 0 0 8 16 0); +DA(origin 0 27 8 16 0){ +DA(orCat 0 12 8 16 0); +DA(orIdent 0 13 8 16 0); +} +DA(ctlNum 0 6 8 16 0); +DA(T 0 22 8 16 0); +DA(Test 0 0 8 16 0); +DA(Check 0 24 8 16 0); +DA(respAddCause 0 12 8 16 0); +} +DO(IncTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(ctlVal 0 3 8 16 0); +DA(origin 0 27 8 16 0){ +DA(orCat 0 12 8 16 0); +DA(orIdent 0 13 8 16 0); +} +DA(ctlNum 0 6 8 16 0); +DA(T 0 22 8 16 0); +DA(Test 0 0 8 16 0); +DA(Check 0 24 8 16 0); +DA(respAddCause 0 12 8 16 0); +} +DO(BscTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(ctlVal 0 25 8 16 0); +DA(origin 0 27 8 16 0){ +DA(orCat 0 12 8 16 0); +DA(orIdent 0 13 8 16 0); +} +DA(ctlNum 0 6 8 16 0); +DA(T 0 22 8 16 0); +DA(Test 0 0 8 16 0); +DA(Check 0 24 8 16 0); +DA(respAddCause 0 12 8 16 0); +} +DO(UrcbTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(rptID 0 19 8 16 0); +DA(rptEna 0 0 8 16 0); +DA(resv 0 0 8 16 0); +DA(datSet 0 31 8 16 0); +DA(confRev 0 9 8 16 0); +DA(optFlds 0 26 8 16 0); +DA(bufTm 0 9 8 16 0); +DA(sqNum 0 6 8 16 0); +DA(trgOps 0 26 8 16 0); +DA(intgPd 0 9 8 16 0); +DA(gi 0 0 8 16 0); +} +DO(BrcbTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(rptID 0 19 8 16 0); +DA(rptEna 0 0 8 16 0); +DA(datSet 0 31 8 16 0); +DA(confRev 0 9 8 16 0); +DA(optFlds 0 26 8 16 0); +DA(bufTm 0 9 8 16 0); +DA(sqNum 0 7 8 16 0); +DA(trgOps 0 26 8 16 0); +DA(intgPd 0 9 8 16 0); +DA(gi 0 0 8 16 0); +DA(purgeBuf 0 0 8 16 0); +DA(entryID 0 15 8 16 0); +DA(timeOfEntry 0 28 8 16 0); +DA(resvTms 0 2 8 16 0); +} +DO(GocbTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(goEna 0 0 8 16 0); +DA(goID 0 19 8 16 0); +DA(datSet 0 31 8 16 0); +DA(confRev 0 9 8 16 0); +DA(ndsCom 0 0 8 16 0); +DA(dstAddress 0 29 8 16 0); +} +DO(SgcbTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(numOfSG 0 6 8 16 0); +DA(actSG 0 6 8 16 0); +DA(editSG 0 6 8 16 0); +DA(cnfEdit 0 0 8 16 0); +DA(lActTm 0 22 8 16 0); +DA(resvTms 0 7 8 16 0); +} +DO(LocbTrk 0){ +DA(objRef 0 31 8 20 0); +DA(serviceType 0 12 8 16 0); +DA(errorCode 0 12 8 16 0); +DA(originatorID 0 13 8 16 0); +DA(t 0 22 8 16 0); +DA(d 0 20 5 16 0); +DA(dU 0 21 5 16 0); +DA(cdcNs 0 20 11 16 0); +DA(cdcName 0 20 11 16 0); +DA(dataNs 0 20 11 16 0); +DA(logEna 0 0 8 16 0); +DA(datSet 0 31 8 16 0); +DA(bufTm 0 9 8 16 0); +DA(trgOps 0 26 8 16 0); +DA(intgPd 0 9 8 16 0); +DA(logRef 0 31 8 16 0); +} +} } }