Compare commits

..

150 Commits

Author SHA1 Message Date
Michael Zillgith a13961110b Merge branch 'v1.6' into v1.6_develop 4 weeks ago
Michael Zillgith bd150595b7 - fixed bug in Hal_getMonotonicTimeInMs
- declare GetTickCount64 for mingw
4 weeks ago
Michael Zillgith e17b280351 - updated CHANGELOG and version number to 1.6.1 4 weeks ago
Michael Zillgith 478f4e8b35 Merge branch 'v1.6_develop_517' into v1.6_develop 4 weeks ago
Michael Zillgith f9bee73c1e - fixed warning about wrong return tzpe of function ItuObjectIdentifier_getArcCount 4 weeks ago
Michael Zillgith 3da8aa5222 Merge branch 'v1.6_develop' of bitbucket.com:mz-automation/libiec61850 into v1.6_develop 4 weeks ago
Maxson Anjos 5fb73a00cc Merged in v1.6_develop_513 (pull request #7)
V1.6 develop 513

Approved-by: Michael Zillgith
4 weeks ago
Maxson Ramon dos Anjos Medeiros 749e603b94 (LIB61850-513)
->API AcseAuthenticationParameter GetPasswordString
4 weeks ago
Michael Zillgith 7d6b3cce69 - code format update 4 weeks ago
Michael Zillgith cb343b6de6 - fixed BER decoder infinite length handling to avoid inifite loop while decoding (LIB61850-516) 4 weeks ago
Michael Zillgith 813b62356e - code format updated
- changed return type of some internal functions from int to bool
4 weeks ago
Maxson Ramon dos Anjos Medeiros edbf23870a (LIB61850-513)
->API IsoApplicationReference_getAeQualifier, IsoApplicationReference_getApTitle, ItuObjectIdentifier_getArcCount, ItuObjectIdentifier_getArc added
4 weeks ago
Maxson Ramon dos Anjos Medeiros 779c038d5c (LIB61850-513)
->Extend AcseAuthenticationParameter to get password
4 weeks ago
Maxson Ramon dos Anjos Medeiros b2631f1b25 (LIB61850-513)
-> Add server clientAuthenticator handler;
->Add LIB61850_API AcseAuthenticationParameter_getAuthMechanism;
->iedServer.SetAuthenticator(clientAuthenticator, null) added to server_example_access_control;
4 weeks ago
Michael Zillgith b7e087bf1f - LinkedList: added NULL checks 4 weeks ago
Michael Zillgith 4481530afb - code format updates 4 weeks ago
Michael Zillgith a41d2dce37 - code format update
- fixed problem in handling of memory allocation error (#553)
4 weeks ago
Michael Zillgith f5fceab050 - fixed handling of invalid object references in IedConnection_setGoCBValuesAsync 4 weeks ago
Michael Zillgith 8a4b7bb616 - IedConnection: code format updates 4 weeks ago
Michael Zillgith 9b467fa60d - code format update and additional NULL pointer checks in ied_connection.c 4 weeks ago
Michael Zillgith 1ff6224d1e - code format update 4 weeks ago
Michael Zillgith 24f70ae220 - MmsServer: replaced strcat with StringUtils_appendString (LIB61850-518) 4 weeks ago
Michael Zillgith 3a9833bad1 - code format update in mms_server_common.c and additional NULL check after memory allocation 4 weeks ago
Michael Zillgith a4c750820b - small code improvements and warnings removed (LIB61850-517) 1 month ago
Michael Zillgith 4a37e625d7 - code format update (LIB61850-517) 1 month ago
Michael Zillgith 3b322de408 - code format updates and added more checks of return values of functions allocating memory (LIB61850-517) 1 month ago
Michael Zillgith db5c66cad6 - ClientConnection: fixed bug in ownerCountMutex creation (LIB61850-517) 1 month ago
Michael Zillgith db97106a8b - removed useless check in GooseReceiver (LIB61850-517) 1 month ago
Michael Zillgith 1fc842037c - memory allocation check in ByteBuffer_create and apply fomatter (LIB61850-517) 1 month ago
Michael Zillgith 81ba6534fd - declared multicastAddress parameter in Ethernet_addMulticastAddress const (LIB61850-517) 1 month ago
Michael Zillgith 6eefcd61df - updated bitbucket pipeline 1 month ago
Michael Zillgith bdc19e9032 - added bitbucket pipeline; cppcheck with XML output 1 month ago
Maxson Ramon dos Anjos Medeiros b22d8ff59f CHANGELOG update -> .NET API: Added ClientConnection.Abort method 1 month ago
Maxson Ramon dos Anjos Medeiros 47dab00371 Merge branch 'v1.6_develop' of bitbucket.org:mz-automation/libiec61850 into v1.6_develop 1 month ago
Maxson Ramon dos Anjos Medeiros 0579b1dcc6 Merge branch 'v1.6_develop_488' into v1.6_develop 1 month ago
Maxson Ramon dos Anjos Medeiros 435ad8d01a Update ConnectionCallBack from example serve1 with clientConnection.Abort() 1 month ago
Maxson Anjos 52047baab4 Merged in v1.6_develop-514 (pull request #5) 1 month ago
Maxson Ramon dos Anjos Medeiros e9bfc53698 rename c and c# handlers 1 month ago
Maxson Ramon dos Anjos Medeiros ee224b611c Change c handers to private 1 month ago
Michael Zillgith d1dd90ed83 - .NET API: Added ClientConnection.Abort method (LIB61850-488) 1 month ago
Michael Zillgith 96a7106a99 - invalidate ClientConnection instance when connection is closed by remote (LIB61850-488) 1 month ago
Michael Zillgith 6630256f63 - ClientConnection: lock access to internal connection handle (LIB61850-488) 1 month ago
Michael Zillgith bdc1556c93 - replaced IsoServer_closeConnection by IsoServer_closeConnectionIndication (LIB61850-488) 1 month ago
Michael Zillgith 9df35ce709 - IED server: added functions ClientConnection_claimOwnerShip and ClientConnection_release to use ClientConnection outside of callbacks (LIB61850-488) 1 month ago
Maxson Ramon dos Anjos Medeiros be9682bfcc Merge branch 'v1.6_develop_503' into v1.6_develop 1 month ago
Maxson Anjos aa9a8dc2de Merged in v1.6_develop_394 (pull request #4)
V1.6 develop 394

Approved-by: Michael Zillgith
1 month ago
Maxson Ramon dos Anjos Medeiros 29403f39f7 Copyright header added to SMVControlBlock file and CHANGELOG updated 1 month ago
Maxson Ramon dos Anjos Medeiros 37a857e128 C -> LIB61850_API SVControlBlock_getName added
.NET -> Wrapper for SVControl ge_name added, called inside of SMVHandler
1 month ago
Maxson Ramon dos Anjos Medeiros f2940775f6 Add SV control handler 1 month ago
Michael Zillgith cd10e14790 Merge branch 'v1.6_develop' into v1.6_develop_488 1 month ago
Michael Zillgith d574cac1f6 - added first version of ClientConnection_abort function (LIB61850-488) 1 month ago
Maxson Ramon dos Anjos Medeiros d7d9c26713 Fix icd file format on tools/ICD files example 1 month ago
Maxson Ramon dos Anjos Medeiros d765734a0a Merge branch V1.6_develop_505
->added some additional checks in IedServer_updateVisibleStringAttributeValue and similar values (LIB61850-504): added checks to avoid buffer underflow in IedServer_getFunctionalConstrainedData (LIB61850-505)
->removed empty line
->added length checks in object reference and component construction when installing the default values in the data model (LIB61850-505)
1 month ago
Maxson Ramon dos Anjos Medeiros 5c6ef51159 ->Add ICD test file example to .net Tools;
->Add IEC61850Model/SVControlBlock.cs;
->Add SVCBHandler to .net
1 month ago
Michael Zillgith 2212c42ac8 - added length checks in object reference and component construction when installing the default values in the data model (LIB61850-505) 1 month ago
Michael Zillgith ce5201382d - removed empty line 1 month ago
Michael Zillgith 8999afaa88 - added some additional checks in IedServer_updateVisibleStringAttributeValue and similar values (LIB61850-504)
- added checks to avoid buffer underflow in IedServer_getFunctionalConstrainedData (LIB61850-505)
1 month ago
Maxson Ramon dos Anjos Medeiros cc4f25d122 -> Add wrapper for GetActiveSettingGroupChangedHandler 1 month ago
Maxson Ramon dos Anjos Medeiros bfa4631eea ->Add –GetChildWithFc on DataObject model, so we can get the DA fc=SE for the SGCB handler 1 month ago
Maxson Ramon dos Anjos Medeiros db0f5b5c9b Add LoadActiveSgValues on control example 1 month ago
Michael Zillgith ddf9d889f9 - fixed double free in IedConnection_destroy when control object clients have not been deleted before (LIB61850-503) 1 month ago
Maxson Ramon dos Anjos Medeiros ba9c255aa0 ->SetEditSettingGroupConfirmationHandler 1 month ago
Maxson Ramon dos Anjos Medeiros f3f1ef5cc4 ->SetEditSettingGroupChangedHandler 1 month ago
Maxson Ramon dos Anjos Medeiros 81af5a159c ->SetActiveSettingGroupChangedHandler;
->Update model.cfg with settingGroup
1 month ago
Michael Zillgith 1f4bf9cdf8 - added function MmsError_toString (LIB61850-423) 2 months ago
Michael Zillgith 5edfd5932f - .NET API: added documentation related to LogStorage (LIB61850-461) 2 months ago
Michael Zillgith cbcee0a41e - removed unnecessary variable initialization 2 months ago
Michael Zillgith 1eb47e8437 - removed unused example from cmake and make files 2 months ago
Michael Zillgith 62b969937a - code format update 2 months ago
Michael Zillgith 7e342598c9 - removed CMV example 2 months ago
Maxson Ramon dos Anjos Medeiros c1a117f038 SetDirectoryAccessHandler added 2 months ago
Maxson Ramon dos Anjos Medeiros 9b90cb2192 SetReadAccessHandler added 2 months ago
Maxson Ramon dos Anjos Medeiros b81279e442 API DataSet access handler added 2 months ago
Maxson Ramon dos Anjos Medeiros 5276813de3 API ControlBlock access handler added 2 months ago
Maxson Ramon dos Anjos Medeiros e13f44b716 Merge remote-tracking branch 'origin/v1.6_develop_486' into v1.6_develop
Merge branch v1.6_develop_486 .NET API: TLS
2 months ago
Maxson Ramon dos Anjos Medeiros b1bcdad4da Upgrade all examples to .net8 2 months ago
Maxson Ramon dos Anjos Medeiros 4a8245caf3 LogServies API added 2 months ago
Michael Zillgith 98687a1ece - fixed format issue 2 months ago
Michael Zillgith 8ac478f629 - fixed typo in comment 2 months ago
Michael Zillgith 458d740c9a - .NET API: added missing TLS related functions (LIB61850-486) 2 months ago
Michael Zillgith c69b958134 - code format update 2 months ago
Michael Zillgith 0630c4fb79 - renamed example 2 months ago
unknown b23b555788 removed commented function 3 months ago
unknown 61b72bfa00 merge 3 months ago
unknown 94be484b6a Merge branch 'v1.6_develop_tools' into v1.6_develop 3 months ago
unknown c002f9e2ca removed comment 3 months ago
unknown 5dcf973a32 changed value from an empty string to null 3 months ago
unknown 0f3cf1a10e fixed issue in displaying nested DAI values 3 months ago
unknown 132264aead changed find DAI to a top down approach instead of bottom up 3 months ago
Maxson Ramon dos Anjos Medeiros 37318b21dd Merge branch 'v1.6_develop_tools' into v1.6_develop 3 months ago
Maxson Ramon dos Anjos Medeiros 7a0070ac6b Clean code 3 months ago
Maxson Ramon dos Anjos Medeiros 1cda600ea1 Clean sclLib code -> remove auto commented code 3 months ago
Maxson Ramon dos Anjos Medeiros 2a49a3af1b Merge branch 'v1.6_develop_tools' into v1.6_develop
Add .NET Model generator to version 1.6.1
3 months ago
Maxson Ramon dos Anjos Medeiros 8fed1f4420 Update tools README file 3 months ago
Maxson Ramon dos Anjos Medeiros 4011845372 Merge branch 'v1.6_develop_tools' into v1.6_d 3 months ago
unknown 18c3d1d28e added value retrieval for nested DOs and DAs 3 months ago
unknown 0214d86790 fixed issue in printing arrays in DAs 3 months ago
unknown 5dd6fbe8bd added array display in DOs 3 months ago
unknown 4c39d49e20 fixed bug in displaying lcb and DA 3 months ago
unknown a960fa442e fixed issue in displaying DA values and two digit representation in RC block 3 months ago
unknown de5f7356b3 fixed daName in ExportDataSet 3 months ago
Maxson Ramon dos Anjos Medeiros c505fcd31c Update CHANGELOG 3 months ago
Maxson Ramon dos Anjos Medeiros c39e7b0b2e Update CHANGELOG and README for the tools 3 months ago
Maxson Ramon dos Anjos Medeiros 27cd8db5fe Organize Tools folder and add the Dynamic Model Generator 3 months ago
unknown 7c74db0b34 added readme for model generatorExample 4 months ago
unknown f049fefbf9 added quotation to svID value since it char* 4 months ago
unknown c372f96f0a added smv example 4 months ago
unknown 763488c9bc fixed bug in loading arrays in DAs 4 months ago
unknown c52eff5231 fixed issue in addressing array elements in DOs 4 months ago
unknown 37b9d88c7e fixed bug when having multiple smvControls 4 months ago
unknown 6f73c1bfd8 fixed issue in reading maxTime in GSE 4 months ago
unknown 9469b7eb40 reordered the entries in SVcontrol block according to Java program 4 months ago
unknown 5a7e0ec0db Merge branch 'v1.6_develop_tools' of bitbucket.org:mz-automation/libiec61850 into v1.6_develop_tools 4 months ago
unknown 5eab3ae3c8 added smvControl to the model generator 4 months ago
Maxson Ramon dos Anjos Medeiros c0c69c7cdc update script 4 months ago
Maxson Ramon dos Anjos Medeiros 68ac65c555 release script 4 months ago
Michael Zillgith 95bcbf1210 - updated code format 4 months ago
Michael Zillgith a0ee6c816c - small code format updates 4 months ago
Maxson Ramon dos Anjos Medeiros 1e1e9045ba Add SCLParser light version and ModelGenerator in .net 4 months ago
Michael Zillgith 463b9fa0ae - disable asn1c code stack overflow check when ASAN enabled (#539) 6 months ago
Michael Zillgith 32768ed7ca - SV Publisher: added support for optional gmIdentity field 7 months ago
Michael Zillgith 899a2bbe2e - merged HAL code from lib60870 (release/2.3.3) 8 months ago
Michael Zillgith 221a1f8615 - fixed - GoCB client access - use after free (#537) 8 months ago
Michael Zillgith cb6af6fa84 Merge branch 'v1.6_develop' of bitbucket.com:mz-automation/libiec61850 into v1.6_develop 9 months ago
Michael Zillgith 6dbdb1636c - TLS: fixed - certificate not validated when allow only allowed certificate is selected and certificate is matching (LIB61850-473)
- TLS: Added option to ignore validity times in certificates and CRLs (LIB61850-474)
9 months ago
Michael Zillgith 0f627cc250 .NET API: Added missing parameter isDyn for function IedServerConfig.SetReportSetting 9 months ago
Michael Zillgith 0ecd50d848 - enabled L2 GOOSE/SMV by default in standard stack_config.h (used by make files) 9 months ago
Michael Zillgith 2b57314c79 - added missing folder include for r_session in make files 9 months ago
Michael Zillgith 4724658ade - code format updates 10 months ago
Michael Zillgith dc199b2d8a - code format updates
- IED_SERVER: added debug message when report data set entry does not exist
10 months ago
Michael Zillgith 1fd2ad9724 - fixed mingw compilation problem of file-tool 10 months ago
Michael Zillgith 500a108962 - code format update 10 months ago
Michael Zillgith 931fda5d32 - IED server: always send LastApplError in operate resp- independent of the control model (LIB61850-472) 10 months ago
Michael Zillgith e62e4e89a5 - code format updates 10 months ago
Michael Zillgith a133aa8d57 - added missing API header files to make and cmake files (#531) 10 months ago
Michael Zillgith 6f5280a73a - handle functional naming (ldName) correctly in data-entry references in reports (LIB61850-467) 10 months ago
Michael Zillgith c05c72f544 - some code format updates 10 months ago
Michael Zillgith b131193694 - some code format updates
- added clang-formatter configuration
10 months ago
Michael Zillgith 243c988526 - config file parser: handle case when there is no phyAddr for SVCB or GoCB (#518) 11 months ago
Michael Zillgith 59b0609a78 Merge branch 'v1.6_develop' of bitbucket.com:mz-automation/libiec61850 into v1.6_develop 11 months ago
Michael Zillgith 4913fd158d - .NET API: fixed from wrong function name SqliteLogStorage_createInstanceEx to SqliteLogStorage_createInstance 11 months ago
Michael Zillgith 9c1709c2bb - fixed missing include in beagle_client example 11 months ago
Michael Zillgith c0b0d10346 - fixed bug in Makefile 11 months ago
Michael Zillgith c058cd4aa9 - fixed bug in GOOSE receiver (unitialized structure field- fixed bug in GOOSE receiver (unitialized structure field) 11 months ago
Michael Zillgith f3231b38b6 - added documentation for function MmsVariableSpecification_getStructureElements 11 months ago
Michael Zillgith 4ab7bf556b - code format update 11 months ago
Michael Zillgith b86806ef13 - .NET API: added support for server side log service (LIB61850-461) 11 months ago
Michael Zillgith ae02944918 - .NET API: Added properties to MmsVariableSpecification class (LIB61850-460) 11 months ago
Michael Zillgith 830059fca2 - HAL (Linux): fixed problem with Hal_getTimeInNs on 32 bit systems 1 year ago
Kiddo 1b91b09802
v1.6_develop fuzz integration (#515)
* - FUZZ: add mms related fuzzers

* - FUZZ: add acse parse fuzzer

* - FUZZ: fix incorrect source code name
1 year ago

@ -0,0 +1,192 @@
---
Language: Cpp
# BasedOnStyle: Microsoft
AccessModifierOffset: -2
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveMacros: None
AlignConsecutiveAssignments: None
AlignConsecutiveBitFields: None
AlignConsecutiveDeclarations: None
AlignEscapedNewlines: Right
AlignOperands: Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: false
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: None
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: Never
AllowShortLoopsOnASingleLine: false
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: All
AlwaysBreakBeforeMultilineStrings: false
AlwaysBreakTemplateDeclarations: MultiLine
AttributeMacros:
- __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
AfterCaseLabel: false
AfterClass: true
AfterControlStatement: Always
AfterEnum: true
AfterFunction: true
AfterNamespace: true
AfterObjCDeclaration: true
AfterStruct: true
AfterUnion: false
AfterExternBlock: true
BeforeCatch: true
BeforeElse: true
BeforeLambdaBody: false
BeforeWhile: false
IndentBraces: false
SplitEmptyFunction: true
SplitEmptyRecord: true
SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: true
BreakBeforeBraces: Custom
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit: 120
CommentPragmas: '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: false
DisableFormat: false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: BinPack
BasedOnStyle: ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
- foreach
- Q_FOREACH
- BOOST_FOREACH
IfMacros:
- KJ_IF_MAYBE
IncludeBlocks: Preserve
IncludeCategories:
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
Priority: 2
SortPriority: 0
CaseSensitive: false
- Regex: '^(<|"(gtest|gmock|isl|json)/)'
Priority: 3
SortPriority: 0
CaseSensitive: false
- Regex: '.*'
Priority: 1
SortPriority: 0
CaseSensitive: false
IncludeIsMainRegex: '(Test)?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: false
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: NoIndent
IndentRequires: false
IndentWidth: 4
IndentWrappedFunctionNames: false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: true
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd: ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 19
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 1000
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
PPIndentWidth: -1
ReferenceAlignment: Pointer
ReflowComments: true
RemoveBracesLLVM: false
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes: CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
AfterControlStatements: true
AfterForeachMacros: true
AfterFunctionDefinitionName: false
AfterFunctionDeclarationName: false
AfterIfMacros: true
AfterOverloadedOperator: false
BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 1
SpacesInAngles: Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
Minimum: 1
Maximum: -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard: Latest
StatementAttributeLikeMacros:
- Q_EMIT
StatementMacros:
- Q_UNUSED
- QT_REQUIRE_VERSION
TabWidth: 4
UseCRLF: false
UseTab: Never
WhitespaceSensitiveMacros:
- STRINGIZE
- PP_STRINGIZE
- BOOST_PP_STRINGIZE
- NS_SWIFT_NAME
- CF_SWIFT_NAME
...

@ -1,3 +1,42 @@
Changes to version 1.6.1
------------------------
New features and improvements:
- Added new function ClientConnection_abort to close a client connection from the server application code
- Added new functions ClientConnection_claimOwnerShip and ClientConnection_release to use a ClientConnection outside of callbacks (LIB61850-488)
- .NET API: SVControlBlock added
- .NET API: Added additional callbacks to control external access to the data model (required to implement RBAC)
- .NET API: IEC61850ServerAPI -> LogStorage function wrapper added.
- .NET API: MmsValue -> MmsValue_encodeMmsData and MmsValue_decodeMmsData added.
- .NET API: Fixed issue of not printing log entries in log_client and log_server examples.
- .NET Tools: in the Tools folder you can find the .net project to generate Static and Dynamic Models
- .NET API: added missing TLS related functions (LIB61850-486)
- .NET API: added support for server side log service (LIB61850-461)
- .NET API: Added properties to MmsVariableSpecification class (LIB61850-460)
- Added .NET versions of tools to create the static server model and configuration files (to replace the Java versions that are still included)
- SCLParser: also available on tools, you can load your SCL model and use it with our library
- added function MmsError_toString (LIB61850-423)
- SV Publisher: added support for optional gmIdentity field
Bug and Vulnerability fixes:
- fixed BER decoder infinite length handling to avoid inifite loop while decoding (LIB61850-516)
- added some additional checks in IedServer_updateVisibleStringAttributeValue and similar functions (LIB61850-504)
- added checks to avoid buffer underflow in IedServer_getFunctionalConstrainedData (LIB61850-505)
- fixed double free in IedConnection_destroy when control object clients have not been deleted before (LIB61850-503)
- disable asn1c code stack overflow check when ASAN enabled (#539)
- fixed - GoCB client access - use after free (#537)
- TLS: fixed - certificate not validated when allow only allowed certificate is selected and certificate is matching (LIB61850-473)
- TLS: Added option to ignore validity times in certificates and CRLs (LIB61850-474)
- handle functional naming (ldName) correctly in data-entry references in reports (LIB61850-467)
- config file parser: handle case when there is no phyAddr for SVCB or GoCB (#518)
- .NET API: fixed wrong function name SqliteLogStorage_createInstanceEx to SqliteLogStorage_createInstance
- HAL (Linux): fixed problem with Hal_getTimeInNs on 32 bit systems
Changes to version 1.6.0
------------------------

@ -12,7 +12,7 @@ ENABLE_TESTING()
set(LIB_VERSION_MAJOR "1")
set(LIB_VERSION_MINOR "6")
set(LIB_VERSION_PATCH "0")
set(LIB_VERSION_PATCH "1")
set(LIB_VERSION "${LIB_VERSION_MAJOR}.${LIB_VERSION_MINOR}.${LIB_VERSION_PATCH}")
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/third_party/cmake/modules/")
@ -93,40 +93,6 @@ include_directories(
${CMAKE_CURRENT_LIST_DIR}/src/logging
)
set(API_HEADERS
hal/inc/hal_base.h
hal/inc/hal_time.h
hal/inc/hal_thread.h
hal/inc/hal_filesystem.h
hal/inc/hal_ethernet.h
hal/inc/hal_socket.h
hal/inc/tls_config.h
src/common/inc/libiec61850_common_api.h
src/common/inc/linked_list.h
src/common/inc/sntp_client.h
src/iec61850/inc/iec61850_client.h
src/iec61850/inc/iec61850_common.h
src/iec61850/inc/iec61850_server.h
src/iec61850/inc/iec61850_model.h
src/iec61850/inc/iec61850_cdc.h
src/iec61850/inc/iec61850_dynamic_model.h
src/iec61850/inc/iec61850_config_file_parser.h
src/mms/inc/mms_value.h
src/mms/inc/mms_common.h
src/mms/inc/mms_types.h
src/mms/inc/mms_type_spec.h
src/mms/inc/mms_client_connection.h
src/mms/inc/mms_server.h
src/mms/inc/iso_connection_parameters.h
src/goose/goose_subscriber.h
src/goose/goose_receiver.h
src/goose/goose_publisher.h
src/sampled_values/sv_subscriber.h
src/sampled_values/sv_publisher.h
src/r_session/r_session.h
src/logging/logging_api.h
)
if(MSVC AND MSVC_VERSION LESS 1800)
include_directories(
${CMAKE_CURRENT_LIST_DIR}/src/vs
@ -158,6 +124,7 @@ endif(CONFIG_USE_EXTERNAL_MBEDTLS_DYNLIB)
if(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/sqlite/sqlite3.h)
set(FOUND_SQLITE3_SOURCE 1)
set(SQLITE_INCLUDE_DIR"${CMAKE_CURRENT_LIST_DIR}/third_party/sqlite")
message("Found sqlite3 source in third_party folder -> can compile with log service support")
endif(EXISTS ${CMAKE_CURRENT_LIST_DIR}/third_party/sqlite/sqlite3.h)
@ -194,6 +161,41 @@ set(CONFIG_IEC61850_R_SMV 0)
endif(WITH_MBEDTLS OR WITH_MBEDTLS3)
set(API_HEADERS
hal/inc/hal_base.h
hal/inc/hal_time.h
hal/inc/hal_thread.h
hal/inc/hal_filesystem.h
hal/inc/hal_ethernet.h
hal/inc/hal_socket.h
hal/inc/tls_config.h
hal/inc/tls_ciphers.h
src/common/inc/libiec61850_common_api.h
src/common/inc/linked_list.h
src/common/inc/sntp_client.h
src/iec61850/inc/iec61850_client.h
src/iec61850/inc/iec61850_common.h
src/iec61850/inc/iec61850_server.h
src/iec61850/inc/iec61850_model.h
src/iec61850/inc/iec61850_cdc.h
src/iec61850/inc/iec61850_dynamic_model.h
src/iec61850/inc/iec61850_config_file_parser.h
src/mms/inc/mms_value.h
src/mms/inc/mms_common.h
src/mms/inc/mms_types.h
src/mms/inc/mms_type_spec.h
src/mms/inc/mms_client_connection.h
src/mms/inc/mms_server.h
src/mms/inc/iso_connection_parameters.h
src/goose/goose_subscriber.h
src/goose/goose_receiver.h
src/goose/goose_publisher.h
src/sampled_values/sv_subscriber.h
src/sampled_values/sv_publisher.h
src/r_session/r_session.h
src/logging/logging_api.h
)
include(CheckCCompilerFlag)
check_c_compiler_flag("-Wredundant-decls" SUPPORT_REDUNDANT_DECLS)

@ -95,14 +95,17 @@ ifndef INSTALL_PREFIX
INSTALL_PREFIX = ./.install
endif
LIB_API_HEADER_FILES = hal/inc/hal_time.h
LIB_API_HEADER_FILES += hal/inc/hal_base.h
LIB_API_HEADER_FILES += hal/inc/hal_time.h
LIB_API_HEADER_FILES += hal/inc/hal_thread.h
LIB_API_HEADER_FILES += hal/inc/hal_filesystem.h
LIB_API_HEADER_FILES += hal/inc/hal_ethernet.h
LIB_API_HEADER_FILES += hal/inc/hal_socket.h
LIB_API_HEADER_FILES += hal/inc/tls_config.h
LIB_API_HEADER_FILES += hal/inc/lib_memory.h
LIB_API_HEADER_FILES += hal/inc/hal_base.h
LIB_API_HEADER_FILES += hal/inc/tls_ciphers.h
LIB_API_HEADER_FILES += src/common/inc/libiec61850_common_api.h
LIB_API_HEADER_FILES += src/common/inc/linked_list.h
LIB_API_HEADER_FILES += src/common/inc/sntp_client.h
LIB_API_HEADER_FILES += src/iec61850/inc/iec61850_client.h
LIB_API_HEADER_FILES += src/iec61850/inc/iec61850_common.h
LIB_API_HEADER_FILES += src/iec61850/inc/iec61850_server.h
@ -122,8 +125,8 @@ LIB_API_HEADER_FILES += src/goose/goose_receiver.h
LIB_API_HEADER_FILES += src/goose/goose_publisher.h
LIB_API_HEADER_FILES += src/sampled_values/sv_subscriber.h
LIB_API_HEADER_FILES += src/sampled_values/sv_publisher.h
LIB_API_HEADER_FILES += src/logging/logging_api.h
LIB_API_HEADER_FILES += src/r_session/r_session.h
LIB_API_HEADER_FILES += src/logging/logging_api.h
get_sources_from_directory = $(wildcard $1/*.c)
get_sources = $(foreach dir, $1, $(call get_sources_from_directory,$(dir)))
@ -158,7 +161,7 @@ static_checks: lib
splint -preproc +posixlib +skip-sys-headers +gnuextensions $(LIB_INCLUDES) $(LIB_SOURCES)
cppcheck: lib
cppcheck --force --std=c99 --enable=all $(LIB_INCLUDES) $(LIB_SOURCES) 2> cppcheck-output.xml
cppcheck --force --std=c99 --xml --enable=all $(LIB_INCLUDES) $(LIB_SOURCES) 2> cppcheck-output.xml
lib: $(LIB_NAME)

@ -0,0 +1,39 @@
image: atlassian/default-image:4
clone:
depth: full # SonarCloud scanner needs the full history to assign issues properly
definitions:
caches:
sonar: ~/.sonar/cache # Caching SonarCloud artifacts will speed up your build
steps:
- step: &build-test-sonarcloud
name: Build, test and analyze on SonarCloud
caches:
- sonar
script:
- export SONAR_SCANNER_VERSION=5.0.1.3006
- export SONAR_SCANNER_OPTS="-Dsonar.javaHome=/usr/lib/jvm/java-17-openjdk-amd64"
- export SONAR_SCANNER_HOME=$HOME/.sonar/sonar-scanner-$SONAR_SCANNER_VERSION-linux
- export BW_OUTPUT=$HOME/.sonar/bw-output
- mkdir -p $BW_OUTPUT
- curl --create-dirs -sSLo $HOME/.sonar/sonar-scanner.zip https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-$SONAR_SCANNER_VERSION-linux.zip
- unzip -o $HOME/.sonar/sonar-scanner.zip -d $HOME/.sonar/
- export PATH=$SONAR_SCANNER_HOME/bin:$PATH
- curl --create-dirs -sSLo $HOME/.sonar/build-wrapper-linux-x86.zip https://sonarcloud.io/static/cpp/build-wrapper-linux-x86.zip
- unzip -o $HOME/.sonar/build-wrapper-linux-x86.zip -d $HOME/.sonar/
- export PATH=$HOME/.sonar/build-wrapper-linux-x86:$PATH
- apt-get update -qq
- apt-get install cmake -y --force-yes
- mkdir build
- cmake . -Bbuild
- build-wrapper-linux-x86-64 --out-dir $BW_OUTPUT cmake --build build
- sonar-scanner -Dsonar.cfamily.build-wrapper-output=$BW_OUTPUT
pipelines: # More info here: https://confluence.atlassian.com/bitbucket/configure-bitbucket-pipelines-yml-792298910.html
branches:
master:
- step: *build-test-sonarcloud
pull-requests:
'**':
- step: *build-test-sonarcloud

@ -5,7 +5,7 @@
*/
#include "iec61850_client.h"
#include "hal_thread.h"
#include <stdlib.h>
#include <stdio.h>
@ -64,6 +64,7 @@ int main(int argc, char **argv)
goto control_error;
if (!ControlObjectClient_operate(controlLED1, ctlValOn, 0))
goto control_error;
Thread_sleep(1000);
if (!ControlObjectClient_operate(controlLED1, ctlValOff, 0))
@ -81,6 +82,7 @@ int main(int argc, char **argv)
if (!ControlObjectClient_operate(controlLED3, ctlValOn, 0))
goto control_error;
Thread_sleep(1000);
if (led4State == false)

@ -0,0 +1,205 @@
/*
* AcseAuthenticationParameter.cs
*
* Copyright 2025-2025 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 <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
using System;
using System.Runtime.InteropServices;
using System.Text;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
{
/// <summary>
/// Authentication mechanism used by AcseAuthenticator
/// </summary>
public enum AcseAuthenticationMechanism
{
/** Neither ACSE nor TLS authentication used */
ACSE_AUTH_NONE = 0,
/** Use ACSE password for client authentication */
ACSE_AUTH_PASSWORD = 1,
/** Use ACSE certificate for client authentication */
ACSE_AUTH_CERTIFICATE = 2,
/** Use TLS certificate for client authentication */
ACSE_AUTH_TLS = 3
}
public class AcseAuthenticationParameter
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr AcseAuthenticationParameter_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void AcseAuthenticationParameter_setAuthMechanism(IntPtr self, int mechanism);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void AcseAuthenticationParameter_setPassword(IntPtr self, string password);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int AcseAuthenticationParameter_getAuthMechanism(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr AcseAuthenticationParameter_getPassword(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int AcseAuthenticationParameter_getPasswordLength(IntPtr self);
private IntPtr self = IntPtr.Zero;
public AcseAuthenticationParameter()
{
self = AcseAuthenticationParameter_create();
}
public AcseAuthenticationParameter(IntPtr self)
{
this.self = self;
}
public void SetAuthMechanism(AcseAuthenticationMechanism acseAuthenticationMechanism)
{
AcseAuthenticationParameter_setAuthMechanism(self, (int)acseAuthenticationMechanism);
}
public void SetPassword(string password)
{
AcseAuthenticationParameter_setPassword(self, password);
}
public AcseAuthenticationMechanism GetAuthMechanism()
{
return (AcseAuthenticationMechanism)AcseAuthenticationParameter_getAuthMechanism(self);
}
public string GetPasswordString()
{
try
{
byte[] password = GetPasswordByteArray();
return Encoding.UTF8.GetString(password);
}
catch (Exception)
{
return null;
}
}
public byte[] GetPasswordByteArray()
{
IntPtr password = AcseAuthenticationParameter_getPassword(self);
if (password != IntPtr.Zero)
{
int lenght = GetPasswordLenght();
byte[] result = new byte[lenght];
Marshal.Copy(password, result, 0, lenght);
return result;
}
else
return null;
}
public int GetPasswordLenght()
{
return AcseAuthenticationParameter_getPasswordLength(self);
}
}
public class IsoApplicationReference
{
private IntPtr self = IntPtr.Zero;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int IsoApplicationReference_getAeQualifier(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IsoApplicationReference_getApTitle(IntPtr self);
public IsoApplicationReference(IntPtr self)
{
this.self = self;
}
public int GetAeQualifier()
{
return IsoApplicationReference_getAeQualifier(self);
}
public ItuObjectIdentifier GetApTitle()
{
IntPtr identfier = IsoApplicationReference_getApTitle(self);
if (identfier == IntPtr.Zero)
return null;
return new ItuObjectIdentifier(identfier);
}
}
public class ItuObjectIdentifier
{
private IntPtr self = IntPtr.Zero;
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ItuObjectIdentifier_getArcCount(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ItuObjectIdentifier_getArc(IntPtr self);
public ItuObjectIdentifier(IntPtr self)
{
this.self = self;
}
public int GetArcCount()
{
return ItuObjectIdentifier_getArcCount(self);
}
public ushort[] GetArcs()
{
int count = ItuObjectIdentifier_getArcCount(self);
if (count <= 0 || count > 10) return Array.Empty<ushort>();
IntPtr arcPtr = ItuObjectIdentifier_getArc(self);
ushort[] arcs = new ushort[count];
short[] temp = new short[count];
Marshal.Copy(arcPtr, temp, 0, count);
for (int i = 0; i < count; i++)
arcs[i] = (ushort)temp[i];
return arcs;
}
}
}

@ -1,24 +1,7 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("IEC61850 API for C#")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("MZ Automation GmbH")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("Michael Zillgith")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,7 +1,7 @@
/*
* Control.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,15 +21,15 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
// IEC 61850 common API parts (used by client and server API)
namespace Common {
{
// IEC 61850 common API parts (used by client and server API)
namespace Common
{
/// <summary>
/// Control model
@ -39,7 +39,7 @@ namespace IEC61850
/** status only */
STATUS_ONLY = 0,
/** direct with normal security */
DIRECT_NORMAL= 1,
DIRECT_NORMAL = 1,
/** select before operate (SBO) with normal security */
SBO_NORMAL = 2,
/** direct with enhanced security */
@ -51,7 +51,8 @@ namespace IEC61850
/// <summary>
/// Originator category
/// </summary>
public enum OrCat {
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 */
@ -70,33 +71,33 @@ namespace IEC61850
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)
{
addCause = (ControlAddCause)lastApplError.addCause;
error = lastApplError.error;
ctlNum = lastApplError.ctlNum;
}
}
}
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;
}
}
public enum ControlActionType
{
@ -108,37 +109,37 @@ namespace IEC61850
/// <summary>
/// Control object.
/// </summary>
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)]
private static extern int ControlObjectClient_getCtlValType(IntPtr self);
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)]
private static extern int ControlObjectClient_getCtlValType(IntPtr self);
[DllImport ("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int ControlObjectClient_getLastError (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int ControlObjectClient_getLastError(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool ControlObjectClient_operate(IntPtr self, IntPtr ctlVal, UInt64 operTime);
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool ControlObjectClient_operate(IntPtr self, IntPtr ctlVal, UInt64 operTime);
/// <summary>
/// Handler for asynchronous control actions (select, operate, cancel)
/// </summary>
public delegate void ControlActionHandler (UInt32 invokeId, Object parameter, IedClientError error, ControlActionType type, bool success);
public delegate void ControlActionHandler(UInt32 invokeId, Object parameter, IedClientError error, ControlActionType type, bool success);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void ControlObjectClient_ControlActionHandler (UInt32 invokeId, IntPtr parameter, int err, int type, [MarshalAs(UnmanagedType.I1)] bool success);
private delegate void ControlObjectClient_ControlActionHandler(UInt32 invokeId, IntPtr parameter, int err, int type, [MarshalAs(UnmanagedType.I1)] bool success);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 ControlObjectClient_operateAsync(IntPtr self, out int err, IntPtr ctlVal, UInt64 operTime,
@ -169,53 +170,53 @@ namespace IEC61850
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, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setSynchroCheck(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setTestMode(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
private static extern void ControlObjectClient_setOrigin(IntPtr self, string orIdent, int orCat);
[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);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setInterlockCheck(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
private IedConnection iedConnection;
private IntPtr self;
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.self = ControlObjectClient_create(objectReference, connection);
if (this.self == System.IntPtr.Zero)
throw new IedConnectionException("Control object not found", 0);
intCommandTerminationHandler = new InternalCommandTerminationHandler (MyCommandTerminationHandler);
ControlObjectClient_setCommandTerminationHandler(self, intCommandTerminationHandler, self);
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setSynchroCheck(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void ControlObjectClient_setTestMode(IntPtr self, [MarshalAs(UnmanagedType.I1)] 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 self;
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;
self = ControlObjectClient_create(objectReference, connection);
if (self == System.IntPtr.Zero)
throw new IedConnectionException("Control object not found", 0);
intCommandTerminationHandler = new InternalCommandTerminationHandler(MyCommandTerminationHandler);
ControlObjectClient_setCommandTerminationHandler(self, intCommandTerminationHandler, self);
}
/// <summary>
/// Gets the control model.
@ -223,23 +224,23 @@ namespace IEC61850
/// <returns>
/// The control model.
/// </returns>
public ControlModel GetControlModel ()
{
ControlModel controlModel = (ControlModel) ControlObjectClient_getControlModel(self);
return controlModel;
}
/// <summary>
/// Get the type of ctlVal.
/// </summary>
/// <returns>MmsType required for the ctlVal value.</returns>
public MmsType GetCtlValType ()
{
MmsType ctlValType = (MmsType) ControlObjectClient_getCtlValType (self);
return ctlValType;
}
public ControlModel GetControlModel()
{
ControlModel controlModel = (ControlModel)ControlObjectClient_getControlModel(self);
return controlModel;
}
/// <summary>
/// Get the type of ctlVal.
/// </summary>
/// <returns>MmsType required for the ctlVal value.</returns>
public MmsType GetCtlValType()
{
MmsType ctlValType = (MmsType)ControlObjectClient_getCtlValType(self);
return ctlValType;
}
/// <summary>
/// Sets the origin parameter used by control commands.
@ -250,18 +251,20 @@ namespace IEC61850
/// <param name='originatorCategory'>
/// Originator category.
/// </param>
public void SetOrigin (string originator, OrCat originatorCategory)
public void SetOrigin(string originator, OrCat originatorCategory)
{
ControlObjectClient_setOrigin(self, originator, (int) originatorCategory);
ControlObjectClient_setOrigin(self, originator, (int)originatorCategory);
}
/// <summary>
/// Gets the error code of the last synchronous control action (operate, select, select-with-value, cancel)
/// </summary>
/// <value>error code.</value>
public IedClientError LastError {
get {
return (IedClientError)ControlObjectClient_getLastError (self);
public IedClientError LastError
{
get
{
return (IedClientError)ControlObjectClient_getLastError(self);
}
}
@ -270,10 +273,10 @@ namespace IEC61850
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (bool ctlVal)
{
return Operate (ctlVal, 0);
}
public bool Operate(bool ctlVal)
{
return Operate(ctlVal, 0);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
@ -281,22 +284,22 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (bool ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate (value, operTime);
}
public bool Operate(bool ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate(value, operTime);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (float ctlVal)
{
return Operate (ctlVal, 0);
}
public bool Operate(float ctlVal)
{
return Operate(ctlVal, 0);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
@ -304,22 +307,22 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (float ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate (value, operTime);
}
public bool Operate(float ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate(value, operTime);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (int ctlVal)
{
return Operate (ctlVal, 0);
}
public bool Operate(int ctlVal)
{
return Operate(ctlVal, 0);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
@ -327,22 +330,22 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (int ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate (value, operTime);
}
public bool Operate(int ctlVal, UInt64 operTime)
{
MmsValue value = new MmsValue(ctlVal);
return Operate(value, operTime);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
/// <param name='ctlVal'>the new value of the control</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (MmsValue ctlVal)
{
return Operate (ctlVal, 0);
}
public bool Operate(MmsValue ctlVal)
{
return Operate(ctlVal, 0);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
@ -350,18 +353,18 @@ namespace IEC61850
/// <param name='ctlVal'>the new value of the control</param>
/// <param name='operTime'>the time when the operation will be executed</param>
/// <returns>true when the operation has been successful, false otherwise</returns>
public bool Operate (MmsValue ctlVal, UInt64 operTime)
{
return ControlObjectClient_operate(self, ctlVal.valueReference, operTime);
}
public bool Operate(MmsValue ctlVal, UInt64 operTime)
{
return ControlObjectClient_operate(self, ctlVal.valueReference, operTime);
}
private ControlObjectClient_ControlActionHandler internalOperateHandler = null;
private void nativeOperateHandler (UInt32 invokeId, IntPtr parameter, int err, int type, bool success)
private void nativeOperateHandler(UInt32 invokeId, IntPtr parameter, int err, int type, bool success)
{
GCHandle handle = GCHandle.FromIntPtr(parameter);
Tuple<ControlActionHandler, object> callbackInfo = handle.Target as Tuple<ControlActionHandler, object>;
Tuple<ControlActionHandler, object> callbackInfo = handle.Target as Tuple<ControlActionHandler, object>;
ControlActionHandler handler = callbackInfo.Item1;
object handlerParameter = callbackInfo.Item2;
@ -370,7 +373,7 @@ namespace IEC61850
IedClientError clientError = (IedClientError)err;
handler(invokeId, handlerParameter, clientError, (ControlActionType) type, success);
handler(invokeId, handlerParameter, clientError, (ControlActionType)type, success);
}
@ -382,11 +385,11 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (bool ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(bool ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
}
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
/// </summary>
@ -396,13 +399,13 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (bool ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(bool ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
MmsValue value = new MmsValue(ctlVal);
return OperateAsync (value, operTime, handler, parameter);
}
return OperateAsync(value, operTime, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
@ -411,11 +414,11 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (float ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(float ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
}
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value (time activated control).
/// </summary>
@ -425,13 +428,13 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (float ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(float ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
MmsValue value = new MmsValue(ctlVal);
return OperateAsync (value, operTime, handler, parameter);
}
return OperateAsync(value, operTime, handler, parameter);
}
/// <summary>
/// Operate the control with the specified control value.
/// </summary>
@ -440,9 +443,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (int ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(int ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
@ -454,9 +457,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (int ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(int ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, operTime, handler, parameter);
return OperateAsync(ctlVal, operTime, handler, parameter);
}
/// <summary>
@ -467,9 +470,9 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(MmsValue ctlVal, ControlActionHandler handler, object parameter)
{
return OperateAsync (ctlVal, 0, handler, parameter);
return OperateAsync(ctlVal, 0, handler, parameter);
}
/// <summary>
@ -481,7 +484,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 OperateAsync (MmsValue ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
public UInt32 OperateAsync(MmsValue ctlVal, UInt64 operTime, ControlActionHandler handler, object parameter)
{
int error;
@ -507,7 +510,7 @@ namespace IEC61850
/// Select the control object.
/// </summary>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool Select ()
public bool Select()
{
return ControlObjectClient_select(self);
}
@ -546,7 +549,7 @@ namespace IEC61850
/// </summary>
/// <param name='ctlVal'>the value to be checked.</param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (MmsValue ctlVal)
public bool SelectWithValue(MmsValue ctlVal)
{
return ControlObjectClient_selectWithValue(self, ctlVal.valueReference);
}
@ -558,7 +561,7 @@ namespace IEC61850
/// the value to be checked.
/// </param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (bool ctlVal)
public bool SelectWithValue(bool ctlVal)
{
return SelectWithValue(new MmsValue(ctlVal));
}
@ -570,7 +573,7 @@ namespace IEC61850
/// the value to be checked.
/// </param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (int ctlVal)
public bool SelectWithValue(int ctlVal)
{
return SelectWithValue(new MmsValue(ctlVal));
}
@ -582,7 +585,7 @@ namespace IEC61850
/// the value to be checked.
/// </param>
/// <returns>true when the selection has been successful, false otherwise</returns>
public bool SelectWithValue (float ctlVal)
public bool SelectWithValue(float ctlVal)
{
return SelectWithValue(new MmsValue(ctlVal));
}
@ -595,7 +598,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (bool ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(bool ctlVal, ControlActionHandler handler, object parameter)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
@ -608,7 +611,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (int ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(int ctlVal, ControlActionHandler handler, object parameter)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
@ -621,11 +624,11 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (float ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(float ctlVal, ControlActionHandler handler, object parameter)
{
return SelectWithValueAsync(new MmsValue(ctlVal), handler, parameter);
}
}
/// <summary>
/// Send a select with value command for generic MmsValue instances - asynchronous version
/// </summary>
@ -634,7 +637,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public UInt32 SelectWithValueAsync (MmsValue ctlVal, ControlActionHandler handler, object parameter)
public UInt32 SelectWithValueAsync(MmsValue ctlVal, ControlActionHandler handler, object parameter)
{
int error;
@ -664,7 +667,7 @@ namespace IEC61850
/// <param name="parameter">User provided callback parameter. Will be passed to the callback function</param>
/// <returns>the invoke ID of the sent request</returns>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public bool Cancel ()
public bool Cancel()
{
return ControlObjectClient_cancel(self);
}
@ -698,90 +701,93 @@ namespace IEC61850
/// Enables the synchro check for operate commands
/// </summary>
[Obsolete("use SetSynchroCheck instead")]
public void EnableSynchroCheck ()
{
ControlObjectClient_setSynchroCheck (self, true);
public void EnableSynchroCheck()
{
ControlObjectClient_setSynchroCheck(self, true);
}
/// <summary>
/// Enables the interlock check for operate and select commands
/// </summary>
[Obsolete("use SetInterlockCheck instead")]
public void EnableInterlockCheck ()
{
ControlObjectClient_setInterlockCheck (self, true);
}
/// <summary>
/// Sets the value of the interlock check flag for operate and select commands
/// </summary>
public void SetInterlockCheck (bool value)
{
ControlObjectClient_setInterlockCheck (self, value);
}
/// <summary>
/// Sets the value of the synchro check flag for operate command
/// </summary>
public void SetSynchroCheck (bool value)
{
ControlObjectClient_setSynchroCheck (self, value);
}
/// <summary>
/// Sets the value of the test flag for the operate command
/// </summary>
public void SetTestMode (bool value)
{
ControlObjectClient_setTestMode (self, value);
}
/// <summary>
/// Gets the last received LastApplError (Additional Cause Diagnostics) value.
/// </summary>
/// <returns>
/// The last appl error.
/// </returns>
public LastApplError GetLastApplError ()
{
LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(self);
return new LastApplError(lastApplError);
}
/// <summary>
/// Sets the command termination handler.
/// </summary>
/// <param name='handler'>
/// the handler (delegate) that is invoked when a CommandTerminationMessage is received.
/// </param>
/// <param name='parameter'>
/// Parameter.
/// </param>
public void SetCommandTerminationHandler (CommandTerminationHandler handler, Object parameter)
{
this.commandTerminationHandler = handler;
this.commandTerminationHandlerParameter = parameter;
}
protected virtual void Dispose(bool disposing) {
if (this.self != System.IntPtr.Zero) {
ControlObjectClient_destroy (self);
this.self = System.IntPtr.Zero;
}
}
public void Dispose() {
Dispose (true);
}
~ControlObject()
{
Dispose (false);
}
}
}
[Obsolete("use SetInterlockCheck instead")]
public void EnableInterlockCheck()
{
ControlObjectClient_setInterlockCheck(self, true);
}
/// <summary>
/// Sets the value of the interlock check flag for operate and select commands
/// </summary>
public void SetInterlockCheck(bool value)
{
ControlObjectClient_setInterlockCheck(self, value);
}
/// <summary>
/// Sets the value of the synchro check flag for operate command
/// </summary>
public void SetSynchroCheck(bool value)
{
ControlObjectClient_setSynchroCheck(self, value);
}
/// <summary>
/// Sets the value of the test flag for the operate command
/// </summary>
public void SetTestMode(bool value)
{
ControlObjectClient_setTestMode(self, value);
}
/// <summary>
/// Gets the last received LastApplError (Additional Cause Diagnostics) value.
/// </summary>
/// <returns>
/// The last appl error.
/// </returns>
public LastApplError GetLastApplError()
{
LastApplErrorInternal lastApplError = ControlObjectClient_getLastApplError(self);
return new LastApplError(lastApplError);
}
/// <summary>
/// Sets the command termination handler.
/// </summary>
/// <param name='handler'>
/// the handler (delegate) that is invoked when a CommandTerminationMessage is received.
/// </param>
/// <param name='parameter'>
/// Parameter.
/// </param>
public void SetCommandTerminationHandler(CommandTerminationHandler handler, Object parameter)
{
commandTerminationHandler = handler;
commandTerminationHandlerParameter = parameter;
}
protected virtual void Dispose(bool disposing)
{
if (self != System.IntPtr.Zero)
{
ControlObjectClient_destroy(self);
self = System.IntPtr.Zero;
}
}
public void Dispose()
{
Dispose(true);
}
~ControlObject()
{
Dispose(false);
}
}
}
}

@ -1,7 +1,7 @@
/*
* DataSet.cs
*
* Copyright 2014-2018 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,12 +20,10 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
namespace Client

@ -1,7 +1,7 @@
/*
* GooseControlBlock.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,270 +20,270 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using IEC61850.Common;
namespace IEC61850
{
namespace Client
{
namespace Client
{
public class GooseControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_create(string dataAttributeReference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_destroy(IntPtr self);
public class GooseControlBlock : IDisposable {
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_create (string dataAttributeReference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedConnection_getGoCBValues(IntPtr connection, out int error, string rcbReference, IntPtr updateRcb);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setGoCBValues(IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, [MarshalAs(UnmanagedType.I1)] bool singleRequest);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr IedConnection_getGoCBValues (IntPtr connection, out int error, string rcbReference, IntPtr updateRcb);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getGoEna(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setGoCBValues (IntPtr connection, out int error, IntPtr rcb, UInt32 parametersMask, [MarshalAs(UnmanagedType.I1)] bool singleRequest);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getGoEna (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setGoEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setGoEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getGoID(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getGoID (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setGoID(IntPtr self, string goId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setGoID (IntPtr self, string goId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getDatSet (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setDatSet(IntPtr self, string datSet);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setDatSet (IntPtr self, string datSet);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getConfRev (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getNdsComm(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getNdsComm (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getMinTime(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getMinTime (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getMaxTime(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientGooseControlBlock_getMaxTime (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getFixedOffs(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientGooseControlBlock_getFixedOffs (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern PhyComAddress ClientGooseControlBlock_getDstAddress(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern PhyComAddress ClientGooseControlBlock_getDstAddress (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getDstAddress_addr(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientGooseControlBlock_getDstAddress_addr(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte ClientGooseControlBlock_getDstAddress_priority(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte ClientGooseControlBlock_getDstAddress_priority(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientGooseControlBlock_getDstAddress_vid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientGooseControlBlock_getDstAddress_vid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientGooseControlBlock_getDstAddress_appid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientGooseControlBlock_getDstAddress_appid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setDstAddress(IntPtr self, PhyComAddress value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientGooseControlBlock_setDstAddress (IntPtr self, PhyComAddress value);
private IntPtr self;
private IntPtr connection;
private string objectReference;
private IntPtr self;
private IntPtr connection;
private string objectReference;
private bool isDisposed = false;
private bool isDisposed = false;
private bool flagGoEna = false;
private bool flagGoID = false;
private bool flagDatSet = false;
private bool flagDstAddress = false;
private bool flagGoEna = false;
private bool flagGoID = false;
private bool flagDatSet = false;
private bool flagDstAddress = false;
internal GooseControlBlock(string objectReference, IntPtr connection)
{
self = ClientGooseControlBlock_create (objectReference);
this.connection = connection;
this.objectReference = objectReference;
}
internal GooseControlBlock(string objectReference, IntPtr connection)
{
self = ClientGooseControlBlock_create(objectReference);
this.connection = connection;
this.objectReference = objectReference;
}
public string GetObjectReference ()
{
return this.objectReference;
}
public string GetObjectReference()
{
return objectReference;
}
/// <summary>
/// Read all GoCB values from the server
/// </summary>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public void GetCBValues ()
{
int error;
/// <summary>
/// Read all GoCB values from the server
/// </summary>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public void GetCBValues()
{
int error;
IedConnection_getGoCBValues (connection, out error, objectReference, self);
IedConnection_getGoCBValues(connection, out error, objectReference, self);
if (error != 0)
throw new IedConnectionException ("getGoCBValues service failed", error);
}
if (error != 0)
throw new IedConnectionException("getGoCBValues service failed", error);
}
private void
resetSendFlags()
{
flagGoEna = false;
flagGoID = false;
flagDatSet = false;
flagDstAddress = false;
}
private void
resetSendFlags()
{
flagGoEna = false;
flagGoID = false;
flagDatSet = false;
flagDstAddress = false;
}
public void SetCBValues (bool singleRequest)
{
UInt32 parametersMask = 0;
public void SetCBValues(bool singleRequest)
{
UInt32 parametersMask = 0;
if (flagGoEna)
parametersMask += 1;
if (flagGoEna)
parametersMask += 1;
if (flagGoID)
parametersMask += 2;
if (flagGoID)
parametersMask += 2;
if (flagDatSet)
parametersMask += 4;
if (flagDatSet)
parametersMask += 4;
if (flagDstAddress)
parametersMask += 32;
if (flagDstAddress)
parametersMask += 32;
int error;
int error;
IedConnection_setGoCBValues (connection, out error, self, parametersMask, singleRequest);
IedConnection_setGoCBValues(connection, out error, self, parametersMask, singleRequest);
resetSendFlags ();
resetSendFlags();
if (error != 0)
throw new IedConnectionException ("setGoCBValues service failed", error);
}
if (error != 0)
throw new IedConnectionException("setGoCBValues service failed", error);
}
public void SetCBValues ()
{
SetCBValues (true);
}
public void SetCBValues()
{
SetCBValues(true);
}
public bool GetGoEna()
{
return ClientGooseControlBlock_getGoEna (self);
}
public bool GetGoEna()
{
return ClientGooseControlBlock_getGoEna(self);
}
public void SetGoEna(bool value)
{
ClientGooseControlBlock_setGoEna (self, value);
public void SetGoEna(bool value)
{
ClientGooseControlBlock_setGoEna(self, value);
flagGoEna = true;
}
flagGoEna = true;
}
public string GetGoID()
{
IntPtr goIdRef = ClientGooseControlBlock_getGoID (self);
public string GetGoID()
{
IntPtr goIdRef = ClientGooseControlBlock_getGoID(self);
return Marshal.PtrToStringAnsi (goIdRef);
}
return Marshal.PtrToStringAnsi(goIdRef);
}
public void SetGoID (string goID)
{
ClientGooseControlBlock_setGoID (self, goID);
public void SetGoID(string goID)
{
ClientGooseControlBlock_setGoID(self, goID);
flagGoID = true;
}
flagGoID = true;
}
public string GetDatSet()
{
IntPtr datSetRef = ClientGooseControlBlock_getDatSet (self);
public string GetDatSet()
{
IntPtr datSetRef = ClientGooseControlBlock_getDatSet(self);
return Marshal.PtrToStringAnsi (datSetRef);
}
return Marshal.PtrToStringAnsi(datSetRef);
}
public void SetDataSet(string datSet)
{
ClientGooseControlBlock_setDatSet (self, datSet);
public void SetDataSet(string datSet)
{
ClientGooseControlBlock_setDatSet(self, datSet);
flagDatSet = true;
}
flagDatSet = true;
}
public UInt32 GetConfRev()
{
return ClientGooseControlBlock_getConfRev (self);
}
public UInt32 GetConfRev()
{
return ClientGooseControlBlock_getConfRev(self);
}
public bool GetNdsComm()
{
return ClientGooseControlBlock_getNdsComm (self);
}
public bool GetNdsComm()
{
return ClientGooseControlBlock_getNdsComm(self);
}
public UInt32 GetMinTime()
{
return ClientGooseControlBlock_getMinTime (self);
}
public UInt32 GetMinTime()
{
return ClientGooseControlBlock_getMinTime(self);
}
public UInt32 GetMaxTime()
{
return ClientGooseControlBlock_getMaxTime (self);
}
public UInt32 GetMaxTime()
{
return ClientGooseControlBlock_getMaxTime(self);
}
public bool GetFixedOffs()
{
return ClientGooseControlBlock_getFixedOffs (self);
}
public bool GetFixedOffs()
{
return ClientGooseControlBlock_getFixedOffs(self);
}
public PhyComAddress GetDstAddress()
{
PhyComAddress addr = new PhyComAddress();
public PhyComAddress GetDstAddress()
{
PhyComAddress addr = new PhyComAddress();
IntPtr value = ClientGooseControlBlock_getDstAddress_addr(self);
IntPtr value = ClientGooseControlBlock_getDstAddress_addr(self);
MmsValue mmsValue = new MmsValue(value);
MmsValue mmsValue = new MmsValue(value);
byte[] dstMacAddr = mmsValue.getOctetString();
byte[] dstMacAddr = mmsValue.getOctetString();
dstMacAddr.CopyTo(addr.dstAddress, 0);
dstMacAddr.CopyTo(addr.dstAddress, 0);
addr.dstAddress = dstMacAddr;
addr.dstAddress = dstMacAddr;
addr.appId = ClientGooseControlBlock_getDstAddress_appid(self);
addr.vlanId = ClientGooseControlBlock_getDstAddress_vid(self);
addr.vlanPriority = ClientGooseControlBlock_getDstAddress_priority(self);
addr.appId = ClientGooseControlBlock_getDstAddress_appid(self);
addr.vlanId = ClientGooseControlBlock_getDstAddress_vid(self);
addr.vlanPriority = ClientGooseControlBlock_getDstAddress_priority(self);
return addr;
}
return addr;
}
public void SetDstAddress(PhyComAddress value)
{
ClientGooseControlBlock_setDstAddress (self, value);
public void SetDstAddress(PhyComAddress value)
{
ClientGooseControlBlock_setDstAddress(self, value);
flagDstAddress = true;
}
flagDstAddress = true;
}
public void Dispose()
{
if (isDisposed == false) {
isDisposed = true;
ClientGooseControlBlock_destroy (self);
self = IntPtr.Zero;
}
}
public void Dispose()
{
if (isDisposed == false)
{
isDisposed = true;
ClientGooseControlBlock_destroy(self);
self = IntPtr.Zero;
}
}
~GooseControlBlock()
{
Dispose ();
}
~GooseControlBlock()
{
Dispose();
}
}
}
}
}
}

@ -1,7 +1,7 @@
/*
* GooseSubscriber.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,345 +21,351 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
namespace GOOSE
{
namespace Subscriber
{
/// <summary>
/// GOOSE listener.
/// </summary>
public delegate void GooseListener (GooseSubscriber report, object parameter);
public class GooseReceiver : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseReceiver_create ();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_addSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_removeSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_start(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_stop(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseReceiver_isRunning (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_setInterfaceId(IntPtr self, string interfaceId);
private IntPtr self;
private bool isDisposed = false;
private List<GooseSubscriber> subscribers = new List<GooseSubscriber>();
public GooseReceiver()
{
self = GooseReceiver_create ();
}
public void SetInterfaceId(string interfaceId)
{
GooseReceiver_setInterfaceId (self, interfaceId);
}
/// <summary>
/// Add the subscriber to be handled by this receiver instance
/// </summary>
/// <remarks>A GooseSubscriber can only be added to one GooseReceiver!</remarks>
/// <param name="subscriber"></param>
public void AddSubscriber(GooseSubscriber subscriber)
{
if (subscriber.attachedToReceiver == false)
{
subscriber.attachedToReceiver = true;
GooseReceiver_addSubscriber(self, subscriber.self);
subscribers.Add(subscriber);
}
}
public void RemoveSubscriber(GooseSubscriber subscriber)
{
if (subscriber.attachedToReceiver)
{
GooseReceiver_removeSubscriber(self, subscriber.self);
subscribers.Remove(subscriber);
subscriber.attachedToReceiver = false;
}
}
public void Start()
{
GooseReceiver_start (self);
}
public void Stop()
{
GooseReceiver_stop (self);
}
public bool IsRunning()
{
return GooseReceiver_isRunning (self);
}
namespace GOOSE
{
namespace Subscriber
{
/// <summary>
/// GOOSE listener.
/// </summary>
public delegate void GooseListener(GooseSubscriber report, object parameter);
public class GooseReceiver : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseReceiver_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_addSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_removeSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_start(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_stop(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseReceiver_isRunning(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseReceiver_setInterfaceId(IntPtr self, string interfaceId);
private IntPtr self;
private bool isDisposed = false;
private List<GooseSubscriber> subscribers = new List<GooseSubscriber>();
public GooseReceiver()
{
self = GooseReceiver_create();
}
public void SetInterfaceId(string interfaceId)
{
GooseReceiver_setInterfaceId(self, interfaceId);
}
/// <summary>
/// Add the subscriber to be handled by this receiver instance
/// </summary>
/// <remarks>A GooseSubscriber can only be added to one GooseReceiver!</remarks>
/// <param name="subscriber"></param>
public void AddSubscriber(GooseSubscriber subscriber)
{
if (subscriber.attachedToReceiver == false)
{
subscriber.attachedToReceiver = true;
GooseReceiver_addSubscriber(self, subscriber.self);
subscribers.Add(subscriber);
}
}
public void RemoveSubscriber(GooseSubscriber subscriber)
{
if (subscriber.attachedToReceiver)
{
GooseReceiver_removeSubscriber(self, subscriber.self);
subscribers.Remove(subscriber);
subscriber.attachedToReceiver = false;
}
}
public void Start()
{
GooseReceiver_start(self);
}
public void Stop()
{
GooseReceiver_stop(self);
}
public bool IsRunning()
{
return GooseReceiver_isRunning(self);
}
public void Dispose()
{
if (isDisposed == false)
{
isDisposed = true;
GooseReceiver_destroy(self);
self = IntPtr.Zero;
}
}
~GooseReceiver()
{
Dispose();
}
}
/// <summary>
/// Representing a GOOSE subscriber
/// </summary>
/// <description>
/// NOTE: After SetListener is called, do not call any function outside of
/// the callback handler!
/// </description>
public class GooseSubscriber : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalGooseListener(IntPtr subscriber, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_create(string goCbRef, IntPtr dataSetValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_setAppId(IntPtr self, UInt16 appId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_isValid(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getStNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getSqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_isTest(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_needsCommission(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getTimeAllowedToLive(IntPtr self);
public void Dispose()
{
if (isDisposed == false) {
isDisposed = true;
GooseReceiver_destroy (self);
self = IntPtr.Zero;
}
}
~GooseReceiver()
{
Dispose ();
}
}
/// <summary>
/// Representing a GOOSE subscriber
/// </summary>
/// <description>
/// NOTE: After SetListener is called, do not call any function outside of
/// the callback handler!
/// </description>
public class GooseSubscriber : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalGooseListener (IntPtr subscriber, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_create (string goCbRef, IntPtr dataSetValue);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_setAppId(IntPtr self, UInt16 appId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_isValid (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getStNum (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getSqNum (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_isTest (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getConfRev (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool GooseSubscriber_needsCommission (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 GooseSubscriber_getTimeAllowedToLive (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt64 GooseSubscriber_getTimestamp (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getDataSetValues(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_setListener (IntPtr self, InternalGooseListener listener, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getGoId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getGoCbRef(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getDataSet(IntPtr self);
internal IntPtr self;
private bool isDisposed = false;
// don't call native destructor when attached to a receiver
internal bool attachedToReceiver = false;
private GooseListener listener = null;
private object listenerParameter = null;
private event InternalGooseListener internalListener = null;
private void internalGooseListener (IntPtr subscriber, IntPtr parameter)
{
try {
if (listener != null) {
listener(this, listenerParameter);
}
} catch (Exception e)
{
// older versions of mono 2.10 (for linux?) cause this exception
Console.WriteLine(e.Message);
}
}
public GooseSubscriber(string goCbRef)
{
self = GooseSubscriber_create (goCbRef, IntPtr.Zero);
}
public void SetAppId(UInt16 appId)
{
GooseSubscriber_setAppId (self, appId);
}
public bool IsValid ()
{
return GooseSubscriber_isValid (self);
}
public void SetListener(GooseListener listener, object parameter)
{
this.listener = listener;
this.listenerParameter = parameter;
if (internalListener == null) {
internalListener = new InternalGooseListener (internalGooseListener);
GooseSubscriber_setListener (self, internalListener, IntPtr.Zero);
}
}
public string GetGoId()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getGoId(self));
}
public string GetGoCbRef()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getGoCbRef(self));
}
public string GetDataSet()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getDataSet(self));
}
public UInt32 GetStNum()
{
return GooseSubscriber_getStNum (self);
}
public UInt32 GetSqNum()
{
return GooseSubscriber_getSqNum (self);
}
public bool IsTest()
{
return GooseSubscriber_isTest (self);
}
public UInt32 GetConfRev()
{
return GooseSubscriber_getConfRev (self);
}
public bool NeedsCommission()
{
return GooseSubscriber_needsCommission (self);
}
public UInt32 GetTimeAllowedToLive()
{
return GooseSubscriber_getTimeAllowedToLive (self);
}
public UInt64 GetTimestamp ()
{
return GooseSubscriber_getTimestamp (self);
}
public DateTimeOffset GetTimestampsDateTimeOffset ()
{
UInt64 entryTime = GetTimestamp ();
DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
return retVal.AddMilliseconds (entryTime);
}
/// <summary>
/// Get the values of the GOOSE data set from the last received GOOSE message
/// </summary>
/// <remarks>
/// The MmsValue instance is only valid in the context of the GooseLister callback.
/// Do not store for outside use!
/// </remarks>
/// <returns>The data set values.</returns>
public MmsValue GetDataSetValues()
{
IntPtr mmsValueRef = GooseSubscriber_getDataSetValues (self);
return (new MmsValue (mmsValueRef));
}
/// <summary>
/// Releases all resource used by the <see cref="IEC61850.GOOSE.Subscriber.GooseSubscriber"/> object.
/// </summary>
/// <remarks>>
/// This function has only to be called when the <see cref="IEC61850.GOOSE.Subscriber.GooseSubscriber"/>
/// has not been added to the GooseReceiver or has been removed from the GooseReceiver.
/// When the GooseReceiver holds a reference it will take care for releasing the resources.
/// In this case Dispose MUST not be called! Otherwise the natice resources will be
/// released twice.
/// </remarks>
public void Dispose()
{
if (isDisposed == false) {
isDisposed = true;
if (attachedToReceiver == false)
GooseSubscriber_destroy (self);
self = IntPtr.Zero;
}
}
~GooseSubscriber()
{
Dispose();
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt64 GooseSubscriber_getTimestamp(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getDataSetValues(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void GooseSubscriber_setListener(IntPtr self, InternalGooseListener listener, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getGoId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getGoCbRef(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr GooseSubscriber_getDataSet(IntPtr self);
internal IntPtr self;
private bool isDisposed = false;
// don't call native destructor when attached to a receiver
internal bool attachedToReceiver = false;
private GooseListener listener = null;
private object listenerParameter = null;
private event InternalGooseListener internalListener = null;
private void internalGooseListener(IntPtr subscriber, IntPtr parameter)
{
try
{
if (listener != null)
{
listener(this, listenerParameter);
}
}
catch (Exception e)
{
// older versions of mono 2.10 (for linux?) cause this exception
Console.WriteLine(e.Message);
}
}
public GooseSubscriber(string goCbRef)
{
self = GooseSubscriber_create(goCbRef, IntPtr.Zero);
}
public void SetAppId(UInt16 appId)
{
GooseSubscriber_setAppId(self, appId);
}
public bool IsValid()
{
return GooseSubscriber_isValid(self);
}
public void SetListener(GooseListener listener, object parameter)
{
this.listener = listener;
listenerParameter = parameter;
if (internalListener == null)
{
internalListener = new InternalGooseListener(internalGooseListener);
GooseSubscriber_setListener(self, internalListener, IntPtr.Zero);
}
}
public string GetGoId()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getGoId(self));
}
public string GetGoCbRef()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getGoCbRef(self));
}
public string GetDataSet()
{
return Marshal.PtrToStringAnsi(GooseSubscriber_getDataSet(self));
}
public UInt32 GetStNum()
{
return GooseSubscriber_getStNum(self);
}
public UInt32 GetSqNum()
{
return GooseSubscriber_getSqNum(self);
}
public bool IsTest()
{
return GooseSubscriber_isTest(self);
}
public UInt32 GetConfRev()
{
return GooseSubscriber_getConfRev(self);
}
public bool NeedsCommission()
{
return GooseSubscriber_needsCommission(self);
}
public UInt32 GetTimeAllowedToLive()
{
return GooseSubscriber_getTimeAllowedToLive(self);
}
public UInt64 GetTimestamp()
{
return GooseSubscriber_getTimestamp(self);
}
public DateTimeOffset GetTimestampsDateTimeOffset()
{
UInt64 entryTime = GetTimestamp();
DateTimeOffset retVal = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
return retVal.AddMilliseconds(entryTime);
}
/// <summary>
/// Get the values of the GOOSE data set from the last received GOOSE message
/// </summary>
/// <remarks>
/// The MmsValue instance is only valid in the context of the GooseLister callback.
/// Do not store for outside use!
/// </remarks>
/// <returns>The data set values.</returns>
public MmsValue GetDataSetValues()
{
IntPtr mmsValueRef = GooseSubscriber_getDataSetValues(self);
return (new MmsValue(mmsValueRef));
}
/// <summary>
/// Releases all resource used by the <see cref="IEC61850.GOOSE.Subscriber.GooseSubscriber"/> object.
/// </summary>
/// <remarks>>
/// This function has only to be called when the <see cref="IEC61850.GOOSE.Subscriber.GooseSubscriber"/>
/// has not been added to the GooseReceiver or has been removed from the GooseReceiver.
/// When the GooseReceiver holds a reference it will take care for releasing the resources.
/// In this case Dispose MUST not be called! Otherwise the natice resources will be
/// released twice.
/// </remarks>
public void Dispose()
{
if (isDisposed == false)
{
isDisposed = true;
if (attachedToReceiver == false)
GooseSubscriber_destroy(self);
self = IntPtr.Zero;
}
}
~GooseSubscriber()
{
Dispose();
}
}
}
}
}
}
}

@ -1,52 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C35D624E-5506-4560-8074-1728F1FA1A4D}</ProjectGuid>
<TargetFramework>netstandard2.0</TargetFramework>
<OutputType>Library</OutputType>
<RootNamespace>iec61850dotnet</RootNamespace>
<AssemblyName>iec61850dotnet</AssemblyName>
<AssemblyTitle>IEC61850 API for C#</AssemblyTitle>
<Company>MZ Automation GmbH</Company>
<Copyright>Michael Zillgith</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="MmsValue.cs" />
<Compile Include="DataSet.cs" />
<Compile Include="ReportControlBlock.cs" />
<Compile Include="IEC61850ClientAPI.cs" />
<Compile Include="Reporting.cs" />
<Compile Include="Control.cs" />
<Compile Include="IsoConnectionParameters.cs" />
<Compile Include="MmsVariableSpecification.cs" />
<Compile Include="IEC61850ServerAPI.cs" />
<Compile Include="IEC61850CommonAPI.cs" />
<Compile Include="TLS.cs" />
<Compile Include="SampledValuesControlBlock.cs" />
<Compile Include="GooseControlBlock.cs" />
<Compile Include="GooseSubscriber.cs" />
<Compile Include="SampledValuesSubscriber.cs" />
<Compile Include="IedServerConfig.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
</Project>

@ -1,7 +1,7 @@
/*
* IEC61850ClientAPI.cs
*
* Copyright 2014-2023 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,14 +20,11 @@
*
* See COPYING file for the complete license text.
*/
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections;
using IEC61850.Common;
using IEC61850.TLS;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
@ -62,11 +59,11 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void MmsServerIdentity_destroy(IntPtr self);
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
private static extern void MmsConnection_setLocalDetail (IntPtr self, Int32 localDetail);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void MmsConnection_setLocalDetail(IntPtr self, Int32 localDetail);
[DllImport ("iec61850", CallingConvention=CallingConvention.Cdecl)]
private static extern Int32 MmsConnection_getLocalDetail (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 MmsConnection_getLocalDetail(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 MmsConnection_setRequestTimeout(IntPtr self, UInt32 timeoutInMs);
@ -106,11 +103,11 @@ namespace IEC61850
self = mmsConnection;
}
~MmsConnection ()
~MmsConnection()
{
if (selfDestroy)
if (self != IntPtr.Zero)
MmsConnection_destroy(self);
if (self != IntPtr.Zero)
MmsConnection_destroy(self);
}
private void FreeHGlobaleDeleteFunction(IntPtr pointer)
@ -140,7 +137,7 @@ namespace IEC61850
throw new IedConnectionException("Failed to read server identity");
MmsServerIdentity serverIdentity = (MmsServerIdentity)
Marshal.PtrToStructure(identity, typeof(MmsServerIdentity));
Marshal.PtrToStructure(identity, typeof(MmsServerIdentity));
MmsServerIdentity_destroy(identity);
@ -194,7 +191,7 @@ namespace IEC61850
int error;
IntPtr mmsValue = MmsConnection_readMultipleVariables(self, out error, domainName, linkedList);
LinkedList_destroyDeep(linkedList, new LinkedListValueDeleteFunction(FreeHGlobaleDeleteFunction));
if (error != 0)
@ -343,7 +340,7 @@ namespace IEC61850
}
}
~MmsJournalEntry ()
~MmsJournalEntry()
{
Dispose();
}
@ -356,7 +353,7 @@ namespace IEC61850
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
/// <param name="rcb">the report control block instance</param>
public delegate void GetRCBValuesHandler(UInt32 invokeId,object parameter,IedClientError err,ReportControlBlock rcb);
public delegate void GetRCBValuesHandler(UInt32 invokeId, object parameter, IedClientError err, ReportControlBlock rcb);
/// <summary>
/// Asynchonous service handler for the set RCB values service
@ -365,7 +362,7 @@ namespace IEC61850
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
/// <param name="rcb">the report control block instance</param>
public delegate void SetRCBValuesHandler(UInt32 invokeId,object parameter,IedClientError err,ReportControlBlock rcb);
public delegate void SetRCBValuesHandler(UInt32 invokeId, object parameter, IedClientError err, ReportControlBlock rcb);
/// <summary>
/// Generic asynchonous service handler - used by simple services that have only success or error result
@ -373,7 +370,7 @@ namespace IEC61850
/// <param name="invokeId">The invoke ID of the request triggering this callback</param>
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
public delegate void GenericServiceHandler(UInt32 invokeId,object parameter,IedClientError err);
public delegate void GenericServiceHandler(UInt32 invokeId, object parameter, IedClientError err);
/// <summary>
/// This class acts as the entry point for the IEC 61850 client API. It represents a single
@ -483,7 +480,7 @@ namespace IEC61850
static extern IntPtr IedConnection_getVariableSpecification(IntPtr self, out int error, string objectReference, int fc);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalConnectionClosedHandler(IntPtr parameter,IntPtr Iedconnection);
private delegate void InternalConnectionClosedHandler(IntPtr parameter, IntPtr Iedconnection);
/// <summary>
/// Called when the connection is closed
@ -552,7 +549,7 @@ namespace IEC61850
static extern int IedConnection_getState(IntPtr connection);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalStateChangedHandler(IntPtr parameter,IntPtr iedConnection,int newState);
private delegate void InternalStateChangedHandler(IntPtr parameter, IntPtr iedConnection, int newState);
/// <summary>
/// Called when there is a change in the connection state
@ -582,56 +579,56 @@ namespace IEC61850
private static extern void IedConnection_releaseAsync(IntPtr self, out int error);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_ReadObjectHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr value);
private delegate void IedConnection_ReadObjectHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_readObjectAsync(IntPtr self, out int error, string objRef, int fc,
IedConnection_ReadObjectHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_WriteObjectHandler(UInt32 invokeId,IntPtr parameter,int err);
private delegate void IedConnection_WriteObjectHandler(UInt32 invokeId, IntPtr parameter, int err);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_writeObjectAsync(IntPtr self, out int error, string objRef, int fc,
IntPtr value, IedConnection_WriteObjectHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_GetNameListHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr nameList,[MarshalAs(UnmanagedType.I1)] bool moreFollows);
private delegate void IedConnection_GetNameListHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr nameList, [MarshalAs(UnmanagedType.I1)] bool moreFollows);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_getServerDirectoryAsync(IntPtr self, out int error, string continueAfter, IntPtr result,
IedConnection_GetNameListHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_getLogicalDeviceVariablesAsync(IntPtr self, out int error, string ldName, string continueAfter, IntPtr result,
IedConnection_GetNameListHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_getLogicalDeviceDataSetsAsync(IntPtr self, out int error, string ldName, string continueAfter, IntPtr result,
IedConnection_GetNameListHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_QueryLogHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr journalEntries,[MarshalAs(UnmanagedType.I1)] bool moreFollows);
private delegate void IedConnection_QueryLogHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr journalEntries, [MarshalAs(UnmanagedType.I1)] bool moreFollows);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_queryLogByTimeAsync(IntPtr self, out int error, string logReference,
UInt64 startTime, UInt64 endTime, IedConnection_QueryLogHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_queryLogAfterAsync(IntPtr self, out int error, string logReference,
IntPtr entryID, UInt64 timeStamp, IedConnection_QueryLogHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_GetVariableSpecificationHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr spec);
private delegate void IedConnection_GetVariableSpecificationHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr spec);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_getVariableSpecificationAsync(IntPtr self, out int error, string dataAttributeReference,
int fc, IedConnection_GetVariableSpecificationHandler handler, IntPtr parameter);
@ -639,7 +636,7 @@ namespace IEC61850
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_ReadDataSetHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr dataSet);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_readDataSetValuesAsync(IntPtr self, out int error, string dataSetReference, IntPtr dataSet,
IedConnection_ReadDataSetHandler handler, IntPtr parameter);
@ -663,26 +660,26 @@ namespace IEC61850
IedConnection_GetDataSetDirectoryHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_GetRCBValuesHandler(UInt32 invokeId,IntPtr parameter,int err,IntPtr rcb);
private delegate void IedConnection_GetRCBValuesHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr rcb);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_getRCBValuesAsync(IntPtr self, out int error, string rcbReference, IntPtr updateRcb,
IedConnection_GetRCBValuesHandler handler, IntPtr parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void IedConnection_GenericServiceHandler(UInt32 invokeId,IntPtr parameter,int err);
private delegate void IedConnection_GenericServiceHandler(UInt32 invokeId, IntPtr parameter, int err);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_setRCBValuesAsync(IntPtr self, out int error, IntPtr rcb,
UInt32 parametersMask, [MarshalAs(UnmanagedType.I1)] bool singleRequest, IedConnection_GenericServiceHandler handler, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_deleteFileAsync(IntPtr self, out int error, string fileName,
IedConnection_deleteFileAsync(IntPtr self, out int error, string fileName,
IedConnection_GenericServiceHandler handler, IntPtr parameter);
/********************
* FileDirectoryEntry
@ -706,7 +703,7 @@ namespace IEC61850
static extern void LinkedList_destroyStatic(IntPtr self);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void LinkedListValueDeleteFunction(IntPtr pointer);
private delegate void LinkedListValueDeleteFunction(IntPtr pointer);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void LinkedList_destroyDeep(IntPtr list, LinkedListValueDeleteFunction valueDeleteFunction);
@ -759,7 +756,7 @@ namespace IEC61850
}
}
~IedConnection ()
~IedConnection()
{
Dispose();
}
@ -897,7 +894,7 @@ namespace IEC61850
if (error != 0)
throw new IedConnectionException("Connect to " + hostname + ":" + tcpPort + " failed", error);
}
/// <summary>
@ -1264,7 +1261,6 @@ namespace IEC61850
moreFollows = moreFollowsVal;
return WrapNativeLogQueryResult(linkedList);
}
/// <summary>
@ -1304,7 +1300,7 @@ namespace IEC61850
{
int error;
IntPtr mmsValue = IedConnection_readObject(connection, out error, objectReference, (int)fc);
IntPtr mmsValue = IedConnection_readObject(connection, out error, objectReference, (int)fc);
if (error != 0)
throw new IedConnectionException("Reading value failed", error);
@ -1531,7 +1527,7 @@ namespace IEC61850
handle.Free();
IedClientError clientError = (IedClientError)err;
handler(invokeId, handlerParameter, clientError);
}
@ -1633,7 +1629,7 @@ namespace IEC61850
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private delegate bool InternalIedClientGetFileHandler(IntPtr parameter,IntPtr buffer,UInt32 bytesRead);
private delegate bool InternalIedClientGetFileHandler(IntPtr parameter, IntPtr buffer, UInt32 bytesRead);
private bool iedClientGetFileHandler(IntPtr parameter, IntPtr buffer, UInt32 bytesRead)
{
@ -1650,16 +1646,16 @@ namespace IEC61850
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 IedConnection_getFile(IntPtr self, out int error, string fileName, InternalIedClientGetFileHandler handler,
IntPtr handlerParameter);
IntPtr handlerParameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setFile(IntPtr self, out int error, string sourceFilename, string destinationFilename);
static extern void IedConnection_setFile(IntPtr self, out int error, string sourceFilename, string destinationFilename);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void IedConnection_setFilestoreBasepath(IntPtr self, string fileName);
public delegate bool GetFileHandler(object parameter,byte[] data);
public delegate bool GetFileHandler(object parameter, byte[] data);
private class GetFileCallback
{
@ -1694,7 +1690,7 @@ namespace IEC61850
GCHandle handle = GCHandle.Alloc(getFileCallback);
IedConnection_getFile(connection, out error, fileName, new InternalIedClientGetFileHandler(iedClientGetFileHandler),
IedConnection_getFile(connection, out error, fileName, new InternalIedClientGetFileHandler(iedClientGetFileHandler),
GCHandle.ToIntPtr(handle));
if (error != 0)
@ -1721,11 +1717,10 @@ namespace IEC61850
{
int error;
IedConnection_setFile(connection, out error, sourceFilename, destinationFilename);
IedConnection_setFile(connection, out error, sourceFilename, destinationFilename);
if (error != 0)
throw new IedConnectionException("Error uploading file", error);
}
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
@ -1745,7 +1740,7 @@ namespace IEC61850
/// <returns>true, continue the file download when moreFollows is true, false, stop file download</returns>
public delegate bool GetFileAsyncHandler(UInt32 invokeId, object parameter, IedClientError err, UInt32 originalInvokeId, byte[] buffer, bool moreFollows);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32
IedConnection_getFileAsync(IntPtr self, out int error, string fileName, IedConnection_GetFileAsyncHandler handler,
IntPtr parameter);
@ -1765,15 +1760,15 @@ namespace IEC61850
IedClientError clientError = (IedClientError)err;
byte[] bytes = null;
if (clientError == IedClientError.IED_ERROR_OK)
{
bytes = new byte[bytesRead];
Marshal.Copy(buffer, bytes, 0, (int)bytesRead);
}
bool retVal = handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows);
}
bool retVal = handler(invokeId, handlerParameter, clientError, originalInvokeId, bytes, moreFollows);
if (clientError != IedClientError.IED_ERROR_OK)
{
@ -1931,7 +1926,7 @@ namespace IEC61850
IedConnection_installConnectionClosedHandler(connection, connectionClosedHandler, connection);
}
userProvidedConnectionClosedHandler = handler;
userProvidedConnectionClosedHandler = handler;
}
private void MyStateChangedHandler(IntPtr parameter, IntPtr IedConnection, int newState)
@ -2013,11 +2008,11 @@ namespace IEC61850
if (dataSet != null)
nativeClientDataSet = dataSet.getNativeInstance();
int error;
nativeClientDataSet = IedConnection_readDataSetValues(connection, out error, dataSetReference, nativeClientDataSet);
if (error != 0)
throw new IedConnectionException("Reading data set failed", error);
@ -2109,7 +2104,6 @@ namespace IEC61850
if (error != 0)
throw new IedConnectionException("Failed to create data set", error);
}
/// <summary>
@ -2341,7 +2335,7 @@ namespace IEC61850
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
/// <param name="value">The read result value or null in case of an error</param>
public delegate void ReadValueHandler(UInt32 invokeId,object parameter,IedClientError err,MmsValue value);
public delegate void ReadValueHandler(UInt32 invokeId, object parameter, IedClientError err, MmsValue value);
private IedConnection_ReadObjectHandler internalReadObjectHandler = null;
@ -2420,7 +2414,7 @@ namespace IEC61850
handler(invokeId, handlerParameter, clientError, varSpec);
}
public delegate void GetVariableSpecifcationHandler(UInt32 invokeId,object parameter,IedClientError err,MmsVariableSpecification spec);
public delegate void GetVariableSpecifcationHandler(UInt32 invokeId, object parameter, IedClientError err, MmsVariableSpecification spec);
/// <summary>Read the variable specification (type description of a DA or FCDO</summary>
/// <param name="objectReference">The object reference of a DA or FCDO.</param>
@ -2440,7 +2434,7 @@ namespace IEC61850
if (internalGetVariableSpecificationHandler == null)
internalGetVariableSpecificationHandler = new IedConnection_GetVariableSpecificationHandler(nativeGetVariableSpecifcationHandler);
UInt32 invokeId = IedConnection_getVariableSpecificationAsync(connection, out error, objectReference, (int)fc, internalGetVariableSpecificationHandler, GCHandle.ToIntPtr(handle));
UInt32 invokeId = IedConnection_getVariableSpecificationAsync(connection, out error, objectReference, (int)fc, internalGetVariableSpecificationHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
@ -2472,11 +2466,11 @@ namespace IEC61850
if (dataSet == null)
dataSet = new DataSet(nativeDataSet);
}
handler(invokeId, handlerParameter, clientError, dataSet);
}
public delegate void ReadDataSetHandler(UInt32 invokeId,object parameter,IedClientError err,DataSet dataSet);
public delegate void ReadDataSetHandler(UInt32 invokeId, object parameter, IedClientError err, DataSet dataSet);
/// <summary>
/// Read the values of a data set (GetDataSetValues service) - asynchronous version
@ -2507,7 +2501,7 @@ namespace IEC61850
if (internalReadDataSetHandler == null)
internalReadDataSetHandler = new IedConnection_ReadDataSetHandler(nativeReadDataSetHandler);
UInt32 invokeId = IedConnection_readDataSetValuesAsync(connection, out error, dataSetReference, dataSetPtr, internalReadDataSetHandler, GCHandle.ToIntPtr(handle));
UInt32 invokeId = IedConnection_readDataSetValuesAsync(connection, out error, dataSetReference, dataSetPtr, internalReadDataSetHandler, GCHandle.ToIntPtr(handle));
if (error != 0)
{
@ -2524,7 +2518,7 @@ namespace IEC61850
/// <param name="invokeId">The invoke ID of the reqeust triggering this callback</param>
/// <param name="parameter">user provided callback parameter</param>
/// <param name="err">Error code of response or timeout error in case of a response timeout</param>
public delegate void WriteValueHandler(UInt32 invokeId,object parameter,IedClientError err);
public delegate void WriteValueHandler(UInt32 invokeId, object parameter, IedClientError err);
private IedConnection_WriteObjectHandler internalWriteObjectHandler = null;
@ -2544,7 +2538,6 @@ namespace IEC61850
handler(invokeId, handlerParameter, clientError);
}
public UInt32 WriteValueAsync(string objectReference, FunctionalConstraint fc, MmsValue value, WriteValueHandler handler, object parameter)
{
int error;
@ -2567,11 +2560,11 @@ namespace IEC61850
return invokeId;
}
public delegate void GetNameListHandler(UInt32 invokeId,object parameter,IedClientError err,List<string> nameList,bool moreFollows);
public delegate void GetNameListHandler(UInt32 invokeId, object parameter, IedClientError err, List<string> nameList, bool moreFollows);
private IedConnection_GetNameListHandler internalGetNameListHandler = null;
private void nativeGetNameListHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr nameList, [MarshalAs(UnmanagedType.I1)] bool moreFollows)
private void nativeGetNameListHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr nameList, [MarshalAs(UnmanagedType.I1)] bool moreFollows)
{
GCHandle handle = GCHandle.FromIntPtr(parameter);
@ -2696,11 +2689,11 @@ namespace IEC61850
return invokeId;
}
public delegate void QueryLogHandler(UInt32 invokeId,object parameter,IedClientError err,List<MmsJournalEntry> journalEntries,bool moreFollows);
public delegate void QueryLogHandler(UInt32 invokeId, object parameter, IedClientError err, List<MmsJournalEntry> journalEntries, bool moreFollows);
private IedConnection_QueryLogHandler internalQueryLogHandler = null;
private void nativeQueryLogHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr journalEntries,
private void nativeQueryLogHandler(UInt32 invokeId, IntPtr parameter, int err, IntPtr journalEntries,
[MarshalAs(UnmanagedType.I1)] bool moreFollows)
{
GCHandle handle = GCHandle.FromIntPtr(parameter);
@ -2940,17 +2933,17 @@ namespace IEC61850
public IedConnectionException(string message)
: base(message)
{
this.errorCode = 0;
errorCode = 0;
}
public int GetErrorCode()
{
return this.errorCode;
return errorCode;
}
public IedClientError GetIedClientError()
{
return (IedClientError)this.errorCode;
return (IedClientError)errorCode;
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,93 @@
/*
* IEC61850ServerAPI.cs
*
* Copyright 2016-2025 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 <http://www.gnu.org/licenses/>.
*
* See COPYING file for the complete license text.
*/
using IEC61850.Server;
using System;
using System.Runtime.InteropServices;
// IEC 61850 API for the libiec61850 .NET wrapper library
namespace IEC61850
{
// IEC 61850 server API.
namespace Model
{
public enum SMVEvent
{
IEC61850_SVCB_EVENT_ENABLE = 1,
IEC61850_SVCB_EVENT_DISABLE = 0,
}
public class SVControlBlock : ModelNode
{
private IntPtr self = IntPtr.Zero;
public IedModel parent { get; }
internal IntPtr Self { get => self; }
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr SVControlBlock_create(string name, IntPtr parent, string svID, string dataSet, UInt32 confRev, uint smpMod,
UInt16 smpRate, uint optFlds, bool isUnicast);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr SVControlBlock_getName(IntPtr self);
/// <summary>
/// create a new Multicast/Unicast Sampled Value (SV) control block (SvCB)
/// Create a new Sampled Value control block(SvCB) and add it to the given logical node(LN)
/// </summary>
/// <param name="name">name of the SvCB relative to the parent LN</param>
/// <param name="parent">the parent LN</param>
/// <param name="svID">the application ID of the SvCB</param>
/// <param name="dataSet">the data set reference to be used by the SVCB</param>
/// <param name="confRev">the configuration revision</param>
/// <param name="smpMod">the sampling mode used</param>
/// <param name="smpRate">the sampling rate used</param>
/// <param name="optFlds"></param>
/// <param name="isUnicast">the optional element configuration</param>
public SVControlBlock(string name, IedModel parent, string svID, string dataSet, UInt32 confRev, uint smpMod,
UInt16 smpRate, uint optFlds, bool isUnicast)
{
self = SVControlBlock_create(name, parent.self, svID, dataSet, confRev, smpMod, smpRate, optFlds, isUnicast);
this.parent = parent;
}
/// <summary>
/// create a new Multicast/Unicast Sampled Value (SV) control block (SvCB)
/// Create a new Sampled Value control block(SvCB) and add it to the given logical node(LN)
/// </summary>
/// <param name="self">the svcontrol instance</param>
public SVControlBlock(IntPtr self)
{
this.self = self;
}
public string Name
{
get
{
return Marshal.PtrToStringAnsi(SVControlBlock_getName(self));
}
}
}
}
}

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
/*
* IedServerConfig.cs
*
* Copyright 2018 Michael Zillgith
* Copyright 2018-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,9 +21,9 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850.Server
{

@ -1,7 +1,7 @@
/*
* IsoConnectionParameters.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -26,38 +26,39 @@ using System.Runtime.InteropServices;
namespace IEC61850
{
namespace Client
{
namespace Client
{
public enum AcseAuthenticationMechanism {
public enum AcseAuthenticationMechanism
{
/** don't use authentication */
ACSE_AUTH_NONE = 0,
ACSE_AUTH_NONE = 0,
/** use password authentication */
ACSE_AUTH_PASSWORD = 1
}
ACSE_AUTH_PASSWORD = 1
}
/// <summary>
/// Connection parameters associated with the ISO protocol layers (transport, session, presentation, ACSE)
/// </summary>
public class IsoConnectionParameters
{
{
[StructLayout(LayoutKind.Sequential)]
private struct NativeTSelector
{
public byte size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=4)] public byte[] value;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 4)] public byte[] value;
}
[StructLayout(LayoutKind.Sequential)]
private struct NativeSSelector
{
public byte size;
[StructLayout(LayoutKind.Sequential)]
private struct NativeSSelector
{
public byte size;
[MarshalAs(UnmanagedType.ByValArray, SizeConst=16)] public byte[] value;
}
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 16)] public byte[] value;
}
[StructLayout(LayoutKind.Sequential)]
private struct NativePSelector
@ -68,49 +69,49 @@ namespace IEC61850
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_destroy(IntPtr self);
private static extern void IsoConnectionParameters_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setRemoteApTitle(IntPtr self, string apTitle, int aeQualifier);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setRemoteApTitle(IntPtr self, string apTitle, int aeQualifier);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setRemoteAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setRemoteAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setLocalApTitle(IntPtr self, string apTitle, int aeQualifier);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setLocalApTitle(IntPtr self, string apTitle, int aeQualifier);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setLocalAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setLocalAddresses(IntPtr self, NativePSelector pSelector, NativeSSelector sSelector, NativeTSelector tSelector);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setAcseAuthenticationParameter(IntPtr self, IntPtr acseAuthParameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void IsoConnectionParameters_setAcseAuthenticationParameter(IntPtr self, IntPtr acseAuthParameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr AcseAuthenticationParameter_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr AcseAuthenticationParameter_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void AcseAuthenticationParameter_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void AcseAuthenticationParameter_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void AcseAuthenticationParameter_setAuthMechanism(IntPtr self, int mechanism);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void AcseAuthenticationParameter_setAuthMechanism(IntPtr self, int mechanism);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void AcseAuthenticationParameter_setPassword(IntPtr self, string password);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void AcseAuthenticationParameter_setPassword(IntPtr self, string password);
private IntPtr self;
private IntPtr self;
private IntPtr authParameter = IntPtr.Zero;
private IntPtr authParameter = IntPtr.Zero;
internal IsoConnectionParameters (IntPtr self)
{
this.self = self;
}
internal IsoConnectionParameters(IntPtr self)
{
this.self = self;
}
~IsoConnectionParameters ()
{
if (authParameter != IntPtr.Zero)
AcseAuthenticationParameter_destroy(authParameter);
}
~IsoConnectionParameters()
{
if (authParameter != IntPtr.Zero)
AcseAuthenticationParameter_destroy(authParameter);
}
/// <summary>
/// Sets the remote ap title related parameters
@ -122,9 +123,9 @@ namespace IEC61850
/// remote AE qualifier.
/// </param>
public void SetRemoteApTitle(string apTitle, int aeQualifier)
{
IsoConnectionParameters_setRemoteApTitle(self, apTitle, aeQualifier);
}
{
IsoConnectionParameters_setRemoteApTitle(self, apTitle, aeQualifier);
}
/// <summary>
/// Sets the remote addresses for ISO layers (transport, session, presentation)
@ -138,27 +139,27 @@ namespace IEC61850
/// <param name='tSelector'>
/// ISO COTP transport layer address
/// </param>
public void SetRemoteAddresses (byte[] pSelector, byte[] sSelector, byte[] tSelector)
{
public void SetRemoteAddresses(byte[] pSelector, byte[] sSelector, byte[] tSelector)
{
if (tSelector.Length > 4)
throw new ArgumentOutOfRangeException("tSelector", "maximum size (4) exceeded");
NativeTSelector nativeTSelector;
nativeTSelector.size = (byte) tSelector.Length;
nativeTSelector.size = (byte)tSelector.Length;
nativeTSelector.value = new byte[4];
for (int i = 0; i < tSelector.Length; i++)
for (int i = 0; i < tSelector.Length; i++)
nativeTSelector.value[i] = tSelector[i];
if (sSelector.Length > 16)
throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded");
if (sSelector.Length > 16)
throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded");
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte) sSelector.Length;
nativeSSelector.value = new byte[16];
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte)sSelector.Length;
nativeSSelector.value = new byte[16];
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value [i] = sSelector [i];
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value[i] = sSelector[i];
if (pSelector.Length > 16)
throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded");
@ -171,7 +172,7 @@ namespace IEC61850
nativePSelector.value[i] = pSelector[i];
IsoConnectionParameters_setRemoteAddresses(self, nativePSelector, nativeSSelector, nativeTSelector);
}
}
/// <summary>
/// Sets the local ap title related parameters
@ -182,10 +183,10 @@ namespace IEC61850
/// <param name='aeQualifier'>
/// local AE qualifier.
/// </param>
public void SetLocalApTitle (string apTitle, int aeQualifier)
{
IsoConnectionParameters_setLocalApTitle(self, apTitle, aeQualifier);
}
public void SetLocalApTitle(string apTitle, int aeQualifier)
{
IsoConnectionParameters_setLocalApTitle(self, apTitle, aeQualifier);
}
/// <summary>
/// Sets the local addresses for ISO layers (transport, session, presentation)
@ -199,27 +200,27 @@ namespace IEC61850
/// <param name='tSelector'>
/// ISO COTP transport layer address
/// </param>
public void SetLocalAddresses (byte[] pSelector, byte[] sSelector, byte[] tSelector)
{
public void SetLocalAddresses(byte[] pSelector, byte[] sSelector, byte[] tSelector)
{
if (tSelector.Length > 4)
throw new ArgumentOutOfRangeException("tSelector", "maximum size (4) exceeded");
NativeTSelector nativeTSelector;
nativeTSelector.size = (byte) tSelector.Length;
nativeTSelector.size = (byte)tSelector.Length;
nativeTSelector.value = new byte[4];
for (int i = 0; i < tSelector.Length; i++)
for (int i = 0; i < tSelector.Length; i++)
nativeTSelector.value[i] = tSelector[i];
if (sSelector.Length > 16)
throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded");
if (sSelector.Length > 16)
throw new ArgumentOutOfRangeException("sSelector", "maximum size (16) exceeded");
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte) sSelector.Length;
nativeSSelector.value = new byte[16];
NativeSSelector nativeSSelector;
nativeSSelector.size = (byte)sSelector.Length;
nativeSSelector.value = new byte[16];
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value [i] = sSelector [i];
for (int i = 0; i < sSelector.Length; i++)
nativeSSelector.value[i] = sSelector[i];
if (pSelector.Length > 16)
throw new ArgumentOutOfRangeException("pSelector", "maximum size (16) exceeded");
@ -232,7 +233,7 @@ namespace IEC61850
nativePSelector.value[i] = pSelector[i];
IsoConnectionParameters_setLocalAddresses(self, nativePSelector, nativeSSelector, nativeTSelector);
}
}
/// <summary>
/// Instruct ACSE layer to use password authentication.
@ -240,19 +241,20 @@ namespace IEC61850
/// <param name='password'>
/// Password that will be used to authenticate the client
/// </param>
public void UsePasswordAuthentication (string password)
{
if (authParameter == IntPtr.Zero) {
authParameter = AcseAuthenticationParameter_create ();
AcseAuthenticationParameter_setAuthMechanism (authParameter, (int)AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD);
AcseAuthenticationParameter_setPassword (authParameter, password);
IsoConnectionParameters_setAcseAuthenticationParameter(self, authParameter);
}
else
throw new IedConnectionException("Authentication parameter already set");
}
}
}
public void UsePasswordAuthentication(string password)
{
if (authParameter == IntPtr.Zero)
{
authParameter = AcseAuthenticationParameter_create();
AcseAuthenticationParameter_setAuthMechanism(authParameter, (int)AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD);
AcseAuthenticationParameter_setPassword(authParameter, password);
IsoConnectionParameters_setAcseAuthenticationParameter(self, authParameter);
}
else
throw new IedConnectionException("Authentication parameter already set");
}
}
}
}

File diff suppressed because it is too large Load Diff

@ -1,7 +1,7 @@
/*
* MmsVariableSpecification.cs
*
* Copyright 2014 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,67 +21,65 @@
* See COPYING file for the complete license text.
*/
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace IEC61850
{
namespace Common
{
namespace Common
{
/// <summary>
/// MMS variable specification. This class is used to represent an MMS variable type definition.
/// </summary>
public class MmsVariableSpecification : IEnumerable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsVariableSpecification_destroy(IntPtr self);
public class MmsVariableSpecification : IEnumerable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void MmsVariableSpecification_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getNamedVariableRecursive(IntPtr variable, string nameId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getNamedVariableRecursive(IntPtr variable, string nameId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsVariableSpecification_getType(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsVariableSpecification_getType(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getName(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getName(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsVariableSpecification_getSize(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsVariableSpecification_getSize(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getChildSpecificationByIndex(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getChildSpecificationByIndex(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getArrayElementSpecification(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr MmsVariableSpecification_getArrayElementSpecification(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsVariableSpecification_getExponentWidth(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int MmsVariableSpecification_getExponentWidth(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern bool MmsVariableSpecification_isValueOfType(IntPtr self, IntPtr value);
internal IntPtr self;
private bool responsableForDeletion;
internal IntPtr self;
private bool responsableForDeletion;
/* only to prevent garbage collector to destroy parent element */
internal MmsVariableSpecification parent = null;
internal MmsVariableSpecification (IntPtr self, MmsVariableSpecification parent)
{
this.self = self;
this.responsableForDeletion = false;
internal MmsVariableSpecification(IntPtr self, MmsVariableSpecification parent)
{
this.self = self;
responsableForDeletion = false;
this.parent = parent;
}
}
internal MmsVariableSpecification (IntPtr self, bool responsableForDeletion)
{
this.self = self;
this.responsableForDeletion = responsableForDeletion;
}
internal MmsVariableSpecification(IntPtr self, bool responsableForDeletion)
{
this.self = self;
this.responsableForDeletion = responsableForDeletion;
}
/// <summary>
/// Get a child variable specification by its name
@ -104,11 +102,11 @@ namespace IEC61850
return null;
}
~MmsVariableSpecification ()
{
if (responsableForDeletion)
MmsVariableSpecification_destroy(self);
}
~MmsVariableSpecification()
{
if (responsableForDeletion)
MmsVariableSpecification_destroy(self);
}
/// <summary>
/// Gets the MmsValue type of the variable
@ -116,10 +114,18 @@ namespace IEC61850
/// <returns>
/// The MmsType of the variable
/// </returns>
public new MmsType GetType ()
{
return (MmsType) MmsVariableSpecification_getType(self);
}
public new MmsType GetType()
{
return (MmsType)MmsVariableSpecification_getType(self);
}
/// <summary>
/// The MmsValue type of the variable
/// </summary>
public MmsType MmsType
{
get { return (MmsType)MmsVariableSpecification_getType(self); }
}
/// <summary>
/// Gets the type of the array elements.
@ -128,15 +134,33 @@ namespace IEC61850
/// The array element type.
/// </returns>
/// <exception cref="MmsValueException">This exception is thrown if the value is not of type MMS_ARRAY</exception>
public MmsVariableSpecification getArrayElementType ()
{
if (GetType() == MmsType.MMS_ARRAY) {
IntPtr varSpecPtr = MmsVariableSpecification.MmsVariableSpecification_getArrayElementSpecification(self);
return new MmsVariableSpecification(varSpecPtr, this);
}
else
throw new MmsValueException ("specification is of wrong type");
}
public MmsVariableSpecification getArrayElementType()
{
if (GetType() == MmsType.MMS_ARRAY)
{
IntPtr varSpecPtr = MmsVariableSpecification.MmsVariableSpecification_getArrayElementSpecification(self);
return new MmsVariableSpecification(varSpecPtr, this);
}
else
throw new MmsValueException("specification is of wrong type");
}
/// <summary>
/// The type of array elements (when the variable is of type MMS_ARRAY)
/// </summary>
public MmsVariableSpecification ArrayElementType
{
get
{
if (GetType() == MmsType.MMS_ARRAY)
{
IntPtr varSpecPtr = MmsVariableSpecification.MmsVariableSpecification_getArrayElementSpecification(self);
return new MmsVariableSpecification(varSpecPtr, this);
}
else
return null;
}
}
/// <summary>
/// Gets the element specification of a structure element
@ -147,41 +171,86 @@ namespace IEC61850
/// <param name='index'>
/// Index.
/// </param>
public MmsVariableSpecification GetElement (int index)
{
if (GetType () == MmsType.MMS_STRUCTURE) {
if ((index >= 0) && (index < Size ())) {
IntPtr varSpecPtr = MmsVariableSpecification_getChildSpecificationByIndex(self, index);
return new MmsVariableSpecification(varSpecPtr, this);
}
else
throw new MmsValueException ("Index out of bounds");
}
else
throw new MmsValueException ("specification is of wrong type");
}
public MmsVariableSpecification GetElement(int index)
{
if (GetType() == MmsType.MMS_STRUCTURE)
{
if ((index >= 0) && (index < Size()))
{
IntPtr varSpecPtr = MmsVariableSpecification_getChildSpecificationByIndex(self, index);
return new MmsVariableSpecification(varSpecPtr, this);
}
else
throw new MmsValueException("Index out of bounds");
}
else
throw new MmsValueException("specification is of wrong type");
}
/// <summary>
/// The element types for complex variables (MMS_STRUCTURE)
/// </summary>
public MmsVariableSpecification[] Elements
{
get
{
if (GetType() != MmsType.MMS_STRUCTURE)
return null;
List<MmsVariableSpecification> elements = new List<MmsVariableSpecification>();
for (int i = 0; i < Size(); i++)
{
elements.Add(GetElement(i));
}
return elements.ToArray();
}
}
/// <summary>
/// Gets the name of the variable
/// Gets the name of the variable (relative to the parent)
/// </summary>
/// <returns>
/// The name.
/// </returns>
public string GetName ()
{
IntPtr namePtr = MmsVariableSpecification_getName(self);
public string GetName()
{
IntPtr namePtr = MmsVariableSpecification_getName(self);
return Marshal.PtrToStringAnsi (namePtr);
}
return Marshal.PtrToStringAnsi(namePtr);
}
/// <summary>
/// The name of the variable (relative to the parent)
/// </summary>
public string Name
{
get
{
return GetName();
}
}
/// <summary>
/// Get the "size" of the variable (array size, number of structure elements ...)
/// </summary>
public int Size ()
{
return MmsVariableSpecification_getSize(self);
}
public int Size()
{
return MmsVariableSpecification_getSize(self);
}
/// <summary>
/// The "size" of the variable (array size, number of structure elements ...)
/// </summary>
public int size
{
get
{
return MmsVariableSpecification_getSize(self);
}
}
/// <summary>
/// Determines whether the given value object matches this type
@ -193,45 +262,46 @@ namespace IEC61850
return MmsVariableSpecification_isValueOfType(self, value.valueReference);
}
IEnumerator IEnumerable.GetEnumerator ()
{
return new MmsVariableSpecificationEnumerator (this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new MmsVariableSpecificationEnumerator(this);
}
private class MmsVariableSpecificationEnumerator : IEnumerator
{
private MmsVariableSpecification value;
private int index = -1;
private class MmsVariableSpecificationEnumerator : IEnumerator
{
private MmsVariableSpecification value;
private int index = -1;
public MmsVariableSpecificationEnumerator (MmsVariableSpecification value)
{
this.value = value;
}
public MmsVariableSpecificationEnumerator(MmsVariableSpecification value)
{
this.value = value;
}
#region IEnumerator Members
public void Reset ()
{
index = -1;
}
#region IEnumerator Members
public void Reset()
{
index = -1;
}
public object Current {
public object Current
{
get { return value.GetElement (index);}
}
get { return value.GetElement(index); }
}
public bool MoveNext ()
{
index++;
public bool MoveNext()
{
index++;
if (index >= value.Size ())
return false;
else
return true;
}
if (index >= value.Size())
return false;
else
return true;
}
#endregion
}
#endregion
}
}
}
}
}
}

@ -1,7 +1,7 @@
/*
* ReportControlBlock.cs
*
* Copyright 2014-2018 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,26 +20,24 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using IEC61850.Common;
namespace IEC61850
{
namespace Client
{
namespace Client
{
/// <summary>
/// Report handler.
/// </summary>
/// <param name="report">represents the received report. DON'T use this object
/// outside the scope of the report handler!</param>
public delegate void ReportHandler (Report report, object parameter);
public delegate void ReportHandler(Report report, object parameter);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void InternalReportHandler (IntPtr parameter, IntPtr report);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
internal delegate void InternalReportHandler(IntPtr parameter, IntPtr report);
/// <summary>
/// Report control block (RCB) representation.
@ -50,214 +48,219 @@ namespace IEC61850
/// Values at the server are only affected when the SetRCBValues method is called.
/// </description>
public class ReportControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_create (string dataAttributeReference);
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_create(string dataAttributeReference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_destroy (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_isBuffered (IntPtr self);
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 IntPtr ClientReportControlBlock_getRptId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setRptId (IntPtr self, string rptId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setRptId(IntPtr self, string rptId);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getRptEna (IntPtr self);
static extern bool ClientReportControlBlock_getRptEna(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setRptEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setRptEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool rptEna);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getResv (IntPtr self);
static extern bool ClientReportControlBlock_getResv(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setResv (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool resv);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setResv(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool resv);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getDataSetReference (IntPtr self);
[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 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 UInt32 ClientReportControlBlock_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientReportControlBlock_getOptFlds (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 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 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 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 UInt16 ClientReportControlBlock_getSqNum(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientReportControlBlock_getTrgOps (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 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 UInt32 ClientReportControlBlock_getIntgPd(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setIntgPd (IntPtr self, UInt32 intgPd);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setIntgPd(IntPtr self, UInt32 intgPd);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getGI (IntPtr self);
static extern bool ClientReportControlBlock_getGI(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setGI (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool gi);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setGI(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool gi);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_getPurgeBuf (IntPtr self);
static extern bool ClientReportControlBlock_getPurgeBuf(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setPurgeBuf (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool purgeBuf);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientReportControlBlock_setPurgeBuf(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool purgeBuf);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientReportControlBlock_hasResvTms(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern Int16 ClientReportControlBlock_getResvTms (IntPtr self);
static extern Int16 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 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 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 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 UInt64 ClientReportControlBlock_getEntryTime(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getOwner (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientReportControlBlock_getOwner(IntPtr self);
internal IntPtr self;
internal IntPtr self;
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 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);
if (self != IntPtr.Zero) {
this.iedConnection = iedConnection;
this.objectReference = objectReference;
}
}
/// <summary>
/// Releases all resource used by the <see cref="IEC61850.Client.ReportControlBlock"/> object.
/// </summary>
/// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="IEC61850.Client.ReportControlBlock"/>. The
/// <see cref="Dispose"/> method leaves the <see cref="IEC61850.Client.ReportControlBlock"/> in an unusable state.
/// After calling <see cref="Dispose"/>, you must release all references to the
/// <see cref="IEC61850.Client.ReportControlBlock"/> so the garbage collector can reclaim the memory that the
/// <see cref="IEC61850.Client.ReportControlBlock"/> was occupying.</remarks>
public void Dispose()
{
lock (this) {
if (self != IntPtr.Zero) {
iedConnection.UninstallReportHandler (objectReference);
iedConnection.RemoveRCB (this);
ClientReportControlBlock_destroy (self);
self = IntPtr.Zero;
}
}
}
~ReportControlBlock()
{
Dispose ();
}
public string GetObjectReference ()
{
return this.objectReference;
}
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);
if (self != IntPtr.Zero)
{
this.iedConnection = iedConnection;
this.objectReference = objectReference;
}
}
/// <summary>
/// Releases all resource used by the <see cref="IEC61850.Client.ReportControlBlock"/> object.
/// </summary>
/// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="IEC61850.Client.ReportControlBlock"/>. The
/// <see cref="Dispose"/> method leaves the <see cref="IEC61850.Client.ReportControlBlock"/> in an unusable state.
/// After calling <see cref="Dispose"/>, you must release all references to the
/// <see cref="IEC61850.Client.ReportControlBlock"/> so the garbage collector can reclaim the memory that the
/// <see cref="IEC61850.Client.ReportControlBlock"/> was occupying.</remarks>
public void Dispose()
{
lock (this)
{
if (self != IntPtr.Zero)
{
iedConnection.UninstallReportHandler(objectReference);
iedConnection.RemoveRCB(this);
ClientReportControlBlock_destroy(self);
self = IntPtr.Zero;
}
}
}
~ReportControlBlock()
{
Dispose();
}
public string GetObjectReference()
{
return objectReference;
}
/// <summary>
/// Installs the report handler.
/// </summary>
@ -272,40 +275,41 @@ namespace IEC61850
/// <param name='parameter'>
/// parameter is passed to the handler when the handler is invoked.
/// </param>
public void InstallReportHandler (ReportHandler reportHandler, object parameter)
{
this.reportHandler = new ReportHandler(reportHandler);
public void InstallReportHandler(ReportHandler reportHandler, object parameter)
{
this.reportHandler = new ReportHandler(reportHandler);
this.reportHandlerParameter = parameter;
reportHandlerParameter = parameter;
if (reportHandlerInstalled == false) {
if (reportHandlerInstalled == false)
{
string reportId = this.GetRptId ();
string reportId = GetRptId();
if (internalHandler == null)
{
internalHandler = new InternalReportHandler(internalReportHandler);
internalHandler = new InternalReportHandler(internalReportHandler);
}
iedConnection.InstallReportHandler (objectReference, reportId, internalHandler);
reportHandlerInstalled = true;
}
}
iedConnection.InstallReportHandler(objectReference, reportId, internalHandler);
reportHandlerInstalled = true;
}
}
/// <summary>
/// Read all RCB values from the server
/// </summary>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public void GetRCBValues ()
{
int error;
public void GetRCBValues()
{
int error;
iedConnection.GetRCBValues (out error, objectReference, self);
iedConnection.GetRCBValues(out error, objectReference, self);
if (error != 0)
throw new IedConnectionException ("getRCBValues service failed", error);
}
if (error != 0)
throw new IedConnectionException("getRCBValues service failed", error);
}
/// <summary>
/// Read all RCB values from the server - asynchronous version
@ -327,10 +331,10 @@ namespace IEC61850
/// The RCB values are sent by a single MMS write request.
/// </description>
/// <exception cref="IedConnectionException">This exception is thrown if there is a connection or service error</exception>
public void SetRCBValues ()
{
SetRCBValues (true);
}
public void SetRCBValues()
{
SetRCBValues(true);
}
private UInt32 CreateParametersMask()
{
@ -382,12 +386,12 @@ namespace IEC61850
}
public UInt32 SetRCBValuesAsync(SetRCBValuesHandler handler, object parameter)
{
{
return SetRCBValuesAsync(true, handler, parameter);
}
public UInt32 SetRCBValuesAsync(bool singleRequest, SetRCBValuesHandler handler, object parameter)
{
{
UInt32 parametersMask = CreateParametersMask();
return iedConnection.SetRCBValuesAsync(this, parametersMask, singleRequest, handler, parameter);
@ -403,7 +407,7 @@ namespace IEC61850
/// <param name='singleRequest'>
/// If true the values are sent by single MMS write request. Otherwise the values are all sent by their own MMS write requests.
/// </param>
public void SetRCBValues (bool singleRequest)
public void SetRCBValues(bool singleRequest)
{
UInt32 parametersMask = CreateParametersMask();
@ -411,21 +415,23 @@ namespace IEC61850
int error;
iedConnection.SetRCBValues (out error, self, parametersMask, singleRequest);
resetSendFlags();
iedConnection.SetRCBValues(out error, self, parametersMask, singleRequest);
resetSendFlags();
if (error != 0)
throw new IedConnectionException ("setRCBValues service failed", error);
throw new IedConnectionException("setRCBValues service failed", error);
if (flagRptId) {
if (flagRptId)
{
if (reportHandlerInstalled) {
if (reportHandlerInstalled)
{
reportHandlerInstalled = false;
InstallReportHandler(this.reportHandler, this.reportHandlerParameter);
InstallReportHandler(reportHandler, reportHandlerParameter);
}
}
}
}
/// <summary>
/// Determines whether this instance is a buffered or unbuffered RCB.
@ -433,10 +439,10 @@ namespace IEC61850
/// <returns>
/// <c>true</c> if this instance is a buffered RCB; otherwise, <c>false</c>.
/// </returns>
public bool IsBuffered ()
{
return ClientReportControlBlock_isBuffered (self);
}
public bool IsBuffered()
{
return ClientReportControlBlock_isBuffered(self);
}
/// <summary>
/// Gets the entry time of the RCB as ms time
@ -447,10 +453,10 @@ namespace IEC61850
/// <returns>
/// The entry time as ms timestamp
/// </returns>
public UInt64 GetEntryTime ()
{
return ClientReportControlBlock_getEntryTime (self);
}
public UInt64 GetEntryTime()
{
return ClientReportControlBlock_getEntryTime(self);
}
/// <summary>
/// Gets the entry time of the RCB as DateTimeOffset
@ -461,49 +467,50 @@ namespace IEC61850
/// <returns>
/// The entry time as DataTimeOffset
/// </returns>
public DateTimeOffset GetEntryTimeAsDateTimeOffset ()
{
UInt64 entryTime = GetEntryTime ();
public DateTimeOffset GetEntryTimeAsDateTimeOffset()
{
UInt64 entryTime = GetEntryTime();
DateTimeOffset retVal = new DateTimeOffset (1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
DateTimeOffset retVal = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
return retVal.AddMilliseconds (entryTime);
}
return retVal.AddMilliseconds(entryTime);
}
/// <summary>
/// Gets the entryID of RCB
/// </summary>
/// Returns the EntryID of the last received GetRCBValues service response.
/// The EntryID is only present in buffered RCBs (BRCBs).
///
/// <returns>The entry ID</returns>
public byte[] GetEntryID()
{
IntPtr entryIdRef = ClientReportControlBlock_getEntryId (self);
/// <summary>
/// Gets the entryID of RCB
/// </summary>
/// Returns the EntryID of the last received GetRCBValues service response.
/// The EntryID is only present in buffered RCBs (BRCBs).
///
/// <returns>The entry ID</returns>
public byte[] GetEntryID()
{
IntPtr entryIdRef = ClientReportControlBlock_getEntryId(self);
if (entryIdRef == IntPtr.Zero)
return null;
else {
MmsValue entryId = new MmsValue (entryIdRef);
if (entryIdRef == IntPtr.Zero)
return null;
else
{
MmsValue entryId = new MmsValue(entryIdRef);
return entryId.getOctetString ();
}
}
return entryId.getOctetString();
}
}
public void SetEntryID(byte[] entryId)
{
flagEntryId = true;
public void SetEntryID(byte[] entryId)
{
flagEntryId = true;
MmsValue entryID = MmsValue.NewOctetString (entryId.Length);
MmsValue entryID = MmsValue.NewOctetString(entryId.Length);
entryID.setOctetString (entryId);
entryID.setOctetString(entryId);
ClientReportControlBlock_setEntryId (self, entryID.valueReference);
ClientReportControlBlock_setEntryId(self, entryID.valueReference);
}
}
/// <summary>
@ -512,12 +519,12 @@ namespace IEC61850
/// <returns>
/// The data set reference.
/// </returns>
public string GetDataSetReference ()
{
IntPtr dataSetRefPtr = ClientReportControlBlock_getDataSetReference (self);
public string GetDataSetReference()
{
IntPtr dataSetRefPtr = ClientReportControlBlock_getDataSetReference(self);
return Marshal.PtrToStringAnsi (dataSetRefPtr);
}
return Marshal.PtrToStringAnsi(dataSetRefPtr);
}
/// <summary>
/// Sets the data set reference. Use this method to select the associated data set for the RCB
@ -525,12 +532,12 @@ namespace IEC61850
/// <returns>
/// The data set reference.
/// </returns>
public void SetDataSetReference (string dataSetReference)
{
ClientReportControlBlock_setDataSetReference (self, dataSetReference);
public void SetDataSetReference(string dataSetReference)
{
ClientReportControlBlock_setDataSetReference(self, dataSetReference);
flagDataSetReference = true;
}
flagDataSetReference = true;
}
/// <summary>
/// Gets the report identifier.
@ -538,12 +545,12 @@ namespace IEC61850
/// <returns>
/// The report identifier.
/// </returns>
public string GetRptId ()
{
IntPtr rptIdPtr = ClientReportControlBlock_getRptId (self);
public string GetRptId()
{
IntPtr rptIdPtr = ClientReportControlBlock_getRptId(self);
return Marshal.PtrToStringAnsi (rptIdPtr);
}
return Marshal.PtrToStringAnsi(rptIdPtr);
}
/// <summary>
/// Sets the RptId (report ID) of the RCB
@ -551,7 +558,7 @@ namespace IEC61850
/// <param name='rptId'>
/// The new RptId
/// </param>
public void SetRptId (string rptId)
public void SetRptId(string rptId)
{
ClientReportControlBlock_setRptId(self, rptId);
flagRptId = true;
@ -563,10 +570,10 @@ namespace IEC61850
/// <returns>
/// true, if reporting is enabled, false otherwise
/// </returns>
public bool GetRptEna ()
{
return ClientReportControlBlock_getRptEna (self);
}
public bool GetRptEna()
{
return ClientReportControlBlock_getRptEna(self);
}
/// <summary>
/// Sets report enable flag. Use this to enable reporting
@ -574,17 +581,17 @@ namespace IEC61850
/// <param name='rptEna'>
/// true to enable reporting, false to disable
/// </param>
public void SetRptEna (bool rptEna)
{
ClientReportControlBlock_setRptEna (self, rptEna);
flagRptEna = true;
}
public void SetRptEna(bool rptEna)
{
ClientReportControlBlock_setRptEna(self, rptEna);
flagRptEna = true;
}
/// <summary>
/// Get the purgeBuf flag of the report control block
/// </summary>
/// <returns>the prugeBuf value</returns>
public bool GetPurgeBuf ()
public bool GetPurgeBuf()
{
return ClientReportControlBlock_getPurgeBuf(self);
}
@ -594,7 +601,7 @@ namespace IEC61850
/// </summary>
/// <description>This is only for buffered RCBs. If set to true the report buffer of a buffered RCB will be cleaned.</description>
/// <param name="purgeBuf">set to true to flush report buffer</param>
public void SetPurgeBuf (bool purgeBuf)
public void SetPurgeBuf(bool purgeBuf)
{
ClientReportControlBlock_setPurgeBuf(self, purgeBuf);
flagPurgeBuf = true;
@ -606,10 +613,10 @@ namespace IEC61850
/// <returns>
/// The buffer time in ms.
/// </returns>
public UInt32 GetBufTm()
{
return ClientReportControlBlock_getBufTm (self);
}
public UInt32 GetBufTm()
{
return ClientReportControlBlock_getBufTm(self);
}
/// <summary>
/// Sets the buffer time.
@ -617,12 +624,12 @@ namespace IEC61850
/// <param name='bufTm'>
/// Buffer time is ms.
/// </param>
public void SetBufTm (UInt32 bufTm)
{
ClientReportControlBlock_setBufTm (self, bufTm);
public void SetBufTm(UInt32 bufTm)
{
ClientReportControlBlock_setBufTm(self, bufTm);
flagBufTm = true;
}
flagBufTm = true;
}
/// <summary>
/// Gets the GI flag
@ -630,10 +637,10 @@ namespace IEC61850
/// <returns>
/// true, if GI flag is set
/// </returns>
public bool GetGI ()
{
return ClientReportControlBlock_getGI (self);
}
public bool GetGI()
{
return ClientReportControlBlock_getGI(self);
}
/// <summary>
/// Sets the GI flag. Use this to trigger a GI (general interrogation) command.
@ -641,11 +648,11 @@ namespace IEC61850
/// <param name='GI'>
/// request general interrogation of true
/// </param>
public void SetGI (bool GI)
{
ClientReportControlBlock_setGI (self, GI);
flagGI = true;
}
public void SetGI(bool GI)
{
ClientReportControlBlock_setGI(self, GI);
flagGI = true;
}
/// <summary>
/// Check if RCB is reserved by a client
@ -653,10 +660,10 @@ namespace IEC61850
/// <returns>
/// true, the RCB is reserver by a client
/// </returns>
public bool GetResv ()
{
return ClientReportControlBlock_getResv (self);
}
public bool GetResv()
{
return ClientReportControlBlock_getResv(self);
}
/// <summary>
/// Gets the configuration revision of the RCB
@ -664,9 +671,9 @@ namespace IEC61850
/// <returns>
/// The conf rev.
/// </returns>
public UInt32 GetConfRev ()
public UInt32 GetConfRev()
{
return ClientReportControlBlock_getConfRev (self);
return ClientReportControlBlock_getConfRev(self);
}
/// <summary>
@ -675,11 +682,11 @@ namespace IEC61850
/// <param name='resv'>
/// true: reserver this RCB for exclusive use
/// </param>
public void SetResv (bool resv)
{
ClientReportControlBlock_setResv (self, resv);
flagResv = true;
}
public void SetResv(bool resv)
{
ClientReportControlBlock_setResv(self, resv);
flagResv = true;
}
/// <summary>
/// Gets the trigger options of the RCB
@ -688,9 +695,9 @@ namespace IEC61850
/// trigger options
/// </returns>
public TriggerOptions GetTrgOps()
{
return (TriggerOptions) ClientReportControlBlock_getTrgOps (self);
}
{
return (TriggerOptions)ClientReportControlBlock_getTrgOps(self);
}
/// <summary>
/// Sets the trigger options of the RCB.
@ -699,11 +706,11 @@ namespace IEC61850
/// trigger options
/// </param>
public void SetTrgOps(TriggerOptions trgOps)
{
ClientReportControlBlock_setTrgOps (self, (int) trgOps);
{
ClientReportControlBlock_setTrgOps(self, (int)trgOps);
flagTrgOps = true;
}
flagTrgOps = true;
}
/// <summary>
/// Gets the integrity period
@ -711,10 +718,10 @@ namespace IEC61850
/// <returns>
/// integrity period in ms
/// </returns>
public UInt32 GetIntgPd ()
{
return ClientReportControlBlock_getIntgPd (self);
}
public UInt32 GetIntgPd()
{
return ClientReportControlBlock_getIntgPd(self);
}
/// <summary>
/// Sets the integrity period
@ -722,11 +729,11 @@ namespace IEC61850
/// <param name='intgPd'>
/// integrity period in ms
/// </param>
public void SetIntgPd (UInt32 intgPd)
{
ClientReportControlBlock_setIntgPd (self, intgPd);
flagIntgPd = true;
}
public void SetIntgPd(UInt32 intgPd)
{
ClientReportControlBlock_setIntgPd(self, intgPd);
flagIntgPd = true;
}
/// <summary>
/// Gets the option fields.
@ -735,9 +742,9 @@ namespace IEC61850
/// The option fields
/// </returns>
public ReportOptions GetOptFlds()
{
return (ReportOptions) ClientReportControlBlock_getOptFlds (self);
}
{
return (ReportOptions)ClientReportControlBlock_getOptFlds(self);
}
/// <summary>
/// Sets the option field. Used to enable or disable optional report elements
@ -746,11 +753,11 @@ namespace IEC61850
/// Option field.
/// </param>
public void SetOptFlds(ReportOptions optFlds)
{
ClientReportControlBlock_setOptFlds (self, (int)optFlds);
{
ClientReportControlBlock_setOptFlds(self, (int)optFlds);
flagOptFlds = true;
}
flagOptFlds = true;
}
/// <summary>
/// Check if the report control block has the "ResvTms" attribute.
@ -805,7 +812,7 @@ namespace IEC61850
else
return null;
}
}
}
}
}
}

@ -1,7 +1,7 @@
/*
* Reporting.cs
*
* Copyright 2014-2018 Michael Zillgith
* Copyright 2014-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,11 +20,10 @@
*
* See COPYING file for the complete license text.
*/
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
namespace IEC61850
{

@ -1,7 +1,7 @@
/*
* SampledValuesControlBlock.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -20,184 +20,184 @@
*
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
using IEC61850.Common;
namespace IEC61850
{
namespace Client
{
/// <summary>
/// Sampled values control bloc (SvCB) representation.
/// </summary>
/// <description>
/// This class is used as a client side representation (copy) of a sampled values control block (SvCB).
/// </description>
public class SampledValuesControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_create (IntPtr iedConnection, string reference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientSVControlBlock_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getLastComError (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_isMulticast (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_setSvEna (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
namespace Client
{
/// <summary>
/// Sampled values control bloc (SvCB) representation.
/// </summary>
/// <description>
/// This class is used as a client side representation (copy) of a sampled values control block (SvCB).
/// </description>
public class SampledValuesControlBlock : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_create(IntPtr iedConnection, string reference);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void ClientSVControlBlock_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getLastComError(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_setResv (IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_isMulticast(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_getSvEna (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_setSvEna(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_getResv (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_setResv(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_getMsvID (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_getDatSet (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientSVControlBlock_getConfRev (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientSVControlBlock_getSmpRate (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getOptFlds (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte ClientSVControlBlock_getSmpMod(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getNoASDU (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern PhyComAddress ClientSVControlBlock_getDstAddress (IntPtr self);
private IntPtr self;
private string objectReference;
private bool isDisposed = false;
internal SampledValuesControlBlock(IntPtr iedConnection, string objectReference)
{
self = ClientSVControlBlock_create (iedConnection, objectReference);
this.objectReference = objectReference;
}
public string GetObjectReference ()
{
return this.objectReference;
}
public IedClientError GetLastComError()
{
return (IedClientError)ClientSVControlBlock_getLastComError (self);
}
public bool IsMulticast()
{
return ClientSVControlBlock_isMulticast (self);
}
public bool GetResv()
{
return ClientSVControlBlock_getResv (self);
}
public bool SetResv(bool value)
{
return ClientSVControlBlock_setResv (self, value);
}
public bool GetSvEna()
{
return ClientSVControlBlock_getSvEna (self);
}
public bool SetSvEna(bool value)
{
return ClientSVControlBlock_setSvEna (self, value);
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_getSvEna(IntPtr self);
public string GetMsvID ()
{
IntPtr msvIdPtr = ClientSVControlBlock_getMsvID (self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool ClientSVControlBlock_getResv(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_getMsvID(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr ClientSVControlBlock_getDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt32 ClientSVControlBlock_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern UInt16 ClientSVControlBlock_getSmpRate(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getOptFlds(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern byte ClientSVControlBlock_getSmpMod(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern int ClientSVControlBlock_getNoASDU(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern PhyComAddress ClientSVControlBlock_getDstAddress(IntPtr self);
private IntPtr self;
private string objectReference;
private bool isDisposed = false;
public IntPtr Self { get => self; }
internal SampledValuesControlBlock(IntPtr iedConnection, string objectReference)
{
self = ClientSVControlBlock_create(iedConnection, objectReference);
this.objectReference = objectReference;
}
public string GetObjectReference()
{
return objectReference;
}
public IedClientError GetLastComError()
{
return (IedClientError)ClientSVControlBlock_getLastComError(self);
}
public bool IsMulticast()
{
return ClientSVControlBlock_isMulticast(self);
}
public bool GetResv()
{
return ClientSVControlBlock_getResv(self);
}
public bool SetResv(bool value)
{
return ClientSVControlBlock_setResv(self, value);
}
public bool GetSvEna()
{
return ClientSVControlBlock_getSvEna(self);
}
public bool SetSvEna(bool value)
{
return ClientSVControlBlock_setSvEna(self, value);
}
return Marshal.PtrToStringAnsi (msvIdPtr);
}
public string GetMsvID()
{
IntPtr msvIdPtr = ClientSVControlBlock_getMsvID(self);
public string GetDatSet ()
{
IntPtr datSetPtr = ClientSVControlBlock_getDatSet (self);
return Marshal.PtrToStringAnsi(msvIdPtr);
}
return Marshal.PtrToStringAnsi (datSetPtr);
}
public string GetDatSet()
{
IntPtr datSetPtr = ClientSVControlBlock_getDatSet(self);
public UInt32 GetConfRev ()
{
return ClientSVControlBlock_getConfRev (self);
}
return Marshal.PtrToStringAnsi(datSetPtr);
}
public UInt16 GetSmpRate ()
{
return ClientSVControlBlock_getSmpRate (self);
}
public UInt32 GetConfRev()
{
return ClientSVControlBlock_getConfRev(self);
}
public SVOptions GetOptFlds ()
{
return (SVOptions)ClientSVControlBlock_getOptFlds (self);
}
public UInt16 GetSmpRate()
{
return ClientSVControlBlock_getSmpRate(self);
}
public SmpMod GetSmpMod ()
{
return (SmpMod)ClientSVControlBlock_getSmpMod (self);
}
public SVOptions GetOptFlds()
{
return (SVOptions)ClientSVControlBlock_getOptFlds(self);
}
public int GetNoASDU ()
{
return ClientSVControlBlock_getNoASDU (self);
}
public PhyComAddress GetDstAddress()
{
return ClientSVControlBlock_getDstAddress (self);
}
public SmpMod GetSmpMod()
{
return (SmpMod)ClientSVControlBlock_getSmpMod(self);
}
public void Dispose()
{
if (isDisposed == false) {
isDisposed = true;
ClientSVControlBlock_destroy (self);
self = IntPtr.Zero;
}
}
~SampledValuesControlBlock()
{
Dispose ();
}
}
}
public int GetNoASDU()
{
return ClientSVControlBlock_getNoASDU(self);
}
public PhyComAddress GetDstAddress()
{
return ClientSVControlBlock_getDstAddress(self);
}
public void Dispose()
{
if (isDisposed == false)
{
isDisposed = true;
ClientSVControlBlock_destroy(self);
self = IntPtr.Zero;
}
}
~SampledValuesControlBlock()
{
Dispose();
}
}
}
}

@ -1,7 +1,7 @@
/*
* SampledValuedSubscriber.cs
*
* Copyright 2017 Michael Zillgith
* Copyright 2017-2025 Michael Zillgith
*
* This file is part of libIEC61850.
*
@ -21,454 +21,463 @@
* See COPYING file for the complete license text.
*/
using IEC61850.Common;
using System;
using System.Runtime.InteropServices;
using IEC61850.Common;
namespace IEC61850
{
namespace SV
{
namespace Subscriber
{
/// <summary>
/// SV receiver.
/// </summary>
/// A receiver is responsible for processing all SV message for a single Ethernet interface.
/// In order to process messages from multiple Ethernet interfaces you have to create multiple
/// instances.
public class SVReceiver : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVReceiver_create ();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_disableDestAddrCheck(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_enableDestAddrCheck(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_addSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_removeSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_start(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_stop(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVReceiver_isRunning (IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_setInterfaceId(IntPtr self, string interfaceId);
private IntPtr self;
private bool isDisposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="IEC61850.SV.Subscriber.SVReceiver"/> class.
/// </summary>
public SVReceiver()
{
self = SVReceiver_create ();
}
public void SetInterfaceId(string interfaceId)
{
SVReceiver_setInterfaceId (self, interfaceId);
}
public void DisableDestAddrCheck()
{
SVReceiver_disableDestAddrCheck (self);
}
public void EnableDestAddrCheck()
{
SVReceiver_enableDestAddrCheck (self);
}
/// <summary>
/// Add a subscriber to handle
/// </summary>
/// <param name="subscriber">Subscriber.</param>
public void AddSubscriber(SVSubscriber subscriber)
{
SVReceiver_addSubscriber (self, subscriber.self);
}
public void RemoveSubscriber(SVSubscriber subscriber)
{
SVReceiver_removeSubscriber (self, subscriber.self);
}
/// <summary>
/// Start handling SV messages
/// </summary>
public void Start()
{
SVReceiver_start (self);
}
/// <summary>
/// Stop handling SV messges
/// </summary>
public void Stop()
{
SVReceiver_stop (self);
}
public bool IsRunning()
{
return SVReceiver_isRunning (self);
}
/// <summary>
/// Releases all resource used by the <see cref="IEC61850.SV.Subscriber.SVReceiver"/> object.
/// </summary>
/// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="IEC61850.SV.Subscriber.SVReceiver"/>. The
/// <see cref="Dispose"/> method leaves the <see cref="IEC61850.SV.Subscriber.SVReceiver"/> in an unusable state.
/// After calling <see cref="Dispose"/>, you must release all references to the
/// <see cref="IEC61850.SV.Subscriber.SVReceiver"/> so the garbage collector can reclaim the memory that the
/// <see cref="IEC61850.SV.Subscriber.SVReceiver"/> was occupying.</remarks>
public void Dispose()
{
if (isDisposed == false) {
isDisposed = true;
SVReceiver_destroy (self);
self = IntPtr.Zero;
}
}
~SVReceiver()
{
Dispose ();
}
}
/// <summary>
/// SV listener.
/// </summary>
public delegate void SVUpdateListener (SVSubscriber report, object parameter, SVSubscriberASDU asdu);
/// <summary>
/// Sampled Values (SV) Subscriber
///
/// A subscriber is an instance associated with a single stream of measurement data. It is identified
/// by the Ethernet destination address, the appID value (both are on SV message level) and the svID value
/// that is part of each ASDU.
/// </summary>
public class SVSubscriber : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalSVUpdateListener (IntPtr subscriber, IntPtr parameter, IntPtr asdu);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_create([Out] byte[] ethAddr, UInt16 appID);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_create(IntPtr ethAddr, UInt16 appID);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVSubscriber_setListener(IntPtr self, InternalSVUpdateListener listener, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVSubscriber_destroy(IntPtr self);
internal IntPtr self;
private bool isDisposed = false;
private SVUpdateListener listener;
private object listenerParameter = null;
private event InternalSVUpdateListener internalListener = null;
private void internalSVUpdateListener (IntPtr subscriber, IntPtr parameter, IntPtr asdu)
{
try {
if (listener != null) {
listener(this, listenerParameter, new SVSubscriberASDU(asdu));
}
}
catch (Exception e) {
// older versions of mono 2.10 (for linux?) cause this exception
Console.WriteLine(e.Message);
}
}
public SVSubscriber(byte[] ethAddr, UInt16 appID)
{
if (ethAddr == null) {
self = SVSubscriber_create (IntPtr.Zero, appID);
} else {
if (ethAddr.Length != 6)
throw new ArgumentException ("ethAddr argument has to be of 6 byte size");
self = SVSubscriber_create (ethAddr, appID);
}
}
public void SetListener(SVUpdateListener listener, object parameter)
{
this.listener = listener;
this.listenerParameter = parameter;
if (internalListener == null) {
internalListener = new InternalSVUpdateListener (internalSVUpdateListener);
SVSubscriber_setListener (self, internalListener, IntPtr.Zero);
}
}
public void Dispose()
{
if (isDisposed == false) {
isDisposed = true;
SVSubscriber_destroy (self);
self = IntPtr.Zero;
}
}
}
public class SVSubscriberASDU
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getSmpCnt(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_ASDU_getSvId(IntPtr self);
namespace SV
{
namespace Subscriber
{
/// <summary>
/// SV receiver.
/// </summary>
/// A receiver is responsible for processing all SV message for a single Ethernet interface.
/// In order to process messages from multiple Ethernet interfaces you have to create multiple
/// instances.
public class SVReceiver : IDisposable
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVReceiver_create();
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_disableDestAddrCheck(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_enableDestAddrCheck(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_addSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_removeSubscriber(IntPtr self, IntPtr subscriber);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_start(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_stop(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVReceiver_isRunning(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_destroy(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVReceiver_setInterfaceId(IntPtr self, string interfaceId);
private IntPtr self;
private bool isDisposed = false;
/// <summary>
/// Initializes a new instance of the <see cref="IEC61850.SV.Subscriber.SVReceiver"/> class.
/// </summary>
public SVReceiver()
{
self = SVReceiver_create();
}
public void SetInterfaceId(string interfaceId)
{
SVReceiver_setInterfaceId(self, interfaceId);
}
public void DisableDestAddrCheck()
{
SVReceiver_disableDestAddrCheck(self);
}
public void EnableDestAddrCheck()
{
SVReceiver_enableDestAddrCheck(self);
}
/// <summary>
/// Add a subscriber to handle
/// </summary>
/// <param name="subscriber">Subscriber.</param>
public void AddSubscriber(SVSubscriber subscriber)
{
SVReceiver_addSubscriber(self, subscriber.self);
}
public void RemoveSubscriber(SVSubscriber subscriber)
{
SVReceiver_removeSubscriber(self, subscriber.self);
}
/// <summary>
/// Start handling SV messages
/// </summary>
public void Start()
{
SVReceiver_start(self);
}
/// <summary>
/// Stop handling SV messges
/// </summary>
public void Stop()
{
SVReceiver_stop(self);
}
public bool IsRunning()
{
return SVReceiver_isRunning(self);
}
/// <summary>
/// Releases all resource used by the <see cref="IEC61850.SV.Subscriber.SVReceiver"/> object.
/// </summary>
/// <remarks>Call <see cref="Dispose"/> when you are finished using the <see cref="IEC61850.SV.Subscriber.SVReceiver"/>. The
/// <see cref="Dispose"/> method leaves the <see cref="IEC61850.SV.Subscriber.SVReceiver"/> in an unusable state.
/// After calling <see cref="Dispose"/>, you must release all references to the
/// <see cref="IEC61850.SV.Subscriber.SVReceiver"/> so the garbage collector can reclaim the memory that the
/// <see cref="IEC61850.SV.Subscriber.SVReceiver"/> was occupying.</remarks>
public void Dispose()
{
if (isDisposed == false)
{
isDisposed = true;
SVReceiver_destroy(self);
self = IntPtr.Zero;
}
}
~SVReceiver()
{
Dispose();
}
}
/// <summary>
/// SV listener.
/// </summary>
public delegate void SVUpdateListener(SVSubscriber report, object parameter, SVSubscriberASDU asdu);
/// <summary>
/// Sampled Values (SV) Subscriber
///
/// A subscriber is an instance associated with a single stream of measurement data. It is identified
/// by the Ethernet destination address, the appID value (both are on SV message level) and the svID value
/// that is part of each ASDU.
/// </summary>
public class SVSubscriber : IDisposable
{
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
private delegate void InternalSVUpdateListener(IntPtr subscriber, IntPtr parameter, IntPtr asdu);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_create([Out] byte[] ethAddr, UInt16 appID);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_create(IntPtr ethAddr, UInt16 appID);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVSubscriber_setListener(IntPtr self, InternalSVUpdateListener listener, IntPtr parameter);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern void SVSubscriber_destroy(IntPtr self);
internal IntPtr self;
private bool isDisposed = false;
private SVUpdateListener listener;
private object listenerParameter = null;
private event InternalSVUpdateListener internalListener = null;
private void internalSVUpdateListener(IntPtr subscriber, IntPtr parameter, IntPtr asdu)
{
try
{
if (listener != null)
{
listener(this, listenerParameter, new SVSubscriberASDU(asdu));
}
}
catch (Exception e)
{
// older versions of mono 2.10 (for linux?) cause this exception
Console.WriteLine(e.Message);
}
}
public SVSubscriber(byte[] ethAddr, UInt16 appID)
{
if (ethAddr == null)
{
self = SVSubscriber_create(IntPtr.Zero, appID);
}
else
{
if (ethAddr.Length != 6)
throw new ArgumentException("ethAddr argument has to be of 6 byte size");
self = SVSubscriber_create(ethAddr, appID);
}
}
public void SetListener(SVUpdateListener listener, object parameter)
{
this.listener = listener;
listenerParameter = parameter;
if (internalListener == null)
{
internalListener = new InternalSVUpdateListener(internalSVUpdateListener);
SVSubscriber_setListener(self, internalListener, IntPtr.Zero);
}
}
public void Dispose()
{
if (isDisposed == false)
{
isDisposed = true;
SVSubscriber_destroy(self);
self = IntPtr.Zero;
}
}
}
public class SVSubscriberASDU
{
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getSmpCnt(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_ASDU_getSvId(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_ASDU_getDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 SVSubscriber_ASDU_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern byte SVSubscriber_ASDU_getSmpMod(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getSmpRate(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern IntPtr SVSubscriber_ASDU_getDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 SVSubscriber_ASDU_getConfRev(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern byte SVSubscriber_ASDU_getSmpMod(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getSmpRate(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasDatSet(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasRefrTm(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasRefrTm(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasSmpMod(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasSmpMod(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasSmpRate(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt64 SVSubscriber_ASDU_getRefrTmAsMs(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern sbyte SVSubscriber_ASDU_getINT8(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int16 SVSubscriber_ASDU_getINT16(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 SVSubscriber_ASDU_getINT32(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int64 SVSubscriber_ASDU_getINT64(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern byte SVSubscriber_ASDU_getINT8U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getINT16U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 SVSubscriber_ASDU_getINT32U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt64 SVSubscriber_ASDU_getINT64U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern float SVSubscriber_ASDU_getFLOAT32(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern double SVSubscriber_ASDU_getFLOAT64(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getQuality(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int SVSubscriber_ASDU_getDataSize(IntPtr self);
private IntPtr self;
internal SVSubscriberASDU(IntPtr self)
{
this.self = self;
}
public UInt16 GetSmpCnt()
{
return SVSubscriber_ASDU_getSmpCnt(self);
}
public string GetSvId()
{
return Marshal.PtrToStringAnsi(SVSubscriber_ASDU_getSvId(self));
}
public string GetDatSet()
{
return Marshal.PtrToStringAnsi(SVSubscriber_ASDU_getDatSet(self));
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
private static extern bool SVSubscriber_ASDU_hasSmpRate(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt64 SVSubscriber_ASDU_getRefrTmAsMs(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern sbyte SVSubscriber_ASDU_getINT8(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int16 SVSubscriber_ASDU_getINT16(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int32 SVSubscriber_ASDU_getINT32(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern Int64 SVSubscriber_ASDU_getINT64(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern byte SVSubscriber_ASDU_getINT8U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getINT16U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt32 SVSubscriber_ASDU_getINT32U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt64 SVSubscriber_ASDU_getINT64U(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern float SVSubscriber_ASDU_getFLOAT32(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern double SVSubscriber_ASDU_getFLOAT64(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern UInt16 SVSubscriber_ASDU_getQuality(IntPtr self, int index);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern int SVSubscriber_ASDU_getDataSize(IntPtr self);
private IntPtr self;
internal SVSubscriberASDU (IntPtr self)
{
this.self = self;
}
public UInt16 GetSmpCnt()
{
return SVSubscriber_ASDU_getSmpCnt (self);
}
public string GetSvId()
{
return Marshal.PtrToStringAnsi (SVSubscriber_ASDU_getSvId(self));
}
public string GetDatSet()
{
return Marshal.PtrToStringAnsi (SVSubscriber_ASDU_getDatSet(self));
}
public UInt32 GetConfRev()
{
return SVSubscriber_ASDU_getConfRev (self);
}
public SmpMod GetSmpMod()
{
return (SmpMod) SVSubscriber_ASDU_getSmpMod (self);
}
public UInt32 GetConfRev()
{
return SVSubscriber_ASDU_getConfRev(self);
}
public SmpMod GetSmpMod()
{
return (SmpMod)SVSubscriber_ASDU_getSmpMod(self);
}
public UInt16 GetSmpRate()
{
return (UInt16)SVSubscriber_ASDU_getSmpRate (self);
}
public bool HasDatSet()
{
return SVSubscriber_ASDU_hasDatSet (self);
}
public bool HasRefrRm()
{
return SVSubscriber_ASDU_hasRefrTm (self);
}
public bool HasSmpMod()
{
return SVSubscriber_ASDU_hasSmpMod (self);
}
public bool HasSmpRate()
{
return SVSubscriber_ASDU_hasSmpRate (self);
}
public UInt64 GetRefrTmAsMs()
{
return SVSubscriber_ASDU_getRefrTmAsMs (self);
}
public sbyte GetINT8(int index)
{
return SVSubscriber_ASDU_getINT8 (self, index);
}
public Int16 GetINT16(int index)
{
return SVSubscriber_ASDU_getINT16 (self, index);
}
public Int32 GetINT32(int index)
{
return SVSubscriber_ASDU_getINT32 (self, index);
}
public Int64 GetINT64(int index)
{
return SVSubscriber_ASDU_getINT64 (self, index);
}
public byte GetINT8U(int index)
{
return SVSubscriber_ASDU_getINT8U (self, index);
}
public UInt16 GetINT16U(int index)
{
return SVSubscriber_ASDU_getINT16U (self, index);
}
public UInt32 GetINT32U(int index)
{
return SVSubscriber_ASDU_getINT32U (self, index);
}
public UInt64 GetINT64U(int index)
{
return SVSubscriber_ASDU_getINT64U (self, index);
}
public float GetFLOAT32(int index)
{
return SVSubscriber_ASDU_getFLOAT32 (self, index);
}
public double GetFLOAT64(int index)
{
return SVSubscriber_ASDU_getFLOAT64 (self, index);
}
private struct PTimestamp
{
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 8)]
public byte[] val;
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern PTimestamp SVSubscriber_ASDU_getTimestamp(IntPtr self, int index);
public Timestamp GetTimestamp(int index)
{
PTimestamp retVal = SVSubscriber_ASDU_getTimestamp (self, index);
return new Timestamp (retVal.val);
}
public Quality GetQuality(int index)
{
UInt16 qValue = SVSubscriber_ASDU_getQuality (self, index);
return new Quality (qValue);
}
/// <summary>
/// Gets the size of the payload data in bytes. The payload comprises the data set data.
/// </summary>
/// <returns>The payload data size in byte</returns>
public int GetDataSize()
{
return SVSubscriber_ASDU_getDataSize (self);
}
}
}
}
public UInt16 GetSmpRate()
{
return SVSubscriber_ASDU_getSmpRate(self);
}
public bool HasDatSet()
{
return SVSubscriber_ASDU_hasDatSet(self);
}
public bool HasRefrRm()
{
return SVSubscriber_ASDU_hasRefrTm(self);
}
public bool HasSmpMod()
{
return SVSubscriber_ASDU_hasSmpMod(self);
}
public bool HasSmpRate()
{
return SVSubscriber_ASDU_hasSmpRate(self);
}
public UInt64 GetRefrTmAsMs()
{
return SVSubscriber_ASDU_getRefrTmAsMs(self);
}
public sbyte GetINT8(int index)
{
return SVSubscriber_ASDU_getINT8(self, index);
}
public Int16 GetINT16(int index)
{
return SVSubscriber_ASDU_getINT16(self, index);
}
public Int32 GetINT32(int index)
{
return SVSubscriber_ASDU_getINT32(self, index);
}
public Int64 GetINT64(int index)
{
return SVSubscriber_ASDU_getINT64(self, index);
}
public byte GetINT8U(int index)
{
return SVSubscriber_ASDU_getINT8U(self, index);
}
public UInt16 GetINT16U(int index)
{
return SVSubscriber_ASDU_getINT16U(self, index);
}
public UInt32 GetINT32U(int index)
{
return SVSubscriber_ASDU_getINT32U(self, index);
}
public UInt64 GetINT64U(int index)
{
return SVSubscriber_ASDU_getINT64U(self, index);
}
public float GetFLOAT32(int index)
{
return SVSubscriber_ASDU_getFLOAT32(self, index);
}
public double GetFLOAT64(int index)
{
return SVSubscriber_ASDU_getFLOAT64(self, index);
}
private struct PTimestamp
{
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I1, SizeConst = 8)]
public byte[] val;
}
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
private static extern PTimestamp SVSubscriber_ASDU_getTimestamp(IntPtr self, int index);
public Timestamp GetTimestamp(int index)
{
PTimestamp retVal = SVSubscriber_ASDU_getTimestamp(self, index);
return new Timestamp(retVal.val);
}
public Quality GetQuality(int index)
{
UInt16 qValue = SVSubscriber_ASDU_getQuality(self, index);
return new Quality(qValue);
}
/// <summary>
/// Gets the size of the payload data in bytes. The payload comprises the data set data.
/// </summary>
/// <returns>The payload data size in byte</returns>
public int GetDataSize()
{
return SVSubscriber_ASDU_getDataSize(self);
}
}
}
}
}

@ -21,14 +21,9 @@
* See COPYING file for the complete license text.
*/
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Collections;
using System.Security.Cryptography.X509Certificates;
using System.Security.Cryptography;
using IEC61850.Common;
using System.Security.Cryptography.X509Certificates;
/// <summary>
/// IEC 61850 API for the libiec61850 .NET wrapper library
@ -114,7 +109,7 @@ namespace IEC61850
{
if (isValid)
{
return (TLSConfigVersion)TLSConnection_getTLSVersion((IntPtr)self);
return (TLSConfigVersion)TLSConnection_getTLSVersion(self);
}
else
{
@ -136,7 +131,7 @@ namespace IEC61850
if (isValid)
{
IntPtr peerAddrBuf = Marshal.AllocHGlobal(130);
IntPtr peerAddrStr = TLSConnection_getPeerAddress(this.self, peerAddrBuf);
IntPtr peerAddrStr = TLSConnection_getPeerAddress(self, peerAddrBuf);
string peerAddr = null;
@ -216,6 +211,12 @@ namespace IEC61850
private bool allowOnlyKnownCerts = false;
private bool chainValidation = true;
private bool sessionResumptionEnabled = true; /* default is true */
private int sessionResumptionInterval = 21600; /* in seconds */
private bool timeValidation = true; /* validate validity time in vertificates (default: true) */
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern IntPtr TLSConfiguration_create();
@ -263,18 +264,41 @@ namespace IEC61850
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addCACertificateFromFile(IntPtr self, string filename);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addCRL(IntPtr self, byte[] crl, int crlLen);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
[return: MarshalAs(UnmanagedType.I1)]
static extern bool TLSConfiguration_addCRLFromFile(IntPtr self, string filename);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_resetCRL(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setMinTlsVersion(IntPtr self, int version);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setMaxTlsVersion(IntPtr self, int version);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_addCipherSuite(IntPtr self, int ciphersuite);
[DllImport("tase2", CallingConvention = CallingConvention.Cdecl)]
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_clearCipherSuiteList(IntPtr self);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_enableSessionResumption(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setSessionResumptionInterval(IntPtr self, int value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setTimeValidation(IntPtr self, [MarshalAs(UnmanagedType.I1)] bool value);
[DllImport("iec61850", CallingConvention = CallingConvention.Cdecl)]
static extern void TLSConfiguration_setRenegotiationTime(IntPtr self, int value);
private TLSEventHandler eventHandler = null;
private object eventHandlerParameter = null;
@ -302,8 +326,8 @@ namespace IEC61850
public void SetEventHandler(TLSEventHandler handler, object parameter)
{
this.eventHandler = handler;
this.eventHandlerParameter = parameter;
eventHandler = handler;
eventHandlerParameter = parameter;
if (internalTLSEventHandlerRef == null)
{
@ -354,6 +378,64 @@ namespace IEC61850
}
}
/// <summary>
/// Enable or disable session resumption (enabled by default)
/// </summary>
public bool SessionResumption
{
set
{
TLSConfiguration_enableSessionResumption(self, value);
sessionResumptionEnabled = value;
}
get
{
return sessionResumptionEnabled;
}
}
/// <summary>
/// Get or set the session resumption interval in seconds
/// </summary>
public int SessionResumptionInterval
{
set
{
TLSConfiguration_setSessionResumptionInterval(self, value);
sessionResumptionInterval = value;
}
get
{
return sessionResumptionInterval;
}
}
/// <summary>
/// Verify validity of times in certificates and CRLs (default: true)
/// </summary>
public bool TimeValidation
{
set
{
TLSConfiguration_setTimeValidation(self, value);
timeValidation = value;
}
get
{
return timeValidation;
}
}
/// <summary>
/// Set the TLS session renegotiation timeout.
/// </summary>
/// <param name="timeInMs">session renegotiation timeout in milliseconds</param>
public void SetRenegotiationTime(int timeInMs)
{
TLSConfiguration_setRenegotiationTime(self, timeInMs);
}
public void SetClientMode()
{
TLSConfiguration_setClientMode(self);
@ -413,7 +495,13 @@ namespace IEC61850
}
}
public void SetOwnKey(string filename, string password)
/// <summary>
/// Set own private key from file
/// </summary>
/// <param name="filename">Filename of a DER or PEM private key file</param>
/// <param name="password">Password in case the private key is password protected</param>
/// <exception cref="CryptographicException"></exception>
public void SetOwnKey(string filename, string password = null)
{
if (TLSConfiguration_setOwnKeyFromFile(self, filename, password) == false)
{
@ -431,6 +519,26 @@ namespace IEC61850
}
}
/// <summary>
/// Add a CRL from a X509 CRL file
/// </summary>
/// <param name="filename">the name of the CRL file</param>
public void AddCRL(string filename)
{
if (TLSConfiguration_addCRLFromFile(self, filename) == false)
{
throw new CryptographicException("Failed to read CRL from file");
}
}
/// <summary>
/// Removes any CRL (certificate revocation list) currently in use
/// </summary>
public void ResetCRL()
{
TLSConfiguration_resetCRL(self);
}
/// <summary>
/// Set minimal allowed TLS version to use
/// </summary>
@ -454,7 +562,7 @@ namespace IEC61850
/// Add an allowed ciphersuite to the list of allowed ciphersuites
/// </summary>
/// <param name="ciphersuite"></param>
public void addCipherSuite(TlsCipherSuite ciphersuite)
public void AddCipherSuite(TlsCipherSuite ciphersuite)
{
TLSConfiguration_addCipherSuite(self,(int) ciphersuite);
}
@ -464,7 +572,7 @@ namespace IEC61850
/// </summary>
/// <remarks>Version for .NET framework that does not support TlsCipherSuite enum</remarks>
/// <param name="ciphersuite"></param>
public void addCipherSuite(int ciphersuite)
public void AddCipherSuite(int ciphersuite)
{
TLSConfiguration_addCipherSuite(self, ciphersuite);
}
@ -473,7 +581,7 @@ namespace IEC61850
/// Clears list of allowed ciphersuites
/// </summary>
/// <returns></returns>
public void clearCipherSuiteList()
public void ClearCipherSuiteList()
{
TLSConfiguration_clearCipherSuiteList(self);
}

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("authenticate")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0BECEC77-2315-4B95-AFF9-E6007E644BBF}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>authenticate</RootNamespace>
<AssemblyName>authenticate</AssemblyName>
<AssemblyTitle>authenticate</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<Deterministic>false</Deterministic>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("client_example_async")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,49 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{71902641-776A-47D8-9C0E-9ACBBEAC1370}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>client_example_async</RootNamespace>
<AssemblyName>client_example_async</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
<AssemblyTitle>client_example_async</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="app.config" />
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("client-example-setting-group")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,44 +1,24 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{0DA95476-B149-450B-AC36-01CEECFC1A43}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>clientexamplesettinggroup</RootNamespace>
<AssemblyName>client-example-setting-group</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AssemblyTitle>client-example-setting-group</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("control")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C351CFA4-E54E-49A1-86CE-69643535541A}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>control</RootNamespace>
<AssemblyName>control</AssemblyName>
<AssemblyTitle>control</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="ControlExample.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("datasets")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>datasets</RootNamespace>
<AssemblyName>datasets</AssemblyName>
<AssemblyTitle>datasets</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="DataSetExample.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,54 +1,58 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.28307.779
# Visual Studio Version 17
VisualStudioVersion = 17.10.35004.147
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IEC61850.NET", "IEC61850forCSharp\IEC61850.NET.csproj", "{C35D624E-5506-4560-8074-1728F1FA1A4D}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IEC61850.NET", "IEC61850forCSharp\IEC61850.NET.csproj", "{C35D624E-5506-4560-8074-1728F1FA1A4D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example1", "example1\example1.csproj", "{C616A6DF-831E-443C-9310-3F343A6E3D1A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "example1", "example1\example1.csproj", "{C616A6DF-831E-443C-9310-3F343A6E3D1A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "model_browsing", "model_browsing\model_browsing.csproj", "{59B85486-F48D-4978-BD35-8F5C3A8288D4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "model_browsing", "model_browsing\model_browsing.csproj", "{59B85486-F48D-4978-BD35-8F5C3A8288D4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "datasets", "datasets\datasets.csproj", "{D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "datasets", "datasets\datasets.csproj", "{D5C7DD38-032A-49B6-B74F-FFD9724A8AE4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "control", "control\control.csproj", "{C351CFA4-E54E-49A1-86CE-69643535541A}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "control", "control\control.csproj", "{C351CFA4-E54E-49A1-86CE-69643535541A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "reporting", "reporting\reporting.csproj", "{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "reporting", "reporting\reporting.csproj", "{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example2", "example2\example2.csproj", "{2A226B6D-1D1F-4BFE-B8CC-158116F71270}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "example2", "example2\example2.csproj", "{2A226B6D-1D1F-4BFE-B8CC-158116F71270}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "authenticate", "authenticate\authenticate.csproj", "{0BECEC77-2315-4B95-AFF9-E6007E644BBF}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "authenticate", "authenticate\authenticate.csproj", "{0BECEC77-2315-4B95-AFF9-E6007E644BBF}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tests", "tests\tests.csproj", "{FBDFE530-DBEB-474B-BA54-9AB287DD57B3}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "files", "files\files.csproj", "{77127456-19B9-4D1A-AEF9-40F8D1C5695E}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "files", "files\files.csproj", "{77127456-19B9-4D1A-AEF9-40F8D1C5695E}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "example3", "example3\example3.csproj", "{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "example3", "example3\example3.csproj", "{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "report_new_dataset", "report_new_dataset\report_new_dataset.csproj", "{71485F99-2976-45E6-B73D-4946E594C15C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "report_new_dataset", "report_new_dataset\report_new_dataset.csproj", "{71485F99-2976-45E6-B73D-4946E594C15C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "log_client", "log_client\log_client.csproj", "{14C71267-2F38-460D-AA55-6803EE80AFB4}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "log_client", "log_client\log_client.csproj", "{14C71267-2F38-460D-AA55-6803EE80AFB4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = ".nuget", ".nuget", "{0D2F61F1-A173-44E7-BFB0-B698A1D44D12}"
ProjectSection(SolutionItems) = preProject
.nuget\packages.config = .nuget\packages.config
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server1", "server1\server1.csproj", "{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "server1", "server1\server1.csproj", "{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tls_client_example", "tls_client_example\tls_client_example.csproj", "{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tls_client_example", "tls_client_example\tls_client_example.csproj", "{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "goose_subscriber", "goose_subscriber\goose_subscriber.csproj", "{1285372C-2E62-494A-A661-8D5D3873318C}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "goose_subscriber", "goose_subscriber\goose_subscriber.csproj", "{1285372C-2E62-494A-A661-8D5D3873318C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "sv_subscriber", "sv_subscriber\sv_subscriber.csproj", "{44651D2D-3252-4FD5-8B8B-5552DBE1B499}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "sv_subscriber", "sv_subscriber\sv_subscriber.csproj", "{44651D2D-3252-4FD5-8B8B-5552DBE1B499}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "tls_server_example", "tls_server_example\tls_server_example.csproj", "{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "tls_server_example", "tls_server_example\tls_server_example.csproj", "{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_setting_groups", "client_example_setting_groups\client_example_setting_groups.csproj", "{0DA95476-B149-450B-AC36-01CEECFC1A43}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "client_example_setting_groups", "client_example_setting_groups\client_example_setting_groups.csproj", "{0DA95476-B149-450B-AC36-01CEECFC1A43}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "client_example_async", "client_example_async\client_example_async.csproj", "{71902641-776A-47D8-9C0E-9ACBBEAC1370}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "client_example_async", "client_example_async\client_example_async.csproj", "{71902641-776A-47D8-9C0E-9ACBBEAC1370}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server_goose_publisher", "server_goose_publisher\server_goose_publisher.csproj", "{C14BB883-86B8-401C-B3D6-B655F55F3298}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "server_goose_publisher", "server_goose_publisher\server_goose_publisher.csproj", "{C14BB883-86B8-401C-B3D6-B655F55F3298}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "log_server", "log_server\log_server.csproj", "{96124F40-D38E-499B-9968-674E0D32F933}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "server_example_access_control", "server_example_access_control\server_example_access_control.csproj", "{304D9146-1490-46EF-B771-20B0603084F5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -140,6 +144,14 @@ Global
{C14BB883-86B8-401C-B3D6-B655F55F3298}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C14BB883-86B8-401C-B3D6-B655F55F3298}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C14BB883-86B8-401C-B3D6-B655F55F3298}.Release|Any CPU.Build.0 = Release|Any CPU
{96124F40-D38E-499B-9968-674E0D32F933}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{96124F40-D38E-499B-9968-674E0D32F933}.Debug|Any CPU.Build.0 = Debug|Any CPU
{96124F40-D38E-499B-9968-674E0D32F933}.Release|Any CPU.ActiveCfg = Release|Any CPU
{96124F40-D38E-499B-9968-674E0D32F933}.Release|Any CPU.Build.0 = Release|Any CPU
{304D9146-1490-46EF-B771-20B0603084F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{304D9146-1490-46EF-B771-20B0603084F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{304D9146-1490-46EF-B771-20B0603084F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{304D9146-1490-46EF-B771-20B0603084F5}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("example1")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C616A6DF-831E-443C-9310-3F343A6E3D1A}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>example1</RootNamespace>
<AssemblyName>example1</AssemblyName>
<AssemblyTitle>example1</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("example2")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{2A226B6D-1D1F-4BFE-B8CC-158116F71270}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>example2</RootNamespace>
<AssemblyName>example2</AssemblyName>
<AssemblyTitle>example2</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="WriteValueExample.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("example3")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{5E5D0FE0-DF44-48D8-A10E-1FB07D34DEA2}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>example3</RootNamespace>
<AssemblyName>example3</AssemblyName>
<AssemblyTitle>example3</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("files")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{77127456-19B9-4D1A-AEF9-40F8D1C5695E}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>files</RootNamespace>
<AssemblyName>files</AssemblyName>
<AssemblyTitle>files</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="FileServicesExample.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("goose_subscriber")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("mzillgit")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,44 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{1285372C-2E62-494A-A661-8D5D3873318C}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>goose_subscriber</RootNamespace>
<AssemblyName>goose_subscriber</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AssemblyTitle>goose_subscriber</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -10,7 +10,7 @@ namespace log_client
private static void PrintJournalEntries(List<MmsJournalEntry> journalEntries) {
foreach (MmsJournalEntry entry in journalEntries) {
Console.WriteLine("EntryID: " + BitConverter.ToString(entry.GetEntryID()));
Console.WriteLine(" occurence time: " + MmsValue.MsTimeToDateTimeOffset(entry.GetOccurenceTime()).ToString());
Console.WriteLine(" occurence time: " + MmsValue.MsTimeToDateTimeOffset(entry.GetOccurenceTime()).ToString());
foreach (MmsJournalVariable variable in entry.GetJournalVariables()) {
Console.WriteLine(" variable: " + variable.GetTag());
Console.WriteLine(" value: " + variable.GetValue().ToString());
@ -47,12 +47,14 @@ namespace log_client
Console.WriteLine("LD: " + deviceName);
List<string> deviceDirectory = con.GetLogicalDeviceDirectory(deviceName);
foreach (string lnName in deviceDirectory) {
foreach (string lnName in deviceDirectory)
{
Console.WriteLine(" LN: " + lnName);
List<string> lcbs = con.GetLogicalNodeDirectory(deviceName + "/" + lnName, IEC61850.Common.ACSIClass.ACSI_CLASS_LCB);
foreach(string lcbName in lcbs) {
foreach (string lcbName in lcbs)
{
Console.WriteLine(" LCB: " + lcbName);
MmsValue lcbValues = con.ReadValue(deviceName + "/" + lnName + "." + lcbName, FunctionalConstraint.LG);
@ -62,7 +64,8 @@ namespace log_client
List<string> logs = con.GetLogicalNodeDirectory(deviceName + "/" + lnName, IEC61850.Common.ACSIClass.ACSI_CLASS_LOG);
foreach(string logName in logs) {
foreach (string logName in logs)
{
Console.WriteLine(" LOG: " + logName);
}
}
@ -72,7 +75,10 @@ namespace log_client
Console.WriteLine("\nQueryLogAfter:");
List<MmsJournalEntry> journalEntries = con.QueryLogAfter("simpleIOGenericIO/LLN0$EventLog",
Console.WriteLine(DateTime.UtcNow);
List<MmsJournalEntry> journalEntries = con.QueryLogAfter("simpleIOGenericIO/LLN0$EventLog",
new byte[]{0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}, 0, out moreFollows);
PrintJournalEntries(journalEntries);

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("log_client")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("mzillgit")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,44 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{14C71267-2F38-460D-AA55-6803EE80AFB4}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>log_client</RootNamespace>
<AssemblyName>log_client</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<AssemblyTitle>log_client</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
</Project>
</Project>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
</startup>
</configuration>

@ -0,0 +1,150 @@
using IEC61850.Common;
using IEC61850.Server;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Data.Common;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static IEC61850.Server.IedServer;
using static IEC61850.Server.LogStorage;
namespace log_server
{
internal class Program
{
public static void Main(string[] args)
{
bool entryCallback(System.IntPtr self, long timestamp, long entryID1, bool moreFollow)
{
if (moreFollow)
Console.WriteLine($"Found entry ID:{entryID1} timestamp:{timestamp}");
return true;
}
bool entryDataCallback(System.IntPtr self, string dataRef, byte[] data, int dataSize, int reasonCode, bool moreFollow)
{
if (moreFollow)
{
Console.WriteLine($"EntryData: ref: {dataRef}\n");
}
return true;
}
bool running = true;
/* run until Ctrl-C is pressed */
Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
running = false;
};
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("model.cfg");
if (iedModel == null)
{
Console.WriteLine("No valid data model found!");
return;
}
IedServerConfig config = new IedServerConfig();
config.ReportBufferSize = 100000;
IedServer iedServer = new IedServer(iedModel, config);
LogStorage statusLog = SqliteLogStorage.CreateLogStorage("log_status.db");
statusLog.MaxLogEntries = 10;
iedServer.SetLogStorage("GenericIO/LLN0$EventLog", statusLog);
long time = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
int entryID = statusLog.AddEntry(time);
MmsValue value = new MmsValue(123);
byte[] blob = new byte[256];
int blobSize = value.EncodeMmsData(blob, 0, true);
bool restun = statusLog.AddEntryData(entryID, "GenericIO/GGIO1.SPCSO1$stVal", blob, blobSize, 0);
value.Dispose();
ulong unixTimeMs = (ulong)DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
entryID = statusLog.AddEntry((long)unixTimeMs);
value = MmsValue.NewUtcTime(unixTimeMs);
blob = new byte[256];
blobSize = value.EncodeMmsData(blob, 0, true);
value.Dispose();
bool restun1 = statusLog.AddEntryData(entryID, "simpleIOGenerioIO/GPIO1$ST$SPCSO1$t", blob, blobSize, 0);
bool return3 = statusLog.GetEntries(0, DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(), (LogEntryCallback)entryCallback, (LogEntryDataCallback)entryDataCallback, (System.IntPtr)null);
iedServer.Start(102);
if (iedServer.IsRunning())
{
Console.WriteLine("Server started");
DataObject ggio1AnIn1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1");
DataAttribute ggio1AnIn1magF = (DataAttribute)ggio1AnIn1.GetChild("mag.f");
DataAttribute ggio1AnIn1T = (DataAttribute)ggio1AnIn1.GetChild("t");
DataObject ggio1Spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO1");
DataAttribute ggio1Spcso1stVal = (DataAttribute)ggio1Spcso1.GetChild("stVal");
DataAttribute ggio1Spcso1T = (DataAttribute)ggio1Spcso1.GetChild("t");
float floatVal = 1.0f;
bool stVal = true;
while (running)
{
floatVal += 1f;
stVal = !stVal;
iedServer.LockDataModel();
long unixSeconds = DateTimeOffset.UtcNow.ToUnixTimeSeconds();
DateTime utcTime = DateTimeOffset.FromUnixTimeSeconds(unixSeconds).UtcDateTime;
var ts = new Timestamp(utcTime);
iedServer.UpdateTimestampAttributeValue(ggio1AnIn1T, ts);
iedServer.UpdateFloatAttributeValue(ggio1AnIn1magF, floatVal);
iedServer.UpdateTimestampAttributeValue(ggio1Spcso1T, ts);
iedServer.UpdateBooleanAttributeValue(ggio1Spcso1stVal, stVal);
iedServer.UnlockDataModel();
Thread.Sleep(100);
}
iedServer.Stop();
Console.WriteLine("Server stopped");
}
else
{
Console.WriteLine("Failed to start server");
}
iedServer.Destroy();
statusLog.Dispose();
}
}
}

@ -0,0 +1,13 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("96124f40-d38e-499b-9968-674e0d32f933")]

@ -0,0 +1,49 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
<UpdateEnabled>false</UpdateEnabled>
<UpdateMode>Foreground</UpdateMode>
<UpdateInterval>7</UpdateInterval>
<UpdateIntervalUnits>Days</UpdateIntervalUnits>
<UpdatePeriodically>false</UpdatePeriodically>
<UpdateRequired>false</UpdateRequired>
<MapFileExtensions>true</MapFileExtensions>
<ApplicationRevision>0</ApplicationRevision>
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<AssemblyTitle>log_server</AssemblyTitle>
<Product>log_server</Product>
<Copyright>Copyright © 2024</Copyright>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<ItemGroup>
<None Update="model.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.8.1">
<Visible>False</Visible>
<ProductName>Microsoft .NET Framework 4.8.1 %28x86 and x64%29</ProductName>
<Install>true</Install>
</BootstrapperPackage>
<BootstrapperPackage Include="Microsoft.Net.Framework.3.5.SP1">
<Visible>False</Visible>
<ProductName>.NET Framework 3.5 SP1</ProductName>
<Install>false</Install>
</BootstrapperPackage>
</ItemGroup>
</Project>

@ -0,0 +1,237 @@
MODEL(simpleIO){
LD(GenericIO){
LN(LLN0){
DO(Mod 0){
DA(stVal 0 12 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=0;
}
DO(Beh 0){
DA(stVal 0 12 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Health 0){
DA(stVal 0 3 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(NamPlt 0){
DA(vendor 0 20 5 0 0);
DA(swRev 0 20 5 0 0);
DA(d 0 20 5 0 0);
DA(configRev 0 20 5 0 0);
DA(ldNs 0 20 11 0 0);
}
DS(Events){
DE(GGIO1$ST$SPCSO1$stVal);
DE(GGIO1$ST$SPCSO2$stVal);
DE(GGIO1$ST$SPCSO3$stVal);
DE(GGIO1$ST$SPCSO4$stVal);
}
DS(AnalogValues){
DE(GGIO1$MX$AnIn1);
DE(GGIO1$MX$AnIn2);
DE(GGIO1$MX$AnIn3);
DE(GGIO1$MX$AnIn4);
}
RC(EventsRCB01 Events 0 Events 1 24 111 50 1000);
RC(AnalogValuesRCB01 AnalogValues 0 AnalogValues 1 24 111 50 1000);
LC(EventLog Events GenericIO/LLN0$EventLog 19 0 0 1);
LC(GeneralLog - - 19 0 0 1);
LOG(GeneralLog);
LOG(EventLog);
GC(gcbEvents events Events 2 0 -1 -1 ){
PA(4 273 4096 010ccd010001);
}
GC(gcbAnalogValues analog AnalogValues 2 0 -1 -1 ){
PA(4 273 4096 010ccd010001);
}
}
LN(LPHD1){
DO(PhyNam 0){
DA(vendor 0 20 5 0 0);
}
DO(PhyHealth 0){
DA(stVal 0 3 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Proxy 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
}
LN(GGIO1){
DO(Mod 0){
DA(stVal 0 12 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=0;
}
DO(Beh 0){
DA(stVal 0 12 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Health 0){
DA(stVal 0 3 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(NamPlt 0){
DA(vendor 0 20 5 0 0);
DA(swRev 0 20 5 0 0);
DA(d 0 20 5 0 0);
}
DO(AnIn1 0){
DA(mag 0 27 1 1 0){
DA(f 0 10 1 1 0);
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
DO(AnIn2 0){
DA(mag 0 27 1 1 101){
DA(f 0 10 1 1 0);
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 102);
}
DO(AnIn3 0){
DA(mag 0 27 1 1 0){
DA(f 0 10 1 1 0);
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
DO(AnIn4 0){
DA(mag 0 27 1 1 0){
DA(f 0 10 1 1 0);
}
DA(q 0 23 1 2 0);
DA(t 0 22 1 0 0);
}
DO(SPCSO1 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(origin 0 27 12 0 0){
DA(orCat 0 12 12 0 0);
DA(orIdent 0 13 12 0 0);
}
DA(ctlNum 0 6 12 0 0);
DA(T 0 22 12 0 0);
DA(Test 0 0 12 0 0);
DA(Check 0 24 12 0 0);
}
DA(ctlModel 0 12 4 0 0)=1;
DA(t 0 22 0 0 0);
}
DO(SPCSO2 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(origin 0 27 12 0 0){
DA(orCat 0 12 12 0 0);
DA(orIdent 0 13 12 0 0);
}
DA(ctlNum 0 6 12 0 0);
DA(T 0 22 12 0 0);
DA(Test 0 0 12 0 0);
DA(Check 0 24 12 0 0);
}
DA(ctlModel 0 12 4 0 0)=1;
DA(t 0 22 0 0 0);
}
DO(SPCSO3 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(origin 0 27 12 0 0){
DA(orCat 0 12 12 0 0);
DA(orIdent 0 13 12 0 0);
}
DA(ctlNum 0 6 12 0 0);
DA(T 0 22 12 0 0);
DA(Test 0 0 12 0 0);
DA(Check 0 24 12 0 0);
}
DA(ctlModel 0 12 4 0 0)=1;
DA(t 0 22 0 0 0);
}
DO(SPCSO4 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(Oper 0 27 12 0 0){
DA(ctlVal 0 0 12 0 0);
DA(origin 0 27 12 0 0){
DA(orCat 0 12 12 0 0);
DA(orIdent 0 13 12 0 0);
}
DA(ctlNum 0 6 12 0 0);
DA(T 0 22 12 0 0);
DA(Test 0 0 12 0 0);
DA(Check 0 24 12 0 0);
}
DA(ctlModel 0 12 4 0 0)=1;
DA(t 0 22 0 0 0);
}
DO(Ind1 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Ind2 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Ind3 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Ind4 0){
DA(stVal 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
}
LN(PDUP1){
DO(Beh 0){
DA(stVal 0 12 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Mod 0){
DA(stVal 0 12 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
DA(ctlModel 0 12 4 0 0)=0;
}
DO(Str 0){
DA(general 0 0 0 1 0);
DA(dirGeneral 0 12 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(Op 0){
DA(general 0 0 0 1 0);
DA(q 0 23 0 2 0);
DA(t 0 22 0 0 0);
}
DO(OpDlTmms 0){
DA(setVal 0 3 2 1 0);
}
DO(RsDlTmms 0){
DA(setVal 0 3 2 1 0);
}
}
}
}

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("model_browsing")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{59B85486-F48D-4978-BD35-8F5C3A8288D4}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>model_browsing</RootNamespace>
<AssemblyName>model_browsing</AssemblyName>
<AssemblyTitle>model_browsing</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="ModelBrowsing.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("report_new_dataset")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,43 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{71485F99-2976-45E6-B73D-4946E594C15C}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>report_new_dataset</RootNamespace>
<AssemblyName>report_new_dataset</AssemblyName>
<AssemblyTitle>report_new_dataset</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="Main.cs" />
<Compile Include="AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle("reporting")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("mzillgit")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,28 +0,0 @@
namespace reporting.Properties {
// This class allows you to handle specific events on the settings class:
// The SettingChanging event is raised before a setting's value is changed.
// The PropertyChanged event is raised after a setting's value is changed.
// The SettingsLoaded event is raised after the setting values are loaded.
// The SettingsSaving event is raised before the setting values are saved.
internal sealed partial class Settings {
public Settings() {
// // To add event handlers for saving and changing settings, uncomment the lines below:
//
// this.SettingChanging += this.SettingChangingEventHandler;
//
// this.SettingsSaving += this.SettingsSavingEventHandler;
//
}
private void SettingChangingEventHandler(object sender, System.Configuration.SettingChangingEventArgs e) {
// Add code to handle the SettingChangingEvent event here.
}
private void SettingsSavingEventHandler(object sender, System.ComponentModel.CancelEventArgs e) {
// Add code to handle the SettingsSaving event here.
}
}
}

@ -1,12 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9E29B4CE-EE5F-4CA6-85F6-5D1FF8B27BF8}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>reporting</RootNamespace>
<AssemblyName>reporting</AssemblyName>
<PublishUrl>publish\</PublishUrl>
<Install>true</Install>
<InstallFrom>Disk</InstallFrom>
@ -22,39 +17,24 @@
<IsWebBootstrapper>false</IsWebBootstrapper>
<UseApplicationTrust>false</UseApplicationTrust>
<BootstrapperEnabled>true</BootstrapperEnabled>
<AssemblyTitle>reporting</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<UseVSHostingProcess>true</UseVSHostingProcess>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
</ItemGroup>
<ItemGroup>
<Compile Include="AssemblyInfo.cs" />
<Compile Include="ReportingExample.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<ItemGroup>
<BootstrapperPackage Include=".NETFramework,Version=v4.0">
@ -78,4 +58,4 @@
<Install>true</Install>
</BootstrapperPackage>
</ItemGroup>
</Project>
</Project>

@ -2,6 +2,9 @@
using IEC61850.Server;
using IEC61850.Common;
using System.Threading;
using System.Net;
using static IEC61850.Server.IedServer;
using System.Collections.Generic;
namespace server1
{
@ -95,6 +98,20 @@ namespace server1
}, null);
void ConnectionCallBack(IedServer server, ClientConnection clientConnection, bool connected, object parameter)
{
string allowedIp = parameter as string;
string ipAddress = clientConnection.GetLocalAddress();
if (allowedIp != ipAddress)
{
clientConnection.Abort();
}
}
var connectionCallBack = new ConnectionIndicationHandler(ConnectionCallBack);
iedServer.SetConnectionIndicationHandler(connectionCallBack, "127.0.0.1:103");
iedServer.Start(102);
if (iedServer.IsRunning())

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("server1")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("mzillgit")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,50 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{9286D2AB-96ED-4631-AB3C-ED20FF5D6E6C}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>server1</RootNamespace>
<AssemblyName>server1</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
<AssemblyTitle>server1</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="model.cfg">
<None Update="model.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

@ -0,0 +1,443 @@
/*
* server_example_access_control.cs
*
* - How to use access control mechanisms
* - How to implement RBAC features based on access control mechanisms
*/
using System;
using IEC61850.Server;
using IEC61850.Common;
using IEC61850;
using System.Threading;
using System.Net;
using static IEC61850.Server.IedServer;
using System.Collections.Generic;
using System.Reflection.Metadata;
using IEC61850.Client;
using ReportControlBlock = IEC61850.Server.ReportControlBlock;
using IEC61850.Model;
using System.Data.Common;
using System.Security.Cryptography;
namespace server_access_control
{
class MainClass
{
class PTOC1Settings
{
public float strVal;
public int opDlTmms;
public int rsDlTmms;
public int rstTms;
}
public static void Main(string[] args)
{
bool running = true;
/* run until Ctrl-C is pressed */
Console.CancelKeyPress += delegate (object sender, ConsoleCancelEventArgs e)
{
e.Cancel = true;
running = false;
};
/* Create new server configuration object */
IedServerConfig config = new IedServerConfig();
/* Set buffer size for buffered report control blocks to 200000 bytes */
config.ReportBufferSize = 200000;
/* Set stack compliance to a specific edition of the standard (WARNING: data model has also to be checked for compliance) */
config.Edition = Iec61850Edition.EDITION_2;
/* Set the base path for the MMS file services */
config.FileServiceBasePath = "./vmd-filestore/";
/* disable MMS file service */
config.FileServiceEnabled = false;
/* enable dynamic data set service */
config.DynamicDataSetServiceEnabled = true;
/* disable log service */
config.LogServiceEnabled = false;
/* set maximum number of clients */
config.MaxMmsConnections = 2;
IedModel iedModel = ConfigFileParser.CreateModelFromConfigFile("model.cfg");
IedServer iedServer = new IedServer(iedModel, config);
iedServer.SetServerIdentity("libiec61850.com", "access control example", "1.0.0");
DataObject spcso1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.SPCSO1");
iedServer.SetControlHandler(spcso1, delegate (ControlAction action, object parameter, MmsValue value, bool test)
{
if (test)
return ControlHandlerResult.FAILED;
if (value.GetType() == MmsType.MMS_BOOLEAN)
{
Console.WriteLine("received binary control command: ");
if (value.GetBoolean())
Console.WriteLine("on\n");
else
Console.WriteLine("off\n");
}
else
return ControlHandlerResult.FAILED;
return ControlHandlerResult.OK;
}, spcso1);
void ConnectionCallBack(IedServer server, ClientConnection clientConnection, bool connected, object parameter)
{
if (connected)
Console.WriteLine("Connection opened\n");
else
Console.WriteLine("Connection closed\n");
}
var connectionCallBack = new ConnectionIndicationHandler(ConnectionCallBack);
iedServer.SetConnectionIndicationHandler(connectionCallBack, "127.0.0.1");
/* Install handler to log RCB events */
iedServer.SetRCBEventHandler(delegate (object parameter, ReportControlBlock rcb, ClientConnection con, RCBEventType eventType, string parameterName, MmsDataAccessError serviceError)
{
Console.WriteLine("RCB: " + rcb.Parent.GetObjectReference() + "." + rcb.Name + " event: " + eventType.ToString());
if (con != null)
{
Console.WriteLine(" caused by client " + con.GetPeerAddress());
}
else
{
Console.WriteLine(" client = null");
}
if ((eventType == RCBEventType.SET_PARAMETER) || (eventType == RCBEventType.GET_PARAMETER))
{
Console.WriteLine("RCB: "+rcb.Name + " event: "+ eventType .ToString()+ "\n");
Console.WriteLine(" param: "+ parameterName + "\n");
Console.WriteLine(" result: "+ serviceError.ToString() + "\n");
}
if (eventType == RCBEventType.ENABLED)
{
Console.WriteLine("RCB: "+ rcb.Name + " event: " + eventType.ToString() + "\n");
string rptId = rcb.RptID;
Console.WriteLine(" rptID: "+ rptId+"\n");
string dataSet =rcb.DataSet;
Console.WriteLine(" datSet:"+ dataSet+"\n");
}
}, null);
/* Install handler to control access to control blocks (RCBs, LCBs, GoCBs, SVCBs, SGCBs)*/
bool ControlBlockAccessCallBack(object parameter, ClientConnection connection, ACSIClass acsiClass, LogicalDevice ld, LogicalNode ln, string objectName, string subObjectName, ControlBlockAccessType accessType)
{
string password = parameter as string;
object securityToken = connection.GetSecurityToken();
if(securityToken != null)
{
if ((securityToken as string == password))
Console.WriteLine("Correct securityToken");
else
Console.WriteLine("Incorrect securityToken");
}
Console.WriteLine(acsiClass.ToString() + " "+ accessType.ToString() + " access " + ld.GetName() + ln.GetName() +"/"+ objectName + "." + subObjectName + "\n");
return true;
}
iedServer.SetControlBlockAccessHandler(ControlBlockAccessCallBack, "securityToken_password");
/* By default access to variables with FC=DC and FC=CF is not allowed.
* This allow to write to simpleIOGenericIO/GGIO1.NamPlt.vendor variable used
* by iec61850_client_example1.
*/
iedServer.SetWriteAccessPolicy(FunctionalConstraint.DC, AccessPolicy.ACCESS_POLICY_ALLOW);
/* Install handler to perform access control on datasets */
bool dataSetAccessHandler(object parameter, ClientConnection connection, DataSetOperation operation, string datasetRef)
{
Console.WriteLine("Data set access: "+ datasetRef+" operation: "+ operation.ToString() + "\n");
return true;
}
iedServer.SetDataSetAccessHandler(dataSetAccessHandler, iedServer);
/* Install handler to perform read access control on data model elements
* NOTE: when read access to a data model element is blocked this will also prevent the client
* to read the data model element in a data set or enable a RCB instance that uses a dataset
* containing the restricted data model element.
*/
MmsDataAccessError readAccessHandler(LogicalDevice ld, LogicalNode ln, DataObject dataObject, FunctionalConstraint fc, ClientConnection connection, object parameter)
{
if( dataObject!= null)
Console.WriteLine("Read access to "+ld.GetName() + "/"+ln.GetName() + "."+dataObject.GetName() + "\n");
else
Console.WriteLine("Read access to "+ld.GetName() + "/"+ln.GetName() + "\n");
if (dataObject == null)
{
if (ln.GetName() == "GGIO1")
{
return MmsDataAccessError.OBJECT_ACCESS_DENIED;
}
}
else
{
if (ln.GetName() == "GGIO1" && dataObject.GetName() == "AnIn1")
{
return MmsDataAccessError.OBJECT_ACCESS_DENIED;
}
}
return MmsDataAccessError.SUCCESS;
}
iedServer.SetReadAccessHandler(readAccessHandler, null);
bool directoryAccessHandler(object parameter, ClientConnection connection, IedServer_DirectoryCategory category, LogicalDevice ld)
{
switch (category)
{
case IedServer_DirectoryCategory.DIRECTORY_CAT_LD_LIST:
Console.WriteLine("Get list of logical devices from "+ connection.GetPeerAddress()+"\n");
break;
case IedServer_DirectoryCategory.DIRECTORY_CAT_DATASET_LIST:
Console.WriteLine("Get list of datasets for LD "+ ld.GetName() + " from "+ connection.GetPeerAddress()+"\n");
break;
case IedServer_DirectoryCategory.DIRECTORY_CAT_DATA_LIST:
Console.WriteLine("Get list of data for LD " + ld.GetName() + " from " + connection.GetPeerAddress() + "\n");
break;
case IedServer_DirectoryCategory.DIRECTORY_CAT_LOG_LIST:
Console.WriteLine("Get list of logs for LD" + ld.GetName() + " from " + connection.GetPeerAddress() + "\n");
return false;
}
return true;
}
iedServer.SetDirectoryAccessHandler(directoryAccessHandler, null);
/*SettingGroups*/
LogicalDevice logicalDevice = (LogicalDevice)iedModel.GetModelNodeByShortObjectReference("GenericIO"); ;
SettingGroupControlBlock settingGroupControlBlock = logicalDevice.GetSettingGroupControlBlock();
List<PTOC1Settings> ptoc1Settings = new List<PTOC1Settings>();
ptoc1Settings.Add(new PTOC1Settings { strVal = 1.0f, opDlTmms = 500, rsDlTmms = 500, rstTms = 500 });
ptoc1Settings.Add(new PTOC1Settings { strVal = 2.0f, opDlTmms = 1500, rsDlTmms = 2500, rstTms = 750 });
ptoc1Settings.Add(new PTOC1Settings { strVal = 3.0f, opDlTmms = 500, rsDlTmms = 1500, rstTms = 750 });
ptoc1Settings.Add(new PTOC1Settings { strVal = 3.5f, opDlTmms = 1250, rsDlTmms = 1750, rstTms = 500 });
ptoc1Settings.Add(new PTOC1Settings { strVal = 3.75f, opDlTmms = 1250, rsDlTmms = 1750, rstTms = 750 });
void LoadActiveSgValues(int actSG)
{
DataAttribute dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.StrVal.setMag.f");
iedServer.UpdateFloatAttributeValue(dataAttribute, ptoc1Settings[actSG - 1].strVal);
dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.OpDlTmms.setVal");
iedServer.UpdateInt32AttributeValue(dataAttribute, ptoc1Settings[actSG - 1].opDlTmms);
dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RsDlTmms.setVal");
iedServer.UpdateInt32AttributeValue(dataAttribute, ptoc1Settings[actSG - 1].rsDlTmms);
dataAttribute = (DataAttribute)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RstTms.setVal");
iedServer.UpdateInt32AttributeValue(dataAttribute, ptoc1Settings[actSG - 1].rstTms);
}
void LoadEditSgValues(int actSG)
{
DataObject strVal = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.StrVal");
DataAttribute setMagF = strVal.GetChildWithFc("setMag.f", FunctionalConstraint.SE);
iedServer.UpdateFloatAttributeValue(setMagF, ptoc1Settings[actSG - 1].strVal);
DataObject opDlTmms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.OpDlTmms");
DataAttribute setVal = opDlTmms.GetChildWithFc("setVal", FunctionalConstraint.SE);
iedServer.UpdateInt32AttributeValue(setVal, ptoc1Settings[actSG - 1].opDlTmms);
DataObject rsDlTmms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RsDlTmms");
DataAttribute rsDlTmms_setVal = rsDlTmms.GetChildWithFc("setVal", FunctionalConstraint.SE);
iedServer.UpdateInt32AttributeValue(rsDlTmms_setVal, ptoc1Settings[actSG - 1].rsDlTmms);
DataObject rstTms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RstTms");
DataAttribute rstTms_setVal = rstTms.GetChildWithFc("setVal", FunctionalConstraint.SE);
iedServer.UpdateInt32AttributeValue(rstTms_setVal, ptoc1Settings[actSG - 1].rstTms);
}
bool activeSGChangedHandler(object parameter, SettingGroupControlBlock sgcb, uint newActSg, ClientConnection connection)
{
Console.WriteLine("Switch to setting group "+ newActSg +"\n");
LoadActiveSgValues(Convert.ToInt32(newActSg));
return true;
}
bool editSGChangedHandler(object parameter, SettingGroupControlBlock sgcb, uint newEditSg, ClientConnection connection)
{
Console.WriteLine("Set edit setting group to " + newEditSg + "\n");
LoadEditSgValues(Convert.ToInt32(newEditSg));
return true;
}
void editSGConfirmationHandler(object parameter, SettingGroupControlBlock sgcb, uint editSg)
{
Console.WriteLine("Received edit sg confirm for sg " + editSg + "\n");
int edit = Convert.ToInt32(editSg);
DataObject strVal = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.StrVal");
DataAttribute setMagF = strVal.GetChildWithFc("setMag.f", FunctionalConstraint.SE);
MmsValue setMagFValue = iedServer.GetAttributeValue(setMagF);
DataObject opDlTmms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.OpDlTmms");
DataAttribute setVal = opDlTmms.GetChildWithFc("setVal", FunctionalConstraint.SE);
MmsValue setValValue = iedServer.GetAttributeValue(setVal);
DataObject rsDlTmms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RsDlTmms");
DataAttribute rsDlTmmsSetVal = rsDlTmms.GetChildWithFc("setVal", FunctionalConstraint.SE);
MmsValue rsDlTmmsSetValValue = iedServer.GetAttributeValue(rsDlTmmsSetVal);
DataObject rstTms = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/PTOC1.RstTms");
DataAttribute rstTmsSetVal = rstTms.GetChildWithFc("setVal", FunctionalConstraint.SE);
MmsValue rstTmsSetValVaue = iedServer.GetAttributeValue(rstTmsSetVal);
ptoc1Settings[edit - 1].strVal = setMagFValue.ToFloat();
ptoc1Settings[edit - 1].opDlTmms = setValValue.ToInt32();
ptoc1Settings[edit - 1].rsDlTmms = rsDlTmmsSetValValue.ToInt32();
ptoc1Settings[edit - 1].rstTms = rsDlTmmsSetValValue.ToInt32();
if (iedServer.GetActiveSettingGroupChangedHandler(sgcb) == edit)
{
LoadActiveSgValues(edit);
}
}
iedServer.SetActiveSettingGroupChangedHandler(activeSGChangedHandler, settingGroupControlBlock, null);
iedServer.SetEditSettingGroupChangedHandler(editSGChangedHandler, settingGroupControlBlock, null);
iedServer.SetEditSettingGroupConfirmationHandler(editSGConfirmationHandler, settingGroupControlBlock, null);
LogicalNode logicalNode = (LogicalNode)iedModel.GetModelNodeByShortObjectReference("GenericIO/LLN0");
SVControlBlock sampledValuesControlBlock_1 = iedModel.GetSVControlBlock(logicalNode, "SMV1");
SVControlBlock sampledValuesControlBlock_2 = iedModel.GetSVControlBlock(logicalNode, "SMV2");
void sVCBEventHandler(SVControlBlock sampledValuesControlBlock, SMVEvent sMVEvent, object parameter)
{
Console.WriteLine("control called " + sampledValuesControlBlock.Name + " Event: " + sMVEvent.ToString() + "\n");
}
iedServer.SetSVCBHandler(sVCBEventHandler, sampledValuesControlBlock_1, null);
iedServer.SetSVCBHandler(sVCBEventHandler, sampledValuesControlBlock_2, null);
bool clientAuthenticator (object parameter, AcseAuthenticationParameter authParameter, object securityToken, IsoApplicationReference isoApplicationReference)
{
List<string> passwords = parameter as List<string>;
int aeQualifier = isoApplicationReference.GetAeQualifier();
ItuObjectIdentifier ituObjectIdentifier = isoApplicationReference.GetApTitle();
int arcCount = ituObjectIdentifier.GetArcCount();
ushort[] arc = ituObjectIdentifier.GetArcs();
Console.WriteLine("ACSE Authenticator:\n");
string appTitle = "";
for (int i = 0; i < arcCount; i++)
{
appTitle += arc[i];
if (i != (arcCount - 1))
appTitle += ".";
}
Console.WriteLine(" client ap-title: " + appTitle);
Console.WriteLine("\n client ae-qualifier: "+ aeQualifier + " \n");
IEC61850.AcseAuthenticationMechanism acseAuthenticationMechanism = authParameter.GetAuthMechanism();
if (acseAuthenticationMechanism == IEC61850.AcseAuthenticationMechanism.ACSE_AUTH_PASSWORD)
{
byte[] passArray = authParameter.GetPasswordByteArray();
int passwordLenght = passArray.Length;
string password = authParameter.GetPasswordString();
if (passwordLenght == passwords.First().Length)
{
if (password == passwords.First())
{
securityToken = passwords.First();
return true;
}
}
else if (passwordLenght == passwords[1].Length)
{
if (password == passwords[1])
{
securityToken = passwords[1];
return true;
}
}
}
return false;
}
List<string> passwords = new List<string>();
passwords.Add("user1@testpw");
passwords.Add("user2@testpw");
iedServer.SetAuthenticator(clientAuthenticator, passwords);
iedServer.Start(102);
if (iedServer.IsRunning())
{
Console.WriteLine("Server started");
GC.Collect();
DataObject ggio1AnIn1 = (DataObject)iedModel.GetModelNodeByShortObjectReference("GenericIO/GGIO1.AnIn1");
DataAttribute ggio1AnIn1magF = (DataAttribute)ggio1AnIn1.GetChild("mag.f");
DataAttribute ggio1AnIn1T = (DataAttribute)ggio1AnIn1.GetChild("t");
float floatVal = 1.0f;
while (running)
{
floatVal += 1f;
iedServer.UpdateTimestampAttributeValue(ggio1AnIn1T, new Timestamp(DateTime.Now));
iedServer.UpdateFloatAttributeValue(ggio1AnIn1magF, floatVal);
Thread.Sleep(100);
}
iedServer.Stop();
Console.WriteLine("Server stopped");
}
else
{
Console.WriteLine("Failed to start server");
}
iedServer.Destroy();
}
}
}

@ -0,0 +1,481 @@
MODEL(simpleIO){
LD(GenericIO){
LN(GGIO1){
DO(Mod 0){
DA(stVal 0 12 0 17 0)=1;
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
DA(ctlModel 0 12 4 16 0)=0;
}
DO(Beh 0){
DA(stVal 0 12 0 17 0)=1;
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(Health 0){
DA(stVal 0 12 0 17 0)=1;
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(NamPlt 0){
DA(vendor 0 20 5 16 0);
DA(swRev 0 20 5 16 0);
DA(d 0 20 5 16 0);
}
DO(AnIn1 0){
DA(mag 0 27 1 17 0){
DA(f 0 10 1 16 0);
}
DA(q 0 23 1 18 0);
DA(t 0 22 1 16 0);
}
DO(AnIn2 0){
DA(mag 0 27 1 17 0){
DA(f 0 10 1 16 0);
}
DA(q 0 23 1 18 0);
DA(t 0 22 1 16 0);
}
DO(AnIn3 0){
DA(mag 0 27 1 17 0){
DA(f 0 10 1 16 0);
}
DA(q 0 23 1 18 0);
DA(t 0 22 1 16 0);
}
DO(AnIn4 0){
DA(mag 0 27 1 17 0){
DA(f 0 10 1 16 0);
}
DA(q 0 23 1 18 0);
DA(t 0 22 1 16 0);
}
DO(SPCSO1 0){
DA(origin 0 27 0 16 0){
DA(orCat 0 12 0 16 0);
DA(orIdent 0 13 0 16 0);
}
DA(ctlNum 0 6 0 16 0);
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
DA(ctlModel 0 12 4 16 0)=1;
DA(Oper 0 27 12 16 0){
DA(ctlVal 0 0 12 16 0);
DA(origin 0 27 12 16 0){
DA(orCat 0 12 12 16 0);
DA(orIdent 0 13 12 16 0);
}
DA(ctlNum 0 6 12 16 0);
DA(T 0 22 12 16 0);
DA(Test 0 0 12 16 0);
DA(Check 0 24 12 16 0);
}
}
DO(SPCSO2 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(Oper 0 27 12 16 0){
DA(ctlVal 0 0 12 16 0);
DA(origin 0 27 12 16 0){
DA(orCat 0 12 12 16 0);
DA(orIdent 0 13 12 16 0);
}
DA(ctlNum 0 6 12 16 0);
DA(T 0 22 12 16 0);
DA(Test 0 0 12 16 0);
DA(Check 0 24 12 16 0);
}
DA(ctlModel 0 12 4 16 0)=1;
DA(t 0 22 0 16 0);
}
DO(SPCSO3 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(Oper 0 27 12 16 0){
DA(ctlVal 0 0 12 16 0);
DA(origin 0 27 12 16 0){
DA(orCat 0 12 12 16 0);
DA(orIdent 0 13 12 16 0);
}
DA(ctlNum 0 6 12 16 0);
DA(T 0 22 12 16 0);
DA(Test 0 0 12 16 0);
DA(Check 0 24 12 16 0);
}
DA(ctlModel 0 12 4 16 0)=1;
DA(t 0 22 0 16 0);
}
DO(SPCSO4 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(Oper 0 27 12 16 0){
DA(ctlVal 0 0 12 16 0);
DA(origin 0 27 12 16 0){
DA(orCat 0 12 12 16 0);
DA(orIdent 0 13 12 16 0);
}
DA(ctlNum 0 6 12 16 0);
DA(T 0 22 12 16 0);
DA(Test 0 0 12 16 0);
DA(Check 0 24 12 16 0);
}
DA(ctlModel 0 12 4 16 0)=1;
DA(t 0 22 0 16 0);
}
DO(Ind1 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(Ind2 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(Ind3 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(Ind4 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
}
LN(LPHD1){
DO(PhyNam 0){
DA(vendor 0 20 5 16 0);
}
DO(PhyHealth 0){
DA(stVal 0 12 0 17 0)=1;
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(Proxy 0){
DA(stVal 0 0 0 17 0);
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
}
LN(LLN0){
SG(1 5)
DO(Mod 0){
DA(stVal 0 12 0 17 0)=1;
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
DA(ctlModel 0 12 4 16 0)=0;
}
DO(Beh 0){
DA(stVal 0 12 0 17 0)=1;
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(Health 0){
DA(stVal 0 12 0 17 0)=1;
DA(q 0 23 0 18 0);
DA(t 0 22 0 16 0);
}
DO(NamPlt 0){
DA(vendor 0 20 5 16 0)="MZ Automation";
DA(swRev 0 20 5 16 0)="1.3.0";
DA(d 0 20 5 16 0)="libiec61850 server example";
DA(configRev 0 20 5 16 0);
DA(ldNs 0 20 11 16 0);
}
DS(Events){
DE(GGIO1$ST$SPCSO1$stVal);
DE(GGIO1$ST$SPCSO2$stVal);
DE(GGIO1$ST$SPCSO3$stVal);
DE(GGIO1$ST$SPCSO4$stVal);
}
DS(Events2){
DE(GGIO1$ST$SPCSO1);
DE(GGIO1$ST$SPCSO2);
DE(GGIO1$ST$SPCSO3);
DE(GGIO1$ST$SPCSO4);
}
DS(Measurements){
DE(GGIO1$MX$AnIn1$mag$f);
DE(GGIO1$MX$AnIn1$q);
DE(GGIO1$MX$AnIn2$mag$f);
DE(GGIO1$MX$AnIn2$q);
DE(GGIO1$MX$AnIn3$mag$f);
DE(GGIO1$MX$AnIn3$q);
DE(GGIO1$MX$AnIn4$mag$f);
DE(GGIO1$MX$AnIn4$q);
}
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);
}
SMVC(SMV1 xxxxMUnn01 Events 0 0 0 1 0 ){
PA(4 123 4000 010CCD040001);
}
SMVC(SMV2 null Measurements 0 0 0 0 0 ){
PA(4 123 4000 010CCD040001);
}
}
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);
}
}
}
}

@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Remove="model.cfg" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="model.cfg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
</Project>

@ -0,0 +1,660 @@
<?xml version="1.0" encoding="UTF-8"?>
<SCL xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://www.iec.ch/61850/2003/SCL" xsi:schemaLocation="http://www.iec.ch/61850/2003/SCL SCL.xsd" version="2007" revision="B">
<Header id="" nameStructure="IEDName">
</Header>
<Communication>
<SubNetwork name="subnetwork1" type="8-MMS" Name="subnetwork1">
<Text>Station bus</Text>
<BitRate unit="b/s">10</BitRate>
<ConnectedAP iedName="simpleIO" apName="accessPoint1">
<Address>
<P type="IP">0.0.0.0</P>
<P type="IP-SUBNET">255.255.255.0</P>
<P type="IP-GATEWAY">192.168.2.1</P>
<P type="OSI-AP-Title">1,3,9999,33</P>
<P type="OSI-AE-Qualifier">33</P>
<P type="OSI-PSEL">00000001</P>
<P type="OSI-SSEL">0001</P>
<P type="OSI-TSEL">0001</P>
<P type="MMS-Port">102</P>
</Address>
<GSE ldInst="GenericIO" cbName="gcbEvents">
<Address>
<P type="VLAN-ID">1</P>
<P type="VLAN-PRIORITY">4</P>
<P type="MAC-Address">01-0c-cd-01-00-01</P>
<P type="APPID">1000</P>
</Address>
<MinTime>1000</MinTime>
<MaxTime>3000</MaxTime>
</GSE>
<SMV cbName="MSVCB01" ldInst="GenericIO">
<Address>
<P type="MAC-Address">01-0C-CD-04-00-01</P>
<P type="APPID">4000</P>
<P type="VLAN-PRIORITY">4</P>
<P type="VLAN-ID">123</P>
</Address>
</SMV>
</ConnectedAP>
</SubNetwork>
</Communication>
<IED name="simpleIO">
<Services>
<DynAssociation />
<GetDirectory />
<GetDataObjectDefinition />
<GetDataSetValue />
<DataSetDirectory />
<ReadWrite />
<GetCBValues />
<ConfLNs fixPrefix="true" fixLnInst="true" />
<GOOSE max="5" />
<GSSE max="5" />
<FileHandling />
<GSEDir />
<TimerActivatedControl />
</Services>
<AccessPoint name="accessPoint1">
<Server>
<Authentication />
<LDevice inst="GenericIO">
<LN lnClass="LPHD" lnType="LPHD1" inst="1" prefix="">
<DOI name="PhyHealth">
<DAI name="stVal">
<Val>ok</Val>
</DAI>
</DOI>
</LN>
<LN lnClass="GGIO" lnType="GGIO1" inst="1" prefix="">
<DOI name="Mod">
<DAI name="stVal">
<Val>on</Val>
</DAI>
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
<DOI name="Beh">
<DAI name="stVal">
<Val>on</Val>
</DAI>
</DOI>
<DOI name="Health">
<DAI name="stVal">
<Val>ok</Val>
</DAI>
</DOI>
<DOI name="SPCSO1">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO2">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO3">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
<DOI name="SPCSO4">
<DAI name="ctlModel">
<Val>direct-with-normal-security</Val>
</DAI>
</DOI>
</LN>
<LN0 lnClass="LLN0" lnType="LLN01" inst="">
<DataSet name="Events" desc="Events">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" daName="stVal" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" daName="stVal" />
</DataSet>
<DataSet name="Events2" desc="Events2">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO1" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO2" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO3" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="ST" lnInst="1" doName="SPCSO4" />
</DataSet>
<DataSet name="Measurements" desc="Measurements">
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn1" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn1" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn2" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn2" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn3" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn3" daName="q" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn4" daName="mag.f" />
<FCDA ldInst="GenericIO" lnClass="GGIO" fc="MX" lnInst="1" doName="AnIn4" daName="q" />
</DataSet>
<DataSet name="ServiceTracking">
<FCDA doName="SpcTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="DpcTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="IncTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="BscTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="UrcbTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="BrcbTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="GocbTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="SgcbTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
<FCDA doName="LocbTrk" fc="SR" ldInst="GenericIO" lnClass="LTRK" lnInst="1" />
</DataSet>
<ReportControl name="EventsRCB" confRev="1" datSet="Events2" rptID="Events1" buffered="false" intgPd="1000" bufTime="50">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" configRef="true" />
<RptEnabled max="1" />
</ReportControl>
<ReportControl name="EventsIndexed" indexed="true" confRev="1" datSet="Events" rptID="Events2" buffered="false" intgPd="1000" bufTime="50">
<TrgOps period="true" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" configRef="true" />
<RptEnabled max="3" />
</ReportControl>
<ReportControl name="Measurements" indexed="true" confRev="1" datSet="Measurements" rptID="Measurements" buffered="true" intgPd="1000" bufTime="50">
<TrgOps period="false" />
<OptFields seqNum="true" timeStamp="true" dataSet="true" reasonCode="true" entryID="true" configRef="true" />
<RptEnabled max="3" />
</ReportControl>
<ReportControl buffered="true" confRev="1" datSet="ServiceTracking" name="brcbServiceTracking" rptID="ServiceTracking">
<TrgOps dchg="true" qchg="true" />
<OptFields configRef="true" entryID="true" reasonCode="true" />
<RptEnabled max="3" />
</ReportControl>
<LogControl name="EventLog" datSet="Events" logName="EventLog" logEna="true">
<TrgOps dchg="true" qchg="true" />
</LogControl>
<LogControl name="GeneralLog" datSet="" logName="">
<TrgOps dchg="true" qchg="true" />
</LogControl>
<Log />
<Log name="EventLog" />
<GSEControl appID="events" name="gcbEvents" type="GOOSE" datSet="Events" confRev="3" />
<SampledValueControl name="MSVCB01" smvID="xxxxMUnn01" datSet="Events">
<SmvOpts refreshTime="true" />
</SampledValueControl>
<SettingControl desc="parameter set" numOfSGs="5" actSG="1" />
<DOI name="Mod">
<DAI name="stVal">
<Val>on</Val>
</DAI>
<DAI name="ctlModel">
<Val>status-only</Val>
</DAI>
</DOI>
<DOI name="Beh">
<DAI name="stVal">
<Val>on</Val>
</DAI>
</DOI>
<DOI name="Health">
<DAI name="stVal">
<Val>ok</Val>
</DAI>
</DOI>
<DOI name="NamPlt">
<DAI name="vendor">
<Val>MZ Automation</Val>
</DAI>
<DAI name="swRev">
<Val>1.3.0</Val>
</DAI>
<DAI name="d">
<Val>libiec61850 server example</Val>
</DAI>
</DOI>
</LN0>
<LN desc="example for setting groups" inst="1" lnClass="PTOC" lnType="PTOC1" />
<LN desc="Service Tracking Information" inst="1" lnClass="LTRK" lnType="myLTRK" />
</LDevice>
</Server>
</AccessPoint>
</IED>
<DataTypeTemplates>
<LNodeType id="LLN01" lnClass="LLN0">
<DO name="Mod" type="ENC_1_Mod" />
<DO name="Beh" type="ENS_1_Beh" />
<DO name="Health" type="ENS_2_Health" />
<DO name="NamPlt" type="LPL_1_NamPlt" />
</LNodeType>
<LNodeType id="LPHD1" lnClass="LPHD">
<DO name="PhyNam" type="DPL_1_PhyNam" />
<DO name="PhyHealth" type="ENS_2_Health" />
<DO name="Proxy" type="SPS_1_Proxy" />
</LNodeType>
<LNodeType id="GGIO1" lnClass="GGIO">
<DO name="Mod" type="ENC_1_Mod" />
<DO name="Beh" type="ENS_1_Beh" />
<DO name="Health" type="ENS_2_Health" />
<DO name="NamPlt" type="LPL_2_NamPlt" />
<DO name="AnIn1" type="MV_1_AnIn1" />
<DO name="AnIn2" type="MV_1_AnIn1" />
<DO name="AnIn3" type="MV_1_AnIn1" />
<DO name="AnIn4" type="MV_1_AnIn1" />
<DO name="SPCSO1" type="SPC_1_SPCSO1" />
<DO name="SPCSO2" type="SPC_2" />
<DO name="SPCSO3" type="SPC_2" />
<DO name="SPCSO4" type="SPC_2" />
<DO name="Ind1" type="SPS_1_Proxy" />
<DO name="Ind2" type="SPS_1_Proxy" />
<DO name="Ind3" type="SPS_1_Proxy" />
<DO name="Ind4" type="SPS_1_Proxy" />
</LNodeType>
<LNodeType id="PTOC1" lnClass="PTOC">
<DO name="Mod" type="ENC_1_Mod" />
<DO name="Beh" type="ENS_1_Beh" />
<DO name="Str" type="ACD_Str" />
<DO name="Op" type="ACT_Op" />
<DO name="StrVal" type="ASG_SE" />
<DO name="OpDlTmms" type="ING_SE" />
<DO name="RsDlTmms" type="ING_SE" />
<DO name="RstTms" type="ING_SE" />
</LNodeType>
<LNodeType id="myLTRK" lnClass="LTRK">
<DO name="Beh" type="myENS_Beh" desc="" />
<DO name="SpcTrk" type="myCTS_Bool" desc="" />
<DO name="DpcTrk" type="myCTS_Bool" desc="" />
<DO name="IncTrk" type="myCTS_Int32" desc="" />
<DO name="BscTrk" type="myCTS_BSC" desc="" />
<DO name="UrcbTrk" type="myUTS" desc="" />
<DO name="BrcbTrk" type="myBTS" desc="" />
<DO name="GocbTrk" type="myGTS" desc="" />
<DO name="SgcbTrk" type="mySTS" desc="" />
<DO name="LocbTrk" type="myLTS" desc="" />
</LNodeType>
<DOType cdc="ACD" id="ACD_Str">
<DA bType="BOOLEAN" dchg="true" fc="ST" name="general" />
<DA bType="Enum" dchg="true" fc="ST" name="dirGeneral" type="dirGeneral" />
<DA bType="Quality" fc="ST" name="q" qchg="true" />
<DA bType="Timestamp" fc="ST" name="t" />
</DOType>
<DOType cdc="ACT" id="ACT_Op">
<DA bType="BOOLEAN" dchg="true" fc="ST" name="general" />
<DA bType="Quality" fc="ST" name="q" qchg="true" />
<DA bType="Timestamp" fc="ST" name="t" />
</DOType>
<DOType cdc="ASG" id="ASG_SE">
<DA bType="Struct" fc="SE" name="setMag" type="AnalogueValue_1" />
</DOType>
<DOType id="ING_SE" cdc="ING">
<DA name="setVal" bType="INT32" fc="SE" dchg="true" />
</DOType>
<DOType id="myCTS_Bool" cdc="CTS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="ctlVal" bType="BOOLEAN" fc="SR" desc="" />
<!-- <DA name="operTm" bType="Timestamp" fc="SR" desc=""/> -->
<DA name="origin" bType="Struct" type="Originator_1" fc="SR" desc="" />
<DA name="ctlNum" bType="INT8U" fc="SR" desc="" />
<DA name="T" bType="Timestamp" fc="SR" desc="" />
<DA name="Test" bType="BOOLEAN" fc="SR" desc="" />
<DA name="Check" bType="Check" fc="SR" desc="" />
<DA name="respAddCause" bType="Enum" type="AddCause" fc="SR" desc="" />
</DOType>
<DOType id="myCTS_Int32" cdc="CTS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="ctlVal" bType="INT32" fc="SR" desc="TINT32 control value" />
<!-- <DA name="operTm" bType="Timestamp" fc="SR" desc=""/> -->
<DA name="origin" bType="Struct" type="Originator_1" fc="SR" desc="" />
<DA name="ctlNum" bType="INT8U" fc="SR" desc="" />
<DA name="T" bType="Timestamp" fc="SR" desc="" />
<DA name="Test" bType="BOOLEAN" fc="SR" desc="" />
<DA name="Check" bType="Check" fc="SR" desc="" />
<DA name="respAddCause" bType="Enum" type="AddCause" fc="SR" desc="" />
</DOType>
<DOType id="myCTS_BSC" cdc="CTS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="ctlVal" bType="Tcmd" fc="SR" desc="" />
<!-- <DA name="operTm" bType="Timestamp" fc="SR" desc=""/> -->
<DA name="origin" bType="Struct" type="Originator_1" fc="SR" desc="" />
<DA name="ctlNum" bType="INT8U" fc="SR" desc="" />
<DA name="T" bType="Timestamp" fc="SR" desc="" />
<DA name="Test" bType="BOOLEAN" fc="SR" desc="" />
<DA name="Check" bType="Check" fc="SR" desc="" />
<DA name="respAddCause" bType="Enum" type="AddCause" fc="SR" desc="" />
</DOType>
<DOType id="myUTS" cdc="UTS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="rptID" bType="VisString129" fc="SR" desc="" />
<DA name="rptEna" bType="BOOLEAN" fc="SR" desc="" />
<DA name="resv" bType="BOOLEAN" fc="SR" desc="" />
<DA name="datSet" bType="ObjRef" fc="SR" desc="" />
<DA name="confRev" bType="INT32U" fc="SR" desc="" />
<DA name="optFlds" bType="OptFlds" fc="SR" desc="" />
<DA name="bufTm" bType="INT32U" fc="SR" desc="" />
<DA name="sqNum" bType="INT8U" fc="SR" desc="" />
<DA name="trgOps" bType="TrgOps" fc="SR" desc="" />
<DA name="intgPd" bType="INT32U" fc="SR" desc="" />
<DA name="gi" bType="BOOLEAN" fc="SR" desc="" />
</DOType>
<DOType id="myBTS" cdc="BTS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="rptID" bType="VisString129" fc="SR" desc="" />
<DA name="rptEna" bType="BOOLEAN" fc="SR" desc="" />
<DA name="datSet" bType="ObjRef" fc="SR" desc="" />
<DA name="confRev" bType="INT32U" fc="SR" desc="" />
<DA name="optFlds" bType="OptFlds" fc="SR" desc="" />
<DA name="bufTm" bType="INT32U" fc="SR" desc="" />
<DA name="sqNum" bType="INT16U" fc="SR" desc="" />
<DA name="trgOps" bType="TrgOps" fc="SR" desc="" />
<DA name="intgPd" bType="INT32U" fc="SR" desc="" />
<DA name="gi" bType="BOOLEAN" fc="SR" desc="" />
<DA name="purgeBuf" bType="BOOLEAN" fc="SR" desc="" />
<DA name="entryID" bType="EntryID" fc="SR" desc="" />
<DA name="timeOfEntry" bType="EntryTime" fc="SR" desc="" />
<DA name="resvTms" bType="INT16" fc="SR" desc="" />
</DOType>
<DOType id="myGTS" cdc="GTS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="goEna" bType="BOOLEAN" fc="SR" desc="" />
<DA name="goID" bType="VisString129" fc="SR" desc="" />
<DA name="datSet" bType="ObjRef" fc="SR" desc="" />
<DA name="confRev" bType="INT32U" fc="SR" desc="" />
<DA name="ndsCom" bType="BOOLEAN" fc="SR" desc="" />
<DA name="dstAddress" bType="PhyComAddr" fc="SR" desc="" />
</DOType>
<DOType id="mySTS" cdc="STS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="numOfSG" bType="INT8U" fc="SR" desc="" />
<DA name="actSG" bType="INT8U" fc="SR" desc="" />
<DA name="editSG" bType="INT8U" fc="SR" desc="" />
<DA name="cnfEdit" bType="BOOLEAN" fc="SR" desc="" />
<DA name="lActTm" bType="Timestamp" fc="SR" desc="" />
<DA name="resvTms" bType="INT16U" fc="SR" desc="" />
</DOType>
<DOType id="myLTS" cdc="LTS" desc="">
<DA name="objRef" bType="ObjRef" fc="SR" desc="" dupd="true" />
<DA name="serviceType" bType="Enum" type="ServiceType" fc="SR" desc="" />
<DA name="errorCode" bType="Enum" type="ServiceError" fc="SR" desc="" />
<DA name="originatorID" bType="Octet64" fc="SR" desc="" />
<DA name="t" bType="Timestamp" fc="SR" desc="" />
<DA name="d" bType="VisString255" fc="DC" desc="" />
<DA name="dU" bType="Unicode255" fc="DC" desc="" />
<DA name="cdcNs" bType="VisString255" fc="EX" desc="" />
<DA name="cdcName" bType="VisString255" fc="EX" desc="" />
<DA name="dataNs" bType="VisString255" fc="EX" desc="" />
<DA name="logEna" bType="BOOLEAN" fc="SR" desc="" />
<DA name="datSet" bType="ObjRef" fc="SR" desc="" />
<DA name="bufTm" bType="INT32U" fc="SR" desc="" />
<DA name="trgOps" bType="TrgOps" fc="SR" desc="" />
<DA name="intgPd" bType="INT32U" fc="SR" desc="" />
<DA name="logRef" bType="ObjRef" fc="SR" desc="" />
</DOType>
<DOType id="ENC_1_Mod" cdc="ENC">
<DA name="stVal" bType="Enum" type="Beh" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
</DOType>
<DOType id="ENS_1_Beh" cdc="ENS">
<DA name="stVal" bType="Enum" type="Beh" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="myENS_Beh" cdc="INS">
<DA name="stVal" bType="Enum" type="Beh" dchg="true" fc="ST" />
<DA name="q" bType="Quality" qchg="true" fc="ST" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="ENS_2_Health" cdc="ENS">
<DA name="stVal" bType="Enum" type="HealthKind" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="LPL_1_NamPlt" cdc="LPL">
<DA name="vendor" bType="VisString255" fc="DC" />
<DA name="swRev" bType="VisString255" fc="DC" />
<DA name="d" bType="VisString255" fc="DC" />
<DA name="configRev" bType="VisString255" fc="DC" />
<DA name="ldNs" bType="VisString255" fc="EX" />
</DOType>
<DOType id="DPL_1_PhyNam" cdc="DPL">
<DA name="vendor" bType="VisString255" fc="DC" />
</DOType>
<DOType id="SPS_1_Proxy" cdc="SPS">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DOType id="LPL_2_NamPlt" cdc="LPL">
<DA name="vendor" bType="VisString255" fc="DC" />
<DA name="swRev" bType="VisString255" fc="DC" />
<DA name="d" bType="VisString255" fc="DC" />
</DOType>
<DOType id="MV_1_AnIn1" cdc="MV">
<DA name="mag" type="AnalogueValue_1" bType="Struct" fc="MX" dchg="true" />
<DA name="q" bType="Quality" fc="MX" qchg="true" />
<DA name="t" bType="Timestamp" fc="MX" />
</DOType>
<DOType id="SPC_1_SPCSO1" cdc="SPC">
<DA name="origin" fc="ST" type="Originator_1" bType="Struct" />
<DA name="ctlNum" fc="ST" bType="INT8U" />
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="t" bType="Timestamp" fc="ST" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
</DOType>
<DOType id="SPC_2" cdc="SPC">
<DA name="stVal" bType="BOOLEAN" fc="ST" dchg="true" />
<DA name="q" bType="Quality" fc="ST" qchg="true" />
<DA name="Oper" type="SPCOperate_1" bType="Struct" fc="CO" />
<DA name="ctlModel" type="CtlModels" bType="Enum" fc="CF" />
<DA name="t" bType="Timestamp" fc="ST" />
</DOType>
<DAType id="AnalogueValue_1">
<BDA name="f" bType="FLOAT32" />
</DAType>
<DAType id="Originator_1">
<BDA name="orCat" type="OrCat" bType="Enum" />
<BDA name="orIdent" bType="Octet64" />
</DAType>
<DAType id="SPCOperate_1">
<BDA name="ctlVal" bType="BOOLEAN" />
<BDA name="origin" type="Originator_1" bType="Struct" />
<BDA name="ctlNum" bType="INT8U" />
<BDA name="T" bType="Timestamp" />
<BDA name="Test" bType="BOOLEAN" />
<BDA name="Check" bType="Check" />
</DAType>
<EnumType id="AddCause">
<EnumVal ord="0">Unknown</EnumVal>
<EnumVal ord="1">Not-supported</EnumVal>
<EnumVal ord="2">Blocked-by-switching-hierarchy</EnumVal>
<EnumVal ord="3">Select-failed</EnumVal>
<EnumVal ord="4">Invalid-position</EnumVal>
<EnumVal ord="5">Position-reached</EnumVal>
<EnumVal ord="6">Parameter-change-in-execution</EnumVal>
<EnumVal ord="7">Step-limit</EnumVal>
<EnumVal ord="8">Blocked-by-Mode</EnumVal>
<EnumVal ord="9">Blocked-by-process</EnumVal>
<EnumVal ord="10">Blocked-by-interlocking</EnumVal>
<EnumVal ord="11">Blocked-by-synchrocheck</EnumVal>
<EnumVal ord="12">Command-already-in-execution</EnumVal>
<EnumVal ord="13">Blocked-by-health</EnumVal>
<EnumVal ord="14">1-of-n-control</EnumVal>
<EnumVal ord="15">Abortion-by-cancel</EnumVal>
<EnumVal ord="16">Time-limit-over</EnumVal>
<EnumVal ord="17">Abortion-by-trip</EnumVal>
<EnumVal ord="18">Object-not-selected</EnumVal>
<EnumVal ord="19">Object-already-selected</EnumVal>
<EnumVal ord="20">No-access-authority</EnumVal>
<EnumVal ord="21">Ended-with-overshoot</EnumVal>
<EnumVal ord="22">Abortion-due-to-deviation</EnumVal>
<EnumVal ord="23">Abortion-by-communication-loss </EnumVal>
<EnumVal ord="24">Blocked-by-command</EnumVal>
<EnumVal ord="25">None</EnumVal>
<EnumVal ord="26">Inconsistent-parameters</EnumVal>
<EnumVal ord="27">Locked-by-other-client</EnumVal>
</EnumType>
<EnumType id="Beh">
<EnumVal ord="1">on</EnumVal>
<EnumVal ord="2">blocked</EnumVal>
<EnumVal ord="3">test</EnumVal>
<EnumVal ord="4">test/blocked</EnumVal>
<EnumVal ord="5">off</EnumVal>
</EnumType>
<EnumType id="HealthKind">
<EnumVal ord="1">ok</EnumVal>
<EnumVal ord="2">warning</EnumVal>
<EnumVal ord="3">alarm</EnumVal>
</EnumType>
<EnumType id="CtlModels">
<EnumVal ord="0">status-only</EnumVal>
<EnumVal ord="1">direct-with-normal-security</EnumVal>
<EnumVal ord="2">sbo-with-normal-security</EnumVal>
<EnumVal ord="3">direct-with-enhanced-security</EnumVal>
<EnumVal ord="4">sbo-with-enhanced-security</EnumVal>
</EnumType>
<EnumType id="OrCat">
<EnumVal ord="0">not-supported</EnumVal>
<EnumVal ord="1">bay-control</EnumVal>
<EnumVal ord="2">station-control</EnumVal>
<EnumVal ord="3">remote-control</EnumVal>
<EnumVal ord="4">automatic-bay</EnumVal>
<EnumVal ord="5">automatic-station</EnumVal>
<EnumVal ord="6">automatic-remote</EnumVal>
<EnumVal ord="7">maintenance</EnumVal>
<EnumVal ord="8">process</EnumVal>
</EnumType>
<EnumType id="ServiceError">
<EnumVal ord="0">no-error</EnumVal>
<EnumVal ord="1">instance-not-available</EnumVal>
<EnumVal ord="2">instance-in-use</EnumVal>
<EnumVal ord="3">access-violation</EnumVal>
<EnumVal ord="4">access-not-allowed-in-current-state</EnumVal>
<EnumVal ord="5">parameter-value-inappropriate</EnumVal>
<EnumVal ord="6">parameter-value-inconsistent</EnumVal>
<EnumVal ord="7">class-not-supported</EnumVal>
<EnumVal ord="8">instance-locked-by-other-client</EnumVal>
<EnumVal ord="9">control-must-be-selected</EnumVal>
<EnumVal ord="10">type-conflict</EnumVal>
<EnumVal ord="11">failed-due-to-communications-constraint</EnumVal>
<EnumVal ord="12">failed-due-to-server-constraint</EnumVal>
</EnumType>
<EnumType id="ServiceType">
<EnumVal ord="0">Unknown</EnumVal>
<EnumVal ord="1">Associate</EnumVal>
<EnumVal ord="2">Abort</EnumVal>
<EnumVal ord="3">Release</EnumVal>
<EnumVal ord="4">GetServerDirectory</EnumVal>
<EnumVal ord="5">GetLogicalDeviceDirectory</EnumVal>
<EnumVal ord="6">GetAllDataValues</EnumVal>
<EnumVal ord="7">GetDataValues</EnumVal>
<EnumVal ord="8">SetDataValues</EnumVal>
<EnumVal ord="9">GetDataDirectory</EnumVal>
<EnumVal ord="10">GetDataDefinition</EnumVal>
<EnumVal ord="11">GetDataSetValues</EnumVal>
<EnumVal ord="12">SetDataSetValues</EnumVal>
<EnumVal ord="13">CreateDataSet</EnumVal>
<EnumVal ord="14">DeleteDataSet</EnumVal>
<EnumVal ord="15">GetDataSetDirectory</EnumVal>
<EnumVal ord="16">SelectActiveSG</EnumVal>
<EnumVal ord="17">SelectEditSG</EnumVal>
<EnumVal ord="18">SetEditSGValue</EnumVal>
<EnumVal ord="19">ConfirmEditSGValues</EnumVal>
<EnumVal ord="20">GetEditSGValue</EnumVal>
<EnumVal ord="21">GetSGCBValues</EnumVal>
<EnumVal ord="22">Report</EnumVal>
<EnumVal ord="23">GetBRCBValues</EnumVal>
<EnumVal ord="24">SetBRCBValues</EnumVal>
<EnumVal ord="25">GetURCBValues</EnumVal>
<EnumVal ord="26">SetURCBValues</EnumVal>
<EnumVal ord="27">GetLCBValues</EnumVal>
<EnumVal ord="28">SetLCBValues</EnumVal>
<EnumVal ord="29">QueryLogByTime</EnumVal>
<EnumVal ord="30">QueryLogAfter</EnumVal>
<EnumVal ord="31">GetLogStatus</EnumVal>
<EnumVal ord="32">SendGOOSEMessage</EnumVal>
<EnumVal ord="33">GetGoCBValues</EnumVal>
<EnumVal ord="34">SetGoCBValues</EnumVal>
<EnumVal ord="35">GetGoReference</EnumVal>
<EnumVal ord="36">GetGOOSEElementNumber</EnumVal>
<EnumVal ord="37">SendMSVMessage</EnumVal>
<EnumVal ord="38">GetMSVCBValues</EnumVal>
<EnumVal ord="39">SetMSVCBValues</EnumVal>
<EnumVal ord="40">SendUSVMessage</EnumVal>
<EnumVal ord="41">GetUSVCBValues</EnumVal>
<EnumVal ord="42">SetUSVCBValues</EnumVal>
<EnumVal ord="43">Select</EnumVal>
<EnumVal ord="44">SelectWithValue</EnumVal>
<EnumVal ord="45">Cancel</EnumVal>
<EnumVal ord="46">Operate</EnumVal>
<EnumVal ord="47">CommandTermination</EnumVal>
<EnumVal ord="48">TimeActivatedOperate</EnumVal>
<EnumVal ord="49">GetFile</EnumVal>
<EnumVal ord="50">SetFile</EnumVal>
<EnumVal ord="51">DeleteFile</EnumVal>
<EnumVal ord="52">GetFileAttributValues</EnumVal>
<EnumVal ord="53">TimeSynchronisation</EnumVal>
<EnumVal ord="54">InternalChange</EnumVal>
</EnumType>
<EnumType id="dirGeneral">
<EnumVal ord="0">unknown</EnumVal>
<EnumVal ord="1">forward</EnumVal>
<EnumVal ord="2">backward</EnumVal>
<EnumVal ord="3">both</EnumVal>
</EnumType>
</DataTypeTemplates>
</SCL>

@ -1,16 +1,6 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("server_goose_publisher")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("server_goose_publisher")]
[assembly: AssemblyCopyright("Copyright © 2021")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -21,16 +11,3 @@ using System.Runtime.InteropServices;
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("c14bb883-86b8-401c-b3d6-b655f55f3298")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

@ -1,63 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{C14BB883-86B8-401C-B3D6-B655F55F3298}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>server_goose_publisher</RootNamespace>
<AssemblyName>server_goose_publisher</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<Deterministic>true</Deterministic>
<AssemblyTitle>server_goose_publisher</AssemblyTitle>
<Product>server_goose_publisher</Product>
<Copyright>Copyright © 2021</Copyright>
<AssemblyVersion>1.0.0.0</AssemblyVersion>
<FileVersion>1.0.0.0</FileVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ServerExampleWithGoosePublisher.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="simpleIO_direct_control_goose.cfg">
<None Update="simpleIO_direct_control_goose.cfg">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="System.Data.DataSetExtensions" Version="4.5.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{c35d624e-5506-4560-8074-1728f1fa1a4d}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("sv_subscriber")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("mzillgit")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,45 +1,22 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{44651D2D-3252-4FD5-8B8B-5552DBE1B499}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>sv_subscriber</RootNamespace>
<AssemblyName>sv_subscriber</AssemblyName>
<TargetFrameworkVersion>v4.0</TargetFrameworkVersion>
<TargetFrameworkProfile />
<AssemblyTitle>sv_subscriber</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
</Project>
</Project>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
@ -7,6 +7,8 @@
<OutputType>Library</OutputType>
<RootNamespace>tests</RootNamespace>
<AssemblyName>tests</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -17,6 +19,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>none</DebugType>
@ -25,6 +28,7 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<ConsolePause>false</ConsolePause>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Compile Include="Test.cs" />

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("tls_client_example")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("mzillgit")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,54 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{6734BF52-2D0D-476B-8EA2-C9C2D1D69B03}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>tls_client_example</RootNamespace>
<AssemblyName>tls_client_example</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AssemblyTitle>tls_client_example</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="client1.cer">
<None Update="client1.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="client1-key.pem">
<None Update="client1-key.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="root.cer">
<None Update="root.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

@ -1,24 +1,8 @@
using System.Reflection;
using System.Runtime.CompilerServices;
// Information about this assembly is defined by the following attributes.
// Change them to the values specific to your project.
[assembly: AssemblyTitle ("tls_server_example")]
[assembly: AssemblyDescription ("")]
[assembly: AssemblyConfiguration ("")]
[assembly: AssemblyCompany ("")]
[assembly: AssemblyProduct ("")]
[assembly: AssemblyCopyright ("mzillgit")]
[assembly: AssemblyTrademark ("")]
[assembly: AssemblyCulture ("")]
// The assembly version has the format "{Major}.{Minor}.{Build}.{Revision}".
// The form "{Major}.{Minor}.*" will automatically update the build and revision,
// and "{Major}.{Minor}.{Build}.*" will update just the revision.
[assembly: AssemblyVersion ("1.0.*")]
// The following attributes are used to specify the signing key for the assembly,
// if desired. See the Mono documentation for more information about signing.

@ -1,57 +1,36 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B63F7A81-1D3A-4F2F-A7C2-D6F77E5BD307}</ProjectGuid>
<TargetFramework>net8.0</TargetFramework>
<OutputType>Exe</OutputType>
<RootNamespace>tls_server_example</RootNamespace>
<AssemblyName>tls_server_example</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<AssemblyTitle>tls_server_example</AssemblyTitle>
<Copyright>mzillgit</Copyright>
<AssemblyVersion>1.0.%2a</AssemblyVersion>
<Deterministic>false</Deterministic>
<Deterministic>false</Deterministic>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug</OutputPath>
<DefineConstants>DEBUG;</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>full</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release</OutputPath>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Externalconsole>true</Externalconsole>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
<ProjectReference Include="..\IEC61850forCSharp\IEC61850.NET.csproj">
<Project>{C35D624E-5506-4560-8074-1728F1FA1A4D}</Project>
<Name>IEC61850.NET</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="server-key.pem">
<None Update="server-key.pem">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="server.cer">
<None Update="server.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="root.cer">
<None Update="root.cer">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="model.cfg">
<None Update="model.cfg">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

@ -60,7 +60,7 @@ main(int argc, char** argv)
IsoConnectionParameters_setRemoteAddresses(parameters, remotePSelector, remoteSSelector, localTSelector);
IsoConnectionParameters_setLocalAddresses(parameters, localPSelector, localSSelector, remoteTSelector);
char* password = "top secret";
char* password = "user1@testpw";
/* use authentication */
AcseAuthenticationParameter auth = AcseAuthenticationParameter_create();
@ -84,6 +84,8 @@ main(int argc, char** argv)
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
while (true);
IedConnection_destroy(con);
AcseAuthenticationParameter_destroy(auth);

@ -308,6 +308,7 @@ int main(int argc, char** argv)
printf("Failed to send operate %i\n", error);
}
MmsValue_delete(ctlVal);
}
else
{

@ -12,10 +12,10 @@
#include "iec61850_client.h"
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef _WIN32
#include <Windows.h>
#include <windows.h>
#else
#include <libgen.h>
#endif
@ -31,14 +31,16 @@ dirname(char* path)
int len = strlen(path);
int i = 0;
while (i < len) {
while (i < len)
{
if (path[i] == '/' || path[i] == ':' || path[i] == '\\')
lastSep = path + i;
i++;
}
if (lastSep) {
if (lastSep)
{
strcpy(_dirname, path);
_dirname[lastSep - path] = 0;
}
@ -48,7 +50,6 @@ dirname(char* path)
return _dirname;
}
static char _basename[1000];
static char*
@ -59,7 +60,8 @@ basename(char* path)
int len = strlen(path);
int i = 0;
while (i < len) {
while (i < len)
{
if (path[i] == '/' || path[i] == ':' || path[i] == '\\')
lastSep = path + i;
@ -81,7 +83,8 @@ static int tcpPort = 102;
static char* filename = NULL;
static bool singleRequest = false;
typedef enum {
typedef enum
{
FileOperationType_None = 0,
FileOperationType_Dir,
FileOperationType_Info,
@ -92,17 +95,17 @@ typedef enum {
static FileOperationType operation = FileOperationType_None;
static bool
downloadHandler(void* parameter, uint8_t* buffer, uint32_t bytesRead)
{
FILE* fp = (FILE*) parameter;
FILE* fp = (FILE*)parameter;
printf("received %i bytes\n", bytesRead);
if (bytesRead > 0) {
if (fwrite(buffer, bytesRead, 1, fp) != 1) {
if (bytesRead > 0)
{
if (fwrite(buffer, bytesRead, 1, fp) != 1)
{
printf("Failed to write local file!\n");
return false;
}
@ -128,7 +131,6 @@ printHelp()
printf(" set <filename> - set file\n");
}
static int
parseOptions(int argc, char** argv)
{
@ -136,40 +138,51 @@ parseOptions(int argc, char** argv)
int retVal = 0;
while (currentArgc < argc) {
if (strcmp(argv[currentArgc], "-h") == 0) {
while (currentArgc < argc)
{
if (strcmp(argv[currentArgc], "-h") == 0)
{
hostname = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "-p") == 0) {
else if (strcmp(argv[currentArgc], "-p") == 0)
{
tcpPort = atoi(argv[++currentArgc]);
}
else if (strcmp(argv[currentArgc], "-s") == 0) {
else if (strcmp(argv[currentArgc], "-s") == 0)
{
singleRequest = true;
}
else if (strcmp(argv[currentArgc], "del") == 0) {
else if (strcmp(argv[currentArgc], "del") == 0)
{
operation = FileOperationType_Del;
filename = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "dir") == 0) {
else if (strcmp(argv[currentArgc], "dir") == 0)
{
operation = FileOperationType_Dir;
}
else if (strcmp(argv[currentArgc], "subdir") == 0) {
else if (strcmp(argv[currentArgc], "subdir") == 0)
{
operation = FileOperationType_Dir;
filename = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "info") == 0) {
else if (strcmp(argv[currentArgc], "info") == 0)
{
operation = FileOperationType_Info;
filename = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "get") == 0) {
else if (strcmp(argv[currentArgc], "get") == 0)
{
operation = FileOperationType_Get;
filename = argv[++currentArgc];
}
else if (strcmp(argv[currentArgc], "set") == 0) {
else if (strcmp(argv[currentArgc], "set") == 0)
{
operation = FileOperationType_Set;
filename = argv[++currentArgc];
}
else {
else
{
printf("Unknown operation!\n");
return 1;
}
@ -195,22 +208,25 @@ showDirectory(IedConnection con)
else
rootDirectory = IedConnection_getFileDirectory(con, &error, filename);
if (error != IED_ERROR_OK) {
if (error != IED_ERROR_OK)
{
printf("Error retrieving file directory\n");
}
else {
else
{
LinkedList directoryEntry = LinkedList_getNext(rootDirectory);
while (directoryEntry != NULL) {
while (directoryEntry != NULL)
{
FileDirectoryEntry entry = (FileDirectoryEntry) directoryEntry->data;
FileDirectoryEntry entry = (FileDirectoryEntry)directoryEntry->data;
printf("%s %i\n", FileDirectoryEntry_getFileName(entry), FileDirectoryEntry_getFileSize(entry));
directoryEntry = LinkedList_getNext(directoryEntry);
}
LinkedList_destroyDeep(rootDirectory, (LinkedListValueDeleteFunction) FileDirectoryEntry_destroy);
LinkedList_destroyDeep(rootDirectory, (LinkedListValueDeleteFunction)FileDirectoryEntry_destroy);
}
if (moreFollows)
@ -228,10 +244,11 @@ getFile(IedConnection con)
FILE* fp = fopen(localFilename, "wb");
if (fp != NULL) {
if (fp != NULL)
{
/* Download a file from the server */
IedConnection_getFile(con, &error, filename, downloadHandler, (void*) fp);
IedConnection_getFile(con, &error, filename, downloadHandler, (void*)fp);
if (error != IED_ERROR_OK)
printf("Failed to get file!\n");
@ -290,14 +307,16 @@ deleteFile(IedConnection con)
int
main(int argc, char** argv)
{
if (argc < 2) {
if (argc < 2)
{
printHelp();
return 0;
}
parseOptions(argc, argv);
if (operation == FileOperationType_None) {
if (operation == FileOperationType_None)
{
printHelp();
return 0;
}
@ -308,10 +327,10 @@ main(int argc, char** argv)
IedConnection_connect(con, &error, hostname, tcpPort);
if (error == IED_ERROR_OK) {
switch (operation) {
if (error == IED_ERROR_OK)
{
switch (operation)
{
case FileOperationType_Dir:
showDirectory(con);
break;
@ -330,15 +349,13 @@ main(int argc, char** argv)
break;
}
IedConnection_abort(con, &error);
}
else {
else
{
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
IedConnection_destroy(con);
return 0;
}

@ -5,13 +5,12 @@
*/
#include "iec61850_client.h"
#include "hal_thread.h"
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
//#include "hal_thread.h"
static void
printJournalEntries(LinkedList journalEntries)
{
@ -19,8 +18,8 @@ printJournalEntries(LinkedList journalEntries)
LinkedList journalEntriesElem = LinkedList_getNext(journalEntries);
while (journalEntriesElem != NULL) {
while (journalEntriesElem != NULL)
{
MmsJournalEntry journalEntry = (MmsJournalEntry) LinkedList_getData(journalEntriesElem);
MmsValue_printToBuffer(MmsJournalEntry_getEntryID(journalEntry), buf, 1024);
@ -30,8 +29,8 @@ printJournalEntries(LinkedList journalEntries)
LinkedList journalVariableElem = LinkedList_getNext(journalEntry->journalVariables);
while (journalVariableElem != NULL) {
while (journalVariableElem != NULL)
{
MmsJournalVariable journalVariable = (MmsJournalVariable) LinkedList_getData(journalVariableElem);
printf(" variable-tag: %s\n", MmsJournalVariable_getTag(journalVariable));
@ -45,8 +44,9 @@ printJournalEntries(LinkedList journalEntries)
}
}
int main(int argc, char** argv) {
int
main(int argc, char** argv)
{
char* hostname;
int tcpPort = 102;
@ -58,7 +58,7 @@ int main(int argc, char** argv) {
if (argc > 2)
tcpPort = atoi(argv[2]);
char* logRef = "simpleIOGenericIO/LLN0$EventLog";
char* logRef = "TestIEDGenericIO/LLN0$EventLog";
IedClientError error;
@ -66,19 +66,21 @@ int main(int argc, char** argv) {
IedConnection_connect(con, &error, hostname, tcpPort);
if (error == IED_ERROR_OK) {
if (error == IED_ERROR_OK)
{
/* read list of logs in LN (optional - if you don't know the existing logs) */
LinkedList logs = IedConnection_getLogicalNodeDirectory(con, &error, "simpleIOGenericIO/LLN0", ACSI_CLASS_LOG);
if (error == IED_ERROR_OK) {
LinkedList logs = IedConnection_getLogicalNodeDirectory(con, &error, "TestIEDGenericIO/LLN0", ACSI_CLASS_LOG);
if (LinkedList_size(logs) > 0) {
if (error == IED_ERROR_OK)
{
if (LinkedList_size(logs) > 0)
{
printf("Found logs in LN simpleIOGenericIO/LLN0:\n");
LinkedList log = LinkedList_getNext(logs);
while (log != NULL) {
while (log != NULL)
{
char* logName = (char*) LinkedList_getData(log);
printf(" %s\n", logName);
@ -86,18 +88,31 @@ int main(int argc, char** argv) {
log = LinkedList_getNext(log);
}
}
else {
else
{
printf("No logs found\n");
}
LinkedList_destroy(logs);
}
/* read log control block (using the generic read function) */
MmsValue* lcbValue = IedConnection_readObject(con, &error, "simpleIOGenericIO/LLN0.EventLog", IEC61850_FC_LG);
IedConnection_writeBooleanValue(con, &error, "TestIEDGenericIO/LLN0.EventLog.LogEna", IEC61850_FC_LG, true);
if (error == IED_ERROR_OK)
{
printf("Enabled log. Waiting ...\n");
Thread_sleep(1000);
}
else
{
printf("Failed to enable log (err=%i)\n", error);
}
if ((error == IED_ERROR_OK) && (MmsValue_getType(lcbValue) != MMS_DATA_ACCESS_ERROR)) {
/* read log control block (using the generic read function) */
MmsValue* lcbValue = IedConnection_readObject(con, &error, "TestIEDGenericIO/LLN0.EventLog", IEC61850_FC_LG);
if ((error == IED_ERROR_OK) && (MmsValue_getType(lcbValue) != MMS_DATA_ACCESS_ERROR))
{
char printBuf[1024];
MmsValue_printToBuffer(lcbValue, printBuf, 1024);
@ -115,9 +130,12 @@ int main(int argc, char** argv) {
* read the log contents. Be aware that the logRef uses the '$' sign as separator between the LN and
* the log name! This is in contrast to the LCB object reference above.
*/
LinkedList logEntries = IedConnection_queryLogAfter(con, &error, "simpleIOGenericIO/LLN0$EventLog", oldEntry, timestamp, &moreFollows);
LinkedList logEntries = IedConnection_queryLogAfter(con, &error, logRef, oldEntry, timestamp, &moreFollows);
if (error == IED_ERROR_OK)
{
printf("Received %d log entries for %s\n", LinkedList_size(logEntries), logRef);
if (error == IED_ERROR_OK) {
printJournalEntries(logEntries);
LinkedList_destroyDeep(logEntries, (LinkedListValueDeleteFunction) MmsJournalEntry_destroy);
@ -132,15 +150,14 @@ int main(int argc, char** argv) {
else
printf("Read LCB failed!\n");
IedConnection_abort(con, &error);
}
else {
else
{
printf("Failed to connect to %s:%i\n", hostname, tcpPort);
}
IedConnection_destroy(con);
return 0;
}

@ -114,6 +114,7 @@ controlBlockAccessHandler(void* parameter, ClientConnection connection, ACSIClas
{
printf("%s %s access %s/%s.%s.%s\n", ACSIClassToStr(acsiClass), accessType == IEC61850_CB_ACCESS_TYPE_WRITE ? "write" : "read", ld->name, ln->name, objectName, subObjectName);
return false;
/* allow only read access to LCBs */
if (acsiClass == ACSI_CLASS_LCB) {
if (accessType == IEC61850_CB_ACCESS_TYPE_READ)

@ -17,9 +17,6 @@
#include "logging_api.h"
LogStorage
SqliteLogStorage_createInstance(const char* filename);
static int running = 0;
static IedServer iedServer = NULL;

@ -0,0 +1,14 @@
#include "acse.h"
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size)
{
AcseConnection acseConnection;
AcseConnection_init(&acseConnection, NULL, NULL, NULL);
ByteBuffer* acseBuffer = ByteBuffer_create(NULL, size);
ByteBuffer_append(acseBuffer, data, size);
AcseConnection_parseMessage(&acseConnection, acseBuffer);
ByteBuffer_destroy(acseBuffer);
return 0;
}

@ -0,0 +1,35 @@
#include <stdio.h>
#include <stdlib.h>
#include "iec61850_server.h"
#include "hal_thread.h"
#include "lib_memory.h"
int LLVMFuzzerTestOneInput(const char *data, size_t size) {
int out;
MmsValue* mmsValue = NULL;
mmsValue = MmsValue_decodeMmsData(data, 0, size, &out);
if (mmsValue == NULL) {
return 0;
}
int dataSize = MmsValue_encodeMmsData(mmsValue, NULL, 0, false);
if (dataSize <= 0) {
return 0;
}
uint8_t *mmsBuffer = (uint8_t *)GLOBAL_MALLOC(dataSize);
if (mmsBuffer == NULL) {
return 0;
}
MmsValue_encodeMmsData(mmsValue, mmsBuffer, 0, true);
GLOBAL_FREEMEM(mmsBuffer);
if (mmsValue != NULL) {
MmsValue_delete(mmsValue);
}
return 0;
}

@ -0,0 +1,30 @@
#include <stdio.h>
#include <stdlib.h>
#include "iec61850_server.h"
#include "hal_thread.h"
#define kBufSize 4096
int LLVMFuzzerTestOneInput(const char *data, size_t size) {
int out;
MmsValue* mmsValue = NULL;
mmsValue = MmsValue_decodeMmsData(data, 0, size, &out);
if (mmsValue == NULL) {
return 0;
}
int dataSize = MmsValue_encodeMmsData(mmsValue, NULL, 0, false);
if (dataSize <= 0) {
return 0;
}
char printBuffer[kBufSize];
MmsValue_printToBuffer(mmsValue, printBuffer, kBufSize);
if (mmsValue != NULL) {
MmsValue_delete(mmsValue);
}
return 0;
}

@ -206,7 +206,8 @@ IF(CONFIG_USE_EXTERNAL_MBEDTLS_DYNLIB)
ENDIF(CONFIG_USE_EXTERNAL_MBEDTLS_DYNLIB)
IF(MINGW)
target_link_libraries(hal ws2_32 iphlpapi)
target_link_libraries(hal ws2_32 iphlpapi bcrypt)
message("Building with MinGW")
ENDIF(MINGW)
IF (MSVC)

@ -364,7 +364,7 @@ Ethernet_setMode(EthernetSocket ethSocket, EthernetSocketMode mode)
}
void
Ethernet_addMulticastAddress(EthernetSocket ethSocket, uint8_t* multicastAddress)
Ethernet_addMulticastAddress(EthernetSocket ethSocket, const uint8_t* multicastAddress)
{
/* not implemented */
}

@ -270,7 +270,7 @@ Ethernet_setMode(EthernetSocket self, EthernetSocketMode mode)
}
void
Ethernet_addMulticastAddress(EthernetSocket self, uint8_t* multicastAddress)
Ethernet_addMulticastAddress(EthernetSocket self, const uint8_t* multicastAddress)
{
struct packet_mreq mreq;
memset(&mreq, 0, sizeof(struct packet_mreq));

@ -385,7 +385,7 @@ Ethernet_setMode(EthernetSocket ethSocket, EthernetSocketMode mode)
}
void
Ethernet_addMulticastAddress(EthernetSocket ethSocket, uint8_t* multicastAddress)
Ethernet_addMulticastAddress(EthernetSocket ethSocket, const uint8_t* multicastAddress)
{
/* not implemented */
}

@ -145,7 +145,7 @@ Ethernet_setMode(EthernetSocket ethSocket, EthernetSocketMode mode);
* \param multicastAddress the multicast Ethernet address (this has to be a byte buffer of at least 6 byte)
*/
PAL_API void
Ethernet_addMulticastAddress(EthernetSocket ethSocket, uint8_t* multicastAddress);
Ethernet_addMulticastAddress(EthernetSocket ethSocket, const uint8_t* multicastAddress);
/*
* \brief set a protocol filter for the specified etherType

@ -1,7 +1,7 @@
/*
* socket_hal.h
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.

@ -1,7 +1,7 @@
/*
* time.c
*
* Copyright 2013-2022 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@ -68,6 +68,22 @@ Hal_getTimeInNs(void);
PAL_API bool
Hal_setTimeInNs(nsSinceEpoch nsTime);
/**
* Get the monotonic time or system tick time in ms
*
* \return the system time with millisecond resolution.
*/
PAL_API msSinceEpoch
Hal_getMonotonicTimeInMs(void);
/**
* Get the monotonic time or system tick in nanoseconds.
*
* \return the system time with nanosecond resolution.
*/
PAL_API nsSinceEpoch
Hal_getMonotonicTimeInNs(void);
/*! @} */
/*! @} */

@ -92,6 +92,10 @@ typedef enum {
#define TLS_EVENT_CODE_ALM_CERT_NOT_TRUSTED 14
#define TLS_EVENT_CODE_ALM_NO_CIPHER 15
#define TLS_EVENT_CODE_INF_SESSION_ESTABLISHED 16
#define TLS_EVENT_CODE_WRN_CERT_EXPIRED 17
#define TLS_EVENT_CODE_WRN_CERT_NOT_YET_VALID 18
#define TLS_EVENT_CODE_WRN_CRL_EXPIRED 19
#define TLS_EVENT_CODE_WRN_CRL_NOT_YET_VALID 20
typedef struct sTLSConnection* TLSConnection;
@ -165,6 +169,14 @@ TLSConfiguration_setSessionResumptionInterval(TLSConfiguration self, int interva
PAL_API void
TLSConfiguration_setChainValidation(TLSConfiguration self, bool value);
/**
* \brief Enables or disables the verification of validity times for certificates and CRLs
*
* \param value true to enable time validation, false to disable (enabled by default)
*/
PAL_API void
TLSConfiguration_setTimeValidation(TLSConfiguration self, bool value);
/**
* \brief Set if only known certificates are accepted.
*

@ -65,3 +65,4 @@ Memory_free(void* memb)
{
free(memb);
}

@ -1,33 +1,33 @@
/*
* socket_bsd.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
*/
#include "hal_socket.h"
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <netdb.h>
#include <netinet/in.h>
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#include <netinet/tcp.h> // required for TCP keepalive
#include <signal.h>
#include <poll.h>
#include <signal.h>
#include "linked_list.h"
#include "hal_thread.h"
#include "lib_memory.h"
#include "linked_list.h"
#ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0
@ -41,22 +41,26 @@
#define MSG_NOSIGNAL 0
#endif
struct sSocket {
struct sSocket
{
int fd;
uint32_t connectTimeout;
};
struct sServerSocket {
struct sServerSocket
{
int fd;
int backLog;
};
struct sUdpSocket {
struct sUdpSocket
{
int fd;
int namespace; /* IPv4: AF_INET; IPv6: AF_INET6 */
};
struct sHandleSet {
struct sHandleSet
{
LinkedList sockets;
bool pollfdIsUpdated;
struct pollfd* fds;
@ -66,9 +70,10 @@ struct sHandleSet {
HandleSet
Handleset_new(void)
{
HandleSet self = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
HandleSet self = (HandleSet)GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (self) {
if (self)
{
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
self->fds = NULL;
@ -81,8 +86,10 @@ Handleset_new(void)
void
Handleset_reset(HandleSet self)
{
if (self) {
if (self->sockets) {
if (self)
{
if (self->sockets)
{
LinkedList_destroyStatic(self->sockets);
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
@ -93,7 +100,8 @@ Handleset_reset(HandleSet self)
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != -1) {
if (self != NULL && sock != NULL && sock->fd != -1)
{
LinkedList_add(self->sockets, sock);
self->pollfdIsUpdated = false;
}
@ -102,7 +110,8 @@ Handleset_addSocket(HandleSet self, const Socket sock)
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self && self->sockets && sock) {
if (self && self->sockets && sock)
{
LinkedList_remove(self->sockets, sock);
self->pollfdIsUpdated = false;
}
@ -112,8 +121,10 @@ int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
/* check if pollfd array is updated */
if (self->pollfdIsUpdated == false) {
if (self->fds) {
if (self->pollfdIsUpdated == false)
{
if (self->fds)
{
GLOBAL_FREEMEM(self->fds);
self->fds = NULL;
}
@ -124,13 +135,16 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
int i;
for (i = 0; i < self->nfds; i++) {
for (i = 0; i < self->nfds; i++)
{
LinkedList sockElem = LinkedList_get(self->sockets, i);
if (sockElem) {
Socket sock = (Socket) LinkedList_getData(sockElem);
if (sockElem)
{
Socket sock = (Socket)LinkedList_getData(sockElem);
if (sock) {
if (sock)
{
self->fds[i].fd = sock->fd;
self->fds[i].events = POLL_IN;
}
@ -140,17 +154,20 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
self->pollfdIsUpdated = true;
}
if (self->fds && self->nfds > 0) {
if (self->fds && self->nfds > 0)
{
int result = poll(self->fds, self->nfds, timeoutMs);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: poll error (errno: %i)\n", errno);
}
return result;
}
else {
else
{
/* there is no socket to wait for */
return 0;
}
@ -159,7 +176,8 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
void
Handleset_destroy(HandleSet self)
{
if (self) {
if (self)
{
if (self->sockets)
LinkedList_destroyStatic(self->sockets);
@ -197,18 +215,20 @@ static bool
prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
{
memset((char *) sockaddr , 0, sizeof(struct sockaddr_in));
memset((char*)sockaddr, 0, sizeof(struct sockaddr_in));
if (address != NULL) {
struct hostent *server;
server = gethostbyname(address);
if (address != NULL)
{
struct hostent* server;
server = gethostbyname(address);
if (server == NULL) return false;
if (server == NULL)
return false;
memcpy((char *) &sockaddr->sin_addr.s_addr, (char *) server->h_addr, server->h_length);
}
else
sockaddr->sin_addr.s_addr = htonl(INADDR_ANY);
memcpy((char*)&sockaddr->sin_addr.s_addr, (char*)server->h_addr, server->h_length);
}
else
sockaddr->sin_addr.s_addr = htonl(INADDR_ANY);
sockaddr->sin_family = AF_INET;
sockaddr->sin_port = htons(port);
@ -228,7 +248,7 @@ activateTcpNoDelay(Socket self)
{
/* activate TCP_NODELAY option - packets will be sent immediately */
int flag = 1;
setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
}
ServerSocket
@ -238,27 +258,31 @@ TcpServerSocket_create(const char* address, int port)
int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0) {
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0)
{
struct sockaddr_in serverAddress;
if (!prepareAddress(address, port, &serverAddress)) {
if (!prepareAddress(address, port, &serverAddress))
{
close(fd);
return NULL;
}
int optionReuseAddr = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optionReuseAddr, sizeof(int));
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&optionReuseAddr, sizeof(int));
if (bind(fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) >= 0) {
serverSocket = (ServerSocket) GLOBAL_MALLOC(sizeof(struct sServerSocket));
if (bind(fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) >= 0)
{
serverSocket = (ServerSocket)GLOBAL_MALLOC(sizeof(struct sServerSocket));
serverSocket->fd = fd;
serverSocket->backLog = 2;
setSocketNonBlocking((Socket) serverSocket);
setSocketNonBlocking((Socket)serverSocket);
}
else {
else
{
close(fd);
return NULL ;
return NULL;
}
}
@ -271,7 +295,6 @@ ServerSocket_listen(ServerSocket self)
listen(self->fd, self->backLog);
}
/* CHANGED TO MAKE NON-BLOCKING --> RETURNS NULL IF NO CONNECTION IS PENDING */
Socket
ServerSocket_accept(ServerSocket self)
@ -280,19 +303,22 @@ ServerSocket_accept(ServerSocket self)
Socket conSocket = NULL;
fd = accept(self->fd, NULL, NULL );
fd = accept(self->fd, NULL, NULL);
if (fd >= 0) {
conSocket = (Socket) GLOBAL_CALLOC(1, sizeof(struct sSocket));
if (fd >= 0)
{
conSocket = (Socket)GLOBAL_CALLOC(1, sizeof(struct sSocket));
if (conSocket) {
if (conSocket)
{
conSocket->fd = fd;
setSocketNonBlocking(conSocket);
activateTcpNoDelay(conSocket);
}
else {
else
{
/* out of memory */
close(fd);
@ -313,7 +339,8 @@ ServerSocket_setBacklog(ServerSocket self, int backlog)
static void
closeAndShutdownSocket(int socketFd)
{
if (socketFd != -1) {
if (socketFd != -1)
{
if (DEBUG_SOCKET)
printf("socket_linux.c: call shutdown for %i!\n", socketFd);
@ -346,10 +373,12 @@ TcpSocket_create()
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != -1) {
self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket));
if (sock != -1)
{
self = (Socket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->connectTimeout = 5000;
@ -358,7 +387,8 @@ TcpSocket_create()
int result = setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
#endif
}
else {
else
{
/* out of memory */
close(sock);
@ -366,7 +396,8 @@ TcpSocket_create()
printf("SOCKET: out of memory\n");
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket (errno=%i)\n", errno);
}
@ -390,7 +421,8 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind TCP socket (errno=%i)\n", errno);
@ -398,7 +430,7 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
self->fd = -1;
return false;
}
}
return true;
}
@ -422,9 +454,11 @@ Socket_connectAsync(Socket self, const char* address, int port)
fcntl(self->fd, F_SETFL, O_NONBLOCK);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
if (connect(self->fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0)
{
if (errno != EINPROGRESS) {
if (errno != EINPROGRESS)
{
self->fd = -1;
return false;
}
@ -444,16 +478,18 @@ Socket_checkAsyncConnectState(Socket self)
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
int selectVal = select(self->fd + 1, NULL, &fdSet , NULL, &timeout);
int selectVal = select(self->fd + 1, NULL, &fdSet, NULL, &timeout);
if (selectVal == 1) {
if (selectVal == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return SOCKET_STATE_CONNECTED;
@ -461,10 +497,12 @@ Socket_checkAsyncConnectState(Socket self)
return SOCKET_STATE_FAILED;
}
else if (selectVal == 0) {
else if (selectVal == 0)
{
return SOCKET_STATE_CONNECTING;
}
else {
else
{
return SOCKET_STATE_FAILED;
}
}
@ -483,21 +521,23 @@ Socket_connect(Socket self, const char* address, int port)
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
if (select(self->fd + 1, NULL, &fdSet , NULL, &timeout) == 1) {
if (select(self->fd + 1, NULL, &fdSet, NULL, &timeout) == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return true;
}
}
close (self->fd);
close(self->fd);
self->fd = -1;
return false;
@ -511,22 +551,24 @@ convertAddressToStr(struct sockaddr_storage* addr)
bool isIPv6;
if (addr->ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) addr;
if (addr->ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr->ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) addr;
else if (addr->ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;
}
else
return NULL ;
return NULL;
char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9);
char* clientConnection = (char*)GLOBAL_MALLOC(strlen(addrString) + 9);
if (isIPv6)
sprintf(clientConnection, "[%s]:%i", addrString, port);
@ -542,7 +584,8 @@ Socket_getPeerAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getpeername(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -555,7 +598,8 @@ Socket_getLocalAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getsockname(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -568,27 +612,29 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
getpeername(self->fd, (struct sockaddr*) &addr, &addrLen);
getpeername(self->fd, (struct sockaddr*)&addr, &addrLen);
char addrString[INET6_ADDRSTRLEN + 7];
int port;
bool isIPv6;
if (addr.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr;
if (addr.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr;
else if (addr.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;
}
else
return NULL ;
return NULL;
if (isIPv6)
sprintf(peerAddressString, "[%s]:%i", addrString, port);
@ -609,18 +655,20 @@ Socket_read(Socket self, uint8_t* buf, int size)
if (read_bytes == 0)
return -1;
if (read_bytes == -1) {
if (read_bytes == -1)
{
int error = errno;
switch (error) {
switch (error)
{
case EAGAIN:
return 0;
case EBADF:
return -1;
case EAGAIN:
return 0;
case EBADF:
return -1;
default:
return -1;
default:
return -1;
}
}
@ -663,21 +711,25 @@ UdpSocket_createUsingNamespace(int namespace)
int sock = socket(namespace, SOCK_DGRAM, IPPROTO_UDP);
if (sock != -1) {
self = (UdpSocket) GLOBAL_MALLOC(sizeof(struct sSocket));
if (sock != -1)
{
self = (UdpSocket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->namespace = namespace;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to allocate memory\n");
close(sock);
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create UDP socket (errno=%i)\n", errno);
}
@ -700,36 +752,42 @@ UdpSocket_createIpV6()
bool
UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
{
if (self->namespace == AF_INET) {
if (self->namespace == AF_INET)
{
struct ip_mreq mreq;
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr))) {
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr)))
{
printf("SOCKET: Invalid IPv4 multicast address\n");
return false;
}
else {
else
{
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", errno);
return false;
}
}
return true;
}
else if (self->namespace == AF_INET6) {
else if (self->namespace == AF_INET6)
{
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1) {
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
mreq.ipv6mr_interface = 0;
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
@ -743,16 +801,20 @@ UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
bool
UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
{
if (self->namespace == AF_INET) {
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) {
if (self->namespace == AF_INET)
{
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", errno);
return false;
}
return true;
}
else if (self->namespace == AF_INET6) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1) {
else if (self->namespace == AF_INET6)
{
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", errno);
return false;
}
@ -766,10 +828,11 @@ UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
bool
UdpSocket_bind(UdpSocket self, const char* address, int port)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_in localAddress;
if (!prepareAddress(address, port, &localAddress)) {
if (!prepareAddress(address, port, &localAddress))
{
close(self->fd);
self->fd = 0;
return false;
@ -777,7 +840,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind UDP socket (errno=%i)\n", errno);
@ -793,10 +857,11 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
bool
UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_in remoteAddress;
if (!prepareAddress(address, port, &remoteAddress)) {
if (!prepareAddress(address, port, &remoteAddress))
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
@ -806,14 +871,17 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
int result = sendto(self->fd, msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
if (result == msgSize) {
if (result == msgSize)
{
return true;
}
else if (result == -1) {
else if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (errno=%i)\n", errno);
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (insufficient data sent)\n");
}
@ -824,31 +892,35 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
int
UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_storage remoteAddress;
socklen_t structSize = sizeof(struct sockaddr_storage);
int result = recvfrom(self->fd, msg, msgSize, MSG_DONTWAIT, (struct sockaddr*)&remoteAddress, &structSize);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to receive UDP message (errno=%i)\n", errno);
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &remoteAddress;
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &remoteAddress;
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;
@ -862,19 +934,22 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
snprintf(address, maxAddrSize, "%s:%i", addrString, port);
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &remoteAddress;
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &remoteAddress;
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;

@ -8,49 +8,52 @@
*/
#include "hal_socket.h"
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <netinet/in.h>
#include <netdb.h>
#include <errno.h>
#include <stdio.h>
#include <fcntl.h>
#include <netinet/tcp.h> /* required for TCP keepalive */
#include <linux/version.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/tcp.h> /* required for TCP keepalive */
#include <stdio.h>
#include <string.h>
#include <sys/select.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <unistd.h>
#define _GNU_SOURCE
#include <signal.h>
#include <poll.h>
#include <signal.h>
#include "linked_list.h"
#include "hal_thread.h"
#include "lib_memory.h"
#include "linked_list.h"
#ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0
#endif
struct sSocket {
struct sSocket
{
int fd;
uint32_t connectTimeout;
};
struct sServerSocket {
struct sServerSocket
{
int fd;
int backLog;
};
struct sUdpSocket {
struct sUdpSocket
{
int fd;
int namespace; /* IPv4: AF_INET; IPv6: AF_INET6 */
};
struct sHandleSet {
struct sHandleSet
{
LinkedList sockets;
bool pollfdIsUpdated;
struct pollfd* fds;
@ -60,23 +63,26 @@ struct sHandleSet {
HandleSet
Handleset_new(void)
{
HandleSet self = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
HandleSet self = (HandleSet)GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (self) {
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
self->fds = NULL;
self->nfds = 0;
}
if (self)
{
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
self->fds = NULL;
self->nfds = 0;
}
return self;
return self;
}
void
Handleset_reset(HandleSet self)
{
if (self) {
if (self->sockets) {
if (self)
{
if (self->sockets)
{
LinkedList_destroyStatic(self->sockets);
self->sockets = LinkedList_create();
self->pollfdIsUpdated = false;
@ -87,17 +93,19 @@ Handleset_reset(HandleSet self)
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != -1) {
if (self != NULL && sock != NULL && sock->fd != -1)
{
LinkedList_add(self->sockets, sock);
self->pollfdIsUpdated = false;
}
LinkedList_add(self->sockets, sock);
self->pollfdIsUpdated = false;
}
}
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self && self->sockets && sock) {
if (self && self->sockets && sock)
{
LinkedList_remove(self->sockets, sock);
self->pollfdIsUpdated = false;
}
@ -107,8 +115,10 @@ int
Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
/* check if pollfd array is updated */
if (self->pollfdIsUpdated == false) {
if (self->fds) {
if (self->pollfdIsUpdated == false)
{
if (self->fds)
{
GLOBAL_FREEMEM(self->fds);
self->fds = NULL;
}
@ -119,13 +129,16 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
int i;
for (i = 0; i < self->nfds; i++) {
for (i = 0; i < self->nfds; i++)
{
LinkedList sockElem = LinkedList_get(self->sockets, i);
if (sockElem) {
Socket sock = (Socket) LinkedList_getData(sockElem);
if (sockElem)
{
Socket sock = (Socket)LinkedList_getData(sockElem);
if (sock) {
if (sock)
{
self->fds[i].fd = sock->fd;
self->fds[i].events = POLL_IN;
}
@ -135,21 +148,25 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
self->pollfdIsUpdated = true;
}
if (self->fds && self->nfds > 0) {
if (self->fds && self->nfds > 0)
{
int result = poll(self->fds, self->nfds, timeoutMs);
if (result == -1 && errno == EINTR) {
if (result == -1 && errno == EINTR)
{
result = 0;
}
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: poll error (errno: %i)\n", errno);
}
return result;
}
else {
else
{
/* there is no socket to wait for */
return 0;
}
@ -158,7 +175,8 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
void
Handleset_destroy(HandleSet self)
{
if (self) {
if (self)
{
if (self->sockets)
LinkedList_destroyStatic(self->sockets);
@ -178,26 +196,30 @@ Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
optval = 1;
if (setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen)) {
if (setsockopt(self->fd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to enable TCP keepalive\n");
}
#if defined TCP_KEEPCNT
optval = idleTime;
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen)) {
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPIDLE, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to set TCP keepalive TCP_KEEPIDLE parameter\n");
}
optval = interval;
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen)) {
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPINTVL, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to set TCP keepalive TCP_KEEPINTVL parameter\n");
}
optval = count;
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen)) {
if (setsockopt(self->fd, IPPROTO_TCP, TCP_KEEPCNT, &optval, optlen))
{
if (DEBUG_SOCKET)
printf("SOCKET: Failed to set TCP keepalive TCP_KEEPCNT parameter\n");
}
@ -211,18 +233,20 @@ prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
{
bool retVal = true;
memset((char *) sockaddr, 0, sizeof(struct sockaddr_in));
memset((char*)sockaddr, 0, sizeof(struct sockaddr_in));
if (address != NULL) {
if (address != NULL)
{
struct addrinfo addressHints;
struct addrinfo *lookupResult;
struct addrinfo* lookupResult;
int result;
memset(&addressHints, 0, sizeof(struct addrinfo));
addressHints.ai_family = AF_INET;
result = getaddrinfo(address, NULL, &addressHints, &lookupResult);
if (result != 0) {
if (result != 0)
{
if (DEBUG_SOCKET)
printf("SOCKET: getaddrinfo failed (code=%i)\n", result);
@ -260,7 +284,7 @@ activateTcpNoDelay(Socket self)
{
/* activate TCP_NODELAY option - packets will be sent immediately */
int flag = 1;
setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
setsockopt(self->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&flag, sizeof(int));
}
ServerSocket
@ -270,22 +294,25 @@ TcpServerSocket_create(const char* address, int port)
int fd;
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0) {
if ((fd = socket(AF_INET, SOCK_STREAM, 0)) >= 0)
{
struct sockaddr_in serverAddress;
if (!prepareAddress(address, port, &serverAddress)) {
if (!prepareAddress(address, port, &serverAddress))
{
close(fd);
return NULL;
}
int optionReuseAddr = 1;
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &optionReuseAddr, sizeof(int));
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char*)&optionReuseAddr, sizeof(int));
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
int tcpUserTimeout = 10000;
int result = setsockopt(fd, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
int result = setsockopt(fd, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
if (result < 0) {
if (result < 0)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to set TCP_USER_TIMEOUT\n");
}
@ -293,16 +320,18 @@ TcpServerSocket_create(const char* address, int port)
#warning "TCP_USER_TIMEOUT not supported by linux kernel"
#endif
if (bind(fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) >= 0) {
serverSocket = (ServerSocket) GLOBAL_MALLOC(sizeof(struct sServerSocket));
if (bind(fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) >= 0)
{
serverSocket = (ServerSocket)GLOBAL_MALLOC(sizeof(struct sServerSocket));
serverSocket->fd = fd;
serverSocket->backLog = 2;
setSocketNonBlocking((Socket) serverSocket);
setSocketNonBlocking((Socket)serverSocket);
}
else {
else
{
close(fd);
return NULL ;
return NULL;
}
}
@ -312,7 +341,8 @@ TcpServerSocket_create(const char* address, int port)
void
ServerSocket_listen(ServerSocket self)
{
if (listen(self->fd, self->backLog) == -1) {
if (listen(self->fd, self->backLog) == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: listen failed (errno: %i)\n", errno);
}
@ -326,19 +356,22 @@ ServerSocket_accept(ServerSocket self)
Socket conSocket = NULL;
fd = accept(self->fd, NULL, NULL );
fd = accept(self->fd, NULL, NULL);
if (fd >= 0) {
conSocket = (Socket) GLOBAL_CALLOC(1, sizeof(struct sSocket));
if (fd >= 0)
{
conSocket = (Socket)GLOBAL_CALLOC(1, sizeof(struct sSocket));
if (conSocket) {
if (conSocket)
{
conSocket->fd = fd;
setSocketNonBlocking(conSocket);
activateTcpNoDelay(conSocket);
}
else {
else
{
/* out of memory */
close(fd);
@ -346,7 +379,8 @@ ServerSocket_accept(ServerSocket self)
printf("SOCKET: out of memory\n");
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: accept failed (errno=%i)\n", errno);
}
@ -363,7 +397,8 @@ ServerSocket_setBacklog(ServerSocket self, int backlog)
static void
closeAndShutdownSocket(int socketFd)
{
if (socketFd != -1) {
if (socketFd != -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: call shutdown for %i!\n", socketFd);
@ -371,14 +406,16 @@ closeAndShutdownSocket(int socketFd)
/* shutdown is required to unblock read or accept in another thread! */
int result = shutdown(socketFd, SHUT_RDWR);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: shutdown error: %i\n", errno);
}
result = close(socketFd);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: close error: %i\n", errno);
}
@ -406,24 +443,28 @@ TcpSocket_create()
int sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != -1) {
self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket));
if (sock != -1)
{
self = (Socket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->connectTimeout = 5000;
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 37)
int tcpUserTimeout = 10000;
int result = setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
int result = setsockopt(sock, SOL_TCP, TCP_USER_TIMEOUT, &tcpUserTimeout, sizeof(tcpUserTimeout));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to set TCP_USER_TIMEOUT (errno=%i)\n", errno);
}
#endif
}
else {
else
{
/* out of memory */
close(sock);
@ -431,7 +472,8 @@ TcpSocket_create()
printf("SOCKET: out of memory\n");
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket (errno=%i)\n", errno);
}
@ -455,7 +497,8 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind TCP socket (errno=%i)\n", errno);
@ -463,7 +506,7 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
self->fd = -1;
return false;
}
}
return true;
}
@ -483,10 +526,13 @@ Socket_connectAsync(Socket self, const char* address, int port)
fcntl(self->fd, F_SETFL, O_NONBLOCK);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
if (connect(self->fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) < 0)
{
if (errno != EINPROGRESS) {
if (close(self->fd) == -1) {
if (errno != EINPROGRESS)
{
if (close(self->fd) == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to close socket (errno: %i)\n", errno);
}
@ -509,14 +555,16 @@ Socket_checkAsyncConnectState(Socket self)
int result = poll(fds, 1, 0);
if (result == 1) {
if (result == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return SOCKET_STATE_CONNECTED;
@ -524,10 +572,12 @@ Socket_checkAsyncConnectState(Socket self)
return SOCKET_STATE_FAILED;
}
else if (result == 0) {
else if (result == 0)
{
return SOCKET_STATE_CONNECTING;
}
else {
else
{
return SOCKET_STATE_FAILED;
}
}
@ -545,21 +595,23 @@ Socket_connect(Socket self, const char* address, int port)
int result = poll(fds, 1, self->connectTimeout);
if (result == 1) {
if (result == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, &so_error, &len) >= 0)
{
if (so_error == 0)
return true;
}
}
close (self->fd);
close(self->fd);
self->fd = -1;
return false;
@ -573,22 +625,24 @@ convertAddressToStr(struct sockaddr_storage* addr)
bool isIPv6;
if (addr->ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) addr;
if (addr->ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr->ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) addr;
else if (addr->ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;
}
else
return NULL ;
return NULL;
char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9);
char* clientConnection = (char*)GLOBAL_MALLOC(strlen(addrString) + 9);
if (isIPv6)
sprintf(clientConnection, "[%s]:%i", addrString, port);
@ -604,7 +658,8 @@ Socket_getPeerAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getpeername(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -617,7 +672,8 @@ Socket_getLocalAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getsockname(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -629,28 +685,37 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
{
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
memset(&addr, 0, sizeof(addr));
getpeername(self->fd, (struct sockaddr*) &addr, &addrLen);
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == -1)
{
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: getpeername -> errno: %i\n", errno);
return NULL;
}
char addrString[INET6_ADDRSTRLEN + 7];
int port;
bool isIPv6;
if (addr.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr;
if (addr.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&addr;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (addr.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr;
else if (addr.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&addr;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;
}
else
return NULL ;
return NULL;
if (isIPv6)
sprintf(peerAddressString, "[%s]:%i", addrString, port);
@ -671,22 +736,24 @@ Socket_read(Socket self, uint8_t* buf, int size)
if (read_bytes == 0)
return -1;
if (read_bytes == -1) {
if (read_bytes == -1)
{
int error = errno;
switch (error) {
switch (error)
{
case EAGAIN:
return 0;
case EBADF:
return -1;
case EAGAIN:
return 0;
case EBADF:
return -1;
default:
default:
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: recv returned error (errno=%i)\n", error);
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: recv returned error (errno=%i)\n", error);
return -1;
return -1;
}
}
@ -702,11 +769,14 @@ Socket_write(Socket self, uint8_t* buf, int size)
/* MSG_NOSIGNAL - prevent send to signal SIGPIPE when peer unexpectedly closed the socket */
int retVal = send(self->fd, buf, size, MSG_NOSIGNAL | MSG_DONTWAIT);
if (retVal == -1) {
if (errno == EAGAIN) {
if (retVal == -1)
{
if (errno == EAGAIN)
{
return 0;
}
else {
else
{
if (DEBUG_SOCKET)
printf("DEBUG_SOCKET: send returned error (errno=%i)\n", errno);
}
@ -736,21 +806,25 @@ UdpSocket_createUsingNamespace(int namespace)
int sock = socket(namespace, SOCK_DGRAM, IPPROTO_UDP);
if (sock != -1) {
self = (UdpSocket) GLOBAL_MALLOC(sizeof(struct sSocket));
if (sock != -1)
{
self = (UdpSocket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->namespace = namespace;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to allocate memory\n");
close(sock);
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create UDP socket (errno=%i)\n", errno);
}
@ -773,36 +847,42 @@ UdpSocket_createIpV6()
bool
UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
{
if (self->namespace == AF_INET) {
if (self->namespace == AF_INET)
{
struct ip_mreq mreq;
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr))) {
if (!inet_aton(multicastAddress, &(mreq.imr_multiaddr)))
{
printf("SOCKET: Invalid IPv4 multicast address\n");
return false;
}
else {
else
{
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", errno);
return false;
}
}
return true;
}
else if (self->namespace == AF_INET6) {
else if (self->namespace == AF_INET6)
{
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1) {
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
mreq.ipv6mr_interface = 0;
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", errno);
return false;
}
@ -816,16 +896,20 @@ UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
bool
UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
{
if (self->namespace == AF_INET) {
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1) {
if (self->namespace == AF_INET)
{
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", errno);
return false;
}
return true;
}
else if (self->namespace == AF_INET6) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1) {
else if (self->namespace == AF_INET6)
{
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", errno);
return false;
}
@ -839,10 +923,11 @@ UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
bool
UdpSocket_bind(UdpSocket self, const char* address, int port)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_in localAddress;
if (!prepareAddress(address, port, &localAddress)) {
if (!prepareAddress(address, port, &localAddress))
{
close(self->fd);
self->fd = 0;
return false;
@ -850,7 +935,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind UDP socket (errno=%i)\n", errno);
@ -866,10 +952,11 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
bool
UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_in remoteAddress;
if (!prepareAddress(address, port, &remoteAddress)) {
if (!prepareAddress(address, port, &remoteAddress))
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
@ -879,14 +966,17 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
int result = sendto(self->fd, msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
if (result == msgSize) {
if (result == msgSize)
{
return true;
}
else if (result == -1) {
else if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (errno=%i)\n", errno);
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (insufficient data sent)\n");
}
@ -897,31 +987,35 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
int
UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_storage remoteAddress;
memset(&remoteAddress, 0, sizeof(struct sockaddr_storage));
socklen_t structSize = sizeof(struct sockaddr_storage);
int result = recvfrom(self->fd, msg, msgSize, MSG_DONTWAIT, (struct sockaddr*)&remoteAddress, &structSize);
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to receive UDP message (errno=%i)\n", errno);
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &remoteAddress;
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &remoteAddress;
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;

@ -1,7 +1,7 @@
/*
* socket_win32.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@ -9,56 +9,64 @@
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
#include <winsock2.h>
#include <ws2tcpip.h>
#include <windows.h>
#include <stdbool.h>
#include <stdio.h>
#pragma comment (lib, "Ws2_32.lib")
#pragma comment(lib, "Ws2_32.lib")
#include "lib_memory.h"
#include "hal_socket.h"
#include "stack_config.h"
#include "lib_memory.h"
#define DEBUG_SOCKET 1
#ifndef DEBUG_SOCKET
#define DEBUG_SOCKET 0
#endif
#ifndef __MINGW64_VERSION_MAJOR
struct tcp_keepalive {
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
struct tcp_keepalive
{
u_long onoff;
u_long keepalivetime;
u_long keepaliveinterval;
};
#endif
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR,4)
#define SIO_KEEPALIVE_VALS _WSAIOW(IOC_VENDOR, 4)
struct sSocket {
struct sSocket
{
SOCKET fd;
uint32_t connectTimeout;
};
struct sServerSocket {
struct sServerSocket
{
SOCKET fd;
int backLog;
};
struct sHandleSet {
struct sHandleSet
{
fd_set handles;
SOCKET maxHandle;
};
struct sUdpSocket {
struct sUdpSocket
{
SOCKET fd;
int ns; /* IPv4: AF_INET; IPv6: AF_INET6 */
int ns; /* IPv4: AF_INET; IPv6: AF_INET6 */
};
HandleSet
Handleset_new(void)
{
HandleSet result = (HandleSet) GLOBAL_MALLOC(sizeof(struct sHandleSet));
HandleSet result = (HandleSet)GLOBAL_MALLOC(sizeof(struct sHandleSet));
if (result != NULL) {
if (result != NULL)
{
FD_ZERO(&result->handles);
result->maxHandle = INVALID_SOCKET;
}
@ -76,19 +84,21 @@ Handleset_reset(HandleSet self)
void
Handleset_addSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET) {
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET)
{
FD_SET(sock->fd, &self->handles);
FD_SET(sock->fd, &self->handles);
if ((sock->fd > self->maxHandle) || (self->maxHandle == INVALID_SOCKET))
self->maxHandle = sock->fd;
}
if ((sock->fd > self->maxHandle) || (self->maxHandle == INVALID_SOCKET))
self->maxHandle = sock->fd;
}
}
void
Handleset_removeSocket(HandleSet self, const Socket sock)
{
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET) {
if (self != NULL && sock != NULL && sock->fd != INVALID_SOCKET)
{
FD_CLR(sock->fd, &self->handles);
}
}
@ -98,7 +108,8 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
{
int result;
if ((self != NULL) && (self->maxHandle != INVALID_SOCKET)) {
if ((self != NULL) && (self->maxHandle != INVALID_SOCKET))
{
struct timeval timeout;
timeout.tv_sec = timeoutMs / 1000;
@ -109,7 +120,9 @@ Handleset_waitReady(HandleSet self, unsigned int timeoutMs)
memcpy((void*)&handles, &(self->handles), sizeof(fd_set));
result = select(self->maxHandle + 1, &handles, NULL, NULL, &timeout);
} else {
}
else
{
result = -1;
}
@ -131,27 +144,26 @@ Socket_activateTcpKeepAlive(Socket self, int idleTime, int interval, int count)
(void)count; /* not supported in windows socket API */
struct tcp_keepalive keepalive;
DWORD retVal=0;
DWORD retVal = 0;
keepalive.onoff = 1;
keepalive.keepalivetime = idleTime * 1000;
keepalive.keepaliveinterval = interval * 1000;
if (WSAIoctl(self->fd, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive),
NULL, 0, &retVal, NULL, NULL) == SOCKET_ERROR)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: WSAIotcl(SIO_KEEPALIVE_VALS) failed: %d\n",
WSAGetLastError());
}
if (WSAIoctl(self->fd, SIO_KEEPALIVE_VALS, &keepalive, sizeof(keepalive), NULL, 0, &retVal, NULL, NULL) ==
SOCKET_ERROR)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: WSAIotcl(SIO_KEEPALIVE_VALS) failed: %d\n", WSAGetLastError());
}
}
static void
setSocketNonBlocking(Socket self)
{
unsigned long mode = 1;
if (ioctlsocket(self->fd, FIONBIO, &mode) != 0) {
if (ioctlsocket(self->fd, FIONBIO, &mode) != 0)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: failed to set socket non-blocking!\n");
}
@ -164,18 +176,19 @@ setSocketNonBlocking(Socket self)
}
static bool
prepareAddress(const char *address, int port, struct sockaddr_in *sockaddr)
prepareAddress(const char* address, int port, struct sockaddr_in* sockaddr)
{
memset((char *)sockaddr, 0, sizeof(struct sockaddr_in));
memset((char*)sockaddr, 0, sizeof(struct sockaddr_in));
if (address != NULL) {
struct hostent *server;
if (address != NULL)
{
struct hostent* server;
server = gethostbyname(address);
if (server == NULL)
return false;
memcpy((char *)&sockaddr->sin_addr.s_addr, (char *)server->h_addr, server->h_length);
memcpy((char*)&sockaddr->sin_addr.s_addr, (char*)server->h_addr, server->h_length);
}
else
sockaddr->sin_addr.s_addr = htonl(INADDR_ANY);
@ -189,20 +202,22 @@ prepareAddress(const char *address, int port, struct sockaddr_in *sockaddr)
static bool
wsaStartUp(void)
{
if (wsaStartupCalled == false) {
if (wsaStartupCalled == false)
{
int ec;
WSADATA wsa;
if ((ec = WSAStartup(MAKEWORD(2, 0), &wsa)) != 0) {
if ((ec = WSAStartup(MAKEWORD(2, 0), &wsa)) != 0)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: winsock error: code %i\n", ec);
return false;
}
else {
else
{
wsaStartupCalled = true;
return true;
}
}
else
return true;
@ -211,12 +226,13 @@ wsaStartUp(void)
static void
wsaShutdown(void)
{
if (wsaStartupCalled) {
if (socketCount == 0) {
if (wsaStartupCalled)
{
if (socketCount == 0)
{
WSACleanup();
wsaStartupCalled = false;
}
}
}
@ -237,7 +253,8 @@ TcpServerSocket_create(const char* address, int port)
listen_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (listen_socket == INVALID_SOCKET) {
if (listen_socket == INVALID_SOCKET)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: socket failed with error: %i\n", WSAGetLastError());
@ -247,11 +264,12 @@ TcpServerSocket_create(const char* address, int port)
}
int optionReuseAddr = 1;
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&optionReuseAddr, sizeof(int));
setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&optionReuseAddr, sizeof(int));
ec = bind(listen_socket, (struct sockaddr*)&server_addr, sizeof(server_addr));
if (ec == SOCKET_ERROR) {
if (ec == SOCKET_ERROR)
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: bind failed with error:%i\n", WSAGetLastError());
closesocket(listen_socket);
@ -263,7 +281,8 @@ TcpServerSocket_create(const char* address, int port)
serverSocket = (ServerSocket)GLOBAL_MALLOC(sizeof(struct sServerSocket));
if (serverSocket) {
if (serverSocket)
{
serverSocket->fd = listen_socket;
serverSocket->backLog = 10;
@ -271,7 +290,8 @@ TcpServerSocket_create(const char* address, int port)
socketCount++;
}
else {
else
{
closesocket(listen_socket);
wsaShutdown();
}
@ -292,8 +312,9 @@ ServerSocket_accept(ServerSocket self)
SOCKET fd = accept(self->fd, NULL, NULL);
if (fd != INVALID_SOCKET) {
conSocket = (Socket) GLOBAL_CALLOC(1, sizeof(struct sSocket));
if (fd != INVALID_SOCKET)
{
conSocket = (Socket)GLOBAL_CALLOC(1, sizeof(struct sSocket));
conSocket->fd = fd;
socketCount++;
@ -303,7 +324,8 @@ ServerSocket_accept(ServerSocket self)
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: connection accepted\n");
}
else {
else
{
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: accept failed\n");
}
@ -320,7 +342,8 @@ ServerSocket_setBacklog(ServerSocket self, int backlog)
void
ServerSocket_destroy(ServerSocket self)
{
if (self->fd != INVALID_SOCKET) {
if (self->fd != INVALID_SOCKET)
{
shutdown(self->fd, 2);
closesocket(self->fd);
socketCount--;
@ -341,25 +364,28 @@ TcpSocket_create()
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock != INVALID_SOCKET) {
self = (Socket) GLOBAL_MALLOC(sizeof(struct sSocket));
if (sock != INVALID_SOCKET)
{
self = (Socket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->connectTimeout = 5000;
socketCount++;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket - cannot allocate memory\n");
closesocket(sock);
wsaShutdown();
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create socket (error code=%i)\n", WSAGetLastError());
}
@ -383,7 +409,8 @@ Socket_bind(Socket self, const char* srcAddress, int srcPort)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == SOCKET_ERROR) {
if (result == SOCKET_ERROR)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind TCP socket (errno=%i)\n", WSAGetLastError());
@ -403,22 +430,19 @@ Socket_connectAsync(Socket self, const char* address, int port)
printf("WIN32_SOCKET: Socket_connect: %s:%i\n", address, port);
struct sockaddr_in serverAddress;
WSADATA wsa;
int ec;
if ((ec = WSAStartup(MAKEWORD(2,0), &wsa)) != 0) {
if (DEBUG_SOCKET)
printf("WIN32_SOCKET: winsock error: code %i\n", ec);
if (wsaStartUp() == false)
return false;
}
if (!prepareAddress(address, port, &serverAddress))
return false;
setSocketNonBlocking(self);
if (connect(self->fd, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) == SOCKET_ERROR) {
if (WSAGetLastError() != WSAEWOULDBLOCK) {
if (connect(self->fd, (struct sockaddr*)&serverAddress, sizeof(serverAddress)) == SOCKET_ERROR)
{
if (WSAGetLastError() != WSAEWOULDBLOCK)
{
closesocket(self->fd);
self->fd = INVALID_SOCKET;
return false;
@ -439,21 +463,25 @@ Socket_checkAsyncConnectState(Socket self)
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
int selectVal = select(self->fd + 1, NULL, &fdSet , NULL, &timeout);
int selectVal = select(self->fd + 1, NULL, &fdSet, NULL, &timeout);
if (selectVal == 1) {
if (selectVal == 1)
{
/* Check if connection is established */
int so_error;
int len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*) (&so_error), &len) != SOCKET_ERROR) {
if (so_error == 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*)(&so_error), &len) != SOCKET_ERROR)
{
if (so_error == 0)
{
int recvRes = recv(self->fd, NULL, 0, 0);
if (recvRes == SOCKET_ERROR) {
if (recvRes == SOCKET_ERROR)
{
int wsaError = WSAGetLastError();
if (wsaError == WSAECONNRESET)
@ -463,17 +491,18 @@ Socket_checkAsyncConnectState(Socket self)
return SOCKET_STATE_FAILED;
}
return SOCKET_STATE_CONNECTED;
}
}
return SOCKET_STATE_FAILED;
}
else if (selectVal == 0) {
else if (selectVal == 0)
{
return SOCKET_STATE_CONNECTING;
}
else {
else
{
return SOCKET_STATE_FAILED;
}
}
@ -492,21 +521,23 @@ Socket_connect(Socket self, const char* address, int port)
FD_ZERO(&fdSet);
FD_SET(self->fd, &fdSet);
if (select(self->fd + 1, NULL, &fdSet , NULL, &timeout) == 1) {
if (select(self->fd + 1, NULL, &fdSet, NULL, &timeout) == 1)
{
/* Check if connection is established */
int so_error;
socklen_t len = sizeof so_error;
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*)&so_error, &len) >= 0) {
if (getsockopt(self->fd, SOL_SOCKET, SO_ERROR, (char*)&so_error, &len) >= 0)
{
if (so_error == 0)
return true;
}
}
closesocket (self->fd);
closesocket(self->fd);
self->fd = INVALID_SOCKET;
return false;
@ -521,26 +552,28 @@ convertAddressToStr(struct sockaddr_storage* addr)
bool isIPv6;
if (addr->ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) addr;
if (addr->ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)addr;
port = ntohs(ipv4Addr->sin_port);
ipv4Addr->sin_port = 0;
WSAAddressToString((LPSOCKADDR) ipv4Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) &addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv4Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = false;
}
else if (addr->ss_family == AF_INET6){
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) addr;
else if (addr->ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)addr;
port = ntohs(ipv6Addr->sin6_port);
ipv6Addr->sin6_port = 0;
WSAAddressToString((LPSOCKADDR) ipv6Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) &addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv6Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = true;
}
else
return NULL;
char* clientConnection = (char*) GLOBAL_MALLOC(strlen(addrString) + 9);
char* clientConnection = (char*)GLOBAL_MALLOC(strlen(addrString) + 9);
if (isIPv6)
sprintf(clientConnection, "[%s]:%i", addrString, port);
@ -550,14 +583,14 @@ convertAddressToStr(struct sockaddr_storage* addr)
return clientConnection;
}
char*
Socket_getPeerAddress(Socket self)
{
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getpeername(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getpeername(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -570,7 +603,8 @@ Socket_getLocalAddress(Socket self)
struct sockaddr_storage addr;
socklen_t addrLen = sizeof(addr);
if (getsockname(self->fd, (struct sockaddr*) &addr, &addrLen) == 0) {
if (getsockname(self->fd, (struct sockaddr*)&addr, &addrLen) == 0)
{
return convertAddressToStr(&addr);
}
else
@ -583,7 +617,7 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
struct sockaddr_storage addr;
int addrLen = sizeof(addr);
getpeername(self->fd, (struct sockaddr*) &addr, &addrLen);
getpeername(self->fd, (struct sockaddr*)&addr, &addrLen);
char addrString[INET6_ADDRSTRLEN + 7];
int addrStringLen = INET6_ADDRSTRLEN + 7;
@ -591,20 +625,22 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
bool isIPv6;
if (addr.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &addr;
if (addr.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&addr;
port = ntohs(ipv4Addr->sin_port);
ipv4Addr->sin_port = 0;
WSAAddressToString((LPSOCKADDR) ipv4Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) & addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv4Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = false;
}
else if (addr.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &addr;
else if (addr.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&addr;
port = ntohs(ipv6Addr->sin6_port);
ipv6Addr->sin6_port = 0;
WSAAddressToString((LPSOCKADDR) ipv6Addr, sizeof(struct sockaddr_storage), NULL,
(LPSTR) addrString, (LPDWORD) & addrStringLen);
WSAAddressToString((LPSOCKADDR)ipv6Addr, sizeof(struct sockaddr_storage), NULL, (LPSTR)addrString,
(LPDWORD)&addrStringLen);
isIPv6 = true;
}
else
@ -621,12 +657,13 @@ Socket_getPeerAddressStatic(Socket self, char* peerAddressString)
int
Socket_read(Socket self, uint8_t* buf, int size)
{
int bytes_read = recv(self->fd, (char*) buf, size, 0);
int bytes_read = recv(self->fd, (char*)buf, size, 0);
if (bytes_read == 0) /* peer has closed socket */
return -1;
if (bytes_read == SOCKET_ERROR) {
if (bytes_read == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
return 0;
else
@ -639,9 +676,10 @@ Socket_read(Socket self, uint8_t* buf, int size)
int
Socket_write(Socket self, uint8_t* buf, int size)
{
int bytes_sent = send(self->fd, (char*) buf, size, 0);
int bytes_sent = send(self->fd, (char*)buf, size, 0);
if (bytes_sent == SOCKET_ERROR) {
if (bytes_sent == SOCKET_ERROR)
{
int errorCode = WSAGetLastError();
if (errorCode == WSAEWOULDBLOCK)
@ -656,7 +694,8 @@ Socket_write(Socket self, uint8_t* buf, int size)
void
Socket_destroy(Socket self)
{
if (self->fd != INVALID_SOCKET) {
if (self->fd != INVALID_SOCKET)
{
shutdown(self->fd, 2);
closesocket(self->fd);
@ -680,23 +719,27 @@ UdpSocket_createUsingNamespace(int ns)
SOCKET sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock != INVALID_SOCKET) {
self = (UdpSocket) GLOBAL_MALLOC(sizeof(struct sSocket));
if (sock != INVALID_SOCKET)
{
self = (UdpSocket)GLOBAL_MALLOC(sizeof(struct sSocket));
if (self) {
if (self)
{
self->fd = sock;
self->ns = ns;
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to allocate memory\n");
closesocket(sock);
}
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to create UDP socket (errno=%i)\n", WSAGetLastError());
printf("SOCKET: failed to create UDP socket (errno=%i)\n", WSAGetLastError());
}
return self;
@ -717,37 +760,43 @@ UdpSocket_createIpV6()
bool
UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
{
if (self->ns == AF_INET) {
if (self->ns == AF_INET)
{
struct ip_mreq mreq;
if (inet_pton(AF_INET, multicastAddress, &(mreq.imr_multiaddr)) < 1) {
if (inet_pton(AF_INET, multicastAddress, &(mreq.imr_multiaddr)) < 1)
{
printf("SOCKET: Invalid IPv4 multicast address\n");
return false;
}
else {
else
{
mreq.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1) {
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", WSAGetLastError());
if (setsockopt(self->fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast group (errno: %i)\n", WSAGetLastError());
return false;
}
}
return true;
}
else if (self->ns == AF_INET6) {
else if (self->ns == AF_INET6)
{
struct ipv6_mreq mreq;
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1) {
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", WSAGetLastError());
if (inet_pton(AF_INET6, multicastAddress, &(mreq.ipv6mr_multiaddr)) < 1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", WSAGetLastError());
return false;
}
mreq.ipv6mr_interface = 0;
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1) {
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", WSAGetLastError());
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (const char*)&mreq, sizeof(mreq)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast group (errno: %i)\n", WSAGetLastError());
return false;
}
@ -760,17 +809,21 @@ UdpSocket_addGroupMembership(UdpSocket self, const char* multicastAddress)
bool
UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
{
if (self->ns == AF_INET) {
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)) == -1) {
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", WSAGetLastError());
if (self->ns == AF_INET)
{
if (setsockopt(self->fd, IPPROTO_IP, IP_MULTICAST_TTL, (const char*)&ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv4 multicast TTL (errno: %i)\n", WSAGetLastError());
return false;
}
return true;
}
else if (self->ns == AF_INET6) {
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&ttl, sizeof(ttl)) == -1) {
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", WSAGetLastError());
else if (self->ns == AF_INET6)
{
if (setsockopt(self->fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (const char*)&ttl, sizeof(ttl)) == -1)
{
printf("SOCKET: failed to set IPv6 multicast TTL(hops) (errno: %i)\n", WSAGetLastError());
return false;
}
@ -783,10 +836,11 @@ UdpSocket_setMulticastTtl(UdpSocket self, int ttl)
bool
UdpSocket_bind(UdpSocket self, const char* address, int port)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_in localAddress;
if (!prepareAddress(address, port, &localAddress)) {
if (!prepareAddress(address, port, &localAddress))
{
closesocket(self->fd);
self->fd = 0;
return false;
@ -794,7 +848,8 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
int result = bind(self->fd, (struct sockaddr*)&localAddress, sizeof(localAddress));
if (result == -1) {
if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to bind UDP socket (errno=%i)\n", errno);
@ -810,10 +865,11 @@ UdpSocket_bind(UdpSocket self, const char* address, int port)
bool
UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_in remoteAddress;
if (!prepareAddress(address, port, &remoteAddress)) {
if (!prepareAddress(address, port, &remoteAddress))
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to lookup remote address %s\n", address);
@ -821,16 +877,20 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
return false;
}
int result = sendto(self->fd, (const char*) msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
int result =
sendto(self->fd, (const char*)msg, msgSize, 0, (struct sockaddr*)&remoteAddress, sizeof(remoteAddress));
if (result == msgSize) {
if (result == msgSize)
{
return true;
}
else if (result == -1) {
else if (result == -1)
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (errno=%i)\n", errno);
}
else {
else
{
if (DEBUG_SOCKET)
printf("SOCKET: failed to send UDP message (insufficient data sent)\n");
}
@ -841,7 +901,7 @@ UdpSocket_sendTo(UdpSocket self, const char* address, int port, uint8_t* msg, in
int
UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* msg, int msgSize)
{
//TODO add support for IPv6
// TODO add support for IPv6
struct sockaddr_storage remoteAddress;
memset(&remoteAddress, 0, sizeof(struct sockaddr_storage));
socklen_t structSize = sizeof(struct sockaddr_storage);
@ -849,31 +909,35 @@ UdpSocket_receiveFrom(UdpSocket self, char* address, int maxAddrSize, uint8_t* m
if (address)
address[0] = 0;
int result = recvfrom(self->fd, (char*) msg, msgSize, 0, (struct sockaddr*)&remoteAddress, &structSize);
int result = recvfrom(self->fd, (char*)msg, msgSize, 0, (struct sockaddr*)&remoteAddress, &structSize);
if (result == 0) /* peer has closed socket */
return -1;
if (result == SOCKET_ERROR) {
if (result == SOCKET_ERROR)
{
if (WSAGetLastError() == WSAEWOULDBLOCK)
return 0;
else
return -1;
}
if (address) {
if (address)
{
bool isIPv6;
char addrString[INET6_ADDRSTRLEN + 7];
int port;
if (remoteAddress.ss_family == AF_INET) {
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*) &remoteAddress;
if (remoteAddress.ss_family == AF_INET)
{
struct sockaddr_in* ipv4Addr = (struct sockaddr_in*)&remoteAddress;
port = ntohs(ipv4Addr->sin_port);
inet_ntop(AF_INET, &(ipv4Addr->sin_addr), addrString, INET_ADDRSTRLEN);
isIPv6 = false;
}
else if (remoteAddress.ss_family == AF_INET6) {
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*) &remoteAddress;
else if (remoteAddress.ss_family == AF_INET6)
{
struct sockaddr_in6* ipv6Addr = (struct sockaddr_in6*)&remoteAddress;
port = ntohs(ipv6Addr->sin6_port);
inet_ntop(AF_INET6, &(ipv6Addr->sin6_addr), addrString, INET6_ADDRSTRLEN);
isIPv6 = true;

@ -1,7 +1,7 @@
/*
* time.c
*
* Copyright 2013-2021 Michael Zillgith
* Copyright 2013-2024 Michael Zillgith
*
* This file is part of Platform Abstraction Layer (libpal)
* for libiec61850, libmms, and lib60870.
@ -41,8 +41,8 @@ Hal_getTimeInNs()
clock_gettime(CLOCK_REALTIME, &now);
nsSinceEpoch nsTime = now.tv_sec * 1000000000UL;
nsTime += now.tv_nsec;
nsSinceEpoch nsTime = (nsSinceEpoch)(now.tv_sec) * 1000000000UL;
nsTime += (nsSinceEpoch)(now.tv_nsec);
return nsTime;
}
@ -62,6 +62,36 @@ Hal_setTimeInNs(nsSinceEpoch nsTime)
return true;
}
msSinceEpoch
Hal_getMonotonicTimeInMs()
{
uint64_t timeVal = 0;
struct timespec ts;
if (clock_gettime (CLOCK_MONOTONIC, &ts) == 0)
{
timeVal = ((uint64_t)ts.tv_sec * 1000LL) + (ts.tv_nsec / 1000000);
}
return timeVal;
}
nsSinceEpoch
Hal_getMonotonicTimeInNs()
{
uint64_t nsTime = 0;
struct timespec ts;
if (clock_gettime(CLOCK_REALTIME, &ts) == 0)
{
nsTime = ts.tv_sec * 1000000000UL;
nsTime += ts.tv_nsec;
}
return nsTime;
}
#endif

Some files were not shown because too many files have changed in this diff Show More

Loading…
Cancel
Save